{"version":3,"sources":["./src/app/components/wp-edit/work-package-changeset.ts","./src/app/components/wp-list/wp-states-initialization.service.ts","./src/app/components/user/user-link/user-link.component.ts","./src/app/components/wp-edit/wp-edit-field/wp-replacement-label.component.ts","./src/app/components/wp-edit/wp-edit-field/wp-replacement-label.html","./src/app/modules/hal/resources/attachment-collection-resource.ts","./src/app/modules/hal/services/hal-events.service.ts","./src/app/modules/a11y/accessible-by-keyboard.component.ts","./src/app/components/wp-table/table-actions/table-action.ts","./src/app/globals/global-listeners/top-menu.ts","./src/app/components/wp-single-view-tabs/activity-panel/activity-on-overview.html","./src/app/components/wp-single-view-tabs/activity-panel/activity-on-overview.component.ts","./src/app/components/wp-single-view-tabs/overview-tab/overview-tab.html","./src/app/components/wp-single-view-tabs/overview-tab/overview-tab.component.ts","./src/app/components/wp-new/wp-new-split-view.html","./src/app/components/wp-new/wp-new-split-view.component.ts","./src/app/components/wp-copy/wp-copy-split-view.component.ts","./src/app/modules/work_packages/routing/split-view-routes.template.ts","./src/app/modules/bim/bcf/helper/bcf-path-helper.service.ts","./src/locales lazy ^\\.\\/.*\\.js$ namespace object","./src/app/components/wp-fast-table/builders/relation-cell-builder.ts","./src/app/components/wp-table/external-configuration/restricted-wp-table-configuration.service.ts","./src/app/modules/common/link-handling/link-handling.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service.ts","./src/app/components/wp-query/query-filters.service.ts","./src/app/components/op-context-menu/handlers/wp-create-settings-menu.directive.ts","./src/app/modules/work_packages/routing/split-view-routes.helper.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service.ts","./src/app/components/op-context-menu/handlers/op-types-context-menu.directive.ts","./src/app/components/wp-buttons/wp-create-button/wp-create-button.component.ts","./src/app/components/wp-buttons/wp-create-button/wp-create-button.html","./src/app/components/work-packages/work-package-comment/work-package-comment-field-handler.ts","./src/app/modules/common/edit-actions-bar/wp-edit-actions-bar.component.ts","./src/app/modules/common/edit-actions-bar/wp-edit-actions-bar.html","./src/app/components/work-packages/wp-breadcrumb/wp-breadcrumb-parent.html","./src/app/components/work-packages/wp-breadcrumb/wp-breadcrumb-parent.component.ts","./src/app/components/work-packages/wp-breadcrumb/wp-breadcrumb.html","./src/app/components/work-packages/wp-breadcrumb/wp-breadcrumb.component.ts","./src/app/modules/attachments/attachments-upload/attachments-upload.component.ts","./src/app/modules/attachments/attachments-upload/attachments-upload.html","./src/app/modules/fields/edit/field-controls/edit-field-controls.component.ts","./src/app/modules/fields/edit/field-controls/edit-field-controls.component.html","./src/app/modules/bim/bcf/api/bcf-path-resources.ts","./src/app/modules/bim/bcf/api/bcf-api-request.service.ts","./src/app/modules/bim/bcf/api/projects/bcf-project.resource.ts","./src/app/modules/bim/bcf/api/topics/bcf-topic.resource.ts","./src/app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths.ts","./src/app/modules/bim/bcf/api/viewpoints/bcf-viewpoint-collection.paths.ts","./src/app/modules/bim/bcf/api/topics/bcf-topic.paths.ts","./src/app/modules/bim/bcf/api/topics/bcf-viewpoint-collection.paths.ts","./src/app/modules/bim/bcf/api/extensions/bcf-extension.resource.ts","./src/app/modules/bim/bcf/api/extensions/bcf-extension.paths.ts","./src/app/modules/bim/bcf/api/projects/bcf-project.paths.ts","./src/app/modules/bim/bcf/api/bcf-api.service.ts","./src/app/components/user/user-avatar/user-avatar-renderer.service.ts","./src/app/components/angular/tracking-functions.ts","./src/app/components/wp-table/timeline/wp-timeline.ts","./src/app/components/op-context-menu/op-context-menu.types.ts","./src/app/components/op-context-menu/op-context-menu.html","./src/app/components/op-context-menu/op-context-menu.component.ts","./src/app/components/op-context-menu/op-context-menu.service.ts","./src/app/components/wp-new/wp-create.service.ts","./src/app/modules/fields/display/display-field.module.ts","./src/app/components/wp-single-view-tabs/activity-panel/activity-base.controller.ts","./src/app/components/wp-fast-table/helpers/wp-table-row-helpers.ts","./src/app/modules/fields/edit/editing-portal/edit-form-portal.injector.ts","./src/app/components/wp-fast-table/builders/modes/rows-builder.ts","./src/app/components/wp-fast-table/builders/modes/grouped/group-header-builder.ts","./src/app/components/wp-fast-table/builders/relations/relation-row-builder.ts","./src/app/components/wp-fast-table/builders/relations/relations-render-pass.ts","./src/app/components/wp-fast-table/builders/timeline/timeline-render-pass.ts","./src/app/components/wp-fast-table/builders/highlighting/row-highlight-render-pass.ts","./src/app/components/wp-fast-table/builders/drag-and-drop/drag-drop-handle-builder.ts","./src/app/components/wp-fast-table/builders/drag-and-drop/drag-drop-handle-render-pass.ts","./src/app/components/wp-fast-table/builders/primary-render-pass.ts","./src/app/components/wp-fast-table/builders/modes/plain/plain-render-pass.ts","./src/app/components/wp-fast-table/builders/modes/grouped/grouped-render-pass.ts","./src/app/components/wp-fast-table/builders/modes/grouped/grouped-rows-builder.ts","./src/app/components/wp-fast-table/builders/modes/hierarchy/hierarchy-render-pass.ts","./src/app/components/wp-fast-table/builders/modes/hierarchy/hierarchy-rows-builder.ts","./src/app/components/wp-fast-table/builders/modes/plain/plain-rows-builder.ts","./src/app/components/wp-edit-form/table-edit-form.ts","./src/app/components/wp-fast-table/wp-table-editing.ts","./src/app/components/wp-fast-table/wp-fast-table.ts","./src/app/modules/common/ckeditor/ckeditor-setup.service.ts","./src/app/modules/fields/edit/edit-field.service.ts","./src/app/components/wp-table/wp-table-scroll-sync.ts","./src/app/modules/common/authoring/authoring.html","./src/app/modules/common/authoring/authoring.component.ts","./src/app/modules/attachments/attachment-list/attachment-list-item.html","./src/app/modules/attachments/attachment-list/attachment-list-item.component.ts","./src/app/modules/attachments/attachment-list/attachment-list.html","./src/app/modules/attachments/attachment-list/attachment-list.component.ts","./src/app/modules/fields/display/field-types/highlightable-display-field.module.ts","./src/app/components/wp-fast-table/builders/table-action-renderer.ts","./src/app/components/wp-fast-table/builders/rows/single-row-builder.ts","./src/app/components/wp-inline-create/inline-create-row-builder.ts","./src/app/components/wp-inline-create/wp-inline-create.component.html","./src/app/components/wp-inline-create/wp-inline-create.component.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service.ts","./src/app/components/filters/quick-filter-by-text-input/quick-filter-by-text-input.component.ts","./src/app/components/filters/quick-filter-by-text-input/quick-filter-by-text-input.html","./src/app/components/filters/filter-boolean-value/filter-boolean-value.component.ts","./src/app/components/filters/filter-boolean-value/filter-boolean-value.component.html","./src/app/components/filters/filter-integer-value/filter-integer-value.component.ts","./src/app/components/filters/filter-integer-value/filter-integer-value.component.html","./src/app/components/filters/filter-date-value/filter-date-value.component.ts","./src/app/components/filters/filter-date-value/filter-date-value.component.html","./src/app/components/filters/filter-dates-value/filter-dates-value.component.ts","./src/app/components/filters/filter-dates-value/filter-dates-value.component.html","./src/app/components/filters/abstract-filter-date-time-value/abstract-filter-date-time-value.controller.ts","./src/app/components/filters/filter-date-time-value/filter-date-time-value.component.html","./src/app/components/filters/filter-date-time-value/filter-date-time-value.component.ts","./src/app/components/filters/filter-date-times-value/filter-date-times-value.component.html","./src/app/components/filters/filter-date-times-value/filter-date-times-value.component.ts","./src/app/components/filters/filter-string-value/filter-string-value.component.ts","./src/app/components/filters/filter-string-value/filter-string-value.component.html","./src/app/components/filters/filter-searchable-multiselect-value/filter-searchable-multiselect-value.component.ts","./src/app/components/filters/filter-searchable-multiselect-value/filter-searchable-multiselect-value.component.html","./src/app/components/filters/filter-toggled-multiselect-value/filter-toggled-multiselect-value.component.ts","./src/app/components/filters/filter-toggled-multiselect-value/filter-toggled-multiselect-value.component.html","./src/app/components/filters/query-filter/query-filter.component.html","./src/app/components/filters/query-filter/query-filter.component.ts","./src/app/components/filters/query-filters/query-filters.component.html","./src/app/components/filters/query-filters/query-filters.component.ts","./src/app/modules/fields/edit/services/global-edit-form-changes-tracker/global-edit-form-changes-tracker.service.ts","./src/app/modules/fields/edit/edit-form/edit-form.component.ts","./src/app/components/wp-table/embedded/wp-embedded-base.component.ts","./src/app/components/wp-table/embedded/wp-embedded-table.html","./src/app/components/wp-table/embedded/wp-embedded-table.component.ts","./src/app/modules/fields/edit/editing-portal/edit-form-portal.component.ts","./src/app/modules/fields/edit/editing-portal/edit-form-portal.component.html","./src/app/modules/hal/schemas/work-package-schema-proxy.ts","./src/app/modules/common/focus/focus-helper.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy-indentation.service.ts","./src/app/components/work-packages/wp-watcher-button/wp-watcher-button.component.ts","./src/app/components/work-packages/wp-watcher-button/wp-watcher-button.html","./src/app/helpers/selection-helpers.ts","./src/app/modules/fields/edit/field/editable-attribute-field.component.ts","./src/app/modules/fields/edit/field/editable-attribute-field.component.html","./src/app/components/wp-card-view/services/wp-card-drag-and-drop.service.ts","./src/app/helpers/dom/set-window-cursor.helper.ts","./src/app/modules/hal/resources/type-resource.ts","./src/app/modules/hal/resources/wp-collection-resource.ts","./src/app/modules/hal/resources/form-resource.ts","./src/app/modules/hal/resources/root-resource.ts","./src/app/modules/hal/resources/query-operator-resource.ts","./src/app/modules/hal/resources/help-text-resource.ts","./src/app/modules/hal/resources/wiki-page-resource.ts","./src/app/modules/hal/resources/meeting-content-resource.ts","./src/app/modules/hal/resources/post-resource.ts","./src/app/modules/hal/resources/time-entry-resource.ts","./src/app/modules/hal/resources/news-resource.ts","./src/app/modules/hal/resources/membership-resource.ts","./src/app/modules/hal/resources/role-resource.ts","./src/app/modules/hal/resources/project-resource.ts","./src/app/modules/hal/resources/group-resource.ts","./src/app/modules/hal/services/hal-resource.config.ts","./src/app/modules/hal/services/hal-aware-error-handler.ts","./src/app/modules/hal/openproject-hal.module.ts","./src/app/components/modals/confirm-dialog/confirm-dialog.modal.ts","./src/app/components/modals/confirm-dialog/confirm-dialog.modal.html","./src/app/modules/a11y/openproject-a11y.module.ts","./src/app/modules/common/no-results/no-results.component.html","./src/app/modules/common/no-results/no-results.component.ts","./src/app/modules/fields/field.service.ts","./src/app/modules/common/config/configuration.service.ts","./src/app/components/op-context-menu/op-context-menu-handler.ts","./src/app/modules/common/drag-and-drop/drag-and-drop.helpers.ts","./src/app/components/wp-fast-table/builders/timeline/timeline-row-builder.ts","./src/app/components/work-packages/wp-relations-count/wp-watchers-count.component.ts","./src/app/components/work-packages/wp-relations-count/wp-relations-count.html","./src/app/modules/fields/edit/edit-form/edit-form-routing.service.ts","./src/app/modules/hal/resources/query-filter-instance-resource.ts","./src/app/modules/boards/board/board-actions/board-actions-registry.service.ts","./src/app/components/work-packages/work-package.service.ts","./src/app/helpers/angular/until-destroyed.mixin.ts","./src/app/components/op-context-menu/icon-triggered-context-menu/icon-triggered-context-menu.component.ts","./src/app/components/op-context-menu/icon-triggered-context-menu/icon-triggered-context-menu.component.html","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service.ts","./src/environments/environment.ts","./src/app/modules/hal/resources/query-resource.ts","./src/app/modules/hal/hal-link/hal-link.ts","./src/app/modules/boards/board/board.ts","./src/app/modules/common/focus/contain-helpers.ts","./src/app/components/wp-fast-table/helpers/wp-table-hierarchy-helpers.ts","./src/app/components/wp-table/configuration-modal/wp-table-configuration-relation-selector.html","./src/app/components/wp-table/configuration-modal/wp-table-configuration-relation-selector.ts","./src/app/components/wp-table/external-configuration/external-relation-query-configuration.component.ts","./src/app/components/wp-table/external-configuration/external-query-configuration.template.html","./src/app/components/wp-table/external-configuration/external-relation-query-configuration.service.ts","./src/app/modules/apiv3/endpoints/grids/apiv3-grid-paths.ts","./src/app/modules/apiv3/paths/apiv3-list-resource.interface.ts","./src/app/modules/apiv3/endpoints/grids/apiv3-grids-paths.ts","./src/app/modules/apiv3/cache/cachable-apiv3-resource.ts","./src/app/modules/apiv3/endpoints/time-entries/apiv3-time-entry-paths.ts","./src/app/modules/apiv3/cache/cachable-apiv3-collection.ts","./src/app/modules/apiv3/endpoints/time-entries/time-entry-cache.service.ts","./src/app/modules/apiv3/endpoints/time-entries/apiv3-time-entries-paths.ts","./src/app/modules/apiv3/endpoints/projects/apiv3-available-projects-paths.ts","./src/app/modules/apiv3/endpoints/memberships/apiv3-memberships-paths.ts","./src/app/modules/apiv3/endpoints/users/apiv3-user-paths.ts","./src/app/modules/apiv3/endpoints/users/apiv3-users-paths.ts","./src/app/modules/apiv3/endpoints/types/apiv3-type-paths.ts","./src/app/modules/apiv3/endpoints/types/apiv3-types-paths.ts","./src/app/modules/apiv3/endpoints/queries/apiv3-query-order.ts","./src/app/modules/apiv3/endpoints/queries/apiv3-query-form.ts","./src/app/modules/apiv3/endpoints/queries/apiv3-query-paths.ts","./src/app/modules/apiv3/endpoints/queries/apiv3-queries-paths.ts","./src/app/modules/apiv3/endpoints/relations/apiv3-relations-paths.ts","./src/app/modules/apiv3/endpoints/work_packages/api-v3-work-package-paths.ts","./src/app/modules/apiv3/endpoints/work_packages/apiv3-work-package-form.ts","./src/app/modules/apiv3/endpoints/work_packages/work-package.cache.ts","./src/app/modules/apiv3/endpoints/work_packages/api-v3-work-package-cached-subresource.ts","./src/app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths.ts","./src/app/modules/apiv3/endpoints/versions/apiv3-version-paths.ts","./src/app/modules/apiv3/endpoints/versions/apiv3-versions-paths.ts","./src/app/modules/apiv3/endpoints/projects/apiv3-project-paths.ts","./src/app/modules/apiv3/endpoints/projects/project.cache.ts","./src/app/modules/apiv3/endpoints/projects/apiv3-projects-paths.ts","./src/app/modules/apiv3/endpoints/statuses/apiv3-status-paths.ts","./src/app/modules/apiv3/endpoints/statuses/apiv3-statuses-paths.ts","./src/app/modules/apiv3/endpoints/news/apiv3-news-paths.ts","./src/app/modules/apiv3/endpoints/help_texts/apiv3-help-texts-paths.ts","./src/app/modules/apiv3/endpoints/configuration/apiv3-configuration-path.ts","./src/app/modules/apiv3/virtual/apiv3-board-path.ts","./src/app/modules/apiv3/virtual/apiv3-boards-paths.ts","./src/app/modules/apiv3/api-v3.service.ts","./src/app/modules/common/editable-toolbar-title/editable-toolbar-title.html","./src/app/modules/common/editable-toolbar-title/editable-toolbar-title.component.ts","./src/app/modules/grids/widgets/widget-changeset.ts","./src/app/modules/grids/widgets/abstract-widget.component.ts","./src/app/modules/common/gon/gon.service.ts","./src/app/modules/common/back-routing/back-button.component.ts","./src/app/modules/hal/resources/schema-resource.ts","./src/app/components/wp-list/wp-list.service.ts","./src/app/modules/work_packages/routing/wp-view-base/work-packages-view.base.ts","./src/app/components/modals/confirm-dialog/confirm-dialog.service.ts","./src/app/globals/dynamic-bootstrapper.ts","./src/app/components/wp-query/query-param-listener.service.ts","./src/app/modules/work_packages/query-space/isolated-query-space.ts","./src/app/modules/common/keyCodes.enum.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service.ts","./src/app/components/modals/export-modal/wp-table-export.modal.ts","./src/app/components/modals/export-modal/wp-table-export.modal.html","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service.ts","./src/app/components/wp-inline-create/wp-inline-create.service.ts","./src/app/components/wp-fast-table/builders/internal-sort-columns.ts","./src/app/init-vendors.ts","./src/app/modules/common/ckeditor/ckeditor-preview.service.ts","./src/app/modules/hal/resources/query-filter-instance-schema-resource.ts","./src/app/modules/projects/openproject-projects.module.ts","./src/app/modules/common/set-click-position/set-click-position.ts","./src/app/modules/fields/changeset/changeset.ts","./src/app/modules/fields/changeset/resource-changeset.ts","./src/app/modules/hal/schemas/hal-payload.helper.ts","./src/app/components/wp-table/configuration-modal/tab-portal-outlet.ts","./src/app/modules/work_packages/query-space/wp-isolated-query-space.directive.ts","./src/app/modules/hal/http/openproject-header-interceptor.ts","./src/app/modules/apiv3/cache/state-cache.service.ts","./src/app/modules/common/highlight-col/highlight-col.directive.ts","./src/app/modules/common/autocomplete/user-autocompleter.component.ts","./src/app/modules/common/autocomplete/user-autocompleter.component.html","./src/app/components/op-modals/op-modal.service.ts","./src/app/modules/fields/edit/field-handler/hal-resource-edit-field-handler.ts","./src/app/modules/fields/edit/editing-portal/editing-portal-service.ts","./src/app/modules/fields/display/display-field.service.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts","./src/app/modules/common/path-helper/path-helper.service.ts","./src/app/modules/common/browser/device.service.ts","./src/app/components/op-context-menu/handlers/wp-status-dropdown-menu.directive.ts","./src/app/components/wp-buttons/wp-status-button/wp-status-button.html","./src/app/components/wp-buttons/wp-status-button/wp-status-button.component.ts","./src/app/modules/fields/display/field-types/multiple-lines-custom-options-display-field.module.ts","./src/app/modules/fields/display/field-types/progress-text-display-field.module.ts","./src/app/modules/fields/display/field-types/multiple-lines-user-display-field.module.ts","./src/app/modules/fields/display/display-field-renderer.ts","./src/app/modules/common/model-auth/model-auth.service.ts","./src/app/modules/hal/resources/mixins/attachable-mixin.ts","./src/app/modules/fields/field.base.ts","./src/app/components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.component.ts","./src/app/components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.html","./src/app/modules/hal/resources/hal-resource.ts","./src/app/modules/common/icon/op-icon.ts","./src/app/modules/hal/resources/relation-resource.ts","./src/app/modules/hal/services/url-params-encoder.ts","./src/app/modules/hal/resources/version-resource.ts","./src/app/components/wp-copy/wp-copy.controller.ts","./src/app/modules/fields/display/field-types/progress-display-field.module.ts","./src/app/components/wp-single-view-tabs/activity-panel/activity-tab.component.ts","./src/app/components/wp-single-view-tabs/activity-panel/activity-tab.html","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-additional-elements.service.ts","./src/app/modules/common/drag-and-drop/dom-autoscroll.service.ts","./src/app/components/work-packages/work-package-authorization.service.ts","./src/app/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts","./src/app/modules/common/op-date-picker/datepicker.ts","./src/app/modules/hal/resources/grid-widget-resource.ts","./src/app/modules/hal/services/hal-resource-notification.service.ts","./src/app/components/op-context-menu/handlers/op-context-menu-trigger.directive.ts","./src/app/modules/hal/helpers/lazy-accessor.ts","./src/app/modules/hal/helpers/hal-resource-builder.ts","./src/app/components/wp-single-view-tabs/keep-tab/keep-tab.service.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service.ts","./src/app/modules/common/colors/colors.service.ts","./src/app/components/wp-details/wp-details-toolbar.component.ts","./src/app/modules/work_packages/routing/wp-split-view/wp-split-view.html","./src/app/components/wp-details/wp-details-toolbar.html","./src/app/modules/work_packages/routing/wp-split-view/wp-split-view.component.ts","./src/app/modules/fields/display/field-types/resources-display-field.module.ts","./src/app/components/wp-table/context-menu-helper/wp-context-menu-helper.service.ts","./src/app/components/wp-query/query-column.ts","./src/app/modules/common/date/op-date-time.component.ts","./src/app/globals/constants.const.ts","./src/app/helpers/random-string.ts","./src/app/components/wp-fast-table/builders/highlighting/highlighting.functions.ts","./src/app/modules/common/autofocus/autofocus.directive.ts","./src/app/modules/hal/resources/custom-action-resource.ts","./src/app/components/api/api-v3/api-v3-filter-builder.ts","./src/app/components/wp-relations/embedded/wp-relation-query.base.ts","./node_modules/moment/locale sync ^\\.\\/.*$","./src/app/components/wp-activity/comment-service.ts","./src/app/components/work-packages/wp-relations-count/wp-relations-count.component.ts","./src/app/modules/common/slide-toggle/slide-toggle.component.ts","./src/app/modules/common/slide-toggle/slide-toggle.component.html","./src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts","./src/app/components/wp-card-view/wp-single-card/wp-single-card.component.html","./src/app/modules/fields/edit/services/hal-resource-editing.service.ts","./src/app/globals/tree-menu.ts","./src/app/components/op-modals/op-modal.component.ts","./src/app/components/main-menu/main-menu-toggle.service.ts","./src/app/components/wp-fast-table/builders/modes/grouped/grouped-rows-helpers.ts","./node_modules/codemirror/mode lazy ^\\.\\/.*\\/.*\\.js$ namespace object","./src/app/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts","./src/app/modules/fields/display/field-types/combined-date-display.field.ts","./src/app/components/modals/editor/macro-wp-button-modal/wp-button-macro.modal.html","./src/app/components/modals/editor/macro-wp-button-modal/wp-button-macro.modal.ts","./src/app/components/modals/editor/macro-wiki-include-page-modal/wiki-include-page-macro.modal.html","./src/app/components/modals/editor/macro-wiki-include-page-modal/wiki-include-page-macro.modal.ts","./src/app/components/modals/editor/macro-code-block-modal/code-block-macro.modal.html","./src/app/components/modals/editor/macro-code-block-modal/code-block-macro.modal.ts","./src/app/components/modals/editor/macro-child-pages-modal/child-pages-macro.modal.html","./src/app/components/modals/editor/macro-child-pages-modal/child-pages-macro.modal.ts","./src/app/components/modals/editor/editor-macros.service.ts","./src/app/components/wp-activity/activity-link.component.ts","./src/app/components/wp-activity/revision/revision-activity.component.html","./src/app/components/wp-activity/revision/revision-activity.component.ts","./src/app/modules/common/dynamic-bootstrap/component/dynamic-bootstrap/dynamic-bootstrap.component.ts","./src/app/components/wp-activity/user/user-activity.component.html","./src/app/modules/common/dynamic-bootstrap/component/dynamic-bootstrap/dynamic-bootstrap.component.html","./src/app/components/wp-activity/user/user-activity.component.ts","./src/app/components/wp-activity/activity-entry.component.html","./src/app/components/wp-activity/activity-entry.component.ts","./src/app/globals/onboarding/helpers.ts","./src/app/components/table-pagination/pagination-instance.ts","./src/app/components/wp-table/wp-table-configuration.ts","./src/app/components/modals/wp-destroy-modal/wp-destroy.modal.ts","./src/app/components/modals/wp-destroy-modal/wp-destroy.modal.html","./src/app/modules/common/drag-and-drop/reorder-delta-builder.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service.ts","./src/app/components/wp-fast-table/handlers/cell/edit-cell-handler.ts","./src/app/components/wp-fast-table/handlers/cell/relations-cell-handler.ts","./src/app/components/op-context-menu/wp-context-menu/wp-table-context-menu.directive.ts","./src/app/components/wp-fast-table/handlers/context-menu/context-menu-handler.ts","./src/app/components/wp-fast-table/handlers/context-menu/context-menu-click-handler.ts","./src/app/components/wp-fast-table/handlers/context-menu/context-menu-keyboard-handler.ts","./src/app/components/wp-fast-table/handlers/context-menu/context-menu-rightclick-handler.ts","./src/app/components/wp-fast-table/handlers/row/click-handler.ts","./src/app/components/wp-fast-table/handlers/row/double-click-handler.ts","./src/app/components/wp-fast-table/handlers/row/group-row-handler.ts","./src/app/components/wp-fast-table/handlers/row/hierarchy-click-handler.ts","./src/app/components/wp-fast-table/handlers/row/wp-state-links-handler.ts","./src/app/components/wp-fast-table/handlers/state/columns-transformer.ts","./src/app/components/wp-fast-table/handlers/state/hierarchy-transformer.ts","./src/app/components/wp-fast-table/handlers/state/relations-transformer.ts","./src/app/components/wp-fast-table/handlers/state/rows-transformer.ts","./src/app/components/wp-fast-table/handlers/state/selection-transformer.ts","./src/app/components/wp-fast-table/handlers/state/timeline-transformer.ts","./src/app/components/wp-fast-table/handlers/state/highlighting-transformer.ts","./src/app/components/wp-fast-table/handlers/state/drag-and-drop-transformer.ts","./src/app/components/wp-fast-table/handlers/state/group-fold-transformer.ts","./src/app/components/wp-fast-table/handlers/table-handler-registry.ts","./src/app/components/wp-table/wp-table-hover-sync.ts","./src/app/components/wp-table/wp-table.directive.html","./src/app/components/wp-table/wp-table.component.ts","./src/app/modules/fields/edit/edit-field.component.ts","./src/app/components/wp-single-view-tabs/watchers-tab/wp-watchers.service.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service.ts","./src/app/modules/augmenting/dynamic-scripts lazy ^\\.\\/.*$ namespace object","./src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service.ts","./src/app/components/wp-fast-table/builders/modes/grouped/group-sums-builder.ts","./src/app/components/wp-form-group/wp-attribute-group.template.html","./src/app/components/wp-form-group/wp-attribute-group.component.ts","./src/app/components/wp-table/timeline/cells/wp-timeline-cell-mouse-handler.ts","./src/app/components/wp-table/timeline/cells/wp-timeline-cell.ts","./src/app/components/wp-table/timeline/cells/timeline-cell-renderer.ts","./src/app/components/wp-table/timeline/cells/timeline-milestone-cell-renderer.ts","./src/app/components/wp-table/timeline/cells/wp-timeline-cells-renderer.ts","./src/app/components/wp-table/timeline/container/wp-timeline-container.directive.ts","./src/app/components/wp-table/timeline/container/wp-timeline-container.html","./src/app/components/op-context-menu/handlers/op-columns-context-menu.directive.ts","./src/app/components/wp-table/timeline/header/wp-timeline-header.directive.ts","./src/app/components/wp-table/timeline/header/wp-timeline-header.html","./src/app/components/wp-table/timeline/global-elements/timeline-relation-element.ts","./src/app/components/wp-table/timeline/global-elements/wp-timeline-relations.directive.ts","./src/app/components/wp-table/timeline/global-elements/timeline-static-element.ts","./src/app/components/wp-table/timeline/global-elements/wp-timeline.today-line.ts","./src/app/components/wp-table/timeline/global-elements/wp-timeline-static-elements.directive.ts","./src/app/components/wp-table/timeline/grid/wp-timeline-grid.directive.ts","./src/app/components/wp-single-view-tabs/watchers-tab/wp-watcher-entry.component.ts","./src/app/components/wp-single-view-tabs/watchers-tab/wp-watcher-entry.html","./src/app/components/wp-table/wp-table-sums-row/wp-table-sums-row.directive.ts","./src/app/components/wp-relations/embedded/wp-relation-query.html","./src/app/components/wp-relations/embedded/relations/wp-relation-query.component.ts","./src/app/components/wp-table/config-menu/config-menu.component.ts","./src/app/components/wp-table/config-menu/config-menu.template.html","./src/app/components/time-entries/time-entry-changeset.ts","./src/app/components/wp-table/sort-header/sort-header.directive.html","./src/app/components/wp-table/sort-header/sort-header.directive.ts","./src/app/modules/work_packages/openproject-work-packages.module.ts","./src/app/components/wp-list/wp-list-checksum.service.ts","./src/app/globals/global-listeners/action-menu.ts","./src/app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry.ts","./src/app/components/wp-card-view/services/wp-card-view.service.ts","./src/app/components/wp-card-view/event-handler/click-handler.ts","./src/app/components/wp-card-view/event-handler/double-click-handler.ts","./src/app/components/wp-card-view/event-handler/right-click-handler.ts","./src/app/components/wp-card-view/event-handler/card-view-handler-registry.ts","./src/app/components/wp-table/external-configuration/external-query-configuration.component.ts","./src/app/modules/boards/board/board.service.ts","./src/app/components/work-packages/wp-type-status/wp-type-status.component.ts","./src/app/components/work-packages/wp-type-status/wp-type-status.html","./src/app/modules/hal/resources/error-resource.ts","./src/app/modules/editor/openproject-editor.module.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service.ts","./src/app/modules/common/loading-indicator/loading-indicator.service.ts","./src/app/components/angular/debounced-event-emitter.ts","./src/app/components/wp-relations/embedded/relations/wp-relation-inline-create.service.ts","./src/app/modules/work_packages/routing/wp-edit-form/wp-edit-form-routing.service.ts","./src/app/modules/work_packages/routing/wp-base/wp--base.component.ts","./src/app/components/wp-fast-table/handlers/click-or-enter-handler.ts","./src/app/components/work-packages/wp-subject/wp-subject.component.ts","./src/app/components/work-packages/wp-subject/wp-subject.html","./src/app/modules/job-status/job-status-modal/job-status.modal.ts","./src/app/modules/job-status/job-status-modal/job-status.modal.html","./src/app/modules/time_entries/form/form.component.ts","./src/app/modules/time_entries/form/form.component.html","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-table-pagination.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service.ts","./src/app/components/api/op-file-upload/op-file-upload.service.ts","./src/app/modules/work_packages/routing/partitioned-query-space-page/partitioned-query-space-page.component.html","./src/app/modules/work_packages/routing/partitioned-query-space-page/partitioned-query-space-page.component.ts","./src/app/components/wp-custom-actions/wp-custom-actions/wp-custom-action.component.ts","./src/app/components/wp-custom-actions/wp-custom-actions.component.html","./src/app/components/wp-custom-actions/wp-custom-actions/wp-custom-action.component.html","./src/app/components/wp-custom-actions/wp-custom-actions.component.ts","./src/app/components/work-packages/wp-single-view/wp-single-view.html","./src/app/components/work-packages/wp-single-view/wp-single-view.component.ts","./src/app/modules/fields/display/field-types/date-display-field.module.ts","./src/app/modules/apiv3/forms/apiv3-form-resource.ts","./src/app/globals/global-listeners/request-for-confirmation.ts","./src/app/globals/global-listeners/toggable-fieldset.ts","./src/app/globals/global-listeners/setup-server-response.ts","./src/app/globals/global-listeners.ts","./src/app/globals/onboarding/onboarding_tour_trigger.ts","./src/app/globals/global-listeners/augmented-date-picker.ts","./src/app/globals/global-listeners/link-hijacking.ts","./src/app/globals/global-listeners/danger-zone-validation.ts","./src/app/globals/global-listeners/refresh-on-form-changes.ts","./src/app/globals/global-listeners/top-menu-scroll.ts","./src/app/globals/global-listeners/settings.ts","./src/app/globals/global-listeners/color-preview.ts","./src/app/globals/global-helpers.ts","./src/app/globals/openproject.ts","./src/app/modules/common/browser/browser-detector.service.ts","./src/app/modules/fields/help-texts/attribute-help-text.service.ts","./src/app/modules/fields/help-texts/help-text.modal.html","./src/app/modules/fields/help-texts/attribute-help-text.modal.ts","./src/app/modules/fields/help-texts/attribute-help-text.component.html","./src/app/modules/fields/help-texts/attribute-help-text.component.ts","./src/vendor/i18n.js-exposed","./src/app/components/wp-fast-table/builders/ui-state-link-builder.ts","./src/$_lazy_route_resource lazy namespace object","./src/app/modules/common/notifications/notifications.service.ts","./src/app/modules/hal/resources/query-filter-resource.ts","./src/app/components/schemas/schema-cache.service.ts","./src/app/components/html/op-title.service.ts","./src/app/modules/fields/edit/edit-form/edit-form.ts","./src/vendor/i18n.js","./src/app/components/wp-grid/wp-grid.component.ts","./src/app/components/filters/filter-container/filter-container.directive.ts","./src/app/components/filters/filter-container/filter-container.directive.html","./src/app/modules/common/op-date-picker/op-date-picker.component.ts","./src/app/modules/common/op-date-picker/op-date-picker.component.html","./src/app/modules/hal/resources/status-resource.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service.ts","./src/app/components/resizer/wp-resizer.component.ts","./src/app/components/wp-relations/embedded/children/wp-children-inline-create.service.ts","./src/app/components/api/op-file-upload/op-direct-file-upload.service.ts","./src/app/components/wp-edit-form/work-package-filter-values.ts","./src/app/modules/common/enterprise/banners.service.ts","./src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts","./src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html","./src/app/modules/plugins/hook-service.ts","./src/app/modules/common/autocomplete/wp-autocompleter.component.ts","./src/app/modules/common/autocomplete/create-autocompleter.component.html","./src/app/components/wp-single-view-tabs/wp-linked-resource-cache.service.ts","./src/app/components/wp-table/external-configuration/external-query-configuration.constants.ts","./src/app/components/wp-card-view/wp-card-view.component.html","./src/app/components/wp-card-view/wp-card-view.component.ts","./src/app/modules/hal/resources/collection-resource.ts","./src/app/components/wp-relations/embedded/inline/add-existing/wp-relation-inline-add-existing.component.ts","./src/app/components/wp-relations/embedded/inline/add-existing/wp-relation-inline-add-existing.component.html","./src/app/modules/hal/services/hal-resource-sorting.service.ts","./src/app/components/states.service.ts","./src/app/modules/backlogs/backlogs-page/backlogs-page.component.ts","./src/app/modules/hal/resources/work-package-resource.ts","./src/app/modules/common/autocomplete/te-work-package-autocompleter.component.ts","./src/app/modules/common/autocomplete/te-work-package-autocompleter.component.html","./src/app/helpers/rxjs/debounced-input-switchmap.ts","./src/app/modules/apiv3/paths/path-resources.ts","./src/app/modules/attachments/attachments.component.ts","./src/app/modules/attachments/attachments.html","./src/app/modules/bim/ifc_models/xeokit/xeokit-server.ts","./src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts","./src/app/components/datetime/timezone.service.ts","./src/app/modules/common/ckeditor/op-ckeditor.component.ts","./src/app/modules/common/ckeditor/op-ckeditor.html","./src/app/components/wp-query-select/wp-static-queries.service.ts","./src/app/modules/hal/services/hal-resource.service.ts","./src/app/components/wp-new/wp-new-full-view.component.ts","./src/app/components/wp-new/wp-new-full-view.html","./src/app/modules/fields/edit/editing-portal/edit-field-handler.ts","./src/app/modules/a11y/accessible-click.directive.ts","./src/app/components/table-pagination/pagination-service.ts","./src/app/components/filters/wp-filters/wp-filters.service.ts","./src/app/components/wp-list/wp-list-invalid-query.service.ts","./src/app/helpers/op-icon-builder.ts","./src/app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service.ts","./src/app/components/table-pagination/table-pagination.component.html","./src/app/components/table-pagination/table-pagination.component.ts","./src/app/components/wp-table/table-pagination/wp-table-pagination.component.ts","./src/app/components/wp-single-view-tabs/activity-panel/activity-entry-info.ts","./src/app/components/wp-single-view-tabs/activity-panel/wp-activity.service.ts","./src/app/modules/bim/bcf/helper/viewpoints.service.ts","./src/app/modules/common/autocomplete/version-autocompleter.component.ts","./src/app/components/wp-fast-table/builders/modes/grouped/grouped-classes.constants.ts","./src/app/modules/apiv3/paths/apiv3-resource.ts","./src/app/components/wp-table/external-configuration/external-query-configuration.service.ts","./src/app/modules/fields/edit/field-types/text-edit-field.component.ts","./src/app/modules/fields/edit/field-types/text-edit-field.component.html","./src/app/modules/fields/edit/field-types/integer-edit-field.component.ts","./src/app/modules/fields/edit/field-types/duration-edit-field.component.ts","./src/app/modules/fields/edit/field-types/select-autocompleter-register.service.ts","./src/app/modules/fields/edit/field-types/select-edit-field.component.ts","./src/app/modules/fields/edit/field-types/select-edit-field.component.html","./src/app/modules/fields/edit/field-types/multi-select-edit-field.component.html","./src/app/modules/fields/edit/field-types/multi-select-edit-field.component.ts","./src/app/modules/fields/edit/field-types/float-edit-field.component.ts","./src/app/modules/fields/edit/field-types/boolean-edit-field.component.ts","./src/app/modules/fields/edit/field-types/work-package-edit-field.component.ts","./src/app/modules/fields/edit/field-types/work-package-edit-field.component.html","./src/app/modules/fields/edit/field-types/date-edit-field.component.ts","./src/app/modules/fields/edit/field-types/formattable-edit-field.component.ts","./src/app/components/work-packages/work-package-comment/wp-comment-field.component.ts","./src/app/modules/fields/helpers/project-status-helper.ts","./src/app/modules/fields/edit/field-types/project-status-edit-field.component.html","./src/app/modules/fields/edit/field-types/project-status-edit-field.component.ts","./src/app/modules/fields/edit/field-types/plain-formattable-edit-field.component.ts","./src/app/modules/fields/edit/field-types/te-work-package-edit-field.component.ts","./src/app/components/datepicker/datepicker.modal.helper.ts","./src/app/components/datepicker/datepicker.modal.html","./src/app/components/datepicker/datepicker.modal.ts","./src/app/modules/fields/edit/field-types/combined-date-edit-field.component.ts","./src/app/modules/fields/display/field-types/text-display-field.module.ts","./src/app/modules/fields/display/field-types/float-display-field.module.ts","./src/app/modules/fields/display/field-types/integer-display-field.module.ts","./src/app/modules/fields/display/field-types/resource-display-field.module.ts","./src/app/modules/fields/display/field-types/formattable-display-field.module.ts","./common/expression.service.ts","./src/app/modules/fields/display/field-types/duration-display-field.module.ts","./src/app/modules/fields/display/field-types/datetime-display-field.module.ts","./src/app/modules/fields/display/field-types/boolean-display-field.module.ts","./src/app/modules/fields/display/field-types/work-package-display-field.module.ts","./src/app/modules/fields/display/field-types/wp-spent-time-display-field.module.ts","./src/app/modules/fields/display/field-types/id-display-field.module.ts","./src/app/modules/fields/display/field-types/highlighted-resource-display-field.module.ts","./src/app/modules/fields/display/field-types/type-display-field.module.ts","./src/app/modules/fields/display/field-types/user-display-field.module.ts","./src/app/modules/fields/display/field-types/multiple-user-display-field.module.ts","./src/app/modules/fields/display/field-types/wp-id-display-field.module.ts","./src/app/modules/fields/display/field-types/project-status-display-field.module.ts","./src/app/modules/fields/display/field-types/plain-formattable-display-field.module.ts","./src/app/modules/fields/display/field-types/linked-work-package-display-field.module.ts","./src/app/modules/fields/openproject-fields.module.ts","./src/app/modules/fields/edit/edit-field.initializer.ts","./src/app/modules/fields/display/display-field.initializer.ts","./src/app/modules/common/focus/focus.directive.ts","./src/app/modules/hal/resources/schema-dependency-resource.ts","./src/app/components/wp-table/table-actions/actions/details-table-action.ts","./src/app/components/wp-table/table-actions/actions/context-menu-table-action.ts","./src/app/components/wp-table/table-actions/table-actions.service.ts","./src/app/modules/router/first-route-service.ts","./src/app/components/wp-buttons/wp-filter-button/wp-filter-button.component.ts","./src/app/components/wp-buttons/wp-filter-button/wp-filter-button.html","./src/app/components/wp-query/url-params-helper.ts","./src/app/modules/common/back-routing/back-routing.service.ts","./src/app/components/wp-table/drag-and-drop/actions/table-drag-action.service.ts","./src/app/components/wp-table/drag-and-drop/actions/hierarchy-drag-action.service.ts","./src/app/components/wp-table/drag-and-drop/actions/group-by-drag-action.service.ts","./src/app/components/wp-table/drag-and-drop/actions/table-drag-actions-registry.service.ts","./src/app/helpers/images/path-helper.ts","./src/app/components/wp-fast-table/builders/cell-builder.ts","./src/app/helpers/debug_output.ts","./src/app/modules/work_packages/notifications/work-package-notification.service.ts","./src/app/modules/hal/resources/query-sort-by-resource.ts","./src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.directive.ts","./src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.template.html","./src/app/components/wp-relations/wp-relation-row/wp-relation-row.template.html","./src/app/components/wp-relations/wp-relation-row/wp-relation-row.component.ts","./src/app/components/wp-relations/wp-relations-group/wp-relations-group.template.html","./src/app/components/wp-relations/wp-relations-group/wp-relations-group.component.ts","./src/app/components/wp-relations/wp-relations-create/wp-relation-create.template.html","./src/app/components/wp-relations/wp-relations-create/wp-relations-create.component.ts","./src/app/components/wp-relations/wp-relations.template.html","./src/app/components/wp-relations/wp-relations.component.ts","./src/app/components/wp-single-view-tabs/relations-tab/relations-tab.html","./src/app/components/wp-single-view-tabs/relations-tab/relations-tab.component.ts","./src/app/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts","./src/app/components/wp-buttons/zen-mode-toggle-button/zen-mode-toggle-button.component.ts","./src/app/components/wp-buttons/wp-button.template.html","./src/app/helpers/angular/inject-field.decorator.ts","./src/app/modules/work_packages/routing/wp-view-base/work-package-single-view.base.ts","./src/app/modules/boards/board/board-list/board-lists.service.ts","./src/app/components/projects/current-project.service.ts","./src/app/components/wp-table/table-actions/actions/unlink-table-action.ts","./src/app/components/wp-table/configuration-modal/wp-table-configuration.modal.ts","./src/app/components/wp-table/configuration-modal/wp-table-configuration.modal.html","./src/app/components/wp-relations/embedded/children/wp-children-query.component.ts","./src/app/modules/common/autocomplete/create-autocompleter.component.ts","./src/app/components/wp-table/configuration-modal/tabs/display-settings-tab.component.html","./src/app/components/wp-table/configuration-modal/tabs/display-settings-tab.component.ts","./src/app/modules/common/draggable-autocomplete/draggable-autocomplete.component.html","./src/app/modules/common/draggable-autocomplete/draggable-autocomplete.component.ts","./src/app/components/wp-table/configuration-modal/tabs/columns-tab.component.html","./src/app/components/wp-table/configuration-modal/tabs/columns-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/filters-tab.component.html","./src/app/components/wp-table/configuration-modal/tabs/filters-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/sort-by-tab.component.html","./src/app/components/wp-table/configuration-modal/tabs/sort-by-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/timelines-tab.component.html","./src/app/components/wp-table/configuration-modal/tabs/timelines-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html","./src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts","./src/app/components/wp-table/configuration-modal/wp-table-configuration.service.ts","./src/app/modules/common/focus/focus-within.directive.ts","./src/app/modules/common/drag-and-drop/drag-and-drop.service.ts","./src/app/modules/common/dynamic-bootstrap/dynamic-bootstrap.module.ts","./src/app/modules/common/openproject-common.module.ts","./src/app/components/user/user-avatar/user-avatar.component.ts","./src/app/modules/apiv3/endpoints/grids/apiv3-grid-form.ts","./src/app/components/wp-relations/wp-relations.service.ts","./src/app/modules/hal/resources/grid-resource.ts","./src/app/modules/common/resizer/resizer.component.ts","./src/app/modules/common/resizer/resizer.component.html","./src/app/components/user/current-user.service.ts","./src/app/modules/hal/schemas/schema-proxy.ts","./src/app/components/work-packages/work-package-comment/work-package-comment.component.html","./src/app/components/work-packages/work-package-comment/work-package-comment.component.ts","./src/app/modules/bim/bcf/fields/display/bcf-thumbnail-field.module.ts","./src/app/modules/bim/bcf/helper/bcf-detector.service.ts","./src/app/modules/bim/bcf/api/bcf-authorization.service.ts","./src/app/modules/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component.html","./src/app/modules/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component.ts","./src/app/modules/bim/bcf/bcf-wp-attribute-group/bcf-new-wp-attribute-group.component.ts","./src/app/modules/bim/revit_add_in/revit-bridge.service.ts","./src/app/modules/bim/bcf/openproject-bcf.module.ts","./src/app/modules/common/i18n/i18n.service.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-table-hierarchies.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service.ts","./src/app/modules/boards/board/caused-updates/caused-updates.service.ts","./src/app/components/enterprise-banner/enterprise-banner.component.ts","./src/app/components/wp-buttons/wp-buttons.module.ts","./src/app/modules/time_entries/shared/modal/base.modal.html","./src/app/modules/time_entries/create/create.modal.ts","./src/app/modules/time_entries/create/create.service.ts","./src/app/modules/attachments/openproject-attachments.module.ts","./src/app/components/wp-fast-table/builders/modes/hierarchy/single-hierarchy-row-builder.ts","./src/app/modules/time_entries/shared/modal/base.modal.ts","./src/app/modules/hal/resources/user-resource.ts","./src/app/components/wp-single-view-tabs/watchers-tab/watchers-tab.component.ts","./src/app/components/wp-single-view-tabs/watchers-tab/watchers-tab.html","./src/app/components/wp-new/wp-create.component.ts","./src/app/components/modals/request-for-confirmation/password-confirmation.modal.ts","./src/app/components/modals/request-for-confirmation/password-confirmation.modal.html","./src/app/components/modals/modal-wrapper/dynamic-content.modal.ts","./src/app/components/modals/modal-wrapper/dynamic-content.modal.html","./src/app/modules/common/html-sanitize/html-sanitize.service.ts","./src/app/modules/plugins/plugin-context.ts","./src/app/modules/plugins/openproject-plugins.module.ts","./src/app/modules/plugins/linked/budgets/hal/resources/budget-resource.ts","./src/app/modules/plugins/linked/budgets/augment/cost-subform.augment.service.ts","./src/app/modules/plugins/linked/budgets/augment/planned-costs-form.ts","./src/app/modules/plugins/linked/budgets/augment/cost-budget-subform.augment.service.ts","./src/app/modules/plugins/linked/budgets/main.ts","./src/app/modules/plugins/linked/costs/wp-display/costs-by-type-display-field.module.ts","./src/app/modules/plugins/linked/costs/wp-display/currency-display-field.module.ts","./src/app/modules/plugins/linked/costs/main.ts","./src/app/helpers/images/resizer.ts","./src/app/modules/plugins/linked/openproject-avatars/avatar-upload-form/avatar-upload-form.html","./src/app/modules/plugins/linked/openproject-avatars/avatar-upload-form/avatar-upload-form.component.ts","./src/app/modules/plugins/linked/openproject-avatars/main.ts","./src/app/modules/plugins/linked/openproject-documents/hal/resources/document-resource.ts","./src/app/modules/plugins/linked/openproject-documents/main.ts","./src/app/modules/plugins/linked-plugins.module.ts","./src/app/modules/grids/areas/grid-area.ts","./src/app/modules/grids/areas/grid-widget-area.ts","./src/app/modules/grids/areas/grid-gap.ts","./src/app/modules/grids/grid/area.service.ts","./src/app/modules/grids/widgets/header/header.component.ts","./src/app/modules/grids/widgets/header/header.component.html","./src/app/modules/grids/grid/remove-widget.service.ts","./src/app/modules/grids/widgets/menu/widget-abstract-menu.component.ts","./src/app/modules/grids/widgets/menu/widget-menu.component.html","./src/app/modules/grids/widgets/menu/widget-menu.component.ts","./src/app/modules/calendar/wp-calendar/wp-calendar.template.html","./src/app/modules/calendar/wp-calendar/wp-calendar.component.ts","./src/app/modules/grids/widgets/wp-calendar/wp-calendar.component.ts","./src/app/modules/grids/widgets/wp-calendar/wp-calendar.component.html","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-configuration-modal/services/time-entries-current-user-configuration-modal/time-entries-current-user-configuration-modal.service.ts","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-configuration-modal/time-entries-current-user-configuration.modal.html","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-configuration-modal/time-entries-current-user-configuration.modal.ts","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-menu.component.ts","./src/app/modules/time_entries/edit/edit.modal.ts","./src/app/modules/time_entries/edit/edit.service.ts","./src/app/modules/calendar/te-calendar/te-calendar.template.html","./src/app/modules/calendar/te-calendar/te-calendar.component.ts","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user.component.ts","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user.component.html","./src/app/modules/grids/widgets/widgets.service.ts","./src/app/modules/calendar/wp-calendar-entry/wp-calendar-entry.component.ts","./src/app/modules/calendar/wp-calendar-entry/wp-calendar-entry.component.html","./src/app/modules/time_entries/openproject-time-entries.module.ts","./src/app/modules/calendar/openproject-calendar.module.ts","./src/app/modules/grids/widgets/documents/documents.component.html","./src/app/modules/grids/widgets/documents/documents.component.ts","./src/app/modules/grids/widgets/news/news.component.html","./src/app/modules/grids/widgets/news/news.component.ts","./src/app/modules/grids/grid/initialization.service.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/settings-tab.component.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/settings-tab.component.html","./src/app/modules/work-package-graphs/configuration-modal/tabs/filters-tab.component.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/filters-tab.component.html","./src/app/modules/work-package-graphs/configuration/wp-graph-configuration.ts","./src/app/modules/work-package-graphs/configuration/wp-graph-configuration.service.ts","./src/app/modules/work-package-graphs/configuration-modal/wp-graph-configuration.modal.ts","./src/app/modules/grids/widgets/menu/wp-set-menu.component.ts","./src/app/modules/grids/widgets/wp-graph/wp-graph-menu.component.ts","./src/app/modules/work-package-graphs/embedded/wp-embedded-graph.html","./src/app/modules/work-package-graphs/embedded/wp-embedded-graph.component.ts","./src/app/modules/grids/widgets/wp-graph/wp-graph.component.ts","./src/app/modules/grids/widgets/wp-graph/wp-graph.component.html","./src/app/modules/grids/widgets/wp-table/wp-table-menu.component.ts","./src/app/modules/grids/widgets/wp-table/wp-table.component.html","./src/app/modules/grids/widgets/wp-table/wp-table.component.ts","./src/app/modules/grids/widgets/wp-table/wp-table-qs.component.ts","./src/app/modules/grids/widgets/wp-table/wp-table-qs.component.html","./src/app/modules/work-package-graphs/configuration-modal/tabs/abstract-query-spaced-tab.component.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/filters-tab-inner.component.html","./src/app/modules/work-package-graphs/configuration-modal/tabs/filters-tab-inner.component.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/settings-tab-inner.component.html","./src/app/modules/work-package-graphs/configuration-modal/tabs/settings-tab-inner.component.ts","./src/app/modules/work-package-graphs/openproject-work-package-graphs.module.ts","./src/app/modules/grids/widgets/project-description/project-description.component.html","./src/app/modules/grids/widgets/project-description/project-description.component.ts","./src/app/modules/work-package-graphs/overview/wp-overview-graph.template.html","./src/app/modules/work-package-graphs/overview/wp-overview-graph.component.ts","./src/app/modules/grids/widgets/wp-overview/wp-overview.component.ts","./src/app/modules/grids/widgets/wp-overview/wp-overview.component.html","./src/app/modules/grids/widgets/custom-text/custom-text-edit-field.service.ts","./src/app/modules/grids/widgets/custom-text/custom-text.component.html","./src/app/modules/grids/widgets/custom-text/custom-text.component.ts","./src/app/modules/grids/widgets/project-details/project-details.component.html","./src/app/modules/grids/widgets/project-details/project-details.component.ts","./src/app/modules/grids/widgets/time-entries/list/time-entries-list.component.ts","./src/app/modules/common/principal/principal-helper.ts","./src/app/modules/grids/widgets/time-entries/list/time-entries-list.component.html","./src/app/modules/grids/widgets/time-entries/project/time-entries-project.component.ts","./src/app/modules/grids/widgets/subprojects/subprojects.component.html","./src/app/modules/grids/widgets/subprojects/subprojects.component.ts","./src/app/modules/common/principal/principal-renderer.service.ts","./src/app/modules/common/principal/op-principal.component.ts","./src/app/modules/grids/widgets/members/members.component.html","./src/app/modules/grids/widgets/members/members.component.ts","./src/app/modules/grids/widgets/project-status/project-status.component.html","./src/app/modules/grids/widgets/project-status/project-status.component.ts","./src/app/modules/grids/openproject-grids.module.ts","./src/app/modules/router/base/application-base.component.ts","./src/app/modules/router/openproject.routes.ts","./src/app/modules/router/openproject-router.module.ts","./src/app/components/wp-copy/wp-copy-full-view.component.ts","./src/app/modules/work_packages/routing/wp-full-view/wp-full-view.html","./src/app/modules/work_packages/routing/wp-full-view/wp-full-view.component.ts","./src/app/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts","./src/app/components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component.ts","./src/app/components/wp-buttons/wp-details-view-button/wp-details-view-button.component.ts","./src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.html","./src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.component.ts","./src/app/components/modals/share-modal/query-sharing-form.component.ts","./src/app/components/modals/share-modal/query-sharing-form.html","./src/app/components/modals/save-modal/save-query.modal.ts","./src/app/components/modals/save-modal/save-query.modal.html","./src/app/components/modals/share-modal/query-sharing.modal.ts","./src/app/components/modals/share-modal/query-sharing.modal.html","./src/app/components/op-context-menu/handlers/op-settings-dropdown-menu.directive.ts","./src/app/components/wp-buttons/wp-settings-button/wp-settings-button.component.ts","./src/app/components/wp-buttons/wp-settings-button/wp-settings-button.component.html","./src/app/components/op-context-menu/handlers/wp-group-toggle-dropdown-menu.directive.ts","./src/app/components/wp-buttons/wp-fold-toggle-button/wp-fold-toggle-button.component.ts","./src/app/modules/work_packages/routing/wp-view-page/wp-view-page.component.ts","./src/app/modules/work_packages/routing/work-packages-routes.ts","./src/app/modules/work_packages/openproject-work-package-routes.module.ts","./src/app/modules/global_search/services/global-search.service.ts","./src/app/modules/global_search/openproject-global-search.module.ts","./src/app/components/main-menu/main-menu-navigation.service.ts","./src/app/modules/admin/types/type-banner.service.ts","./src/app/modules/admin/types/type-form-configuration.html","./src/app/modules/admin/types/type-form-configuration.component.ts","./src/app/modules/admin/types/group-edit-in-place.html","./src/app/modules/admin/types/group-edit-in-place.component.ts","./src/app/modules/admin/types/attribute-group.component.html","./src/app/modules/admin/types/attribute-group.component.ts","./src/app/modules/admin/types/query-group.component.ts","./src/app/modules/admin/types/query-group.component.html","./src/app/modules/admin/openproject-admin.module.ts","./src/app/modules/grids/widgets/add/add.modal.html","./src/app/modules/grids/widgets/add/add.modal.ts","./src/app/modules/grids/grid/move.service.ts","./src/app/modules/grids/grid/drag-and-drop.service.ts","./src/app/modules/grids/grid/resize.service.ts","./src/app/modules/grids/grid/add-widget.service.ts","./src/app/modules/grids/grid/page/grid-page.component.ts","./src/app/modules/grids/grid/grid.component.html","./src/app/modules/grids/grid/grid.component.ts","./src/app/modules/grids/grid/page/grid-page.component.html","./src/app/modules/dashboards/dashboard/dashboard.component.ts","./src/app/modules/dashboards/openproject-dashboards.module.ts","./src/app/components/modals/preview-modal/wp-preview-modal/wp-preview.modal.html","./src/app/components/modals/preview-modal/wp-preview-modal/wp-preview.modal.ts","./src/app/globals/global-listeners/preview-trigger.service.ts","./src/app/modules/overview/overview.component.ts","./src/app/modules/overview/openproject-overview.module.ts","./src/app/modules/my-page/my-page.component.ts","./src/app/modules/my-page/openproject-my-page.module.ts","./src/app/modules/a11y/keyboard-shortcut-service.ts","./src/app/components/wp-table/embedded/wp-embedded-table-entry.component.ts","./src/app/components/wp-table/embedded/embedded-tables-macro.component.ts","./src/app/modules/common/colors/colors-autocompleter.component.ts","./src/app/modules/global_search/global-search-work-packages.component.ts","./src/app/components/homescreen/blocks/new-features.component.ts","./src/app/modules/bim/bcf/bcf-constants.const.ts","./src/app/components/wp-custom-actions/date-action/custom-date-action-admin.html","./src/app/components/wp-custom-actions/date-action/custom-date-action-admin.component.ts","./src/app/modules/boards/boards-sidebar/boards-menu.component.html","./src/app/modules/boards/boards-sidebar/boards-menu.component.ts","./src/app/modules/global_search/global-search-work-packages-entry.component.ts","./src/app/modules/common/notifications/upload-progress.component.ts","./src/app/modules/common/notifications/notification.component.html","./src/app/modules/common/notifications/notification.component.ts","./src/app/modules/common/notifications/notifications-container.component.ts","./src/app/ckeditor/ckeditor-augmented-textarea.html","./src/app/ckeditor/ckeditor-augmented-textarea.component.ts","./src/app/modules/common/persistent-toggle/persistent-toggle.component.ts","./src/app/modules/common/hide-section/hide-section.service.ts","./src/app/modules/common/hide-section/hide-section-link/hide-section-link.component.ts","./src/app/modules/common/hide-section/hide-section-link/hide-section-link.component.html","./src/app/modules/common/hide-section/show-section-dropdown.component.ts","./src/app/modules/common/hide-section/add-section-dropdown/add-section-dropdown.component.html","./src/app/modules/common/hide-section/add-section-dropdown/add-section-dropdown.component.ts","./src/app/modules/common/autocomplete/autocomplete-select-decoration.component.ts","./src/app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component.html","./src/app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component.ts","./src/app/modules/common/tabs/content-tabs/content-tabs.component.ts","./src/app/modules/common/copy-to-clipboard/copy-to-clipboard.directive.ts","./src/app/components/modals/confirm-form-submit/confirm-form-submit.directive.ts","./src/app/components/resizer/main-menu-resizer.component.ts","./src/app/modules/global_search/input/global-search-input.component.html","./src/app/modules/global_search/input/global-search-input.component.ts","./src/app/modules/common/collapsible-section/collapsible-section.component.ts","./src/app/modules/common/collapsible-section/collapsible-section.html","./src/app/components/enterprise-banner/enterprise-banner-bootstrap.component.ts","./src/app/modules/common/autocomplete/lazyloaded/lazyloaded-autocompleter.ts","./src/app/components/projects/project-menu-autocomplete/project-menu-autocomplete.component.ts","./src/app/components/projects/project-menu-autocomplete/project-menu-autocomplete.template.html","./src/app/modules/common/remote-field-updater/remote-field-updater.component.ts","./src/app/components/wp-query-select/wp-query-select.template.html","./src/app/components/wp-query-select/wp-query-select-dropdown.component.ts","./src/app/modules/global_search/title/global-search-title.component.ts","./src/app/modules/global_search/title/global-search-title.component.html","./src/app/modules/global_search/tabs/global-search-tabs.component.ts","./src/app/components/main-menu/main-menu-toggle.component.ts","./src/app/modules/members/members-autocompleter.component.ts","./src/app/components/enterprise/enterprise-trial.service.ts","./src/app/helpers/i18n/localized-link.ts","./src/app/components/enterprise/enterprise-modal/enterprise-trial-form/ee-trial-form.component.html","./src/app/components/enterprise/enterprise-modal/enterprise-trial-form/ee-trial-form.component.ts","./src/app/components/enterprise/enterprise-active-trial/ee-active-trial.base.ts","./src/app/components/enterprise/enterprise-active-trial/ee-active-trial.component.html","./src/app/components/enterprise/enterprise-active-trial/ee-active-trial.component.ts","./src/app/components/enterprise/enterprise-trial-waiting/ee-trial-waiting.component.html","./src/app/components/enterprise/enterprise-trial-waiting/ee-trial-waiting.component.ts","./src/app/components/enterprise/enterprise-modal/enterprise-trial.modal.html","./src/app/components/enterprise/enterprise-modal/enterprise-trial.modal.ts","./src/app/components/enterprise/enterprise-base.component.html","./src/app/components/enterprise/enterprise-base.component.ts","./src/app/components/enterprise/enterprise-active-trial/ee-active-saved-trial.component.ts","./src/app/modules/time_entries/edit/trigger-actions-entry.component.ts","./src/app/modules/fields/macros/attribute-model-loader.service.ts","./src/app/modules/fields/display/display-field.component.ts","./src/app/modules/fields/macros/attribute-value-macro.html","./src/app/modules/fields/macros/attribute-value-macro.component.ts","./src/app/helpers/string-helpers.ts","./src/app/modules/fields/macros/attribute-label-macro.html","./src/app/modules/fields/macros/attribute-label-macro.component.ts","./src/app/modules/fields/macros/work-package-quickinfo-macro.html","./src/app/modules/fields/macros/work-package-quickinfo-macro.component.ts","./src/app/modules/admin/editable-query-props/editable-query-props.component.ts","./src/app/modules/admin/editable-query-props/editable-query-props.component.html","./src/app/global-dynamic-components.const.ts","./src/app/modules/members/members.module.ts","./src/app/components/enterprise/openproject-enterprise.module.ts","./src/app/modules/augmenting/services/modal-wrapper.augment.service.ts","./src/app/modules/augmenting/services/path-script.augment.service.ts","./src/app/modules/augmenting/openproject-augmenting.module.ts","./src/app/modules/bim/revit_add_in/revit-add-in-settings-button.service.ts","./src/app/angular4-modules.ts","./src/main.ts","./src/app/sentry/sentry-reporter.ts","./src/app/init-locale.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts"],"names":["WorkPackageChangeset","key","val","super","setValue","this","updateForm","payload","description","applyChanges","pristineResource","isNew","setNewDefaultFor","form$","hasValue","create","schema","projectedResource","WorkPackageStatesInitializationService","states","querySpace","wpTableColumns","wpTableGroupBy","wpTableGroupFold","wpTableSortBy","wpTableFilters","wpTableSum","wpTableTimeline","wpTableHierarchies","wpTableHighlighting","wpTableRelationColumns","wpTablePagination","wpTableOrder","wpTableAdditionalElements","apiV3Service","wpListChecksumService","authorisationService","wpDisplayRepresentation","query","results","clearStates","putValue","initializeFromQuery","updateQuerySpace","updateChecksum","form","_","each","filtersSchemas","elements","schemas","get","$href","initializeFilters","queryForm","queries","columns","allowedValues","sortBy","groupBy","displayRepresentation","additionalRequiredWorkPackages","clear","tableRendered","href","initModelAuth","$links","forEach","wp","work_packages","cache","updateWorkPackage","groups","initialize","values$","pipe","subscribe","initialized","updateIfDifferent","value","current","applyToQuery","reason","UserLinkComponent","I18n","user","showUserPath","name","t","WorkPackageReplacementLabelComponent","wpeditForm","elementRef","$element","jQuery","nativeElement","evt","target","closest","length","field","fields","fieldName","handleUserActivate","activate","AttachmentCollectionResource","source","$initialize","HalEventsService","_events","events$","asObservable","resourceType","debounceTimeInMs","event","resourceReference","id","_type","next","AccessibleByKeyboardComponent","execute","isDisabled","emit","handleClick","contextMenuTdClassName","contextMenuSpanClassName","contextMenuLinkClassName","contextColumnIcon","OpTableAction","injector","workPackage","ANIMATION_RATE_MS","TopMenu","menuContainer","hover","menuIsOpen","withHeadingFoldOutAtBorder","setupDropdownClick","registerEventHandlers","closeOnBodyClick","accessibility","skipContentClickListener","on","visibleLink","not","first","trigger","attr","dropdown","isOpen","closing","open","opening","startHover","stopHover","closeAllItems","removeClass","addClass","openDropdowns","ix","item","close","self","wrapper","document","getElementById","addEventListener","contains","dropdowns","filter","find","menu_start_position","undefined","tagName","innerHeight","position","top","css","hasClass","children","wiki_heading","it","click","toggleClick","e","preventDefault","dontCloseWhenUsing","closeOtherItems","slideAndFocus","immediate","slideUp","stopPropagation","bind","callback","slideDown","focusFirstInputOrLink","toDrop","hide","toFocus","blur","setTimeout","focus","toggler","latestActivityInfo","trackByHref","trackByProperty","workPackageId","ngOnInit","activities","updateActivities","latestActivities","visible","reverse","unfilteredActivities","slice","map","el","i","info","segment","startIndex","$state","tabName","params","requireAndStream","untilDestroyed","makeSplitViewRoutes","baseRoute","menuItemClass","showComponent","newComponent","makeFullWidth","routeName","url","redirectTo","reloadOnSearch","data","bodyClasses","menuItem","newRoute","partition","views","component","parent","allowMovingInEditMode","BcfPathHelperService","pathHelper","projectIdentifier","projectPath","filters","viewpoint","webpackAsyncContext","req","__webpack_require__","o","Promise","resolve","then","Error","code","ids","keys","Object","module","exports","relationCellTdClassName","relationCellIndicatorClassName","RelationCellbuilder","column","td","createElement","classList","add","dataset","expanded","getExpandFor","relationState","wpRelations","state","relations","relationsForColumn","indicator","renderIndicator","badge","renderBadge","appendChild","setAttribute","textContent","RestrictedWpTableConfigurationService","locals","disabledTabs","_tabs","disableBecause","LinkHandling","isClickedWithModifier","modifier","ctrlKey","shiftKey","metaKey","middleButton","button","WorkPackageViewCollapsedGroupsService","workPackageViewGroupByService","schemaCacheService","groupTypesWithHeaderCellsWhenCollapsed","isMilestone","of","wpTypesToShowInCollapsedGroupHeaders","updatesState","getValueOr","getDefaultState","config","allGroupsAreCollapsed","allGroupsAreExpanded","collapsedGroups","allGroupsChanged","lastChangedGroup","groupedBy","currentGroupedBy","getAllGroupsCollapsedState","currentGroups","groupIdentifier","newCollapsedState","newState","update","collapsedState","groupUpdatedState","reduce","updatedState","group","identifier","currentCollapsedGroupsState","firstGroupIdentifier","firstGroupCollapsedState","allGroupsHaveTheSameCollapseState","every","QueryFiltersService","schemaCache","available","$embedded","allowedFilterValue","getFilterSchema","updateValue","WorkPackageCreateSettingsMenuDirective","opContextMenu","halEditing","workPackages","changeFor","getForm","loadedForm","buildItems","show","positionArgs","assign","my","at","items","configureFormLink","configureForm","queryCustomFields","customFields","push","icon","linkText","onClick","splitViewRoute","WorkPackageViewHighlightingService","Banners","isInline","eeShowBanners","selectedAttributes","lastUpdatedState","mode","filteredValue","highlight","highlightingMode","highlightedAttributes","isEqual","isEmpty","conditional","browserDetector","wpCreate","ngAfterViewInit","active","isMobile","stateName","getEmptyForm","type","contextMenuId","types","disabled","ariaLabel","class","inlineClass","$event","go","currentProject","transition","cdRef","text","createWithDropdown","createButton","explanation","observeUntil","allowed","allowedWhen","combined","permission","split","can","updateDisabledState","transitionUnregisterFn","onSuccess","ngOnDestroy","includes","detectChanges","WorkPackageCommentFieldHandler","handler","inEditMode","inFlight","onDestroy","change","withText","raw","writable","required","hasDefault","commentValue","deactivate","reset","complete","querySelector","onlyCancel","WorkPackageEditActionsBarComponent","editForm","onSave","onCancel","_saving","save","cancel","saving","submit","catch","wpRelationsHierarchy","notificationService","onSwitch","isSaving","edit_parent","set_or_remove_parent","remove_parent","set_parent","changeParent","editing","toggle","newParent","newParentId","error","handleRawError","WorkPackageBreadcrumbComponent","hierarchy","inputActive","ancestors","hierarchyCount","AttachmentsUploadComponent","ConfigurationService","notificationsService","halResourceService","draggingOver","uploadLabel","dropFiles","dropFilesHint","foldersWarning","maxFileSize","maximumAttachmentFileSize","filePicker","dataTransfer","dropEffect","dfFiles","files","uploadFiles","containsFiles","Array","from","indexOf","countBefore","filterFolders","resource","uploadAttachments","addNotice","file","size","console","warn","EditFieldControlsComponent","basePath","path","resourceClass","headers","encoder","fromObject","withCredentials","responseType","_request","method","body","http","request","response","deserialize","catchError","throwError","parse","BcfProjectResource","BcfTopicAuthorizationMap","String","BcfTopicResource","preserveNull","deserializer","moment","serializer","timestamp","toISOString","format","bcfTopicService","toPath","comments","viewpoints","BcfExtensionResource","bcfExtensionService","bcfProjectService","topics","extensions","bcfApiVersion","appBasePath","window","bcfApiBase","projects","startsWith","parts","replace","pathOrId","UserAvatarRendererService","colors","container","users","renderName","multiLine","span","avatar","render","sep","classes","userInitials","getInitials","colorCode","toHsl","fallback","className","style","background","image","Image","src","toString","title","alt","onload","replaceWith","characters","lastSpace","lastIndexOf","toUpperCase","join","AngularTrackingHelpers","compareByAttribute","attribute","a","b","compareByHref","halHref","_index","compareByName","trackByName","prop","trackByHrefAndProperty","propertyName","trackByTrackingIdentifier","compareByHrefOrString","timelineElementCssClass","timelineBackgroundElementClass","timelineGridElementCssClass","timelineMarkerSelectionStartClass","timelineHeaderCSSClass","timelineHeaderSelector","TimelineViewParametersSettings","zoomLevel","zoomLevelOrder","getPixelPerDayForZoomLevel","requiredPixelMarginLeft","TimelineViewParameters","now","hour","minute","seconds","dateDisplayStart","dateDisplayEnd","clone","settings","activeSelectionMode","selectionModeStart","maxSteps","pixelPerDay","diff","Math","ceil","calculatePositionValueForDayCountingPx","viewParams","days","calculatePositionValueForDayCount","getTimeSlicesForHeader","vp","unit","startView","endView","inViewport","rest","time","startOf","end","endOf","isBefore","sliceStart","sliceEnd","viewport","visibleViewportAtCalculationTime","isSameOrAfter","isSameOrBefore","firstRest","splice","lastRest","pop","inViewportAndBoundaries","concat","isNil","calculateDaySpan","visibleWorkPackages","loadedWorkPackages","viewParameters","earliest","latest","renderedRow","wpId","start","startDate","date","due","dueDate","isAfter","OpContextMenuLocalsToken","OPContextMenuComponent","hidden","service","divider","componentFactoryResolver","FocusHelper","appRef","$transitions","isOpening","hostElement","portalHostElement","bodyPortalHost","onStart","which","ESCAPE","that","menu","portal","injectorFor","attach","display","reposition","onOpen","activeMenu","detach","onClose","injectorTokens","WeakMap","set","newWorkPackageHref","WorkPackageCreateService","hooks","halEvents","newWorkPackageCreatedSubject","committedChanges","commit","wasNew","newWorkPackageCreated","changes$","changeset","withOptionalProject","forPayload","toPromise","fromCreateForm","initializeNewResource","edit","call","copyFrom","$source","post","stopEditing","defaults","changePromise","continueExistingEdit","createNewWithDefaults","clearSome","changeType","hasChanges","typeEmpty","typeMatches","idFromLink","withFiltersPayload","filterDefaults","mergedPayload","merge","_links","createNewWorkPackage","defaultsFromFilters","object","except","applyDefaultsFromFilters","fromFilter","forTypePayload","toApiPayload","links","$plain","createHalResourceOfType","__initialized_at","Date","updateImmediately","cssClassCustomOption","DisplayField","context","activeChange","texts","empty","placeholder","constructor","isFormattable","valueString","element","displayText","options","emptyDiv","ActivityPanelBaseController","$transition","wpActivity","visibleActivities","onlyComments","commentsOnly","showAll","isReversed","togglerText","require","getVisibleActivities","showToggler","shouldShowToggler","count_all","count_with_comments","getActivitiesWithComments","activity","index","rowId","relationRowClass","locateTableRow","locateTableRowByIdentifier","isInsideCollapsedGroup","listClass","locatePredecessorBySelector","selector","previous","previousElementSibling","matches","scrollTableRowIntoView","scrollParent","containerTop","scrollTop","containerBottom","height","elemTop","offsetTop","elemBottom","createLocalInjector","fieldHandler","RowsBuilder","workPackageTable","table","groupClassNameFor","collapse","expand","colspan","togglerIconClass","row","collapsed","innerHTML","escape","count","relationGroupClass","relationCellClassName","emptyRelationCell","buildCell","relation","denormalized","to","targetId","createEmptyRelationRow","tr","buildEmptyRow","relationClassIdentifier","jRow","columnId","typeLabel","reverseRelationType","relationLabel","createTextNode","append","cell","tablePass","relationRowBuilder","isApplicable","renderedOrder","fromId","relationsToExtendFor","relationRow","buildEmptyRelationRow","additionalClasses","appendRelationLabel","spliceRow","classIdentifier","belongsTo","renderType","relationType","oldRow","newRow","refreshRow","hasRelationColumns","timelineBody","createDocumentFragment","timelineBuilder","secondary","build","highlightAttribute","getComputedStyle","property","tableBody","backgroundClass","dragActionRegistry","actionService","canPickup","dragDropHandleBuilder","configuration","dragAndDropEnabled","withLoadedPositions","positions","handle","replaceChild","firstElementChild","rowBuilder","prepare","doRender","postRender","highlighting","dragDropHandle","timeline","replacement","refreshRelationRow","renderedInfo","last","after","renderPlaceholderRow","placeholderRow","classIdentifer","originalRows","originalRowIndex","buildEmpty","appendRow","headerBuilder","sumsBuilder","currentGroup","nextGroup","matchingGroup","groupsChanged","renderSumsRow","groupClass","rowElement","buildGroupRow","appendNonWorkPackageRow","buildSingleRow","isArray","matchesMultiValue","valueLink","l","joinedOrderedHrefs","objects","sort","isEqualWith","sums","buildSumsRow","columnCount","builder","getGroupData","rendered","tableAndTimelineContainer","groupIndex","parentNode","affected","toggleClass","additionalParents","deferred","parentsWithVisibleChildren","hierarchies","ancestor","deferInsertion","buildWithHierarchy","markRendered","renderAllDeferredChildren","ancestorChain","inTable","newElements","child","uniqBy","insertUnderParent","getOrBuildRow","ancestorGroups","ancestorRow","buildAncestorRow","insertAtExistingHierarchy","previousAncestor","isAncestor","buildRenderInfo","hierarchyRoot","hierarchyGroup","ancestorClasses","ancestorRowData","_table","isEnabled","cellBuilder","resourceSubscription","unsubscribe","rowContainer","errors","waitForContainer","findCell","width","parseInt","editingPortalService","findContainer","refresh","focusElement","addColumn","noWarnings","loadFieldSchema","reject","interval","setInterval","clearInterval","forms","destroy","typedState","existing","scrollContainer","tbody","timelineController","hierarchyRowsBuilder","groupedRowsBuilder","plainRowsBuilder","builders","lastRenderPass","findIndex","renderedRows","rows","buildIndex","redrawTableAndTimeline","renderPass","performRenderPass","requestAnimationFrame","result","pass","insert","buildRows","t0","performance","refreshExpansionState","t1","CKEditorSetupService","PathHelper","initialData","load","editorClass","OPConstrainedEditor","OPClassicEditor","toolbarWrapper","contentWrapper","contentLanguage","rtl","editor","createCustomized","openProject","createConfig","language","content","ui","view","toolbar","setData","cb","getData","trim","macros","helpURL","textFormattingHelp","pluginContext","OpenProject","EditFieldService","selectorTimelineSide","jQueryScrollSyncEventNamespace","getPlattformAgnosticScrollAmount","originalValue","delta","syncWheelEvent","jev","elementTable","elementTimeline","scrollTarget","ev","originalEvent","deltaX","deltaY","x","y","getXandYScrollDeltas","scrollLeft","createScrollSync","elTable","elTimeline","timelineVisible","syncedLeft","syncedRight","off","AuthoringComponent","timezoneService","createdOnTime","parseDatetime","createdOn","timeago","fromNow","userLink","userPath","author","projectActivityPath","project","halNotification","destroyImmediately","removeAttachment","dragHint","destroyConfirmation","removeFile","arg","downloadPath","previewElement","draggableHTML","outerHTML","setDragImage","isImage","fileName","attachmentDownloadPath","attachment","ext","imageFileExtensions","toLowerCase","customName","confirm","stopImmediatePropagation","setDragData","attachments","deletedAttachments","updateAttachments","setupResourceUpdateListener","setupAttachmentDeletionCallback","forResource","newResource","$formElement","newAttachments","attachmentsBackend","destroyRemovedAttachments","attachmentsUpdatable","updateElements","HighlightableDisplayField","colorize","shouldHighlight","viewHighlighting","shouldHighlightInline","highlightName","tableActionsService","tableRowClassName","commonRowClassName","relationCellBuilder","contextLinkBuilder","augmentedColumns","buildAugmentedColumns","getColumns","unshift","actionsColumnEnabled","columnMenuEnabled","createEmptyRow","colSpan","cells","newCells","oldTd","isColumnBeingEdited","prepend","activeFields","changedAttributes","oldCell","wpTableSelection","isSelected","inlineCreateRowClassName","cancelButton","buildCancelButton","wpInlineCreate","wpTableFocus","canAdd","canReference","buttonTexts","hasReferenceClass","registerCreationCallback","refreshOnColumnChanges","registerCancelHandler","resetRow","updates$","isActive","onNewWorkPackage","currentWorkPackage","isEmbedded","updateFocus","newInlineWorkPackageCreated","cancelCreation","removeWorkPackageRow","showRow","addWorkPackageRow","referenceComponentClass","referenceClass","createOrContinueWorkPackage","editingSubscription","changesetUpdates$","insertRow","workPackageEditForm","renderInlineCreateRow","activateMissingFields","hideRow","startEditing","buildNew","remove","WorkPackageViewSortByService","pristineState","comparer","wasManuallySorted","isManuallySorted","isManualSortingMode","candidate","criteria","findAvailableDirection","direction","newValue","manualSortObject","persisted","availableState","endsWith","deactivateFilter","searchTerm","searchTermChanged","Subject","pristine$","currentSearchFilter","values","upstreamTerm","log","timestampOfLastValue","isValueOlderThan","distinctUntilChanged","tap","debounceTime","term","operator","findOperator","shouldFocus","filterChanged","onFilterUpdated","isValid","d","parseDate","formattedISODate","parser","spacer","isValidISODateTime","isValidISODate","parseISODatetime","formattedISODateTime","lowerBoundary","upperBoundary","hours","minutes","isoDateParser","begin","enter_text","halSorting","_availableOptions","requests","loadAvailable","_isEmpty","initialization","input$","ngSelectInstance","output$","availableOptions","matching","createFilters","currentSchema","collectionFromString","filtered","collection","dropdownPanel","_updatePosition","setValues","repositionDropdown","currentUser","fetchAllowedValues","castArray","loadAllowedValues","loadingPromises","$load","isUserResource","root","all","resources","addMeValue","me","createHalResource","bannerService","showValuesInput","open_filter","close_filter","label_filter_add","upsale_for_more","upsale_link","button_delete","showValues","availableOperators","isValueRequired","removeThisFilter","filtersChanged","wpFiltersService","showCloseFilter","remainingFilters","focusElementIndex","close_form","selected_filter_list","please_select","filter_by_text","updateRemainingFilters","filterToBeAdded","newFilter","instantiate","currentFilterLength","updateFilterFocus","ngSelectComponent","clearItem","toggleVisibility","removedFilter","f","hasSearch","hasAvailableFilter","isFilterAvailable","remainingVisibleFilters","activeFilterCount","filterIndex","currentFilterAt","availableFilters","some","availableFilter","isTemplated","GlobalEditFormChangesTrackerService","i18nService","activeForms","Map","thereAreFormsWithUnsavedChanges","returnValue","delete","editFormRouting","globalEditFormChangesTrackerService","initializeEditMode","skippedFields","onSavedEmitter","registeredFields","confirmText","requiresConfirmation","warnOnLeavingUnsaved","unregisterListener","onBefore","blockedTransition","editMode","addToActiveForms","removeFromActiveForms","waitForField","ctrl","setActive","editContainer","savedResource","isInitial","closeEditFields","hasActiveFields","skipField","activateOnForm","take","changed","changes","uniqueEmbeddedTableName","initialLoadingIndicator","renderTable","showTablePagination","providedConfiguration","loadQuery","queryId","queryProps","projectContext","wpStatesInitialization","urlParamsHelper","buildV3GetQueryFromQueryResource","encodeQueryJsonParams","tableVisible","firstPage","pagination","paginationObject","offset","promise","wpListService","loadQueryFromExisting","queryProjectScope","loadingIndicator","loadingIndicatorService","tableActions","externalHeight","onError","onQueryLoaded","loadedQuery","setActions","page","perPage","withLatestFrom","initializeStates","onUpdated","valuesPromise","opModalService","onDataUpdated","withFilters","loadForm","total","setLoaded","isVisible","compactTableStyle","formPromise","apiv3Service","updateStatesFromForm","pageSize","message","double","keepTab","requestedState","EditFormPortalComponent","editField","onEditFieldReady","editFieldHandler","schemaInput","changeInput","componentClass","getSpecificClassFor","fieldInjector","WorkPackageSchemaProxy","receiver","isReadonly","propertySchema","ofProperty","isAttributeEditable","status","scheduleManually","hasOwnProperty","FocusHelperService","minimumOffsetForNewSwitchInMs","lastFocusSwitch","lastPriority","allowFocusSwitch","priority","checkTimeout","throttleAndCheckIfAllowedFocusChangeBasedOnTimeout","focusser","focusable","is","FOCUSABLE_SELECTORS","getFocusableElement","$focusable","checkIfAllowedFocusChange","WorkPackageViewHierarchyIdentationService","wpViewHierarchies","wpRelationHierarchy","isList","applicable","renderedWorkPackageIds","ancestorIds","ancestorCount","lastAncestor","canIndent","predecessorId","predecessor","difference","canOutdent","WorkPackageWatcherButtonComponent","wpWatchersService","showText","setWatchStatus","isWatched","toggleLink","nextStateLink","$link","linkName","buttonTitle","buttonText","buttonClass","buttonId","watchIconClass","SelectionHelpers","hasSelectionWithin","selection","getSelection","hasSelection","isWithin","anchorNode","NotificationsService","displayFieldOptions","isDropTarget","editFieldContainerClass","destroyed","componentDestroyed","fieldRenderer","register","temporaryEditResource","isEditable","displayPlaceholder","displayContainer","positionOffset","getPosition","$onUserActivate","startDragOverActivation","activateIfEditable","WorkPackageCardDragAndDropService","reorderService","dragService","componentRef","cardView","dragContainer","scrollContainers","moves","card","canDragOutOf","accepts","dragInto","onMoved","toIndex","newOrder","move","currentOrder","updateOrder","onRemoved","onAdded","addWorkPackageToQuery","parentElement","removeChild","_workPackages","activeInlineCreateWp","existingNewWp","uniq","workPackageAddedHandler","removeCard","DomHelpers","setBodyCursor","cursor","setProperty","validationErrors","halInitializer","errorIdentifier","isValidationError","idPart","decodeURIComponent","HelpTextResource","WikiPageResource","MeetingContentResource","PostResource","timeEntries","without","$linkableKeys","halResourceDefaultConfig","WorkPackage","cls","attrTypes","Activity","Relation","Schema","Type","Status","SchemaDependency","User","Group","Collection","WorkPackageCollection","AttachmentCollection","Query","Form","FormPayload","QueryFilterInstance","QueryFilterInstanceSchema","QueryFilter","Root","QueryOperator","HelpText","CustomAction","WikiPage","MeetingContent","Post","Project","Role","Grid","GridWidget","TimeEntry","Membership","News","Version","internal_error","errorMessages","ErrorReporter","captureException","captureMessage","handleError","OpenprojectHalModule","provide","useClass","multi","useFactory","registerResource","deps","ConfirmDialogModal","confirmed","button_continue","button_cancel","close_popup","dangerHighlighting","defaultTo","passedData","closeOnEscape","closeByEscape","closeOnOutsideClick","closeByDocument","showClose","closeMe","confirmAndClose","OpenprojectAccessibilityModule","NoResultsComponent","setHostClass","AbstractFieldService","attributeType","fieldType","defaultFieldType","getClassFor","fieldClass","attributes","addFieldType","loadConfiguration","userPreference","timezone","prepareAttachmentURL","systemPreference","startOfWeekPresent","locale","firstDayOfWeek","pref","OpContextMenuHandler","afterFocusOn","openerEvent","collision","DragAndDropHelpers","reinsert","previousIndex","currentIndex","pointOfInsertion","insertBefore","timelineCellClassName","TimelineRowBuilder","rowClasses","WorkPackageWatchersCountComponent","wpWatcherService","watchers","EditFormRoutingService","QueryFilterInstanceResource","memoizedCurrentSchemas","api","v3","apiV3Base","resultingSchema","operatorSymbol","flag","BoardActionsRegistryService","mapping","localizedName","WorkPackageService","UrlParamsHelper","successful_delete","defaultHandling","workPackagesBulkDeletePath","addSuccess","eventType","urlParams","buildQueryString","location","UntilDestroyedMixin","IconTriggeredContextMenuComponent","menuItems","additional","WorkPackageViewGroupByService","cur","environment","production","QueryResource","HalLink","requestMethod","templated","link","templateValues","regexp","RegExp","$callable","linkFunc","$fetch","extend","Board","grid","isAction","isFree","widget","isNewWidget","widgets","createdAt","startColumn","actionAttribute","ContainHelpers","insideOrSelf","within","whenOutside","activeElement","collapsedGroupClass","ancestorId","hierarchyGroupClass","hierarchyRootClass","ancestorClassIdentifier","WpTableConfigurationRelationSelectorComponent","relationFilterIds","availableRelationFilters","selectedRelationFilter","filter_work_packages_by_relation_type","precedes","follows","relates","duplicates","duplicated","blocks","blocked","requires","partof","onReady","relationFiltersOf","setSelectedRelationFilter","currentRelationFilters","onRelationFilterSelected","removeRelationFiltersFromCurrentState","addFilterToCurrentState","filtersToRemove","getOperatorForId","f1","f2","useValue","subResource","extractPayload","patch","listParamsString","JSON","stringify","filterParam","toParams","queryPropsString","apiRoot","createCache","force","stale","observable","shareReplay","clearAndLoad","observe","switchMap","mapTo","updateFor","source$","touch","extractPayloadFromSchema","observeAll","ensureLoaded","cacheResponse","projectId","toJson","available_projects","wpIds","withOptionalId","queryFilters","setSchemas","buildQueryResource","URI","search","order","mapSchemasIntoFilters","parameterised","default","filter_instance_schemas","queryData","starred","unstar","star","listParams","list","workPackageIds","validIds","test","revisions","available_watchers","skipOnIdentical","multiState","updateWorkPackageList","loadCollectionsFor","pagedResults","idOnly","additionalParams","n","getAllPaginated","version","versions","available_assignees","statuses","$configuration","grids","newBoard","sortWidgets","board","fetchSchema","boardPath","scope","createGrid","projectBoardsPath","forType","apiV3CollectionEndpoint","apiV3CustomEndpoint","documents","apiV3SingularEndpoint","priorities","time_entries","memberships","news","placeholder_users","help_texts","job_statuses","boards","fullPath","triggerEditingEvent","selectableTitleIdentifier","EditableToolbarTitleComponent","editable","showSaveCondition","initialFocus","smallHeader","onEmptySubmit","click_to_edit","press_enter_to_save","query_has_changed_click_to_save","input_title","input_placeholder","search_query_title","confirm_edit_cancel","duplicate_query_title","inputField","selectedTitle","inputTitle","currentValue","firstChange","selectInputOnInitalFocus","toggleToolbarButtonVisibility","input","select","resetInputField","onEmptyError","emitSave","focusInputOnError","i18n","resourceChanged","editableName","widgetIdentifier","defaultValue","setChangesetOptions","GonService","gon","BackButtonComponent","backRoutingService","goBack","customBackMethod","linkClass","SchemaResource","match","availableAttributes","fieldSchema","WorkPackagesListService","wpListInvalidQueryService","queryRequests","queryLoading","q","ensurePerPageKnown","streamQueryRequest","queryParams","conditionallyLoadForm","decodedProps","getCurrentQueryProps","buildV3GetQueryFromJsonParams","query_id","handleQueryLoadingError","query_props","fromQueryParams","reloadQuery","currentQuery","loadDefaultQuery","reload","addError","toggleStarred","currentForm","loadWithParams","restoreQuery","isPerPageKnown","WorkPackagesViewBase","queryLoaded","setupQueryObservers","setupRefreshObserver","setupQueryLoadedListener","isQueryOutdated","setupChangeObserver","queryState","hasChanged","newQuery","triggerUpdate","aggregated$","events","filterRefreshEvents","Set","has","ConfirmDialogService","closingEvent","modal","DynamicBootstrapper","defs","optionalBoostrapComponents","doc","definitions","performBootstrap","embeddable","embedded","querySelectorAll","bootstrap","QueryParamListenerService","observe$","listenForQueryParamsChanged","queryChangeListener","newChecksum","newId","custom","notify","executeIfOutdated","IsolatedQuerySpace","timelineRendered","renderedWorkPackages","$","stopAllSubscriptions","keyCodes","WorkPackageViewSumService","WpTableExportModal","httpClient","notifications","closePopup","exportPreparing","requestExport","exportOptions","buildExportOptions","representations","label","addColumnsToHref","json","replaceWithJobModal","job_id","jobId","showError","columnIds","removeSearch","addSearch","WorkPackageViewFiltersService","incomplete","rawFilters","newFilters","filterOrId","availableSchemas","getFilter","mapper","isCompletelyDefined","cloneFilters","invisibleFilters","currentFilterResources","isComplete","differenceBy","WorkPackageViewRelationColumnsService","eachCallback","findById","relationColumnType","typeHref","RELATION_TO_TYPE","RELATION_OF_TYPE","nextState","WorkPackageInlineCreateService","referenceTarget","reference","newInlineWorkPackageReferenced","canCreateWorkPackages","internalSortColumn","internalContextMenuColumn","CKEditorPreviewService","preview","refs","getEmbeddable","entry","matchedElements","resolveComponentFactory","attachView","hostView","changeDetectorRef","ref","detachView","QueryFilterInstanceSchemaResource","_dependencies","dependency","definesAllowedValues","staticSchema","dependentSchema","forValue","dependencies","OpenprojectProjectsModule","ClickPositionMapper","setPosition","setSelectionRange","originalEvt","caretRangeFromPoint","clientX","clientY","startOffset","rangeParent","range","createRange","setStart","rangeOffset","Changeset","k","pristineValue","getItem","updatePristineResource","buildPayloadFromChanges","_pristineResource","Proxy","proxyGet","isPristine","hasActivePromiseRequest","setNewDefaults","putFromPromiseIfPristine","getValue","lockVersion","plainPayload","getLinkedValue","cloneDeep","minimalPayload","isArrayType","valueExists","HalPayloadHelper","nonLinkProperties","TabPortalOutlet","availableTabs","outletElement","activeTabs","currentTab","tab","instance","activateInstance","_getComponentRootNode","setAttachedHost","dispose","createComponent","rootNodes","WorkPackageIsolatedQuerySpaceDirective","useExisting","OpenProjectHeaderInterceptor","csrf_token","newHeaders","clonedRequest","StateCacheService","holdValuesForSeconds","cacheDurationInMs","loader","clearAndPutFromPromise","observeChange","mapped","HighlightColDirective","thead","siblings","currentTarget","highlightColBootstrap","usersAutocompleterSelector","UserAutocompleterComponent","userTracker","onChange","clearAfterSelection","allowEmpty","appendTo","multiple","initialSelection","getAvailableUsers","inputFilters","updateInputField","getElementsByName","setInitialSelection","filterInput","lastRequestedValue","u","searchFilters","res","isNaN","onFocus","onModelChange","OpModalLocalsToken","OpModalService","closeOnEscapeFunction","activeModal","withErrors","setErrors","htmlId","fieldLabel","setClickOffset","subject","handleUserSubmit","newErrors","isErrorenous","onBeforeSubmit","onSubmit","ENTER","handleUserCancel","messages","previewPath","outlet","createDomOutlet","localInjector","attachComponentPortal","DisplayFieldService","apply","WorkPackageViewColumnsService","isCurrentlyEqualTo","c","toApply","oldColumns","newColumns","relationColumns","isLast","setColumns","compact","fromIndex","moveColumn","newColumn","PROPERTY","Apiv3Paths","base","PathHelperService","attachmentIdentifier","slug","staticBase","forumIdentifier","projectForumPath","messageIdentifier","newsId","projectsPath","projectWorkPackagesPath","suffix","workPackagePath","usersPath","placeholderUsersPath","groupsPath","workPackagesPath","DeviceService","mobileWidthTreshold","innerWidth","workPackageNotificationService","showSave","postIcon","postIconTitle","updateStatus","workPackageReadOnly","workPackageStatusBlocked","renderEmpty","renderValues","div","percentLabel","avatarRenderer","renderMultiple","editableClassName","readOnlyClassName","displayClassName","fieldCache","renderFieldValue","setSpanAttributes","requestedAttribute","attributeName","getField","getText","getAriaLabel","getFieldForCurrentContext","isCustomMultiLinesField","isUserMultiLinesField","displayFieldService","getDefaultPlaceholder","titleContent","labelContent","getLabelContent","displayName","mappedName","AuthorisationService","modelName","modelLinks","doModify","action","Attachable","Base","addAttachment","pull","$isHal","max","updateState","uploads","finished","performUpload","notification","addAttachmentUpload","r","ErrorEvent","directUploadURL","opDirectFileUpload","uploadAndMapResponse","opFileUpload","prepareAttachment","Field","WorkPackageRelationsAutocomplete","CurrentProject","inputPlaceholder","additionalFilters","hiddenOverflowContainer","onSelected","onEmptySelected","isLoading","searchInput$","appendToContainer","results$","queryString","autocompleteWorkPackages","availableRelationCandidates","filterCandidatesFor","selectedRelationType","one","onWorkPackageSelected","HalResource","$loaded","$halType","other","_name","_fieldName","$loadResource","$self","properties","OpIcon","iconTitle","RelationResource","includeParentChild","includeParentchild","RELATION_TYPES","reverseType","URLParamsEncoder","encodeURIComponent","VersionResource","WorkPackageCopyController","copying","addCommonRelation","copiedWorkPackageId","stateParams","copiedFromWorkPackageId","createCopyFrom","titleService","setFirstPart","sourceChangeset","copyWorkPackage","copyChangeset","ProgressDisplayField","roundedProgress","round","Number","WorkPackageActivityTabComponent","WorkPackageViewAdditionalElementsService","requireInvolvedRelations","requireHierarchyElements","requireSumsSchema","loadAdditional","flatten","requireAll","getInvolvedWorkPackages","sumsSchema","DomAutoscrollService","down","scrollWhenOutside","maxSpeed","margin","autoScroll","point","pointCB","init","onMove","onUp","setScroll","cleanAnimation","cancelAnimationFrame","animationFrame","windowAnimationFrame","scrolling","targetObject","underPoint","inside","dispatched","getElementsUnderPoint","getTarget","outerScrollContainer","scrollTick","scrollAutomatically","scrollx","scrolly","rect","left","right","bottom","scrollY","scrollX","amount","scrollTo","pageXOffset","pageYOffset","WorkPackageAuthorization","workPackageDetailsCopyPath","workPackageCopyPath","copyLink","allActions","allowedActions","validActions","isPermitted","linkForAction","HookService","opContextMenuService","authorization","permittedActions","getPermittedActions","timeEntryCreateService","actions","permittedActionsWithLinks","getPermittedPluginActions","indexBy","triggerContextMenuAction","DatePicker","datepickerElemIdentifier","datepickerTarget","configurationService","datepickerFormat","datepickerCont","hideDuringScroll","datepickerInstance","reshowTimeout","clearTimeout","visibleAndActive","startOfWeek","mergedOptions","weekNumbers","getWeek","dateObj","week","dateFormat","defaultDate","weekdays","shorthand","longhand","months","weekAbbreviation","datePickerInstances","removeEventListener","dates","setDate","isInViewport","getBoundingClientRect","documentElement","clientHeight","clientWidth","GridWidgetResource","endRow","startRow","endColumn","halResource","HalResourceNotificationService","isCreate","handleErrorResponse","errorBody","retrieveError","showGeneralError","createHalResourceOfClass","errorResource","showApiErrorMessages","showCustomError","details","i18nString","lookup","OpContextMenuTrigger","Mousetrap","OpenprojectHalModuleHelpers","lazy","obj","getter","setter","isObject","done","configurable","enumerable","defineProperty","cloneHalResourceCollection","v","$copy","initializeHalProperties","asHalResource","loaded","_embedded","setupProperty","instanceName","sourceName","sourceObj","propName","setSource","$embeddableKeys","createLinkedResource","setEmbeddedAsProperties","KeepTabService","updateTabs","isCurrentState","currentShowTab","currentDetailsTab","lastActiveTab","currentShowState","currentDetailsState","updateTab","WorkPackageViewTimelineService","appliedZoomLevel$","defaultState","timelineZoomLevel","labels","timelineLabels","visibilityChanged","zoomLevelChanged","labelsChanged","currentState","setVisible","defaultLabels","modify","positionAsString","level","applyZoomLevel","applied","appliedZoomLevel","setZoomLevel","idx","farRight","ColorsService","valueHash","opacity","hash","charCodeAt","WorkPackageSplitViewToolbarComponent","button_more","firstRoute","backRouting","observeWorkPackage","focusedWorkPackage","isFirstRoute","isSameID","workPackageI","setRowState","whenChanged","goToBaseState","initializeTexts","closeDetailsView","goTofullScreen","ResourcesDisplayField","cf","abridged","optionDiv","valueAbridged","valueForDisplay","WorkPackageContextMenuHelperService","wpViewRepresentation","wpViewTimeline","wpViewIndent","BULK_ACTIONS","permittedActionConstants","allowSplitScreenActions","singularPermittedActions","getAllowedActions","getAllowedParentActions","getAllowedRelationActions","allowedAction","bulkPermittedActions","permittedAction","getBulkActionLink","workPackageIdParams","serializedIdParams","linkAndQueryString","shift","addRelation","addChild","getPermittedActionLinks","getIntersectOfPermittedActions","queryColumnTypes","isRelationColumn","OpDateTimeComponent","formattedDatetimeComponents","dateTimeValue","enterpriseEditionUrl","enterpriseDemoUrl","randomString","pattern","random","_element","charAt","floor","Highlighting","colorClass","highlightColorTextInline","overdueDate","isBright","styles","variable","getPropertyValue","AutofocusDirective","focusHelper","condition","CustomActionResource","FalseValue","TrueValue","ApiV3FilterBuilder","filterMap","only","toAdd","pickBy","toFilterObject","mergeParams","transformedFilters","serializeFilter","URLSearchParams","transformedFilter","typeName","operatorAndValues","serializeFilterValue","filterValue","buildApiV3Filter","WorkPackageRelationQueryBase","queryUrlParamsHelper","embeddedTable","isInitialized","filtersLength","projectValuesCount","loadedFiltersLength","valid_subset","webpackContext","webpackContextResolve","CommentService","quoteEvents","comment","addComment","errorAndReject","WorkPackageRelationsCountComponent","relationCount","childrenCount","slideToggleSelector","SlideToggleComponent","valueChanged","inputName","containerId","containerClasses","inputId","onValueChanged","WorkPackageSingleCardComponent","showInfoButton","showStatusButton","showRemoveButton","draggable","orientation","shrinkOnMobile","onRemove","stateLinkClicked","uiStateLinkClass","detailsView","live$","detail","stateToEmit","setSelection","findRenderedCard","cardHighlighting","attributeHighlighting","bcfSnapshotPath","bcfViewpoints","ChangesetStates","changesets","initializeMembers","ResourceChangesetCommit","saved","changeMap","HalResourceEditingService","hook","buildRequestPayload","retainFrom","onSaved","newChangeset","_i","tree","selectedPage","selected","scrollIntoView","OpModalComponent","openingEvent","modalElement","MainMenuToggleService","deviceService","elementMinWidth","defaultWidth","localStorageKey","localStorageStateKey","global","htmlNode","getElementsByTagName","mainMenu","hideElements","titleData","titleData$","changeData","changeData$","elementWidth","guardedLocalStorage","menuCollapsed","closeMenu","setWidth","saveWidth","offsetWidth","closeWhenOnMobile","showNavigation","savedWidth","widthToSave","maxMenuWidth","snapBack","setToggleTitle","toggleClassHidden","changeEvent","Event","toggleTitle","groupByProperty","groupName","groupedRowClassName","groupTypeFromIdentifier","groupIdFromIdentifier","PERMITTED_CONTEXT_MENU_ACTIONS","CombinedDateDisplayField","startDateElement","createDateDisplayField","dueDateElement","separator","dateElement","dateDisplayField","formattedDate","none","selected_type","button_style","button_style_hint","button_save","selectedType","buttonStyle","availableTypes","typeSelect","applyAndClose","hint","selectedPageInput","_language","debouncedLanguageLoader","debounce","loadLanguageAsMode","language_hint","languageClass","codeMirrorInstance","lang","imported","CodeMirror","fromTextArea","codeMirrorPane","lineNumbers","smartIndent","autofocus","updateCodeMirrorMode","newLanguage","setOption","updateLanguage","includeParent","include_parent","selectedIncludeParent","updateIncludeParent","pageValue","ActivityLinkComponent","activityHtmlId","activityNo","activityLabel","RevisionActivityComponent","loadAuthor","revision","html","revisionPath","showRevision","formattedRevision","formattedIdentifier","revision_identifier","revisionLink","committed_revision_link","formattedDatetime","userName","authorName","userId","userActive","userAvatar","showUser","userLabel","domSanitizer","dynamicBootstrapper","templateString","innerHtml","bypassSecurityTrustHtml","bootstrapOptionalEmbeddable","sanitization","wpLinkedActivities","commentService","ngZone","userCanEdit","userCanQuote","focused","label_created_on","label_updated_on","quote_comment","edit_comment","updateCommentText","isComment","isBcfComment","runOutsideAngular","focussing","rawComment","updateComment","quotedText","newActivity","finally","quoted","line","focusEditIcon","postedComment","ActivityEntryComponent","activityType","demoProjectName","scrumDemoProjectName","onboardingTourStorageKey","waitForElement","execFunction","MutationObserver","mutations","observerInstance","disconnect","childList","subtree","demoProjectsLinks","demoProjects","demoProjectsLink","scrumDemoProjectsLink","preventClickHandler","PaginationInstance","limit","min","WorkPackageTableConfiguration","providedConfig","contextMenuEnabled","inlineCreateEnabled","hierarchyToggleEnabled","isCardView","filtersExpanded","showFilterButton","filterButtonText","WpDestroyModal","busy","childrenDeletionConfirmed","label_visibility_settings","warning","label_confirm_children_deletion","workPackageLabel","singleWorkPackage","singleWorkPackageChildren","childCount","hasChildren","childUnits","deletesChildren","mustConfirmChildren","blockedDueToUnconfirmedChildren","performBulkDelete","confirmDeletion","MIN_ORDER","MAX_ORDER","ORDER_DISTANCE","isAscendingOrder","buildInsertPosition","rebuildPositions","minMaxPositions","redistribute","abs","positionSwap","insertAsFirst","predecessorPosition","buildUpPredecessorPosition","reorderedInsert","successorPosition","positionFor","distance","myPosition","neighbor","neighborPosition","DEFAULT_ORDER","livePosition","firstPosition","lastPosition","itemsToDistribute","space","any","causedUpdates","assignPosition","buildDelta","updatedAt","upstreamOrder","pos","orderedWorkPackages","setExpandFor","additionalPositionArgs","startAddRelationPredecessor","startAddRelationFollower","wpViewIndentation","indent","outdent","rowSelector","openContextMenu","keyCode","F10","altKey","SELECTOR","findRenderedRow","itemClicked","setMultiSelectionFrom","toggleRow","selectionChanged","getSelectedWorkPackageIds","parents","workPackageViewCollapsedGroupsService","toggleGroupCollapseState","takeUntil","redrawTable","lastValue","renderHierarchyState","classNames","isCollapsed","initialSetup","changedId","refreshRows","ifShouldFocus","renderSelectionState","registerSelectAllListener","registerDeselectAllListener","renderVisibility","inlineCreateService","updateRenderedOrder","sibling","rowIndex","collapsedGroupId","collapsedGroupElements","getElementsByClassName","collapsedGroupLastChild","findRowIndex","handleDrop","onNewOrder","switchToManualSorting","changeShadowElement","sourceIndex","onCloned","original","subjectWithId","maxWidth","onShadowInserted","isEdge","mappedOrder","currentRenderedOrder","groupsCollapseEvent","setGroupsCollapseState","eventHandlers","stateTransformers","viewRef","attachTo","cssClassRowHovered","WpTableHoverSync","tableAndTimeline","lastHoveredElement","eventListener","handleHover","passive","removeAllHoverClasses","parentTableRow","locateHoveredTableRow","parentTimelineRow","locateHoveredTimelineRow","removeOldAndAddNewHoverClass","getAttribute","hovered","extractWorkPackageId","tableRow","timelineRow","zone","limitedResults","configurationObject","noResults","tableSummary","tableSummaryHints","combineLatest","timelines","numTableColumns","scrollSyncUpdate","manualSortEnabled","wpTableHoverSync","controller","getTableAndTimelineElement","tableElement","$tableSide","$timelineSide","OpEditingPortalSchemaToken","OpEditingPortalHandlerToken","OpEditingPortalChangesetToken","editModeClassName","EditFieldComponent","updateFromChangeset","markForCheck","parseValue","WorkPackageWatchersService","$update","wpDisplayListRepresentation","wpDisplayCardRepresentation","WorkPackageViewDisplayRepresentationService","representation","WorkPackageRelationsHierarchyService","parentId","relatedWorkPackage","childWpId","wpToBecomeChild","args","parent_id","childWorkPackage","parentWorkPackage","GroupSumsBuilder","sum","renderColumns","renderContent","appendFirstLabel","wpEditForm","fixColumns","fromEvent","elem","descriptor","lastOffset","classNameLeftHandle","classNameRightHandle","registerWorkPackageMouseHandler","getRenderInfo","workPackageTimeline","bar","renderer","renderInfo","dateStates","placeholderForEmptyCell","mouseDownStartDay","jBody","getCursorOffsetInDaysFromLeft","leftOffset","getAbsoluteLeftCoordinates","cursorOffsetLeftInPx","createMouseMoveFn","offsetDayCurrent","offsetX","dayUnderCursor","onDaysMoved","assignDateValues","applyDateValues","keyPressFn","handleMouseMoveOnEmptyCell","isLeaf","canMoveDates","displayPlaceholderUnderCursor","onmouseleave","onmousedown","pointerEvents","offsetDayStart","dateForCreate","mouseDownType","onMouseDown","onmousemove","widthInDays","moved","onmouseup","cancelled","disableViewParamsCalculation","noop","resetCursor","cancelChange","stopAndRefresh","onMouseDownEnd","filterUpdatedSince","saveWorkPackage","refreshView","classNameActiveDrag","workPackageMouseDownFn","classNameLeftLabel","classNameRightContainer","classNameRightLabel","classNameLeftHoverLabel","classNameRightHoverLabel","classNameHoverStyle","classNameFarRightLabel","classNameShowOnHover","classNameHideOnHover","WorkPackageCellLabels","center","leftHover","rightHover","withAlternativeLabels","renderers","latestRenderInfo","wpElement","cellRenderer","getMarginLeftOfLeftSide","getMarginLeftOfRightSide","getPaddingLeftForIncomingRelationLines","getPaddingRightForOutgoingRelationLines","cellElement","cellContainer","elementShape","isDuplicatedCell","createAndAddLabels","milestone","generic","lazyInit","label_children_derived_duration","dateDisplaysOnMouseMove","ganttChartRowHeight","valueOf","zIndex","applyTypeColor","assignDate","updateLabels","initialStartDate","initialDueDate","projection","forceCursor","visibility","backgroundImage","setElementPositionAndSize","checkForActiveSelectionMode","checkForSpecialDisplaySituations","offsetStart","duration","labelCenter","labelLeft","containerRight","labelRight","labelFarRight","labelHoverLeft","labelHoverRight","bg","selectionMode","minWidth","derivedStartDate","derivedDueDate","previousChildrenDurationBar","childrenDurationBar","childrenDurationHoverContainer","visibleChildren","activeDragNDrop","labelConfiguration","getNormalizedLabels","renderLabel","renderHoverLabels","inHierarchyMode","diamond","initialDate","marginLeft","ri","wpTimeline","cellRenderers","getCellsFor","synchronizeCells","refreshSingleCell","renderInfoFor","currentlyActive","workPackageIdOrder","rowClassIdentifier","wpTableComponent","_viewParameters","cellsRenderer","selectionParams","refreshRequest","collapsedGroupsCellsMap","orderedRows","wpsWithGroupHeaderCell","tableWorkPackage","shouldBeShownInCollapsedGroupHeaders","outerContainer","registerTimeline","commonPipes","timelineState","setupManageCollapsedGroupHeaderCells","isAutoZoom","applyAutoZoomLevel","calculateViewParams","refreshAllCells","refreshCollapsedGroupsHeaderCells","currentWidth","scrollWidth","activateSelectionMode","getParentScrollContainer","nonVisibleDaysLeft","viewPortRight","daysUntilViewPortEnds","unbind","resetSelectionMode","currentParams","newParams","getWorkPackagesToCalculateTimelineWidthFrom","subtract","dayCountForMarginLeft","visibleDays","isSame","getFirstDayInViewport","getLastDayInViewport","workPackagesToCalculateWidthFrom","daysSpan","timelineWidthInPx","manageCollapsedGroupHeaderCells","groupsCollapseConfig","tableWorkPackages","refreshAllGroupHeaderCells","collapsedGroupsChange","collapsedGroupsChangeArray","groupsToUpdate","shouldManageCollapsedGroupHeaderCells","createCollapsedGroupHeaderCells","removeCollapsedGroupHeaderCells","keyGroupType","changedGroupId","changedGroupType","changedGroupWpsWithHeaderCellsIds","buildCellsAndRenderOnRow","collapsedGroupKey","wpTypeFunction","workPackagesWithGroupHeaderCell","confirmDialog","confirmDelete","showAnchorRight","isSortable","setAsSingleSortCriteria","addSortCriteria","isGroupable","isCurrentlyGroupedBy","setEnabled","setBy","isFirst","focusColumn","removeColumn","initialTab","wpTimelineService","workPackageTimelineTableController","onRefreshRequested","innerHeader","renderLabels","activeZoomLevel","renderLabelsDays","renderLabelsWeeks","renderLabelsMonths","renderLabelsQuarters","renderLabelsYears","renderTimeSlices","quarter_number","marginTop","cellCallback","addLabelCell","workPackagePrefix","TimelineRelationElement","belongsToId","timelineGlobalElementCssClassname","newSegment","yPosition","color","workPackagesWithRelations","setupRelationSubscription","wps","relationsForWorkPackage","renderWorkPackagesRelations","workPackageWithRelation","removeRelationElementsForWorkPackage","renderElement","removeAllVisibleElements","renderElements","wpIdsWithRelations","involved","startCells","workPackageCells","endCells","startCell","idxFrom","workPackageIndex","endCell","idxTo","renderRelation","rowFrom","rowTo","canConnectRelations","startX","targetX","directionY","directionX","paddingRight","startLineWith","lastX","timelineStaticElementCssClassname","finishElement","offsetToday","dayProgress","checkForWeekendHighlight","day","gridContainer","paddingTop","WorkPackageWatcherEntryComponent","panelCtrl","deleting","watcher","removeWatcher","wpTableSums","isHidden","groupSumsBuilder","totalSums","factoryFor","relatedTo","refreshTable","getRelationTypeFromQuery","buildQueryProps","toId","configureTable","openTableConfigurationModal","toggleHierarchy","openMenu","sortColumn","onReadyWithAvailable","latestSortElement","headerColumn","currentSortDirection","setActiveColumnClass","sortable","directionClass","getDirectionClass","isHierarchyColumn","columnType","columnName","hierarchyIcon","isHierarchyDisabled","setHierarchyIcon","toggleState","disable","bootstrapAttributeGroups","bootstrapAttributeGroupsCalled","hookService","WorkPackagesListChecksumService","newQueryChecksum","getNewChecksum","routePromise","isUninitialized","isIdDifferent","maintainUrlQueryState","isChecksumDifferent","isOutdated","checksum","visibleChecksum","otherId","otherChecksum","hasCurrentQueryID","hasCurrentChecksum","idChanged","checksumChanged","visibleChecksumChanged","pick","close_menu","install_menu_logic","drop_down","open_menu","WorkPackageViewHandlerToken","WorkPackageViewHandlerRegistry","factory","eventScope","EVENT","handleEvent","WorkPackageCardViewService","renderedCards","CardClickHandler","handleWorkPackage","wpCardView","CardDblClickHandler","ExternalQueryConfigurationComponent","openConfigurationModal","buildUrlParams","BoardService","boardActions","boardsList","currentBoard$","unnamed_board","action_board","unnamed_list","loadAllPromise","allInScope","reorderWidgets","boardName","addFreeQuery","addInitialColumnsForAction","WorkPackageTypeStatusComponent","v3ErrorIdentifierMultipleErrors","ErrorResource","isMultiErrorMessage","extractMultiError","perAttribute","OpenprojectEditorModule","WorkPackageViewFocusService","focusAfterRender","setFocusAfterRender","withLoadingIndicator","delayStopTime","delayedStop","stop","withDelayedLoadingIndicator","LoadingIndicator","indicatorTemplate","stopper","LoadingIndicatorService","getIndicatorAt","DebouncedEventEmitter","takeUntil$","emitter","debouncer","generatorOrNext","WpRelationInlineCreateService","removeRelation","toState","fromState","fromParams","WorkPackagesBaseComponent","onClickOrEnter","ClickOrEnterHandler","processEvent","WorkPackageSubjectComponent","uiRouterGlobals","uniqueElementIdentifier","JobStatusModal","redirect","redirect_errors","redirect_link","download_starts","click_to_download","downloadHref","listenOnJobStatus","performRequest","continuedStatus","onResponse","handleRedirect","handleDownload","download","statusIcon","iconForStatus","redirectionUrl","downloadLink","jobUrl","TimeEntryFormComponent","showWorkPackageField","modifiedEntry","spentOn","wpRequired","workPackageSelected","setCustomFields","entries","keySchema","signalModifiedEntry","paginationService","getCachedPerPage","updateFromObject","OpenProjectFileUploadService","upload","uploadUrl","staticDownloadLocation","uploadSingle","whenFinished","formData","FormData","metadata","reportProgress","promises","Response","PartitionedQuerySpacePageComponent","showToolbar","toolbarButtonComponents","filterAllowed","currentPartition","filterContainerDefinition","showToolbarSaveButton","setPartition","removeTransitionSubscription","isFirstLoad","setupInformationLoadedListener","queryParamListener","unRegisterTitleListener","updateTitle","onQueryUpdated","removeQueryChangeListener","updateTitleName","toolbarDisabled","wpStaticQueries","getStaticName","titleEditingEnabled","shouldUpdateHtmlTitle","visibly","loadFirstPage","getPaginationInfo","additionalLoadingTime","loadCurrentQueryFromParams","changeChangesFromTitle","WpCustomActionComponent","wpSchemaCacheService","savedWp","fetchAction","customActions","showProject","groupedFields","resourceContextChange","switchTo","infoRow","createdBy","lastUpdatedOn","firstTimeFocused","contextFrom","projectWorkPackagePath","apiv3Path","inProjectContext","getFields","attributeGroups","_attributeGroups","rebuildGroupedFields","members","queryInNew","projectname","groupId","getAttributesGroupId","isolated","fieldNames","descriptors","getDateField","displayField","spanAll","schemaHref","projectHref","baseSchema","overflowingIdentifier","DateDisplayField","showSchedulingMode","schedulingIcon","canOverdue","daysFromToday","isClosed","APIv3FormResource","registerRequestForConfirmation","getPluginContext","services","passwordConfirmationModal","modals","passwordConfirmation","password_confirmation","registerListener","createFieldsetToggleStateLabel","legend","labelClass","toggleLabel","legendLink","setFieldsetToggleState","fieldset","getFieldset","setupToggableFieldsets","fieldsets","contentArea","slideToggle","toggleFieldset","setupServerResponse","upToggle","initMainMenuExpandStatus","firstErrorSpan","focusFirstErroneousField","activateFlashNotice","activateFlashError","ajaxComplete","ajaxSend","csrf_meta_tag","token","setRequestHeader","ajaxStop","addClickEventToAllErrorMessages","resizeTo","error_focus","input_focus","substr","activateFlash","triggerTour","allowInput","augmentedDatePicker","linkElement","hashPos","performAnchorHijacking","pageIsSubmitted","marginBottom","dangerZoneVerification","expectedValue","pageWasEdited","serialize","refreshOnFormChanges","prevScrollPos","currentScrollPos","scrollHeaderOnMobile","URL","demoProjectsAvailable","currentTourPart","sessionStorage","tourCancelled","searchParams","setItem","once","detectOnboardingTour","wasDisabled","checked","vendor","option","langSelectSwitchData","settingName","newLang","textArea","storedValue","delivery_method","isNone","wasChecked","removeAttr","listenToSettingChanges","func","previewColor","keyup","actualValue","GlobalHelpers","boxes","all_checked","helpers","edition","localStorage","BrowserDetector","hasBodyClass","helpTexts","helpText","editText","attributeHelpTextSelector","attributeHelpTexts","exists","open_dialog","helpTextId","attributeScope","additionalLabel","requireById","checkedClassName","UiStateLinkBuilder","webpackEmptyAsyncContext","stack","timeoutAfter","nextValue","autoHidePopups","createNotification","createAttachmentUploadNotification","QueryFilterResource","SchemaCacheService","stateKey","getSchemaHref","hrefs","OpTitleService","getTitle","titleParts","setTitle","activeFieldContainerClassName","activeFieldClassName","EditForm","errorsPerAttribute","renderField","showEditingBlockedError","requireVisible","activateWhenNeeded","openFields","handleSubmissionErrors","resetChange","handleErroneousAttributes","erroneousAttributes","getInvolvedAttributes","getMessagesPerAttribute","setErrorsForFields","erroneousFields","focusOnFirstError","loadFormAndCheck","activateField","prototype","padding","number","toFixed","precision","decimalAdjust","isFunction","isSet","isString","isNumber","isBoolean","exp","NaN","lazyEvaluate","dest","DATE","day_names","abbr_day_names","month_names","abbr_month_names","meridian","NUMBER_FORMAT","delimiter","strip_insignificant_zeros","CURRENCY_FORMAT","sign_first","PERCENTAGE_FORMAT","SIZE_UNITS","DEFAULT_OPTIONS","defaultLocale","defaultSeparator","fallbacks","translations","missingBehaviour","missingTranslationPrefix","initializeOptions","locales","localeParts","firstFallback","secondFallback","nullableFallbackLocale","pluralization","currentLocale","scopes","fullScope","getFullScope","pluralizationLookupWithoutFallback","pluralizerKey","pluralizerKeys","pluralizer","pluralizationLookup","am","pm","prepareOptions","arguments","createTranslationOptions","translationOptions","translate","translation","optionsWithoutDefault","translationOption","interpolate","pluralize","missingTranslation","regex","nullPlaceholder","missingPlaceholder","s","p1","p2","toNumber","formattedNumber","negative","buffer","sign","toCurrency","localize","toPercentage","localizedValue","toTime","convertedDate","fraction","UTC","setTime","$1","$2","$3","$6","$4","$5","strftime","meridianOptions","getTime","weekDay","getDay","getDate","year","getFullYear","month","getMonth","getHours","hour12","secs","getSeconds","mins","getMinutes","getTimezoneOffset","absOffsetHours","absOffsetMinutes","timezoneoffset","dateString","toHumanSize","kb","iterations","obj1","obj2","p","WorkPackagesGridComponent","wpTableHighlight","wpList","showResizer","resizerClass","resizerStorageKey","gridOrientation","WorkPackageFilterContainerComponent","visible$","isAvailable","replaceIfComplete","OpDatePickerComponent","initializeDatepicker","datePickerInstance","_event","inputIsValidDate","relatedTarget","calendarContainer","inputElement","dateInput","initialValue","selectedDates","dateStr","onKeyDown","parseISODate","toDate","openOnClick","onInputChange","StatusResource","WorkPackageViewSelectionService","selectedWorkPackageIds","activeRowIndex","_emptyState","wpState","selectionCount","renderedElements","selectAll","WpResizerDirective","toggleService","resizeStyle","moving","resizingElement","elementClass","localStorageValue","parseLocalStorageValue","toggleFullscreenColumns","resizer","applyColumnLayout","actualElementWidth","resizeEvent","dispatchEvent","manageErrorClass","deltas","relative","newWidth","toggleColumns","checkWidth","fullScreenLeftView","shouldBePresent","resizeEnd","resizeStart","resizeMove","WpChildrenInlineCreateService","wpRelationsHierarchyService","addExistingChildWp","canAddChild","OpenProjectDirectFileUploadService","getDirectUploadFormFrom","uploadToExternal","finishUpload","completeUpload","fileSize","contentType","form_fields","WorkPackageFilterValues","excluded","handlers","applyFirstValue","setToNull","filterAlreadyApplied","mapFilterToAttribute","setValueFor","findSpecialValue","isLoggedIn","fromSelfLink","BannersService","_banners","bannersVisible","bannersNotVisible","callMaybe","WorkPackageListViewComponent","wpViewFilters","showTableView","tableInformationLoaded","showResultOverlay$","incomplete$","wpTableConfiguration","updateViewRepresentation","selectedRow","selectedCard","previousSibling","block","valueFromQuery","openInFullView","handleWorkPackageClicked","WorkPackageAutocompleterComponent","changeModel","opened","closed","keyPressed","WorkPackageLinkedResourceCache","cacheDurationInSeconds","isCached","OpQueryConfigurationLocalsToken","WorkPackageCardViewComponent","wpViewOrder","cardDragDrop","cardsRemovable","showEmptyResultsBox","isResultEmpty","addNewCard","inReference","referenceOutputs","setReferenceMode","onReferenced","updateRenderedCardsValues","registerDragAndDrop","registry","onCardSaved","CollectionResource","WpRelationInlineAddExistingComponent","buildQueryFilters","abort","selectedWpId","newRelationId","err","addExisting","relationTypes","buildV3GetFilterIdFromFilter","buildV3GetFilters","HalResourceSortingService","halType","sortingProperty","States","posts","QueryAvailableDataStates","GlobalStateChanges","camelCase","backlogsPageComponentSelector","BacklogsPageComponent","WorkPackageBaseResource","truncateSubject","truncate","otherWorkPackage","resourceNames","linked","wpCacheService","WorkPackageResource","TimeEntryWorkPackageAutocompleterComponent","modeSwitch","loading","errorNotificationHandler","DebouncedRequestSwitchmap","requestHandler","errorHandler","preFilterNull","debounceMs","loading$","lastResult","until","SimpleResourceCollection","SimpleResource","attachmentsSelector","AttachmentsComponent","allowUploading","ifcModels","ifc_models","_error","projectData","models","viewerContent","modelsLoaded","shown_models","viewerConfigs","saoEnabled","_projectId","modelId","attachmentId","metadata_attachment_ids","utils","loadJSON","attachmentContentPath","xkt_attachment_ids","loadArraybuffer","shouldShowViewer","viewerVisible$","BehaviorSubject","XeokitViewerModule","server","viewerUI","BIMViewer","alert","objectName","objectType","objectId","loadProject","viewer","_viewer","setKeyboardEnabled","saveBCFViewpoint","spacesVisible","bitmaps","routeWithViewer","viewpointsService","getViewPoint$","loadBCFViewpoint","bimDetailsPath","TimezoneService","setupLocale","datetime","isTimezoneSet","local","tz","getTimeFormat","utc","getDateFormat","today","datetimeString","durationString","asHours","toHours","dateTime","dateFormatPresent","timeFormatPresent","timeFormat","OpCkeditorComponent","Notifications","ckEditorSetup","ckEditorType","onInitialized","onContentChange","onInitializationFailed","allowManualMode","manualMode","errorTitle","debouncedEmitter","getTransformedContent","leading","_content","ckEditorInstance","notificationOnError","getRawData","newVal","initializeEditor","editorPromise","opCkeditorReplacementContainer","model","enableManualMode","disableManualMode","WorkPackageStaticQueriesService","CurrentUserService","assignee","created_at","updated_at","gantt","latest_activity","created_by_me","assigned_to_me","recently_created","all_open","summary","static_link","pp","pa","matched","HalResourceService","httpError","expected","retrieved","allResults","toEprops","getEmptyResource","getResourceClassOfType","fromType","toType","getResourceClassOfAttribute","defaultClass","typeConfig","deflated","eprops","btoa","WorkPackageNewFullViewComponent","successState","EditFieldHandler","_onSubmitHandlers","_onBeforeSubmitHandlers","AccessibleClickDirective","stopEventPropagation","skipEventModifiers","isMatchingEvent","skipOnModifier","KeyboardEvent","MouseEvent","DEFAULT_PAGINATION_OPTIONS","PaginationService","loadPaginationOptions","initialPageOptions","localStoragePerPage","initialLength","paginationOptions","perPageOptions","maxVisiblePageOptions","optionsTruncationSize","WorkPackageFiltersService","WorkPackagesListInvalidQueryService","restoreFilters","restoreColumns","restoreSortBy","restoreGroupBy","restoreOtherProperties","querySchema","filterInstanceSchema","recreatedFilter","stubQuery","sortBys","opIconElement","ViewerBridgeService","hideForSinglePageResults","showPerPage","showPageSelections","updateResults","label_previous","label_next","per_page","no_other_page","currentRange","pageNumbers","postPageNumbers","prePageNumbers","totalEntries","updateCurrentRangeLabel","updatePageNumbers","setPerPage","showPage","onUpdatedPage","totalItems","lowerBound","getLowerPageBound","upperBound","getUpperPageBound","maxVisible","getMaxVisiblePageOptions","truncSize","getOptionsTruncationSize","currentPage","startingDiff","truncatePageNums","perform","disectFrom","disectLength","truncateFrom","truncationSize","truncatedNums","wpPagination","infoText","paginationInfoText","pageNumber","ActivityEntryInfo","forceReverse","orderedIndex","activityDate","dateOfPrevious","commentsSortedInDescendingOrder","aggregated","sortedActivityList","sorted","ViewpointsService","viewpointHref","bcfApi","getViewPointResource","wpProjectId","topicUUID$","setBcfTopic$","viewpoint$","viewerBridge","getViewpoint$","topicUUID","topicHref","bcfTopic","createBcfTopic$","wpPayload","convertBCF","guid","VersionAutocompleterComponent","onCreate","canCreateNewActionElements","createAllowed","createNewVersion","getVersionPayload","closeSelect","definingProject","rowGroupClassName","collapsedRowClass","APIv3ResourcePath","APIv3GettableResource","APIv3ResourceCollection","ExternalQueryConfigurationService","_portalHostElement","_bodyPortalHost","externalQueryConfigurationComponent","hasAttached","validity","valid","parsedValue","SelectAutocompleterRegisterService","_fields","assignment","valuesLoaded","newElement","onKeydown","handleUserKeydown","onAfterViewInit","_autocompleterComponent","requiredPlaceholder","valuesLoadingPromise","initialValueLoading","loadValues","selectAutocompleterRegister","getAutocompleterOfAttribute","overflowingSelector","openDirectly","_syncUrlParamsOnChangeIfNeeded","editFormComponent","valueOptions","availableValues","sortValues","addEmptyOption","mapAllowedValue","loadValuesFromBackend","cacheKey","cacheValue","fetchAllowedValueQuery","allowedValuesFilter","addValue","selectedOption","emptyOption","getEmptyOption","isRequired","registerOnBeforeSubmit","newType","Optional","currentValueInvalid","requestFocus","nullOption","openAutocompleteSelectField","findValueOption","_selectedOption","adjustPosition","valueOption","sortValuesByName","nameA","nameB","buildSelectedOption","checkCurrentValueValidity","filterParams","prefix","onValueSelected","initializationError","isPreview","previewHtml","editorType","getEditorTypeFor","registerOnSubmit","getCurrentValue","attachmentLabel","rawValue","previewContext","isBusy","projectStatusCodeCssClass","ensureDefaultCode","projectStatusI18n","_availableStatusCodes","currentStatusCode","availableStatuses","recentWorkPackageIds","timeEntry","sortValuesByRecentIds","DatePickerModalHelper","setHours","firstDate","secondDate","parsedDate1","parsedDate2","currentlyActivatedDateField","datePicker","setDatepickerRestrictions","enforceDate","currentMonth","currentYear","setDates","redraw","disableFunction","isStateOfCurrentActivatedField","monthContainer","highlightRangeInSingleMonth","selectedElements","selectRangeFromUntil","datepickerShowsDate","firstDay","datepickerIsInDateRange","selectedElement","toDateString","firstDayOfMonthElement","firstDayOfMonth","nextUntil","datepickerHelper","manualScheduling","endDate","isParent","isSwitchedFromManualToAutomatic","singleDate","isWritable","setCurrentActivatedField","initialActivatedField","isSchedulable","showDateSelection","onDataChange","removeDateSelection","isSavable","mappedDate","enforceManualChangesToDatepicker","validDate","setRangeClasses","showMonths","inline","handleDatePickerChange","onMonthChange","onYearChange","toggleField","setRangeClassesAndToggleActiveField","setDateAndToggleActiveField","areDatesEqual","otherDateIndex","overwriteDatePickerWithNewDates","sortDates","newDate","forceDatePickerUpdate","toggleCurrentActivatedField","output","changeSchedulingMode","text_no_start_date","text_no_due_date","showDatePickerModal","currentStartDate","currentDueDate","toLocaleString","useGrouping","maximumFractionDigits","unescape","UNESCAPED_EXPRESSION","ESCAPED_EXPRESSION","derivedText","formattedDuration","derivedPropertyName","derivedValue","actual","renderActual","derived","renderDerived","derivedValueString","actualPresent","valueEmpty","derivedEmpty","translatedValue","linkTitle","logTime","wpID","projectTimeEntriesPath","appendTimelogLink","timelogElement","showTimelogWidget","addHighlight","hlClass","names","divContainer","renderAbridgedValues","dots","uiStateBuilder","linkToShow","bulb","pulldown","innerText","OpenprojectFieldsModule","editFieldService","selectAutocompleterRegisterService","addSpecificFieldType","FocusDirective","SchemaDependencyResource","uiStatebuilder","detailsLink","linkToDetails","contextMenu","built","buildElement","FirstRouteService","WorkPackageFilterButtonComponent","iconClass","setupObserver","currentlyVisibleFilters","performAction","UrlParamsHelperService","paramsData","encodeColumns","encodeSums","encodeTimelineVisible","encodeHighlightingMode","encodeHighlightedAttributes","hi","showHierarchies","g","encodeSortBy","encodeFilters","dr","hl","hla","queryFilterValueToParam","tv","tll","tzl","updateJson","getPerPage","showSums","urlFilter","vs","filterData","contextual","buildV3GetColumnsFromQueryResource","buildV3GetFiltersAsJson","buildV3GetSortByFromQuery","idFromHref","replacements","buildV3GetOperatorIdFromFilter","buildV3GetValuesFromFilter","filterHash","sortByIds","substring","BackRoutingService","route","preferListOverSplit","goToOtherState","backRoute","currentDetailsSubState","isDetailsState","goBackToDetailsState","goBackNotToDetailsState","goBackToPreviousState","paramsFromCopy","_backRoute","TableDragActionService","shadowElement","backToDefault","determineParent","relationHierarchyService","nextElementSibling","droppedIntoGroup","relationRoot","findRelationRowRoot","previousWpId","isHiearchyRoot","loadParentOfWP","inGroup","isRoot","skipDroppedIntoGroup","elementGroups","previousGroups","nextGroups","isLastElementOfGroup","elementAlreadyBelongsToGroup","elementGroup","groupedAttribute","groupedValue","getValueForGroup","groupHeader","applies","ImageHelpers","imagePath","tdClassName","editCellContainer","CellBuilder","displayElement","whenDebugging","debugLog","timeOutput","msg","WorkPackageNotificationService","addWorkPackageFullscreenLink","QUERY_SORT_BY_ASC","QUERY_SORT_BY_DESC","showEditForm","parentHeadline","childrenHeadline","canModifyHierarchy","canAddRelation","childrenQueryProps","showRelationInfo","userInputs","newRelationText","showDescriptionEditForm","showRelationTypesForm","fieldController","removeButton","description_label","toggleDescription","updateRelation","relatedBy","availableRelationTypes","LOCALIZED_RELATION_TYPES","normalizedType","textarea","relationDescriptionTextarea","textlen","cancelDescriptionEdit","savedRelation","groupByWorkPackageType","updateRelationType","onToggleGroupBy","groupByType","groupByRelation","toggleElement","showRelationsCreateForm","DEFAULT","addNewRelation","createCommonRelation","toggleRelationsCreateForm","relationGroups","relationGroupKeys","relationsPresent","relations_header","currentRelations","loadedRelations","observablesToGetZipped","zip","buildRelationGroups","stateValues","relatedWpIds","relatedWpId","getRelatedWorkPackageId","getRelatedWorkPackages","relatedWorkPackages","WorkPackageViewContextMenu","selectedWorkPackages","getSelectedWorkPackages","WorkPackageContextMenuHelper","deleteSelectedWorkPackages","editSelectedWorkPackages","copySelectedWorkPackages","addNewChildWp","logTimeForSelectedWorkPackage","screenfull","zenModeComponentSelector","ZenModeButtonComponent","activateLabel","deactivateLabel","enabled","onchange","isFullscreen","deactivateZenMode","inZenMode","exit","activateZenMode","InjectField","flags","Reflect","getMetadata","_val","WorkPackageSingleViewBase","tabs","subjectWithType","showStaticPagePath","updateFocusAnchorLabel","tabLabel","focusAnchorLabel","BoardListsService","filterJson","buildQueryRequest","freeBoardQueryFilter","addQuery","public","manualSort","CurrentProjectService","detect","getCurrent","projectName","OpUnlinkTableAction","WpTableConfigurationModalPrependToken","WpTableConfigurationModalComponent","prependModalComponent","columnsLabel","selectedColumns","multiSelectLabel","applyButton","upsaleRelationColumns","upsaleRelationColumnsLink","selectedColumnMap","wpTableConfigurationService","tabPortalHost","tabContentOutlet","activeComponents","saveChanges","WorkPackageChildrenQueryComponent","addExistingChildEnabled","CreateAutocompleterComponent","finishedLoading","hideSelected","add_new_action","_openDirectly","openSelect","WpTableConfigurationDisplaySettingsTab","displayMode","availableGroups","displaySums","choose_mode","label_group_by","display_sums","display_sums_hint","display_mode","grouped","hierarchy_hint","updateGroup","dragula","_selected","updateAvailableOptions","columnsGroup","createGroup","drag","drop","autoscroll","drake","dragging","clearModel","WpTableConfigurationColumnsTab","availableColumnsOptions","column2Like","availableColumns","availableColumnsMap","keyBy","columnsHelp","upsaleCheckOutLink","setColumnsById","updateSelected","WpTableConfigurationFiltersTab","SortModalObject","sort_criteria_1","sort_criteria_2","sort_criteria_3","sorting_mode","automatic","manually","availableDirections","allColumns","sortationObjects","emptyColumn","sortingMode","sortElements","manualSortColumn","getMatchingSort","getManualSortingOption","updateSortingMode","updateUsedColumns","fillUpSortElements","usedColumns","availableZoomLevels","display_timelines","display_timelines_hint","zoom","weeks","quarters","years","auto","availableLabels","allPropertyColumns","localeCompare","WpTableConfigurationHighlightingTab","entireRowMode","lastEntireRowAttribute","availableInlineHighlightedAttributes","availableRowHighlightedAttributes","highlighting_mode","inline_all_attributes","entire_row_by","upsaleAttributeHighlighting","availableHighlightedAttributes","setSelectedValues","updateMode","currentValues","updateHighlightingAttributes","FocusWithinDirective","focusedObservable","DragAndDropService","escapeListener","containers","member","setupAutoscroll","initializeDrake","setOuterScrollContainer","getMember","invalid","copy","revertOnSpill","removeOnSpill","mirrorContainer","ignoreInputTextSelection","DynamicBootstrapModule","OpenprojectCommonModule","routerState","addContext","setUser","email","mail","setTag","setExtra","bootstrapModule","withComponents","userAvatarSelector","UserAvatarComponent","Apiv3GridForm","RelationStateGroup","WorkPackageRelationsService","relationsStateValue","loadInvolved","accumulateRelationsFromInvolved","removeFromStates","insertIntoStates","relevant","isInvolved","GridBaseResource","widgetResource","GridResource","ResizerComponent","resizing","customHandler","cursorClass","buttons","oldX","pageX","touches","oldY","startY","pageY","newX","newY","setResizeCursor","bindEventListener","setAutoCursor","mouseMoveHandler","onMouseMove","mouseUpHandler","onMouseUp","origin","absolute","userMeta","SchemaProxy","proxyMethod","__","argumentsList","WorkPackageCommentComponent","editTitle","cancelTitle","canAddComment","showAbove","quote","commentContainer","scrollToBottom","wpDetails","createComment","scrollableContainer","scrollHeight","bcfPathHelper","snapshotPath","BcfDetectorService","authorizationMap","extension","authorized$","bcfAuthorization","bcf","add_viewpoint","show_viewpoint","delete_viewpoint","text_are_you_sure","notice_successful_create","notice_successful_delete","galleryOptions","thumbnailsColumns","thumbnailsAutoHide","thumbnailSize","imageAnimation","previewAnimation","previewCloseOnEsc","previewKeyboardNavigation","imageSize","imageArrowsAutoHide","thumbnailsMargin","thumbnailMargin","previewDownload","previewCloseOnClick","arrowPrevIcon","arrowNextIcon","closeIcon","downloadIcon","thumbnailActions","breakpoint","imagePercent","thumbnailsPercent","galleryImages","viewAllowed","viewerVisible","observeChanges","refreshViewpoints","isAllowedTo","loadViewpointFromRoute","snapshotURL","setViewpointsOnGallery","showViewpoint","deleteViewPoint$","gallery","saveViewpoint$","showIndex","selectViewpointInGallery","titleText","deleteViewpoint","setThumbnailProperties","small","medium","big","viewpointCount","dynamicThumbnailHeight","galleryViewpoints","observeCreation","observables","viewPointItem","forkJoin","newViewpoint","snapshot","snapshot_data","revitMessageReceivedSource","trackingIdNumber","revitMessageReceived$","RevitBridge","hookUpRevitListener","trackingId","newTrackingId","sendMessageToRevit","messageType","viewpointJson","messagePayload","snapshot_type","jsonPayload","sendMessageToOpenProject","messageString","bootstrapCalled","isBimEdition","navigator","userAgent","I18nService","_i18n","translateId","parameters","WorkPackageViewHierarchies","setState","initialState","CausedUpdatesService","EnterpriseBannerComponent","leftMargin","enterpriseFeature","opReferrer","AbstractWorkPackageButtonComponent","labelKey","textKey","activationPrefix","deactivationPrefix","createdEntry","reloadWorkPackageAndClose","setModifiedEntry","createNewTimeEntry","OpenprojectAttachmentsModule","indicatorCollapsedClass","additionalHierarchyRowClassName","SingleHierarchyRowBuilder","leaf","appendHierarchyIndicator","hierarchyLevel","hierarchyElement","buildHierarchyIndicator","hierarchyIndicator","indicatorWidth","indentation","TimeEntryBaseModal","areYouSure","formInFlight","UserResource","active_user_statuses","WorkPackageWatchersTabComponent","allowedToView","allowedToAdd","allowedToRemove","watching","loadingError","autocomplete","loadCurrentWatchers","availableWatchersPath","addWatcher","loadingPromise","$prepare","user_id","WorkPackageCreateComponent","wpViewFocus","cancelState","button_settings","closeEditFormWhenNewWorkPackageSaved","showForm","createdWorkPackage","newWorkPackage","loginPath","back_url","field_description","confirm_button","password","passwordValuePresent","passwordConfirmationField","modalClassName","modalBody","sanitizer","string","sanitize","HTML","_knownHookNames","externalQueryConfiguration","externalRelationQueryConfiguration","htmlSanitizeService","ckEditorPreview","pathHelperService","dynamicContent","run","BudgetResource","CostSubformAugmentService","templateEl","template","PlannedCostsFormAugment","objId","objName","makeEditable","edit_and_focus","currency","getCurrency","insertAfter","CostBudgetSubformAugmentService","row_identifier","buildRefreshRequest","HTMLInputElement","element_id","fixed_date","extendFieldType","listen","initializeCostsPlugin","loadIfNecessary","showCosts","renderCostAsLink","renderCostAsText","costType","spentUnits","addSeparator","parseFloat","workPackageSingleContextMenu","workPackageTableContextMenu","resizeImage","maxSize","canvas","ctx","getContext","drawImage","dataUrl","toDataURL","dataURItoBlob","dataURI","bytes","atob","mime","ia","Uint8Array","Blob","resizeFile","reader","FileReader","readerEvent","readAsDataURL","fileInvalid","label_choose_avatar","upload_instructions","error_too_large","wrong_file_format","button_update","uploading","_evt","avatarFilePicker","dataURL","blob","avatarFile","avatarPreviewUrl","progress","onFilePickerChanged","uploadAvatar","DocumentResource","LinkedPluginsModule","GridArea","storedGuid","newGuid","s4","otherArea","rowOverlaps","columnOverlaps","sink","isRow","numColumns","numRows","mousedOverArea","$mousedOverArea","helpMode","rowCount","buildAreas","area","unusedRows","widgetAreas","removeRow","unusedColumns","gridAreas","buildGridAreas","gridGaps","buildGridGaps","gridAreaIds","buildGridAreaIds","buildGridWidgetAreas","persist","writeAreaChangesToWidgets","saveGrid","payloadWidget","w","widgetResources","isSingleCell","scrollIntoViewIfNeeded","updatedGrid","assignAreasWidget","newGrid","takenIds","newWidget","buildGridAreasRow","buildGridGapRow","writeAreaChangeToWidget","excludeRow","movedWidgets","rowWidgets","moveSubsequentRowWidgets","excludeColumn","columnWidgets","moveSubsequentColumnWidgets","ignoredArea","gridResource","isGap","removedWidget","cleanupUnusedAreas","rebuildAndPersist","subsequentWidget","layout","onRenamed","renamed","GridRemoveWidgetService","removeWidget","menuItemList","removeItem","resizeSubject","static","alreadyLoaded","ucCalendar","getApi","addTooltip","toWPFullView","resizeObserver","ResizeObserver","updateSize","setupWorkPackagesListener","initializeCalendar","fetchInfo","successCallback","failureCallback","updateTimeframe","calendarOptions","fixedWeekCount","calendarEventsFunction","plugins","initialView","calendarHeight","headerToolbar","buildHeader","filtersEmpty","defaultQueryProps","datesIntervalFilter","tooltip","tooltipContentString","extendedProps","track","removeTooltip","history","pushState","inherit","heightElement","topOfCalendar","topOfHeightElement","calendarElement","calendarDate","calendarUnit","lower","changeView","setCalendarsDate","refetchEvents","warnOnTooManyResults","mapToCalendarEvents","eventDate","exclusiveEnd","allDay","tooManyResultsText","MAX_DISPLAYED","props","sanitizedValue","toStringMethod","renameWidget","TimeEntriesCurrentUserConfigurationModalService","daysCheckedValues","localeWeekDays","localeOffset","localeData","offsetToApply","offsetCheckedValues","orderedDaysCheckedValues","dayCheckedValue","originalIndex","getOriginalIndex","arrayLength","configuredDays","localeDayData","validDays","timeEntriesCurrentUserConfigurationModalService","displayedDays","daysOriginalCheckedValues","getOrderedDaysData","checkedValuesInOriginalOrder","getCheckedValuesInOriginalOrder","onConfigured","configureItem","destroyedEntry","createChangeset","TIME_ENTRY_CLASS_NAME","ADD_ENTRY_CLASS_NAME","ADD_ENTRY_PROHIBITED_CLASS_NAME","timeEntryEdit","timeEntryCreate","minHour","maxHour","labelIntervalHours","scaleRatio","memoizedCreateAllowed","hiddenDays","contentHeight","slotEventOverlap","slotLabelInterval","slotLabelFormat","allDaySlot","displayEventTime","slotMinTime","slotMaxTime","eventOverlap","stillEvent","setHiddenDays","alterEventEntry","beforeEventRemove","dispatchEventClick","moveEvent","fetchTimeEntries","buildEntries","memoizedTimeEntries","dmFilters","createTimeEntry","setRatio","buildTimeEntryEntries","buildAuxEntries","dateSums","calculateDateSums","maxHours","oldRatio","smallerSuitableRatio","hoursDistribution","entryName","calendarEntries","m","sumEntry","addEntry","startEditable","backgroundColor","borderColor","rendering","formatNumber","editEvent","addEvent","modificationAction","updateEventSet","revert","foundIndex","appendAddIcon","appendSum","prependDuration","appendFadeout","addIcon","fadeout","hslaStart","toHsla","hslaEnd","workPackageName","divisor","cdr","updateConfiguration","updateEntries","GridWidgetsService","Hook","registeredWidgets","registration","OpenprojectTimeEntriesModule","CALENDAR_ROUTES","OpenprojectCalendarModule","forChild","entriesLoaded","documentsUrl","orders","project_id","addedBy","newsAuthorName","age","newsCreated","authorLink","newsAuthorPath","newsDmParams","setupNews","newsPath","myPageForm","WpGraphConfigurationSettingsTab","tabInner","WpGraphConfigurationFiltersTab","WpGraphConfiguration","chartOptions","chartType","is_public","_forms","persistChanges","reloadQueries","saveQuery","loadQueries","createInitial","queryCreationParams","queryPromises","queryParam","formFor","_configuration","_formsPromise","loadForms","queryTabs","formPromises","graphConfiguration","configurationComponent","WorkPackageEmbeddedGraphComponent","chartHeight","chartLabels","chartData","datasets","setChartOptions","updateChartData","uniqLabels","array","labelCountMaps","countMap","setHeight","responsive","maintainAspectRatio","datalabels","align","chartTypeDefaults","scales","setChartAxesValues","inputChartOptions","changeableValuesAxis","stacked","ticks","constantValuesAxis","yAxes","xAxes","initializeConfiguration","loadQueriesInitially","persistAndReload","repaint","ensureQueryAndLoad","updateGraph","query$","skip","ensureFormAndSaveQuery","initializationProps","onResourceChanged","QuerySpacedTabComponent","wpGraphConfiguration","initializeQuerySpace","group_by","chart_type","currentChartType","initializeAvailableGroups","initializeAvailableChartType","availableChartTypes","project$","graphConfigurationService","displayModeSingle","availableGroupBy","additionalFilter","setQueryProps","graphParams","sortedDatasets","propsBoth","propsOpen","propsClosed","sortingArray","baseProps","subprojectId","displaySingle","embeddedGraphSingle","embeddedGraphMulti","initializeChangeset","valueChanged$","rawText","textValue","resourceSource","canAddAttachments","schemaSource","setupVariables","newText","currentRawText","clickedElementIsLinkWithinDisplayContainer","textEmpty","initial","memorizeRawText","reinitialize","memorizeCustomText","customText","htmlText","loadAndRender","loadProjectSchema","loadedEntry","timeEntryEditService","changedEntry","oldEntryIndex","newEntries","anEntry","sumsByDateSpent","sortedEntries","currentDate","PrincipalHelper","projectListParams","typeFromHref","principal","renderAvatar","renderUserAvatar","principalURL","groupPath","placeholderUserPath","OpPrincipalComponent","principalRenderer","avatarClasses","principalFromDataset","principalId","plural","principalType","principalName","viewAll","entriesByRoles","membersAddable","listMembersParams","partitionEntriesByRole","sortUsersByName","totalMembers","listAvailableProjectsParams","projectMembershipsPath","membership","roles","role","OpenprojectGridsModule","defaultColumns","assignedFilters","assignedProps","accountableFilters","accountableProps","createdFilters","createdProps","watchedFilters","watchedProps","registerWidgets","appBaseSelector","ApplicationBaseComponent","OPENPROJECT_ROUTES","abstract","squash","flash_message","dynamic","loadChildren","OpenprojectBoardsModule","OpenprojectIFCModelsModule","OpenprojectBacklogsModule","OpenprojectReportingModule","OpenProjectJobStatusModule","bodyClass","cssClass","updateMenuItem","menuItemTitle","stateService","wpBase","onEnter","onExit","router","start_onboarding_tour","paramsCopy","sync","profiler","MiniProfiler","pageTransition","pathname","pathWithSearch","setIfFirst","initializeUiRouterListeners","forRoot","useHash","uiRouter","urlService","strictMode","encode","decode","equals","stateName$","full_view","setWorkPackageScopeProperties","displayWatchButton","wpDisplayRepresentationService","setDisplayRepresentation","detectView","transitions","accessKey","activeState","listState","transitionListener","openListView","openDetailsView","minZoomLevel","maxZoomLevel","isMaxLevel","isMinLevel","zoomIn","zoomOut","zoomAuto","updateZoomWithDelta","toggleTimeline","enableAutozoom","showInMenu","visibleForOthers","showInMenuText","visibleForOthersText","isSave","isStarred","isPublic","updatePublic","updateStarred","queryName","save_as","label_name","queryNameField","savedQuery","saveQueryAs","focusAfterClose","queryUpdate","formUpdate","allowAction","cannot","allowQueryAction","create_new","allowFormAction","allowWorkPackageAction","WorkPackageSettingsButtonComponent","wpViewCollapsedGroups","setAllGroupsCollapseStateTo","WorkPackageFoldToggleButtonComponent","inputs","WORK_PACKAGES_ROUTES","OpenprojectWorkPackageRoutesModule","currentProjectService","_searchTerm","searchTerm$","_currentTab","currentTab$","_projectScope","projectScope$","tabs$","_resultsHidden","resultsHidden$","loadGonData","available_search_types","search_term","current_tab","project_scope","global_search","searchPath","projectScope","searchQueryParams","OpenprojectGlobalSearchModule","navigationEvents$","targetLi","mainItems","wrap","elementId","wrapperElement","wrapMainItem","recreateToggler","activeRoot","navigateUp","wrapInner","contents","parentURL","header","upLink","parentLink","before","emptyTypeGroup","Gon","externalRelationQuery","drag_to_activate","label_group","new_group","label_inactive","custom_field","add_group","add_table","inactives","no_filter_query","noFilterQuery","submitted","updateHiddenFields","groupsDrake","attributeDrake","activeGroups","inactiveAttributes","updateInactives","newGroup","editQuery","hiddenField","emptyGroup","resetToDefault","addGroupAndOpenQuery","onValueChange","editedName","showEEOnlyHint","leaveEditingMode","deleteGroup","removeAttribute","rename","edit_query","OpenprojectAdminModule","widgetsService","upsale_text","eligibleWidgets","chosenWidget","schemaWidgetIdentifiers","registered","GridMoveService","movedArea","ignoreArea","movedAreas","remainingAreas","moveOneDown","anchorAreas","movableAreas","moveSpecification","firstAreaToMove","toMoveArea","anchorArea","areaHeight","overlappingArea","movableArea","overlaps","referenceArea","setupMousedOverAreaSubscription","mousedOverAreaObserver","throttleTime","currentlyDragging","placeholderArea","updateArea","scrollPlaceholderIntoView","resetAreas","draggedArea","moveAreasOnDragging","dropArea","widgetArea","copyPositionButRestrict","isDragged","draggedHeight","offsetHeight","copyDimensionsTo","unchangedSize","GridResizeService","resizedArea","resizeTargets","sameRow","higherRow","fixedArea","targetIds","areaId","currentlyResizing","isResized","isAllowed","resize","inHelpMode","addLine","newArea","setMaxWidth","addRow","isColumn","existingArea","startColumnOverlaps","GridPageComponent","gridInitialization","addWidget","areas","i18nNamespace","html_title","gridScopePath","setHtmlTitle","GRID_PROVIDERS","uiWidgets","GRID_AREA_HEIGHT","GRID_GAP_DIMENSION","reg","saveWidgetChangeset","gridStyle","itemStyle","bypassSecurityTrustStyle","projectDashboardsPath","DASHBOARDS_ROUTES","OpenprojectDashboardsModule","rules","when","created_by","workPackageLink","previewModal","isMouseOverPreview","horizontalHover","verticalHover","OVERVIEW_ROUTES","OpenprojectOverviewModule","myPagePath","MY_PAGE_ROUTES","OpenprojectMyPageModule","accessKeys","quickSearch","projectSearch","help","moreMenu","KeyboardShortcutService","shortcuts","showHelpModal","globalAction","projectScoped","focusPrevItem","focusNextItem","keyName","clickLink","createEvent","bubbles","cancelable","fireEvent","keyboardShortcutsHelpPath","domLists","focusElements","firstLink","findListInPage","focusItemOffset","WorkPackageEmbeddedTableEntryComponent","getInputsFromData","EmbeddedTablesMacroComponent","highlightTextInline","setColorOptions","updateInput","selectedColorId","selectedColor","highlightingClass","globalSearchService","wpFilters","resultsHidden","tableConfiguration","newSearchTerm","newProjectScope","new_features_image","newFeatures","descriptionNewFeatures","learnAbout","i18nBase","isStandardEdition","translated","bypassSecurityTrustResourceUrl","i18nPrefix","list_styling_class","bcf_api_link","CustomDateActionAdminComponent","valueVisible","onKey","currentKey","currentFieldValue","operators","fieldValue","selectedOperator","visibleValue","toggleValueVisibility","updateDbValue","boardService","mainMenuService","trackById","currentProjectIdentifier","boards$","onActivate","focusBackArrow","loadAllBoards","selectedBoardId","GlobalSearchWorkPackagesEntryComponent","completed","progressBar","progressPercentage","Sent","UploadProgress","updateProgress","NotificationComponent","uploadCount","isEditing","textareaSelector","formElement","wrappedTextArea","initialContent","$attachmentsElement","setupAttachmentAddedCallback","setupAttachmentRemovalSignal","addUploadedAttachmentsToForm","setLabel","removedUrls","downloadLocation","fire","textareaId","ckContent","maxValue","toArray","addedAttachments","setup","markEdited","PersistentToggleComponent","$targetNotification","getTargetNotification","isNowHidden","displayed","sections","removeHiddenOnSubmit","section","HideSectionLinkComponent","hideSectionService","sectionName","hideSection","ShowSectionDropdownComponent","HideSectionService","optValue","hideSecWithName","prev","trackByKey","selectable","AutocompleteSelectDecorationComponent","multiselect","labelForId","syncInputFieldName","updateSelection","removeCurrentSyncedFields","createSyncedField","ScrollableTabsComponent","currentTabId","hideLeftButton","hideRightButton","pane","scrollPane","determineScrollButtonVisibility","scrollIntoVisibleArea","tabId","tabRightBorderAt","outerWidth","onScroll","scrollRight","gonTabs","CopyToClipboardDirective","clickTarget","clipboardTarget","supported","queryCommandSupported","execCommand","addNotification","ConfirmFormSubmitController","$form","openConfirmationDialog","markable","setMarkedOption","all_projects","current_project","current_project_and_all_descendants","search_dots","close_search","toggleTopMenuClass","unregister","btn","toggleMobileSearch","submitNonEmptySearch","wpPath","openCloseMenu","searchedTerm","selectedItem","followSelectedItem","searchInScope","currentScope","statusId","followItem","hashFreeQuery","queryWithoutHash","fetchSearchResults","searchResultsToOptions","filterBySubjectOrId","searchItems","searchOptions","detailedSearchOptions","suggestion","itemsList","markItem","selectedItems","forcePageLoad","isAfterSearch","replaceState","submitSearch","serviceScope","unregisterGlobalListener","onFocusOut","onEnterBeforeResultsLoaded","clearSearch","CollapsibleSectionComponent","sectionTitle","sectionBody","EnterpriseBannerBootstrapComponent","textMessage","linkMessage","referrer","LazyLoadedAutocompleter","_create","_super","_search","_renderMenu","ul","_renderLazyMenu","pageElements","maxItemsPerPage","_renderItemData","shownHeight","_pages","_repositionMenu","_resizeMenu","autoFocus","_renderItem","renderItem","mark","pages","_renderMenuPage","scroll","outerHeight","isScrollbarBottom","widgetName","literalMatches","literalSearch","fuseInstance","str","setupParams","shouldSort","tokenize","threshold","maxPatternLength","minMatchCharLength","autocompleteValues","delay","fuzzyResults","fuzzySearch","augmentedResultSet","onItemSelected","onNoResultsFound","minLength","no_results","dropdownMenu","projectMenuAutocomplete","loadProjects","addInputHandlers","addClickHandler","scrollCurrentProjectIntoView","projectLink","currentMenuItem","projectLevelListPath","augmentWithParents","currentLevel","matchedParents","keydown","touchMoved","currentProjectHeight","scrollValue","htmlMode","keyCodesArray","TAB","SHIFT","updater","remoteFieldKey","scope_default","scope_starred","scope_global","scope_private","hiddenCategories","reportsBodySelector","queryResultsContainer","_queryResultsContainerElement","initializeAutocomplete","unregisterTransitionListener","searchInput","_wpQueryMenuSearchInput","buttonArrowLeft","setupAutoCompletion","updateMenuOnChanges","combinedQueries","sortQueries","categorized","private","auto_id","category","sortByLabel","filterNonHidden","querycomplete","transformQueries","thisCategory","expandCollapseCategory","defineJQueryQueryComplete","autocompleteUi","sourceEvent","thisComponent","buildQueryItemUrl","li","setInitialHighlighting","currentCategory","labelFunction","behavior","currentLi","getQueryParams","currentId","currentProps","onWorkPackagesPage","onWorkPackagesReportPage","currentIdSelected","matchesStaticQueryProps","allOpen","onSummary","highlightBySelector","clickedWithModifier","isStatic","highlightSelected","clickedCategory","project_and_subprojects","search_for","in","projectText","searchTitle","currentProjectName","currentTabSub","tabsSub","clickTab","initializeMenu","userData$","modalOpen","emailInvalid","invalid_email","taken_email","taken_domain","baseUrlAugur","augur_url","tokenVersion","token_version","ee_trial_key","setMailSubmittedStatus","enterpriseTrial","trialLink","saveTrialKey","retryConfirmation","addWarning","token_retrieved","saveToken","resendLink","resend","resendlink","trialKey","trial_key","enterprise_token","encoded_token","retries","getToken","emailTaken","domainTaken","I18nHelpers","localizeLink","en","formBuilder","currentUserService","eeTrialService","userData","trialForm","company","first_name","last_name","domain","host","general_consent","newsletter_consent","link_terms","de","link_privacy","label_test_ee","label_company","label_first_name","label_last_name","label_email","label_domain","privacy_policy","receive_newsletter","terms_of_service","controls","checkMailField","label_expires_at","label_maximum_users","label_starts_at","label_subscriber","subscriber","userForm","formatUserData","eeTrialKey","getUserDataFromAugur","created","confirmation_info","resend_success","resend_warning","session_timeout","status_confirmed","status_label","status_waiting","savedDateStr","button_submit","heading_confirmation","heading_next_steps","heading_test_ee","quick_overview","trustedEEVideoURL","trustedURL","formComponent","addControl","sendForm","setStartTrialStatus","mailSubmitted","trialStarted","button_trial","button_book","link_quote","become_hero","you_contribute","email_not_received","enterprise_edition","confidence","try_another_email","userCount","startsAt","expiresAt","TriggerActionsEntryComponent","loadEntry","timeEntryId","editTimeEntry","deleteTimeEntry","not_found","cache$","loadWorkPackage","DisplayFieldComponent","containerType","getDisplayFieldInstance","displayClass","displayFieldContext","resourceLoader","invalid_attribute","hostTitle","markError","attributeFromLocalizedName","StringHelpers","capitalize","loadResourceAttribute","detailed","workPackage$","EditableQueryPropsComponent","externalQuery","globalDynamicComponents","OpenprojectMembersModule","OpenprojectEnterpriseModule","wrapElement","activationLink","activationSelector","iframeUrl","appendIframe","subdom","iframe","OpenprojectAugmentingModule","modalWrapper","pathScript","setupListener","loadRequiredScripts","RevitAddInSettingsButtonService","labelText","groupLabelText","addUserMenuItem","addLoginMenuItem","userMenu","goToSettings","loginModal","loginMenuItem","bootstrapOptionalDocument","_injector","PreviewTrigger","mainMenuNavigationService","keyboardShortcuts","contextCallbacks","messageStack","sentryConfigured","sentryElement","Sentry","dsn","debug","ignoreErrors","beforeSend","filterEvent","sentryLoaded","client","configureScope","setupContext","severity","handleOfflineMessage","withScope","fromString","callbacks","hostname","enableReactiveStatesLogging","disableReactiveStatesLogging","meta","initializeLocale","platformRef","WorkPackageViewBaseService","combinedRaw","pristine","WorkPackageQueryStateService"],"mappings":"8FACA,4DAIO,MAAMA,UAA6B,IAEjC,SAASC,EAAYC,GAC1BC,MAAMC,SAASH,EAAKC,GAER,YAARD,GAA6B,SAARA,GACvBI,KAAKC,aAIC,aAAaC,GAMrB,cAFOA,EAAQC,YAERL,MAAMM,aAAaF,GAGlB,iBAAiBN,EAAYC,GAGzB,gBAARD,GAAyBI,KAAKK,iBAAiBC,MACjDN,KAAKK,iBAAiBF,YAAcN,EAItCC,MAAMS,iBAAiBX,EAAKC,GAQ9B,aACE,OAAIG,KAAKQ,MAAMC,WACN,IAAuBC,OAAOZ,MAAMa,OAAQX,KAAKY,mBAEjDd,MAAMa,U,oCC5CnB,gSA4BO,MAAME,EACX,YAAsBC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,GAlBA,KAAAlB,SACA,KAAAC,aACA,KAAAC,iBACA,KAAAC,iBACA,KAAAC,mBACA,KAAAC,gBACA,KAAAC,iBACA,KAAAC,aACA,KAAAC,kBACA,KAAAC,qBACA,KAAAC,sBACA,KAAAC,yBACA,KAAAC,oBACA,KAAAC,eACA,KAAAC,4BACA,KAAAC,eACA,KAAAC,wBACA,KAAAC,uBACA,KAAAC,0BAUf,WAAWC,EAAqBC,GACrClC,KAAKmC,cAGLnC,KAAKe,WAAWkB,MAAMG,SAASH,GAC/BjC,KAAKqC,oBAAoBJ,EAAOC,GAGhClC,KAAKsC,iBAAiBL,EAAOC,GAG7BlC,KAAKuC,eAAeN,EAAOC,GAStB,qBAAqBD,EAAqBO,GAC/C,IAAI7B,EAA6B6B,EAAK7B,OAEtC8B,EAAEC,KAAK/B,EAAOgC,eAAeC,SAAWjC,IACtCX,KAAKc,OAAO+B,QAAQC,IAAInC,EAAOoC,OAAiBX,SAASzB,KAG3DX,KAAKoB,eAAe4B,kBAAkBf,EAAOtB,GAC7CX,KAAKe,WAAWkC,UAAUb,SAASI,GAEnCxC,KAAKc,OAAOoC,QAAQC,QAAQf,SAASzB,EAAOwC,QAAQC,eACpDpD,KAAKc,OAAOoC,QAAQG,OAAOjB,SAASzB,EAAO0C,OAAOD,eAClDpD,KAAKc,OAAOoC,QAAQI,QAAQlB,SAASzB,EAAO2C,QAAQF,eACpDpD,KAAKc,OAAOoC,QAAQK,sBAAsBnB,SAASzB,EAAO4C,sBAAsBH,eAG3E,iBAAiBnB,EAAqBC,GAE3ClC,KAAKe,WAAWyC,+BAA+BC,MAAM,gDACrDzD,KAAKe,WAAW2C,cAAcD,MAAM,uDAEhCvB,EAAQW,SACVJ,EAAEC,KAAKR,EAAQW,QAAQD,SAAWjC,IAChCX,KAAKc,OAAO+B,QAAQC,IAAInC,EAAOgD,MAAgBvB,SAASzB,KAI5DX,KAAKe,WAAWkB,MAAMG,SAASH,GAE/BjC,KAAK+B,qBAAqB6B,cAAc,gBAAiB1B,EAAQ2B,QAEjE3B,EAAQU,SAASkB,QAAQC,GAAM/D,KAAK6B,aAAamC,cAAcC,MAAMC,kBAAkBH,GAAI,IAE3F/D,KAAKe,WAAWmB,QAAQE,SAASF,GAEjClC,KAAKe,WAAWoD,OAAO/B,SAASF,EAAQiC,QAExCnE,KAAK0B,kBAAkB0C,WAAWnC,EAAOC,GAEzClC,KAAKyB,uBAAuB2C,WAAWnC,EAAOC,GAE9ClC,KAAK4B,0BAA0BwC,WAAWnC,EAAOC,GAEjDlC,KAAK2B,aAAayC,WAAWnC,EAAOC,GAEpClC,KAAKgC,wBAAwBoC,WAAWnC,EAAOC,GAE/ClC,KAAKe,WAAWyC,+BACba,UACAC,KAAK,YAAK,IACVC,UAAU,IAAMvE,KAAKe,WAAWyD,YAAYpC,SAAS,OAGnD,eAAeH,EAAqBC,GACzClC,KAAK8B,sBAAsB2C,kBAAkBzE,KAAKe,WAAWkB,MAAMyC,MAAQ1E,KAAK0B,kBAAkBiD,SAClG3E,KAAK+B,qBAAqB6B,cAAc,gBAAiB1B,EAAQ2B,QAG5D,oBAAoB5B,EAAqBC,GAC9ClC,KAAKe,WAAWkB,MAAMG,SAASH,GAE/BjC,KAAKqB,WAAW+C,WAAWnC,GAC3BjC,KAAKgB,eAAeoD,WAAWnC,EAAOC,GACtClC,KAAKmB,cAAciD,WAAWnC,EAAOC,GACrClC,KAAKiB,eAAemD,WAAWnC,EAAOC,GACtClC,KAAKkB,iBAAiBkD,WAAWnC,EAAOC,GACxClC,KAAKsB,gBAAgB8C,WAAWnC,EAAOC,GACvClC,KAAKuB,mBAAmB6C,WAAWnC,EAAOC,GAC1ClC,KAAKwB,oBAAoB4C,WAAWnC,EAAOC,GAC3ClC,KAAKgC,wBAAwBoC,WAAWnC,EAAOC,GAE/ClC,KAAK+B,qBAAqB6B,cAAc,QAAS3B,EAAM4B,QACvD7D,KAAK+B,qBAAqB6B,cAAc,gBAAiB1B,EAAQ2B,QAG5D,aAAa5B,GAClBjC,KAAKoB,eAAewD,aAAa3C,GACjCjC,KAAKqB,WAAWuD,aAAa3C,GAC7BjC,KAAKgB,eAAe4D,aAAa3C,GACjCjC,KAAKmB,cAAcyD,aAAa3C,GAChCjC,KAAKiB,eAAe2D,aAAa3C,GACjCjC,KAAKkB,iBAAiB0D,aAAa3C,GACnCjC,KAAKsB,gBAAgBsD,aAAa3C,GAClCjC,KAAKwB,oBAAoBoD,aAAa3C,GACtCjC,KAAKuB,mBAAmBqD,aAAa3C,GACrCjC,KAAK2B,aAAaiD,aAAa3C,GAC/BjC,KAAKgC,wBAAwB4C,aAAa3C,GAGrC,cACL,MAAM4C,EAAS,4CAGf7E,KAAKe,WAAWyD,YAAYf,MAAMoB,GAClC7E,KAAKe,WAAWkB,MAAMwB,MAAMoB,GAC5B7E,KAAKe,WAAWmB,QAAQuB,MAAMoB,GAC9B7E,KAAKe,WAAWoD,OAAOV,MAAMoB,GAC7B7E,KAAKe,WAAWyC,+BAA+BC,MAAMoB,GAErD7E,KAAKoB,eAAeqC,MAAMoB,GAC1B7E,KAAKgB,eAAeyC,MAAMoB,GAC1B7E,KAAKmB,cAAcsC,MAAMoB,GACzB7E,KAAKiB,eAAewC,MAAMoB,GAC1B7E,KAAKkB,iBAAiBuC,MAAMoB,GAC5B7E,KAAKgC,wBAAwByB,MAAMoB,GACnC7E,KAAKqB,WAAWoC,MAAMoB,GAGtB7E,KAAKe,WAAW2C,cAAcD,MAAMoB,I,sCA7J3BhE,GAAsC,gM,yBAAtCA,EAAsC,QAAtCA,EAAsC,a,oCCCnD,kF,wBAMI,c,oBAGG,2BAFA,yBAAkB,kB,yBAIrB,QACE,QACF,QAFA,Q,oBACE,8BAKC,MAAMiE,EAGX,YAAqBC,GAAA,KAAAA,OAGrB,WACE,OAAO/E,KAAKgF,MAAQhF,KAAKgF,KAAKC,aAGhC,WACE,OAAOjF,KAAKgF,MAAQhF,KAAKgF,KAAKE,KAGhC,YACE,OAAOlF,KAAK+E,KAAKI,EAAE,kBAAmB,CAAEH,KAAMhF,KAAKkF,Q,sCAf1CJ,GAAiB,Y,uBAAjBA,EAAiB,4JAX1B,oBAKA,gC,MALI,oBAKW,+B,0FCXnB,4DAOO,MAAMM,EAIX,YAAsBC,EACAC,GADA,KAAAD,aACA,KAAAC,aAGtB,WACEtF,KAAKuF,SAAWC,OAAOxF,KAAKsF,WAAWG,eAGlC,SAASC,GAGd,GADeF,OAAOE,EAAIC,QACfC,QAAQ,qBAAqBC,OACtC,OAAO,EAGT,MAAMC,EAAQ9F,KAAKqF,WAAWU,OAAO/F,KAAKgG,WAG1C,OAFAF,GAASA,EAAMG,mBAAmB,OAE3B,G,sCAtBEb,GAAoC,sB,uBAApCA,EAAoC,uF,MAAA,0G,OCpCjD,iBAEE,gCAAS,EAAAc,SAAA,KAET,QACF,S,uDCwBA,gDAEO,MAAMC,UAAqC,IACzC,YAAYC,GACjBtG,MAAMuG,YAAYD,GAElBpG,KAAK4C,SAAW5C,KAAK4C,UAAY,M,oCClCrC,gGAkCO,MAAM0D,EADb,cAEU,KAAAC,QAAU,IAAI,IAGf,KAAAC,QAAUxG,KAAKuG,QAAQE,eAGvB,YAAYC,EAAqBC,EAAmB,KACzD,OAAO3G,KACJwG,QACAlC,KACC,YAAQsC,GAAmBA,EAAMF,eAAiBA,GAClD,YAAO1G,KAAKwG,QAAQlC,KAAK,YAAaqC,MAIrC,KAAKE,EAA2DD,GACrEA,EAAME,GAAKD,EAAkBC,GAC7BF,EAAMF,aAAeG,EAAkBE,MAEvC/G,KAAKuG,QAAQS,KAAKJ,I,sCApBTN,I,yBAAAA,EAAgB,QAAhBA,EAAgB,qBADH,U,oCCN1B,wEAkBO,MAAMW,EAhBb,cAiBY,KAAAC,QAAU,IAAI,IAOjB,YAAYN,GAKjB,OAJK5G,KAAKmH,YACRnH,KAAKkH,QAAQE,KAAKR,IAGb,G,sCAbEK,I,uBAAAA,EAA6B,uN,MAAA,2H,OAbxC,cAAG,0CAAmB,EAAAI,YAAA,KAOpB,iBACE,QACF,OACF,Q,MARG,4BACA,sCAAyC,oBAAzC,CAAyC,8BAIpC,sC,oRClCH,MAAMC,EAAyB,4BACzBC,EAA2B,8BAC3BC,EAA2B,6BAC3BC,EAAoB,6BAE1B,MAAeC,EAIpB,YAAqBC,EACAC,GADA,KAAAD,WACA,KAAAC,eAHN,aAAd,c,0BAAoB,M,gECcvB,gEAAO,MAAMC,EAAoB,IAE1B,MAAMC,EAIX,YAAqBC,GAAA,KAAAA,gBAHb,KAAAC,OAAQ,EACR,KAAAC,YAAa,EAGnBjI,KAAKkI,6BACLlI,KAAKmI,qBACLnI,KAAKoI,wBACLpI,KAAKqI,mBACLrI,KAAKsI,gBACLtI,KAAKuI,2BAGP,2BAEE/C,OAAO,6BAA6BgD,GAAG,QAAS,KAE9C,MACMC,EAAcjD,OADF,6FAEfkD,IAAI,WACJC,QAECF,EAAY5C,QACd4C,EAAYG,QAAQ,WAK1B,gBACEpD,OAAO,mBAAmBqD,KAAK,gBAAiB,SAGlD,YAAYC,GACN9I,KAAKiI,WACHjI,KAAK+I,OAAOD,GACd9I,KAAKgJ,UAELhJ,KAAKiJ,KAAKH,IAGZ9I,KAAKkJ,UACLlJ,KAAKiJ,KAAKH,IAKd,UACE9I,KAAKmJ,aACLnJ,KAAKiI,YAAa,EAClBjI,KAAK+H,cAAca,QAAQ,aAAc5I,KAAK+H,eAIhD,UACE/H,KAAKoJ,YACLpJ,KAAKqJ,gBACLrJ,KAAKiI,YAAa,EAClBjI,KAAK+H,cAAca,QAAQ,aAAc5I,KAAK+H,eAGhD,YACE/H,KAAKgI,OAAQ,EACbhI,KAAK+H,cAAcuB,YAAY,SAGjC,aACEtJ,KAAKgI,OAAQ,EACbhI,KAAK+H,cAAcwB,SAAS,SAG9B,gBACEvJ,KAAKwJ,gBAAgB9G,KAAK,CAAC+G,EAAIC,KAC7B1J,KAAK2J,MAAMnE,OAAOkE,MAItB,mBACE,IAAIE,EAAO5J,KACP6J,EAAUC,SAASC,eAAe,WAEjCF,GAILA,EAAQG,iBAAiB,QAAS,SAAUtE,GACtCkE,EAAK3B,aAAe2B,EAAKJ,gBAAgB,GAAGS,SAASvE,EAAIC,SAC3DiE,EAAKZ,YAEN,GAGL,gBACE,OAAOhJ,KAAKkK,YAAYC,OAAO,SAGjC,YACE,OAAOnK,KAAK+H,cAAcqC,KAAK,gBAGjC,6BACE,IAAIC,EACJ,QAAyCC,IAArCtK,KAAK+H,cAAcf,OAAOlE,IAAI,IAAkE,OAA7C9C,KAAK+H,cAAcf,OAAOlE,IAAI,GAAGyH,QACtFF,EAAsBrK,KAAK+H,cAAcf,OAAOwD,cAAiBxK,KAAK+H,cAAcf,OAAOyD,WAAWC,IACtG1K,KAAK+H,cAAcqC,KAAK,+BAA+BO,IAAI,CAAED,IAAKL,SAC7D,GAAIrK,KAAK+H,cAAcf,OAAO4D,SAAS,sBACmBN,IAA/DtK,KAAK+H,cAAcf,OAAO6D,WAAW7D,OAAO2B,QAAQ7F,IAAI,IACe,OAAvE9C,KAAK+H,cAAcf,OAAO6D,WAAW7D,OAAO2B,QAAQ7F,IAAI,GAAGyH,QAAkB,CAC7E,IAAIO,EAAe9K,KAAK+H,cAAcf,OAAO6D,WAAW7D,OAAO2B,QAC/D0B,EAAsBS,EAAaN,cAAiBM,EAAaL,WAAWC,IAC5E1K,KAAK+H,cAAcqC,KAAK,+BAA+BO,IAAI,CAAED,IAAKL,KAItE,qBACE,IAAIT,EAAO5J,KACXA,KAAKkK,YAAYxH,KAAK,SAAU+G,EAAIsB,GAClCvF,OAAOuF,GAAIC,MAAM,WAEf,OADApB,EAAKqB,YAAYzF,OAAOxF,QACjB,IAETwF,OAAOuF,GAAIvC,GAAG,aAAc,SAAU0C,GAIpC,QAAI1F,OAAO0F,EAAEvF,QAAQC,QAAQ,6BAA6BC,SAG1DqF,EAAEC,iBACF3F,OAAOxF,MAAMgL,SACN,OAKb,OAAOlC,GACL,OAA2C,IAApCA,EAASqB,OAAO,SAAStE,OAGlC,SAASiD,GACP,OAAQ9I,KAAK+I,OAAOD,GAGtB,KAAKA,GACH9I,KAAKoL,mBAAmBtC,GACxB9I,KAAKqL,gBAAgBvC,GACrB9I,KAAKsL,cAAcxC,EAAU,WAC3BA,EAASF,QAAQ,SAAUE,KAI/B,MAAMA,EAAiByC,GACrBvL,KAAKwL,QAAQ1C,EAAUyC,GACvBzC,EAASF,QAAQ,SAAUE,GAG7B,gBAAgBA,GACd,IAAIc,EAAO5J,KACXA,KAAKwJ,gBAAgB9G,KAAK,SAAU+G,EAAIsB,GAClCvF,OAAOuF,KAAQvF,OAAOsD,IACxBc,EAAKD,MAAMnE,OAAOuF,IAAK,KAK7B,mBAAmBjC,GACjBtD,OAAOsD,GAAUsB,KAAK,MAAMY,MAAM,SAAUpE,GAC1CA,EAAM6E,oBAERjG,OAAOsD,GAAU4C,KAAK,0BAA2B,SAAU9E,GACzDA,EAAM6E,oBAIV,cAAc3C,EAAiB6C,GAC7B3L,KAAK4L,UAAU9C,EAAU6C,GACzB3L,KAAK6L,sBAAsB/C,GAG7B,UAAUA,EAAiB6C,GACzB,IAAIG,EAAShD,EAASsB,KAAK,QAC3BtB,EAASS,SAAS,QAClBuC,EAAOF,UAAU/D,EAAmB8D,GAAU9C,KAAK,gBAAiB,QAGtE,QAAQC,EAAiByC,GACvB,IAAIO,EAAStG,OAAOsD,GAAUsB,KAAK,QACnCtB,EAASQ,YAAY,QAEjBiC,EACFO,EAAOC,OAEPD,EAAON,QAAQ3D,GAGjBiE,EAAOjD,KAAK,gBAAiB,SAK/B,sBAAsBC,GACpB,IAAIkD,EAAUlD,EAASsB,KAAK,2BACL,IAAnB4B,EAAQnG,SACVmG,EAAUlD,EAASsB,KAAK,uBAK1B4B,EAAQC,OACRC,WAAW,WACTF,EAAQG,SACP,IAGL,wBACE,MAAMC,EAAU5G,OAAO,qBAEvBxF,KAAK+H,cAAcS,GAAG,gBAAkB5B,IACtC5G,KAAK2J,MAAMnE,OAAOoB,EAAMjB,WACvB6C,GAAG,eAAiB5B,IACrB5G,KAAKiJ,KAAKzD,OAAOoB,EAAMjB,WACtB6C,GAAG,YAAa,KACjBxI,KAAKgJ,YACJR,GAAG,WAAY,KAChBxI,KAAKiJ,KAAKjJ,KAAKkK,YAAYvB,SAC3B3I,KAAKkJ,YAGPkD,EAAQ5D,GAAG,QAAS,KAClBxI,KAAKgJ,e,iPC9PL,gBAEE,2BAKF,Q,mCALkB,0CAA2B,sBAA3B,CAA2B,oCAA3B,CAA2B,4B,yBAH/C,gBACE,sBAQF,Q,oBARuB,6CAAuB,+BCqC3C,MAAM,UAA0C,IALvD,c,oBAQS,KAAAqD,mBAAyC,GACzC,KAAAC,YAAc,IAAuBC,gBAAgB,cAE5D,WACEvM,KAAKwM,cAAgBxM,KAAK4H,YAAYd,GACtChH,MAAM2M,WAGE,oBACR,OAAO,EAGC,iBAAiBC,GACzB5M,MAAM6M,iBAAiBD,GACvB1M,KAAKqM,mBAAqBrM,KAAK4M,mBAGzB,iBAAiBC,EAAiB,GAExC,GAAI7M,KAAK8M,QAAS,CAIhB,OADc9M,KAAK+M,qBAAqBC,MAAM,EAAGH,GAClCI,IAAI,CAACC,EAAgBC,IAAanN,KAAKoN,KAAKF,EAAIC,IAC1D,CAEL,IAAIE,EAAUrN,KAAK+M,qBAAqBC,OAAOH,GAC3CS,EAAatN,KAAK+M,qBAAqBlH,OAASwH,EAAQxH,OAC5D,OAAOwH,EAAQJ,IAAI,CAACC,EAAgBC,IAAanN,KAAKoN,KAAKF,EAAII,EAAaH,M,oCA/BrE,I,uBAAA,EAAiC,8YDxC9C,iCACE,4BAYF,Q,KAbsB,mC,0ECwCT,G,wBCxCb,2B,oBAAgB,mC,yBAGhB,gBACE,gBACE,gBACE,eACF,OACF,OAEA,wCACF,Q,oBALgD,sCAIjB,2CC6BxB,MAAM,UAAwC,IAKnD,YAA4BpI,EACAwI,EACA1L,GAC1B/B,QAH0B,KAAAiF,OACA,KAAAwI,SACA,KAAA1L,eAJrB,KAAA2L,QAAUxN,KAAK+E,KAAKI,EAAE,4BAO3BnF,KAAKwM,cAAgBxM,KAAKuN,OAAOE,OAAOjB,cAExCxM,KACG6B,aACAmC,cACA8C,GAAG9G,KAAKwM,eACRkB,mBACApJ,KACCtE,KAAK2N,kBAENpJ,UAAWR,GAAO/D,KAAK4H,YAAc7D,I,sCApB/B,GAA+B,2C,uBAA/B,EAA+B,2UDvC5C,iCAGA,uB,MAFiB,2BAEc,qC,gOEH/B,gBAIE,sBAGW,8DACX,gBACI,gBACE,2BACA,gBACE,cAAG,qEAED,iBACF,OACF,OACF,OACA,2BAGF,OAEA,iBACE,kCACE,yEACF,OACF,OAEA,kBACE,yBAEF,OACF,OACF,O,uBA9Ba,0CAA2B,0BAA3B,CAA2B,iBAMhB,6CAQF,6CAA8B,yBAYlC,6EAAgE,qDCM3E,MAAM,UAAyC,K,oCAAzC,I,uBAAA,EAAgC,+uBDpC7C,uB,KAEG,+B,sFCkCU,G,mGDpCb,gBAIE,sBAGW,8DACX,gBACI,gBACE,2BACA,gBACE,cAAG,qEAED,iBACF,OACF,OACF,OACA,2BAGF,OAEA,iBACE,kCACE,yEACF,OACF,OAEA,kBACE,yBAEF,OACF,OACF,O,uBA9Ba,0CAA2B,0BAA3B,CAA2B,iBAMhB,6CAQF,6CAA8B,yBAYlC,6EAAgE,qDEM3E,MAAM,UAA0C,K,oCAA1C,I,uBAAA,EAAiC,gvBFpC9C,uB,KAEG,+B,sFEkCU,GCoBN,SAAS6J,EAAoBC,EACAC,EACAC,EACAC,EAAkC,EAClCC,EACAC,EAAYL,GAO9C,MAAO,CACL,CACE3I,KAAMgJ,EAAY,WAClBC,IAAK,kCACLC,WAAYF,EAAY,oBACxBG,gBAAgB,EAChBC,KAAM,CACJC,YAAa,uDACbC,SAAUV,EAEVD,UAAWA,EACXY,SAAUP,EAAY,OACtBQ,UAdYT,EAAgB,aAAe,UAkB7CU,MArBcV,EACF,CAAC,mBAAoB,CAAEW,UAAWb,IAClC,CAAC,oBAAqB,CAAEa,UAAWb,KAqBjD,CACE7I,KAAMgJ,EAAY,oBAClBC,IAAK,YACLS,UAAW,EACXN,KAAM,CACJT,UAAWA,EACXW,SAAUV,EACVe,OAAQX,EAAY,aAGxB,CACEhJ,KAAMgJ,EAAY,oBAClBC,IAAK,YACLS,UAAW,IACXN,KAAM,CACJT,UAAWA,EACXW,SAAUV,EACVe,OAAQX,EAAY,aAGxB,CACEhJ,KAAMgJ,EAAY,qBAClBC,IAAK,aACLS,UAAW,IACXN,KAAM,CACJT,UAAWA,EACXW,SAAUV,EACVe,OAAQX,EAAY,aAGxB,CACEhJ,KAAMgJ,EAAY,oBAClBC,IAAK,YACLS,UAAW,IACXN,KAAM,CACJT,UAAWA,EACXW,SAAUV,EACVe,OAAQX,EAAY,aAIxB,CACEhJ,KAAMgJ,EAAY,OAClBC,IAAK,+CACLE,gBAAgB,EAChBC,KAAM,CACJI,UAAW,SACXI,uBAAuB,EACvBP,YAAa,mDAEbV,UAAWA,EACXgB,OAAQhB,GAEVc,MAAO,CAGL,oBAAqB,CAAEC,UAAWZ,KAItC,CACE9I,KAAMgJ,EAAY,QAClBC,IAAK,iDACLQ,MAAO,CACL,oBAAqB,CAAEC,UAAW,IAEpCP,gBAAgB,EAChBC,KAAM,CACJT,UAAWA,EACXgB,OAAQhB,EACRiB,uBAAuB,EACvBP,YAAa,+CACbC,SAAUV,EACVY,UAAW,c,2EClInB,4DAIO,MAAMK,EACX,YAAqBC,GAAA,KAAAA,aAGd,uBAAuBC,GAC5B,OAAOjP,KAAKgP,WAAWE,YAAYD,GAAqB,iBAGnD,wBAAwBA,EAA0BE,GACvD,OAAIA,EACKnP,KAAKgP,WAAWE,YAAYD,GAAqB,8BAAgCE,EAEjFnP,KAAKgP,WAAWE,YAAYD,GAAqB,qBAIrD,aAAaG,GAClB,OAAOA,EAAUzL,KAAO,a,sCAjBfoL,GAAoB,Y,yBAApBA,EAAoB,QAApBA,EAAoB,a,uBCjCjC,IAAI9B,EAAM,CACT,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,cAAe,CACd,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,WAAY,CACX,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,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CX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,gBAAiB,OACjB,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,UAAW,OACX,aAAc,OACd,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,UAAW,OACX,aAAc,OACd,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW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AAQK,KAAKuV,MAAM,KAAKwO,MAMvC,SAAS06D,EAAoB1pD,GAClC,MAAO,eAAeA,EAMjB,SAAS2pD,EAAwB1uE,GACtC,OAAOA,EAAgBuF,MAAM,KAAK,GAM7B,SAASopE,EAAsB3uE,GACpC,OAAOA,EAAgBuF,MAAM,KAAKwO,MA9CpC,iM,qBCFA,IAAIza,EAAM,CACT,eAAgB,CACf,OACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,yBAA0B,CACzB,OACA,EACA,IAED,2BAA4B,CAC3B,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,GAED,uBAAwB,CACvB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,iCAAkC,CACjC,OACA,EACA,GAED,6BAA8B,CAC7B,OACA,EACA,IAED,uBAAwB,CACvB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,IAED,WAAY,CACX,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,EACA,EACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,uBAAwB,CACvB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,EACA,EACA,IAED,uBAAwB,CACvB,OACA,EACA,IAED,aAAc,CACb,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,EACA,EACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,GAED,yCAA0C,CACzC,OACA,EACA,EACA,IAED,uBAAwB,CACvB,OACA,EACA,GAED,iBAAkB,CACjB,OACA,EACA,IAED,iCAAkC,CACjC,OACA,EACA,EACA,EACA,EACA,IAED,2BAA4B,CAC3B,OACA,EACA,EACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,yBAA0B,CACzB,OACA,EACA,GAED,+BAAgC,CAC/B,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,yBAA0B,CACzB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,EACA,IAED,yBAA0B,CACzB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,aAAc,CACb,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,EACA,EACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,KAED,6BAA8B,CAC7B,OACA,EACA,KAED,yBAA0B,CACzB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,EACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,GAED,WAAY,CACX,OACA,EACA,KAED,WAAY,CACX,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,GAED,iBAAkB,CACjB,OACA,EACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,KAED,mBAAoB,CACnB,OACA,EACA,KAED,mBAAoB,CACnB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,EACA,EACA,EACA,IAED,2BAA4B,CAC3B,OACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,EACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,KAED,+BAAgC,CAC/B,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,uBAAwB,CACvB,OACA,EACA,KAED,6BAA8B,CAC7B,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,uBAAwB,CACvB,OACA,EACA,EACA,EACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,KAED,yBAA0B,CACzB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,EACA,KAED,aAAc,CACb,OACA,EACA,KAED,yBAA0B,CACzB,OACA,EACA,KAED,yBAA0B,CACzB,OACA,EACA,KAED,uBAAwB,CACvB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,EACA,EACA,GACA,EACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED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,EAAU3E,KAAK2E,QAGrB,OAFA1C,EAAMsB,sBAAoC,OAAZoB,OAAmB2F,EAAY3F,GAEtD,EAGT,cACE,OAAO3E,KAAK6W,iBAAiB9D,WAAW,MAG1C,aACE,MAAMpO,EAAU3E,KAAK2E,QACrB,OAAQA,GAAWA,IAAY6vF,EAGjC,cACE,OAAOx0F,KAAK2E,UAAY8vF,EAGnB,yBAAyBE,GAC9B30F,KAAK8T,OAAO6gF,I,sCAnCHD,GAA2C,sB,yBAA3CA,EAA2C,QAA3CA,EAA2C,a,qBCxCxD,IAAIznF,EAAM,CACT,gBAAiB,CAChB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,4BAA6B,CAC5B,OACA,EACA,IAED,+BAAgC,CAC/B,OACA,EACA,IAED,aAAc,CACb,OACA,EACA,EACA,GAED,gBAAiB,CAChB,OACA,EACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,GAED,wBAAyB,CACxB,OACA,EACA,GAED,sBAAuB,CACtB,OACA,EACA,GAED,yBAA0B,CACzB,OACA,EACA,GAED,oBAAqB,CACpB,OACA,EACA,GAED,uBAAwB,CACvB,OACA,EACA,GAED,8BAA+B,CAC9B,OACA,EACA,GAED,iCAAkC,CACjC,OACA,EACA,GAED,wBAAyB,CACxB,OACA,EACA,GAED,2BAA4B,CAC3B,OACA,EACA,GAED,4BAA6B,CAC5B,OACA,EACA,GAED,+BAAgC,CAC/B,OACA,EACA,GAED,mBAAoB,CACnB,OACA,EACA,GAED,sBAAuB,CACtB,OACA,EACA,GAED,uBAAwB,CACvB,OACA,EACA,GAED,0BAA2B,CAC1B,OACA,EACA,GAED,oBAAqB,CACpB,OACA,EACA,GAED,uBAAwB,CACvB,OACA,EACA,GAED,mBAAoB,CACnB,OACA,EACA,GAED,sBAAuB,CACtB,OACA,EACA,GAED,kBAAmB,CAClB,OACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,GAED,uBAAwB,CACvB,OACA,EACA,GAED,0BAA2B,CAC1B,OACA,EACA,GAED,0BAA2B,CAC1B,OACA,EACA,GAED,6BAA8B,CAC7B,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","file":"main.0e56bb43c1f86a2a3e1e.js","sourcesContent":["import {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport { WorkPackageSchemaProxy } from 'core-app/modules/hal/schemas/work-package-schema-proxy';\n\nexport class WorkPackageChangeset extends ResourceChangeset {\n\n public setValue(key:string, val:any) {\n super.setValue(key, val);\n\n if (key === 'project' || key === 'type') {\n this.updateForm();\n }\n }\n\n protected applyChanges(payload:any):any {\n // Explicitly delete the description if it was not set by the user.\n // if it was set by the user, #applyChanges will set it again.\n // Otherwise, the backend will set it for us.\n delete payload.description;\n\n return super.applyChanges(payload);\n }\n\n protected setNewDefaultFor(key:string, val:unknown) {\n // Special handling for taking over the description\n // to the pristine resource\n if (key === 'description' && this.pristineResource.isNew) {\n this.pristineResource.description = val;\n return;\n }\n\n super.setNewDefaultFor(key, val);\n }\n\n /**\n * Get the best schema currently available, either the default resource schema (must exist).\n * If loaded, return the form schema, which provides better information on writable status\n * and contains available values.\n */\n public get schema():SchemaResource {\n if (this.form$.hasValue()) {\n return WorkPackageSchemaProxy.create(super.schema, this.projectedResource);\n } else {\n return super.schema;\n }\n }\n}\n","import {States} from '../states.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {QueryFormResource} from 'core-app/modules/hal/resources/query-form-resource';\nimport {WorkPackagesListChecksumService} from './wp-list-checksum.service';\nimport {AuthorisationService} from 'core-app/modules/common/model-auth/model-auth.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {QuerySchemaResource} from 'core-app/modules/hal/resources/query-schema-resource';\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {take} from \"rxjs/operators\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {WorkPackageViewDisplayRepresentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageViewSumService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {WorkPackageViewAdditionalElementsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-additional-elements.service\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageViewPaginationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {WorkPackageViewCollapsedGroupsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service\";\n\n@Injectable()\nexport class WorkPackageStatesInitializationService {\n constructor(protected states:States,\n protected querySpace:IsolatedQuerySpace,\n protected wpTableColumns:WorkPackageViewColumnsService,\n protected wpTableGroupBy:WorkPackageViewGroupByService,\n protected wpTableGroupFold:WorkPackageViewCollapsedGroupsService,\n protected wpTableSortBy:WorkPackageViewSortByService,\n protected wpTableFilters:WorkPackageViewFiltersService,\n protected wpTableSum:WorkPackageViewSumService,\n protected wpTableTimeline:WorkPackageViewTimelineService,\n protected wpTableHierarchies:WorkPackageViewHierarchiesService,\n protected wpTableHighlighting:WorkPackageViewHighlightingService,\n protected wpTableRelationColumns:WorkPackageViewRelationColumnsService,\n protected wpTablePagination:WorkPackageViewPaginationService,\n protected wpTableOrder:WorkPackageViewOrderService,\n protected wpTableAdditionalElements:WorkPackageViewAdditionalElementsService,\n protected apiV3Service:APIV3Service,\n protected wpListChecksumService:WorkPackagesListChecksumService,\n protected authorisationService:AuthorisationService,\n protected wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService) {\n }\n\n /**\n * Initialize the query and table states from the given query and results.\n * They may or may not come from the same query source.\n *\n * @param query\n * @param results\n */\n public initialize(query:QueryResource, results:WorkPackageCollectionResource) {\n this.clearStates();\n\n // Update the (global) wp query states\n this.querySpace.query.putValue(query);\n this.initializeFromQuery(query, results);\n\n // Update the (local) table states\n this.updateQuerySpace(query, results);\n\n // Ensure checksum for state is correct\n this.updateChecksum(query, results);\n }\n\n /**\n * Insert new information from the query from to the states.\n *\n * @param query\n * @param form\n */\n public updateStatesFromForm(query:QueryResource, form:QueryFormResource) {\n let schema:QuerySchemaResource = form.schema as any;\n\n _.each(schema.filtersSchemas.elements, (schema) => {\n this.states.schemas.get(schema.$href as string).putValue(schema as any);\n });\n\n this.wpTableFilters.initializeFilters(query, schema);\n this.querySpace.queryForm.putValue(form);\n\n this.states.queries.columns.putValue(schema.columns.allowedValues);\n this.states.queries.sortBy.putValue(schema.sortBy.allowedValues);\n this.states.queries.groupBy.putValue(schema.groupBy.allowedValues);\n this.states.queries.displayRepresentation.putValue(schema.displayRepresentation.allowedValues);\n }\n\n public updateQuerySpace(query:QueryResource, results:WorkPackageCollectionResource) {\n // Clear table required data states\n this.querySpace.additionalRequiredWorkPackages.clear('Clearing additional WPs before updating rows');\n this.querySpace.tableRendered.clear('Clearing rendered data before upgrading query space');\n\n if (results.schemas) {\n _.each(results.schemas.elements, (schema:SchemaResource) => {\n this.states.schemas.get(schema.href as string).putValue(schema);\n });\n }\n\n this.querySpace.query.putValue(query);\n\n this.authorisationService.initModelAuth('work_packages', results.$links);\n\n results.elements.forEach(wp => this.apiV3Service.work_packages.cache.updateWorkPackage(wp, true));\n\n this.querySpace.results.putValue(results);\n\n this.querySpace.groups.putValue(results.groups);\n\n this.wpTablePagination.initialize(query, results);\n\n this.wpTableRelationColumns.initialize(query, results);\n\n this.wpTableAdditionalElements.initialize(query, results);\n\n this.wpTableOrder.initialize(query, results);\n\n this.wpDisplayRepresentation.initialize(query, results);\n\n this.querySpace.additionalRequiredWorkPackages\n .values$()\n .pipe(take(1))\n .subscribe(() => this.querySpace.initialized.putValue(null));\n }\n\n public updateChecksum(query:QueryResource, results:WorkPackageCollectionResource) {\n this.wpListChecksumService.updateIfDifferent(this.querySpace.query.value!, this.wpTablePagination.current);\n this.authorisationService.initModelAuth('work_packages', results.$links);\n }\n\n public initializeFromQuery(query:QueryResource, results:WorkPackageCollectionResource) {\n this.querySpace.query.putValue(query);\n\n this.wpTableSum.initialize(query);\n this.wpTableColumns.initialize(query, results);\n this.wpTableSortBy.initialize(query, results);\n this.wpTableGroupBy.initialize(query, results);\n this.wpTableGroupFold.initialize(query, results);\n this.wpTableTimeline.initialize(query, results);\n this.wpTableHierarchies.initialize(query, results);\n this.wpTableHighlighting.initialize(query, results);\n this.wpDisplayRepresentation.initialize(query, results);\n\n this.authorisationService.initModelAuth('query', query.$links);\n this.authorisationService.initModelAuth('work_packages', results.$links);\n }\n\n public applyToQuery(query:QueryResource) {\n this.wpTableFilters.applyToQuery(query);\n this.wpTableSum.applyToQuery(query);\n this.wpTableColumns.applyToQuery(query);\n this.wpTableSortBy.applyToQuery(query);\n this.wpTableGroupBy.applyToQuery(query);\n this.wpTableGroupFold.applyToQuery(query);\n this.wpTableTimeline.applyToQuery(query);\n this.wpTableHighlighting.applyToQuery(query);\n this.wpTableHierarchies.applyToQuery(query);\n this.wpTableOrder.applyToQuery(query);\n this.wpDisplayRepresentation.applyToQuery(query);\n }\n\n public clearStates() {\n const reason = 'Clearing states before re-initialization.';\n\n // Clear immediate input states\n this.querySpace.initialized.clear(reason);\n this.querySpace.query.clear(reason);\n this.querySpace.results.clear(reason);\n this.querySpace.groups.clear(reason);\n this.querySpace.additionalRequiredWorkPackages.clear(reason);\n\n this.wpTableFilters.clear(reason);\n this.wpTableColumns.clear(reason);\n this.wpTableSortBy.clear(reason);\n this.wpTableGroupBy.clear(reason);\n this.wpTableGroupFold.clear(reason);\n this.wpDisplayRepresentation.clear(reason);\n this.wpTableSum.clear(reason);\n\n // Clear rendered state\n this.querySpace.tableRendered.clear(reason);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component, Input} from '@angular/core';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\n\n@Component({\n selector: 'user-link',\n template: `\n \n \n \n {{ name }}\n \n `,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class UserLinkComponent {\n @Input() user:UserResource;\n\n constructor(readonly I18n:I18nService) {\n }\n\n public get href() {\n return this.user && this.user.showUserPath;\n }\n\n public get name() {\n return this.user && this.user.name;\n }\n\n public get label() {\n return this.I18n.t('js.label_author', { user: this.name });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {Component, ElementRef, Input, OnInit} from '@angular/core';\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\n\n@Component({\n selector: 'wp-replacement-label',\n templateUrl: './wp-replacement-label.html'\n})\nexport class WorkPackageReplacementLabelComponent implements OnInit {\n @Input('fieldName') public fieldName:string;\n private $element:JQuery;\n\n constructor(protected wpeditForm:EditFormComponent,\n protected elementRef:ElementRef) {\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n }\n\n public activate(evt:JQuery.TriggeredEvent) {\n // Skip clicks on help texts\n const target = jQuery(evt.target);\n if (target.closest('.help-text--entry').length) {\n return true;\n }\n\n const field = this.wpeditForm.fields[this.fieldName];\n field && field.handleUserActivate(null);\n\n return false;\n }\n}\n","\n \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\n\nexport class AttachmentCollectionResource extends CollectionResource {\n public $initialize(source:any) {\n super.$initialize(source);\n\n this.elements = this.elements || [];\n }\n\n}\n\nexport interface AttachmentCollectionResource {\n elements:HalResource[];\n}\n\n","import {Injectable} from \"@angular/core\";\nimport {Observable, Subject} from \"rxjs\";\nimport {buffer, debounceTime, filter} from \"rxjs/operators\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ResourceChangesetCommit} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\n\nexport interface HalEvent {\n id:string;\n eventType:string;\n resourceType:string;\n commit?:ResourceChangesetCommit;\n}\n\nexport interface HalCreatedEvent extends HalEvent {\n eventType:'created';\n}\n\nexport interface HalUpdatedEvent extends HalEvent {\n eventType:'updated';\n}\n\nexport interface RelatedWorkPackageEvent extends HalEvent {\n eventType:'association';\n relatedWorkPackage:string|null;\n relationType:string;\n}\n\nexport interface HalDeletedEvent extends HalEvent {\n eventType:'deleted';\n}\n\nexport type HalEventTypes =\n HalCreatedEvent|HalUpdatedEvent|RelatedWorkPackageEvent|HalDeletedEvent;\n\n@Injectable({ providedIn: 'root' })\nexport class HalEventsService {\n private _events = new Subject();\n\n /** Entire event stream */\n public events$ = this._events.asObservable();\n\n /** Aggregated events */\n public aggregated$(resourceType:string, debounceTimeInMs = 500):Observable {\n return this\n .events$\n .pipe(\n filter((event:HalEvent) => event.resourceType === resourceType),\n buffer(this.events$.pipe(debounceTime(debounceTimeInMs)))\n );\n }\n\n public push(resourceReference:HalResource|{ id:string, _type:string }, event:Partial) {\n event.id = resourceReference.id!;\n event.resourceType = resourceReference._type!;\n\n this._events.next(event as HalEvent);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, EventEmitter, Input, Output} from '@angular/core';\n\n@Component({\n selector: 'accessible-by-keyboard',\n template: `\n \n \n \n \n \n `\n})\nexport class AccessibleByKeyboardComponent {\n @Output() execute = new EventEmitter();\n @Input() isDisabled:boolean;\n @Input() linkClass:string;\n @Input() linkTitle:string;\n @Input() spanClass:string;\n @Input() linkAriaLabel:string;\n\n public handleClick(event:JQuery.TriggeredEvent) {\n if (!this.isDisabled) {\n this.execute.emit(event);\n }\n\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport type OpTableActionFactory = (i:Injector, wp:WorkPackageResource) => OpTableAction;\nexport const contextMenuTdClassName = 'wp-table--context-menu-td';\nexport const contextMenuSpanClassName = 'wp-table--context-menu-span';\nexport const contextMenuLinkClassName = 'wp-table-context-menu-link';\nexport const contextColumnIcon = 'wp-table-context-menu-icon';\n\nexport abstract class OpTableAction {\n\n @InjectField() I18n!:I18nService;\n\n constructor(readonly injector:Injector,\n readonly workPackage:WorkPackageResource) {\n }\n\n /** Identifier to uniquely identify the action */\n public abstract readonly identifier:string;\n\n /** The actual action factory to return the action element, if it can be rendered */\n public abstract buildElement():HTMLElement|null;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nexport const ANIMATION_RATE_MS = 100;\n\nexport class TopMenu {\n private hover = false;\n private menuIsOpen = false;\n\n constructor(readonly menuContainer:JQuery) {\n this.withHeadingFoldOutAtBorder();\n this.setupDropdownClick();\n this.registerEventHandlers();\n this.closeOnBodyClick();\n this.accessibility();\n this.skipContentClickListener();\n }\n\n skipContentClickListener() {\n // Skip menu on content\n jQuery('#skip-navigation--content').on('click', () => {\n // Skip to the breadcrumb or the first link in the toolbar or the first link in the content (homescreen)\n const selectors = '.first-breadcrumb-element a, .toolbar-container a:first-of-type, #content a:first-of-type';\n const visibleLink = jQuery(selectors)\n .not(':hidden')\n .first();\n\n if (visibleLink.length) {\n visibleLink.trigger('focus');\n }\n });\n }\n\n accessibility() {\n jQuery(\".drop-down > ul\").attr(\"aria-expanded\", \"false\");\n }\n\n toggleClick(dropdown:JQuery) {\n if (this.menuIsOpen) {\n if (this.isOpen(dropdown)) {\n this.closing();\n } else {\n this.open(dropdown);\n }\n } else {\n this.opening();\n this.open(dropdown);\n }\n }\n\n // somebody opens the menu via click, hover possible afterwards\n opening() {\n this.startHover();\n this.menuIsOpen = true;\n this.menuContainer.trigger(\"openedMenu\", this.menuContainer);\n }\n\n // the entire menu gets closed, no hover possible afterwards\n closing() {\n this.stopHover();\n this.closeAllItems();\n this.menuIsOpen = false;\n this.menuContainer.trigger(\"closedMenu\", this.menuContainer);\n }\n\n stopHover() {\n this.hover = false;\n this.menuContainer.removeClass(\"hover\");\n }\n\n startHover() {\n this.hover = true;\n this.menuContainer.addClass(\"hover\");\n }\n\n closeAllItems() {\n this.openDropdowns().each((ix, item) => {\n this.close(jQuery(item));\n });\n }\n\n closeOnBodyClick() {\n let self = this;\n let wrapper = document.getElementById('wrapper');\n\n if (!wrapper) {\n return;\n }\n\n wrapper.addEventListener('click', function (evt) {\n if (self.menuIsOpen && !self.openDropdowns()[0].contains(evt.target as HTMLElement)) {\n self.closing();\n }\n }, true);\n }\n\n openDropdowns() {\n return this.dropdowns().filter(\".open\");\n }\n\n dropdowns() {\n return this.menuContainer.find(\"li.drop-down\");\n }\n\n withHeadingFoldOutAtBorder() {\n var menu_start_position;\n if (this.menuContainer.next().get(0) !== undefined && (this.menuContainer.next().get(0).tagName === 'H2')) {\n menu_start_position = this.menuContainer.next().innerHeight()! + this.menuContainer.next().position().top;\n this.menuContainer.find(\"ul.menu-drop-down-container\").css({ top: menu_start_position });\n } else if (this.menuContainer.next().hasClass(\"wiki-content\") &&\n this.menuContainer.next().children().next().first().get(0) !== undefined &&\n this.menuContainer.next().children().next().first().get(0).tagName === 'H1') {\n var wiki_heading = this.menuContainer.next().children().next().first();\n menu_start_position = wiki_heading.innerHeight()! + wiki_heading.position().top;\n this.menuContainer.find(\"ul.menu-drop-down-container\").css({ top: menu_start_position });\n }\n }\n\n setupDropdownClick() {\n var self = this;\n this.dropdowns().each(function (ix, it) {\n jQuery(it).click(function () {\n self.toggleClick(jQuery(this));\n return false;\n });\n jQuery(it).on('touchstart', function (e) {\n // This shall avoid the hover event is fired,\n // which would otherwise lead to menu being closed directly after its opened.\n // Ignore clicks from within the dropdown\n if (jQuery(e.target).closest('.menu-drop-down-container').length) {\n return true;\n }\n e.preventDefault();\n jQuery(this).click();\n return false;\n });\n });\n }\n\n isOpen(dropdown:JQuery) {\n return dropdown.filter(\".open\").length === 1;\n }\n\n isClosed(dropdown:JQuery) {\n return !this.isOpen(dropdown);\n }\n\n open(dropdown:JQuery) {\n this.dontCloseWhenUsing(dropdown);\n this.closeOtherItems(dropdown);\n this.slideAndFocus(dropdown, function () {\n dropdown.trigger(\"opened\", dropdown);\n });\n }\n\n close(dropdown:JQuery, immediate?:any) {\n this.slideUp(dropdown, immediate);\n dropdown.trigger(\"closed\", dropdown);\n }\n\n closeOtherItems(dropdown:JQuery) {\n var self = this;\n this.openDropdowns().each(function (ix, it) {\n if (jQuery(it) !== jQuery(dropdown)) {\n self.close(jQuery(it), true);\n }\n });\n }\n\n dontCloseWhenUsing(dropdown:JQuery) {\n jQuery(dropdown).find(\"li\").click(function (event) {\n event.stopPropagation();\n });\n jQuery(dropdown).bind(\"mousedown mouseup click\", function (event) {\n event.stopPropagation();\n });\n }\n\n slideAndFocus(dropdown:JQuery, callback:any) {\n this.slideDown(dropdown, callback);\n this.focusFirstInputOrLink(dropdown);\n }\n\n slideDown(dropdown:JQuery, callback:any) {\n var toDrop = dropdown.find(\"> ul\");\n dropdown.addClass(\"open\");\n toDrop.slideDown(ANIMATION_RATE_MS, callback).attr(\"aria-expanded\", \"true\");\n }\n\n slideUp(dropdown:JQuery, immediate:any) {\n var toDrop = jQuery(dropdown).find(\"> ul\");\n dropdown.removeClass(\"open\");\n\n if (immediate) {\n toDrop.hide();\n } else {\n toDrop.slideUp(ANIMATION_RATE_MS);\n }\n\n toDrop.attr(\"aria-expanded\", \"false\");\n }\n\n // If there is ANY input, it will have precedence over links,\n // i.e. links will only get focussed, if there is NO input whatsoever\n focusFirstInputOrLink(dropdown:JQuery) {\n var toFocus = dropdown.find(\"ul :input:visible:first\");\n if (toFocus.length === 0) {\n toFocus = dropdown.find(\"ul a:visible:first\");\n }\n // actually a simple focus should be enough.\n // The rest is only there to work around a rendering bug in webkit (as of Oct 2011),\n // occuring mostly inside the login/signup dropdown.\n toFocus.blur();\n setTimeout(function () {\n toFocus.focus();\n }, 10);\n }\n\n registerEventHandlers() {\n const toggler = jQuery(\"#main-menu-toggle\");\n\n this.menuContainer.on(\"closeDropDown\", (event) => {\n this.close(jQuery(event.target));\n }).on(\"openDropDown\", (event) => {\n this.open(jQuery(event.target));\n }).on(\"closeMenu\", () => {\n this.closing();\n }).on(\"openMenu\", () => {\n this.open(this.dropdowns().first());\n this.opening();\n });\n\n toggler.on(\"click\", () => { // click on hamburger icon is closing other menu\n this.closing();\n });\n }\n}\n","\n \n
\n
\n \n \n
\n
\n
\n
\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {ActivityPanelBaseController} from 'core-components/wp-single-view-tabs/activity-panel/activity-base.controller';\nimport {ChangeDetectionStrategy, Component, Input} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {ActivityEntryInfo} from 'core-components/wp-single-view-tabs/activity-panel/activity-entry-info';\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\n\n@Component({\n selector: 'newest-activity-on-overview',\n templateUrl: './activity-on-overview.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class NewestActivityOnOverviewComponent extends ActivityPanelBaseController {\n @Input('workPackage') public workPackage:WorkPackageResource;\n\n public latestActivityInfo:ActivityEntryInfo[] = [];\n public trackByHref = AngularTrackingHelpers.trackByProperty('identifier');\n\n ngOnInit() {\n this.workPackageId = this.workPackage.id!;\n super.ngOnInit();\n }\n\n protected shouldShowToggler() {\n return false;\n }\n\n protected updateActivities(activities:any) {\n super.updateActivities(activities);\n this.latestActivityInfo = this.latestActivities();\n }\n\n private latestActivities(visible:number = 3) {\n\n if (this.reverse) {\n // In reverse, we already get reversed entries from API.\n // So simply take the first three\n let segment = this.unfilteredActivities.slice(0, visible);\n return segment.map((el:HalResource, i:number) => this.info(el, i));\n } else {\n // In ascending sort, take the last three items\n let segment = this.unfilteredActivities.slice(-visible);\n let startIndex = this.unfilteredActivities.length - segment.length;\n return segment.map((el:HalResource, i:number) => this.info(el, startIndex + i));\n }\n }\n}\n","\n\n
\n
\n
\n

\n
\n
\n\n \n
\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from '@angular/core';\nimport {StateService} from '@uirouter/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './overview-tab.html',\n selector: 'wp-overview-tab',\n})\nexport class WorkPackageOverviewTabComponent extends UntilDestroyedMixin {\n public workPackageId:string;\n public workPackage:WorkPackageResource;\n public tabName = this.I18n.t('js.label_latest_activity');\n\n public constructor(readonly I18n:I18nService,\n readonly $state:StateService,\n readonly apiV3Service:APIV3Service) {\n super();\n\n this.workPackageId = this.$state.params.workPackageId;\n\n this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp) => this.workPackage = wp);\n }\n}\n","\n \n
\n
\n \n
\n \n \n \n
\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n
\n
\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageCreateComponent} from 'core-components/wp-new/wp-create.component';\nimport {ChangeDetectionStrategy, Component} from '@angular/core';\n\n@Component({\n selector: 'wp-new-split-view',\n templateUrl: './wp-new-split-view.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WorkPackageNewSplitViewComponent extends WorkPackageCreateComponent {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {WorkPackageCopyController} from 'core-components/wp-copy/wp-copy.controller';\n\n@Component({\n selector: 'wp-copy-split-view',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: '../wp-new/wp-new-split-view.html'\n})\nexport class WorkPackageCopySplitViewComponent extends WorkPackageCopyController {\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageOverviewTabComponent} from 'core-components/wp-single-view-tabs/overview-tab/overview-tab.component';\nimport {WorkPackageActivityTabComponent} from 'core-components/wp-single-view-tabs/activity-panel/activity-tab.component';\nimport {WorkPackageRelationsTabComponent} from 'core-components/wp-single-view-tabs/relations-tab/relations-tab.component';\nimport {WorkPackageWatchersTabComponent} from 'core-components/wp-single-view-tabs/watchers-tab/watchers-tab.component';\nimport {WorkPackageNewSplitViewComponent} from 'core-components/wp-new/wp-new-split-view.component';\nimport {Ng2StateDeclaration} from \"@uirouter/angular\";\nimport {ComponentType} from \"@angular/cdk/overlay\";\nimport {WorkPackageCopySplitViewComponent} from \"core-components/wp-copy/wp-copy-split-view.component\";\n\n/**\n * Return a set of routes for a split view mounted under the given base route,\n * which must be a grandchild of a PartitionedQuerySpacePageComponent.\n *\n * Example: base route = foo.bar\n *\n * Split view will be created at\n *\n * foo.bar.details\n * foo.bar.details.activity\n * foo.bar.details.relations\n * foo.bar.details.watchers\n *\n * NOTE: All parameters here must either be `export const` or literal strings,\n * otherwise AOT will not be able to look them up. This might result in missing routes.\n *\n * @param baseRoute The base route to mount under\n * @param showComponent The split view component to mount\n */\nexport function makeSplitViewRoutes(baseRoute:string,\n menuItemClass:string|undefined,\n showComponent:ComponentType,\n newComponent:ComponentType = WorkPackageNewSplitViewComponent,\n makeFullWidth?:boolean,\n routeName = baseRoute):Ng2StateDeclaration[] {\n // makeFullWidth configuration\n const views:any = makeFullWidth ?\n {'content-left@^.^': { component: showComponent }} :\n {'content-right@^.^': { component: showComponent }};\n const partition = makeFullWidth ? '-left-only' : '-split';\n\n return [\n {\n name: routeName + '.details',\n url: '/details/{workPackageId:[0-9]+}',\n redirectTo: routeName + '.details.overview',\n reloadOnSearch: false,\n data: {\n bodyClasses: 'router--work-packages-partitioned-split-view-details',\n menuItem: menuItemClass,\n // Remember the base route so we can route back to it anywhere\n baseRoute: baseRoute,\n newRoute: routeName + '.new',\n partition,\n },\n // Retarget and by that override the grandparent views\n // https://ui-router.github.io/guide/views#relative-parent-state\n views,\n },\n {\n name: routeName + '.details.overview',\n url: '/overview',\n component: WorkPackageOverviewTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: routeName + '.details'\n }\n },\n {\n name: routeName + '.details.activity',\n url: '/activity',\n component: WorkPackageActivityTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: routeName + '.details'\n }\n },\n {\n name: routeName + '.details.relations',\n url: '/relations',\n component: WorkPackageRelationsTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: routeName + '.details'\n }\n },\n {\n name: routeName + '.details.watchers',\n url: '/watchers',\n component: WorkPackageWatchersTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: routeName + '.details'\n }\n },\n // Split create route\n {\n name: routeName + '.new',\n url: '/create_new?{type:[0-9]+}&{parent_id:[0-9]+}',\n reloadOnSearch: false,\n data: {\n partition: '-split',\n allowMovingInEditMode: true,\n bodyClasses: 'router--work-packages-partitioned-split-view-new',\n // Remember the base route so we can route back to it anywhere\n baseRoute: baseRoute,\n parent: baseRoute\n },\n views: {\n // Retarget and by that override the grandparent views\n // https://ui-router.github.io/guide/views#relative-parent-state\n 'content-right@^.^': { component: newComponent }\n }\n },\n // Split copy route\n {\n name: routeName + '.copy',\n url: '/details/{copiedFromWorkPackageId:[0-9]+}/copy',\n views: {\n 'content-right@^.^': { component: WorkPackageCopySplitViewComponent }\n },\n reloadOnSearch: false,\n data: {\n baseRoute: baseRoute,\n parent: baseRoute,\n allowMovingInEditMode: true,\n bodyClasses: 'router--work-packages-partitioned-split-view',\n menuItem: menuItemClass,\n partition: '-split'\n },\n },\n ];\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {HalLink} from \"core-app/modules/hal/hal-link/hal-link\";\n\n@Injectable()\nexport class BcfPathHelperService {\n constructor(readonly pathHelper:PathHelperService) {\n }\n\n public projectImportIssuePath(projectIdentifier:string) {\n return this.pathHelper.projectPath(projectIdentifier) + '/issues/upload';\n }\n\n public projectExportIssuesPath(projectIdentifier:string, filters:string|null) {\n if (filters) {\n return this.pathHelper.projectPath(projectIdentifier) + '/work_packages.bcf?filters=' + filters;\n } else {\n return this.pathHelper.projectPath(projectIdentifier) + '/work_packages.bcf';\n }\n }\n\n public snapshotPath(viewpoint:HalLink) {\n return viewpoint.href + '/snapshot';\n }\n}\n","var map = {\n\t\"./af.js\": [\n\t\t\"NTxu\",\n\t\t142\n\t],\n\t\"./ar.js\": [\n\t\t\"sz2f\",\n\t\t143\n\t],\n\t\"./az.js\": [\n\t\t\"cJhg\",\n\t\t144\n\t],\n\t\"./be.js\": [\n\t\t\"ytP5\",\n\t\t145\n\t],\n\t\"./bg.js\": [\n\t\t\"wq8R\",\n\t\t146\n\t],\n\t\"./bn.js\": [\n\t\t\"xax0\",\n\t\t147\n\t],\n\t\"./bs.js\": [\n\t\t\"Mn6t\",\n\t\t148\n\t],\n\t\"./ca.js\": [\n\t\t\"bFR9\",\n\t\t149\n\t],\n\t\"./cs.js\": [\n\t\t\"uT64\",\n\t\t150\n\t],\n\t\"./cy.js\": [\n\t\t\"XBH+\",\n\t\t151\n\t],\n\t\"./da.js\": [\n\t\t\"oqPE\",\n\t\t152\n\t],\n\t\"./de-AT.js\": [\n\t\t\"WrCB\",\n\t\t153\n\t],\n\t\"./de-CH.js\": [\n\t\t\"oai4\",\n\t\t154\n\t],\n\t\"./de-DE.js\": [\n\t\t\"tJ4f\",\n\t\t155\n\t],\n\t\"./de.js\": [\n\t\t\"iFlR\",\n\t\t156\n\t],\n\t\"./el-CY.js\": [\n\t\t\"TPLK\",\n\t\t157\n\t],\n\t\"./el.js\": [\n\t\t\"k48E\",\n\t\t158\n\t],\n\t\"./en-AU.js\": [\n\t\t\"M4sl\",\n\t\t159\n\t],\n\t\"./en-CA.js\": [\n\t\t\"xfKs\",\n\t\t160\n\t],\n\t\"./en-CY.js\": [\n\t\t\"ufn/\",\n\t\t161\n\t],\n\t\"./en-GB.js\": [\n\t\t\"r3/2\",\n\t\t162\n\t],\n\t\"./en-IE.js\": [\n\t\t\"u1k6\",\n\t\t163\n\t],\n\t\"./en-IN.js\": [\n\t\t\"8VPa\",\n\t\t164\n\t],\n\t\"./en-NZ.js\": [\n\t\t\"THql\",\n\t\t165\n\t],\n\t\"./en-US.js\": [\n\t\t\"KW4L\",\n\t\t166\n\t],\n\t\"./en-ZA.js\": [\n\t\t\"Wc4I\",\n\t\t167\n\t],\n\t\"./en.js\": [\n\t\t\"CQue\",\n\t\t168\n\t],\n\t\"./eo.js\": [\n\t\t\"zj11\",\n\t\t169\n\t],\n\t\"./es-419.js\": [\n\t\t\"AuO9\",\n\t\t170\n\t],\n\t\"./es-AR.js\": [\n\t\t\"kEy0\",\n\t\t171\n\t],\n\t\"./es-CL.js\": [\n\t\t\"ft4/\",\n\t\t172\n\t],\n\t\"./es-CO.js\": [\n\t\t\"s2os\",\n\t\t173\n\t],\n\t\"./es-CR.js\": [\n\t\t\"2jQJ\",\n\t\t174\n\t],\n\t\"./es-EC.js\": [\n\t\t\"U6Bt\",\n\t\t175\n\t],\n\t\"./es-ES.js\": [\n\t\t\"ZPhd\",\n\t\t176\n\t],\n\t\"./es-MX.js\": [\n\t\t\"06FW\",\n\t\t177\n\t],\n\t\"./es-NI.js\": [\n\t\t\"a+FD\",\n\t\t178\n\t],\n\t\"./es-PA.js\": [\n\t\t\"QXC7\",\n\t\t179\n\t],\n\t\"./es-PE.js\": [\n\t\t\"I5eF\",\n\t\t180\n\t],\n\t\"./es-US.js\": [\n\t\t\"pDd2\",\n\t\t181\n\t],\n\t\"./es-VE.js\": [\n\t\t\"feyl\",\n\t\t182\n\t],\n\t\"./es.js\": [\n\t\t\"0MJg\",\n\t\t183\n\t],\n\t\"./et.js\": [\n\t\t\"Cagy\",\n\t\t184\n\t],\n\t\"./eu.js\": [\n\t\t\"J9ic\",\n\t\t185\n\t],\n\t\"./fa.js\": [\n\t\t\"eWY+\",\n\t\t186\n\t],\n\t\"./fi.js\": [\n\t\t\"/z4B\",\n\t\t187\n\t],\n\t\"./fil.js\": [\n\t\t\"PQTg\",\n\t\t188\n\t],\n\t\"./fr-CA.js\": [\n\t\t\"kmLF\",\n\t\t189\n\t],\n\t\"./fr-CH.js\": [\n\t\t\"bJRw\",\n\t\t190\n\t],\n\t\"./fr-FR.js\": [\n\t\t\"O+Vq\",\n\t\t191\n\t],\n\t\"./fr.js\": [\n\t\t\"S399\",\n\t\t192\n\t],\n\t\"./gl.js\": [\n\t\t\"GRki\",\n\t\t193\n\t],\n\t\"./he.js\": [\n\t\t\"R/Q/\",\n\t\t194\n\t],\n\t\"./hi-IN.js\": [\n\t\t\"zRlf\",\n\t\t195\n\t],\n\t\"./hi.js\": [\n\t\t\"TOBP\",\n\t\t196\n\t],\n\t\"./hr.js\": [\n\t\t\"ED+y\",\n\t\t197\n\t],\n\t\"./hu.js\": [\n\t\t\"a/eb\",\n\t\t198\n\t],\n\t\"./id.js\": [\n\t\t\"u8bJ\",\n\t\t199\n\t],\n\t\"./is.js\": [\n\t\t\"pUlV\",\n\t\t200\n\t],\n\t\"./it-CH.js\": [\n\t\t\"M295\",\n\t\t201\n\t],\n\t\"./it.js\": [\n\t\t\"VfVk\",\n\t\t202\n\t],\n\t\"./ja.js\": [\n\t\t\"EQXh\",\n\t\t203\n\t],\n\t\"./ka.js\": [\n\t\t\"+Ljo\",\n\t\t204\n\t],\n\t\"./km.js\": [\n\t\t\"WMQS\",\n\t\t205\n\t],\n\t\"./kn.js\": [\n\t\t\"8qXJ\",\n\t\t206\n\t],\n\t\"./ko.js\": [\n\t\t\"QfUy\",\n\t\t207\n\t],\n\t\"./lb.js\": [\n\t\t\"9q38\",\n\t\t208\n\t],\n\t\"./lo.js\": [\n\t\t\"AGs6\",\n\t\t209\n\t],\n\t\"./lt.js\": [\n\t\t\"D+E8\",\n\t\t210\n\t],\n\t\"./lv.js\": [\n\t\t\"TGF+\",\n\t\t211\n\t],\n\t\"./mg.js\": [\n\t\t\"4VZG\",\n\t\t212\n\t],\n\t\"./mk.js\": [\n\t\t\"VzW1\",\n\t\t213\n\t],\n\t\"./ml.js\": [\n\t\t\"Nm61\",\n\t\t214\n\t],\n\t\"./mn.js\": [\n\t\t\"aew7\",\n\t\t215\n\t],\n\t\"./mr-IN.js\": [\n\t\t\"Ivdp\",\n\t\t216\n\t],\n\t\"./ms.js\": [\n\t\t\"PIEu\",\n\t\t217\n\t],\n\t\"./nb.js\": [\n\t\t\"NgvQ\",\n\t\t218\n\t],\n\t\"./ne.js\": [\n\t\t\"2RGT\",\n\t\t219\n\t],\n\t\"./nl.js\": [\n\t\t\"Vw9A\",\n\t\t220\n\t],\n\t\"./nn.js\": [\n\t\t\"3tCn\",\n\t\t221\n\t],\n\t\"./no.js\": [\n\t\t\"i6Wc\",\n\t\t222\n\t],\n\t\"./oc.js\": [\n\t\t\"Peea\",\n\t\t223\n\t],\n\t\"./or.js\": [\n\t\t\"7kX+\",\n\t\t224\n\t],\n\t\"./pa.js\": [\n\t\t\"OB7H\",\n\t\t225\n\t],\n\t\"./pl.js\": [\n\t\t\"023k\",\n\t\t226\n\t],\n\t\"./pt-BR.js\": [\n\t\t\"GZMl\",\n\t\t227\n\t],\n\t\"./pt.js\": [\n\t\t\"03fs\",\n\t\t228\n\t],\n\t\"./rm.js\": [\n\t\t\"1n3U\",\n\t\t229\n\t],\n\t\"./ro.js\": [\n\t\t\"1Oix\",\n\t\t230\n\t],\n\t\"./ru.js\": [\n\t\t\"ue6V\",\n\t\t231\n\t],\n\t\"./sk.js\": [\n\t\t\"QBQ5\",\n\t\t232\n\t],\n\t\"./sl.js\": [\n\t\t\"0ek5\",\n\t\t233\n\t],\n\t\"./sq.js\": [\n\t\t\"GouJ\",\n\t\t234\n\t],\n\t\"./sr.js\": [\n\t\t\"iiJJ\",\n\t\t235\n\t],\n\t\"./sv-SE.js\": [\n\t\t\"w/km\",\n\t\t236\n\t],\n\t\"./sv.js\": [\n\t\t\"rcLn\",\n\t\t237\n\t],\n\t\"./sw.js\": [\n\t\t\"ci3q\",\n\t\t238\n\t],\n\t\"./ta.js\": [\n\t\t\"HgV+\",\n\t\t239\n\t],\n\t\"./te.js\": [\n\t\t\"icKA\",\n\t\t240\n\t],\n\t\"./th.js\": [\n\t\t\"Uvgq\",\n\t\t241\n\t],\n\t\"./tl.js\": [\n\t\t\"VyBs\",\n\t\t242\n\t],\n\t\"./tr.js\": [\n\t\t\"5nPu\",\n\t\t243\n\t],\n\t\"./tt.js\": [\n\t\t\"hEsF\",\n\t\t244\n\t],\n\t\"./ug.js\": [\n\t\t\"JCdo\",\n\t\t245\n\t],\n\t\"./uk.js\": [\n\t\t\"4ZxZ\",\n\t\t246\n\t],\n\t\"./ur.js\": [\n\t\t\"IzNn\",\n\t\t247\n\t],\n\t\"./uz.js\": [\n\t\t\"2yAK\",\n\t\t248\n\t],\n\t\"./vi.js\": [\n\t\t\"mhGZ\",\n\t\t249\n\t],\n\t\"./wo.js\": [\n\t\t\"JViR\",\n\t\t250\n\t],\n\t\"./zh-CN.js\": [\n\t\t\"L27e\",\n\t\t251\n\t],\n\t\"./zh-HK.js\": [\n\t\t\"J9h6\",\n\t\t252\n\t],\n\t\"./zh-TW.js\": [\n\t\t\"FEz5\",\n\t\t253\n\t],\n\t\"./zh-YUE.js\": [\n\t\t\"tZgQ\",\n\t\t254\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tvar ids = map[req], id = ids[0];\n\treturn __webpack_require__.e(ids[1]).then(function() {\n\t\treturn __webpack_require__.t(id, 7);\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = \"0Int\";\nmodule.exports = webpackAsyncContext;","import {Injector} from '@angular/core';\nimport {States} from '../../states.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {tdClassName} from './cell-builder';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {QueryColumn} from '../../wp-query/query-column';\nimport {WorkPackageRelationsService} from '../../wp-relations/wp-relations.service';\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport const relationCellTdClassName = 'wp-table--relation-cell-td';\nexport const relationCellIndicatorClassName = 'wp-table--relation-indicator';\n\nexport class RelationCellbuilder {\n\n @InjectField() states:States;\n @InjectField() wpRelations:WorkPackageRelationsService;\n @InjectField() wpTableRelationColumns:WorkPackageViewRelationColumnsService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public build(workPackage:WorkPackageResource, column:QueryColumn) {\n const td = document.createElement('td');\n td.classList.add(tdClassName, relationCellTdClassName, column.id);\n td.dataset['columnId'] = column.id;\n\n // Get current expansion and value state\n const expanded = this.wpTableRelationColumns.getExpandFor(workPackage.id!) === column.id;\n const relationState = this.wpRelations.state(workPackage.id!).value;\n const relations = this.wpTableRelationColumns.relationsForColumn(workPackage,\n relationState,\n column);\n\n const indicator = this.renderIndicator();\n const badge = this.renderBadge(relations);\n\n if (expanded) {\n td.classList.add('-expanded');\n }\n\n if (relations.length > 0) {\n td.appendChild(badge);\n td.appendChild(indicator);\n }\n\n return td;\n }\n\n private renderIndicator() {\n const indicator = document.createElement('span');\n indicator.classList.add(relationCellIndicatorClassName);\n indicator.setAttribute('aria-hidden', 'true');\n indicator.setAttribute('tabindex', '0');\n\n return indicator;\n }\n\n private renderBadge(relations:RelationResource[]) {\n const badge = document.createElement('span');\n badge.classList.add('wp-table--relation-count');\n\n badge.textContent = '' + relations.length;\n badge.classList.add('badge', '-border-only');\n\n return badge;\n }\n}\n\n","import {Inject, Injectable} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {TabInterface} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {WpTableConfigurationService} from 'core-components/wp-table/configuration-modal/wp-table-configuration.service';\nimport {QueryConfigurationLocals} from 'core-components/wp-table/external-configuration/external-query-configuration.component';\nimport {OpQueryConfigurationLocalsToken} from \"core-components/wp-table/external-configuration/external-query-configuration.constants\";\n\n@Injectable()\nexport class RestrictedWpTableConfigurationService extends WpTableConfigurationService {\n\n constructor(@Inject(OpQueryConfigurationLocalsToken) readonly locals:QueryConfigurationLocals,\n readonly I18n:I18nService) {\n super(I18n);\n }\n\n public get tabs():TabInterface[] {\n const disabledTabs = this.locals.disabledTabs || {};\n\n return this\n ._tabs\n .map(el => {\n const reason = disabledTabs[el.name];\n if (reason != null) {\n el.disableBecause = reason;\n }\n\n return el;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nexport namespace LinkHandling {\n\n export function isClickedWithModifier(event:MouseEvent|JQuery.TriggeredEvent) {\n const modifier = event.ctrlKey || event.shiftKey || event.metaKey;\n const middleButton = event.button === 1;\n\n return modifier || middleButton;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageViewBaseService} from './wp-view-base.service';\nimport {Injectable} from '@angular/core';\nimport {WorkPackageViewGroupByService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service';\nimport {IsolatedQuerySpace} from 'core-app/modules/work_packages/query-space/isolated-query-space';\nimport {take} from 'rxjs/operators';\nimport {GroupObject, WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {QuerySchemaResource} from 'core-app/modules/hal/resources/query-schema-resource';\nimport {QueryGroupByResource} from 'core-app/modules/hal/resources/query-group-by-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {SchemaCacheService} from 'core-components/schemas/schema-cache.service';\n\n@Injectable()\nexport class WorkPackageViewCollapsedGroupsService extends WorkPackageViewBaseService {\n readonly wpTypesToShowInCollapsedGroupHeaders:((wp:WorkPackageResource) => boolean)[];\n readonly groupTypesWithHeaderCellsWhenCollapsed = ['project'];\n\n get config():IGroupsCollapseEvent {\n return this.updatesState.getValueOr(this.getDefaultState());\n }\n\n get currentGroups():GroupObject[] {\n return this.querySpace.groups.value!;\n }\n\n get allGroupsAreCollapsed():boolean {\n return this.config.allGroupsAreCollapsed;\n }\n\n get allGroupsAreExpanded():boolean {\n return this.config.allGroupsAreExpanded;\n }\n\n get currentGroupedBy():QueryGroupByResource|null {\n return this.workPackageViewGroupByService.current;\n }\n\n constructor(\n protected readonly querySpace:IsolatedQuerySpace,\n readonly workPackageViewGroupByService:WorkPackageViewGroupByService,\n private schemaCacheService:SchemaCacheService,\n ) {\n super(querySpace);\n this.wpTypesToShowInCollapsedGroupHeaders = [this.isMilestone];\n }\n\n // Every time the groupedBy changes, this services is initialized\n private getDefaultState():IGroupsCollapseEvent {\n return {\n state: this.querySpace.collapsedGroups.value || {},\n allGroupsChanged: false,\n lastChangedGroup: null,\n groupedBy: this.currentGroupedBy?.id || null,\n ...this.getAllGroupsCollapsedState(this.currentGroups, this.querySpace.collapsedGroups.value!),\n };\n }\n\n isMilestone = (workPackage:WorkPackageResource):boolean => {\n return this.schemaCacheService.of(workPackage)?.isMilestone;\n }\n\n toggleGroupCollapseState(groupIdentifier:string):void {\n const newCollapsedState = !this.config.state[groupIdentifier];\n const state = {\n ...this.config.state,\n [groupIdentifier]: newCollapsedState\n };\n const newState = {\n ...this.config,\n state,\n lastChangedGroup: groupIdentifier,\n ...this.getAllGroupsCollapsedState(this.currentGroups, state),\n };\n\n this.update(newState);\n }\n\n setAllGroupsCollapseStateTo(collapsedState:boolean):void {\n const groupUpdatedState = this.currentGroups.reduce((updatedState:{[key:string]:boolean}, group) => {\n return {\n ...updatedState,\n [group.identifier]:collapsedState,\n };\n }, {});\n const newState = {\n ...this.config,\n state: {\n ...this.config.state,\n ...groupUpdatedState,\n },\n lastChangedGroup: null,\n allGroupsAreCollapsed: collapsedState,\n allGroupsAreExpanded: !collapsedState,\n allGroupsChanged: true,\n };\n\n this.update(newState);\n }\n\n getAllGroupsCollapsedState(groups:GroupObject[], currentCollapsedGroupsState:IGroupsCollapseEvent['state']) {\n let allGroupsAreCollapsed = false;\n let allGroupsAreExpanded = true;\n\n if (currentCollapsedGroupsState && groups?.length) {\n const firstGroupIdentifier = groups[0].identifier;\n const firstGroupCollapsedState = currentCollapsedGroupsState[firstGroupIdentifier];\n const allGroupsHaveTheSameCollapseState = groups.every((group) => {\n return currentCollapsedGroupsState[group.identifier] != null &&\n currentCollapsedGroupsState[group.identifier] === currentCollapsedGroupsState[firstGroupIdentifier];\n });\n\n allGroupsAreCollapsed = allGroupsHaveTheSameCollapseState && firstGroupCollapsedState;\n allGroupsAreExpanded = allGroupsHaveTheSameCollapseState && !firstGroupCollapsedState;\n }\n\n return {allGroupsAreCollapsed, allGroupsAreExpanded};\n }\n\n initialize(query:QueryResource, results:WorkPackageCollectionResource, schema?:QuerySchemaResource) {\n // When this service is initialized (first time the table is loaded and very time the groupBy changes),\n // we need to wait until the table is ready to emit the collapseStatus. Otherwise the groups are not\n // ready in the DOM and can't be collapsed/expanded.\n this.querySpace.tableRendered.values$().pipe(take(1)).subscribe(() => this.update({ ...this.config, allGroupsChanged: true }));\n }\n\n valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource) {\n return this.getDefaultState();\n }\n\n applyToQuery(query:QueryResource) { return; }\n}\n","import {Injectable} from \"@angular/core\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {\n QueryFilterInstanceSchemaResource,\n QueryFilterInstanceSchemaResourceLinks\n} from \"core-app/modules/hal/resources/query-filter-instance-schema-resource\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\n\n@Injectable()\nexport class QueryFiltersService {\n constructor(protected schemaCache:SchemaCacheService) {\n }\n\n /**\n * Get the matching schema of the filter resource\n * from the schema\n */\n private getFilterSchema(filter:QueryFilterInstanceResource, form:QueryFormResource):QueryFilterInstanceSchemaResource|undefined {\n const available = form.$embedded.schema.filtersSchemas.elements;\n return _.find(available, schema => schema.allowedFilterValue.href === filter.filter.href);\n }\n\n /**\n * Prepares the schemas of each filter to be readily placed to make alterations\n * to the filter based on the filter e.g. when sending an updated filter to the backend.\n * @param query\n * @param form\n */\n public mapSchemasIntoFilters(query:QueryResource, form:QueryFormResource) {\n query.filters.forEach(filter => {\n let schema = this.getFilterSchema(filter, form)!;\n filter.$links.schema = schema.$links.self;\n this.schemaCache.update(filter, schema);\n });\n }\n\n public setSchemas(schemas:CollectionResource) {\n schemas.elements.forEach(schema => {\n this.schemaCache.updateValue(schema.$links.self.href!, schema);\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {Directive, ElementRef} from \"@angular/core\";\nimport {OpContextMenuTrigger} from \"core-components/op-context-menu/handlers/op-context-menu-trigger.directive\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {States} from \"core-components/states.service\";\nimport {FormResource} from 'core-app/modules/hal/resources/form-resource';\n\n@Directive({\n selector: '[wpCreateSettingsMenu]'\n})\nexport class WorkPackageCreateSettingsMenuDirective extends OpContextMenuTrigger {\n\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly states:States,\n readonly halEditing:HalResourceEditingService) {\n\n super(elementRef, opContextMenu);\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n const wp = this.states.workPackages.get('new').value;\n\n if (wp) {\n const change = this.halEditing.changeFor(wp);\n change.getForm().then(\n (loadedForm:FormResource) => {\n this.buildItems(loadedForm);\n this.opContextMenu.show(this, evt);\n }\n );\n }\n }\n\n /**\n * Positioning args for jquery-ui position.\n *\n * @param {Event} openerEvent\n */\n public positionArgs(evt:JQuery.TriggeredEvent) {\n let additionalPositionArgs = {\n my: 'right top',\n at: 'right bottom'\n };\n\n let position = super.positionArgs(evt);\n _.assign(position, additionalPositionArgs);\n\n return position;\n }\n\n private buildItems(form:FormResource) {\n this.items = [];\n const configureFormLink = form.configureForm;\n const queryCustomFields = form.customFields;\n\n if (queryCustomFields) {\n this.items.push({\n href: queryCustomFields.href,\n icon: 'icon-custom-fields',\n linkText: queryCustomFields.name,\n onClick: () => false\n });\n }\n\n if (configureFormLink) {\n this.items.push({\n href: configureFormLink.href,\n icon: 'icon-settings3',\n linkText: configureFormLink.name,\n onClick: () => false\n });\n }\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {StateService} from \"@uirouter/angular\";\n\n/**\n * Returns the path to the split view based on the current route\n *\n * @param state State service\n */\nexport function splitViewRoute(state:StateService):string {\n const baseRoute = state.current.data.baseRoute || '';\n return baseRoute + '.details';\n}\n","import {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {States} from 'core-components/states.service';\nimport {BannersService} from \"core-app/modules/common/enterprise/banners.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {QuerySchemaResource} from \"core-app/modules/hal/resources/query-schema-resource\";\nimport {WorkPackageViewHighlight} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-highlight\";\n\n@Injectable()\nexport class WorkPackageViewHighlightingService extends WorkPackageQueryStateService {\n public constructor(readonly states:States,\n readonly Banners:BannersService,\n readonly querySpace:IsolatedQuerySpace) {\n super(querySpace);\n }\n\n initialize(query:QueryResource, results:WorkPackageCollectionResource, schema?:QuerySchemaResource) {\n super.initialize(query, results, schema);\n }\n\n /**\n * Decides whether we want to inline highlight the given field name.\n *\n * @param name A display field name such as 'status', 'priority'.\n */\n public shouldHighlightInline(name:string):boolean {\n // 1. Are we in inline mode or unable to render?\n if (!this.isInline || this.Banners.eeShowBanners) {\n return false;\n }\n\n // 2. Is selected attributes === undefined or empty Array?\n if (this.current.selectedAttributes === undefined || this.current.selectedAttributes === []) {\n return true;\n }\n\n // 3. Is name in selected attributes ?\n return !!_.find(this.current.selectedAttributes, (attr:HalResource) => attr.id === name);\n }\n\n public get current():WorkPackageViewHighlight {\n let value = this.lastUpdatedState.getValueOr({ mode: 'inline' } as WorkPackageViewHighlight);\n return this.filteredValue(value);\n }\n\n public get isInline() {\n return this.current.mode === 'inline';\n }\n\n public get isDisabled() {\n return this.current.mode === 'none';\n }\n\n public update(value:WorkPackageViewHighlight) {\n super.update(this.filteredValue(value));\n }\n\n public valueFromQuery(query:QueryResource):WorkPackageViewHighlight {\n const highlight = { mode: query.highlightingMode || 'inline', selectedAttributes: query.highlightedAttributes };\n return this.filteredValue(highlight);\n }\n\n public hasChanged(query:QueryResource) {\n return query.highlightingMode !== this.current.mode ||\n !_.isEqual(query.highlightedAttributes, this.current.selectedAttributes);\n }\n\n public applyToQuery(query:QueryResource):boolean {\n const current = this.current;\n query.highlightingMode = current.mode;\n\n query.highlightedAttributes = current.selectedAttributes;\n\n return false;\n }\n\n private filteredValue(value:WorkPackageViewHighlight):WorkPackageViewHighlight {\n if (_.isEmpty(value.selectedAttributes)) {\n value.selectedAttributes = undefined;\n }\n\n this.Banners.conditional(() => {\n value.mode = 'none';\n value.selectedAttributes = undefined;\n });\n\n return value;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpContextMenuItem} from 'core-components/op-context-menu/op-context-menu.types';\nimport {StateService} from '@uirouter/core';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {Directive, ElementRef, Input, OnInit} from \"@angular/core\";\nimport {LinkHandling} from \"core-app/modules/common/link-handling/link-handling\";\nimport {OpContextMenuTrigger} from \"core-components/op-context-menu/handlers/op-context-menu-trigger.directive\";\nimport {TypeResource} from 'core-app/modules/hal/resources/type-resource';\nimport {Highlighting} from 'core-app/components/wp-fast-table/builders/highlighting/highlighting.functions';\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {WorkPackageCreateService} from 'core-components/wp-new/wp-create.service';\n\n@Directive({\n selector: '[opTypesCreateDropdown]'\n})\nexport class OpTypesContextMenuDirective extends OpContextMenuTrigger {\n @Input('projectIdentifier') public projectIdentifier:string|null|undefined;\n @Input('stateName') public stateName:string;\n @Input('dropdownActive') active:boolean;\n\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly browserDetector:BrowserDetector,\n readonly wpCreate:WorkPackageCreateService,\n readonly $state:StateService) {\n super(elementRef, opContextMenu);\n }\n\n ngAfterViewInit():void {\n super.ngAfterViewInit();\n\n if (!this.active) {\n return;\n }\n\n // Force full-view create if in mobile view\n if (this.browserDetector.isMobile) {\n this.stateName = 'work-packages.new';\n }\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n this\n .wpCreate\n .getEmptyForm(this.projectIdentifier)\n .then(form => {\n this.buildItems(form.schema.type.allowedValues);\n this.opContextMenu.show(this, evt);\n });\n }\n\n public get locals():{ showAnchorRight?:boolean, contextMenuId?:string, items:OpContextMenuItem[] } {\n return {\n items: this.items,\n contextMenuId: 'types-context-menu'\n };\n }\n\n private buildItems(types:TypeResource[]) {\n this.items = types.map((type:TypeResource) => {\n return {\n disabled: false,\n linkText: type.name,\n href: this.$state.href(this.stateName, { type: type.id! }),\n ariaLabel: type.name,\n class: Highlighting.inlineClass('type', type.id!),\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (LinkHandling.isClickedWithModifier($event)) {\n return false;\n }\n\n this.$state.go(this.stateName, { type: type.id });\n return true;\n }\n };\n });\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {StateService, TransitionService} from '@uirouter/core';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {Observable} from \"rxjs\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\n@Component({\n selector: 'wp-create-button',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './wp-create-button.html'\n})\nexport class WorkPackageCreateButtonComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n @Input('allowed') allowedWhen:string[];\n @Input('stateName$') stateName$:Observable;\n\n allowed:boolean;\n disabled:boolean\n projectIdentifier:string|null;\n types:any;\n transitionUnregisterFn:Function;\n\n text = {\n createWithDropdown: this.I18n.t('js.work_packages.create.button'),\n createButton: this.I18n.t('js.label_work_package'),\n explanation: this.I18n.t('js.label_create_work_package')\n };\n\n constructor(readonly $state:StateService,\n readonly currentProject:CurrentProjectService,\n readonly authorisationService:AuthorisationService,\n readonly transition:TransitionService,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit() {\n this.projectIdentifier = this.currentProject.identifier;\n\n // Find the first permission that is allowed\n this.authorisationService\n .observeUntil(componentDestroyed(this))\n .subscribe(() => {\n this.allowed = !!this\n .allowedWhen\n .find(combined => {\n let [module, permission] = combined.split('.');\n return this.authorisationService.can(module, permission);\n });\n\n this.updateDisabledState();\n });\n\n\n this.transitionUnregisterFn = this.transition.onSuccess({}, this.updateDisabledState.bind(this));\n }\n\n ngOnDestroy():void {\n super.ngOnDestroy();\n this.transitionUnregisterFn();\n }\n\n private updateDisabledState() {\n this.disabled = !this.allowed || this.$state.includes('**.new');\n this.cdRef.detectChanges();\n }\n}\n","
\n \n
\n","import {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport { ElementRef, Injector, OnInit, Directive } from \"@angular/core\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {Subject} from \"rxjs\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\n\n@Directive()\nexport abstract class WorkPackageCommentFieldHandler extends EditFieldHandler implements OnInit {\n public fieldName = 'comment';\n public handler = this;\n public active = false;\n public inEditMode = false;\n public inFlight = false;\n\n public change:WorkPackageChangeset;\n\n // Destroy events\n public onDestroy = new Subject();\n\n constructor(protected elementRef:ElementRef,\n protected injector:Injector) {\n super();\n }\n\n public ngOnInit() {\n this.change = new WorkPackageChangeset(this.workPackage);\n }\n\n /**\n * Handle saving the comment\n */\n public abstract handleUserSubmit():Promise;\n\n public abstract get workPackage():WorkPackageResource;\n\n public reset(withText:string = '') {\n if (withText.length > 0) {\n withText += '\\n';\n }\n\n this.change.setValue('comment' , { raw: withText });\n }\n\n public get schema():IFieldSchema {\n return {\n name: I18n.t('js.label_comment'),\n writable: true,\n required: false,\n type: '_comment',\n hasDefault: false\n };\n }\n\n public get rawComment() {\n return _.get(this.commentValue, 'raw', '');\n }\n\n public get commentValue() {\n return this.change.value('comment');\n }\n\n public handleUserCancel() {\n this.deactivate(true);\n }\n\n public activate(withText?:string) {\n this.active = true;\n this.reset(withText);\n }\n\n deactivate(focus:boolean):void {\n this.active = false;\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n focus():void {\n const trigger = this.elementRef.nativeElement.querySelector('.inplace-editing--trigger-container');\n trigger && trigger.focus();\n }\n\n onFocusOut():void {\n }\n\n handleUserKeydown(event:JQuery.TriggeredEvent, onlyCancel?:boolean):void {\n }\n\n isChanged():boolean {\n return false;\n }\n\n stopPropagation(evt:JQuery.TriggeredEvent):boolean {\n return false;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\n\n@Component({\n templateUrl: './wp-edit-actions-bar.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-edit-actions-bar',\n})\nexport class WorkPackageEditActionsBarComponent {\n @Output('onSave') public onSave = new EventEmitter();\n @Output('onCancel') public onCancel = new EventEmitter();\n public _saving:boolean = false;\n\n public text = {\n save: this.I18n.t('js.button_save'),\n cancel: this.I18n.t('js.button_cancel')\n };\n\n constructor(private I18n:I18nService,\n private editForm:EditFormComponent,\n private cdRef:ChangeDetectorRef) {\n }\n\n public set saving(active:boolean) {\n this._saving = active;\n this.cdRef.detectChanges();\n }\n\n public get saving() {\n return this._saving;\n }\n\n public save():void {\n if (this.saving) {\n return;\n }\n\n this.saving = true;\n this.editForm\n .submit()\n .then(() => {\n this.saving = false;\n this.onSave.emit();\n })\n .catch(() => {\n this.saving = false;\n });\n }\n\n public cancel():void {\n this.editForm.cancel();\n this.onCancel.emit();\n }\n}\n","
\n \n \n \n \n \n \n \n \n
\n","\n \n \n \n \n \n \n \n \n\n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, EventEmitter, Output} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageRelationsHierarchyService} from 'core-app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Component({\n templateUrl: './wp-breadcrumb-parent.html',\n selector: 'wp-breadcrumb-parent',\n})\nexport class WorkPackageBreadcrumbParentComponent {\n @Input('workPackage') workPackage:WorkPackageResource;\n @Output('onSwitch') onSwitch = new EventEmitter();\n\n public isSaving = false;\n public text = {\n edit_parent: this.I18n.t('js.relation_buttons.change_parent'),\n set_or_remove_parent: this.I18n.t('js.relations_autocomplete.parent_placeholder'),\n remove_parent: this.I18n.t('js.relation_buttons.remove_parent'),\n set_parent: this.I18n.t('js.relation_buttons.set_parent'),\n };\n\n private editing:boolean;\n\n public constructor(\n protected readonly I18n:I18nService,\n protected readonly wpRelationsHierarchy:WorkPackageRelationsHierarchyService,\n protected readonly notificationService:WorkPackageNotificationService\n ) {\n }\n\n public canModifyParent():boolean {\n return !!this.workPackage.changeParent;\n }\n\n public get parent() {\n return this.workPackage && this.workPackage.parent;\n }\n\n public get active():boolean {\n return this.editing;\n }\n\n public close():void {\n this.toggle(false);\n }\n\n public open():void {\n this.toggle(true);\n }\n\n public updateParent(newParent:WorkPackageResource|null) {\n this.close();\n let newParentId = newParent ? newParent.id : null;\n if (_.get(this.parent, 'id', null) === newParentId) {\n return;\n }\n\n this.isSaving = true;\n this.wpRelationsHierarchy.changeParent(this.workPackage, newParentId)\n .catch((error:any) => {\n this.notificationService.handleRawError(error, this.workPackage);\n })\n .then(() => this.isSaving = false); // Behaves as .finally()\n }\n\n private toggle(state:boolean) {\n if (this.editing !== state) {\n this.editing = state;\n this.onSwitch.emit(this.editing);\n }\n }\n}\n\n\n","
\n
    \n 0\">\n
  • \n {{ hierarchyLabel }}: \n
  • \n \n \n \n \n \n
    \n 1 }\">\n \n \n
\n
\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\n\n@Component({\n templateUrl: './wp-breadcrumb.html',\n styleUrls: ['./wp-breadcrumb.sass'],\n selector: 'wp-breadcrumb',\n})\nexport class WorkPackageBreadcrumbComponent {\n @Input('workPackage') workPackage:WorkPackageResource;\n\n public text = {\n parent: this.I18n.t('js.relations_hierarchy.parent_headline'),\n hierarchy: this.I18n.t('js.relations_hierarchy.hierarchy_headline'),\n };\n\n constructor(private I18n:I18nService) {\n }\n\n public inputActive:boolean = false;\n\n public get hierarchyCount() {\n return this.workPackage.ancestors.length;\n }\n\n public get hierarchyLabel() {\n return (this.hierarchyCount === 1) ? this.text.parent : this.text.hierarchy;\n }\n\n public updateActiveInput(val:boolean) {\n this.inputActive = val;\n }\n}\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {Component, ElementRef, Input, ViewChild} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {OnInit} from '@angular/core';\nimport {UploadFile} from \"core-components/api/op-file-upload/op-file-upload.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\n\n@Component({\n selector: 'attachments-upload',\n templateUrl: './attachments-upload.html'\n})\nexport class AttachmentsUploadComponent implements OnInit {\n @Input() public resource:HalResource;\n\n @ViewChild('hiddenFileInput') public filePicker:ElementRef;\n\n public draggingOver:boolean = false;\n public text:any;\n public maxFileSize:number;\n public $element:JQuery;\n\n constructor(readonly I18n:I18nService,\n readonly ConfigurationService:ConfigurationService,\n readonly notificationsService:NotificationsService,\n protected elementRef:ElementRef,\n protected halResourceService:HalResourceService) {\n this.text = {\n uploadLabel: I18n.t('js.label_add_attachments'),\n dropFiles: I18n.t('js.label_drop_files'),\n dropFilesHint: I18n.t('js.label_drop_files_hint'),\n foldersWarning: I18n.t('js.label_drop_folders_hint')\n };\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.ConfigurationService.initialized.then(() =>\n this.maxFileSize = this.ConfigurationService.maximumAttachmentFileSize\n );\n }\n\n public triggerFileInput(event:MouseEvent) {\n this.filePicker.nativeElement.click();\n\n event.preventDefault();\n event.stopPropagation();\n return false;\n }\n\n public onDropFiles(event:DragEvent) {\n event.dataTransfer!.dropEffect = 'copy';\n event.preventDefault();\n event.stopPropagation();\n\n let dfFiles = event.dataTransfer!.files;\n let length:number = dfFiles ? dfFiles.length : 0;\n\n let files:UploadFile[] = [];\n for (let i = 0; i < length; i++) {\n files.push(dfFiles[i]);\n }\n\n this.uploadFiles(files);\n this.draggingOver = false;\n }\n\n public onDragOver(event:DragEvent) {\n if (this.containsFiles(event.dataTransfer)) {\n event.dataTransfer!.dropEffect = 'copy';\n this.draggingOver = true;\n }\n\n event.preventDefault();\n event.stopPropagation();\n }\n\n public onDragLeave(event:DragEvent) {\n this.draggingOver = false;\n event.preventDefault();\n event.stopPropagation();\n }\n\n public onFilePickerChanged() {\n const files:UploadFile[] = Array.from(this.filePicker.nativeElement.files);\n this.uploadFiles(files);\n }\n\n private containsFiles(dataTransfer:any) {\n if (dataTransfer.types.contains) {\n return dataTransfer.types.contains('Files');\n } else {\n return (dataTransfer as DataTransfer).types.indexOf('Files') >= 0;\n }\n }\n\n protected uploadFiles(files:UploadFile[]):void {\n files = files || [];\n const countBefore = files.length;\n files = this.filterFolders(files);\n\n if (files.length === 0) {\n\n // If we filtered all files as directories, show a notice\n if (countBefore > 0) {\n this.notificationsService.addNotice(this.text.foldersWarning);\n }\n\n return;\n }\n\n this.resource.uploadAttachments(files);\n }\n\n /**\n * We try to detect folders by checking for either empty types\n * or empty file sizes.\n * @param files\n */\n protected filterFolders(files:UploadFile[]) {\n return files.filter((file) => {\n\n // Folders never have a mime type\n if (file.type !== '') {\n return true;\n }\n\n // Files however MAY have no mime type as well\n // so fall back to checking zero or 4096 bytes\n if (file.size === 0 || file.size === 4096) {\n console.warn(`Skipping file because of file size (${file.size}) %O`, file);\n return false;\n }\n\n return true;\n });\n }\n}\n","\n \n
\n
\n \n \n
\n
\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, Output, EventEmitter} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\n\n@Component({\n selector: 'edit-field-controls',\n templateUrl: './edit-field-controls.component.html'\n})\nexport class EditFieldControlsComponent {\n @Input() public cancelTitle:string;\n @Input() public saveTitle:string;\n @Input('fieldController') public field:EditFieldComponent;\n @Output() public onSave = new EventEmitter();\n @Output() public onCancel = new EventEmitter();\n\n public save() {\n this.onSave.emit();\n }\n\n public cancel() {\n this.onCancel.emit();\n }\n}\n","
\n
\n \n \n \n \n \n \n
\n
\n","import {Injector} from \"@angular/core\";\nimport {Constructor} from \"@angular/cdk/table\";\nimport {SimpleResource, SimpleResourceCollection} from \"core-app/modules/apiv3/paths/path-resources\";\n\nexport class BcfResourcePath extends SimpleResource {\n constructor(readonly injector:Injector,\n basePath:string,\n readonly id:string|number) {\n super(basePath, id);\n }\n}\n\nexport class BcfResourceCollectionPath extends SimpleResourceCollection {\n constructor(readonly injector:Injector,\n protected basePath:string,\n segment:string,\n protected resource?:Constructor) {\n super(basePath, segment, resource);\n }\n\n public id(id:string|number):T {\n return new (this.resource || BcfResourcePath)(this.injector, this.path, id) as T;\n }\n\n}","import {HttpClient, HttpErrorResponse, HttpParams} from \"@angular/common/http\";\nimport {Injector} from \"@angular/core\";\nimport {TypedJSON} from \"typedjson\";\nimport {Constructor} from \"@angular/cdk/table\";\nimport {Observable, throwError} from \"rxjs\";\nimport {\n HTTPClientHeaders,\n HTTPClientOptions,\n HTTPClientParamMap,\n HTTPSupportedMethods\n} from \"core-app/modules/hal/http/http.interfaces\";\nimport {URLParamsEncoder} from \"core-app/modules/hal/services/url-params-encoder\";\nimport {catchError, map} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class BcfApiRequestService {\n @InjectField() http:HttpClient;\n\n /**\n * Create a BCF api request service.\n * Optionally pass a resource map to map the resulting data to with TypedJson.\n *\n * @param injector Injector\n * @param resourceClass Optional mapped resource class with TypedJson annotations\n */\n constructor(readonly injector:Injector,\n readonly resourceClass?:Constructor) {\n }\n\n /**\n * Request GET from the given BCF API 2.1 resource and map it to +resourceClass+.\n *\n * @param path API path to request\n * @param params Request query params\n * @param headers optional headers map\n */\n get(path:string, params:HTTPClientParamMap, headers:HTTPClientHeaders = {}):Observable {\n const config:HTTPClientOptions = {\n headers: headers,\n params: new HttpParams({ encoder: new URLParamsEncoder(), fromObject: params }),\n withCredentials: true,\n responseType: 'json'\n };\n\n return this._request('get', path, config);\n }\n\n /**\n * Request the given BCF API 2.1 resource and map it to +resourceClass+.\n *\n * @param method request method\n * @param path API path to request\n * @param data Request payload (URL params for get, JSON payload otherwise)\n * @param data Request payload (URL params for get, JSON payload otherwise)\n */\n public request(method:HTTPSupportedMethods, path:string, data:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}):Observable {\n\n // HttpClient requires us to create HttpParams instead of passing data for get\n // so forward to that method instead.\n if (method === 'get') {\n return this.get(path, data, headers);\n }\n\n const config:HTTPClientOptions = {\n body: data || {},\n headers: headers,\n withCredentials: true,\n responseType: 'json'\n };\n\n return this._request(method, path, config);\n }\n\n /**\n * Perform the request with httpClient and deserialize the result\n *\n * @param method Request method\n * @param path Request path\n * @param config HTTP client configuration\n *\n * @private\n */\n private _request(method:HTTPSupportedMethods, path:string, config:HTTPClientOptions):Observable {\n return this\n .http\n .request(method, path, config)\n .pipe(\n map((response:any) => this.deserialize(response)),\n catchError((error:HttpErrorResponse) => {\n console.error(`Failed to ${method} ${path}: ${error.name}`);\n return throwError(error);\n })\n );\n }\n\n /**\n * Deserialize the JSON data into the mapped resource class, if given.\n * @param data JSON API response.\n */\n protected deserialize(data:any):T {\n if (this.resourceClass) {\n const serializer = new TypedJSON(this.resourceClass);\n return serializer.parse(data)!;\n } else {\n return data;\n }\n }\n}","import {jsonMember, jsonObject} from \"typedjson\";\n\n@jsonObject\nexport class BcfProjectResource {\n\n @jsonMember\n project_id:number;\n\n @jsonMember\n name:string;\n}\n","import {jsonArrayMember, jsonMember, jsonObject} from \"typedjson\";\nimport * as moment from \"moment\";\nimport {Moment} from \"moment\";\n\n@jsonObject\nexport class BcfTopicAuthorizationMap {\n @jsonArrayMember(String)\n topic_actions:string[];\n\n @jsonArrayMember(String)\n topic_status:string[];\n}\n\n@jsonObject\nexport class BcfTopicResource {\n\n @jsonMember\n guid:string;\n\n @jsonMember\n topic_type:string;\n\n @jsonMember\n topic_status:string;\n\n @jsonMember\n priority:string;\n\n @jsonArrayMember(String)\n reference_links:string[];\n\n @jsonMember\n title:string;\n\n @jsonMember({ preserveNull: true })\n index:number|null;\n\n @jsonArrayMember(String)\n labels:string[];\n\n @jsonMember({ deserializer: value => moment(value), serializer: (timestamp:Moment) => timestamp.toISOString() })\n creation_date:Moment;\n\n @jsonMember\n creation_author:string;\n\n @jsonMember({ deserializer: value => moment(value), serializer: (timestamp:Moment) => timestamp.toISOString() })\n modified_date:Moment;\n\n @jsonMember({ preserveNull: true })\n modified_author:string|null;\n\n @jsonMember\n assigned_to:string;\n\n @jsonMember({ preserveNull: true })\n stage:string|null;\n\n @jsonMember\n description:string;\n\n @jsonMember({\n deserializer: value => moment(value),\n serializer: (timestamp:Moment) => timestamp.format('YYYY-MM-DD')\n })\n due_date:Moment;\n\n @jsonMember\n authorization:BcfTopicAuthorizationMap;\n}\n","import {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {BcfResourcePath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\n\nexport class BcfViewpointPaths extends BcfResourcePath {\n readonly bcfTopicService = new BcfApiRequestService(this.injector);\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n return this.bcfTopicService.get(this.toPath(), params, headers);\n }\n\n delete(headers:HTTPClientHeaders = {}) {\n return this.bcfTopicService.request('delete', this.toPath(), {}, headers);\n }\n}","import {BcfResourceCollectionPath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {Observable} from \"rxjs\";\nimport {BcfViewpointPaths} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths\";\n\nexport class BcfViewpointCollectionPath extends BcfResourceCollectionPath {\n readonly bcfTopicService = new BcfApiRequestService(this.injector);\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n throw new Error(\"Not implemented\");\n }\n\n post(viewpoint:BcfViewpointInterface):Observable {\n return this\n .bcfTopicService\n .request(\n 'post',\n this.toPath(),\n viewpoint\n );\n }\n}","import {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {BcfResourceCollectionPath, BcfResourcePath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfTopicResource} from \"core-app/modules/bim/bcf/api/topics/bcf-topic.resource\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {BcfViewpointPaths} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths\";\nimport {BcfViewpointCollectionPath} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint-collection.paths\";\n\nexport class BcfTopicPaths extends BcfResourcePath {\n readonly bcfTopicService = new BcfApiRequestService(this.injector, BcfTopicResource);\n\n /** /comments */\n public readonly comments = new BcfResourceCollectionPath(this.injector, this.path, 'comments');\n\n /** /viewpoints */\n public readonly viewpoints = new BcfViewpointCollectionPath(this.injector, this.path, 'viewpoints', BcfViewpointPaths);\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n return this.bcfTopicService.get(this.toPath(), params, headers);\n }\n}","import {BcfResourceCollectionPath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {Observable} from \"rxjs\";\nimport {BcfTopicPaths} from \"core-app/modules/bim/bcf/api/topics/bcf-topic.paths\";\nimport {Injector} from \"@angular/core\";\nimport {BcfTopicResource} from \"core-app/modules/bim/bcf/api/topics/bcf-topic.resource\";\n\nexport class BcfTopicCollectionPath extends BcfResourceCollectionPath {\n readonly bcfTopicService = new BcfApiRequestService(this.injector, BcfTopicResource);\n\n constructor(readonly injector:Injector,\n protected basePath:string,\n segment:string) {\n super(injector, basePath, segment, BcfTopicPaths);\n }\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n throw new Error(\"Not implemented\");\n }\n\n /**\n * Create a topic from its to-be-associated work package\n */\n post(payload:any):Observable {\n return this\n .bcfTopicService\n .request(\n 'post',\n this.toPath(),\n payload\n );\n }\n}","import {jsonArrayMember, jsonObject} from \"typedjson\";\n\n@jsonObject\nexport class BcfExtensionResource {\n\n @jsonArrayMember(String)\n topic_actions:string[];\n\n @jsonArrayMember(String)\n project_actions:string[];\n\n @jsonArrayMember(String)\n comment_actions:string[];\n}\n","import {BcfResourcePath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {BcfExtensionResource} from \"core-app/modules/bim/bcf/api/extensions/bcf-extension.resource\";\n\nexport class BcfExtensionPaths extends BcfResourcePath {\n readonly bcfExtensionService = new BcfApiRequestService(this.injector, BcfExtensionResource);\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n return this.bcfExtensionService.get(this.toPath(), params, headers);\n }\n}\n","import {BcfResourcePath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {BcfProjectResource} from \"core-app/modules/bim/bcf/api/projects/bcf-project.resource\";\nimport {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {BcfTopicCollectionPath} from \"core-app/modules/bim/bcf/api/topics/bcf-viewpoint-collection.paths\";\nimport {BcfExtensionPaths} from \"core-app/modules/bim/bcf/api/extensions/bcf-extension.paths\";\n\nexport class BcfProjectPaths extends BcfResourcePath {\n readonly bcfProjectService = new BcfApiRequestService(this.injector, BcfProjectResource);\n\n /** /topics */\n public readonly topics = new BcfTopicCollectionPath(this.injector, this.path, 'topics');\n\n public readonly extensions = new BcfExtensionPaths(this.injector, this.path, 'extensions');\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n return this.bcfProjectService.get(this.toPath(), params, headers);\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from \"@angular/core\";\nimport {BcfResourceCollectionPath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfProjectPaths} from \"core-app/modules/bim/bcf/api/projects/bcf-project.paths\";\n\n\n@Injectable({ providedIn: 'root' })\nexport class BcfApiService {\n\n public readonly bcfApiVersion = '2.1';\n public readonly appBasePath = window.appBasePath || '';\n public readonly bcfApiBase = `${this.appBasePath}/api/bcf/${this.bcfApiVersion}`;\n\n // /api/bcf/:version/projects\n public readonly projects = new BcfResourceCollectionPath(this.injector, this.bcfApiBase, 'projects', BcfProjectPaths);\n\n constructor(readonly injector:Injector) {\n }\n\n /**\n * Parse the given string into a BCF resource path\n *\n * @param href\n */\n parse(href:string):T {\n if (!href.startsWith(this.bcfApiBase)) {\n throw new Error(`Cannot parse ${href} into BCF resource.`);\n }\n\n const parts = href\n .replace(this.bcfApiBase + '/', '')\n .split('/');\n\n // Try to find a target collection or resource\n let current:any = this;\n\n for (let i = 0; i < parts.length; i++) {\n let pathOrId:string = parts[i];\n if (pathOrId in current) {\n // Current has a member named like this URL part\n // descend into it\n current = current[pathOrId];\n } else if (current instanceof BcfResourceCollectionPath) {\n // Otherwise, assume we're looking for an ID\n current = current.id(pathOrId);\n } else {\n // Otherwise, return the current\n break;\n }\n }\n\n return current === this ? undefined : current;\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {ColorsService} from \"core-app/modules/common/colors/colors.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport interface UserLike {\n name:string;\n id:string|number|null;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class UserAvatarRendererService {\n\n constructor(private pathHelper:PathHelperService,\n private apiV3Service:APIV3Service,\n private colors:ColorsService) {\n\n }\n\n renderMultiple(container:HTMLElement,\n users:UserLike[],\n renderName:boolean = true,\n multiLine:boolean = false) {\n\n const span = document.createElement('span');\n\n\n for (let i = 0; i < users.length; i++) {\n const avatar = document.createElement('span');\n if (multiLine) {\n avatar.classList.add('user-avatar--multi-line');\n }\n\n this.render(avatar, users[i], renderName);\n\n if (!multiLine && i < users.length - 1) {\n const sep = document.createElement('span');\n sep.textContent = ', ';\n avatar.appendChild(sep);\n }\n\n span.appendChild(avatar);\n }\n\n container.appendChild(span);\n }\n\n render(container:HTMLElement,\n user:UserLike,\n renderName:boolean = true,\n classes:string = 'avatar-medium'):void {\n const userInitials = this.getInitials(user.name);\n const colorCode = this.colors.toHsl(user.name);\n\n let fallback = document.createElement('div');\n fallback.className = classes;\n fallback.classList.add('avatar-default');\n fallback.textContent = userInitials;\n fallback.style.background = colorCode;\n\n container.appendChild(fallback);\n\n if (renderName) {\n const name = document.createElement('span');\n name.textContent = user.name;\n container.appendChild(name);\n }\n\n // Avoid using the image when ID is null\n if (!user.id) {\n return;\n }\n\n const image = new Image();\n image.className = classes;\n image.classList.add('avatar--fallback');\n image.src = this.apiV3Service.users.id(user.id).avatar.toString();\n image.title = user.name;\n image.alt = user.name;\n image.onload = function () {\n fallback.replaceWith(image);\n (fallback as any) = undefined;\n };\n }\n\n private getInitials(name:string) {\n let characters = [...name];\n let lastSpace = name.lastIndexOf(' ');\n let first = characters[0]?.toUpperCase();\n let last = name[lastSpace + 1]?.toUpperCase();\n\n return [first, last].join(\"\");\n }\n}","import {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport namespace AngularTrackingHelpers {\n export function halHref(_index:number, item:T):string|null {\n return item.$href;\n }\n\n export function compareByName(a:T|undefined|null, b:T|undefined|null):boolean {\n return compareByAttribute('name')(a, b);\n }\n\n export function compareByAttribute(attribute:string) {\n return (a:any, b:any) => {\n const bothNil = !a && !b;\n return bothNil || (!!a && !!b && a[attribute] === b[attribute]);\n };\n }\n\n export function trackByName(i:number, item:any) {\n return _.get(item, 'name');\n }\n\n export function trackByHref(i:number, item:HalResource) {\n return _.get(item, 'href');\n }\n\n export function trackByProperty(prop:string) {\n return (i:number, item:HalResource) => _.get(item, prop);\n }\n\n export function trackByHrefAndProperty(propertyName:string) {\n return (i:number, item:HalResource) => {\n let href = _.get(item, 'href');\n let prop = _.get(item, propertyName, 'none');\n\n return `${href}#${propertyName}=${prop}`;\n };\n }\n\n export function trackByTrackingIdentifier(i:number, item:any) {\n return _.get(item, 'trackingIdentifier', item && item.href);\n }\n\n export function compareByHref(a:T|undefined|null, b:T|undefined|null):boolean {\n const bothNil = !a && !b;\n return bothNil || (!!a && !!b && a.$href === b.$href);\n }\n\n export function compareByHrefOrString(a:T|string|undefined|null, b:T|string|undefined|null):boolean {\n if (a instanceof HalResource && b instanceof HalResource) {\n return compareByHref(a as HalResource, b as HalResource);\n }\n\n const bothNil = !a && !b;\n return bothNil || a === b;\n }\n}\n","import {TimelineZoomLevel} from 'core-app/modules/hal/resources/query-resource';\n//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport * as moment from 'moment';\nimport {InputState, MultiInputState} from 'reactivestates';\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport Moment = moment.Moment;\n\nexport const timelineElementCssClass = 'timeline-element';\nexport const timelineBackgroundElementClass = 'timeline-element--bg';\nexport const timelineGridElementCssClass = 'wp-timeline--grid-element';\nexport const timelineMarkerSelectionStartClass = 'selection-start';\nexport const timelineHeaderCSSClass = 'wp-timeline--header-element';\nexport const timelineHeaderSelector = 'wp-timeline-header';\n\n/**\n *\n */\nexport class TimelineViewParametersSettings {\n\n zoomLevel:TimelineZoomLevel = 'days';\n\n}\n\n// Can't properly map the enum to a string aray\nexport const zoomLevelOrder:TimelineZoomLevel[] = [\n 'days', 'weeks', 'months', 'quarters', 'years'\n];\n\nexport function getPixelPerDayForZoomLevel(zoomLevel:TimelineZoomLevel) {\n switch (zoomLevel) {\n case 'days':\n return 30;\n case 'weeks':\n return 15;\n case 'months':\n return 6;\n case 'quarters':\n return 2;\n case 'years':\n return 0.5;\n }\n throw new Error('invalid zoom level: ' + zoomLevel);\n}\n\n/**\n * Number of pixels to display before the earliest workpackage in view\n */\nexport const requiredPixelMarginLeft = 120;\n\n/**\n *\n */\nexport class TimelineViewParameters {\n\n readonly now:Moment = moment({hour: 0, minute: 0, seconds: 0});\n\n dateDisplayStart:Moment = moment({hour: 0, minute: 0, seconds: 0});\n\n dateDisplayEnd:Moment = this.dateDisplayStart.clone().add(1, 'day');\n\n settings:TimelineViewParametersSettings = new TimelineViewParametersSettings();\n\n activeSelectionMode:null | ((wp:WorkPackageResource) => any) = null;\n\n selectionModeStart:null | string = null;\n\n /**\n * The visible viewport (at the time the view parameters were calculated last!!!)\n */\n visibleViewportAtCalculationTime:[Moment, Moment];\n\n get pixelPerDay():number {\n return getPixelPerDayForZoomLevel(this.settings.zoomLevel);\n }\n\n get maxWidthInPx() {\n return this.maxSteps * this.pixelPerDay;\n }\n\n get maxSteps():number {\n return this.dateDisplayEnd.diff(this.dateDisplayStart, 'days');\n }\n\n get dayCountForMarginLeft():number {\n return Math.ceil(requiredPixelMarginLeft / this.pixelPerDay);\n }\n\n}\n\n/**\n *\n */\nexport interface RenderInfo {\n viewParams:TimelineViewParameters;\n workPackage:WorkPackageResource;\n change:WorkPackageChangeset;\n isDuplicatedCell?:boolean;\n withAlternativeLabels?:boolean;\n}\n\n/**\n *\n */\nexport function calculatePositionValueForDayCountingPx(viewParams:TimelineViewParameters, days:number):number {\n const daysInPx = days * viewParams.pixelPerDay;\n return daysInPx;\n}\n\n/**\n *\n */\nexport function calculatePositionValueForDayCount(viewParams:TimelineViewParameters, days:number):string {\n const value = calculatePositionValueForDayCountingPx(viewParams, days);\n return value + 'px';\n}\n\nexport function getTimeSlicesForHeader(vp:TimelineViewParameters,\n unit:moment.unitOfTime.DurationConstructor,\n startView:Moment,\n endView:Moment) {\n\n const inViewport:[Moment, Moment][] = [];\n const rest:[Moment, Moment][] = [];\n\n const time = startView.clone().startOf(unit);\n const end = endView.clone().endOf(unit);\n\n while (time.isBefore(end)) {\n const sliceStart = moment.max(time, startView).clone();\n const sliceEnd = moment.min(time.clone().endOf(unit), endView).clone();\n time.add(1, unit);\n\n const viewport = vp.visibleViewportAtCalculationTime;\n if ((sliceStart.isSameOrAfter(viewport[0]) && sliceStart.isSameOrBefore(viewport[1]))\n || (sliceEnd.isSameOrAfter(viewport[0]) && sliceEnd.isSameOrBefore(viewport[1]))) {\n\n inViewport.push([sliceStart, sliceEnd]);\n } else {\n rest.push([sliceStart, sliceEnd]);\n }\n }\n\n const firstRest:[Moment, Moment] = rest.splice(0, 1)[0];\n const lastRest:[Moment, Moment] = rest.pop()!;\n const inViewportAndBoundaries = _.concat(\n [firstRest].filter(e => !_.isNil(e)),\n inViewport,\n [lastRest].filter(e => !_.isNil(e))\n );\n\n return {\n inViewportAndBoundaries,\n rest\n };\n\n}\n\nexport function calculateDaySpan(visibleWorkPackages:RenderedWorkPackage[],\n loadedWorkPackages:MultiInputState,\n viewParameters:TimelineViewParameters):number {\n let earliest:Moment = moment();\n let latest:Moment = moment();\n\n visibleWorkPackages.forEach((renderedRow) => {\n const wpId = renderedRow.workPackageId;\n\n if (!wpId) {\n return;\n }\n const workPackageState:InputState = loadedWorkPackages.get(wpId);\n const workPackage:WorkPackageResource|undefined = workPackageState.value;\n\n if (!workPackage) {\n return;\n }\n\n const start = workPackage.startDate ? workPackage.startDate : workPackage.date;\n if (start && moment(start).isBefore(earliest)) {\n earliest = moment(start);\n }\n\n const due = workPackage.dueDate ? workPackage.dueDate : workPackage.date;\n if (due && moment(due).isAfter(latest)) {\n latest = moment(due);\n }\n });\n\n const daysSpan = latest.diff(earliest, 'days') + 1;\n return daysSpan;\n}\n","import {InjectionToken} from \"@angular/core\";\n\nexport const OpContextMenuLocalsToken = new InjectionToken('CONTEXT_MENU_LOCALS');\n\nexport interface OpContextMenuLocalsMap {\n items:OpContextMenuItem[];\n contextMenuId?:string;\n [key:string]:any;\n};\n\nexport interface OpContextMenuItem {\n disabled?:boolean;\n hidden?:boolean;\n icon?:string;\n href?:string;\n class?:string;\n ariaLabel?:string;\n linkText?:string;\n divider?:boolean;\n onClick?:($event:JQuery.TriggeredEvent) => boolean;\n}\n","
\n \n
\n","import {Component, Inject} from \"@angular/core\";\nimport {\n OpContextMenuItem,\n OpContextMenuLocalsMap, OpContextMenuLocalsToken\n} from \"core-components/op-context-menu/op-context-menu.types\";\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\n\n@Component({\n templateUrl: './op-context-menu.html'\n})\nexport class OPContextMenuComponent {\n public items:OpContextMenuItem[];\n public service:OPContextMenuService;\n\n constructor(@Inject(OpContextMenuLocalsToken) public locals:OpContextMenuLocalsMap) {\n this.items = this.locals.items.filter(item => !item?.hidden);\n this.service = this.locals.service;\n }\n\n public handleClick(item:OpContextMenuItem, $event:JQuery.TriggeredEvent) {\n if (item.disabled || item.divider) {\n return false;\n }\n\n if (item.onClick!($event)) {\n this.locals.service.close();\n $event.preventDefault();\n $event.stopPropagation();\n return false;\n }\n\n return true;\n }\n}\n","import {ApplicationRef, ComponentFactoryResolver, Injectable, Injector} from '@angular/core';\nimport {ComponentPortal, DomPortalOutlet, PortalInjector} from \"@angular/cdk/portal\";\nimport {TransitionService} from \"@uirouter/core\";\nimport {OpContextMenuHandler} from \"core-components/op-context-menu/op-context-menu-handler\";\nimport {OpContextMenuLocalsMap, OpContextMenuLocalsToken} from \"core-components/op-context-menu/op-context-menu.types\";\nimport {OPContextMenuComponent} from \"core-components/op-context-menu/op-context-menu.component\";\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {FocusHelperService} from 'core-app/modules/common/focus/focus-helper';\n\n@Injectable({ providedIn: 'root' })\nexport class OPContextMenuService {\n public active:OpContextMenuHandler|null = null;\n\n // Hold a reference to the DOM node we're using as a host\n private portalHostElement:HTMLElement;\n // And a reference to the actual portal host interface on top of the element\n private bodyPortalHost:DomPortalOutlet;\n\n // Allow temporarily disabling the close handler\n private isOpening = false;\n\n constructor(private componentFactoryResolver:ComponentFactoryResolver,\n readonly FocusHelper:FocusHelperService,\n private appRef:ApplicationRef,\n private $transitions:TransitionService,\n private injector:Injector) {\n\n const hostElement = this.portalHostElement = document.createElement('div');\n hostElement.classList.add('op-context-menu--overlay');\n document.body.appendChild(hostElement);\n\n this.bodyPortalHost = new DomPortalOutlet(\n hostElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n\n // Close context menus on state change\n $transitions.onStart({}, () => this.close());\n\n // Listen to keyups on window to close context menus\n jQuery(window).on('keydown', (evt:JQuery.TriggeredEvent) => {\n if (this.active && evt.which === keyCodes.ESCAPE) {\n this.close();\n }\n\n return true;\n });\n\n // Listen to any click and close the active context menu\n const that = this;\n document.getElementById('wrapper')!.addEventListener('click', function(evt:Event) {\n if (that.active && !that.portalHostElement.contains(evt.target as Element)) {\n that.close();\n }\n }, true);\n }\n\n /**\n * Open a ContextMenu reference and append it to the portal\n * @param contextMenu A reference to a context menu handler\n */\n public show(menu:OpContextMenuHandler, event:JQuery.TriggeredEvent, component:any = OPContextMenuComponent) {\n this.close();\n\n // Create a portal for the given component class and render it\n this.isOpening = true;\n const portal = new ComponentPortal(component, null, this.injectorFor(menu.locals));\n this.bodyPortalHost.attach(portal);\n this.portalHostElement.style.display = 'block';\n this.active = menu;\n\n setTimeout(() => {\n this.reposition(event);\n // Focus on the first element\n this.active && this.active.onOpen(this.activeMenu);\n this.isOpening = false;\n });\n }\n\n public isActive(menu:OpContextMenuHandler) {\n return this.active && this.active === menu;\n }\n\n /**\n * Closes all currently open context menus.\n */\n public close() {\n if (this.isOpening) {\n return;\n }\n\n // Detach any component currently in the portal\n this.bodyPortalHost.detach();\n this.portalHostElement.style.display = 'none';\n this.active && this.active.onClose();\n this.active = null;\n }\n\n public reposition(event:JQuery.TriggeredEvent) {\n if (!this.active) {\n return;\n }\n\n this.activeMenu\n .position(this.active.positionArgs(event))\n .css('visibility', 'visible');\n }\n\n public get activeMenu():JQuery {\n return jQuery(this.portalHostElement).find('.dropdown');\n }\n\n /**\n * Create an augmented injector that is equal to this service's injector + the additional data\n * passed into +show+.\n * This allows callers to pass data into the newly created context menu component.\n *\n * @param {OpContextMenuLocalsMap} data\n * @returns {PortalInjector}\n */\n private injectorFor(data:OpContextMenuLocalsMap) {\n const injectorTokens = new WeakMap();\n // Pass the service because otherwise we're getting a cyclic dependency between the portal\n // host service and the bound portal\n data.service = this;\n\n injectorTokens.set(OpContextMenuLocalsToken, data);\n\n return new PortalInjector(this.injector, injectorTokens);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from '@angular/core';\nimport {Observable, Subject} from 'rxjs';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {HookService} from 'core-app/modules/plugins/hook-service';\nimport {WorkPackageFilterValues} from \"core-components/wp-edit-form/work-package-filter-values\";\nimport {\n HalResourceEditingService,\n ResourceChangesetCommit\n} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {filter} from \"rxjs/operators\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {HalResource, HalSource, HalSourceLink} from \"core-app/modules/hal/resources/hal-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\n\nexport const newWorkPackageHref = '/api/v3/work_packages/new';\n\n@Injectable()\nexport class WorkPackageCreateService extends UntilDestroyedMixin {\n protected form:Promise|undefined;\n\n // Allow callbacks to happen on newly created work packages\n protected newWorkPackageCreatedSubject = new Subject();\n\n constructor(protected injector:Injector,\n protected hooks:HookService,\n protected apiV3Service:APIV3Service,\n protected halResourceService:HalResourceService,\n protected querySpace:IsolatedQuerySpace,\n protected authorisationService:AuthorisationService,\n protected halEditing:HalResourceEditingService,\n protected schemaCache:SchemaCacheService,\n protected halEvents:HalEventsService) {\n super();\n\n this.halEditing\n .committedChanges\n .pipe(\n this.untilDestroyed(),\n filter(commit => commit.resource._type === 'WorkPackage' && commit.wasNew)\n )\n .subscribe((commit:ResourceChangesetCommit) => {\n this.newWorkPackageCreated(commit.resource);\n });\n\n this.halEditing\n .changes$(newWorkPackageHref)\n .pipe(\n this.untilDestroyed(),\n filter(changeset => !changeset)\n )\n .subscribe(() => {\n this.reset();\n });\n }\n\n protected newWorkPackageCreated(wp:WorkPackageResource) {\n this.reset();\n this.newWorkPackageCreatedSubject.next(wp);\n }\n\n public onNewWorkPackage():Observable {\n return this.newWorkPackageCreatedSubject.asObservable();\n }\n\n public createNewWorkPackage(projectIdentifier:string|undefined|null, payload:HalSource):Promise {\n return this\n .apiV3Service\n .withOptionalProject(projectIdentifier)\n .work_packages\n .form\n .forPayload(payload)\n .toPromise()\n .then((form:FormResource) => {\n return this.fromCreateForm(form);\n });\n }\n\n public fromCreateForm(form:FormResource):WorkPackageChangeset {\n let wp = this.initializeNewResource(form);\n\n const change = this.halEditing.edit(wp, form);\n\n // Call work package initialization hook\n this.hooks.call('workPackageNewInitialization', change);\n\n return change;\n }\n\n public copyWorkPackage(copyFrom:WorkPackageChangeset) {\n let request = copyFrom.pristineResource.$source;\n\n // Ideally we would make an empty request before to get the create schema (cannot use the update schema of the source changeset)\n // to get all the writable attributes and only send those.\n // But as this would require an additional request, we don't.\n return this\n .apiV3Service\n .work_packages\n .form\n .post(request)\n .toPromise()\n .then((form:FormResource) => {\n let changeset = this.fromCreateForm(form);\n\n return changeset;\n });\n }\n\n /**\n * Create a copy resource from other and the new work package form\n * @param form Work Package create form\n */\n private copyFrom(form:FormResource) {\n let wp = this.initializeNewResource(form);\n\n return this.halEditing.edit(wp, form);\n }\n\n\n public getEmptyForm(projectIdentifier:string|null|undefined):Promise {\n if (!this.form) {\n this.form = this\n .apiV3Service\n .withOptionalProject(projectIdentifier)\n .work_packages\n .form\n .post({})\n .toPromise();\n }\n\n return this.form as Promise;\n }\n\n public cancelCreation() {\n this.halEditing.stopEditing({ href: newWorkPackageHref });\n this.reset();\n }\n\n public changesetUpdates$() {\n return this\n .halEditing\n .state(newWorkPackageHref)\n .values$();\n }\n\n public createOrContinueWorkPackage(projectIdentifier:string|null|undefined, type?:number, defaults?:HalSource) {\n let changePromise = this.continueExistingEdit(type);\n\n if (!changePromise) {\n changePromise = this.createNewWithDefaults(projectIdentifier, defaults);\n }\n\n return changePromise.then((change:WorkPackageChangeset) => {\n this.authorisationService.initModelAuth('work_package', change.pristineResource);\n this.halEditing.updateValue(newWorkPackageHref, change);\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(change.pristineResource, true);\n\n return change;\n });\n }\n\n protected reset() {\n this\n .apiV3Service\n .work_packages\n .cache\n .clearSome('new');\n this.form = undefined;\n }\n\n protected continueExistingEdit(type?:number) {\n const change = this.halEditing.state(newWorkPackageHref).value as WorkPackageChangeset;\n if (change !== undefined) {\n const changeType = change.projectedResource.type;\n\n const hasChanges = !change.isEmpty();\n const typeEmpty = !changeType && !type;\n const typeMatches = type && changeType && changeType.idFromLink === type.toString();\n\n if (hasChanges && (typeEmpty || typeMatches)) {\n return Promise.resolve(change);\n }\n }\n\n return null;\n }\n\n /**\n * Initializes a new work package. The work package is not yet persisted.\n * The properties of the work package are initialized from two sources:\n * * The default values provided\n * * The filter values that might exist in the query space\n *\n * The first can be employed to e.g. provide the type or the parent of the work package.\n * The later can be employed to create a work package that adheres to the filter values.\n *\n * @params projectIdentifier The project the work package is to be created in.\n * @param defaults Values the new work package should possess on creation.\n */\n protected createNewWithDefaults(projectIdentifier:string|null|undefined, defaults?:HalSource) {\n return this\n .withFiltersPayload(projectIdentifier, defaults)\n .then(filterDefaults => {\n const mergedPayload = _.merge({ _links: {} }, filterDefaults, defaults);\n\n return this.createNewWorkPackage(projectIdentifier, mergedPayload).then((change:WorkPackageChangeset) => {\n if (!change) {\n throw 'No new work package was created';\n }\n\n // We need to apply the defaults again (after them being applied in the form requests)\n // here as the initial form requests might have led to some default\n // values not being carried over. This can happen when custom fields not available in one type are filter values.\n this.defaultsFromFilters(change, defaults);\n\n return change;\n });\n });\n }\n\n /**\n * Fetches all values of filters applicable to work as default values (e.g. assignee = 123).\n * If defaults already contain the type, that filter is ignored.\n *\n * The ignoring functionality could be generalized.\n *\n * @params object\n * @param defaults\n */\n private defaultsFromFilters(object:HalSource|WorkPackageChangeset, defaults?:HalSource) {\n // Not using WorkPackageViewFiltersService here as the embedded table does not load the form\n // which will result in that service having empty current filters.\n let query = this.querySpace.query.value;\n\n if (query) {\n const except:string[] = defaults?._links && defaults._links['type'] ? ['type'] : [];\n\n new WorkPackageFilterValues(this.injector, query.filters, except)\n .applyDefaultsFromFilters(object);\n }\n }\n\n /**\n * Returns valid payload based on the filters active in the query space validated by the backend via a form\n * request. In case no filters are active, the (empty) filters payload is just passed through.\n *\n * If there are filters applied, we need the additional form request to turn the defaults of the filters into\n * a valid payload in the sense that all properties are at their correct place and are in the right format. That means\n * HalResources are in the _links section and follow the { href: some_link } format while simple properties stay on the\n * top level.\n */\n private withFiltersPayload(projectIdentifier:string|null|undefined, defaults?:HalSource):Promise {\n const fromFilter = { _links: {} };\n this.defaultsFromFilters(fromFilter, defaults);\n\n const filtersApplied = Object.keys(fromFilter).length > 1 || Object.keys(fromFilter._links).length > 0;\n\n if (filtersApplied) {\n return this\n .apiV3Service\n .withOptionalProject(projectIdentifier)\n .work_packages\n .form\n .forTypePayload(defaults || { _links: {} })\n .toPromise()\n .then((form:FormResource) => {\n this.toApiPayload(fromFilter, form.schema);\n return fromFilter;\n });\n } else {\n return Promise.resolve(fromFilter);\n }\n }\n\n private toApiPayload(payload:HalSource, schema:SchemaResource) {\n let links:string[] = [];\n\n Object.keys(schema.$source).forEach(attribute => {\n if (!['Integer',\n 'Float',\n 'Date',\n 'DateTime',\n 'Duration',\n 'Formattable',\n 'Boolean',\n 'String',\n 'Text',\n undefined].includes(schema.$source[attribute].type)) {\n links.push(attribute);\n }\n });\n\n links.forEach(attribute => {\n const value = payload[attribute];\n if (value === undefined) {\n // nothing\n } else if (value instanceof HalResource) {\n payload._links[attribute] = { href: value.$links.self.href };\n } else if (!value) {\n payload._links[attribute] = { href: null };\n } else {\n payload._links[attribute] = value as unknown as HalSourceLink;\n }\n delete payload[attribute];\n });\n }\n\n /**\n * Assign values from the form for a newly created work package resource.\n * @param form\n */\n private initializeNewResource(form:FormResource) {\n let payload = form.payload.$plain();\n\n // maintain the reference to the schema\n payload['_links']['schema'] = { href: 'new' };\n\n let wp = this.halResourceService.createHalResourceOfType('WorkPackage', payload);\n\n wp.$source.id = 'new';\n\n // Ensure type is set to identify the resource\n wp._type = 'WorkPackage';\n\n // Since the ID will change upon saving, keep track of the WP\n // with the actual creation date\n wp.__initialized_at = Date.now();\n\n // Set update link to form\n wp['update'] = wp.$links.update = form.$links.self;\n // Use POST /work_packages for saving link\n wp['updateImmediately'] = wp.$links.updateImmediately = (payload) => {\n return this.apiV3Service.work_packages.post(payload).toPromise();\n };\n\n // We need to provide the schema to the cache so that it is available in the html form to e.g. determine\n // the editability.\n // It would be better if the edit field could simply rely on the changeset if it exists.\n this.schemaCache.update(wp, form.schema);\n\n return wp;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Field, IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {DisplayFieldContext} from \"core-app/modules/fields/display/display-field.service\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport const cssClassCustomOption = 'custom-option';\n\nexport class DisplayField extends Field {\n public static type:string;\n public mode:string | null = null;\n public activeChange:ResourceChangeset|null = null;\n\n @InjectField() I18n!:I18nService;\n\n constructor(public name:string, public context:DisplayFieldContext) {\n super();\n }\n\n /**\n * Apply the display field to the given resource and schema\n * @param resource\n * @param schema\n */\n public apply(resource:T, schema:IFieldSchema) {\n this.resource = resource;\n this.schema = schema;\n }\n\n public texts = {\n empty: this.I18n.t('js.label_no_value'),\n placeholder: this.I18n.t('js.placeholders.default')\n };\n\n public get isFormattable():boolean {\n return false;\n }\n\n /**\n * Return the provided local injector,\n * which is relevant to provide the display field\n * the current space context.\n */\n public get injector() {\n return this.context.injector;\n }\n\n public get value() {\n if (!this.schema) {\n return null;\n }\n\n if (this.activeChange) {\n return this.activeChange.projectedResource[this.name];\n }\n else {\n return this.attribute;\n }\n }\n\n protected get attribute() {\n return this.resource[this.name];\n }\n\n public get type():string {\n return (this.constructor as typeof DisplayField).type;\n }\n\n public get valueString():string {\n return this.value;\n }\n\n public get placeholder():string {\n return '-';\n }\n\n public get label() {\n return (this.schema.name || this.name);\n }\n\n public get title():string|null {\n\n // Don't return a value for long text fields,\n // since they shouldn't / won't be truncated.\n if (this.isFormattable) {\n return null;\n }\n\n return this.valueString;\n }\n\n public render(element:HTMLElement, displayText:string, options:any = {}):void {\n element.textContent = displayText;\n }\n\n /**\n * Render an empty placeholder if no values are present\n */\n public renderEmpty(element:HTMLElement) {\n const emptyDiv = document.createElement('div');\n emptyDiv.setAttribute('title', this.texts.empty);\n emptyDiv.textContent = this.texts.placeholder;\n emptyDiv.classList.add(cssClassCustomOption, '-empty');\n\n element.appendChild(emptyDiv);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectorRef, Directive, OnInit} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {ActivityEntryInfo} from 'core-components/wp-single-view-tabs/activity-panel/activity-entry-info';\nimport {WorkPackagesActivityService} from 'core-components/wp-single-view-tabs/activity-panel/wp-activity.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {Transition} from \"@uirouter/core\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Directive()\nexport class ActivityPanelBaseController extends UntilDestroyedMixin implements OnInit {\n public workPackage:WorkPackageResource;\n public workPackageId:string;\n\n // All activities retrieved for the work package\n public unfilteredActivities:HalResource[] = [];\n\n // Visible activities\n public visibleActivities:ActivityEntryInfo[] = [];\n\n public reverse:boolean;\n public showToggler:boolean;\n\n public onlyComments:boolean = false;\n public togglerText:string;\n public text = {\n commentsOnly: this.I18n.t('js.label_activity_show_only_comments'),\n showAll: this.I18n.t('js.label_activity_show_all')\n };\n\n constructor(readonly apiV3Service:APIV3Service,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly $transition:Transition,\n readonly wpActivity:WorkPackagesActivityService) {\n super();\n\n this.reverse = wpActivity.isReversed;\n this.togglerText = this.text.commentsOnly;\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.wpActivity.require(this.workPackage).then((activities:any) => {\n this.updateActivities(activities);\n this.cdRef.detectChanges();\n });\n });\n }\n\n protected updateActivities(activities:HalResource[]) {\n this.unfilteredActivities = activities;\n\n const visible = this.getVisibleActivities();\n this.visibleActivities = visible.map((el:HalResource, i:number) => this.info(el, i));\n this.showToggler = this.shouldShowToggler();\n }\n\n protected shouldShowToggler() {\n const count_all = this.unfilteredActivities.length;\n const count_with_comments = this.getActivitiesWithComments().length;\n\n return count_all > 1 &&\n count_with_comments > 0 &&\n count_with_comments < this.unfilteredActivities.length;\n }\n\n protected getVisibleActivities() {\n if (!this.onlyComments) {\n return this.unfilteredActivities;\n } else {\n return this.getActivitiesWithComments();\n }\n }\n\n protected getActivitiesWithComments() {\n return this.unfilteredActivities\n .filter((activity:HalResource) => !!_.get(activity, 'comment.html'));\n }\n\n public toggleComments() {\n this.onlyComments = !this.onlyComments;\n this.updateActivities(this.unfilteredActivities);\n\n if (this.onlyComments) {\n this.togglerText = this.text.showAll;\n } else {\n this.togglerText = this.text.commentsOnly;\n }\n }\n\n public info(activity:HalResource, index:number) {\n return this.wpActivity.info(this.unfilteredActivities, activity, index);\n }\n}\n\n","/**\n * Return the row html id attribute for the given work package ID.\n */\nimport {collapsedGroupClass} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\n\nexport function rowId(workPackageId:string):string {\n return `wp-row-${workPackageId}-table`;\n}\n\nexport function relationRowClass():string {\n return `wp-table--relations-aditional-row`;\n}\n\nexport function locateTableRow(workPackageId:string):JQuery {\n return jQuery('.' + rowId(workPackageId));\n}\n\nexport function locateTableRowByIdentifier(identifier:string) {\n return jQuery(`.${identifier}-table`);\n}\n\nexport function isInsideCollapsedGroup(el?:Element | null) {\n if (!el) {\n return false;\n }\n\n return Array.from(el.classList).find(listClass => listClass.includes(collapsedGroupClass())) != null;\n}\n\nexport function locatePredecessorBySelector(el:HTMLElement, selector:string):HTMLElement|null {\n let previous = el.previousElementSibling;\n\n while (previous) {\n if (previous.matches(selector)) {\n return previous as HTMLElement;\n } else {\n previous = previous.previousElementSibling;\n }\n }\n\n return null;\n}\n\nexport function scrollTableRowIntoView(workPackageId:string):void {\n try {\n const element = locateTableRow(workPackageId);\n const container = element.scrollParent()!;\n const containerTop = container.scrollTop()!;\n const containerBottom = containerTop + container.height()!;\n\n const elemTop = element[0].offsetTop;\n const elemBottom = elemTop + element.height()!;\n\n if (elemTop < containerTop) {\n container[0].scrollTop = elemTop;\n } else if (elemBottom > containerBottom) {\n container[0].scrollTop = elemBottom - container.height()!;\n }\n } catch (e) {\n console.warn(\"Can't scroll row element into view: \" + e);\n }\n}\n","import {Injector} from \"@angular/core\";\nimport {\n OpEditingPortalChangesetToken,\n OpEditingPortalHandlerToken,\n OpEditingPortalSchemaToken\n} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {PortalInjector} from \"@angular/cdk/portal\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\n\n/**\n * Creates an injector for the edit field portal to pass data into.\n *\n * @returns {PortalInjector}\n */\nexport function createLocalInjector(injector:Injector, change:ResourceChangeset, fieldHandler:EditFieldHandler, schema:IFieldSchema):Injector {\n const injectorTokens = new WeakMap();\n\n injectorTokens.set(OpEditingPortalChangesetToken, change);\n injectorTokens.set(OpEditingPortalHandlerToken, fieldHandler);\n injectorTokens.set(OpEditingPortalSchemaToken, schema);\n\n return new PortalInjector(injector, injectorTokens);\n}\n","import {Injector} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {PrimaryRenderPass} from '../primary-render-pass';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport abstract class RowsBuilder {\n\n @InjectField() public states:States;\n\n constructor(public readonly injector:Injector, public workPackageTable:WorkPackageTable) {\n }\n\n /**\n * Build all rows of the table.\n */\n public abstract buildRows():PrimaryRenderPass;\n\n /**\n * Determine if this builder applies to the current view mode.\n */\n public isApplicable(table:WorkPackageTable) {\n return true;\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {groupName} from './grouped-rows-helpers';\nimport {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {rowGroupClassName} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport function groupClassNameFor(group:GroupObject) {\n return `group-${group.identifier}`;\n}\n\nexport class GroupHeaderBuilder {\n\n @InjectField() public I18n:I18nService;\n public text:{ collapse:string, expand:string };\n\n constructor(public readonly injector:Injector) {\n this.text = {\n collapse: this.I18n.t('js.label_collapse'),\n expand: this.I18n.t('js.label_expand'),\n };\n }\n\n public buildGroupRow(group:GroupObject, colspan:number) {\n let row = document.createElement('tr');\n let togglerIconClass, text;\n\n if (group.collapsed) {\n text = this.text.expand;\n togglerIconClass = 'icon-plus';\n } else {\n text = this.text.collapse;\n togglerIconClass = 'icon-minus2';\n }\n\n row.classList.add(rowGroupClassName, groupClassNameFor(group));\n row.id = `wp-table-rowgroup-${group.index}`;\n row.dataset['groupIndex'] = (group.index).toString();\n row.dataset['groupIdentifier'] = group.identifier;\n row.innerHTML = `\n \n
\n ${_.escape(text)}\n
\n
\n ${_.escape(groupName(group))}\n \n (${group.count})\n \n
\n \n `;\n\n return row;\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {States} from '../../../states.service';\nimport {isRelationColumn, QueryColumn} from '../../../wp-query/query-column';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {tdClassName} from '../cell-builder';\nimport {commonRowClassName, SingleRowBuilder, tableRowClassName} from '../rows/single-row-builder';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {RelationColumnType} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport function relationGroupClass(workPackageId:string) {\n return `__relations-expanded-from-${workPackageId}`;\n}\n\nexport function relationIdentifier(targetId:string, workPackageId:string) {\n return `wp-relation-row-${workPackageId}-to-${targetId}`;\n}\n\nexport const relationCellClassName = 'wp-table--relation-cell-td';\n\nexport class RelationRowBuilder extends SingleRowBuilder {\n\n @InjectField() public states:States;\n @InjectField() public I18n:I18nService;\n\n constructor(public readonly injector:Injector,\n protected workPackageTable:WorkPackageTable) {\n\n super(injector, workPackageTable);\n }\n\n /**\n * For additional relation rows, we don't want to render an expandable relation cell,\n * but instead we render the relation label.\n * @param workPackage\n * @param column\n * @return {any}\n */\n public buildCell(workPackage:WorkPackageResource, column:QueryColumn):HTMLElement|null {\n\n // handle relation types\n if (isRelationColumn(column)) {\n return this.emptyRelationCell(column);\n }\n\n return super.buildCell(workPackage, column);\n }\n\n /**\n * Build the columns on the given empty row\n */\n public buildEmptyRelationRow(from:WorkPackageResource, relation:RelationResource, type:RelationColumnType):[HTMLElement, WorkPackageResource] {\n const denormalized = relation.denormalized(from);\n\n const to = this.states.workPackages.get(denormalized.targetId).value!;\n\n // Let the primary row builder build the row\n const row = this.createEmptyRelationRow(from, to);\n const [tr, _] = super.buildEmptyRow(to, row);\n\n return [tr, to];\n }\n\n /**\n * Create an empty unattached row element for the given work package\n * @param workPackage\n * @returns {any}\n */\n public createEmptyRelationRow(from:WorkPackageResource, to:WorkPackageResource) {\n const identifier = this.relationClassIdentifier(from, to);\n let tr = document.createElement('tr');\n tr.dataset['workPackageId'] = to.id!;\n tr.dataset['classIdentifier'] = identifier;\n\n tr.classList.add(\n commonRowClassName, tableRowClassName, 'issue',\n `wp-table--relations-aditional-row`,\n identifier,\n `${identifier}-table`,\n relationGroupClass(from.id!)\n );\n\n return tr;\n }\n\n public relationClassIdentifier(from:WorkPackageResource, to:WorkPackageResource) {\n return relationIdentifier(to.id!, from.id!);\n }\n\n /**\n *\n * @param from\n * @param denormalized\n * @param type\n */\n public appendRelationLabel(jRow:JQuery, from:WorkPackageResource, relation:RelationResource, columnId:string, type:RelationColumnType) {\n const denormalized = relation.denormalized(from);\n let typeLabel = '';\n\n // Add the relation label if this is a \"Relations for \" column\n if (type === 'toType') {\n typeLabel = this.I18n.t(`js.relation_labels.${denormalized.reverseRelationType}`);\n }\n // Add the WP type label if this is a \" Relations\" column\n if (type === 'ofType') {\n const wp = this.states.workPackages.get(denormalized.target.id!).value!;\n typeLabel = wp.type.name;\n }\n\n const relationLabel = document.createElement('span');\n relationLabel.classList.add('relation-row--type-label');\n relationLabel.textContent = typeLabel;\n\n const textNode = document.createTextNode(denormalized.target.name);\n\n jRow.find(`.${relationCellClassName}`).empty();\n jRow.find(`.${relationCellClassName}.${columnId}`).append(relationLabel);\n }\n\n protected emptyRelationCell(column:QueryColumn) {\n const cell = document.createElement('td');\n cell.classList.add(relationCellClassName, tdClassName, column.id);\n\n return cell;\n }\n}\n","import {Injector} from '@angular/core';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {PrimaryRenderPass, RowRenderInfo} from '../primary-render-pass';\nimport {relationGroupClass, RelationRowBuilder} from './relation-row-builder';\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {\n RelationColumnType,\n WorkPackageViewRelationColumnsService\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport interface RelationRenderInfo extends RowRenderInfo {\n data:{\n relation:RelationResource;\n columnId:string;\n relationType:RelationColumnType;\n };\n}\n\nexport class RelationsRenderPass {\n @InjectField() wpRelations:WorkPackageRelationsService;\n @InjectField() wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() wpTableRelationColumns:WorkPackageViewRelationColumnsService;\n\n public relationRowBuilder:RelationRowBuilder;\n\n constructor(public readonly injector:Injector,\n private table:WorkPackageTable,\n private tablePass:PrimaryRenderPass) {\n\n this.relationRowBuilder = new RelationRowBuilder(injector, table);\n }\n\n public render() {\n // If no relation column active, skip this pass\n if (!this.isApplicable) {\n return;\n }\n\n // Render for each original row, clone it since we're modifying the tablepass\n const rendered = _.clone(this.tablePass.renderedOrder);\n rendered.forEach((row:RowRenderInfo, position:number) => {\n\n // We only care for rows that are natural work packages\n if (!row.workPackage) {\n return;\n }\n\n // If the work package has no relations, ignore\n const workPackage = row.workPackage;\n const fromId = workPackage.id!;\n const state = this.wpRelations.state(fromId);\n if (!state.hasValue() || _.size(state.value) === 0) {\n return;\n }\n\n this.wpTableRelationColumns.relationsToExtendFor(workPackage,\n state.value,\n (relation:RelationResource, column:QueryColumn, type:any) => {\n\n // Build each relation row (currently sorted by order defined in API)\n const [relationRow, target] = this.relationRowBuilder.buildEmptyRelationRow(\n workPackage,\n relation,\n type\n );\n\n // Augment any data for the belonging work package row to it\n relationRow.classList.add(...row.additionalClasses);\n this.relationRowBuilder.appendRelationLabel(jQuery(relationRow),\n workPackage,\n relation,\n column.id,\n type);\n\n // Insert next to the work package row\n // If no relations exist until here, directly under the row\n // otherwise as the last element of the relations\n // Insert into table\n this.tablePass.spliceRow(\n relationRow,\n `.${this.relationRowBuilder.classIdentifier(workPackage)},.${relationGroupClass(fromId)}`,\n {\n classIdentifier: this.relationRowBuilder.relationClassIdentifier(workPackage, target),\n additionalClasses: row.additionalClasses.concat(['wp-table--relations-aditional-row']),\n workPackage: target,\n belongsTo: workPackage,\n renderType: 'relations',\n hidden: row.hidden,\n data: {\n relation: relation,\n columnId: column.id,\n relationType: type\n }\n } as RelationRenderInfo\n );\n });\n });\n }\n\n public refreshRelationRow(renderedRow:RelationRenderInfo,\n workPackage:WorkPackageResource,\n oldRow:JQuery) {\n const newRow = this.relationRowBuilder.refreshRow(workPackage, oldRow);\n this.relationRowBuilder.appendRelationLabel(newRow,\n renderedRow.belongsTo!,\n renderedRow.data.relation,\n renderedRow.data.columnId,\n renderedRow.data.relationType);\n\n return newRow;\n }\n\n private get isApplicable() {\n return this.wpTableColumns.hasRelationColumns();\n }\n}\n","import {Injector} from '@angular/core';\nimport {PrimaryRenderPass, RowRenderInfo} from '../primary-render-pass';\nimport {TimelineRowBuilder} from './timeline-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\n\nexport class TimelineRenderPass {\n\n /** Row builders */\n protected timelineBuilder:TimelineRowBuilder;\n\n /** Resulting timeline body */\n public timelineBody:DocumentFragment;\n\n constructor(public readonly injector:Injector,\n private table:WorkPackageTable,\n private tablePass:PrimaryRenderPass) {\n }\n\n public render() {\n // Prepare and reset the render pass\n this.timelineBody = document.createDocumentFragment();\n this.timelineBuilder = new TimelineRowBuilder(this.injector, this.table);\n\n // Render into timeline fragment\n this.tablePass.renderedOrder.forEach((row:RowRenderInfo) => {\n const wpId = row.workPackage ? row.workPackage.id : null;\n\n const secondary = this.timelineBuilder.build(wpId);\n secondary.classList.add(row.classIdentifier, `${row.classIdentifier}-timeline`, ...row.additionalClasses);\n this.timelineBody.appendChild(secondary);\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {PrimaryRenderPass, RowRenderInfo} from \"core-components/wp-fast-table/builders/primary-render-pass\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HighlightingRenderPass {\n\n @InjectField() wpTableHighlighting:WorkPackageViewHighlightingService;\n @InjectField() querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n private table:WorkPackageTable,\n private tablePass:PrimaryRenderPass) {\n\n }\n\n public render() {\n // If highlighting is done inline in attributes, skip\n if (!this.isApplicable) {\n return;\n }\n\n const highlightAttribute = this.wpTableHighlighting.current.mode;\n\n // Get the computed style to identify bright properties\n const styles = window.getComputedStyle(document.body);\n\n // Render for each original row, clone it since we're modifying the tablepass\n this.tablePass.renderedOrder.forEach((row:RowRenderInfo, position:number) => {\n\n // We only care for rows that are natural work packages\n if (!row.workPackage) {\n return;\n }\n\n // Get the loaded attribute of the WP\n const property = row.workPackage[highlightAttribute] as HalResource;\n\n // We only color rows that have an active attribute\n if (!property) {\n return;\n }\n\n const id = property.id!;\n const element:HTMLElement = this.tablePass.tableBody.children[position] as HTMLElement;\n element.classList.add(Highlighting.backgroundClass(highlightAttribute, id));\n });\n }\n\n private get isApplicable() {\n return !(this.wpTableHighlighting.isInline || this.wpTableHighlighting.isDisabled);\n }\n}\n","import {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {tdClassName} from \"core-components/wp-fast-table/builders/cell-builder\";\nimport {Injector} from \"@angular/core\";\nimport {TableDragActionsRegistryService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-actions-registry.service\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {internalSortColumn} from \"core-components/wp-fast-table/builders/internal-sort-columns\";\n\n/** Debug the render position */\nconst RENDER_DRAG_AND_DROP_POSITION = false;\n\nexport class DragDropHandleBuilder {\n\n // Injections\n private actionService:TableDragActionService;\n\n constructor(public readonly injector:Injector) {\n const dragActionRegistry = this.injector.get(TableDragActionsRegistryService);\n this.actionService = dragActionRegistry.get(injector);\n }\n\n /**\n * Renders an angular CDK drag component into the column\n */\n public build(workPackage:WorkPackageResource, position?:number):HTMLElement {\n // Append sort handle\n let td = document.createElement('td');\n\n td.classList.add(tdClassName, internalSortColumn.id);\n\n if (!this.actionService.canPickup(workPackage)) {\n return td;\n }\n\n td.classList.add('wp-table--sort-td', internalSortColumn.id, 'hide-when-print');\n\n // Wrap handle as span\n let span = document.createElement('span');\n span.classList.add('wp-table--drag-and-drop-handle', 'icon-drag-handle');\n td.appendChild(span);\n\n if (RENDER_DRAG_AND_DROP_POSITION) {\n let text = document.createElement('span');\n text.textContent = '' + position;\n td.appendChild(text);\n }\n\n return td;\n }\n}\n","import {Injector} from '@angular/core';\nimport {PrimaryRenderPass, RowRenderInfo} from '../primary-render-pass';\nimport {DragDropHandleBuilder} from \"core-components/wp-fast-table/builders/drag-and-drop/drag-drop-handle-builder\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {QueryOrder} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-order\";\n\nexport class DragDropHandleRenderPass {\n\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() public wpTableOrder:WorkPackageViewOrderService;\n\n // Drag & Drop handle builder\n protected dragDropHandleBuilder = new DragDropHandleBuilder(this.injector);\n\n constructor(public readonly injector:Injector,\n private table:WorkPackageTable,\n private tablePass:PrimaryRenderPass) {\n }\n\n public render() {\n if (!this.table.configuration.dragAndDropEnabled) {\n return;\n }\n\n\n this.wpTableOrder.withLoadedPositions().then((positions:QueryOrder) => {\n this.tablePass.renderedOrder.forEach((row:RowRenderInfo, position:number) => {\n // We only care for rows that are natural work packages and are not relation sub-rows\n if (!row.workPackage || row.renderType === 'relations') {\n return;\n }\n\n const handle = this.dragDropHandleBuilder.build(row.workPackage!, positions[row.workPackage!.id!]);\n\n if (handle) {\n row.element.replaceChild(handle, row.element.firstElementChild!);\n }\n });\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {timeOutput} from '../../../helpers/debug_output';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../../states.service';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageTable} from '../wp-fast-table';\nimport {RelationRenderInfo, RelationsRenderPass} from './relations/relations-render-pass';\nimport {SingleRowBuilder} from './rows/single-row-builder';\nimport {TimelineRenderPass} from './timeline/timeline-render-pass';\nimport {HighlightingRenderPass} from \"core-components/wp-fast-table/builders/highlighting/row-highlight-render-pass\";\nimport {DragDropHandleRenderPass} from \"core-components/wp-fast-table/builders/drag-and-drop/drag-drop-handle-render-pass\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport type RenderedRowType = 'primary'|'relations';\n\nexport interface RowRenderInfo {\n // The rendered row\n element:HTMLTableRowElement;\n // Unique class name as an identifier to uniquely identify the row in both table and timeline\n classIdentifier:string;\n // Additional classes to be added by any secondary render passes\n additionalClasses:string[];\n // If this row is a work package, contains a reference to the rendered WP\n workPackage:WorkPackageResource|null;\n // If this is an additional row not present, this contains a reference to the WP\n // it originated from\n belongsTo?:WorkPackageResource;\n // The type of row this was rendered from\n renderType:RenderedRowType;\n // Marks if the row is currently hidden to the user\n hidden:boolean;\n // Additional data by the render passes\n data?:any;\n}\n\nexport abstract class PrimaryRenderPass {\n\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() states:States;\n @InjectField() I18n!:I18nService;\n\n /** The rendered order of rows of work package IDs or , if not a work package row */\n public renderedOrder:RowRenderInfo[];\n\n /** Resulting table body */\n public tableBody:DocumentFragment;\n\n /** Additional render pass that handles timeline rendering */\n public timeline:TimelineRenderPass;\n\n /** Additional render pass that handles table relation rendering */\n public relations:RelationsRenderPass;\n\n /** Additional render pass that handles drag'n'drop handle rendering */\n public dragDropHandle:DragDropHandleRenderPass;\n\n /** Additional render pass that handles highlighting of rows */\n public highlighting:HighlightingRenderPass;\n\n constructor(public readonly injector:Injector,\n public workPackageTable:WorkPackageTable,\n public rowBuilder:SingleRowBuilder) {\n }\n\n /**\n * Execute the entire render pass, executing this pass and all subsequent registered passes\n * for timeline and relations.\n * @return {PrimaryRenderPass}\n */\n public render():this {\n\n timeOutput('Primary render pass', () => {\n\n // Prepare and reset the render pass\n this.prepare();\n\n // Render into the table fragment\n this.doRender();\n\n // Post render\n this.postRender();\n });\n\n // Render subsequent passes\n // that may modify the structure of the table\n this.highlighting.render();\n\n timeOutput('Relations render pass', () => {\n this.relations.render();\n });\n\n timeOutput('Drag handle render pass', () => {\n this.dragDropHandle.render();\n });\n\n // Synchronize the rows to timeline\n timeOutput('Timelines render pass', () => {\n this.timeline.render();\n });\n\n return this;\n }\n\n /**\n * Refresh a single row using the render pass it was originally created from.\n * @param row\n */\n public refresh(row:RowRenderInfo, workPackage:WorkPackageResource, body:HTMLElement) {\n let oldRow = jQuery(body).find(`.${row.classIdentifier}`);\n let replacement:JQuery|null = null;\n\n switch (row.renderType) {\n case 'primary':\n replacement = this.rowBuilder.refreshRow(workPackage, oldRow);\n break;\n case 'relations':\n replacement = this.relations.refreshRelationRow(row as RelationRenderInfo, workPackage, oldRow);\n }\n\n if (replacement !== null && oldRow.length) {\n oldRow.replaceWith(replacement);\n }\n }\n\n public get result():RenderedWorkPackage[] {\n return this.renderedOrder.map((row) => {\n return {\n classIdentifier: row.classIdentifier,\n workPackageId: row.workPackage ? row.workPackage.id : null,\n hidden: row.hidden\n };\n });\n }\n\n /**\n * Splice a row into a specific location of the current render pass through the given selector.\n *\n * 1. Insert into the document fragment after the last match of the selector\n * 2. Splice into the renderedOrder array.\n */\n public spliceRow(row:HTMLElement, selector:string, renderedInfo:RowRenderInfo) {\n // Insert into table using the selector\n // If it matches multiple, select the last element\n const target = jQuery(this.tableBody)\n .find(selector)\n .last();\n\n target.after(row);\n\n // Splice the renderedOrder at this exact location\n const index = target.index();\n this.renderedOrder.splice(index + 1, 0, renderedInfo);\n }\n\n protected prepare() {\n this.timeline = new TimelineRenderPass(this.injector, this.workPackageTable, this);\n this.relations = new RelationsRenderPass(this.injector, this.workPackageTable, this);\n this.dragDropHandle = new DragDropHandleRenderPass(this.injector, this.workPackageTable, this);\n this.highlighting = new HighlightingRenderPass(this.injector, this.workPackageTable, this);\n this.tableBody = document.createDocumentFragment();\n this.renderedOrder = [];\n }\n\n /**\n * The actual render function of this renderer.\n */\n protected abstract doRender():void;\n\n /**\n * Post render shared among all sub passes\n */\n protected postRender():void {\n if (this.renderedOrder.length === 0 && this.workPackageTable.renderPlaceholderRow) {\n this.tableBody.appendChild(this.rowBuilder.placeholderRow);\n }\n }\n\n /**\n * Append a work package row to both containers\n * @param workPackage The work package, if the row belongs to one\n * @param row HTMLElement to append\n * @param rowClasses Additional classes to apply to the timeline row for mirroring purposes\n * @param hidden whether the row was rendered hidden\n */\n protected appendRow(workPackage:WorkPackageResource,\n row:HTMLTableRowElement,\n additionalClasses:string[] = [],\n hidden:boolean = false) {\n\n this.tableBody.appendChild(row);\n\n this.renderedOrder.push({\n classIdentifier: this.rowBuilder.classIdentifier(workPackage),\n additionalClasses: additionalClasses,\n workPackage: workPackage,\n renderType: 'primary',\n element: row,\n hidden: hidden\n });\n }\n\n /**\n * Append a non-work package row to both containers\n * @param row HTMLElement to append\n * @param classIdentifer a unique identifier for the two rows (one each in table/timeline).\n * @param hidden whether the row was rendered hidden\n */\n protected appendNonWorkPackageRow(row:HTMLTableRowElement,\n classIdentifer:string,\n additionalClasses:string[] = [],\n hidden:boolean = false) {\n row.classList.add(classIdentifer);\n this.tableBody.appendChild(row);\n\n this.renderedOrder.push({\n element: row,\n classIdentifier: classIdentifer,\n additionalClasses: additionalClasses,\n workPackage: null,\n renderType: 'primary',\n hidden: hidden\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {PrimaryRenderPass} from '../../primary-render-pass';\nimport {SingleRowBuilder} from '../../rows/single-row-builder';\n\nexport class PlainRenderPass extends PrimaryRenderPass {\n\n constructor(public readonly injector:Injector,\n public workPackageTable:WorkPackageTable,\n public rowBuilder:SingleRowBuilder) {\n\n super(injector, workPackageTable, rowBuilder);\n }\n\n /**\n * The actual render function of this renderer.\n */\n protected doRender():void {\n this.workPackageTable.originalRows.forEach((wpId:string) => {\n let row = this.workPackageTable.originalRowIndex[wpId];\n let [tr,] = this.rowBuilder.buildEmpty(row.object);\n row.element = tr;\n this.appendRow(row.object, tr);\n this.tableBody.appendChild(tr);\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {WorkPackageTableRow} from '../../../wp-table.interfaces';\nimport {SingleRowBuilder} from '../../rows/single-row-builder';\nimport {PlainRenderPass} from '../plain/plain-render-pass';\nimport {groupClassNameFor, GroupHeaderBuilder} from './group-header-builder';\nimport {groupByProperty, groupedRowClassName} from './grouped-rows-helpers';\nimport {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {collapsedRowClass} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants\";\nimport {GroupSumsBuilder} from \"core-components/wp-fast-table/builders/modes/grouped/group-sums-builder\";\n\nexport const groupRowClass = '-group-row';\n\nexport class GroupedRenderPass extends PlainRenderPass {\n\n private sumsBuilder = new GroupSumsBuilder(this.injector, this.workPackageTable);\n\n constructor(public readonly injector:Injector,\n public workPackageTable:WorkPackageTable,\n public groups:GroupObject[],\n public headerBuilder:GroupHeaderBuilder,\n public colspan:number) {\n\n super(injector, workPackageTable, new SingleRowBuilder(injector, workPackageTable));\n }\n\n /**\n * Rebuild the entire grouped tbody from the given table\n */\n protected doRender() {\n let currentGroup:GroupObject | null = null;\n const length = this.workPackageTable.originalRows.length;\n this.workPackageTable.originalRows.forEach((wpId:string, index:number) => {\n let row = this.workPackageTable.originalRowIndex[wpId];\n let nextGroup = this.matchingGroup(row.object);\n let groupsChanged = currentGroup !== nextGroup;\n\n // Render the sums row\n if (currentGroup && groupsChanged) {\n this.renderSumsRow(currentGroup);\n }\n\n // Render the next group row\n if (nextGroup && groupsChanged) {\n const groupClass = groupClassNameFor(nextGroup);\n let rowElement = this.headerBuilder.buildGroupRow(nextGroup, this.colspan);\n this.appendNonWorkPackageRow(rowElement, groupClass, [groupRowClass]);\n currentGroup = nextGroup;\n }\n\n row.group = currentGroup;\n this.buildSingleRow(row);\n });\n\n // Render the last sums row\n if (currentGroup) {\n this.renderSumsRow(currentGroup);\n }\n }\n\n /**\n * Find a matching group for the given work package.\n * The API sadly doesn't provide us with the information which group a WP belongs to.\n */\n private matchingGroup(workPackage:WorkPackageResource) {\n return _.find(this.groups, (group:GroupObject) => {\n let property = workPackage[groupByProperty(group)];\n // explicitly check for undefined as `false` (bool) is a valid value.\n if (property === undefined) {\n property = null;\n }\n\n // If the property is a multi-value\n // Compare the href's of all resources with the ones in valueLink\n if (_.isArray(property)) {\n return this.matchesMultiValue(property as HalResource[], group);\n }\n\n //// If its a linked resource, compare the href,\n //// which is an array of links the resource offers\n if (property && property.$href) {\n return !!_.find(group._links.valueLink, (l:any):any => property.$href === l.href);\n }\n\n // Otherwise, fall back to simple value comparison.\n let value = group.value === '' ? null : group.value;\n\n if (value) {\n // For matching we have to remove the % sign which is shown when grouping after progress\n value = value.replace('%', '');\n }\n\n // Values provided by the API are always string\n // so avoid triple equal here\n // tslint:disable-next-line\n return value == property;\n }) as GroupObject;\n }\n\n private matchesMultiValue(property:HalResource[], group:GroupObject) {\n if (property.length !== group.href.length) {\n return false;\n }\n\n let joinedOrderedHrefs = (objects:any[]) => {\n return _.map(objects, object => object.href).sort().join(', ');\n };\n\n return _.isEqualWith(\n property,\n group.href,\n (a, b) => joinedOrderedHrefs(a) === joinedOrderedHrefs(b)\n );\n }\n\n /**\n * Enhance a row from the rowBuilder with group information.\n */\n private buildSingleRow(row:WorkPackageTableRow):void {\n const group = row.group;\n\n if (!group) {\n console.warn(\"All rows should have a group, but this one doesn't %O\", row);\n }\n\n let hidden = false;\n let additionalClasses:string[] = [];\n\n let [tr, _] = this.rowBuilder.buildEmpty(row.object);\n\n if (group) {\n additionalClasses.push(groupedRowClassName(group.index));\n hidden = !!group.collapsed;\n\n if (hidden) {\n additionalClasses.push(collapsedRowClass);\n }\n }\n\n row.element = tr;\n tr.classList.add(...additionalClasses);\n this.appendRow(row.object, tr, additionalClasses, hidden);\n }\n\n /**\n * Render the sums row for the current group\n */\n private renderSumsRow(group:GroupObject) {\n if (!group.sums) {\n return;\n }\n\n const groupClass = groupClassNameFor(group);\n let rowElement = this.sumsBuilder.buildSumsRow(group);\n this.appendNonWorkPackageRow(rowElement, groupClass);\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {States} from '../../../../states.service';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {tableRowClassName} from '../../rows/single-row-builder';\nimport {RowsBuilder} from '../rows-builder';\nimport {GroupHeaderBuilder} from './group-header-builder';\nimport {GroupedRenderPass} from './grouped-render-pass';\nimport {groupedRowClassName, groupIdentifier} from './grouped-rows-helpers';\nimport {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {\n collapsedRowClass,\n rowGroupClassName\n} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class GroupedRowsBuilder extends RowsBuilder {\n\n // Injections\n @InjectField() private readonly querySpace:IsolatedQuerySpace;\n @InjectField() public states:States;\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() public I18n:I18nService;\n\n constructor(public readonly injector:Injector, workPackageTable:WorkPackageTable) {\n super(injector, workPackageTable);\n }\n\n /**\n * The hierarchy builder is only applicable if the hierachy mode is active\n */\n public isApplicable(table:WorkPackageTable) {\n return !_.isEmpty(this.groups);\n }\n\n /**\n * Returns the reference to the last table.groups state value\n */\n public get groups() {\n return this.querySpace.groups.value || [];\n }\n\n /**\n * Returns the reference to the last table.collapesedGroups state value\n */\n public get collapsedGroups() {\n return this.querySpace.collapsedGroups.value || {};\n }\n\n public get colspan() {\n // Columns + manual sorting column + settings column\n return this.wpTableColumns.columnCount + 2;\n }\n\n public buildRows() {\n const builder = new GroupHeaderBuilder(this.injector);\n return new GroupedRenderPass(\n this.injector,\n this.workPackageTable,\n this.getGroupData(),\n builder,\n this.colspan\n ).render();\n }\n\n /**\n * Refresh the group expansion state\n */\n public refreshExpansionState() {\n const groups = this.getGroupData();\n const rendered = this.querySpace.tableRendered.value!;\n const builder = new GroupHeaderBuilder(this.injector);\n\n jQuery(this.workPackageTable.tableAndTimelineContainer)\n .find(`.${rowGroupClassName}`)\n .each((i:number, oldRow:Element) => {\n let groupIndex = jQuery(oldRow).data('groupIndex');\n let group = groups[groupIndex];\n\n // Refresh the group header\n let newRow = builder.buildGroupRow(group, this.colspan);\n\n if (oldRow.parentNode) {\n oldRow.parentNode.replaceChild(newRow, oldRow);\n }\n\n // Set expansion state of contained rows\n const affected = jQuery(this.workPackageTable.tableAndTimelineContainer)\n .find(`.${groupedRowClassName(groupIndex)}`);\n affected.toggleClass(collapsedRowClass, !!group.collapsed);\n\n // Update the hidden section of the rendered state\n affected.filter(`.${tableRowClassName}`).each((i, el) => {\n // Get the index of this row\n const index = jQuery(el).index();\n\n // Update the hidden state\n rendered[index].hidden = !!group.collapsed;\n });\n });\n\n this.querySpace.tableRendered.putValue(rendered, 'Updated hidden state of rows after group change.');\n }\n\n /**\n * Augment the given groups with the current collapsed state data.\n */\n private getGroupData() {\n return this.groups.map((group:GroupObject, index:number) => {\n group.index = index;\n if (group._links && group._links.valueLink) {\n group.href = group._links.valueLink;\n }\n group.identifier = groupIdentifier(group);\n group.collapsed = this.collapsedGroups[group.identifier];\n return group;\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {additionalHierarchyRowClassName, SingleHierarchyRowBuilder} from './single-hierarchy-row-builder';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {PrimaryRenderPass, RowRenderInfo} from \"core-components/wp-fast-table/builders/primary-render-pass\";\nimport {States} from \"core-components/states.service\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageTableRow} from \"core-components/wp-fast-table/wp-table.interfaces\";\nimport {\n ancestorClassIdentifier,\n hierarchyGroupClass\n} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\nimport {WorkPackageViewHierarchies} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-hierarchies\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class HierarchyRenderPass extends PrimaryRenderPass {\n\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() states:States;\n @InjectField() apiV3Service:APIV3Service;\n @InjectField() wpTableHierarchies:WorkPackageViewHierarchiesService;\n\n // Remember which rows were already rendered\n readonly rendered:{ [workPackageId:string]:boolean } = {};\n\n // Remember additional parents inserted that are not part of the results table\n private additionalParents:{ [workPackageId:string]:WorkPackageResource } = {};\n\n // Defer children to be rendered when their parent occurs later in the table\n private deferred:{ [parentId:string]:WorkPackageResource[] } = {};\n\n // Collapsed state\n private hierarchies:WorkPackageViewHierarchies;\n\n // Build a map of hierarchy elements present in the table\n // with at least a visible child\n public parentsWithVisibleChildren:{ [id:string]:boolean } = {};\n\n constructor(public readonly injector:Injector,\n public workPackageTable:WorkPackageTable,\n public rowBuilder:SingleHierarchyRowBuilder) {\n super(injector, workPackageTable, rowBuilder);\n }\n\n protected prepare() {\n super.prepare();\n\n this.hierarchies = this.wpTableHierarchies.current;\n\n _.each(this.workPackageTable.originalRowIndex, (row, ) => {\n row.object.ancestors.forEach((ancestor:WorkPackageResource) => {\n this.parentsWithVisibleChildren[ancestor.id!] = true;\n });\n });\n\n this.rowBuilder.parentsWithVisibleChildren = this.parentsWithVisibleChildren;\n }\n\n /**\n * Render the hierarchy table into the document fragment\n */\n protected doRender() {\n this.workPackageTable.originalRows.forEach((wpId:string) => {\n const row:WorkPackageTableRow = this.workPackageTable.originalRowIndex[wpId];\n const workPackage:WorkPackageResource = row.object;\n\n // If we need to defer this row, skip it for now\n if (this.deferInsertion(workPackage)) {\n return;\n }\n\n if (workPackage.ancestors.length) {\n // If we have ancestors, render it\n this.buildWithHierarchy(row);\n } else {\n // Render a work package root with no parents\n let [tr, hidden] = this.rowBuilder.buildEmpty(workPackage);\n row.element = tr;\n this.tableBody.appendChild(tr);\n this.markRendered(tr, workPackage, hidden);\n }\n\n // Render all potentially deferred rows\n this.renderAllDeferredChildren(workPackage);\n });\n }\n\n /**\n * If the given work package has a visible ancestor in the table, return true\n * and remember the work package until the ancestor is rendered.\n * @param workPackage\n * @returns {boolean}\n */\n public deferInsertion(workPackage:WorkPackageResource):boolean {\n const ancestors = workPackage.ancestors;\n\n // Will only defer if at least one ancestor exists\n if (ancestors.length === 0) {\n return false;\n }\n\n // Cases for wp\n // 1. No wp.ancestors in table -> Render them immediately (defer=false)\n // 2. Parent in table -> deffered[parent] = wp\n // 3. Parent not in table BUT a ancestor in table\n // -> deferred[a ancestor] = parent\n // -> deferred[parent] = wp\n // 4. Any ancestor already rendered -> Render normally (don't defer)\n let ancestorChain = ancestors.concat([workPackage]);\n for (let i = ancestorChain.length - 2; i >= 0; --i) {\n const parent = ancestorChain[i];\n\n const inTable = this.workPackageTable.originalRowIndex[parent.id!];\n const alreadyRendered = this.rendered[parent.id!];\n\n if (alreadyRendered) {\n // parent is already rendered.\n // Don't defer, but render all intermediate parents below it\n return false;\n }\n\n if (inTable) {\n // Get the current elements\n let elements = this.deferred[parent.id!] || [];\n // Append to them the child and all children below\n let newElements:WorkPackageResource[] = ancestorChain.slice(i + 1, ancestorChain.length);\n newElements = newElements.map(child => this.apiV3Service.work_packages.cache.state(child.id!).value!);\n // Append all new elements\n elements = elements.concat(newElements);\n // Remove duplicates (Regression #29652)\n this.deferred[parent.id!] = _.uniqBy(elements, el => el.id!);\n return true;\n }\n // Otherwise, continue the chain upwards\n }\n\n return false;\n }\n\n\n /**\n * Render any deferred children of the given work package. If recursive children were\n * deferred, each of them will be passed through renderCallback.\n * @param workPackage\n */\n private renderAllDeferredChildren(workPackage:WorkPackageResource) {\n const wpId = workPackage.id!;\n const deferredChildren = this.deferred[wpId] || [];\n\n // If the work package has deferred children to render,\n // run them through the callback\n deferredChildren.forEach((child:WorkPackageResource) => {\n this.insertUnderParent(this.getOrBuildRow(child), child.parent || workPackage);\n\n // Descend into any children the child WP might have and callback\n this.renderAllDeferredChildren(child);\n });\n }\n\n private getOrBuildRow(workPackage:WorkPackageResource) {\n let row:WorkPackageTableRow = this.workPackageTable.originalRowIndex[workPackage.id!];\n\n if (!row) {\n row = {object: workPackage} as WorkPackageTableRow;\n }\n\n return row;\n }\n\n private buildWithHierarchy(row:WorkPackageTableRow) {\n // Ancestor data [root, med, thisrow]\n const ancestors = row.object.ancestors;\n const ancestorGroups:string[] = [];\n\n // Iterate ancestors\n ancestors.forEach((el:WorkPackageResource, index:number) => {\n const ancestor = this.states.workPackages.get(el.id!).getValueOr(el);\n\n // If we see the parent the first time,\n // build it as an additional row and insert it into the ancestry\n if (!this.rendered[ancestor.id!]) {\n let [ancestorRow, hidden] = this.rowBuilder.buildAncestorRow(ancestor, ancestorGroups, index);\n // Insert the ancestor row, either right here if it's a root node\n // Or below the appropriate parent\n\n if (index === 0) {\n // Special case, first ancestor => root without parent\n this.tableBody.appendChild(ancestorRow);\n this.markRendered(ancestorRow, ancestor, hidden, true);\n } else {\n // This ancestor must be inserted in the last position of its root\n const parent = ancestors[index - 1];\n this.insertAtExistingHierarchy(ancestor, ancestorRow, parent, hidden, true);\n }\n\n // Remember we just added this extra ancestor row\n this.additionalParents[ancestor.id!] = ancestor;\n }\n\n // Push the correct ancestor groups for identifiying a hierarchy group\n ancestorGroups.push(hierarchyGroupClass(ancestor.id!));\n ancestors.slice(0, index).forEach((previousAncestor) => {\n ancestorGroups.push(hierarchyGroupClass(previousAncestor.id!));\n });\n });\n\n // Insert this row to parent\n const parent = _.last(ancestors);\n this.insertUnderParent(row, parent!);\n }\n\n /**\n * Insert the given node as a child of the parent\n * @param row\n * @param parent\n */\n private insertUnderParent(row:WorkPackageTableRow, parent:WorkPackageResource) {\n const [tr, hidden] = this.rowBuilder.buildEmpty(row.object);\n row.element = tr;\n this.insertAtExistingHierarchy(row.object, tr, parent, hidden, false);\n }\n\n /**\n * Mark the given work package as rendered\n * @param workPackage\n * @param hidden\n * @param isAncestor\n */\n private markRendered(row:HTMLTableRowElement, workPackage:WorkPackageResource, hidden:boolean = false, isAncestor:boolean = false) {\n this.rendered[workPackage.id!] = true;\n this.renderedOrder.push(this.buildRenderInfo(row, workPackage, hidden, isAncestor));\n }\n\n /**\n * Append a row to the given parent hierarchy group.\n */\n private insertAtExistingHierarchy(workPackage:WorkPackageResource,\n el:HTMLTableRowElement,\n parent:WorkPackageResource,\n hidden:boolean,\n isAncestor:boolean) {\n // Either append to the hierarchy group root (= the parentID row itself)\n const hierarchyRoot = `.__hierarchy-root-${parent.id}`;\n // Or, if it has descendants, append to the LATEST of that set\n const hierarchyGroup = `.__hierarchy-group-${parent.id}`;\n\n // Insert into table\n this.spliceRow(\n el,\n `${hierarchyRoot},${hierarchyGroup}`,\n this.buildRenderInfo(el, workPackage, hidden, isAncestor)\n );\n\n this.rendered[workPackage.id!] = true;\n }\n\n private buildRenderInfo(row:HTMLTableRowElement, workPackage:WorkPackageResource, hidden:boolean, isAncestor:boolean):RowRenderInfo {\n let info:RowRenderInfo = {\n element: row,\n classIdentifier: '',\n additionalClasses: [],\n workPackage: workPackage,\n renderType: 'primary',\n hidden: hidden\n };\n\n let [ancestorClasses, _] = this.rowBuilder.ancestorRowData(workPackage);\n\n if (isAncestor) {\n info.additionalClasses = [additionalHierarchyRowClassName].concat(ancestorClasses);\n info.classIdentifier = ancestorClassIdentifier(workPackage.id!);\n } else {\n info.additionalClasses = ancestorClasses;\n info.classIdentifier = this.rowBuilder.classIdentifier(workPackage);\n }\n\n return info as RowRenderInfo;\n }\n}\n","import {Injector} from '@angular/core';\nimport {States} from '../../../../states.service';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {RowsBuilder} from '../rows-builder';\nimport {HierarchyRenderPass} from './hierarchy-render-pass';\nimport {SingleHierarchyRowBuilder} from './single-hierarchy-row-builder';\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HierarchyRowsBuilder extends RowsBuilder {\n\n // Injections\n @InjectField() states:States;\n @InjectField() wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() wpTableHierarchies:WorkPackageViewHierarchiesService;\n\n // The group expansion state\n constructor(public readonly injector:Injector, public workPackageTable:WorkPackageTable) {\n super(injector, workPackageTable);\n }\n\n /**\n * The hierarchy builder is only applicable if the hierachy mode is active\n */\n public isApplicable(_table:WorkPackageTable) {\n return this.wpTableHierarchies.isEnabled;\n }\n\n /**\n * Rebuild the entire grouped tbody from the given table\n */\n public buildRows():HierarchyRenderPass {\n const builder = new SingleHierarchyRowBuilder(this.injector, this.workPackageTable);\n return new HierarchyRenderPass(this.injector, this.workPackageTable, builder).render();\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {PrimaryRenderPass} from '../../primary-render-pass';\nimport {SingleRowBuilder} from '../../rows/single-row-builder';\nimport {RowsBuilder} from '../rows-builder';\nimport {PlainRenderPass} from './plain-render-pass';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class PlainRowsBuilder extends RowsBuilder {\n\n // Injections\n @InjectField() public I18n:I18nService;\n\n // The group expansion state\n constructor(public readonly injector:Injector, workPackageTable:WorkPackageTable) {\n super(injector, workPackageTable);\n }\n\n /**\n * Rebuild the entire grouped tbody from the given table\n */\n public buildRows():PrimaryRenderPass {\n const builder = new SingleRowBuilder(this.injector, this.workPackageTable);\n return new PlainRenderPass(this.injector, this.workPackageTable, builder).render();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injector} from '@angular/core';\nimport {Subscription} from 'rxjs';\nimport {States} from 'core-components/states.service';\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\n\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {FocusHelperService} from \"core-app/modules/common/focus/focus-helper\";\nimport {EditingPortalService} from \"core-app/modules/fields/edit/editing-portal/editing-portal-service\";\nimport {CellBuilder, editCellContainer, tdClassName} from \"core-components/wp-fast-table/builders/cell-builder\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {EditForm} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {editModeClassName} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const activeFieldContainerClassName = 'inline-edit--active-field';\nexport const activeFieldClassName = 'inline-edit--field';\n\nexport class TableEditForm extends EditForm {\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() public apiV3Service!:APIV3Service;\n @InjectField() public states:States;\n @InjectField() public FocusHelper:FocusHelperService;\n @InjectField() public editingPortalService:EditingPortalService;\n\n // Use cell builder to reset edit fields\n private cellBuilder = new CellBuilder(this.injector);\n\n // Subscription\n private resourceSubscription:Subscription = this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .subscribe((wp) => this.resource = wp);\n\n constructor(public injector:Injector,\n public table:WorkPackageTable,\n public workPackageId:string,\n public classIdentifier:string) {\n super(injector);\n }\n\n destroy() {\n this.resourceSubscription.unsubscribe();\n }\n\n public findContainer(fieldName:string):JQuery {\n return this.rowContainer.find(`.${tdClassName}.${fieldName} .${editCellContainer}`).first();\n }\n\n public findCell(fieldName:string) {\n return this.rowContainer.find(`.${tdClassName}.${fieldName}`).first();\n }\n\n public activateField(form:EditForm, schema:IFieldSchema, fieldName:string, errors:string[]):Promise {\n return this.waitForContainer(fieldName)\n .then((cell) => {\n\n // Forcibly set the width since the edit field may otherwise\n // be given more width. Thereby preserve a minimum width of 150.\n // To avoid flickering content, the padding is removed, too.\n const td = this.findCell(fieldName);\n td.addClass(editModeClassName);\n let width = parseInt(td.css('width'));\n width = width > 150 ? width - 10 : 150;\n td.css('max-width', width + 'px');\n td.css('width', width + 'px');\n\n return this.editingPortalService.create(\n cell,\n this.injector,\n form,\n schema,\n fieldName,\n errors\n );\n });\n }\n\n public reset(fieldName:string, focus?:boolean) {\n const cell = this.findContainer(fieldName);\n const td = this.findCell(fieldName);\n\n if (cell.length) {\n this.findCell(fieldName).css('width', '');\n this.findCell(fieldName).css('max-width', '');\n this.cellBuilder.refresh(cell[0], this.resource, fieldName);\n td.removeClass(editModeClassName);\n\n if (focus) {\n this.FocusHelper.focusElement(cell);\n }\n }\n }\n\n public requireVisible(fieldName:string):Promise {\n this.wpTableColumns.addColumn(fieldName);\n return this.waitForContainer(fieldName);\n }\n\n protected focusOnFirstError():void {\n // Focus the first field that is erroneous\n jQuery(this.table.tableAndTimelineContainer)\n .find(`.${activeFieldContainerClassName}.-error .${activeFieldClassName}`)\n .first()\n .trigger('focus');\n }\n\n /**\n * Load the resource form to get the current field schema with all\n * values loaded.\n * @param fieldName\n */\n protected loadFieldSchema(fieldName:string, noWarnings:boolean = false):Promise {\n // We need to handle start/due date cases like they were combined dates\n if (['startDate', 'dueDate', 'date'].includes(fieldName)) {\n fieldName = 'combinedDate';\n }\n\n return super.loadFieldSchema(fieldName, noWarnings);\n }\n\n // Ensure the given field is visible.\n // We may want to look into MutationObserver if we need this in several places.\n private waitForContainer(fieldName:string):Promise {\n return new Promise((resolve, reject) => {\n const interval = setInterval(() => {\n const container = this.findContainer(fieldName);\n\n if (container.length > 0) {\n clearInterval(interval);\n resolve(container[0]);\n }\n }, 100);\n });\n }\n\n private get rowContainer() {\n return jQuery(this.table.tableAndTimelineContainer).find(`.${this.classIdentifier}-table`);\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageTable} from 'core-components/wp-fast-table/wp-fast-table';\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {EditForm} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {TableEditForm} from \"core-components/wp-edit-form/table-edit-form\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class WorkPackageTableEditingContext {\n\n @InjectField() public halEditing:HalResourceEditingService;\n\n constructor(readonly table:WorkPackageTable,\n readonly injector:Injector) {\n }\n\n public forms:{ [wpId:string]:TableEditForm } = {};\n\n public reset() {\n _.each(this.forms, (form) => form.destroy());\n this.forms = {};\n }\n\n public change(workPackage:WorkPackageResource):WorkPackageChangeset|undefined {\n return this.halEditing.typedState(workPackage).value;\n }\n\n // TODO\n public stopEditing(workPackage:WorkPackageResource) {\n this.halEditing.stopEditing(workPackage);\n\n const existing = this.forms[workPackage.id!];\n if (existing) {\n existing.destroy();\n delete this.forms[workPackage.id!];\n }\n }\n\n public startEditing(workPackage:WorkPackageResource, classIdentifier:string):EditForm {\n const wpId = workPackage.id!;\n const existing = this.forms[wpId];\n if (existing) {\n return existing;\n }\n\n // Get any existing edit state for this work package\n return this.forms[wpId] = new TableEditForm(this.injector, this.table, wpId, classIdentifier);\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {IsolatedQuerySpace} from 'core-app/modules/work_packages/query-space/isolated-query-space';\nimport {debugLog} from '../../helpers/debug_output';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../states.service';\nimport {WorkPackageTimelineTableController} from '../wp-table/timeline/container/wp-timeline-container.directive';\nimport {GroupedRowsBuilder} from './builders/modes/grouped/grouped-rows-builder';\nimport {HierarchyRowsBuilder} from './builders/modes/hierarchy/hierarchy-rows-builder';\nimport {PlainRowsBuilder} from './builders/modes/plain/plain-rows-builder';\nimport {RowsBuilder} from './builders/modes/rows-builder';\nimport {PrimaryRenderPass} from './builders/primary-render-pass';\nimport {WorkPackageTableEditingContext} from './wp-table-editing';\nimport {WorkPackageTableRow} from './wp-table.interfaces';\nimport {WorkPackageTableConfiguration} from 'core-app/components/wp-table/wp-table-configuration';\nimport {RenderedWorkPackage} from 'core-app/modules/work_packages/render-info/rendered-work-package.type';\nimport {InjectField} from 'core-app/helpers/angular/inject-field.decorator';\nimport {APIV3Service} from 'core-app/modules/apiv3/api-v3.service';\nimport {WorkPackageViewCollapsedGroupsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service';\n\nexport class WorkPackageTable {\n\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() apiV3Service:APIV3Service;\n @InjectField() states:States;\n @InjectField() I18n!:I18nService;\n @InjectField() workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService;\n\n public originalRows:string[] = [];\n public originalRowIndex:{ [id:string]:WorkPackageTableRow } = {};\n private hierarchyRowsBuilder = new HierarchyRowsBuilder(this.injector, this);\n private groupedRowsBuilder = new GroupedRowsBuilder(this.injector, this);\n private plainRowsBuilder = new PlainRowsBuilder(this.injector, this);\n\n // WP rows builder\n // Ordered by priority\n private builders = [this.hierarchyRowsBuilder, this.groupedRowsBuilder, this.plainRowsBuilder];\n\n // Last render pass used for refreshing single rows\n public lastRenderPass:PrimaryRenderPass|null = null;\n\n // Work package editing context handler in the table, which handles open forms\n // and their contexts\n public editing:WorkPackageTableEditingContext = new WorkPackageTableEditingContext(this, this.injector);\n\n constructor(public readonly injector:Injector,\n public tableAndTimelineContainer:HTMLElement,\n public scrollContainer:HTMLElement,\n public tbody:HTMLElement,\n public timelineBody:HTMLElement,\n public timelineController:WorkPackageTimelineTableController,\n public configuration:WorkPackageTableConfiguration) {\n }\n\n public get renderedRows() {\n return this.querySpace.tableRendered.getValueOr([]);\n }\n\n public findRenderedRow(classIdentifier:string):[number, RenderedWorkPackage] {\n const index = _.findIndex(this.renderedRows, (row) => row.classIdentifier === classIdentifier);\n\n return [index, this.renderedRows[index]];\n }\n\n public get rowBuilder():RowsBuilder {\n return _.find(this.builders, (builder:RowsBuilder) => builder.isApplicable(this))!;\n }\n\n /**\n * Build the row index and positions from the given set of ordered work packages.\n * @param rows\n */\n private buildIndex(rows:WorkPackageResource[]) {\n this.originalRowIndex = {};\n this.originalRows = rows.map((wp:WorkPackageResource, i:number) => {\n let wpId = wp.id!;\n\n // Ensure we get the latest version\n wp = this.apiV3Service.work_packages.cache.current(wpId, wp)!;\n\n this.originalRowIndex[wpId] = { object: wp, workPackageId: wpId, position: i };\n return wpId;\n });\n }\n\n /**\n *\n * @param rows\n */\n public initialSetup(rows:WorkPackageResource[]) {\n // Build the row representation\n this.buildIndex(rows);\n\n // Draw work packages\n this.redrawTableAndTimeline();\n }\n\n /**\n * Removes the contents of this table's tbody and redraws\n * all elements.\n */\n public redrawTableAndTimeline() {\n const renderPass = this.performRenderPass(false);\n\n // Insert timeline body\n requestAnimationFrame(() => {\n this.tbody.innerHTML = '';\n this.timelineBody.innerHTML = '';\n this.tbody.appendChild(renderPass.tableBody);\n this.timelineBody.appendChild(renderPass.timeline.timelineBody);\n\n // Mark rendering event in a timeout to let DOM process\n setTimeout(() =>\n this.querySpace.tableRendered.putValue(renderPass.result)\n );\n });\n }\n\n /**\n * Redraw all elements in the table section only\n */\n public redrawTable() {\n const renderPass = this.performRenderPass();\n this.querySpace.tableRendered.putValue(renderPass.result);\n }\n\n /**\n * Redraw single rows for a given work package being updated.\n */\n public refreshRows(workPackage:WorkPackageResource) {\n const pass = this.lastRenderPass;\n if (!pass) {\n debugLog('Trying to refresh a singular row without a previous render pass.');\n return;\n }\n\n _.each(pass.renderedOrder, (row) => {\n if (row.workPackage && row.workPackage.id === workPackage.id!) {\n debugLog(`Refreshing rendered row ${row.classIdentifier}`);\n row.workPackage = workPackage;\n pass.refresh(row, workPackage, this.tbody);\n }\n });\n }\n\n /**\n * Determine whether we need an empty placeholder row.\n * When D&D is enabled, the table requires a drag target that is non-empty,\n * and the tbody cannot be resized appropriately.\n */\n public get renderPlaceholderRow() {\n return this.configuration.dragAndDropEnabled;\n }\n\n\n /**\n * Perform the render pass\n * @param insert whether to insert the result (set to false for timeline)\n */\n private performRenderPass(insert:boolean = true) {\n this.editing.reset();\n const renderPass = this.lastRenderPass = this.rowBuilder.buildRows();\n\n // Insert table body\n if (insert) {\n requestAnimationFrame(() => {\n this.tbody.innerHTML = '';\n this.tbody.appendChild(renderPass.tableBody);\n });\n }\n\n return renderPass;\n }\n\n setGroupsCollapseState(newState:{[key:string]:boolean}) {\n this.querySpace.collapsedGroups.putValue(newState);\n\n const t0 = performance.now();\n this.groupedRowsBuilder.refreshExpansionState();\n const t1 = performance.now();\n\n debugLog('Group redraw took ' + (t1 - t0) + ' milliseconds.');\n }\n}\n","import {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Injectable} from \"@angular/core\";\n\nexport interface ICKEditorInstance {\n getData(obtions:{ trim:boolean }):string;\n\n setData(content:string):void;\n\n on(event:string, callback:Function):void;\n\n model:any;\n editing:any;\n config:any;\n ui:any;\n element:HTMLElement;\n}\n\nexport interface ICKEditorStatic {\n create(el:HTMLElement, config?:any):Promise;\n\n createCustomized(el:string|HTMLElement, config?:any):Promise;\n}\n\nexport interface ICKEditorContext {\n resource?:HalResource;\n // Specific removing of plugins\n removePlugins?:string[];\n // Set of enabled macro plugins or false to disable all\n macros?:'none'|'wp'|'full'|boolean|string[];\n // Additional options like the text orientation of the editors content\n options?:{\n rtl?:boolean;\n };\n // context link to append on preview requests\n previewContext?:string;\n}\n\ndeclare global {\n interface Window {\n OPConstrainedEditor:ICKEditorStatic;\n OPClassicEditor:ICKEditorStatic;\n }\n}\n\n@Injectable()\nexport class CKEditorSetupService {\n constructor(private PathHelper:PathHelperService) {\n }\n\n /**\n * Create a CKEditor instance of the given type on the wrapper element.\n * Pass a ICKEditorContext object that will be used to decide active plugins.\n *\n *\n * @param {\"full\" | \"constrained\"} type\n * @param {HTMLElement} wrapper\n * @param {ICKEditorContext} context\n * @returns {Promise}\n */\n public async create(type:'full'|'constrained', wrapper:HTMLElement, context:ICKEditorContext, initialData:string|null = null) {\n // Load the bundle\n await this.load();\n\n const editorClass = type === 'constrained' ? window.OPConstrainedEditor : window.OPClassicEditor;\n wrapper.classList.add(`ckeditor-type-${type}`);\n\n const toolbarWrapper = wrapper.querySelector('.document-editor__toolbar') as HTMLElement;\n const contentWrapper = wrapper.querySelector('.document-editor__editable') as HTMLElement;\n\n var contentLanguage = context.options && context.options.rtl ? 'ar' : 'en';\n\n\n const editor:ICKEditorInstance = await editorClass\n .createCustomized(contentWrapper, {\n openProject: this.createConfig(context),\n initialData: initialData,\n language: {\n content: contentLanguage\n }\n });\n\n toolbarWrapper.appendChild(editor.ui.view.toolbar.element);\n\n // Allow custom events on wrapper to set/get data for debugging\n jQuery(wrapper)\n .on('op:ckeditor:setData', (event:any, data:string) => editor.setData(data))\n .on('op:ckeditor:clear', (event:any) => editor.setData(' '))\n .on('op:ckeditor:getData', (event:any, cb:any) => cb(editor.getData({ trim: false })));\n\n return editor;\n }\n\n /**\n * Load the ckeditor asset\n */\n private load():Promise {\n // untyped module cannot be dynamically imported\n // @ts-ignore\n return import(/* webpackChunkName: \"ckeditor\" */ 'core-vendor/ckeditor/ckeditor.js');\n }\n\n private createConfig(context:ICKEditorContext):any {\n if (context.macros === 'none') {\n context.macros = false;\n } else if (context.macros === 'wp') {\n context.macros = [\n 'OPMacroToc',\n 'OPMacroEmbeddedTable',\n 'OPMacroWpButton'\n ];\n } else {\n context.macros = context.macros;\n }\n\n return {\n context: context,\n helpURL: this.PathHelper.textFormattingHelp(),\n pluginContext: window.OpenProject.pluginContext.value\n };\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {AbstractFieldService, IFieldType} from \"core-app/modules/fields/field.service\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\n\nexport interface IEditFieldType extends IFieldType {\n new():EditFieldComponent;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class EditFieldService extends AbstractFieldService {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nexport const selectorTableSide = \".work-packages-tabletimeline--table-side\";\nexport const selectorTimelineSide = \".work-packages-tabletimeline--timeline-side\";\nconst jQueryScrollSyncEventNamespace = \".scroll-sync\";\nconst scrollStep = 15;\n\n\nfunction getXandYScrollDeltas(ev: WheelEvent): [number, number] {\n let x = ev.deltaX;\n let y = ev.deltaY;\n\n if (ev.shiftKey) {\n x = y;\n y = 0;\n }\n\n return [x, y];\n}\n\nfunction getPlattformAgnosticScrollAmount(originalValue: number) {\n if (originalValue === 0) {\n return originalValue;\n }\n\n let delta = scrollStep;\n\n // Browser-specific logic\n // TODO\n\n if (originalValue < 0) {\n delta *= -1;\n }\n return delta;\n}\n\nfunction syncWheelEvent(jev: JQuery.TriggeredEvent, elementTable: JQuery, elementTimeline: JQuery) {\n const scrollTarget = jev.target;\n const ev: WheelEvent = jev.originalEvent as any;\n let [deltaX, deltaY] = getXandYScrollDeltas(ev);\n\n if (deltaY === 0) {\n return;\n }\n\n deltaX = getPlattformAgnosticScrollAmount(deltaX); // apply only in target div\n deltaY = getPlattformAgnosticScrollAmount(deltaY); // apply in both divs\n\n window.requestAnimationFrame(function () {\n elementTable[0].scrollTop = elementTable[0].scrollTop + deltaY;\n elementTimeline[0].scrollTop = elementTimeline[0].scrollTop + deltaY;\n\n scrollTarget.scrollLeft = scrollTarget.scrollLeft + deltaX;\n });\n}\n\n/**\n * Activate or deactivate the scroll-sync between the table and timeline view.\n *\n * @param $element true if the timeline is visible, false otherwise.\n */\nexport function createScrollSync($element:JQuery) {\n\n var elTable = jQuery($element).find(selectorTableSide);\n var elTimeline = jQuery($element).find(selectorTimelineSide);\n\n return (timelineVisible: boolean) => {\n\n // state vars\n var syncedLeft = false;\n var syncedRight = false;\n\n if (timelineVisible) {\n // setup event listener for table\n elTable.on(\"wheel\" + jQueryScrollSyncEventNamespace, (jev: JQuery.TriggeredEvent) => {\n syncWheelEvent(jev, elTable, elTimeline);\n });\n elTable.on(\"scroll\" + jQueryScrollSyncEventNamespace, (ev: JQuery.TriggeredEvent) => {\n syncedLeft = true;\n if (!syncedRight) {\n elTimeline[0].scrollTop = ev.target.scrollTop;\n }\n if (syncedLeft && syncedRight) {\n syncedLeft = false;\n syncedRight = false;\n }\n });\n\n // setup event listener for timeline\n elTimeline.on(\"wheel\" + jQueryScrollSyncEventNamespace, (jev: JQuery.TriggeredEvent) => {\n syncWheelEvent(jev, elTable, elTimeline);\n });\n elTimeline.on(\"scroll\" + jQueryScrollSyncEventNamespace, (ev: JQuery.TriggeredEvent) => {\n syncedRight = true;\n if (!syncedLeft) {\n elTable[0].scrollTop = ev.target.scrollTop;\n }\n if (syncedLeft && syncedRight) {\n syncedLeft = false;\n syncedRight = false;\n }\n });\n } else {\n elTable.off(jQueryScrollSyncEventNamespace);\n }\n };\n\n}\n","
\n \n \n\n \n \n \n \n \n
\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\n\n@Component({\n templateUrl: './authoring.html',\n styleUrls: ['./authoring.sass'],\n selector: 'authoring',\n})\nexport class AuthoringComponent implements OnInit {\n // scope: { createdOn: '=', author: '=', showAuthorAsLink: '=', project: '=', activity: '=' },\n @Input('createdOn') createdOn:string;\n @Input('author') author:HalResource;\n @Input('showAuthorAsLink') showAuthorAsLink:boolean;\n @Input('project') project:any;\n @Input('activity') activity:any;\n\n public createdOnTime:any;\n public timeago:any;\n public time:any;\n public userLink:string;\n\n public constructor(readonly PathHelper:PathHelperService,\n readonly I18n:I18nService,\n readonly timezoneService:TimezoneService) {\n\n }\n\n ngOnInit() {\n this.createdOnTime = this.timezoneService.parseDatetime(this.createdOn);\n this.timeago = this.createdOnTime.fromNow();\n this.time = this.createdOnTime.format('LLL');\n this.userLink = this.PathHelper.userPath(this.author.idFromLink);\n }\n\n public activityFromPath(from:any) {\n var path = this.PathHelper.projectActivityPath(this.project);\n\n if (from) {\n path += '?from=' + from;\n }\n\n return path;\n }\n}\n","
  • \n \n \n \n\n {{ attachment.fileName || attachment.customName || attachment.name }}\n\n \n \n \n \n \n \n\n \n
  • \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, EventEmitter, Input, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {States} from 'core-components/states.service';\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\n\n@Component({\n selector: 'attachment-list-item',\n templateUrl: './attachment-list-item.html'\n})\nexport class AttachmentListItemComponent {\n @Input() public resource:HalResource;\n @Input() public attachment:any;\n @Input() public index:any;\n @Input() destroyImmediately:boolean = true;\n\n @Output() public removeAttachment = new EventEmitter();\n\n static imageFileExtensions:string[] = ['jpeg', 'jpg', 'gif', 'bmp', 'png'];\n\n public text = {\n dragHint: this.I18n.t('js.attachments.draggable_hint'),\n destroyConfirmation: this.I18n.t('js.text_attachment_destroy_confirmation'),\n removeFile: (arg:any) => this.I18n.t('js.label_remove_file', arg)\n };\n\n constructor(protected halNotification:HalResourceNotificationService,\n readonly I18n:I18nService,\n readonly states:States,\n readonly pathHelper:PathHelperService) {\n }\n\n /**\n * Set the appropriate data for drag & drop of an attachment item.\n * @param evt DragEvent\n */\n public setDragData(evt:DragEvent) {\n const url = this.downloadPath;\n const previewElement = this.draggableHTML(url);\n\n evt.dataTransfer!.setData(\"text/plain\", url);\n evt.dataTransfer!.setData(\"text/html\", previewElement.outerHTML);\n evt.dataTransfer!.setData(\"text/uri-list\", url);\n evt.dataTransfer!.setDragImage(previewElement, 0, 0);\n }\n\n public draggableHTML(url:string) {\n let el:HTMLImageElement|HTMLAnchorElement;\n\n if (this.isImage) {\n el = document.createElement('img') as HTMLImageElement;\n el.src = url;\n el.textContent = this.fileName;\n } else {\n el = document.createElement('a') as HTMLAnchorElement;\n el.href = url;\n el.textContent = this.fileName;\n }\n\n return el;\n }\n\n public get downloadPath() {\n return this.pathHelper.attachmentDownloadPath(this.attachment.id, this.fileName);\n }\n\n public get isImage() {\n const ext = this.fileName.split('.').pop() || '';\n return AttachmentListItemComponent.imageFileExtensions.indexOf(ext.toLowerCase()) > -1;\n }\n\n public get fileName() {\n const a = this.attachment;\n return a.fileName || a.customName || a.name;\n }\n\n public confirmRemoveAttachment($event:JQuery.TriggeredEvent) {\n if (!window.confirm(this.text.destroyConfirmation)) {\n $event.stopImmediatePropagation();\n $event.preventDefault();\n return false;\n }\n\n this.removeAttachment.emit();\n\n if (this.destroyImmediately) {\n this\n .resource\n .removeAttachment(this.attachment);\n }\n\n return false;\n }\n}\n","
    \n
      \n \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectorRef, Component, ElementRef, Input, OnInit} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {filter} from \"rxjs/operators\";\nimport {States} from \"core-components/states.service\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Component({\n selector: 'attachment-list',\n templateUrl: './attachment-list.html'\n})\nexport class AttachmentListComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public resource:HalResource;\n @Input() public destroyImmediately:boolean = true;\n\n trackByHref = AngularTrackingHelpers.trackByHref;\n\n attachments:HalResource[] = [];\n deletedAttachments:HalResource[] = [];\n\n public $element:JQuery;\n public $formElement:JQuery;\n\n constructor(protected elementRef:ElementRef,\n protected states:States,\n protected cdRef:ChangeDetectorRef,\n protected halResourceService:HalResourceService) {\n super();\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.updateAttachments();\n this.setupResourceUpdateListener();\n\n if (!this.destroyImmediately) {\n this.setupAttachmentDeletionCallback();\n }\n }\n\n public setupResourceUpdateListener() {\n this.states.forResource(this.resource)!\n .values$()\n .pipe(\n this.untilDestroyed(),\n filter(newResource => !!newResource)\n )\n .subscribe((newResource:HalResource) => {\n this.resource = newResource || this.resource;\n\n this.updateAttachments();\n this.cdRef.detectChanges();\n });\n }\n\n ngOnDestroy():void {\n super.ngOnDestroy();\n if (!this.destroyImmediately) {\n this.$formElement.off('submit.attachment-component');\n }\n }\n\n public removeAttachment(attachment:HalResource) {\n this.deletedAttachments.push(attachment);\n // Keep the same object as we would otherwise loose the connection to the\n // resource's attachments array. That way, attachments added after removing one would not be displayed.\n // This is bad design.\n let newAttachments = this.attachments.filter((el) => el !== attachment);\n this.attachments.length = 0;\n this.attachments.push(...newAttachments);\n\n this.cdRef.detectChanges();\n }\n\n private get attachmentsUpdatable() {\n return (this.resource.attachments && this.resource.attachmentsBackend);\n }\n\n public setupAttachmentDeletionCallback() {\n this.$formElement = this.$element.closest('form');\n this.$formElement.on('submit.attachment-component', () => {\n this.destroyRemovedAttachments();\n });\n }\n\n private destroyRemovedAttachments() {\n this.deletedAttachments.forEach((attachment) => {\n this\n .resource\n .removeAttachment(attachment);\n });\n }\n\n private updateAttachments() {\n if (!this.attachmentsUpdatable) {\n this.attachments = this.resource.attachments.elements;\n return;\n }\n\n this\n .resource\n .attachments\n .updateElements()\n .then(() => {\n this.attachments = this.resource.attachments.elements;\n this.cdRef.detectChanges();\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HighlightableDisplayField extends DisplayField {\n /** Optionally test if we can inject highlighting service */\n @InjectField(WorkPackageViewHighlightingService, null) viewHighlighting:WorkPackageViewHighlightingService;\n\n\n // DisplayFieldRenderer.attributeName returns the 'date' name for the\n // 'dueDate' field because it is its schema.mappedName (that allows to display\n // the correct input type). In the query.highlightedAttributes (used to decide\n // if a field is highlighted) the attribute has the name 'dueDate', so we need\n // to return the original name to get it highlighted.\n get highlightName () {\n if (this.name === 'date') {\n return 'dueDate';\n } else {\n return this.name;\n }\n }\n\n public get shouldHighlight() {\n if (this.context.options.colorize === false) {\n return false;\n }\n\n const shouldHighlight = !!this.viewHighlighting && this.viewHighlighting.shouldHighlightInline(this.highlightName);\n\n return this.context.container !== 'table' || shouldHighlight;\n }\n}\n","import {Injector} from '@angular/core';\nimport {tdClassName} from './cell-builder';\nimport {OpTableActionsService} from 'core-components/wp-table/table-actions/table-actions.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {contextMenuSpanClassName, contextMenuTdClassName} from \"core-components/wp-table/table-actions/table-action\";\nimport {internalContextMenuColumn} from \"core-components/wp-fast-table/builders/internal-sort-columns\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class TableActionRenderer {\n\n // Injections\n @InjectField() tableActionsService:OpTableActionsService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public build(workPackage:WorkPackageResource):HTMLElement {\n // Append details button\n let td = document.createElement('td');\n td.classList.add(tdClassName, contextMenuTdClassName, internalContextMenuColumn.id, 'hide-when-print');\n\n // Wrap any actions in a span\n let span = document.createElement('span');\n span.classList.add(contextMenuSpanClassName);\n\n this.tableActionsService\n .render(workPackage)\n .forEach((el:HTMLElement) => {\n span.appendChild(el);\n });\n\n td.appendChild(span);\n return td;\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {locateTableRowByIdentifier} from 'core-components/wp-fast-table/helpers/wp-table-row-helpers';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {isRelationColumn, QueryColumn} from '../../../wp-query/query-column';\nimport {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {CellBuilder, tdClassName} from '../cell-builder';\nimport {RelationCellbuilder} from '../relation-cell-builder';\nimport {checkedClassName} from '../ui-state-link-builder';\nimport {TableActionRenderer} from 'core-components/wp-fast-table/builders/table-action-renderer';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {\n internalContextMenuColumn,\n internalSortColumn\n} from \"core-components/wp-fast-table/builders/internal-sort-columns\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n// Work package table row entries\nexport const tableRowClassName = 'wp-table--row';\n// Work package and timeline rows\nexport const commonRowClassName = 'wp--row';\n\nexport class SingleRowBuilder {\n\n // Injections\n @InjectField() wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() I18n!:I18nService;\n\n // Cell builder instance\n protected cellBuilder = new CellBuilder(this.injector);\n // Relation cell builder instance\n protected relationCellBuilder = new RelationCellbuilder(this.injector);\n\n // Details Link builder\n protected contextLinkBuilder = new TableActionRenderer(this.injector);\n\n // Build the augmented columns set to render with\n protected readonly augmentedColumns:QueryColumn[] = this.buildAugmentedColumns();\n\n constructor(public readonly injector:Injector,\n protected workPackageTable:WorkPackageTable) {\n }\n\n /**\n * Returns the current set of columns\n */\n public get columns():QueryColumn[] {\n return this.wpTableColumns.getColumns();\n }\n\n /**\n * Returns the current set of columns, augmented by the internal columns\n * we add for buttons and timeline.\n */\n private buildAugmentedColumns():QueryColumn[] {\n let columns = [...this.columns, internalContextMenuColumn];\n\n if (this.workPackageTable.configuration.dragAndDropEnabled) {\n columns.unshift(internalSortColumn);\n }\n\n return columns;\n }\n\n public buildCell(workPackage:WorkPackageResource, column:QueryColumn):HTMLElement|null {\n // handle relation types\n if (isRelationColumn(column)) {\n return this.relationCellBuilder.build(workPackage, column);\n }\n\n // Handle property types\n switch (column.id) {\n case internalContextMenuColumn.id:\n if (this.workPackageTable.configuration.actionsColumnEnabled) {\n return this.contextLinkBuilder.build(workPackage);\n } else if (this.workPackageTable.configuration.columnMenuEnabled) {\n let td = document.createElement('td');\n td.classList.add('hide-when-print');\n return td;\n } else {\n return null;\n }\n default:\n return this.cellBuilder.build(workPackage, column);\n }\n }\n\n /**\n * Build the columns on the given empty row\n */\n public buildEmpty(workPackage:WorkPackageResource):[HTMLTableRowElement, boolean] {\n let row = this.createEmptyRow(workPackage);\n return this.buildEmptyRow(workPackage, row);\n }\n\n /**\n * Create an empty unattached row element for the given work package\n * @param workPackage\n * @returns {any}\n */\n public createEmptyRow(workPackage:WorkPackageResource) {\n const identifier = this.classIdentifier(workPackage);\n let tr = document.createElement('tr');\n tr.setAttribute('tabindex', '0');\n tr.dataset['workPackageId'] = workPackage.id!;\n tr.dataset['classIdentifier'] = identifier;\n tr.classList.add(\n tableRowClassName,\n commonRowClassName,\n identifier,\n `${identifier}-table`,\n 'issue'\n );\n\n return tr;\n }\n\n /**\n * In case the table will end up empty, we insert a placeholder\n * row to provide some space within the tbody.\n */\n public get placeholderRow() {\n const tr:HTMLTableRowElement = document.createElement('tr');\n const td:HTMLTableCellElement = document.createElement('td');\n\n tr.classList.add('wp--placeholder-row');\n td.colSpan = this.augmentedColumns.length;\n tr.appendChild(td);\n\n return tr;\n }\n\n public classIdentifier(workPackage:WorkPackageResource) {\n return `wp-row-${workPackage.id}`;\n }\n\n /**\n * Refresh a row that is currently being edited, that is, some edit fields may be open\n */\n public refreshRow(workPackage:WorkPackageResource, jRow:JQuery):JQuery {\n // Detach all current edit cells\n const cells = jRow.find(`.${tdClassName}`).detach();\n\n // Remember the order of all new edit cells\n const newCells:HTMLElement[] = [];\n\n this.augmentedColumns.forEach((column:QueryColumn) => {\n const oldTd = cells.filter(`td.${column.id}`);\n\n // Treat internal columns specially\n // and skip the replacement of the column if this is being edited.\n // But only do that, if the column existed before. Sometimes, e.g. when lacking permissions\n // the column was not correctly created (with the intended classes). This code then\n // increases the robustness.\n if ((column.id.startsWith('__internal') || this.isColumnBeingEdited(workPackage, column)) && oldTd.length) {\n newCells.push(oldTd[0]);\n return;\n }\n\n // Otherwise, refresh that cell and append it\n const cell = this.buildCell(workPackage, column);\n\n if (cell) {\n newCells.push(cell);\n }\n });\n\n jRow.prepend(newCells);\n return jRow;\n }\n\n protected isColumnBeingEdited(workPackage:WorkPackageResource, column:QueryColumn) {\n const form = this.workPackageTable.editing.forms[workPackage.id!];\n\n return form && form.activeFields[column.id];\n }\n\n protected buildEmptyRow(workPackage:WorkPackageResource, row:HTMLTableRowElement):[HTMLTableRowElement, boolean] {\n const change = this.workPackageTable.editing.change(workPackage);\n let cells:{ [attribute:string]:JQuery } = {};\n\n if (change && !change.isEmpty()) {\n // Try to find an old instance of this row\n const oldRow = locateTableRowByIdentifier(this.classIdentifier(workPackage));\n\n change.changedAttributes.forEach((attribute:string) => {\n cells[attribute] = oldRow.find(`.${tdClassName}.${attribute}`);\n });\n }\n\n this.augmentedColumns.forEach((column:QueryColumn) => {\n let cell:Element|null;\n let oldCell:JQuery|undefined = cells[column.id];\n\n if (oldCell && oldCell.length) {\n debugLog(`Rendering previous open column ${column.id} on ${workPackage.id}`);\n jQuery(row).append(oldCell);\n } else {\n cell = this.buildCell(workPackage, column);\n\n if (cell) {\n row.appendChild(cell);\n }\n }\n });\n\n // Set the row selection state\n if (this.wpTableSelection.isSelected(workPackage.id!)) {\n row.classList.add(checkedClassName);\n }\n\n return [row, false];\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../states.service';\nimport {\n commonRowClassName,\n SingleRowBuilder,\n tableRowClassName\n} from '../wp-fast-table/builders/rows/single-row-builder';\nimport {rowId} from '../wp-fast-table/helpers/wp-table-row-helpers';\nimport {WorkPackageTable} from '../wp-fast-table/wp-fast-table';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {QueryColumn} from \"core-components/wp-query/query-column\";\nimport {tdClassName} from \"core-components/wp-fast-table/builders/cell-builder\";\nimport {internalContextMenuColumn} from \"core-components/wp-fast-table/builders/internal-sort-columns\";\nimport {EditForm} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport const inlineCreateRowClassName = 'wp-inline-create-row';\nexport const inlineCreateCancelClassName = 'wp-table--cancel-create-link';\n\nexport class InlineCreateRowBuilder extends SingleRowBuilder {\n\n // Injections\n @InjectField() public states:States;\n @InjectField() public wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() public I18n:I18nService;\n\n protected text:{ cancelButton:string };\n\n constructor(public readonly injector:Injector,\n workPackageTable:WorkPackageTable) {\n\n super(injector, workPackageTable);\n\n this.text = {\n cancelButton: this.I18n.t('js.button_cancel')\n };\n }\n\n public buildCell(workPackage:WorkPackageResource, column:QueryColumn):HTMLElement|null {\n switch (column.id) {\n case internalContextMenuColumn.id:\n return this.buildCancelButton();\n default:\n return super.buildCell(workPackage, column);\n }\n }\n\n public buildNew(workPackage:WorkPackageResource, form:EditForm):[HTMLElement, boolean] {\n // Get any existing edit state for this work package\n const [row, hidden] = this.buildEmpty(workPackage);\n\n\n return [row, hidden];\n }\n\n /**\n * Create an empty unattached row element for the given work package\n * @param workPackage\n * @returns {any}\n */\n public createEmptyRow(workPackage:WorkPackageResource) {\n const identifier = this.classIdentifier(workPackage);\n const tr = document.createElement('tr');\n tr.id = rowId(workPackage.id!);\n tr.dataset['workPackageId'] = workPackage.id!;\n tr.dataset['classIdentifier'] = identifier;\n tr.classList.add(\n inlineCreateRowClassName, commonRowClassName, tableRowClassName, 'issue',\n identifier,\n `${identifier}-table`\n );\n\n return tr;\n }\n\n protected buildCancelButton() {\n const td = document.createElement('td');\n td.classList.add(tdClassName, 'wp-table--cancel-create-td');\n\n td.innerHTML = `\n \n \n `;\n\n return td;\n }\n}\n","\n \n \n
    \n \n \n \n \n \n \n \n \n \n \n
    \n \n \n \n \n \n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n AfterViewInit,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostListener,\n Injector,\n Input,\n OnInit\n} from '@angular/core';\nimport {AuthorisationService} from 'core-app/modules/common/model-auth/model-auth.service';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {filter} from 'rxjs/operators';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {onClickOrEnter} from '../wp-fast-table/handlers/click-or-enter-handler';\nimport {WorkPackageTable} from '../wp-fast-table/wp-fast-table';\nimport {WorkPackageCreateService} from '../wp-new/wp-create.service';\nimport {\n inlineCreateCancelClassName,\n InlineCreateRowBuilder,\n inlineCreateRowClassName\n} from './inline-create-row-builder';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {Subscription} from 'rxjs';\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {EditForm} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Component({\n selector: '[wpInlineCreate]',\n templateUrl: './wp-inline-create.component.html'\n})\nexport class WorkPackageInlineCreateComponent extends UntilDestroyedMixin implements OnInit, AfterViewInit {\n\n @Input('wp-inline-create--table') table:WorkPackageTable;\n @Input('wp-inline-create--project-identifier') projectIdentifier:string;\n\n // inner state\n public canAdd:boolean = false;\n public canReference:boolean = false;\n\n // Inline create / reference row is active\n public mode:'inactive'|'create'|'reference' = 'inactive';\n\n public focus:boolean = false;\n\n public text = this.wpInlineCreate.buttonTexts;\n\n private currentWorkPackage:WorkPackageResource|null;\n\n private workPackageEditForm:EditForm|undefined;\n\n private editingSubscription:Subscription|undefined;\n\n private $element:JQuery;\n\n get isActive():boolean {\n return this.mode !== 'inactive';\n }\n\n constructor(public readonly injector:Injector,\n protected readonly elementRef:ElementRef,\n protected readonly schemaCache:SchemaCacheService,\n protected readonly I18n:I18nService,\n protected readonly querySpace:IsolatedQuerySpace,\n protected readonly cdRef:ChangeDetectorRef,\n protected readonly wpCreate:WorkPackageCreateService,\n protected readonly wpInlineCreate:WorkPackageInlineCreateService,\n protected readonly wpTableColumns:WorkPackageViewColumnsService,\n protected readonly wpTableFocus:WorkPackageViewFocusService,\n protected readonly authorisationService:AuthorisationService) {\n super();\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n }\n\n ngAfterViewInit() {\n this.authorisationService\n .observeUntil(componentDestroyed(this))\n .subscribe(() => {\n this.canReference = this.hasReferenceClass && this.wpInlineCreate.canReference;\n this.canAdd = this.wpInlineCreate.canAdd;\n this.cdRef.detectChanges();\n\n if (this.canAdd || this.canReference) {\n // Add this row's height as a padding to the timeline\n // so the table and the timeline keep aligned\n const container = jQuery(this.table.timelineBody);\n container.addClass('-inline-create-mirror');\n }\n });\n\n // Register callback on newly created work packages\n this.registerCreationCallback();\n\n // Watch on this scope when the columns change and refresh this row\n this.refreshOnColumnChanges();\n\n // Cancel edition of current new row\n this.registerCancelHandler();\n }\n\n /**\n * Reset the inline creation row on the cancel button,\n * which is dynamically inserted into the action row by the inline create renderer.\n */\n private registerCancelHandler() {\n this.$element.on('click keydown', `.${inlineCreateCancelClassName}`, (evt:JQuery.TriggeredEvent) => {\n onClickOrEnter(evt, () => {\n this.resetRow();\n });\n\n evt.stopImmediatePropagation();\n return false;\n });\n }\n\n /**\n * Since the table is refreshed imperatively whenever columns are changed,\n * we need to manually ensure the inline create row gets refreshed as well.\n */\n private refreshOnColumnChanges() {\n this.wpTableColumns\n .updates$()\n .pipe(\n filter(() => this.isActive), // Take only when row is inserted\n this.untilDestroyed()\n )\n .subscribe(() => this.refreshRow());\n }\n\n /**\n * Listen to newly created work packages to detect whether the WP is the one we created,\n * and properly reset inline create in this case\n */\n private registerCreationCallback() {\n this.wpCreate\n .onNewWorkPackage()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n if (this.currentWorkPackage && this.currentWorkPackage.__initialized_at === wp.__initialized_at) {\n // Remove row and focus\n this.resetRow();\n\n // Split view on the last inserted id if any\n if (!this.table.configuration.isEmbedded) {\n this.wpTableFocus.updateFocus(wp.id!);\n }\n\n // Notify inline create service\n this.wpInlineCreate.newInlineWorkPackageCreated.next(wp.id!);\n } else {\n // Remove current row\n this.wpCreate.cancelCreation();\n this.removeWorkPackageRow();\n this.showRow();\n }\n\n this.cdRef.detectChanges();\n });\n }\n\n public handleAddRowClick() {\n this.addWorkPackageRow();\n return false;\n }\n\n public handleReferenceClick() {\n this.mode = 'reference';\n return false;\n }\n\n public get referenceClass() {\n return this.wpInlineCreate.referenceComponentClass;\n }\n\n public get hasReferenceClass() {\n return !!this.referenceClass;\n }\n\n public addWorkPackageRow() {\n this.wpCreate\n .createOrContinueWorkPackage(this.projectIdentifier)\n .then((change:WorkPackageChangeset) => {\n\n const wp = this.currentWorkPackage = change.projectedResource;\n\n this.editingSubscription = this\n .wpCreate\n .changesetUpdates$()\n .pipe(\n filter(() => !!this.currentWorkPackage),\n ).subscribe((form) => {\n if (!this.isActive) {\n this.insertRow(wp);\n } else {\n this.schemaCache.update(this.currentWorkPackage!, form!.schema);\n this.refreshRow();\n }\n });\n });\n }\n\n private insertRow(wp:WorkPackageResource) {\n // Actually render the row\n const form = this.workPackageEditForm = this.renderInlineCreateRow(wp);\n\n setTimeout(() => {\n // Activate any required fields\n form.activateMissingFields();\n\n // Hide the button row\n this.hideRow();\n });\n }\n\n private refreshRow() {\n const builder = new InlineCreateRowBuilder(this.injector, this.table);\n const rowElement = this.$element.find(`.${inlineCreateRowClassName}`);\n\n if (rowElement.length && this.currentWorkPackage) {\n builder.refreshRow(this.currentWorkPackage, rowElement);\n }\n }\n\n /**\n * Actually render the row manually\n * in the same fashion as all rows in the table are rendered.\n *\n * @param wp Work package to be rendered\n * @returns The work package form of the row\n */\n private renderInlineCreateRow(wp:WorkPackageResource):EditForm {\n const builder = new InlineCreateRowBuilder(this.injector, this.table);\n const form = this.table.editing.startEditing(wp, builder.classIdentifier(wp));\n\n const [row,] = builder.buildNew(wp, form);\n this.$element.append(row);\n\n return form;\n }\n\n /**\n * Reset the new work package row and refocus on the button\n */\n @HostListener('keydown.escape')\n public resetRow() {\n this.focus = true;\n this.removeWorkPackageRow();\n // Manually cancelled, show the row again\n setTimeout(() => {\n this.showRow();\n this.cdRef.detectChanges();\n }, 50);\n }\n\n public removeWorkPackageRow() {\n this.wpCreate.cancelCreation();\n this.currentWorkPackage = null;\n this.$element.find('.wp-row-new').remove();\n if (this.editingSubscription) {\n this.editingSubscription.unsubscribe();\n }\n }\n\n public showRow() {\n this.mode = 'inactive';\n this.cdRef.detectChanges();\n }\n\n public hideRow() {\n this.mode = 'create';\n this.cdRef.detectChanges();\n }\n\n public get colspan():number {\n return this.wpTableColumns.columnCount + 1;\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {States} from 'core-components/states.service';\nimport {combine} from 'reactivestates';\nimport {mapTo} from 'rxjs/operators';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {Observable} from 'rxjs';\nimport {QuerySortByResource} from 'core-app/modules/hal/resources/query-sort-by-resource';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {QueryColumn} from \"core-components/wp-query/query-column\";\n\n@Injectable()\nexport class WorkPackageViewSortByService extends WorkPackageQueryStateService {\n\n constructor(protected readonly states:States,\n protected readonly querySpace:IsolatedQuerySpace,\n protected readonly pathHelper:PathHelperService) {\n super(querySpace);\n }\n\n public valueFromQuery(query:QueryResource) {\n return [...query.sortBy];\n }\n\n public onReadyWithAvailable():Observable {\n return combine(this.pristineState, this.states.queries.sortBy)\n .values$()\n .pipe(\n mapTo(null)\n );\n }\n\n public hasChanged(query:QueryResource) {\n const comparer = (sortBy:QuerySortByResource[]) => sortBy.map(el => el.href);\n\n return !_.isEqual(\n comparer(query.sortBy),\n comparer(this.current)\n );\n }\n\n public applyToQuery(query:QueryResource) {\n const wasManuallySorted = this.isManuallySorted(query.sortBy);\n\n query.sortBy = [...this.current];\n\n // Reload every time unless we stayed in manual sort mode\n return !(wasManuallySorted && this.isManualSortingMode);\n }\n\n public isSortable(column:QueryColumn):boolean {\n return !!_.find(\n this.available,\n (candidate) => candidate.column.$href === column.$href\n );\n }\n\n public addSortCriteria(column:QueryColumn, criteria:string) {\n let available = this.findAvailableDirection(column, criteria);\n\n if (available) {\n this.add(available);\n }\n }\n\n public setAsSingleSortCriteria(column:QueryColumn, criteria:string) {\n let available:QuerySortByResource = this.findAvailableDirection(column, criteria)!;\n\n if (available) {\n this.update([available]);\n }\n }\n\n public findAvailableDirection(column:QueryColumn, direction:string):QuerySortByResource | undefined {\n return _.find(\n this.available,\n (candidate) => (candidate.column.$href === column.$href &&\n candidate.direction.$href === direction)\n );\n }\n\n public add(sortBy:QuerySortByResource) {\n let newValue = _\n .uniqBy([sortBy, ...this.current], sortBy => sortBy.column.$href)\n .slice(0, 3);\n\n this.update(newValue);\n }\n\n public get isManualSortingMode():boolean {\n return this.isManuallySorted(this.current);\n }\n\n public switchToManualSorting(query:QueryResource):boolean {\n let manualSortObject = this.manualSortObject;\n if (manualSortObject && !this.isManualSortingMode) {\n\n if (query && query.persisted) {\n // Save the query if it is persisted\n query.sortBy = [manualSortObject];\n return true;\n } else {\n // Query cannot be saved, just update the props for now\n this.update([manualSortObject]);\n }\n }\n\n return false;\n }\n\n public get current():QuerySortByResource[] {\n return this.lastUpdatedState.getValueOr([]);\n }\n\n private get availableState() {\n return this.states.queries.sortBy;\n }\n\n public get available():QuerySortByResource[] {\n return this.availableState.getValueOr([]);\n }\n\n private isManuallySorted(sortBy:QuerySortByResource[]):boolean {\n if (sortBy && sortBy.length > 0) {\n return sortBy[0].column.href!.endsWith('/manualSorting');\n }\n\n return false;\n }\n\n private get manualSortObject() {\n return _.find(this.available, sort => {\n return sort.column.$href!.endsWith('/manualSorting');\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, EventEmitter, Output} from '@angular/core';\nimport {I18nService} from \"app/modules/common/i18n/i18n.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {Subject} from \"rxjs\";\nimport {debounceTime, distinctUntilChanged, map, tap} from \"rxjs/operators\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {input} from \"reactivestates\";\nimport {QueryFilterResource} from \"core-app/modules/hal/resources/query-filter-resource\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-filter-by-text-input',\n templateUrl: './quick-filter-by-text-input.html'\n})\n\nexport class WorkPackageFilterByTextInputComponent extends UntilDestroyedMixin {\n @Output() public deactivateFilter = new EventEmitter();\n\n public text = {\n createWithDropdown: this.I18n.t('js.work_packages.create.button'),\n createButton: this.I18n.t('js.label_work_package'),\n explanation: this.I18n.t('js.label_create_work_package'),\n placeholder: this.I18n.t('js.work_packages.placeholder_filter_by_text')\n };\n\n /** Observable to the current search filter term */\n public searchTerm = input('');\n\n /** Input for search requests */\n public searchTermChanged:Subject = new Subject();\n\n constructor(readonly I18n:I18nService,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpTableFilters:WorkPackageViewFiltersService) {\n super();\n\n this.wpTableFilters\n .pristine$()\n .pipe(\n this.untilDestroyed(),\n map(() => {\n const currentSearchFilter = this.wpTableFilters.find('search');\n return currentSearchFilter ? (currentSearchFilter.values[0] as string) : '';\n }),\n )\n .subscribe((upstreamTerm:string) => {\n console.log(\"upstream \" + upstreamTerm + \" \" + (this.searchTerm as any).timestampOfLastValue);\n if (!this.searchTerm.value || this.searchTerm.isValueOlderThan(500)) {\n console.log(\"Upstream value setting to \" + upstreamTerm);\n this.searchTerm.putValue(upstreamTerm);\n }\n });\n\n this.searchTermChanged\n .pipe(\n this.untilDestroyed(),\n distinctUntilChanged(),\n tap((val) => this.searchTerm.putValue(val)),\n debounceTime(500),\n )\n .subscribe(term => {\n if (term.length > 0) {\n this.wpTableFilters.replace('search', filter => {\n filter.operator = filter.findOperator('**')!;\n filter.values = [term];\n });\n } else {\n let filter = this.wpTableFilters.find('search');\n\n this.wpTableFilters.remove(filter!);\n\n this.deactivateFilter.emit(filter);\n }\n });\n }\n}\n","\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, EventEmitter, Input, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\n\n@Component({\n selector: 'filter-boolean-value',\n templateUrl: './filter-boolean-value.component.html'\n})\nexport class FilterBooleanValueComponent {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new EventEmitter();\n\n constructor(readonly I18n:I18nService) {\n }\n\n public get value():HalResource | string {\n return this.filter.values[0];\n }\n\n public onFilterUpdated(val:string | HalResource) {\n this.filter.values[0] = val;\n this.filterChanged.emit(this.filter);\n }\n\n}\n","\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {Component, Input, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {DebouncedEventEmitter} from 'core-components/angular/debounced-event-emitter';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Component({\n selector: 'filter-integer-value',\n templateUrl: './filter-integer-value.component.html'\n})\nexport class FilterIntegerValueComponent extends UntilDestroyedMixin {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n constructor(readonly I18n:I18nService,\n readonly schemaCache:SchemaCacheService) {\n super();\n }\n\n public get value() {\n return parseInt(this.filter.values[0] as string);\n }\n\n public set value(val) {\n if (typeof (val) === 'number') {\n this.filter.values = [val.toString()];\n } else {\n this.filter.values = [];\n }\n\n this.filterChanged.emit(this.filter);\n }\n\n public get unit() {\n switch ((this.schema.filter.allowedValues as QueryFilterResource[])[0].id) {\n case 'startDate':\n case 'dueDate':\n case 'updatedAt':\n case 'createdAt':\n return this.I18n.t('js.work_packages.time_relative.days');\n default:\n return '';\n }\n }\n\n private get schema() {\n return this.schemaCache.of(this.filter);\n }\n}\n","
    \n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {DebouncedEventEmitter} from 'core-components/angular/debounced-event-emitter';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\n@Component({\n selector: 'filter-date-value',\n templateUrl: './filter-date-value.component.html'\n})\nexport class FilterDateValueComponent extends UntilDestroyedMixin {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n constructor(readonly timezoneService:TimezoneService,\n readonly I18n:I18nService) {\n super();\n }\n\n public get value():HalResource|string {\n return this.filter.values[0];\n }\n\n public set value(val) {\n this.filter.values = [val as string];\n this.filterChanged.emit(this.filter);\n }\n\n public parser(data:any) {\n if (moment(data, 'YYYY-MM-DD', true).isValid()) {\n return data;\n } else {\n return null;\n }\n }\n\n public formatter(data:any) {\n if (moment(data, 'YYYY-MM-DD', true).isValid()) {\n var d = this.timezoneService.parseDate(data);\n return this.timezoneService.formattedISODate(d);\n } else {\n return null;\n }\n }\n}\n","
    \n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {Component, Input, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {DebouncedEventEmitter} from 'core-components/angular/debounced-event-emitter';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport * as moment from 'moment';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\n@Component({\n selector: 'filter-dates-value',\n templateUrl: './filter-dates-value.component.html'\n})\nexport class FilterDatesValueComponent extends UntilDestroyedMixin {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n readonly text = {\n spacer: this.I18n.t('js.filter.value_spacer')\n };\n\n constructor(readonly timezoneService:TimezoneService,\n readonly I18n:I18nService) {\n super();\n }\n\n public get begin():any {\n return this.filter.values[0];\n }\n\n public set begin(val:any) {\n this.filter.values[0] = val || '';\n this.filterChanged.emit(this.filter);\n }\n\n public get end():HalResource|string {\n return this.filter.values[1];\n }\n\n public set end(val) {\n this.filter.values[1] = val || '';\n this.filterChanged.emit(this.filter);\n }\n\n public parser(data:any) {\n if (moment(data, 'YYYY-MM-DD', true).isValid()) {\n return data;\n } else {\n return null;\n }\n }\n\n public formatter(data:any) {\n if (moment(data, 'YYYY-MM-DD', true).isValid()) {\n var d = this.timezoneService.parseDate(data);\n return this.timezoneService.formattedISODate(d);\n } else {\n return null;\n }\n }\n}\n","
    \n \n \n\n \n \n\n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Moment} from 'moment';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport { OnInit, Directive } from '@angular/core';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Directive()\nexport abstract class AbstractDateTimeValueController extends UntilDestroyedMixin implements OnInit {\n public filter:QueryFilterInstanceResource;\n\n constructor(protected I18n:I18nService,\n protected timezoneService:TimezoneService) {\n super();\n }\n\n ngOnInit() {\n _.remove(this.filter.values as string[], value => !this.timezoneService.isValidISODateTime(value));\n }\n\n public abstract get lowerBoundary():Moment|null;\n\n public abstract get upperBoundary():Moment|null;\n\n public isoDateParser(data:any) {\n if (!this.timezoneService.isValidISODate(data)) {\n return '';\n }\n var d = this.timezoneService.parseISODatetime(data);\n return this.timezoneService.formattedISODateTime(d);\n }\n\n public isoDateFormatter(data:any) {\n if (!this.timezoneService.isValidISODateTime(data)) {\n return '';\n }\n var d = this.timezoneService.parseISODatetime(data);\n return this.timezoneService.formattedISODate(d);\n }\n\n public get isTimeZoneDifferent() {\n let value = this.lowerBoundary || this.upperBoundary;\n\n if (!value) {\n return false;\n } else {\n return value.hours() !== 0 || value.minutes() !== 0;\n }\n }\n\n public get timeZoneText() {\n if (this.lowerBoundary && this.upperBoundary) {\n return this.I18n.t('js.filter.time_zone_converted.two_values',\n {\n from: this.lowerBoundary.format('YYYY-MM-DD HH:mm'),\n to: this.upperBoundary.format('YYYY-MM-DD HH:mm')\n });\n } else if (this.upperBoundary) {\n return this.I18n.t('js.filter.time_zone_converted.only_end',\n { to: this.upperBoundary.format('YYYY-MM-DD HH:mm') });\n\n } else if (this.lowerBoundary) {\n return this.I18n.t('js.filter.time_zone_converted.only_start',\n { from: this.lowerBoundary.format('YYYY-MM-DD HH:mm') });\n\n }\n\n return '';\n }\n}\n","
    \n \n \n \n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, OnInit, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {DebouncedEventEmitter} from 'core-components/angular/debounced-event-emitter';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {Moment} from 'moment';\nimport {AbstractDateTimeValueController} from '../abstract-filter-date-time-value/abstract-filter-date-time-value.controller';\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\n@Component({\n selector: 'filter-date-time-value',\n templateUrl: './filter-date-time-value.component.html'\n})\nexport class FilterDateTimeValueComponent extends AbstractDateTimeValueController implements OnInit {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n constructor(readonly I18n:I18nService,\n readonly timezoneService:TimezoneService) {\n super(I18n, timezoneService);\n }\n\n public get value():HalResource|string {\n return this.filter.values[0];\n }\n\n public get valueString() {\n return this.filter.values[0].toString();\n }\n\n public set value(val) {\n this.filter.values = [val as string];\n this.filterChanged.emit(this.filter);\n }\n\n public get lowerBoundary():Moment|null {\n if (this.value && this.timezoneService.isValidISODateTime(this.valueString)) {\n return this.timezoneService.parseDatetime(this.valueString);\n }\n\n return null;\n }\n\n public get upperBoundary():Moment|null {\n if (this.value && this.timezoneService.isValidISODateTime(this.valueString)) {\n return this.timezoneService.parseDatetime(this.valueString).add(24, 'hours');\n }\n\n return null;\n }\n}\n","
    \n \n \n\n \n \n\n \n \n \n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {Moment} from 'moment';\nimport {AbstractDateTimeValueController} from '../abstract-filter-date-time-value/abstract-filter-date-time-value.controller'\nimport {Component, Input, OnInit, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {DebouncedEventEmitter} from 'core-components/angular/debounced-event-emitter';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\n@Component({\n selector: 'filter-date-times-value',\n templateUrl: './filter-date-times-value.component.html'\n})\nexport class FilterDateTimesValueComponent extends AbstractDateTimeValueController implements OnInit {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n readonly text = {\n spacer: this.I18n.t('js.filter.value_spacer')\n };\n\n constructor(readonly I18n:I18nService,\n readonly timezoneService:TimezoneService) {\n super(I18n, timezoneService);\n }\n\n public get begin():HalResource|string {\n return this.filter.values[0];\n }\n\n public set begin(val) {\n this.filter.values[0] = val || '';\n this.filterChanged.emit(this.filter);\n }\n\n public get end() {\n return this.filter.values[1];\n }\n\n public set end(val) {\n this.filter.values[1] = val || '';\n this.filterChanged.emit(this.filter);\n }\n\n public get lowerBoundary():Moment|null {\n if (this.begin && this.timezoneService.isValidISODateTime(this.begin.toString())) {\n return this.timezoneService.parseDatetime(this.begin.toString());\n } else {\n return null;\n }\n }\n\n public get upperBoundary():Moment|null {\n if (this.end && this.timezoneService.isValidISODateTime(this.end.toString())) {\n return this.timezoneService.parseDatetime(this.end.toString());\n } else {\n return null;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {DebouncedEventEmitter} from 'core-components/angular/debounced-event-emitter';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\n@Component({\n selector: 'filter-string-value',\n templateUrl: './filter-string-value.component.html'\n})\nexport class FilterStringValueComponent extends UntilDestroyedMixin {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n readonly text = {\n enter_text: this.I18n.t('js.work_packages.description_enter_text')\n };\n\n constructor(readonly I18n:I18nService) {\n super();\n }\n\n public get value():HalResource|string {\n return this.filter.values[0];\n }\n\n public set value(val) {\n if (val.length) {\n this.filter.values[0] = val;\n } else {\n this.filter.values.length = 0;\n }\n this.filterChanged.emit(this.filter);\n }\n}\n","
    \n \n \n
    \n","\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {AngularTrackingHelpers} from 'core-components/angular/tracking-functions';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {HalResourceSortingService} from 'core-app/modules/hal/services/hal-resource-sorting.service';\nimport {NgSelectComponent} from '@ng-select/ng-select';\nimport {APIV3Service} from 'core-app/modules/apiv3/api-v3.service';\nimport { DebouncedRequestSwitchmap, errorNotificationHandler } from 'core-app/helpers/rxjs/debounced-input-switchmap';\nimport { ValueOption } from 'core-app/modules/fields/edit/field-types/select-edit-field.component';\nimport { Observable } from 'rxjs';\nimport { HalResourceNotificationService } from 'core-app/modules/hal/services/hal-resource-notification.service';\nimport { CurrentProjectService } from 'core-app/components/projects/current-project.service';\nimport { ApiV3FilterBuilder, FilterOperator } from 'core-app/components/api/api-v3/api-v3-filter-builder';\nimport { map } from 'rxjs/operators';\nimport { APIv3ResourceCollection } from 'core-app/modules/apiv3/paths/apiv3-resource';\nimport { UserResource } from 'core-app/modules/hal/resources/user-resource';\nimport { APIv3UserPaths } from 'core-app/modules/apiv3/endpoints/users/apiv3-user-paths';\nimport { APIV3WorkPackagePaths } from 'core-app/modules/apiv3/endpoints/work_packages/api-v3-work-package-paths';\nimport { WorkPackageResource } from 'core-app/modules/hal/resources/work-package-resource';\nimport { UntilDestroyedMixin } from 'core-app/helpers/angular/until-destroyed.mixin';\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nexport interface FilterConditions {name:string; operator:FilterOperator; values:unknown[]|boolean; }\n\n@Component({\n selector: 'filter-searchable-multiselect-value',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl:'./filter-searchable-multiselect-value.component.html'\n})\n\n\nexport class FilterSearchableMultiselectValueComponent extends UntilDestroyedMixin implements OnInit, AfterViewInit {\n @Input() public filter:QueryFilterInstanceResource;\n @Input() public shouldFocus:boolean = false;\n @Output() public filterChanged = new EventEmitter();\n\n private _isEmpty:boolean;\n public _availableOptions:HalResource[] = [];\n public compareByHrefOrString = AngularTrackingHelpers.compareByHrefOrString;\n public active:Set;\n public requests = new DebouncedRequestSwitchmap(\n (searchTerm:string) => this.loadAvailable(searchTerm),\n errorNotificationHandler(this.halNotification),\n true\n );\n readonly text = {\n placeholder: this.I18n.t('js.placeholders.selection'),\n };\n\n public get value() {\n return this.filter.values;\n }\n public get availableOptions() {\n return this._availableOptions;\n }\n\n public set availableOptions(val:HalResource[]) {\n this._availableOptions = this.halSorting.sort(val);\n }\n\n public get isEmpty():boolean {\n return this._isEmpty = this.value.length === 0;\n }\n\n @ViewChild('ngSelectInstance', { static: true }) ngSelectInstance:NgSelectComponent;\n\n constructor(readonly halResourceService:HalResourceService,\n readonly halSorting:HalResourceSortingService,\n readonly apiV3Service:APIV3Service,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService,\n protected currentProject:CurrentProjectService,\n readonly halNotification:HalResourceNotificationService) {\n super();\n }\n\n ngOnInit() {\n this.initialization();\n // Request an empty value to load warning early on\n this.requests.input$.next('');\n }\n\n ngAfterViewInit():void {\n if (this.ngSelectInstance && this.shouldFocus) {\n this.ngSelectInstance.focus();\n }\n }\n\n initialization() {\n this\n .requests\n .output$.pipe(\n this.untilDestroyed()\n )\n .subscribe((values:HalResource[]) => {\n this.availableOptions = values;\n this.cdRef.detectChanges();\n });\n }\n\n public loadAvailable(matching:string):Observable {\n const filters:ApiV3FilterBuilder = this.createFilters(matching);\n const href = (this.filter.currentSchema!.values!.allowedValues as any).$href;\n\n const filteredData = (this.apiV3Service.collectionFromString(href) as\n APIv3ResourceCollection)\n .filtered(filters)\n .get()\n .pipe(map(collection => collection.elements));\n\n return filteredData;\n }\n\n protected createFilters(matching:string) {\n const filters = new ApiV3FilterBuilder();\n\n if (matching) {\n filters.add('subjectOrId', '**', [matching]);\n }\n\n return filters;\n }\n\n public setValues(val:any) {\n this.filter.values = val.length > 0 ? (Array.isArray(val) ? val : [val]) : [] as HalResource[];\n this.filterChanged.emit(this.filter);\n this.requests.input$.next('');\n this.cdRef.detectChanges();\n }\n\n public repositionDropdown() {\n if (this.ngSelectInstance) {\n const component = (this.ngSelectInstance) as any;\n if (component && component.dropdownPanel) {\n component.dropdownPanel._updatePosition();\n }\n }\n }\n}\n","
    \n\n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {RootResource} from 'core-app/modules/hal/resources/root-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n Input,\n OnInit,\n Output,\n ViewChild\n} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {AngularTrackingHelpers} from 'core-components/angular/tracking-functions';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {HalResourceSortingService} from \"core-app/modules/hal/services/hal-resource-sorting.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {CurrentUserService} from \"core-components/user/current-user.service\";\n\n@Component({\n selector: 'filter-toggled-multiselect-value',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './filter-toggled-multiselect-value.component.html'\n})\nexport class FilterToggledMultiselectValueComponent implements OnInit, AfterViewInit {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new EventEmitter();\n\n @ViewChild('ngSelectInstance', { static: true }) ngSelectInstance:NgSelectComponent;\n\n public _availableOptions:HalResource[] = [];\n public compareByHrefOrString = AngularTrackingHelpers.compareByHrefOrString;\n\n private _isEmpty:boolean;\n\n readonly text = {\n placeholder: this.I18n.t('js.placeholders.selection'),\n };\n\n constructor(readonly halResourceService:HalResourceService,\n readonly halSorting:HalResourceSortingService,\n readonly PathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly currentUser:CurrentUserService,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n }\n\n ngOnInit() {\n this.fetchAllowedValues();\n }\n\n ngAfterViewInit():void {\n if (this.ngSelectInstance && this.shouldFocus) {\n this.ngSelectInstance.focus();\n }\n }\n\n public get value() {\n return this.filter.values;\n }\n\n public setValues(val:any) {\n this.filter.values = _.castArray(val);\n this.filterChanged.emit(this.filter);\n this.cdRef.detectChanges();\n }\n\n public get availableOptions() {\n return this._availableOptions;\n }\n\n public set availableOptions(val:HalResource[]) {\n this._availableOptions = this.halSorting.sort(val);\n }\n\n public get isEmpty():boolean {\n return this._isEmpty = this.value.length === 0;\n }\n\n public repositionDropdown() {\n if (this.ngSelectInstance) {\n setTimeout(() => {\n const component = (this.ngSelectInstance) as any;\n if (component && component.dropdownPanel) {\n component.dropdownPanel._updatePosition();\n }\n }, 25);\n }\n }\n\n private get isUserResource() {\n let type = _.get(this.filter.currentSchema, 'values.type', null);\n return type && type.indexOf('User') > 0;\n }\n\n private fetchAllowedValues() {\n if ((this.filter.currentSchema!.values!.allowedValues as CollectionResource)['$load']) {\n this.loadAllowedValues();\n } else {\n this.availableOptions = (this.filter.currentSchema!.values!.allowedValues as HalResource[]);\n }\n }\n\n private loadAllowedValues() {\n let valuesSchema = this.filter.currentSchema!.values!;\n let loadingPromises = [(valuesSchema.allowedValues as any).$load()];\n\n // If it is a User resource, we want to have the 'me' option.\n // We therefore fetch the current user from the api and copy\n // the current user's value from the set of allowedValues. The\n // copy will have it's name altered to 'me' and will then be\n // prepended to the list.\n if (this.isUserResource) {\n loadingPromises.push(this.apiV3Service.root.get().toPromise());\n }\n\n Promise.all(loadingPromises)\n .then(((resources:Array) => {\n let options = (resources[0] as CollectionResource).elements;\n\n this.availableOptions = options;\n\n if (this.isUserResource && this.filter.filter.id !== 'memberOfGroup') {\n this.addMeValue((resources[1] as RootResource).user);\n }\n }));\n }\n\n private addMeValue(currentUser:UserResource) {\n if (!(currentUser && currentUser.$href)) {\n return;\n }\n\n let me:HalResource = this.halResourceService.createHalResource(\n {\n _links: {\n self: {\n href: this.apiV3Service.users.me,\n title: this.I18n.t('js.label_me')\n }\n }\n }, true\n );\n\n this._availableOptions.unshift(me);\n }\n}\n","
    \n\n \n \n
    \n","\n \n \n\n \n
    \n\n \n\n \n \n \n
    \n \n \n
    \n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n
    \n
    \n\n
    \n
    \n\n
    \n \n \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {AngularTrackingHelpers} from 'core-components/angular/tracking-functions';\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {BannersService} from \"core-app/modules/common/enterprise/banners.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport { CurrentProjectService } from 'core-app/components/projects/current-project.service';\n\n@Component({\n selector: '[query-filter]',\n templateUrl: './query-filter.component.html'\n})\nexport class QueryFilterComponent implements OnInit {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new EventEmitter();\n @Output() public deactivateFilter = new EventEmitter();\n\n public availableOperators:any;\n public showValuesInput:boolean = false;\n public eeShowBanners:boolean = false;\n public trackByHref = AngularTrackingHelpers.halHref;\n public compareByHref = AngularTrackingHelpers.compareByHref;\n\n public text = {\n open_filter: this.I18n.t('js.filter.description.text_open_filter'),\n close_filter: this.I18n.t('js.filter.description.text_close_filter'),\n label_filter_add: this.I18n.t('js.work_packages.label_filter_add'),\n upsale_for_more: this.I18n.t('js.filter.upsale_for_more'),\n upsale_link: this.I18n.t('js.filter.upsale_link'),\n button_delete: this.I18n.t('js.button_delete'),\n };\n\n constructor(readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly schemaCache:SchemaCacheService,\n readonly I18n:I18nService,\n readonly currentProject:CurrentProjectService,\n readonly bannerService:BannersService) {\n }\n\n public onFilterUpdated(filter:QueryFilterInstanceResource) {\n this.filter = filter;\n this.showValuesInput = this.showValues(this.filter);\n this.filterChanged.emit(this.filter);\n }\n\n public removeThisFilter() {\n this.deactivateFilter.emit(this.filter);\n }\n\n public get valueType():string|undefined {\n if (this.filter.currentSchema && this.filter.currentSchema.values) {\n return this.filter.currentSchema.values.type;\n }\n\n return undefined;\n }\n\n ngOnInit() {\n this.eeShowBanners = this.bannerService.eeShowBanners;\n this.availableOperators = this.schemaCache.of(this.filter).availableOperators;\n this.showValuesInput = this.showValues(this.filter);\n }\n\n private showValues(filter:QueryFilterInstanceResource) {\n return this.filter.currentSchema!.isValueRequired() && this.filter.currentSchema!.values!.type !== '[1]Boolean';\n }\n}\n","
    \n \n\n \n \n\n
      \n
    • \n \n\n
      \n \n \n
      \n
    • \n\n
    • \n\n \n
    • \n
    • \n
      \n\n
    • \n\n
    • \n \n \n \n\n
      \n \n \n
      \n
    • \n
    \n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component, Input, OnChanges, OnInit, Output, ViewChild} from '@angular/core';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {DebouncedEventEmitter} from 'core-components/angular/debounced-event-emitter';\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {BannersService} from \"core-app/modules/common/enterprise/banners.service\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {WorkPackageFiltersService} from \"core-components/filters/wp-filters/wp-filters.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\nconst ADD_FILTER_SELECT_INDEX = -1;\n\n\n@Component({\n selector: 'query-filters',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './query-filters.component.html'\n})\nexport class QueryFiltersComponent extends UntilDestroyedMixin implements OnInit, OnChanges {\n\n @ViewChild(NgSelectComponent) public ngSelectComponent:NgSelectComponent;\n @Input() public filters:QueryFilterInstanceResource[];\n @Input() public showCloseFilter:boolean = false;\n @Output() public filtersChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n\n public remainingFilters:any[] = [];\n public eeShowBanners:boolean = false;\n public focusElementIndex:number = 0;\n public trackByName = AngularTrackingHelpers.trackByName;\n\n public text = {\n open_filter: this.I18n.t('js.filter.description.text_open_filter'),\n label_filter_add: this.I18n.t('js.work_packages.label_filter_add'),\n close_filter: this.I18n.t('js.filter.description.text_close_filter'),\n upsale_for_more: this.I18n.t('js.filter.upsale_for_more'),\n upsale_link: this.I18n.t('js.filter.upsale_link'),\n close_form: this.I18n.t('js.close_form_title'),\n selected_filter_list: this.I18n.t('js.label_selected_filter_list'),\n button_delete: this.I18n.t('js.button_delete'),\n please_select: this.I18n.t('js.placeholders.selection'),\n filter_by_text: this.I18n.t('js.work_packages.label_filter_by_text')\n };\n\n constructor(readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly wpFiltersService:WorkPackageFiltersService,\n readonly I18n:I18nService,\n readonly bannerService:BannersService) {\n super();\n }\n\n ngOnInit() {\n this.eeShowBanners = this.bannerService.eeShowBanners;\n }\n\n ngOnChanges() {\n this.updateRemainingFilters();\n }\n\n public onFilterAdded(filterToBeAdded:QueryFilterResource) {\n if (filterToBeAdded) {\n let newFilter = this.wpTableFilters.instantiate(filterToBeAdded);\n this.filters.push(newFilter);\n\n const index = this.currentFilterLength();\n this.updateFilterFocus(index);\n this.updateRemainingFilters();\n\n this.filtersChanged.emit(this.filters);\n this.ngSelectComponent.clearItem(filterToBeAdded);\n }\n }\n\n public closeFilter() {\n this.wpFiltersService.toggleVisibility();\n }\n\n public deactivateFilter(removedFilter:QueryFilterInstanceResource) {\n let index = this.filters.indexOf(removedFilter);\n _.remove(this.filters, f => f.id === removedFilter.id);\n\n this.filtersChanged.emit(this.filters);\n\n this.updateFilterFocus(index);\n this.updateRemainingFilters();\n }\n\n public get isSecondSpacerVisible():boolean {\n const hasSearch = !!_.find(this.filters, (f) => f.id === 'search');\n const hasAvailableFilter = !!this.filters.find((f) => f.id !== 'search' && this.isFilterAvailable(f));\n\n return hasSearch && hasAvailableFilter;\n }\n\n private updateRemainingFilters() {\n this.remainingFilters = _.sortBy(this.wpTableFilters.remainingVisibleFilters(this.filters), 'name');\n }\n\n private updateFilterFocus(index:number) {\n let activeFilterCount = this.currentFilterLength();\n\n if (activeFilterCount === 0) {\n this.focusElementIndex = ADD_FILTER_SELECT_INDEX;\n } else {\n const filterIndex = (index < activeFilterCount) ? index : activeFilterCount - 1;\n const filter = this.currentFilterAt(filterIndex);\n this.focusElementIndex = this.filters.indexOf(filter);\n }\n }\n\n public currentFilterLength() {\n return this.filters.length;\n }\n\n public currentFilterAt(index:number) {\n return this.filters[index];\n }\n\n public isFilterAvailable(filter:QueryFilterResource):boolean {\n return (this.wpTableFilters.availableFilters.some(availableFilter => availableFilter.id === filter.id) &&\n !(this.wpTableFilters.hidden.includes(filter.id) || filter.isTemplated()));\n }\n\n public onOpen() {\n setTimeout(() => {\n const component = this.ngSelectComponent as any;\n if (component && component.dropdownPanel) {\n component.dropdownPanel._updatePosition();\n }\n }, 25);\n }\n}\n","import { Injectable } from '@angular/core';\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Injectable({\n providedIn: 'root'\n})\nexport class GlobalEditFormChangesTrackerService {\n private activeForms = new Map();\n\n get thereAreFormsWithUnsavedChanges () {\n return Array.from(this.activeForms.keys()).some(form => {\n return !form.change.isEmpty();\n });\n }\n\n constructor(\n private i18nService:I18nService,\n ) {\n // Global beforeunload hook to show a data loss warn\n // when the user clicks on a link out of the Angular app\n window.addEventListener('beforeunload', (event) => {\n if (this.thereAreFormsWithUnsavedChanges) {\n event.preventDefault();\n event.returnValue = this.i18nService.t('js.work_packages.confirm_edit_cancel');\n }\n });\n }\n\n public addToActiveForms(form:EditFormComponent) {\n this.activeForms.set(form, true);\n }\n\n public removeFromActiveForms(form:EditFormComponent) {\n this.activeForms.delete(form);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, EventEmitter, Injector, Input, OnDestroy, OnInit, Optional, Output} from '@angular/core';\nimport {StateService, Transition, TransitionService} from '@uirouter/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {EditableAttributeFieldComponent} from 'core-app/modules/fields/edit/field/editable-attribute-field.component';\nimport {input} from 'reactivestates';\nimport {filter, map, take} from 'rxjs/operators';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n activeFieldClassName,\n activeFieldContainerClassName,\n EditForm\n} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {EditingPortalService} from \"core-app/modules/fields/edit/editing-portal/editing-portal-service\";\nimport {EditFormRoutingService} from \"core-app/modules/fields/edit/edit-form/edit-form-routing.service\";\nimport {ResourceChangesetCommit} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {GlobalEditFormChangesTrackerService} from \"core-app/modules/fields/edit/services/global-edit-form-changes-tracker/global-edit-form-changes-tracker.service\";\n\n@Component({\n selector: 'edit-form,[edit-form]',\n template: ''\n})\nexport class EditFormComponent extends EditForm implements OnInit, OnDestroy {\n @Input('resource') resource:HalResource;\n @Input('inEditMode') initializeEditMode:boolean = false;\n @Input('skippedFields') skippedFields:string[] = [];\n\n @Output('onSaved') onSavedEmitter = new EventEmitter<{ savedResource:HalResource, isInitial:boolean }>();\n\n public fields:{ [attribute:string]:EditableAttributeFieldComponent } = {};\n private registeredFields = input();\n private unregisterListener:Function;\n\n constructor(public readonly injector:Injector,\n protected readonly elementRef:ElementRef,\n protected readonly $transitions:TransitionService,\n protected readonly ConfigurationService:ConfigurationService,\n protected readonly editingPortalService:EditingPortalService,\n protected readonly $state:StateService,\n protected readonly I18n:I18nService,\n @Optional() protected readonly editFormRouting:EditFormRoutingService,\n private globalEditFormChangesTrackerService:GlobalEditFormChangesTrackerService) {\n super(injector);\n\n const confirmText = I18n.t('js.work_packages.confirm_edit_cancel');\n const requiresConfirmation = ConfigurationService.warnOnLeavingUnsaved();\n\n this.unregisterListener = $transitions.onBefore({}, (transition:Transition) => {\n if (!this.editing) {\n return undefined;\n }\n\n // Show confirmation message when transitioning to a new state\n // that's not within the edit mode.\n if (!this.editFormRouting || this.editFormRouting.blockedTransition(transition)) {\n if (requiresConfirmation && !window.confirm(confirmText)) {\n return false;\n }\n\n this.cancel(false);\n }\n\n return true;\n });\n }\n\n ngOnInit() {\n this.editMode = this.initializeEditMode;\n this.globalEditFormChangesTrackerService.addToActiveForms(this);\n\n if (this.initializeEditMode) {\n this.start();\n }\n }\n\n ngOnDestroy() {\n this.unregisterListener();\n this.globalEditFormChangesTrackerService.removeFromActiveForms(this);\n }\n\n public async activateField(form:EditForm, schema:IFieldSchema, fieldName:string, errors:string[]):Promise {\n return this.waitForField(fieldName).then((ctrl) => {\n ctrl.setActive(true);\n const container = ctrl.editContainer.nativeElement;\n return this.editingPortalService.create(\n container,\n this.injector,\n form,\n schema,\n fieldName,\n errors\n );\n });\n }\n\n public async reset(fieldName:string, focus:boolean = false) {\n const ctrl = await this.waitForField(fieldName);\n ctrl.reset();\n ctrl.deactivate(focus);\n }\n\n public onSaved(commit:ResourceChangesetCommit) {\n this.cancel(false);\n this.onSavedEmitter.emit({savedResource: commit.resource, isInitial: commit.wasNew });\n }\n\n public cancel(reset:boolean = false) {\n this.editMode = false;\n this.closeEditFields('all', reset);\n\n if (reset) {\n this.halEditing.reset(this.change);\n }\n }\n\n public requireVisible(fieldName:string):Promise {\n return new Promise((resolve, _) => {\n const interval = setInterval(() => {\n const field = this.fields[fieldName];\n\n if (field !== undefined) {\n clearInterval(interval);\n resolve();\n }\n }, 50);\n });\n }\n\n public get editing():boolean {\n return this.editMode || this.hasActiveFields();\n }\n\n public register(field:EditableAttributeFieldComponent) {\n this.fields[field.fieldName] = field;\n this.registeredFields.putValue(_.keys(this.fields));\n\n const shouldActivate =\n (this.editMode && !this.skipField(field) || this.activeFields[field.fieldName]);\n\n if (shouldActivate) {\n field.activateOnForm(true);\n }\n }\n\n public waitForField(name:string):Promise {\n return this.registeredFields\n .values$()\n .pipe(\n filter(keys => keys.indexOf(name) >= 0),\n take(1),\n map(() => this.fields[name])\n )\n .toPromise();\n }\n\n public start() {\n _.each(this.fields, ctrl => this.activate(ctrl.fieldName));\n }\n\n protected focusOnFirstError():void {\n // Focus the first field that is erroneous\n jQuery(this.elementRef.nativeElement)\n .find(`.${activeFieldContainerClassName}.-error .${activeFieldClassName}`)\n .first()\n .trigger('focus');\n }\n\n private skipField(field:EditableAttributeFieldComponent) {\n const fieldName = field.fieldName;\n\n const isSkipField = this.skippedFields.indexOf(fieldName) !== -1;\n\n // Only skip status or type\n if (!isSkipField) {\n return false;\n }\n\n // Only skip if value present and not changed in changeset\n const hasDefault = this.resource[fieldName];\n const changed = this.change.changes[fieldName];\n\n return hasDefault && !changed;\n }\n}\n","import {AfterViewInit, ChangeDetectorRef, Directive, Input, SimpleChanges} from '@angular/core';\nimport {CurrentProjectService} from '../../projects/current-project.service';\nimport {WorkPackageStatesInitializationService} from '../../wp-list/wp-states-initialization.service';\nimport {\n WorkPackageTableConfiguration,\n WorkPackageTableConfigurationObject\n} from 'core-components/wp-table/wp-table-configuration';\nimport {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service';\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackagesViewBase} from \"core-app/modules/work_packages/routing/wp-view-base/work-packages-view.base\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Directive()\nexport abstract class WorkPackageEmbeddedBaseComponent extends WorkPackagesViewBase implements AfterViewInit {\n @Input('configuration') protected providedConfiguration:WorkPackageTableConfigurationObject;\n @Input() public uniqueEmbeddedTableName:string = `embedded-table-${Date.now()}`;\n @Input() public initialLoadingIndicator:boolean = true;\n\n public renderTable = false;\n public showTablePagination = false;\n public configuration:WorkPackageTableConfiguration;\n public error:string|null = null;\n\n protected initialized:boolean = false;\n\n @InjectField() apiV3Service:APIV3Service;\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() I18n!:I18nService;\n @InjectField() urlParamsHelper:UrlParamsHelperService;\n @InjectField() loadingIndicatorService:LoadingIndicatorService;\n @InjectField() wpStatesInitialization:WorkPackageStatesInitializationService;\n @InjectField() currentProject:CurrentProjectService;\n @InjectField() cdRef:ChangeDetectorRef;\n\n ngOnInit() {\n this.configuration = new WorkPackageTableConfiguration(this.providedConfiguration);\n // Set embedded status in configuration\n this.configuration.isEmbedded = true;\n this.initialized = true;\n\n super.ngOnInit();\n }\n\n ngAfterViewInit():void {\n // Load initially\n this.loadQuery(true, false);\n }\n\n ngOnChanges(changes:SimpleChanges) {\n if (this.initialized && (changes.queryId || changes.queryProps)) {\n this.loadQuery(this.initialLoadingIndicator, false);\n }\n }\n\n public get projectIdentifier() {\n if (this.configuration.projectContext) {\n return this.currentProject.identifier || undefined;\n } else {\n return this.configuration.projectIdentifier || undefined;\n }\n }\n\n public buildQueryProps() {\n const query = this.querySpace.query.value!;\n this.wpStatesInitialization.applyToQuery(query);\n\n return this.urlParamsHelper.buildV3GetQueryFromQueryResource(query);\n }\n\n public buildUrlParams() {\n const query = this.querySpace.query.value!;\n this.wpStatesInitialization.applyToQuery(query);\n\n return this.urlParamsHelper.encodeQueryJsonParams(query);\n }\n\n protected setLoaded() {\n this.renderTable = this.configuration.tableVisible;\n this.cdRef.detectChanges();\n }\n\n public refresh(visible:boolean = true, firstPage:boolean = false):Promise {\n const query = this.querySpace.query.value!;\n const pagination = this.wpTablePagination.paginationObject;\n\n if (firstPage) {\n pagination.offset = 1;\n }\n\n const params = this.urlParamsHelper.buildV3GetQueryFromQueryResource(query, pagination);\n const promise =\n this\n .wpListService\n .loadQueryFromExisting(query, params, this.queryProjectScope)\n .toPromise()\n .then((query) => this.wpStatesInitialization.updateQuerySpace(query, query.results));\n\n if (visible) {\n this.loadingIndicator = promise;\n }\n return promise;\n }\n\n public get isInitialized() {\n return !!this.configuration;\n }\n\n public set loadingIndicator(promise:Promise) {\n if (this.configuration.tableVisible) {\n this.loadingIndicatorService\n .indicator(this.uniqueEmbeddedTableName)\n .promise = promise;\n }\n }\n\n public abstract loadQuery(visible:boolean, firstPage:boolean):Promise;\n\n protected get queryProjectScope() {\n if (!this.configuration.projectContext) {\n return undefined;\n } else {\n return this.projectIdentifier;\n }\n }\n\n protected initializeStates(query:QueryResource) {\n this.wpStatesInitialization.clearStates();\n this.wpStatesInitialization.initializeFromQuery(query, query.results);\n this.wpStatesInitialization.updateQuerySpace(query, query.results);\n }\n}\n","
    \n\n \n \n \n\n \n\n \n \n\n \n
    \n \n \n
    \n\n \n \n
    \n\n
    \n \n
    \n
    \n","import {AfterViewInit, Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';\nimport {WorkPackageViewTimelineService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service';\nimport {WorkPackageViewPaginationService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service';\nimport {OpTableActionFactory} from 'core-components/wp-table/table-actions/table-action';\nimport {OpTableActionsService} from 'core-components/wp-table/table-actions/table-actions.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WpTableConfigurationModalComponent} from 'core-components/wp-table/configuration-modal/wp-table-configuration.modal';\nimport {OpModalService} from 'core-components/op-modals/op-modal.service';\nimport {WorkPackageEmbeddedBaseComponent} from \"core-components/wp-table/embedded/wp-embedded-base.component\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {distinctUntilChanged, map, take, withLatestFrom} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {KeepTabService} from \"core-components/wp-single-view-tabs/keep-tab/keep-tab.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-embedded-table',\n templateUrl: './wp-embedded-table.html'\n})\nexport class WorkPackageEmbeddedTableComponent extends WorkPackageEmbeddedBaseComponent implements OnInit, AfterViewInit, OnDestroy {\n @Input('queryId') public queryId?:string;\n @Input('queryProps') public queryProps:any = {};\n @Input() public tableActions:OpTableActionFactory[] = [];\n @Input() public externalHeight:boolean = false;\n\n /** Inform about loading errors */\n @Output() public onError = new EventEmitter();\n\n /** Inform about loaded query */\n @Output() public onQueryLoaded = new EventEmitter();\n\n @InjectField() apiv3Service:APIV3Service;\n @InjectField() opModalService:OpModalService;\n @InjectField() tableActionsService:OpTableActionsService;\n @InjectField() wpTableTimeline:WorkPackageViewTimelineService;\n @InjectField() wpTablePagination:WorkPackageViewPaginationService;\n @InjectField() keepTab:KeepTabService;\n\n // Cache the form promise\n private formPromise:Promise|undefined;\n\n // If the query was provided to use via the query space,\n // use it to cache first loading\n private loadedQuery:QueryResource|undefined;\n\n ngOnInit() {\n super.ngOnInit();\n this.loadedQuery = this.querySpace.query.value;\n }\n\n ngAfterViewInit():void {\n super.ngAfterViewInit();\n\n // Provision embedded table actions\n if (this.tableActions) {\n this.tableActionsService.setActions(...this.tableActions);\n }\n\n // Reload results on changes to pagination (Regression #29845)\n this.wpTablePagination\n .updates$()\n .pipe(\n map(pagination => [pagination.page, pagination.perPage]),\n distinctUntilChanged(),\n this.untilDestroyed(),\n withLatestFrom(this.querySpace.query.values$())\n ).subscribe(([_, query]) => {\n const pagination = this.wpTablePagination.paginationObject;\n const params = this.urlParamsHelper.buildV3GetQueryFromQueryResource(query, pagination);\n\n this.loadingIndicator =\n this\n .wpListService\n .loadQueryFromExisting(query, params, this.queryProjectScope)\n .toPromise()\n .then((query) => this.initializeStates(query));\n });\n }\n\n public openConfigurationModal(onUpdated:() => void) {\n this.querySpace.query\n .valuesPromise()\n .then(() => {\n const modal = this.opModalService\n .show(WpTableConfigurationModalComponent, this.injector);\n\n // Detach this component when the modal closes and pass along the query data\n modal.onDataUpdated.subscribe(onUpdated);\n });\n }\n\n protected initializeStates(query:QueryResource) {\n // If the configuration requests filters, we need to load the query form as well.\n if (this.configuration.withFilters) {\n this.loadForm(query);\n }\n\n super.initializeStates(query);\n\n\n this.querySpace\n .initialized\n .values$()\n .pipe(take(1))\n .subscribe(() => {\n this.showTablePagination = query.results.total > query.results.count;\n this.setLoaded();\n\n // Disable compact mode when timeline active\n if (this.wpTableTimeline.isVisible) {\n this.configuration = { ...this.configuration, compactTableStyle: false };\n }\n });\n }\n\n private loadForm(query:QueryResource):Promise {\n if (this.formPromise) {\n return this.formPromise;\n }\n\n return this.formPromise =\n this\n .apiv3Service\n .withOptionalProject(this.projectIdentifier)\n .queries\n .form\n .load(query)\n .toPromise()\n .then(([form, _]) => {\n this.wpStatesInitialization.updateStatesFromForm(query, form);\n return form;\n })\n .catch(() => this.formPromise = undefined);\n }\n\n public loadQuery(visible:boolean = true, firstPage:boolean = false):Promise {\n // Ensure we are loading the form.\n this.formPromise = undefined;\n\n if (this.loadedQuery) {\n const query = this.loadedQuery;\n this.loadedQuery = undefined;\n this.initializeStates(query);\n return Promise.resolve(this.loadedQuery!);\n }\n\n // HACK: Decrease loading time of queries when results are not needed.\n // We should allow the backend to disable results embedding instead.\n if (!this.configuration.tableVisible) {\n this.queryProps.pageSize = 1;\n }\n\n // Set first page\n if (firstPage) {\n this.queryProps.page = 1;\n }\n\n this.error = null;\n const promise = this\n .apiv3Service\n .queries\n .find(\n this.queryProps,\n this.queryId,\n this.queryProjectScope\n )\n .toPromise()\n .then((query:QueryResource) => {\n this.initializeStates(query);\n this.onQueryLoaded.emit(query);\n return query;\n })\n .catch((error) => {\n this.error = this.I18n.t(\n 'js.error.embedded_table_loading',\n { message: _.get(error, 'message', error) }\n );\n this.onError.emit(error);\n });\n\n if (visible) {\n this.loadingIndicator = promise;\n }\n\n return promise;\n }\n\n handleWorkPackageClicked(event:{ workPackageId:string; double:boolean }) {\n if (event.double) {\n this.$state.go(\n 'work-packages.show',\n { workPackageId: event.workPackageId }\n );\n }\n }\n\n openStateLink(event:{ workPackageId:string; requestedState:string }) {\n this.$state.go(\n (this.keepTab as any)[event.requestedState] || event.requestedState,\n { workPackageId: event.workPackageId, focus: true }\n );\n }\n}\n","import {\n AfterViewInit,\n Component,\n ElementRef,\n EventEmitter,\n Injector,\n Input,\n OnDestroy,\n OnInit,\n Output\n} from \"@angular/core\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {\n OpEditingPortalChangesetToken,\n OpEditingPortalHandlerToken,\n OpEditingPortalSchemaToken\n} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {createLocalInjector} from \"core-app/modules/fields/edit/editing-portal/edit-form-portal.injector\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {EditFieldService, IEditFieldType} from \"core-app/modules/fields/edit/edit-field.service\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\n\n@Component({\n selector: 'edit-form-portal',\n templateUrl: './edit-form-portal.component.html'\n})\nexport class EditFormPortalComponent implements OnInit, OnDestroy, AfterViewInit {\n @Input() schemaInput:IFieldSchema;\n @Input() changeInput:ResourceChangeset;\n @Input() editFieldHandler:EditFieldHandler;\n @Output() public onEditFieldReady = new EventEmitter();\n\n public handler:EditFieldHandler;\n public schema:IFieldSchema;\n public change:ResourceChangeset;\n public fieldInjector:Injector;\n\n public componentClass:IEditFieldType;\n public htmlId:string;\n public label:string;\n\n constructor(readonly injector:Injector,\n readonly editField:EditFieldService,\n readonly elementRef:ElementRef) {\n }\n\n ngOnInit() {\n if (this.editFieldHandler && this.schemaInput) {\n this.handler = this.editFieldHandler;\n this.schema = this.schemaInput;\n this.change = this.changeInput;\n\n } else {\n this.handler = this.injector.get(OpEditingPortalHandlerToken);\n this.schema = this.injector.get(OpEditingPortalSchemaToken);\n this.change = this.injector.get(OpEditingPortalChangesetToken);\n }\n\n this.componentClass = this.editField.getSpecificClassFor(this.change.pristineResource._type, this.handler.fieldName, this.schema.type);\n this.fieldInjector = createLocalInjector(this.injector, this.change, this.handler, this.schema);\n }\n\n ngOnDestroy() {\n this.onEditFieldReady.complete();\n }\n\n ngAfterViewInit() {\n // Fire in a timeout to avoid same execution context in AfterViewInit\n setTimeout(() => {\n this.onEditFieldReady.emit();\n });\n }\n}\n","
    \n
    \n\n \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {SchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\n\nexport class WorkPackageSchemaProxy extends SchemaProxy {\n get(schema:SchemaResource, property:PropertyKey, receiver:any):any {\n switch (property) {\n case 'isMilestone': {\n return this.isMilestone;\n }\n case 'isReadonly': {\n return this.isReadonly;\n }\n default: {\n return super.get(schema, property, receiver);\n }\n }\n }\n\n /**\n * Returns the part of the schema relevant for the provided property.\n *\n * We use it to support the virtual attribute 'combinedDate' which is the combination of the three\n * attributes 'startDate', 'dueDate' and 'scheduleManually'. That combination exists only in the front end\n * and not on the native schema. As a property needs to be writable for us to allow the user editing,\n * we need to mark the writability positively if any of the combined properties are writable.\n *\n * @param property the schema part is desired for\n */\n public ofProperty(property:string) {\n if (property === 'combinedDate') {\n let propertySchema = super.ofProperty('startDate');\n\n if (!propertySchema) {\n return null;\n }\n\n propertySchema.writable = propertySchema.writable ||\n this.isAttributeEditable('dueDate') ||\n this.isAttributeEditable('scheduleManually');\n\n return propertySchema;\n } else {\n return super.ofProperty(property);\n }\n }\n\n public get isReadonly():boolean {\n return this.resource.status?.isReadonly;\n }\n\n /**\n * Return whether the work package is editable with the user's permission\n * on the given work package attribute.\n *\n * @param property\n */\n public isAttributeEditable(property:string):boolean {\n if (this.isReadonly && property !== 'status') {\n return false;\n } else if (['startDate', 'dueDate', 'date'].includes(property) &&\n this.resource.scheduleManually) {\n // This is a blatant shortcut but should be adequate.\n return super.isAttributeEditable('scheduleManually');\n } else {\n return super.isAttributeEditable(property);\n }\n }\n\n public get isMilestone():boolean {\n return this.schema.hasOwnProperty('date');\n }\n\n public mappedName(property:string):string {\n if (this.isMilestone && (property === 'startDate' || property === 'dueDate')) {\n return 'date';\n } else {\n return property;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\n\n@Injectable({ providedIn: 'root' })\nexport class FocusHelperService {\n private minimumOffsetForNewSwitchInMs = 100;\n private lastFocusSwitch = -this.minimumOffsetForNewSwitchInMs;\n private lastPriority = -1;\n\n private static FOCUSABLE_SELECTORS = 'a, button, :input, [tabindex], select';\n\n public throttleAndCheckIfAllowedFocusChangeBasedOnTimeout() {\n var allowFocusSwitch = (Date.now() - this.lastFocusSwitch) >= this.minimumOffsetForNewSwitchInMs;\n\n // Always update so that a chain of focus-change-requests gets considered as one\n this.lastFocusSwitch = Date.now();\n\n return allowFocusSwitch;\n }\n\n public checkIfAllowedFocusChange(priority?:any) {\n var checkTimeout = this.throttleAndCheckIfAllowedFocusChangeBasedOnTimeout();\n\n if (checkTimeout) {\n // new timeout window -> reset priority\n this.lastPriority = -1;\n } else {\n // within timeout window\n if (priority > this.lastPriority) {\n this.lastPriority = priority;\n return true;\n }\n }\n\n return checkTimeout;\n }\n\n public getFocusableElement(element:JQuery) {\n var focusser = element.find('input.ui-select-focusser');\n\n if (focusser.length > 0) {\n return focusser[0];\n }\n\n var focusable = element;\n\n if (!element.is(FocusHelperService.FOCUSABLE_SELECTORS)) {\n focusable = element.find(FocusHelperService.FOCUSABLE_SELECTORS);\n }\n\n return focusable[0];\n }\n\n public focus(element:JQuery) {\n var focusable = jQuery(this.getFocusableElement(element)),\n $focusable = jQuery(focusable),\n isDisabled = $focusable.is('[disabled]');\n\n if (isDisabled && !$focusable.attr('ng-disabled')) {\n $focusable.prop('disabled', false);\n }\n\n focusable.focus();\n\n if (isDisabled && !$focusable.attr('ng-disabled')) {\n $focusable.prop('disabled', true);\n }\n }\n\n public focusElement(element:JQuery, priority?:any) {\n if (!this.checkIfAllowedFocusChange(priority)) {\n return;\n }\n\n setTimeout(() => {\n this.focus(element);\n }, 10);\n }\n}\n","import {Injectable} from '@angular/core';\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageRelationsHierarchyService} from \"core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service\";\nimport {States} from \"core-components/states.service\";\nimport {WorkPackageViewDisplayRepresentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageViewHierarchyIdentationService {\n\n constructor(private wpViewHierarchies:WorkPackageViewHierarchiesService,\n private wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService,\n private states:States,\n private wpRelationHierarchy:WorkPackageRelationsHierarchyService,\n private apiV3Service:APIV3Service,\n private querySpace:IsolatedQuerySpace) {\n }\n\n /**\n * Return whether the current hierarchy mode is active\n */\n public get applicable():boolean {\n return this.wpViewHierarchies.isEnabled && this.wpDisplayRepresentation.isList;\n }\n\n /**\n * Returns whether the given work package can be indented in the current render order\n * @param workPackage\n */\n public canIndent(workPackage:WorkPackageResource):boolean {\n if (!workPackage.changeParent || !this.applicable) {\n return false;\n }\n\n const rendered = this.renderedWorkPackageIds;\n const index = rendered.indexOf(workPackage.id!);\n\n // We can never indent the first item\n if (index === 0) {\n return false;\n }\n\n // We can not indent work packages whose predecessors are already their ancestors\n const ancestors = workPackage.ancestorIds;\n const ancestorCount = ancestors.length;\n\n // We can always indent if the ancestor count is 0\n if (ancestorCount === 0) {\n return true;\n }\n\n // Otherwise, we can only indent if the predecessor is NOT the last ancestor\n const lastAncestor:string = ancestors[ancestorCount - 1];\n const predecessorId:string = rendered[index - 1];\n\n return predecessorId !== lastAncestor;\n }\n\n /**\n * Returns whether the given work package can be outdented\n * @param workPackage\n */\n public canOutdent(workPackage:WorkPackageResource):boolean {\n if (!workPackage.changeParent || !this.applicable) {\n return false;\n }\n\n // We can always outdent if the work package has a parent\n return !!workPackage.parent;\n }\n\n /**\n * Try to indent the work package.\n * @return a Promise with the change parent result\n */\n public async indent(workPackage:WorkPackageResource):Promise {\n if (!this.canIndent(workPackage)) {\n return Promise.reject();\n }\n\n const rendered = this.renderedWorkPackageIds;\n const index = rendered.indexOf(workPackage.id!);\n const predecessorId:string = rendered[index - 1];\n\n // By default, assume we're going to insert under parent\n let newParentId = predecessorId;\n\n // If the predecessor is in an ancestor chain.\n // get the first element of the ancestor chain that workPackage is not in\n const predecessor = await this.apiV3Service.work_packages.id(predecessorId).get().toPromise();\n\n const difference = _.difference(predecessor.ancestorIds, workPackage.ancestorIds);\n if (difference && difference.length > 0) {\n newParentId = difference[0];\n }\n\n return this\n .wpRelationHierarchy\n .changeParent(workPackage, newParentId);\n }\n\n /**\n * Try to outdent the work package.\n * @return a Promise with the change parent result\n */\n public outdent(workPackage:WorkPackageResource):Promise {\n if (!this.canOutdent(workPackage)) {\n return Promise.reject();\n }\n\n let newParentId:string|null = null;\n\n // If we have more than one ancestor,\n // just drop the last one\n const ancestorIds = workPackage.ancestorIds;\n const ancestorCount = ancestorIds.length;\n if (ancestorCount > 1) {\n newParentId = ancestorIds[ancestorCount - 2];\n }\n\n return this\n .wpRelationHierarchy\n .changeParent(workPackage, newParentId);\n }\n\n /**\n * Get the currently rendered work packages\n */\n private get renderedWorkPackageIds():string[] {\n return this.querySpace.renderedWorkPackageIds.getValueOr([]);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageWatchersService} from 'core-components/wp-single-view-tabs/watchers-tab/wp-watchers.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-watcher-button',\n templateUrl: './wp-watcher-button.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageWatcherButtonComponent extends UntilDestroyedMixin implements OnInit {\n @Input('workPackage') public workPackage:WorkPackageResource;\n @Input('showText') public showText:boolean = false;\n @Input('disabled') public disabled:boolean = false;\n\n public buttonText:string;\n public buttonTitle:string;\n public buttonClass:string;\n public buttonId:string;\n public watchIconClass:string;\n\n constructor(readonly I18n:I18nService,\n readonly wpWatchersService:WorkPackageWatchersService,\n readonly apiV3Service:APIV3Service,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.setWatchStatus();\n this.cdRef.detectChanges();\n });\n }\n\n public get isWatched() {\n return this.workPackage.hasOwnProperty('unwatch');\n }\n\n public get displayWatchButton() {\n return this.isWatched || this.workPackage.hasOwnProperty('watch');\n }\n\n public toggleWatch() {\n const toggleLink = this.nextStateLink();\n\n toggleLink(toggleLink.$link.payload).then(() => {\n this.wpWatchersService.clear(this.workPackage.id!);\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .refresh();\n });\n }\n\n public nextStateLink() {\n const linkName = this.isWatched ? 'unwatch' : 'watch';\n return this.workPackage[linkName];\n }\n\n private setWatchStatus() {\n if (this.isWatched) {\n this.buttonTitle = this.I18n.t('js.label_unwatch_work_package');\n this.buttonText = this.I18n.t('js.label_unwatch');\n this.buttonClass = '-active';\n this.buttonId = 'unwatch-button';\n this.watchIconClass = 'icon-watched';\n\n } else {\n this.buttonTitle = this.I18n.t('js.label_watch_work_package');\n this.buttonText = this.I18n.t('js.label_watch');\n this.buttonClass = '';\n this.buttonId = 'watch-button';\n this.watchIconClass = 'icon-unwatched';\n }\n }\n}\n","\n","export namespace SelectionHelpers {\n\n /**\n * Test whether we currently have a selection within.\n * @param {HTMLElement} target\n * @return {boolean}\n */\n export function hasSelectionWithin(target:Element):boolean {\n try {\n const selection = window.getSelection()!;\n const hasSelection = selection.toString().length > 0;\n const isWithin = target.contains(selection.anchorNode);\n\n return hasSelection && isWithin;\n } catch (e) {\n console.error('Failed to test whether in selection ', e);\n return false;\n }\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {States} from 'core-components/states.service';\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {SelectionHelpers} from '../../../../helpers/selection-helpers';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input,\n OnDestroy,\n OnInit, Optional,\n ViewChild\n} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {ClickPositionMapper} from \"core-app/modules/common/set-click-position/set-click-position\";\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {ISchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {\n displayClassName,\n DisplayFieldRenderer,\n editFieldContainerClass\n} from \"core-app/modules/fields/display/display-field-renderer\";\n\n@Component({\n selector: 'editable-attribute-field',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './editable-attribute-field.component.html'\n})\nexport class EditableAttributeFieldComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n @Input() public fieldName:string;\n @Input() public resource:HalResource;\n @Input() public wrapperClasses?:string;\n @Input() public displayFieldOptions:any = {};\n @Input() public displayPlaceholder?:string;\n @Input() public isDropTarget?:boolean = false;\n\n @ViewChild('displayContainer', { static: true }) readonly displayContainer:ElementRef;\n @ViewChild('editContainer', { static: true }) readonly editContainer:ElementRef;\n\n public fieldRenderer:DisplayFieldRenderer;\n public editFieldContainerClass = editFieldContainerClass;\n public active = false;\n private $element:JQuery;\n\n public destroyed:boolean = false;\n\n constructor(protected states:States,\n protected injector:Injector,\n protected elementRef:ElementRef,\n protected ConfigurationService:ConfigurationService,\n protected opContextMenu:OPContextMenuService,\n protected halEditing:HalResourceEditingService,\n protected schemaCache:SchemaCacheService,\n // Get parent field group from injector if we're in a form\n @Optional() protected editForm:EditFormComponent,\n protected NotificationsService:NotificationsService,\n protected cdRef:ChangeDetectorRef,\n protected I18n:I18nService) {\n super();\n }\n\n public setActive(active:boolean = true) {\n this.active = active;\n if (!this.componentDestroyed) {\n this.cdRef.detectChanges();\n }\n }\n\n public ngOnInit() {\n this.fieldRenderer = new DisplayFieldRenderer(this.injector, 'single-view', this.displayFieldOptions);\n this.$element = jQuery(this.elementRef.nativeElement);\n\n // Register on the form if we're in an editable context\n this.editForm?.register(this);\n\n this.halEditing\n .temporaryEditResource(this.resource)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(resource => {\n this.resource = resource;\n this.render();\n });\n }\n\n // Open the field when its closed and relay drag & drop events to it.\n public startDragOverActivation(event:JQuery.TriggeredEvent) {\n if (!this.isDropTarget || !this.isEditable || this.active) {\n return true;\n }\n\n this.handleUserActivate(null);\n event.preventDefault();\n return false;\n }\n\n public render() {\n const el = this.fieldRenderer.render(this.resource, this.fieldName, null, this.displayPlaceholder);\n this.displayContainer.nativeElement.innerHTML = '';\n this.displayContainer.nativeElement.appendChild(el);\n }\n\n public deactivate(focus:boolean = false) {\n this.editContainer.nativeElement.innerHTML = '';\n this.editContainer.nativeElement.hidden = true;\n this.setActive(false);\n\n if (focus) {\n setTimeout(() => this.$element.find(`.${displayClassName}`).focus(), 20);\n }\n }\n\n public get isEditable():boolean {\n return this.editForm && this.schema.isAttributeEditable(this.fieldName);\n }\n\n public activateIfEditable(event:JQuery.TriggeredEvent) {\n // Ignore selections\n if (SelectionHelpers.hasSelectionWithin(event.target)) {\n debugLog(`Not activating ${this.fieldName} because of active selection within`);\n return true;\n }\n\n // Skip activation if the user clicked on a link or within a macro\n const target = jQuery(event.target);\n if (target.closest('a,macro', this.displayContainer.nativeElement).length > 0) {\n return true;\n }\n\n if (this.isEditable) {\n this.handleUserActivate(event);\n }\n\n this.opContextMenu.close();\n event.preventDefault();\n event.stopImmediatePropagation();\n\n return false;\n }\n\n public activateOnForm(noWarnings:boolean = false) {\n // Activate the field\n this.setActive(true);\n\n return this.editForm\n .activate(this.fieldName, noWarnings)\n .catch(() => this.deactivate(true));\n }\n\n public handleUserActivate(evt:JQuery.TriggeredEvent|null) {\n let positionOffset = 0;\n\n if (evt) {\n // Get the position where the user clicked.\n positionOffset = ClickPositionMapper.getPosition(evt);\n }\n\n this.activateOnForm()\n .then((handler) => {\n if (!handler) {\n return;\n }\n\n handler.$onUserActivate.next();\n handler.focus(positionOffset);\n });\n\n return false;\n }\n\n public reset() {\n this.render();\n this.deactivate();\n }\n\n private get schema() {\n if (this.halEditing.typedState(this.resource).hasValue()) {\n return this.halEditing.typedState(this.resource).value!.schema;\n } else {\n return this.schemaCache.of(this.resource) as ISchemaProxy;\n }\n }\n}\n","
    \n\n
    \n
    \n\n
    \n
    \n","import {Injectable, Injector, Optional} from '@angular/core';\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {States} from \"core-components/states.service\";\nimport {WorkPackageCreateService} from \"core-components/wp-new/wp-create.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {DragAndDropService} from \"core-app/modules/common/drag-and-drop/drag-and-drop.service\";\nimport {DragAndDropHelpers} from \"core-app/modules/common/drag-and-drop/drag-and-drop.helpers\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageCardDragAndDropService {\n\n private _workPackages:WorkPackageResource[];\n\n /** Whether the card view has an active inline created wp */\n public activeInlineCreateWp?:WorkPackageResource;\n\n /** A reference to the component in use, to have access to the current input variables */\n public cardView:WorkPackageCardViewComponent;\n\n\n public constructor(readonly states:States,\n readonly injector:Injector,\n readonly reorderService:WorkPackageViewOrderService,\n readonly wpCreate:WorkPackageCreateService,\n readonly notificationService:WorkPackageNotificationService,\n readonly apiV3Service:APIV3Service,\n readonly currentProject:CurrentProjectService,\n @Optional() readonly dragService:DragAndDropService,\n readonly wpInlineCreate:WorkPackageInlineCreateService) {\n\n }\n\n public init(componentRef:WorkPackageCardViewComponent) {\n this.cardView = componentRef;\n }\n\n public destroy() {\n if (this.dragService !== null) {\n this.dragService.remove(this.cardView.container.nativeElement);\n }\n }\n\n public registerDragAndDrop() {\n // The DragService may not have been provided\n // in which case we do not provide drag and drop\n if (this.dragService === null) {\n return;\n }\n\n this.dragService.register({\n dragContainer: this.cardView.container.nativeElement,\n scrollContainers: [this.cardView.container.nativeElement],\n moves: (card:HTMLElement) => {\n const wpId:string = card.dataset.workPackageId!;\n const workPackage = this.states.workPackages.get(wpId).value;\n\n return !!workPackage && this.cardView.canDragOutOf(workPackage) && !card.dataset.isNew;\n },\n accepts: () => this.cardView.dragInto,\n onMoved: async (card:HTMLElement) => {\n const wpId:string = card.dataset.workPackageId!;\n const toIndex = DragAndDropHelpers.findIndex(card);\n\n const newOrder = await this.reorderService.move(this.currentOrder, wpId, toIndex);\n this.updateOrder(newOrder);\n\n this.cardView.onMoved.emit();\n },\n onRemoved: (card:HTMLElement) => {\n const wpId:string = card.dataset.workPackageId!;\n\n const newOrder = this.reorderService.remove(this.currentOrder, wpId);\n this.updateOrder(newOrder);\n },\n onAdded: async (card:HTMLElement) => {\n const wpId:string = card.dataset.workPackageId!;\n const toIndex = DragAndDropHelpers.findIndex(card);\n\n const workPackage = await this\n .apiV3Service\n .work_packages\n .id(wpId)\n .get()\n .toPromise();\n const result = await this.addWorkPackageToQuery(workPackage, toIndex);\n\n if (card.parentElement) {\n card.parentElement.removeChild(card);\n }\n\n return result;\n }\n });\n }\n\n /**\n * Get the current work packages\n */\n public get workPackages():WorkPackageResource[] {\n return this._workPackages;\n }\n\n /**\n * Set work packages array,\n * remembering to keep the active inline-create\n */\n public set workPackages(workPackages:WorkPackageResource[]) {\n if (this.activeInlineCreateWp) {\n let existingNewWp = this._workPackages.find(o => o.isNew);\n\n // If there is already a card for a new WP,\n // we have to replace this one by the new activeInlineCreateWp\n if (existingNewWp) {\n let index = this._workPackages.indexOf(existingNewWp);\n this._workPackages[index] = this.activeInlineCreateWp;\n } else {\n this._workPackages = [this.activeInlineCreateWp, ...workPackages];\n }\n } else {\n this._workPackages = [...workPackages];\n }\n }\n\n /**\n * Get current order\n */\n private get currentOrder():string[] {\n return this.workPackages\n .filter(wp => wp && !wp.isNew)\n .map(el => el.id!);\n }\n\n /**\n * Update current order\n */\n private updateOrder(newOrder:string[]) {\n newOrder = _.uniq(newOrder);\n\n Promise\n .all(newOrder.map(id =>\n this\n .apiV3Service\n .work_packages\n .id(id)\n .get()\n .toPromise()\n ))\n .then((workPackages:WorkPackageResource[]) => {\n this.workPackages = workPackages;\n this.cardView.cdRef.detectChanges();\n });\n }\n\n /**\n * Inline create a new card\n */\n public addNewCard() {\n this.wpCreate\n .createOrContinueWorkPackage(this.currentProject.identifier)\n .then((changeset:WorkPackageChangeset) => {\n this.activeInlineCreateWp = changeset.projectedResource;\n this.workPackages = this.workPackages;\n this.cardView.cdRef.detectChanges();\n });\n }\n\n /**\n * Add the given work package to the query\n */\n async addWorkPackageToQuery(workPackage:WorkPackageResource, toIndex:number = -1):Promise {\n try {\n await this.cardView.workPackageAddedHandler(workPackage);\n const newOrder = await this.reorderService.add(this.currentOrder, workPackage.id!, toIndex);\n this.updateOrder(newOrder);\n return true;\n } catch (e) {\n this.notificationService.handleRawError(e, workPackage);\n }\n\n return false;\n }\n\n /**\n * Remove the new card\n */\n public removeReferenceWorkPackageForm() {\n if (this.activeInlineCreateWp) {\n this.removeCard(this.activeInlineCreateWp);\n }\n }\n\n removeCard(wp:WorkPackageResource) {\n const index = this.workPackages.indexOf(wp);\n this.workPackages.splice(index, 1);\n this.activeInlineCreateWp = undefined;\n\n if (!wp.isNew) {\n const newOrder = this.reorderService.remove(this.currentOrder, wp.id!);\n this.updateOrder(newOrder);\n }\n }\n\n /**\n * On new card saved\n */\n async onCardSaved(wp:WorkPackageResource) {\n const index = this.workPackages.findIndex((el) => el.id === 'new');\n\n if (index !== -1) {\n this.activeInlineCreateWp = undefined;\n\n // Add this item to the results\n const newOrder = await this.reorderService.add(this.currentOrder, wp.id!, index);\n this.updateOrder(newOrder);\n\n // Notify inline create service\n this.wpInlineCreate.newInlineWorkPackageCreated.next(wp.id!);\n }\n }\n}\n","export namespace DomHelpers {\n export function setBodyCursor(cursor:string, priority:'important'|'' = '') {\n document.body.style.setProperty('cursor', cursor, priority);\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {InputState} from 'reactivestates';\n\nexport class TypeResource extends HalResource {\n public color:string;\n\n public get state():InputState {\n return this.states.types.get(this.href as string) as any;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport interface WorkPackageCollectionResourceEmbedded {\n elements:WorkPackageResource[];\n groups:GroupObject[];\n}\n\nexport class WorkPackageCollectionResource extends CollectionResource {\n public schemas:CollectionResource;\n public createWorkPackage:any;\n public elements:WorkPackageResource[];\n public groups:GroupObject[];\n public totalSums?:Object;\n public sumsSchema?:SchemaResource;\n public representations:Array;\n}\n\nexport interface WorkPackageCollectionResource extends WorkPackageCollectionResourceEmbedded {\n}\n\n/**\n * A reference to a group object as returned from the API.\n * Augmented with state information such as collapsed state.\n */\nexport interface GroupObject {\n value:any;\n count:number;\n collapsed?:boolean;\n index:number;\n identifier:string;\n sums:{[attribute:string]:number|null};\n href:{ href:string }[];\n _links:{\n valueLink:{ href:string }[];\n groupBy:{ href:string };\n };\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {\n ErrorResource,\n v3ErrorIdentifierMultipleErrors\n} from 'core-app/modules/hal/resources/error-resource';\n\nexport interface FormResourceLinks {\n commit(payload:any):Promise;\n}\n\nexport class FormResource extends HalResource {\n\n public schema:SchemaResource;\n public validationErrors:{ [attribute:string]:ErrorResource };\n\n public getErrors():ErrorResource|null {\n const errors = _.values(this.validationErrors);\n const count = errors.length;\n\n if (count === 0) {\n return null;\n }\n\n let resource;\n if (count === 1) {\n resource = new ErrorResource(this.injector, errors[0], true, this.halInitializer, 'Error');\n } else {\n resource = new ErrorResource(this.injector, {}, true, this.halInitializer, 'Error');\n resource.errorIdentifier = v3ErrorIdentifierMultipleErrors;\n resource.errors = errors;\n }\n resource.isValidationError = true;\n return resource;\n }\n}\n\nexport interface FormResource extends FormResourceLinks {}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\n\nexport class RootResource extends HalResource {\n\n public user:UserResource;\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class QueryOperatorResource extends HalResource {\n public get id():string {\n return this.$source.id || this.idFromLink;\n }\n\n public get idFromLink():string {\n if (this.$href) {\n const idPart = HalResource.idFromLink(this.$href);\n return decodeURIComponent(idPart);\n }\n\n return '';\n }\n\n\n public set id(val:string) {\n this.$source.id = val;\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {CallableHalLink} from 'core-app/modules/hal/hal-link/hal-link';\nimport {Attachable} from \"core-app/modules/hal/resources/mixins/attachable-mixin\";\n\nexport class HelpTextBaseResource extends HalResource {\n public attribute:string;\n public attributeCaption:string;\n public scope:string;\n public helpText:api.v3.Formattable;\n}\n\nexport const HelpTextResource = Attachable(HelpTextBaseResource);\n\nexport interface HelpTextResource extends HelpTextBaseResource {\n editText?:CallableHalLink;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {Attachable} from 'core-app/modules/hal/resources/mixins/attachable-mixin';\n\n\nexport interface WikiPageResourceLinks {\n addAttachment(attachment:HalResource):Promise;\n}\n\nclass WikiPageBaseResource extends HalResource {\n public $links:WikiPageResourceLinks;\n\n private attachmentsBackend = false;\n}\n\nexport const WikiPageResource = Attachable(WikiPageBaseResource);\n\nexport interface WikiPageResource extends HalResource {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {Attachable} from 'core-app/modules/hal/resources/mixins/attachable-mixin';\n\n\nexport interface MeetingContentResourceLinks {\n addAttachment(attachment:HalResource):Promise;\n}\n\nclass MeetingContentBaseResource extends HalResource {\n public $links:MeetingContentResourceLinks;\n\n private attachmentsBackend = false;\n}\n\nexport const MeetingContentResource = Attachable(MeetingContentBaseResource);\n\nexport interface MeetingContentResource extends HalResource {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {Attachable} from 'core-app/modules/hal/resources/mixins/attachable-mixin';\n\nexport interface PostResourceLinks {\n addAttachment(attachment:HalResource):Promise;\n}\n\nclass PostBaseResource extends HalResource {\n public $links:PostResourceLinks;\n\n private attachmentsBackend = false;\n}\n\nexport const PostResource = Attachable(PostBaseResource);\n\nexport interface PostResource extends PostResourceLinks {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class TimeEntryResource extends HalResource {\n public get state() {\n return this.states.timeEntries.get(this.id!) as any;\n }\n\n /**\n * Exclude the schema _link from the linkable Resources.\n */\n public $linkableKeys():string[] {\n return _.without(super.$linkableKeys(), 'schema');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class NewsResource extends HalResource {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {RoleResource} from \"core-app/modules/hal/resources/role-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\n\nexport interface MembershipResourceLinks {\n update(payload:unknown):Promise;\n updateImmediately(payload:unknown):Promise;\n delete():Promise;\n}\n\nexport interface MembershipResourceEmbedded {\n principal:UserResource;\n roles:RoleResource[];\n project:ProjectResource;\n}\n\nexport class MembershipResource extends HalResource {\n}\n\nexport interface MembershipResource extends MembershipResourceLinks, MembershipResourceEmbedded {}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class RoleResource extends HalResource {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class ProjectResource extends HalResource {\n public get state() {\n return this.states.projects.get(this.id!) as any;\n }\n\n public getEditorTypeFor(fieldName:string):\"full\"|\"constrained\" {\n if (['statusExplanation', 'description'].indexOf(fieldName) !== -1) {\n return 'full';\n }\n\n return 'constrained';\n }\n\n /**\n * Exclude the schema _link from the linkable Resources.\n */\n public $linkableKeys():string[] {\n return _.without(super.$linkableKeys(), 'schema');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class GroupResource extends HalResource {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {TypeResource} from 'core-app/modules/hal/resources/type-resource';\nimport {SchemaDependencyResource} from 'core-app/modules/hal/resources/schema-dependency-resource';\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {FormResource} from 'core-app/modules/hal/resources/form-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {QueryFilterInstanceSchemaResource} from 'core-app/modules/hal/resources/query-filter-instance-schema-resource';\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {RootResource} from 'core-app/modules/hal/resources/root-resource';\nimport {QueryOperatorResource} from 'core-app/modules/hal/resources/query-operator-resource';\nimport {HelpTextResource} from 'core-app/modules/hal/resources/help-text-resource';\nimport {CustomActionResource} from 'core-app/modules/hal/resources/custom-action-resource';\nimport {\n HalResourceFactoryConfigInterface,\n HalResourceService\n} from 'core-app/modules/hal/services/hal-resource.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {WikiPageResource} from \"core-app/modules/hal/resources/wiki-page-resource\";\nimport {MeetingContentResource} from \"core-app/modules/hal/resources/meeting-content-resource\";\nimport {PostResource} from \"core-app/modules/hal/resources/post-resource\";\nimport {StatusResource} from \"core-app/modules/hal/resources/status-resource\";\nimport {AttachmentCollectionResource} from \"core-app/modules/hal/resources/attachment-collection-resource\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {NewsResource} from \"core-app/modules/hal/resources/news-resource\";\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {MembershipResource} from \"core-app/modules/hal/resources/membership-resource\";\nimport {RoleResource} from \"core-app/modules/hal/resources/role-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {GroupResource} from \"core-app/modules/hal/resources/group-resource\";\n\nconst halResourceDefaultConfig:{ [typeName:string]:HalResourceFactoryConfigInterface } = {\n WorkPackage: {\n cls: WorkPackageResource,\n attrTypes: {\n parent: 'WorkPackage',\n ancestors: 'WorkPackage',\n children: 'WorkPackage',\n relations: 'Relation',\n schema: 'Schema',\n status: 'Status',\n type: 'Type'\n }\n },\n Activity: {\n cls: HalResource,\n attrTypes: {\n user: 'User'\n }\n },\n 'Activity::Comment': {\n cls: HalResource,\n attrTypes: {\n user: 'User'\n }\n },\n 'Activity::Revision': {\n cls: HalResource,\n attrTypes: {\n user: 'User'\n }\n },\n Relation: {\n cls: RelationResource,\n attrTypes: {\n from: 'WorkPackage',\n to: 'WorkPackage'\n }\n },\n Schema: {\n cls: SchemaResource\n },\n Type: {\n cls: TypeResource\n },\n Status: {\n cls: StatusResource\n },\n SchemaDependency: {\n cls: SchemaDependencyResource\n },\n Error: {\n cls: ErrorResource\n },\n User: {\n cls: UserResource\n },\n Group: {\n cls: GroupResource\n },\n Collection: {\n cls: CollectionResource\n },\n WorkPackageCollection: {\n cls: WorkPackageCollectionResource\n },\n AttachmentCollection: {\n cls: AttachmentCollectionResource\n },\n Query: {\n cls: QueryResource,\n attrTypes: {\n filters: 'QueryFilterInstance'\n }\n },\n Form: {\n cls: FormResource,\n attrTypes: {\n payload: 'FormPayload'\n }\n },\n FormPayload: {\n cls: HalResource,\n attrTypes: {\n attachments: 'AttachmentsCollection'\n }\n },\n QueryFilterInstance: {\n cls: QueryFilterInstanceResource,\n attrTypes: {\n schema: 'QueryFilterInstanceSchema',\n filter: 'QueryFilter',\n operator: 'QueryOperator'\n }\n },\n QueryFilterInstanceSchema: {\n cls: QueryFilterInstanceSchemaResource,\n },\n QueryFilter: {\n cls: QueryFilterResource,\n },\n Root: {\n cls: RootResource,\n },\n QueryOperator: {\n cls: QueryOperatorResource,\n },\n HelpText: {\n cls: HelpTextResource,\n },\n CustomAction: {\n cls: CustomActionResource\n },\n WikiPage: {\n cls: WikiPageResource\n },\n MeetingContent: {\n cls: MeetingContentResource\n },\n Post: {\n cls: PostResource\n },\n Project: {\n cls: ProjectResource\n },\n Role: {\n cls: RoleResource\n },\n Grid: {\n cls: GridResource,\n },\n GridWidget: {\n cls: GridWidgetResource\n },\n TimeEntry: {\n cls: TimeEntryResource\n },\n Membership: {\n cls: MembershipResource\n },\n News: {\n cls: NewsResource\n },\n Version: {\n cls: VersionResource\n }\n};\n\nexport function initializeHalResourceConfig(halResourceService:HalResourceService) {\n return () => {\n _.each(halResourceDefaultConfig, (value, key) => halResourceService.registerResource(key, value));\n };\n}\n\n","import {ErrorHandler, Injectable} from \"@angular/core\";\nimport {ErrorResource} from \"core-app/modules/hal/resources/error-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\n\n@Injectable()\nexport class HalAwareErrorHandler extends ErrorHandler {\n private text = {\n internal_error: this.I18n.t('js.error.internal')\n };\n\n constructor(private readonly I18n:I18nService) {\n super();\n }\n\n public handleError(error:unknown) {\n let message:string = this.text.internal_error;\n\n if (error instanceof ErrorResource) {\n console.error(\"Returned error resource %O\", error);\n message += ` ${error.errorMessages.join(\"\\n\")}`;\n } else if (error instanceof HalResource) {\n console.error(\"Returned hal resource %O\", error);\n message += `Resource returned ${error.name}`;\n } else if (error instanceof Error) {\n window.ErrorReporter.captureException(error);\n } else if (typeof error === 'string') {\n window.ErrorReporter.captureMessage(error);\n message = error;\n }\n\n super.handleError(message);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APP_INITIALIZER, ErrorHandler, NgModule} from '@angular/core';\nimport {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';\nimport {initializeHalResourceConfig} from 'core-app/modules/hal/services/hal-resource.config';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {OpenProjectHeaderInterceptor} from 'core-app/modules/hal/http/openproject-header-interceptor';\nimport {CommonModule} from \"@angular/common\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {HalAwareErrorHandler} from \"core-app/modules/hal/services/hal-aware-error-handler\";\n\n@NgModule({\n imports: [\n CommonModule,\n HttpClientModule,\n ],\n providers: [\n { provide: ErrorHandler, useClass: HalAwareErrorHandler },\n { provide: HTTP_INTERCEPTORS, useClass: OpenProjectHeaderInterceptor, multi: true },\n { provide: APP_INITIALIZER, useFactory: initializeHalResourceConfig, deps: [HalResourceService], multi: true },\n HalResourceNotificationService\n ]\n})\nexport class OpenprojectHalModule { }\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {ChangeDetectorRef, Component, ElementRef, Inject} from \"@angular/core\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\nexport interface ConfirmDialogOptions {\n text:{\n title:string;\n text:string;\n button_continue?:string;\n button_cancel?:string;\n };\n closeByEscape?:boolean;\n showClose?:boolean;\n closeByDocument?:boolean;\n passedData?:string[];\n dangerHighlighting?:boolean;\n}\n\n@Component({\n templateUrl: './confirm-dialog.modal.html'\n})\nexport class ConfirmDialogModal extends OpModalComponent {\n\n public showClose:boolean;\n\n public confirmed = false;\n\n private options:ConfirmDialogOptions;\n\n public text:any = {\n title: this.I18n.t('js.modals.form_submit.title'),\n text: this.I18n.t('js.modals.form_submit.text'),\n button_continue: this.I18n.t('js.button_continue'),\n button_cancel: this.I18n.t('js.button_cancel'),\n close_popup: this.I18n.t('js.close_popup_title')\n };\n\n public passedData:string[];\n\n public dangerHighlighting:boolean;\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n\n super(locals, cdRef, elementRef);\n this.options = locals.options || {};\n\n this.dangerHighlighting = _.defaultTo(this.options.dangerHighlighting, false);\n this.passedData = _.defaultTo(this.options.passedData, []);\n this.closeOnEscape = _.defaultTo(this.options.closeByEscape, true);\n this.closeOnOutsideClick = _.defaultTo(this.options.closeByDocument, true);\n this.showClose = _.defaultTo(this.options.showClose, true);\n // override default texts if any\n this.text = _.defaults(this.options.text, this.text);\n }\n\n public confirmAndClose(evt:JQuery.TriggeredEvent) {\n this.confirmed = true;\n this.closeMe(evt);\n }\n}\n\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n

    \n \n
    \n \n
    \n {{data}}\n
    \n

    \n
    \n\n
    \n \n \n\n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++ Ng1FieldControlsWrapper,\n\n\nimport {FormsModule} from \"@angular/forms\";\nimport {NgModule} from \"@angular/core\";\nimport {AccessibleClickDirective} from \"core-app/modules/a11y/accessible-click.directive\";\nimport {AccessibleByKeyboardComponent} from \"core-app/modules/a11y/accessible-by-keyboard.component\";\nimport {CommonModule} from \"@angular/common\";\nimport {DoubleClickOrTapDirective} from \"core-app/modules/a11y/double-click-or-tap.directive\";\n\n@NgModule({\n imports: [\n FormsModule,\n CommonModule,\n ],\n exports: [\n AccessibleClickDirective,\n DoubleClickOrTapDirective,\n AccessibleByKeyboardComponent,\n ],\n declarations: [\n AccessibleClickDirective,\n AccessibleByKeyboardComponent,\n DoubleClickOrTapDirective,\n ]\n})\nexport class OpenprojectAccessibilityModule {\n}\n\n\n","\n\n {{ title }}\n \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, HostBinding} from '@angular/core';\n\n@Component({\n templateUrl: './no-results.component.html',\n selector: 'no-results'\n})\n\nexport class NoResultsComponent {\n @Input() title:string;\n @Input() description:string;\n\n @HostBinding('class.generic-table--no-results-container') setHostClass = true;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injector} from '@angular/core';\nimport {Field} from \"core-app/modules/fields/field.base\";\n\nexport interface IFieldType {\n fieldType:string;\n $injector:Injector;\n new(...args:any[]):T;\n}\n\nexport abstract class AbstractFieldService> {\n /** Default field type to fall back to */\n public defaultFieldType:string;\n\n /** Registered attribute types => field identifier */\n protected fields:{[attributeType:string]:string} = {};\n\n /** Registered field classes */\n protected classes:{[type:string]:C} = {};\n\n /**\n * Get the field type for the given attribute type.\n * If no registered type exists for the field, returns the default type.\n *\n * @param {string} attributeType\n * @returns {string}\n */\n public fieldType(attributeType:string):string|undefined {\n return this.fields[attributeType];\n }\n\n /**\n * Get the Field class for the given field name.\n * Returns the default class if no registered type exists\n * @param {string} fieldName\n * @returns {C}\n */\n public getClassFor(fieldName:string, type:string = 'unknown'):C {\n let key = this.fieldType(fieldName) || this.fieldType(type) || this.defaultFieldType;\n return this.classes[key];\n }\n\n public getSpecificClassFor(resourceType:string, fieldName:string, type:string = 'unknown'):C {\n let key = this.fieldType(`${resourceType}-${fieldName}`) ||\n this.fieldType(`${resourceType}-${type}`);\n\n if (key) {\n return this.classes[key];\n }\n\n return this.getClassFor(fieldName, type);\n }\n\n /**\n * Add a field class for the given attribute names.\n *\n * @param fieldClass The field class\n * @param {string} fieldType the field type identifier (e.g., 'progress')\n * @param {string[]} attributes The schema attribute names to register for (e.g., 'Progress')\n *\n * @returns {this}\n */\n public addFieldType(fieldClass:any, fieldType:string, attributes:string[]) {\n fieldClass.fieldType = fieldType;\n this.register(fieldClass, attributes);\n\n return this;\n }\n\n /**\n * Add a field class for the given attribute names and a specify resource.\n *\n * @param resourceType The resource type (e.g Work Package)\n * @param fieldClass The field class\n * @param {string} fieldType the field type identifier (e.g., 'progress')\n * @param {string[]} attributes The schema attribute names to register for (e.g., 'Progress')\n *\n * @returns {this}\n */\n public addSpecificFieldType(resourceType:string, fieldClass:any, fieldType:string, attributes:string[]) {\n fieldClass.fieldType = `${resourceType}-${fieldType}`;\n attributes = attributes.map((attribute) => `${resourceType}-${attribute}`);\n this.register(fieldClass, attributes);\n\n return this;\n }\n\n /**\n * Register new schema attribute names for an existing field type\n *\n * @param {string} fieldType The field type to extend (e.g., 'select')\n * @param {string[]} attributes The attribute schema names to register to the existing fieldType (e.g., 'budget')\n *\n * @returns {this}\n */\n public extendFieldType(fieldType:string, attributes:string[]) {\n let fieldClass = this.classes[fieldType] || this.getClassFor(fieldType);\n return this.addFieldType(fieldClass, fieldType, attributes);\n }\n\n /**\n * Register the\n * @param {C} fieldClass\n * @param {string[]} fields\n */\n protected register(fieldClass:C, fields:string[] = []) {\n const type = fieldClass.fieldType;\n fields.forEach((field:string) => this.fields[field] = type);\n this.classes[type] = fieldClass;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {ConfigurationResource} from \"core-app/modules/hal/resources/configuration-resource\";\nimport * as moment from \"moment\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class ConfigurationService {\n // fetches configuration from the ApiV3 endpoint\n // TODO: this currently saves the request between page reloads,\n // but could easily be stored in localStorage\n private configuration:ConfigurationResource;\n public initialized:Promise;\n\n public constructor(readonly I18n:I18nService,\n readonly apiV3Service:APIV3Service) {\n this.initialized = this.loadConfiguration().then(() => true).catch(() => false);\n }\n\n public commentsSortedInDescendingOrder() {\n return this.userPreference('commentSortDescending');\n }\n\n public warnOnLeavingUnsaved() {\n return this.userPreference('warnOnLeavingUnsaved');\n }\n\n public autoHidePopups() {\n return this.userPreference('autoHidePopups');\n }\n\n public isTimezoneSet() {\n return !!this.timezone();\n }\n\n public timezone() {\n return this.userPreference('timeZone');\n }\n\n public isDirectUploads() {\n return !!this.prepareAttachmentURL;\n }\n\n public get prepareAttachmentURL() {\n return _.get(this.configuration, ['prepareAttachment', 'href']);\n }\n\n public get maximumAttachmentFileSize() {\n return this.systemPreference('maximumAttachmentFileSize');\n }\n\n public get perPageOptions() {\n return this.systemPreference('perPageOptions');\n }\n\n public dateFormatPresent() {\n return !!this.systemPreference('dateFormat');\n }\n\n public dateFormat() {\n return this.systemPreference('dateFormat');\n }\n\n public timeFormatPresent() {\n return !!this.systemPreference('timeFormat');\n }\n\n public timeFormat() {\n return this.systemPreference('timeFormat');\n }\n\n public startOfWeekPresent() {\n return !!this.systemPreference('startOfWeek');\n }\n\n public startOfWeek() {\n if (this.startOfWeekPresent()) {\n return this.systemPreference('startOfWeek');\n } else {\n return moment.localeData(I18n.locale).firstDayOfWeek();\n }\n }\n\n private loadConfiguration() {\n return this\n .apiV3Service\n .configuration\n .get()\n .toPromise()\n .then((configuration) => {\n this.configuration = configuration;\n });\n }\n\n private userPreference(pref:string) {\n return _.get(this.configuration, ['userPreferences', pref]);\n }\n\n private systemPreference(pref:string) {\n return _.get(this.configuration, pref);\n }\n}\n","import {OPContextMenuService} from 'core-components/op-context-menu/op-context-menu.service';\nimport {OpContextMenuItem} from 'core-components/op-context-menu/op-context-menu.types';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n/**\n * Interface passed to CM service to open a particular context menu.\n * This will often be a trigger component, but does not have to be.\n */\nexport abstract class OpContextMenuHandler extends UntilDestroyedMixin {\n protected $element:JQuery;\n protected items:OpContextMenuItem[] = [];\n\n constructor(readonly opContextMenu:OPContextMenuService) {\n super();\n }\n\n /**\n * Called when the service closes this context menu\n */\n public onClose() {\n this.afterFocusOn.focus();\n }\n\n public onOpen(menu:JQuery) {\n menu.find('.menu-item').first().focus();\n }\n\n /**\n * Positioning args for jquery-ui position.\n *\n * @param {Event} openerEvent\n */\n public positionArgs(openerEvent:JQuery.TriggeredEvent):any {\n return {\n my: 'left top',\n at: 'right bottom',\n of: openerEvent,\n collision: 'flipfit'\n };\n }\n\n /**\n * Get the locals passed to the op-context-menu component\n */\n public get locals():{ showAnchorRight?:boolean, contextMenuId?:string, items:OpContextMenuItem[] } {\n return {\n items: this.items\n };\n }\n\n /**\n * Open this context menu\n */\n protected open(evt:JQuery.TriggeredEvent) {\n this.opContextMenu.show(this, evt);\n }\n\n protected get afterFocusOn():JQuery {\n return this.$element;\n }\n}\n","export namespace DragAndDropHelpers {\n export function findIndex(el:HTMLElement):number {\n if (!el.parentElement) {\n return -1;\n }\n\n const children = Array.from(el.parentElement.children);\n return children.indexOf(el);\n }\n\n export function reinsert(el:HTMLElement, previousIndex:number|string, container:HTMLElement) {\n previousIndex = typeof previousIndex === 'string' ? parseInt(previousIndex, 10) : previousIndex;\n const currentIndex = el.parentNode && Array.from(el.parentNode.children).indexOf(el) || null;\n const children = Array.from(container.children);\n let pointOfInsertion;\n\n if (currentIndex != null) {\n const isDraggingDown = currentIndex > previousIndex;\n pointOfInsertion = isDraggingDown ? children[previousIndex] : children[previousIndex + 1];\n } else {\n pointOfInsertion = children[previousIndex];\n }\n\n if (pointOfInsertion) {\n container.insertBefore(el, pointOfInsertion);\n } else {\n container.appendChild(el);\n }\n }\n}\n","import {Injector} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {commonRowClassName} from '../rows/single-row-builder';\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const timelineCellClassName = 'wp-timeline-cell';\n\nexport class TimelineRowBuilder {\n\n @InjectField() public states:States;\n @InjectField() public wpTableTimeline:WorkPackageViewTimelineService;\n\n constructor(public readonly injector:Injector,\n protected workPackageTable:WorkPackageTable) {\n }\n\n public build(workPackageId:string|null) {\n const cell = document.createElement('div');\n cell.classList.add(timelineCellClassName, commonRowClassName);\n\n if (workPackageId) {\n cell.dataset['workPackageId'] = workPackageId;\n }\n\n return cell;\n }\n\n /**\n * Build and insert a timeline row for the given work package using the additional classes.\n * @param workPackage\n * @param timelineBody\n * @param rowClasses\n */\n public insert(workPackageId:string|null,\n timelineBody:DocumentFragment|HTMLElement,\n rowClasses:string[] = []) {\n\n const cell = this.build(workPackageId);\n cell.classList.add(...rowClasses);\n\n timelineBody.appendChild(cell);\n }\n}\n","import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {WorkPackageWatchersService} from 'core-app/components/wp-single-view-tabs/watchers-tab/wp-watchers.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './wp-relations-count.html',\n selector: 'wp-watchers-count',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageWatchersCountComponent extends UntilDestroyedMixin implements OnInit {\n @Input('wpId') wpId:string;\n public count:number = 0;\n\n constructor(protected apiV3Service:APIV3Service,\n protected wpWatcherService:WorkPackageWatchersService,\n protected cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit():void {\n this\n .apiV3Service\n .work_packages\n .id(this.wpId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n ).subscribe((workPackage) => {\n this.wpWatcherService\n .require(workPackage)\n .then((watchers:HalResource[]) => {\n this.count = watchers.length;\n this.cdRef.detectChanges();\n });\n });\n }\n}\n"," 0\"\n [textContent]=\"count\">\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Transition} from \"@uirouter/core\";\nimport {Injectable} from \"@angular/core\";\n\n@Injectable()\nexport class EditFormRoutingService {\n /**\n * Return whether the given transition is cancelled during the editing of this form\n *\n * @param transition The transition that is underway.\n * @return A boolean marking whether the transition should be blocked.\n */\n public blockedTransition(transition:Transition):boolean {\n // By default, don't allow any transitions to continue\n return true;\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {QueryFilterInstanceSchemaResource} from 'core-app/modules/hal/resources/query-filter-instance-schema-resource';\nimport {QueryOperatorResource} from 'core-app/modules/hal/resources/query-operator-resource';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\n\nexport class QueryFilterInstanceResource extends HalResource {\n public filter:QueryFilterResource;\n public operator:QueryOperatorResource;\n public values:HalResource[]|string[];\n private memoizedCurrentSchemas:{ [key:string]:QueryFilterInstanceSchemaResource } = {};\n\n @InjectField(SchemaCacheService) schemaCache:SchemaCacheService;\n @InjectField(PathHelperService) pathHelper:PathHelperService;\n\n public $initialize(source:any) {\n super.$initialize(source);\n\n this.$links['schema'] = {\n href: this.pathHelper.api.v3.apiV3Base + '/queries/filter_instance_schemas/' + this.filter.idFromLink\n };\n }\n\n public get id():string {\n return this.filter.id;\n }\n\n public get name():string {\n return this.filter.name;\n }\n\n /**\n * Get the complete current schema.\n *\n * The filter instance's schema is made up of a static and a variable part.\n * The variable part depends on the currently selected operator.\n * Therefore, the schema differs based on the selected operator.\n */\n public get currentSchema():QueryFilterInstanceSchemaResource|null {\n if (!this.operator) {\n return null;\n }\n\n let key = this.operator.href!.toString();\n\n if (this.memoizedCurrentSchemas[key] === undefined) {\n try {\n this.memoizedCurrentSchemas[key] = this.schemaCache.of(this).resultingSchema(this.operator);\n } catch(e) {\n console.error(\"Failed to access filter schema\" + e);\n }\n }\n\n return this.memoizedCurrentSchemas[key];\n }\n\n public isCompletelyDefined() {\n return this.values.length || (this.currentSchema && !this.currentSchema.isValueRequired());\n }\n\n public findOperator(operatorSymbol:string):QueryOperatorResource|undefined {\n return _.find(this.schemaCache.of(this).availableOperators, (operator:QueryOperatorResource) => operator.id === operatorSymbol) as QueryOperatorResource|undefined;\n }\n\n public isTemplated() {\n let flag = false;\n (this.values as any[]).find((value:any) => {\n const href:string = value?.href || value.toString() || '';\n flag = href.includes('{id}');\n });\n return flag;\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {BoardActionService} from \"core-app/modules/boards/board/board-actions/board-action.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class BoardActionsRegistryService {\n\n private mapping:{ [attribute:string]:BoardActionService } = {};\n\n public add(attribute:string, service:BoardActionService) {\n this.mapping[attribute] = service;\n }\n\n public available() {\n return _.map(this.mapping, (service:BoardActionService, attribute:string) => {\n return { attribute: attribute, text: service.localizedName, icon:'', description:'', image:''};\n });\n }\n\n public get(attribute:string):BoardActionService {\n if (this.mapping[attribute]) {\n return this.mapping[attribute];\n }\n\n throw(`No action service exists for ${attribute}`);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {StateService} from '@uirouter/core';\nimport {Injectable} from \"@angular/core\";\nimport {HttpClient} from \"@angular/common/http\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalDeletedEvent, HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\n\n@Injectable()\nexport class WorkPackageService {\n\n private text = {\n successful_delete: this.I18n.t('js.work_packages.message_successful_bulk_delete')\n };\n\n constructor(private readonly http:HttpClient,\n private readonly $state:StateService,\n private readonly PathHelper:PathHelperService,\n private readonly UrlParamsHelper:UrlParamsHelperService,\n private readonly NotificationsService:NotificationsService,\n private readonly I18n:I18nService,\n private readonly halEvents:HalEventsService) {\n }\n\n public performBulkDelete(ids:string[], defaultHandling:boolean) {\n const params = {\n 'ids[]': ids\n };\n const promise = this.http\n .delete(\n this.PathHelper.workPackagesBulkDeletePath(),\n {params: params, withCredentials: true}\n )\n .toPromise();\n\n if (defaultHandling) {\n promise\n .then(() => {\n this.NotificationsService.addSuccess(this.text.successful_delete);\n\n ids.forEach(id => this.halEvents.push({_type:'WorkPackage', id: id}, { eventType: 'deleted'} as HalDeletedEvent));\n\n if (this.$state.includes('**.list.details.**')\n && ids.indexOf(this.$state.params.workPackageId) > -1) {\n this.$state.go('work-packages.partitioned.list', this.$state.params);\n }\n })\n .catch(() => {\n const urlParams = this.UrlParamsHelper.buildQueryString(params);\n window.location.href = this.PathHelper.workPackagesBulkDeletePath() + '?' + urlParams;\n });\n }\n\n return promise;\n }\n}\n","import {OnDestroyMixin, untilComponentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {Directive, OnDestroy} from \"@angular/core\";\nimport {Observable} from \"rxjs\";\n\n/**\n * Mixin function to provide access to observable and flags\n * whether this component has been destroyed.\n *\n * Use for rxjs with .pipe(this.untilDestroyed)\n */\n@Directive()\nexport class UntilDestroyedMixin extends OnDestroyMixin implements OnDestroy {\n public componentDestroyed = false;\n\n ngOnDestroy():void {\n this.componentDestroyed = true;\n super.ngOnDestroy();\n }\n\n /**\n * Helper function to access `untilComponentDestroyed`\n */\n protected untilDestroyed():(source:Observable) => Observable {\n return untilComponentDestroyed(this);\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectorRef, Component, ElementRef, Injector, Input} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {OpContextMenuTrigger} from 'core-components/op-context-menu/handlers/op-context-menu-trigger.directive';\nimport {OPContextMenuService} from 'core-components/op-context-menu/op-context-menu.service';\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {OpContextMenuItem} from \"core-components/op-context-menu/op-context-menu.types\";\n\n@Component({\n selector: 'icon-triggered-context-menu',\n templateUrl: './icon-triggered-context-menu.component.html',\n styleUrls: ['./icon-triggered-context-menu.component.sass']\n})\nexport class IconTriggeredContextMenuComponent extends OpContextMenuTrigger {\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly opModalService:OpModalService,\n readonly injector:Injector,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n\n super(elementRef, opContextMenu);\n }\n\n @Input('menu-items') menuItems:Function;\n\n protected async open(evt:JQuery.TriggeredEvent) {\n this.items = await this.buildItems();\n this.opContextMenu.show(this, evt);\n }\n\n /**\n * Positioning args for jquery-ui position.\n *\n * @param {Event} openerEvent\n */\n public positionArgs(evt:JQuery.TriggeredEvent) {\n let additionalPositionArgs = {\n my: 'right top',\n at: 'right bottom'\n };\n\n let position = super.positionArgs(evt);\n _.assign(position, additionalPositionArgs);\n\n return position;\n }\n\n private async buildItems() {\n let items:OpContextMenuItem[] = [];\n\n // Add action specific menu entries\n if (this.menuItems) {\n const additional = await this.menuItems();\n return items.concat(additional);\n }\n\n return items;\n }\n}\n","\n \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {QueryGroupByResource} from 'core-app/modules/hal/resources/query-group-by-resource';\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {States} from 'core-components/states.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {QueryColumn} from \"core-components/wp-query/query-column\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\n\n@Injectable()\nexport class WorkPackageViewGroupByService extends WorkPackageQueryStateService {\n public constructor(readonly states:States,\n readonly querySpace:IsolatedQuerySpace) {\n super(querySpace);\n }\n\n valueFromQuery(query:QueryResource) {\n return query.groupBy || null;\n }\n\n public hasChanged(query:QueryResource) {\n const comparer = (groupBy:QueryColumn|HalResource|null|undefined) => groupBy ? groupBy.href : null;\n\n return !_.isEqual(\n comparer(query.groupBy),\n comparer(this.current)\n );\n }\n\n public applyToQuery(query:QueryResource) {\n const current = this.current;\n query.groupBy = current === null ? undefined : current;\n return true;\n }\n\n public isGroupable(column:QueryColumn):boolean {\n return !!_.find(this.available, candidate => candidate.id === column.id);\n }\n\n public disable() {\n this.update(null);\n }\n\n public setBy(column:QueryColumn) {\n let groupBy = _.find(this.available, candidate => candidate.id === column.id);\n\n if (groupBy) {\n this.update(groupBy);\n }\n }\n\n public get current():QueryGroupByResource|null {\n return this.lastUpdatedState.getValueOr(null);\n }\n\n protected get availableState() {\n return this.states.queries.groupBy;\n }\n\n public get isEnabled():boolean {\n return !!this.current;\n }\n\n public get available():QueryGroupByResource[] {\n return this.availableState.getValueOr([]);\n }\n\n public isCurrentlyGroupedBy(column:QueryColumn):boolean {\n let cur = this.current;\n return !!(cur && cur.id === column.id);\n }\n}\n","export const environment = {\n production: true\n};\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {QueryGroupByResource} from 'core-app/modules/hal/resources/query-group-by-resource';\nimport {ProjectResource} from 'core-app/modules/hal/resources/project-resource';\nimport {QuerySortByResource} from 'core-app/modules/hal/resources/query-sort-by-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {HighlightingMode} from \"core-components/wp-fast-table/builders/highlighting/highlighting-mode.const\";\nimport {QueryOrder} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-order\";\n\nexport interface QueryResourceEmbedded {\n results:WorkPackageCollectionResource;\n columns:QueryColumn[];\n groupBy:QueryGroupByResource|undefined;\n project:ProjectResource;\n sortBy:QuerySortByResource[];\n filters:QueryFilterInstanceResource[];\n}\n\nexport type TimelineZoomLevel = 'days'|'weeks'|'months'|'quarters'|'years'|'auto';\n\nexport interface TimelineLabels {\n left:string|null;\n right:string|null;\n farRight:string|null;\n}\n\nexport class QueryResource extends HalResource {\n public $embedded:QueryResourceEmbedded;\n public results:WorkPackageCollectionResource;\n public columns:QueryColumn[];\n public groupBy:QueryGroupByResource|undefined;\n public sortBy:QuerySortByResource[];\n public filters:QueryFilterInstanceResource[];\n public starred:boolean;\n public sums:boolean;\n public hasError:boolean;\n public timelineVisible:boolean;\n public timelineZoomLevel:TimelineZoomLevel;\n public highlightingMode:HighlightingMode;\n public highlightedAttributes:HalResource[]|undefined;\n public displayRepresentation:string|undefined;\n public timelineLabels:TimelineLabels;\n public showHierarchies:boolean;\n public public:boolean;\n public hidden:boolean;\n public project:ProjectResource;\n public ordered_work_packages:QueryOrder;\n\n public $initialize(source:any) {\n super.$initialize(source);\n\n this.filters = this\n .filters\n .map((filter:Object) => new QueryFilterInstanceResource(\n this.injector,\n filter,\n true,\n this.halInitializer,\n 'QueryFilterInstance'\n )\n );\n }\n}\n\nexport interface QueryResourceLinks {\n updateImmediately?(attributes:any):Promise;\n}\n\nexport interface QueryResource extends QueryResourceLinks {\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {HTTPSupportedMethods} from \"core-app/modules/hal/http/http.interfaces\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\n\nexport interface HalLinkInterface {\n href:string|null;\n method:HTTPSupportedMethods;\n title?:string;\n templated?:boolean;\n payload?:any;\n type?:string;\n identifier?:string;\n}\n\nexport interface HalLinkSource {\n href:string|null;\n title:string;\n}\n\nexport interface CallableHalLink extends HalLinkInterface {\n $link:this;\n data?:Promise;\n}\n\nexport class HalLink implements HalLinkInterface {\n constructor(public requestMethod:(method:HTTPSupportedMethods, href:string, data:any, headers:any) => Promise,\n public href:string|null = null,\n public title:string = '',\n public method:HTTPSupportedMethods = 'get',\n public templated:boolean = false,\n public payload?:any,\n public type:string = 'application/json',\n public identifier?:string) {\n }\n\n /**\n * Create the HalLink from an object with the HalLinkInterface.\n */\n public static fromObject(halResourceService:HalResourceService, link:HalLinkInterface):HalLink {\n return new HalLink(\n (method:HTTPSupportedMethods, href:string, data:any, headers:any) =>\n halResourceService.request(method, href, data, headers).toPromise(),\n link.href,\n link.title,\n link.method,\n link.templated,\n link.payload,\n link.type,\n link.identifier\n );\n }\n\n /**\n * Fetch the resource.\n */\n public $fetch(...params:any[]):Promise {\n const [data, headers] = params;\n return this.requestMethod(this.method, this.href as string, data, headers);\n }\n\n /**\n * Prepare the templated link and return a CallableHalLink with the templated parameters set\n *\n * @returns {CallableHalLink}\n */\n public $prepare(templateValues:{ [templateKey:string]:string }) {\n if (!this.templated) {\n throw 'The link ' + this.href + ' is not templated.';\n }\n\n let href = _.clone(this.href) || '';\n _.each(templateValues, (value:string, key:string) => {\n let regexp = new RegExp('{' + key + '}');\n href = href.replace(regexp, value);\n });\n\n return new HalLink(\n this.requestMethod,\n href,\n this.title,\n this.method,\n false,\n this.payload,\n this.type,\n this.identifier\n ).$callable();\n }\n\n /**\n * Return a function that fetches the resource.\n *\n * @returns {CallableHalLink}\n */\n public $callable():CallableHalLink {\n const linkFunc:any = (...params:any[]) => this.$fetch(...params);\n\n _.extend(linkFunc, {\n $link: this,\n href: this.href,\n title: this.title,\n method: this.method,\n templated: this.templated,\n payload: this.payload,\n type: this.type,\n identifier: this.identifier,\n });\n\n return linkFunc;\n }\n}\n","import {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {CardHighlightingMode} from \"core-components/wp-fast-table/builders/highlighting/highlighting-mode.const\";\nimport {ApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\n\nexport type BoardType = 'free'|'action';\n\nexport interface BoardWidgetOption {\n queryId:string;\n filters:ApiV3Filter[];\n}\n\nexport class Board {\n constructor(public grid:GridResource) {\n }\n\n public get id() {\n return this.grid.id;\n }\n\n public get name() {\n return this.grid.name;\n }\n\n public get editable() {\n return !!this.grid.updateImmediately;\n }\n\n public get isFree() {\n return !this.isAction;\n }\n\n public get isAction() {\n return this.grid.options.type === 'action';\n }\n\n public get actionAttribute():string|undefined {\n if (this.isFree) {\n return undefined;\n }\n\n return this.grid.options.attribute as string;\n }\n\n public set highlightingMode(val:CardHighlightingMode) {\n this.grid.options.highlightingMode = val;\n }\n\n public get highlightingMode():CardHighlightingMode {\n return (this.grid.options.highlightingMode || 'none') as CardHighlightingMode;\n }\n\n public set name(name:string) {\n this.grid.name = name;\n }\n\n public addQuery(widget:GridWidgetResource) {\n widget.isNewWidget = true;\n this.grid.widgets.push(widget);\n }\n\n public removeQuery(widget:GridWidgetResource) {\n this.grid.widgets = this.grid.widgets.filter(el => el.options.queryId !== widget.options.queryId);\n }\n\n public get queries():GridWidgetResource[] {\n return this.grid.widgets;\n }\n\n public get createdAt() {\n return this.grid.createdAt;\n }\n\n public get filters():ApiV3Filter[] {\n return (this.grid.options.filters || []) as ApiV3Filter[];\n }\n\n public set filters(filters:ApiV3Filter[]) {\n this.grid.options.filters = filters;\n }\n\n public sortWidgets() {\n this.grid.widgets = this.grid.widgets.sort((a, b) => {\n return a.startColumn - b.startColumn;\n });\n }\n\n public showStatusButton() {\n return this.actionAttribute !== 'status';\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nexport namespace ContainHelpers {\n\n /**\n * Execute the callback when the element is outside\n * @param {Element} within\n * @param {Function} callback\n */\n export function whenOutside(within:Element, callback:Function) {\n setTimeout(() => {\n if (!insideOrSelf(within, document.activeElement!)) {\n callback();\n }\n }, 20);\n }\n\n /**\n * Return whether the target element is either the same as within, or contained within it.\n *\n * @param {Element} within\n * @param {Element} target\n * @returns {boolean}\n */\n export function insideOrSelf(within:Element, target:Element):boolean {\n return within === target || within.contains(target);\n }\n}\n","/**\n * Returns the collapsed group class for the given ancestor id\n */\nexport function collapsedGroupClass(ancestorId:string = ''):string {\n return `__collapsed-group-${ancestorId}`;\n}\n\nexport function hierarchyGroupClass(ancestorId:string):string {\n return `__hierarchy-group-${ancestorId}`;\n}\n\nexport function hierarchyRootClass(ancestorId:string):string {\n return `__hierarchy-root-${ancestorId}`;\n}\n\nexport function ancestorClassIdentifier(ancestorId:string) {\n return `wp-ancestor-row-${ancestorId}`;\n}\n","
    \n
    \n \n &ngsp;\n \n
    \n
    \n","import {\n Component,\n Injector,\n OnInit,\n} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {QueryFilterResource} from \"core-app/modules/hal/resources/query-filter-resource\";\nimport {QueryOperatorResource} from \"core-app/modules/hal/resources/query-operator-resource\";\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Component({\n templateUrl: './wp-table-configuration-relation-selector.html',\n selector: 'wp-table-configuration-relation-selector'\n})\nexport class WpTableConfigurationRelationSelectorComponent implements OnInit {\n private relationFilterIds:string[] = [\n 'parent',\n 'precedes',\n 'follows',\n 'relates',\n 'duplicates',\n 'duplicated',\n 'blocks',\n 'blocked',\n 'partof',\n 'includes',\n 'requires',\n 'required'\n ];\n\n public availableRelationFilters:QueryFilterResource[] = [];\n public selectedRelationFilter:QueryFilterResource|undefined = undefined;\n\n public text = {\n filter_work_packages_by_relation_type: this.I18n.t('js.work_packages.table_configuration.relation_filters.filter_work_packages_by_relation_type'),\n please_select: this.I18n.t('js.placeholders.selection'),\n // We need to inverse the translation strings, as the filters's are named the other way around than what\n // a user knows from the relations tab:\n parent: this.I18n.t('js.relation_labels.children'),\n precedes: this.I18n.t('js.relation_labels.follows'),\n follows: this.I18n.t('js.relation_labels.precedes'),\n relates: this.I18n.t('js.relation_labels.relates'),\n duplicates: this.I18n.t('js.relation_labels.duplicated'),\n duplicated: this.I18n.t('js.relation_labels.duplicates'),\n blocks: this.I18n.t('js.relation_labels.blocked'),\n blocked: this.I18n.t('js.relation_labels.blocks'),\n requires: this.I18n.t('js.relation_labels.required'),\n required: this.I18n.t('js.relation_labels.requires'),\n partof: this.I18n.t('js.relation_labels.includes'),\n includes: this.I18n.t('js.relation_labels.partof')\n };\n\n constructor(readonly injector:Injector,\n readonly I18n:I18nService,\n readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly ConfigurationService:ConfigurationService,\n readonly schemaCache:SchemaCacheService) {\n }\n\n ngOnInit() {\n let self:WpTableConfigurationRelationSelectorComponent = this;\n\n this.wpTableFilters\n .onReady()\n .then(() => {\n self.availableRelationFilters = self.relationFiltersOf(self.wpTableFilters.availableFilters) as QueryFilterResource[];\n self.setSelectedRelationFilter();\n });\n }\n\n private setSelectedRelationFilter():void {\n let currentRelationFilters:QueryFilterInstanceResource[] = this.relationFiltersOf(this.wpTableFilters.current) as QueryFilterInstanceResource[];\n if (currentRelationFilters.length > 0) {\n this.selectedRelationFilter = _.find(this.availableRelationFilters, { id: currentRelationFilters[0].id }) as QueryFilterResource;\n } else {\n this.selectedRelationFilter = this.availableRelationFilters[0];\n }\n this.onRelationFilterSelected();\n }\n\n public onRelationFilterSelected() {\n if (this.selectedRelationFilter) {\n this.removeRelationFiltersFromCurrentState();\n this.addFilterToCurrentState(this.selectedRelationFilter as QueryFilterResource);\n }\n }\n\n private removeRelationFiltersFromCurrentState() {\n let filtersToRemove = this.relationFiltersOf(this.wpTableFilters.current) as QueryFilterInstanceResource[];\n this.wpTableFilters.remove(...filtersToRemove);\n }\n\n private relationFiltersOf(filters:QueryFilterResource[]|QueryFilterInstanceResource[]):QueryFilterResource[]|QueryFilterInstanceResource[] {\n return _.filter(filters, (filter:QueryFilterResource|QueryFilterInstanceResource) => _.includes(this.relationFilterIds, filter.id));\n }\n\n private addFilterToCurrentState(filter:QueryFilterResource):void {\n let newFilter = this.wpTableFilters.instantiate(filter);\n let operator:QueryOperatorResource = this.getOperatorForId(newFilter, '=');\n newFilter.operator = operator;\n newFilter.values = [{href: '/api/v3/work_packages/{id}'}] as HalResource[];\n\n this.wpTableFilters.add(newFilter);\n }\n\n private getOperatorForId(filter:QueryFilterResource, id:string):QueryOperatorResource {\n return _.find(this.schemaCache.of(filter).availableOperators, { 'id': id}) as QueryOperatorResource;\n }\n\n public compareRelationFilters(f1:undefined|QueryFilterResource, f2:undefined|QueryFilterResource):boolean {\n return f1 && f2 ? f1.id === f2.id : f1 === f2;\n }\n}\n","import {\n Component,\n} from '@angular/core';\nimport {WpTableConfigurationService} from 'core-components/wp-table/configuration-modal/wp-table-configuration.service';\nimport {RestrictedWpTableConfigurationService} from 'core-components/wp-table/external-configuration/restricted-wp-table-configuration.service';\nimport {WpTableConfigurationRelationSelectorComponent} from \"core-components/wp-table/configuration-modal/wp-table-configuration-relation-selector\";\nimport {WpTableConfigurationModalPrependToken} from \"core-components/wp-table/configuration-modal/wp-table-configuration.modal\";\nimport {ExternalQueryConfigurationComponent} from \"core-components/wp-table/external-configuration/external-query-configuration.component\";\n\n@Component({\n templateUrl: './external-query-configuration.template.html',\n providers: [\n [\n { provide: WpTableConfigurationService, useClass: RestrictedWpTableConfigurationService }\n ],\n { provide: WpTableConfigurationModalPrependToken, useValue: WpTableConfigurationRelationSelectorComponent }\n ],\n})\nexport class ExternalRelationQueryConfigurationComponent extends ExternalQueryConfigurationComponent {\n}\n","\n \n \n\n","import {Injectable} from '@angular/core';\nimport {\n Class,\n ExternalQueryConfigurationService\n} from \"core-components/wp-table/external-configuration/external-query-configuration.service\";\nimport {ExternalRelationQueryConfigurationComponent} from \"core-components/wp-table/external-configuration/external-relation-query-configuration.component\";\n\n@Injectable()\nexport class ExternalRelationQueryConfigurationService extends ExternalQueryConfigurationService {\n externalQueryConfigurationComponent():Class {\n return ExternalRelationQueryConfigurationComponent;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {Observable} from \"rxjs\";\nimport {Apiv3GridForm} from \"core-app/modules/apiv3/endpoints/grids/apiv3-grid-form\";\n\nexport class Apiv3GridPaths extends APIv3GettableResource {\n // Static paths\n readonly form = this.subResource('form', Apiv3GridForm);\n\n /**\n * Update a grid resource or payload\n * @param resource\n * @param schema\n */\n public patch(resource:GridResource|Object, schema:SchemaResource|null = null):Observable {\n let payload = this.form.extractPayload(resource, schema);\n\n return this\n .halResourceService\n .patch(this.path, payload);\n }\n\n /**\n * Delete a grid resource\n */\n public delete():Observable {\n return this\n .halResourceService\n .delete(this.path);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {ApiV3FilterBuilder, FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {Observable} from \"rxjs\";\n\nexport interface Apiv3ListParameters {\n filters?:[string, FilterOperator, string[]][];\n sortBy?:[string, string][];\n pageSize?:number;\n}\n\nexport interface Apiv3ListResourceInterface {\n list(params:Apiv3ListParameters):Observable>;\n}\n\nexport function listParamsString(params?:Apiv3ListParameters):string {\n let queryProps = [];\n\n if (params && params.sortBy) {\n queryProps.push(`sortBy=${JSON.stringify(params.sortBy)}`);\n }\n\n // 0 should not be treated as false\n if (params && params.pageSize !== undefined) {\n queryProps.push(`pageSize=${params.pageSize}`);\n }\n\n if (params && params.filters) {\n let filters = new ApiV3FilterBuilder();\n\n params.filters.forEach((filterParam) => {\n filters.add(...filterParam);\n });\n\n queryProps.push(filters.toParams());\n }\n\n let queryPropsString = '';\n\n if (queryProps.length) {\n queryPropsString = `?${queryProps.join('&')}`;\n }\n\n return queryPropsString;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {Apiv3GridPaths} from \"core-app/modules/apiv3/endpoints/grids/apiv3-grid-paths\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {Apiv3GridForm} from \"core-app/modules/apiv3/endpoints/grids/apiv3-grid-form\";\nimport {Observable} from \"rxjs\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface,\n listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\n\nexport class Apiv3GridsPaths\n extends APIv3ResourceCollection\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'grids', Apiv3GridPaths);\n }\n\n readonly form = this.subResource('form', Apiv3GridForm);\n\n /**\n * Load a list of grids with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n\n /**\n * Create a new GridResource\n *\n * @param resource\n * @param schema\n */\n public post(resource:GridResource, schema:SchemaResource|null = null):Observable {\n return this\n .halResourceService\n .post(\n this.path,\n this.form.extractPayload(resource, schema)\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {States} from \"core-components/states.service\";\nimport {HasId, StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {concat, from, merge, Observable, of} from \"rxjs\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {mapTo, publish, share, shareReplay, switchMap, take, tap} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\nexport abstract class CachableAPIV3Resource\n extends APIv3GettableResource {\n @InjectField() states:States;\n @InjectField() schemaCache:SchemaCacheService;\n\n readonly cache = this.createCache();\n\n /**\n * Require the value to be loaded either when forced or the value is stale\n * according to the cache interval specified for this service.\n *\n * Returns an observable to the values stream of the state.\n *\n * @param force Load the value anyway.\n */\n public requireAndStream(force:boolean = false):Observable {\n const id = this.id.toString();\n\n // Refresh when stale or being forced\n if (this.cache.stale(id) || force) {\n const observable = this\n .load()\n .pipe(\n take(1),\n shareReplay(1)\n );\n\n this.cache.clearAndLoad(\n id,\n observable\n );\n\n // Return concat of the loading observable\n // for error handling and the like,\n // but then continue with the streamed cache\n return concat(\n observable,\n this.cache.state(id).values$()\n );\n }\n\n return this.cache.state(id).values$();\n }\n\n\n /**\n * Observe the values of this resource,\n * but do not request it actively.\n */\n public observe():Observable {\n return this\n .cache\n .observe(this.id.toString());\n }\n\n\n /**\n * Returns a (potentially cached) observable.\n *\n * Only observes one value.\n *\n * Accesses or modifies the global store for this resource.\n */\n get():Observable {\n return this\n .requireAndStream(false)\n .pipe(\n take(1)\n );\n }\n\n /**\n * Returns a freshly loaded value but ensuring the value\n * is also updated in the cache.\n *\n * Only observes one value.\n *\n * Accesses or modifies the global store for this resource.\n */\n refresh():Promise {\n return this\n .requireAndStream(true)\n .pipe(\n take(1),\n )\n // Use a promise to ensure this fires\n // even if caller isn't subscribing.\n .toPromise();\n }\n\n /**\n * Perform a request to the HalResourceService with the current path\n */\n protected load():Observable {\n return this\n .halResourceService\n .get(this.path)\n .pipe(\n switchMap((resource) => {\n if (resource.$links.schema) {\n return this.schemaCache\n .requireAndStream(resource.$links.schema.href)\n .pipe(\n take(1),\n mapTo(resource),\n );\n } else {\n return of(resource);\n }\n })\n ) as any; // T does not extend HalResource for virtual endpoints such as board, thus we need to cast here\n }\n\n /**\n * Update a single resource\n */\n protected touch(resource:T):void {\n this.cache.updateFor(resource);\n }\n\n /**\n * Inserts a collection response to cache as an rxjs tap function\n */\n protected cacheResponse():(source:Observable) => Observable {\n return (source$:Observable) => {\n return source$.pipe(\n tap(\n (resource:T) => this.touch(resource)\n )\n );\n };\n }\n\n /**\n * Creates the cache state instance\n */\n protected abstract createCache():StateCacheService;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {MultiInputState} from \"reactivestates\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Observable} from \"rxjs\";\nimport {tap} from \"rxjs/operators\";\nimport {Apiv3TimeEntriesPaths} from \"core-app/modules/apiv3/endpoints/time-entries/apiv3-time-entries-paths\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\n\nexport class Apiv3TimeEntryPaths extends CachableAPIV3Resource {\n // Static paths\n readonly form = this.subResource('form', APIv3FormResource);\n\n /**\n * Update the time entry with the given payload.\n *\n * In case of updating from the hal resource, a schema resource is needed\n * to identify the writable attributes.\n * @param payload\n * @param schema\n */\n public patch(payload:Object, schema:SchemaResource|null = null):Observable {\n return this\n .halResourceService\n .patch(this.path, this.extractPayload(payload, schema))\n .pipe(\n tap(resource => this.touch(resource))\n );\n }\n\n /**\n * Delete the time entry under the current path\n */\n public delete():Observable {\n return this\n .halResourceService\n .delete(this.path)\n .pipe(\n tap(() => this.cache.clearSome(this.id.toString()))\n );\n }\n\n protected createCache():StateCacheService {\n return (this.parent as Apiv3TimeEntriesPaths).cache;\n }\n\n /**\n * Extract payload from the given request with schema.\n * This will ensure we will only write writable attributes and so on.\n *\n * @param resource\n * @param schema\n */\n protected extractPayload(resource:HalResource|Object|null, schema:SchemaResource|null = null) {\n if (resource instanceof HalResource && schema) {\n return HalPayloadHelper.extractPayloadFromSchema(resource, schema);\n } else if (!(resource instanceof HalResource)) {\n return resource;\n } else {\n return {};\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {States} from \"core-components/states.service\";\nimport {HasId, StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {Observable} from \"rxjs\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {tap} from \"rxjs/operators\";\n\nexport abstract class CachableAPIV3Collection<\n T extends HasId = HalResource,\n V extends APIv3GettableResource = APIv3GettableResource,\n X extends StateCacheService = StateCacheService\n >\n extends APIv3ResourceCollection {\n @InjectField() states:States;\n\n readonly cache:X = this.createCache();\n\n /**\n * Observe all value changes of the cache\n */\n public observeAll():Observable {\n return this.cache.observeAll();\n }\n\n /**\n * Inserts a collection or single response to cache as an rxjs tap function\n */\n protected cacheResponse():(source:Observable) => Observable {\n return (source$) => {\n return source$.pipe(\n tap(\n (response:R) => {\n if (response instanceof CollectionResource) {\n response.elements.forEach(this.touch.bind(this));\n } else if (response instanceof HalResource) {\n this.touch(response as any);\n }\n }\n )\n );\n };\n }\n\n /**\n * Update a single resource\n */\n protected touch(resource:T):void {\n this.cache.updateFor(resource);\n }\n\n /**\n * Creates the cache state instance\n */\n protected abstract createCache():X;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {States} from \"core-components/states.service\";\nimport {Injector} from \"@angular/core\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {MultiInputState} from \"reactivestates\";\n\nexport class TimeEntryCacheService extends StateCacheService {\n @InjectField() readonly states:States;\n @InjectField() readonly schemaCache:SchemaCacheService;\n\n constructor(readonly injector:Injector, state:MultiInputState) {\n super(state);\n }\n\n updateValue(id:string, val:TimeEntryResource):Promise {\n return this.schemaCache\n .ensureLoaded(val)\n .then(() => {\n this.putValue(id, val);\n return val;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {Apiv3TimeEntryPaths} from \"core-app/modules/apiv3/endpoints/time-entries/apiv3-time-entry-paths\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {Observable} from \"rxjs\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {MultiInputState} from \"reactivestates\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface,\n listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {TimeEntryCacheService} from \"core-app/modules/apiv3/endpoints/time-entries/time-entry-cache.service\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class Apiv3TimeEntriesPaths\n extends CachableAPIV3Collection\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'time_entries', Apiv3TimeEntryPaths);\n }\n\n // Static paths\n public readonly form = this.subResource('form', APIv3FormResource);\n\n /**\n * Load a list of time entries with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params))\n .pipe(\n this.cacheResponse()\n );\n }\n\n /**\n * Create a time entry resource from the given payload\n * @param payload\n */\n public post(payload:Object):Observable {\n return this\n .halResourceService\n .post(this.path, payload)\n .pipe(\n this.cacheResponse()\n );\n }\n\n protected createCache():StateCacheService {\n return new TimeEntryCacheService(this.injector, this.states.timeEntries);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {buildApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {Observable} from \"rxjs\";\nimport {map} from \"rxjs/operators\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface, listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\n\nexport class Apiv3AvailableProjectsPaths\n extends APIv3GettableResource>\n implements Apiv3ListResourceInterface {\n\n /**\n * Load a list of available projects with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n\n /**\n * Performs a request against the available_projects endpoint\n * to see whether this is contained\n *\n * Returns whether the given id exists in the set\n * of available projects\n *\n * @param projectId\n */\n public exists(projectId:string):Observable {\n return this\n .halResourceService\n .get>(\n this.path,\n { filters: buildApiV3Filter('id', '=', [projectId]).toJson() }\n )\n .pipe(\n map(collection => collection.count > 0)\n );\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3AvailableProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-available-projects-paths\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface, listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {Observable} from \"rxjs\";\nimport {MembershipResource} from \"core-app/modules/hal/resources/membership-resource\";\n\nexport class Apiv3MembershipsPaths\n extends APIv3ResourceCollection>\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'memberships');\n }\n\n /**\n * Load a list of membership entries with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n\n\n // /api/v3/memberships/available_projects\n readonly available_projects = this.subResource('available_projects', Apiv3AvailableProjectsPaths);\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {MultiInputState} from \"reactivestates\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIv3UserPaths extends CachableAPIV3Resource {\n\n readonly avatar = this.subResource('avatar');\n\n protected createCache():StateCacheService {\n return new StateCacheService(this.states.users);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {APIv3UserPaths} from \"core-app/modules/apiv3/endpoints/users/apiv3-user-paths\";\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class Apiv3UsersPaths extends APIv3ResourceCollection {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'users', APIv3UserPaths);\n }\n\n // Static paths\n\n // /api/v3/users/me\n public readonly me = this.path + '/me';\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {TypeResource} from \"core-app/modules/hal/resources/type-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {APIv3TypesPaths} from \"core-app/modules/apiv3/endpoints/types/apiv3-types-paths\";\n\nexport class APIv3TypePaths extends CachableAPIV3Resource {\n\n protected createCache():StateCacheService {\n return (this.parent as APIv3TypesPaths).cache;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {TypeResource} from \"core-app/modules/hal/resources/type-resource\";\nimport {APIv3TypePaths} from \"core-app/modules/apiv3/endpoints/types/apiv3-type-paths\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIv3TypesPaths extends CachableAPIV3Collection {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'types', APIv3TypePaths);\n }\n\n protected createCache():StateCacheService {\n return new StateCacheService(this.states.types);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injector} from \"@angular/core\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {HttpClient} from \"@angular/common/http\";\nimport {SimpleResource} from \"core-app/modules/apiv3/paths/path-resources\";\n\nexport type QueryOrder = { [wpId:string]:number };\n\nexport class APIV3QueryOrder extends SimpleResource {\n @InjectField() http:HttpClient;\n\n constructor(readonly injector:Injector,\n readonly basePath:string,\n readonly id:string|number) {\n super(basePath, id);\n }\n\n public get():Promise {\n return this.http\n .get(\n this.path\n )\n .toPromise()\n .then(result => result || {});\n }\n\n public update(delta:QueryOrder):Promise {\n return this.http\n .patch(\n this.path,\n { delta: delta },\n { withCredentials: true }\n )\n .toPromise()\n .then((response:{t:string}) => response.t);\n }\n\n public delete(id:string, ...wpIds:string[]) {\n let delta:QueryOrder = {};\n wpIds.forEach(id => delta[id] = -1);\n\n return this.update(delta);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {Observable} from \"rxjs\";\nimport * as URI from \"urijs\";\nimport {map, tap} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {QueryFiltersService} from \"core-components/wp-query/query-filters.service\";\n\nexport class Apiv3QueryForm extends APIv3FormResource {\n @InjectField() private queryFilters:QueryFiltersService;\n\n /**\n * Load the query form for the given existing (or new) query resource\n * @param query\n */\n public load(query:QueryResource):Observable<[QueryFormResource, QueryResource]> {\n // We need a valid payload so that we\n // can check whether form saving is possible.\n // The query needs a name to be valid.\n let payload:any = {\n 'name': query.name || '!!!__O__o__O__!!!'\n };\n\n if (query.project) {\n payload['_links'] = {\n 'project': {\n 'href': query.project.$href\n }\n };\n }\n\n let path = this.apiRoot.queries.withOptionalId(query.id).form.path;\n return this.halResourceService\n .post(path, payload)\n .pipe(\n tap(form => this.queryFilters.setSchemas(form.$embedded.schema.$embedded.filtersSchemas)),\n map(form => [form, this.buildQueryResource(form)])\n );\n }\n\n /**\n * Load the query form only with the given query props.\n *\n * @param params\n * @param queryId\n * @param projectIdentifier\n * @param payload\n */\n public loadWithParams(params:{[key:string]:unknown}, queryId:string|undefined, projectIdentifier:string|undefined|null, payload:any = {}):Observable<[QueryFormResource, QueryResource]> {\n // We need a valid payload so that we\n // can check whether form saving is possible.\n // The query needs a name to be valid.\n if (!queryId && !payload.name) {\n payload.name = '!!!__O__o__O__!!!';\n }\n\n if (projectIdentifier) {\n payload._links = payload._links || {};\n payload._links.project = {\n 'href': this.apiRoot.projects.id(projectIdentifier).toString()\n };\n\n }\n\n let path = this.apiRoot.queries.withOptionalId(queryId).form.path;\n const href = URI(path).search(params).toString();\n return this.halResourceService\n .post(href, payload)\n .pipe(\n tap(form => this.queryFilters.setSchemas(form.$embedded.schema.$embedded.filtersSchemas)),\n map(form => [form, this.buildQueryResource(form)])\n );\n }\n\n protected buildQueryResource(form:QueryFormResource):QueryResource {\n return this.halResourceService.createHalResourceOfType('Query', form.payload);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {APIV3QueryOrder} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-order\";\nimport {Apiv3QueryForm} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-form\";\nimport {Observable} from \"rxjs\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {QueryFiltersService} from \"core-components/wp-query/query-filters.service\";\nimport {PaginationObject} from \"core-components/table-pagination/pagination-service\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\n\nexport class APIv3QueryPaths extends APIv3GettableResource {\n @InjectField() private queryFilters:QueryFiltersService;\n\n // Static paths\n readonly form = this.subResource('form', Apiv3QueryForm);\n\n // Order path\n readonly order = new APIV3QueryOrder(this.injector, this.path, 'order');\n\n /**\n * Stream the response for the given query request\n * @param queryData\n */\n public parameterised(params:Object):Observable {\n return this.halResourceService\n .get(this.path, params);\n }\n\n /**\n * Update the given query\n * @param query\n * @param form\n */\n public patch(payload:QueryResource|Object, form?:QueryFormResource):Observable {\n if (payload instanceof QueryResource && form) {\n // Extracting requires having the filter schemas loaded as the dependencies\n this.queryFilters.mapSchemasIntoFilters(payload, form);\n payload = HalPayloadHelper.extractPayloadFromSchema(payload, form.schema);\n }\n\n return this\n .halResourceService\n .patch(this.path, payload);\n }\n\n /**\n * Delete the query\n */\n public delete() {\n return this\n .halResourceService\n .delete(this.path);\n }\n\n /**\n * Reload with a given pagination\n * @param pagination\n */\n public paginated(pagination:PaginationObject):Observable {\n return this.parameterised(pagination);\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {APIv3QueryPaths} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-paths\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3QueryForm} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-form\";\nimport {Observable} from \"rxjs\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {Apiv3ListParameters, listParamsString} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {QueryFiltersService} from \"core-components/wp-query/query-filters.service\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\n\nexport class APIv3QueriesPaths extends APIv3ResourceCollection {\n @InjectField() private queryFilters:QueryFiltersService;\n\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'queries', APIv3QueryPaths);\n }\n\n // Static paths\n // /api/v3/queries/form\n readonly form = this.subResource('form', Apiv3QueryForm);\n\n // /api/v3/queries/default\n readonly default = this.subResource>('default');\n\n // /api/v3/queries/filter_instance_schemas/:id\n readonly filter_instance_schemas = new APIv3ResourceCollection(this.apiRoot, this.path, 'filter_instance_schemas');\n\n /**\n * Load a list of queries with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n\n /**\n * Locate a query for the response for the given query request.\n * This might be the default query or an existing query identified by its ID.\n * @param queryData\n * @param queryId\n * @param projectIdentifier\n */\n public find(queryData:Object, queryId?:string, projectIdentifier?:string|null|undefined):Observable {\n let path:string;\n\n if (queryId) {\n path = this.apiRoot.queries.id(queryId).toString();\n } else {\n path = this.apiRoot.withOptionalProject(projectIdentifier).queries.default.toString();\n }\n\n return this\n .halResourceService\n .get(path, queryData);\n }\n\n\n /**\n * Stream the response for the given query request\n *\n * @param params\n */\n public parameterised(params:Object):Observable {\n return this.halResourceService\n .get(\n this.default.path,\n params\n );\n }\n\n /**\n * Create a new query resource\n *\n * @param payload Payload object or query HAL resource\n * @param form Form resource, needed when QueryResource is passed\n */\n public post(payload:QueryResource|Object, form?:QueryFormResource):Observable {\n if (payload instanceof QueryResource && form) {\n // Extracting requires having the filter schemas loaded as the dependencies\n this.queryFilters.mapSchemasIntoFilters(payload, form);\n payload = HalPayloadHelper.extractPayloadFromSchema(payload, form.schema);\n }\n\n return this\n .halResourceService\n .post(\n this.apiRoot.queries.path, payload\n );\n }\n\n /**\n * Invert the starred state of the given query\n *\n * @param query\n */\n public toggleStarred(query:QueryResource):Promise {\n if (query.starred) {\n return query.unstar();\n } else {\n return query.star();\n }\n }\n\n /**\n * Filter for non-hidden queries\n *\n * @param projectIdentifier\n */\n public filterNonHidden(projectIdentifier?:string|null):Observable> {\n let listParams:Apiv3ListParameters = {\n filters: [['hidden', '=', ['f']]]\n };\n\n if (projectIdentifier) {\n // all queries with the provided projectIdentifier\n listParams.filters!.push(['project_identifier', '=', [projectIdentifier]]);\n } else {\n // all queries having no project (i.e. being global)\n listParams.filters!.push(['project', '!*', []]);\n }\n\n return this.list(listParams);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {from, NEVER, Observable} from \"rxjs\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {Apiv3AvailableProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-available-projects-paths\";\nimport {APIv3VersionPaths} from \"core-app/modules/apiv3/endpoints/versions/apiv3-version-paths\";\nimport {RelationResource} from \"core-app/modules/hal/resources/relation-resource\";\nimport {buildApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {map} from \"rxjs/operators\";\n\nexport class Apiv3RelationsPaths extends APIv3ResourceCollection> {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'relations');\n }\n\n /**\n * Get all versions\n */\n public get():Observable> {\n return this\n .halResourceService\n .get>(this.path);\n }\n\n public loadInvolved(workPackageIds:string[]):Observable {\n let validIds = _.filter(workPackageIds, id => /\\d+/.test(id));\n\n if (validIds.length === 0) {\n return from([]);\n }\n\n return this\n .filtered(buildApiV3Filter('involved', '=', validIds))\n .get()\n .pipe(\n map(collection => collection.elements)\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource, APIv3ResourcePath} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {Apiv3RelationsPaths} from \"core-app/modules/apiv3/endpoints/relations/apiv3-relations-paths\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {Observable} from \"rxjs\";\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {APIV3WorkPackagesPaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIV3WorkPackagePaths extends CachableAPIV3Resource {\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/relations\n public readonly relations = this.subResource('relations', Apiv3RelationsPaths);\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/revisions\n public readonly revisions = this.subResource('revisions');\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/activities\n public readonly activities = this.subResource('activities');\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/available_watchers\n public readonly available_watchers = this.subResource('available_watchers');\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/available_projects\n public readonly available_projects = this.subResource('available_projects');\n\n protected createCache():StateCacheService {\n return (this.parent as APIV3WorkPackagesPaths).cache;\n }\n}\n","import {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {Observable} from \"rxjs\";\nimport {HalSource} from \"core-app/modules/hal/resources/hal-resource\";\n\nexport class APIv3WorkPackageForm extends APIv3FormResource {\n /**\n * Returns a promise to post `/api/v3/work_packages/form` with only the type part of the\n * provided payload being sent to the backend.\n *\n * @param payload: The payload to be sent to the backend\n * @returns A work package form resource prefilled with the provided payload.\n */\n public forTypePayload(payload:HalSource):Observable {\n let typePayload = payload._links['type'] ? { _links: { type: payload['_links']['type'] } } : { _links: {} } ;\n\n return this.post(payload);\n }\n /**\n * Returns a promise to post `/api/v3/work_packages/form` where the\n * payload sent to the backend has been provided.\n *\n * @param payload: The payload to be sent to the backend\n * @returns A work package form resource prefilled with the provided payload.\n */\n public forPayload(payload:HalSource):Observable {\n return this.post(payload);\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {MultiInputState} from 'reactivestates';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Injectable, Injector} from '@angular/core';\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Injectable()\nexport class WorkPackageCache extends StateCacheService {\n @InjectField() private schemaCacheService:SchemaCacheService;\n\n constructor(readonly injector:Injector,\n state:MultiInputState) {\n super(state);\n }\n\n updateValue(id:string, val:WorkPackageResource):Promise {\n return this.schemaCacheService.ensureLoaded(val).then(() => {\n this.putValue(id, val);\n return val;\n });\n }\n\n updateWorkPackage(wp:WorkPackageResource, immediate:boolean = false):Promise {\n if (immediate || wp.isNew) {\n return super.updateValue(wp.id!, wp);\n } else {\n return this.updateValue(wp.id!, wp);\n }\n }\n\n updateWorkPackageList(list:WorkPackageResource[], skipOnIdentical = true) {\n for (var i of list) {\n const wp = i;\n const workPackageId = wp.id!;\n const state = this.multiState.get(workPackageId);\n\n // If the work package is new, ignore the schema\n if (wp.isNew) {\n state.putValue(wp);\n continue;\n }\n\n // Ensure the schema is loaded\n // so that no consumer needs to call schema#$load manually\n this.schemaCacheService.ensureLoaded(wp).then(() => {\n // Check if the work package has changed\n if (skipOnIdentical && state.hasValue() && _.isEqual(state.value!.$source, wp.$source)) {\n debugLog('Skipping identical work package from updating');\n return;\n }\n\n state.putValue(wp);\n });\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {Observable} from \"rxjs\";\nimport {APIV3WorkPackagesPaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths\";\nimport {take, tap} from \"rxjs/operators\";\nimport {WorkPackageCache} from \"core-app/modules/apiv3/endpoints/work_packages/work-package.cache\";\n\nexport class ApiV3WorkPackageCachedSubresource extends APIv3GettableResource {\n\n public get():Observable {\n return this\n .halResourceService\n .get(this.path)\n .pipe(\n tap(collection => this.cache.updateWorkPackageList(collection.elements)),\n take(1)\n );\n }\n\n protected get cache():WorkPackageCache {\n return (this.parent as APIV3WorkPackagesPaths).cache;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIV3WorkPackagePaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-package-paths\";\nimport {ApiV3FilterBuilder, buildApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {Observable} from \"rxjs\";\nimport {APIv3WorkPackageForm} from \"core-app/modules/apiv3/endpoints/work_packages/apiv3-work-package-form\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {WorkPackageCache} from \"core-app/modules/apiv3/endpoints/work_packages/work-package.cache\";\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {ApiV3WorkPackageCachedSubresource} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-package-cached-subresource\";\n\nexport class APIV3WorkPackagesPaths extends CachableAPIV3Collection {\n // Base path\n public readonly path:string;\n\n constructor(readonly apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'work_packages', APIV3WorkPackagePaths);\n }\n\n // Static paths\n\n // /api/v3/(projects/:projectIdentifier)/work_packages/form\n public readonly form:APIv3WorkPackageForm = this.subResource('form', APIv3WorkPackageForm);\n\n /**\n *\n * Load a collection of work packages and put them all into cache\n *\n * @param ids\n */\n public requireAll(ids:string[]):Promise {\n return new Promise((resolve, reject) => {\n this\n .loadCollectionsFor(_.uniq(ids))\n .then((pagedResults:WorkPackageCollectionResource[]) => {\n _.each(pagedResults, (results) => {\n if (results.schemas) {\n _.each(results.schemas.elements, (schema:SchemaResource) => {\n this.states.schemas.get(schema.href as string).putValue(schema);\n });\n }\n\n if (results.elements) {\n this.cache.updateWorkPackageList(results.elements);\n }\n\n });\n\n resolve(undefined);\n }, reject);\n });\n }\n\n /**\n * Create a work package from a form payload\n *\n * @param payload\n * @return {Promise}\n */\n public post(payload:Object):Observable {\n return this\n .halResourceService\n .post(this.path, payload)\n .pipe(\n this.cacheResponse()\n );\n }\n\n filtered>(filters:ApiV3FilterBuilder, params:{ [p:string]:string } = {}):R {\n return super.filtered(filters, params, ApiV3WorkPackageCachedSubresource) as any;\n }\n\n /**\n * Shortcut to filter work packages by subject or ID\n * @param term\n * @param idOnly\n * @param additionalParams Additional set of params to the API\n */\n public filterBySubjectOrId(term:string, idOnly:boolean = false, additionalParams:{ [key:string]:string } = {}):ApiV3WorkPackageCachedSubresource {\n let filters:ApiV3FilterBuilder = new ApiV3FilterBuilder();\n\n if (idOnly) {\n filters.add('id', '=', [term]);\n } else {\n filters.add('subjectOrId', '**', [term]);\n }\n\n let params = {\n sortBy: '[[\"updatedAt\",\"desc\"]]',\n offset: '1',\n pageSize: '10',\n ...additionalParams\n };\n\n return this.filtered(filters, params);\n }\n\n /**\n * Returns work packages within the ids array to be updated since \n * @param ids work package IDs to filter for\n * @param timestamp The timestamp to clip at\n */\n public filterUpdatedSince(ids:(string|null)[], timestamp:unknown):ApiV3WorkPackageCachedSubresource {\n let filters = new ApiV3FilterBuilder()\n .add('id', '=', ids.filter((n:String|null) => n)) // no null values\n .add('updatedAt', '<>d', [timestamp, '']);\n\n let params = {\n offset: '1',\n pageSize: '10'\n };\n\n return this.filtered(filters, params);\n }\n\n /**\n * Loads the work packages collection for the given work package IDs.\n * Returns a WP Collection with schemas and results embedded.\n *\n * @param ids\n * @return {WorkPackageCollectionResource[]}\n */\n protected loadCollectionsFor(ids:string[]):Promise {\n return this\n .halResourceService\n .getAllPaginated(\n this.path,\n ids.length,\n {\n filters: buildApiV3Filter('id', '=', ids).toJson(),\n }\n );\n }\n\n protected createCache():WorkPackageCache {\n return new WorkPackageCache(this.injector, this.states.workPackages);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {Observable} from \"rxjs\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {MultiInputState} from \"reactivestates\";\nimport {tap} from \"rxjs/operators\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIv3VersionPaths extends CachableAPIV3Resource {\n\n /**\n * Update a version resource with the given payload\n *\n * @param resource\n * @param payload\n */\n public patch(payload:Object):Observable {\n return this\n .halResourceService\n .patch(\n this.path,\n payload\n )\n .pipe(\n tap(version => this.touch(version))\n );\n }\n\n protected createCache():StateCacheService {\n return new StateCacheService(this.states.versions);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {Observable} from \"rxjs\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {Apiv3AvailableProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-available-projects-paths\";\nimport {APIv3VersionPaths} from \"core-app/modules/apiv3/endpoints/versions/apiv3-version-paths\";\n\nexport class APIv3VersionsPaths extends APIv3ResourceCollection {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'versions', APIv3VersionPaths);\n }\n\n // /api/v3/versions/form\n public readonly form = this.subResource('form', APIv3FormResource);\n\n public readonly available_projects = this.subResource('available_projects', Apiv3AvailableProjectsPaths);\n\n /**\n * Get all versions\n */\n public get():Observable> {\n return this\n .halResourceService\n .get>(this.path);\n }\n\n /**\n * Create a version from the given payload\n *\n * @param payload\n * @return {Promise}\n */\n public post(payload:Object):Observable {\n return this\n .halResourceService\n .post(this.path, payload);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3QueriesPaths} from \"core-app/modules/apiv3/endpoints/queries/apiv3-queries-paths\";\nimport {APIv3TypesPaths} from \"core-app/modules/apiv3/endpoints/types/apiv3-types-paths\";\nimport {APIV3WorkPackagesPaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {MultiInputState} from \"reactivestates\";\nimport {APIv3VersionsPaths} from \"core-app/modules/apiv3/endpoints/versions/apiv3-versions-paths\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {APIv3ProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-projects-paths\";\n\nexport class APIv3ProjectPaths extends CachableAPIV3Resource {\n // /api/v3/projects/:project_id/available_assignees\n public readonly available_assignees = this.subResource('available_assignees');\n\n // /api/v3/projects/:project_id/queries\n public readonly queries = new APIv3QueriesPaths(this.apiRoot, this.path);\n\n // /api/v3/projects/:project_id/types\n public readonly types = new APIv3TypesPaths(this.apiRoot, this.path);\n\n // /api/v3/projects/:project_id/work_packages\n public readonly work_packages = new APIV3WorkPackagesPaths(this.apiRoot, this.path);\n\n // /api/v3/projects/:project_id/versions\n public readonly versions = new APIv3VersionsPaths(this.apiRoot, this.path);\n\n protected createCache():StateCacheService {\n return (this.parent as APIv3ProjectsPaths).cache;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {MultiInputState} from 'reactivestates';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Injectable, Injector} from '@angular/core';\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\n\n@Injectable()\nexport class ProjectCache extends StateCacheService {\n @InjectField() private schemaCacheService:SchemaCacheService;\n\n constructor(readonly injector:Injector,\n state:MultiInputState) {\n super(state);\n }\n\n updateValue(id:string, val:ProjectResource):Promise {\n return this.schemaCacheService.ensureLoaded(val).then(() => {\n this.putValue(id, val);\n return val;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3ProjectPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-project-paths\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface,\n listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {Observable} from \"rxjs\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {ProjectCache} from \"core-app/modules/apiv3/endpoints/projects/project.cache\";\n\nexport class APIv3ProjectsPaths\n extends CachableAPIV3Collection\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'projects', APIv3ProjectPaths);\n }\n\n // /api/v3/projects/schema\n public readonly schema = this.subResource('schema');\n\n /**\n * Load a list of project with a given list parameter filter\n *\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params))\n .pipe(\n this.cacheResponse()\n );\n }\n\n protected createCache():StateCacheService {\n return new ProjectCache(this.injector, this.states.projects);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {StatusResource} from \"core-app/modules/hal/resources/status-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIv3StatusPaths extends CachableAPIV3Resource {\n\n protected createCache():StateCacheService {\n return new StateCacheService(this.states.statuses);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3ResourceCollection, APIv3ResourcePath} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {Injector} from \"@angular/core\";\nimport {StatusResource} from \"core-app/modules/hal/resources/status-resource\";\nimport {APIv3StatusPaths} from \"core-app/modules/apiv3/endpoints/statuses/apiv3-status-paths\";\nimport {Observable} from \"rxjs\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {tap} from \"rxjs/operators\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class APIv3StatusesPaths extends APIv3ResourceCollection {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'statuses', APIv3StatusPaths);\n }\n\n /**\n * Perform a request to the HalResourceService with the current path\n */\n public get():Observable> {\n return this\n .halResourceService\n .get>(this.path)\n .pipe(\n tap(collection => {\n collection.elements.forEach((resource, id) => {\n this.id(resource.id!).cache.updateValue(resource.id!, resource);\n });\n })\n );\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface,\n listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {NewsResource} from \"core-app/modules/hal/resources/news-resource\";\n\nexport class Apiv3NewsPaths\n extends APIv3ResourceCollection>\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'news');\n }\n\n /**\n * Load a list of time entries with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {HelpTextResource} from \"core-app/modules/hal/resources/help-text-resource\";\n\nexport class Apiv3HelpTextsPaths\n extends APIv3ResourceCollection> {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'help_texts');\n }\n\n /**\n * Load a list of membership entries with a given list parameter filter\n * @param params\n */\n public get():Observable> {\n return this\n .halResourceService\n .get>(this.path);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {ConfigurationResource} from \"core-app/modules/hal/resources/configuration-resource\";\nimport {Observable} from \"rxjs\";\nimport {shareReplay} from \"rxjs/operators\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class Apiv3ConfigurationPath extends APIv3GettableResource {\n private $configuration:Observable;\n\n constructor(protected apiRoot:APIV3Service,\n readonly basePath:string) {\n super(apiRoot, basePath, 'configuration');\n }\n\n\n\n public get():Observable {\n if (this.$configuration) {\n return this.$configuration;\n }\n\n return this.$configuration = this.halResourceService\n .get(this.path)\n .pipe(\n shareReplay()\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Board} from \"core-app/modules/boards/board/board\";\nimport {Observable} from \"rxjs\";\nimport {map, switchMap, tap} from \"rxjs/operators\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {MultiInputState} from \"reactivestates\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {Apiv3BoardsPaths} from \"core-app/modules/apiv3/virtual/apiv3-boards-paths\";\n\nexport class APIv3BoardPath extends CachableAPIV3Resource {\n\n /**\n * Perform a request to the HalResourceService with the current path\n */\n protected load():Observable {\n return this\n .apiRoot\n .grids\n .id(this.id)\n .get()\n .pipe(\n map(grid => {\n const newBoard = new Board(grid);\n\n newBoard.sortWidgets();\n\n return newBoard;\n })\n );\n }\n\n /**\n * Save the changes to the board\n */\n public save(board:Board):Observable {\n return this\n .fetchSchema(board)\n .pipe(\n switchMap((schema:SchemaResource) => this\n .apiRoot\n .grids\n .id(board.grid)\n .patch(board.grid, schema)\n ),\n map(grid => {\n board.grid = grid;\n board.sortWidgets();\n return board;\n }),\n this.cacheResponse()\n );\n }\n\n public delete():Observable {\n return this\n .apiRoot\n .grids\n .id(this.id)\n .delete()\n .pipe(\n tap(() => this.cache.clearSome(this.id.toString()))\n );\n }\n\n private fetchSchema(board:Board):Observable {\n return this\n .apiRoot\n .grids\n .id(board.grid)\n .form\n .post({})\n .pipe(\n map(form => form.schema)\n );\n }\n\n protected createCache():StateCacheService {\n return (this.parent as Apiv3BoardsPaths).cache;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Constructor} from \"@angular/cdk/table\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {Apiv3ListParameters, listParamsString} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {Board, BoardType} from \"core-app/modules/boards/board/board\";\nimport {map, switchMap, tap} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {MultiInputState} from \"reactivestates\";\nimport {APIv3BoardPath} from \"core-app/modules/apiv3/virtual/apiv3-board-path\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class Apiv3BoardsPaths extends CachableAPIV3Collection {\n\n @InjectField() private authorisationService:AuthorisationService;\n @InjectField() private PathHelper:PathHelperService;\n\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'grids', APIv3BoardPath);\n }\n\n /**\n * Load a list of grids with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params))\n .pipe(\n tap(collection => this.authorisationService.initModelAuth('boards', collection.$links)),\n map(collection =>\n collection.elements.map(grid => {\n let board = new Board(grid);\n board.sortWidgets();\n this.touch(board);\n\n return board;\n })\n )\n );\n }\n\n /**\n * Return all boards in the current scope of the project\n *\n * @param projectIdentifier\n */\n public allInScope(projectIdentifier:string):Observable {\n const path = this.boardPath(projectIdentifier);\n return this.list({ filters: [['scope', '=', [path]]] });\n }\n\n /**\n * Create a new board\n * @param type\n * @param name\n * @param projectIdentifier\n */\n public create(type:BoardType, name:string, projectIdentifier:string, actionAttribute?:string):Observable {\n const scope = this.boardPath(projectIdentifier);\n return this\n .createGrid(type, name, scope, actionAttribute)\n .pipe(\n map(grid => new Board(grid))\n );\n }\n\n /**\n * Retrieve the board path identifier for looking up grids.\n *\n * @param projectIdentifier The current project identifier\n */\n public boardPath(projectIdentifier:string) {\n return this.PathHelper.projectBoardsPath(projectIdentifier);\n }\n\n protected createCache():StateCacheService {\n let state = this.states.forType('boards');\n return new StateCacheService(state);\n }\n\n private createGrid(type:BoardType, name:string, scope:string, actionAttribute?:string):Observable {\n let payload:any = _.set({ name: name }, '_links.scope.href', scope);\n payload.options = {\n type: type,\n };\n\n if (actionAttribute) {\n payload.options.attribute = actionAttribute;\n }\n\n return this\n .apiRoot\n .grids\n .form\n .post(payload)\n .pipe(\n switchMap((form) => {\n return this\n .apiRoot\n .grids\n .post(form.payload.$source);\n })\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from \"@angular/core\";\nimport {\n APIv3GettableResource,\n APIv3ResourceCollection,\n APIv3ResourcePath\n} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {Constructor} from \"@angular/cdk/table\";\nimport {Apiv3GridsPaths} from \"core-app/modules/apiv3/endpoints/grids/apiv3-grids-paths\";\nimport {Apiv3TimeEntriesPaths} from \"core-app/modules/apiv3/endpoints/time-entries/apiv3-time-entries-paths\";\nimport {Apiv3MembershipsPaths} from \"core-app/modules/apiv3/endpoints/memberships/apiv3-memberships-paths\";\nimport {Apiv3UsersPaths} from \"core-app/modules/apiv3/endpoints/users/apiv3-users-paths\";\nimport {APIv3TypesPaths} from \"core-app/modules/apiv3/endpoints/types/apiv3-types-paths\";\nimport {APIv3QueriesPaths} from \"core-app/modules/apiv3/endpoints/queries/apiv3-queries-paths\";\nimport {APIv3ProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-projects-paths\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {APIV3WorkPackagesPaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIv3ProjectPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-project-paths\";\nimport {RootResource} from \"core-app/modules/hal/resources/root-resource\";\nimport {APIv3StatusesPaths} from \"core-app/modules/apiv3/endpoints/statuses/apiv3-statuses-paths\";\nimport {APIv3VersionsPaths} from \"core-app/modules/apiv3/endpoints/versions/apiv3-versions-paths\";\nimport {Apiv3RelationsPaths} from \"core-app/modules/apiv3/endpoints/relations/apiv3-relations-paths\";\nimport {Apiv3NewsPaths} from \"core-app/modules/apiv3/endpoints/news/apiv3-news-paths\";\nimport {Apiv3HelpTextsPaths} from \"core-app/modules/apiv3/endpoints/help_texts/apiv3-help-texts-paths\";\nimport {Apiv3ConfigurationPath} from \"core-app/modules/apiv3/endpoints/configuration/apiv3-configuration-path\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport * as ts from \"typescript/lib/tsserverlibrary\";\nimport Project = ts.server.Project;\nimport {Apiv3BoardsPaths} from \"core-app/modules/apiv3/virtual/apiv3-boards-paths\";\n\n@Injectable({ providedIn: 'root' })\nexport class APIV3Service {\n // /api/v3/attachments\n public readonly attachments = this.apiV3CollectionEndpoint('attachments');\n\n // /api/v3/configuration\n public readonly configuration = this.apiV3CustomEndpoint(Apiv3ConfigurationPath);\n\n // /api/v3/documents\n public readonly documents = this.apiV3CollectionEndpoint('documents');\n\n // /api/v3/grids\n public readonly grids = this.apiV3CustomEndpoint(Apiv3GridsPaths);\n\n // /api/v3/groups\n public readonly groups = this.apiV3CollectionEndpoint('groups');\n\n // /api/v3/root\n public readonly root = this.apiV3SingularEndpoint('');\n\n // /api/v3/statuses\n public readonly statuses = this.apiV3CustomEndpoint(APIv3StatusesPaths);\n\n // /api/v3/relations\n public readonly relations = this.apiV3CustomEndpoint(Apiv3RelationsPaths);\n\n // /api/v3/priorities\n public readonly priorities = this.apiV3CollectionEndpoint('priorities');\n\n // /api/v3/time_entries\n public readonly time_entries = this.apiV3CustomEndpoint(Apiv3TimeEntriesPaths);\n\n // /api/v3/memberships\n public readonly memberships = this.apiV3CustomEndpoint(Apiv3MembershipsPaths);\n\n // /api/v3/news\n public readonly news = this.apiV3CustomEndpoint(Apiv3NewsPaths);\n\n // /api/v3/types\n public readonly types = this.apiV3CustomEndpoint(APIv3TypesPaths);\n\n // /api/v3/versions\n public readonly versions = this.apiV3CustomEndpoint(APIv3VersionsPaths);\n\n // /api/v3/work_packages\n public readonly work_packages = this.apiV3CustomEndpoint(APIV3WorkPackagesPaths);\n\n // /api/v3/queries\n public readonly queries = this.apiV3CustomEndpoint(APIv3QueriesPaths);\n\n // /api/v3/projects\n public readonly projects = this.apiV3CustomEndpoint(APIv3ProjectsPaths);\n\n // /api/v3/users\n public readonly users = this.apiV3CustomEndpoint(Apiv3UsersPaths);\n\n // /api/v3/placeholderUsers\n public readonly placeholder_users = this.apiV3CollectionEndpoint('placeholder_users')\n\n // /api/v3/help_texts\n public readonly help_texts = this.apiV3CustomEndpoint(Apiv3HelpTextsPaths);\n\n // /api/v3/job_statuses\n public readonly job_statuses = this.apiV3CollectionEndpoint('job_statuses');\n\n // VIRTUAL boards are /api/v3/grids + a scope filter\n public readonly boards = this.apiV3CustomEndpoint(Apiv3BoardsPaths);\n\n constructor(readonly injector:Injector,\n readonly pathHelper:PathHelperService) {\n }\n\n /**\n * Returns the part of the API that exists both\n * - WITHIN a project scope /api/v3/projects/*\n * - GLOBALLY /api/v3/*\n *\n * The available API endpoints are being restricted automatically by typescript.\n *\n * @param projectIdentifier\n */\n public withOptionalProject(projectIdentifier:string|number|null|undefined):APIv3ProjectPaths|this {\n if (_.isNil(projectIdentifier)) {\n return this;\n } else {\n return this.projects.id(projectIdentifier);\n }\n }\n\n public collectionFromString(fullPath:string) {\n const path = fullPath.replace(this.pathHelper.api.v3.apiV3Base + '/', '');\n\n return this.apiV3CollectionEndpoint(path);\n }\n\n private apiV3CollectionEndpoint>(segment:string, resource?:Constructor) {\n return new APIv3ResourceCollection(this, this.pathHelper.api.v3.apiV3Base, segment, resource);\n }\n\n private apiV3CustomEndpoint(cls:Constructor):T {\n return new cls(this, this.pathHelper.api.v3.apiV3Base);\n }\n\n private apiV3SingularEndpoint(segment:string):APIv3GettableResource {\n return new APIv3GettableResource(this, this.pathHelper.api.v3.apiV3Base, segment);\n }\n}\n","
    \n \n \n \n \n \n {{ selectedTitle || text.input_placeholder }}{{ selectedTitle ? '  ' : ''}}\n
    \n

    {{ selectedTitle }}\n

    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {\n Component,\n ElementRef,\n EventEmitter,\n Injector,\n Input,\n OnChanges,\n OnInit,\n Output,\n SimpleChanges,\n ViewChild\n} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ContainHelpers} from \"core-app/modules/common/focus/contain-helpers\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport const triggerEditingEvent = 'op:selectableTitle:trigger';\nexport const selectableTitleIdentifier = 'editable-toolbar-title';\n\n@Component({\n selector: 'editable-toolbar-title',\n templateUrl: './editable-toolbar-title.html',\n styleUrls: ['./editable-toolbar-title.sass'],\n host: {'class': 'title-container'}\n})\nexport class EditableToolbarTitleComponent implements OnInit, OnChanges {\n @Input('title') public inputTitle:string;\n @Input() public editable:boolean = true;\n @Input() public inFlight:boolean = false;\n @Input() public showSaveCondition:boolean = false;\n @Input() public initialFocus:boolean = false;\n @Input() public smallHeader:boolean = false;\n\n @Output() public onSave = new EventEmitter();\n @Output() public onEmptySubmit = new EventEmitter();\n\n @ViewChild('editableTitleInput') inputField?:ElementRef;\n\n public selectedTitle:string;\n public selectableTitleIdentifier = selectableTitleIdentifier;\n\n @InjectField() protected readonly elementRef:ElementRef;\n @InjectField() I18n!:I18nService;\n\n public text = {\n click_to_edit: this.I18n.t('js.work_packages.query.click_to_edit_query_name'),\n press_enter_to_save: this.I18n.t('js.label_press_enter_to_save'),\n query_has_changed_click_to_save: this.I18n.t('js.label_view_has_changed'),\n input_title: '',\n input_placeholder: this.I18n.t('js.work_packages.query.rename_query_placeholder'),\n search_query_title: this.I18n.t('js.toolbar.search_query_title'),\n confirm_edit_cancel: this.I18n.t('js.work_packages.query.confirm_edit_cancel'),\n duplicate_query_title: this.I18n.t('js.work_packages.query.errors.duplicate_query_title')\n };\n\n constructor(readonly injector:Injector) {\n }\n\n ngOnInit() {\n this.text['input_title'] = `${this.text.click_to_edit} ${this.text.press_enter_to_save}`;\n\n jQuery(this.elementRef.nativeElement).on(triggerEditingEvent, (evt:Event, val:string = '') => {\n // In case we're not editable, ignore request\n if (!this.inputField) {\n return;\n }\n\n this.selectedTitle = val;\n setTimeout(() => {\n const field:HTMLInputElement = this.inputField!.nativeElement;\n field.focus();\n }, 20);\n\n evt.stopPropagation();\n });\n }\n\n ngOnChanges(changes:SimpleChanges):void {\n\n if (changes.inputTitle) {\n this.selectedTitle = changes.inputTitle.currentValue;\n }\n\n if (changes.initialFocus && changes.initialFocus.firstChange && this.inputField!) {\n const field:HTMLInputElement = this.inputField!.nativeElement;\n this.selectInputOnInitalFocus(field);\n }\n\n }\n\n public onFocus(event:FocusEvent) {\n this.toggleToolbarButtonVisibility(true);\n this.selectInputOnInitalFocus(event.target as HTMLInputElement);\n }\n\n public onBlur() {\n this.toggleToolbarButtonVisibility(false);\n }\n\n public selectInputOnInitalFocus(input:HTMLInputElement) {\n if (this.initialFocus) {\n input.select();\n this.initialFocus = false;\n }\n }\n\n public saveWhenFocusOutside($event:FocusEvent) {\n ContainHelpers.whenOutside(this.elementRef.nativeElement, () => this.save($event));\n }\n\n public reset() {\n this.resetInputField();\n this.selectedTitle = this.inputTitle;\n }\n\n public get showSave() {\n return this.editable && this.showSaveCondition;\n }\n\n public save($event:Event, force = false) {\n $event.preventDefault();\n\n this.resetInputField();\n this.selectedTitle = this.selectedTitle.trim();\n\n // If the title is empty, show an error\n if (this.isEmpty) {\n this.onEmptyError();\n return;\n }\n\n if (!force && this.inputTitle === this.selectedTitle) {\n return; // Nothing changed\n }\n\n // Blur this element\n if (this.inputField) {\n (this.inputField.nativeElement as HTMLInputElement).blur();\n }\n\n // Avoid double saving\n if (this.inFlight) {\n return;\n }\n\n this.inFlight = true;\n\n this.emitSave(this.selectedTitle);\n\n // Unset in-flight after some delay not to trigger the blur\n setTimeout(() => this.inFlight = false, 100);\n }\n\n public get isEmpty():boolean {\n return this.selectedTitle === '';\n }\n\n /**\n * Called when saving the changed title\n */\n private emitSave(title:string) {\n this.onSave.emit(title);\n }\n\n /**\n * Called when trying to save an empty text\n */\n private onEmptyError() {\n // this.updateItemInMenu(); // Throws an error message, when name is empty\n this.onEmptySubmit.emit();\n this.focusInputOnError();\n }\n\n private focusInputOnError() {\n if (this.inputField) {\n const el = this.inputField.nativeElement;\n el.classList.add('-error');\n el.focus();\n }\n }\n\n private resetInputField() {\n if (this.inputField) {\n const el = this.inputField.nativeElement;\n el.classList.remove('-error');\n }\n }\n\n private toggleToolbarButtonVisibility(hidden:boolean) {\n jQuery('.toolbar-items').toggleClass('hidden-for-mobile', hidden);\n }\n}\n","import {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\n\nexport class WidgetChangeset extends ResourceChangeset {\n\n}\n","import {Directive, EventEmitter, HostBinding, Injector, Input, Output} from \"@angular/core\";\nimport {GridWidgetResource} from \"app/modules/hal/resources/grid-widget-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WidgetChangeset} from \"core-app/modules/grids/widgets/widget-changeset\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Directive()\nexport abstract class AbstractWidgetComponent extends UntilDestroyedMixin {\n @HostBinding('style.grid-column-start') gridColumnStart:number;\n @HostBinding('style.grid-column-end') gridColumnEnd:number;\n @HostBinding('style.grid-row-start') gridRowStart:number;\n @HostBinding('style.grid-row-end') gridRowEnd:number;\n\n @Input() resource:GridWidgetResource;\n\n @Output() resourceChanged = new EventEmitter();\n\n public get widgetName():string {\n let editableName = this.resource?.options.name as string;\n let widgetIdentifier = this.resource?.identifier;\n\n if (this.isEditable) {\n return editableName;\n } else {\n return this.i18n.t(\n `js.grid.widgets.${widgetIdentifier}.title`,\n { defaultValue: editableName }\n );\n }\n }\n\n public renameWidget(name:string) {\n let changeset = this.setChangesetOptions({ name: name });\n\n this.resourceChanged.emit(changeset);\n }\n\n /**\n * By default, all widget titles are editable by the user.\n * We arbitrarily restrict this for some resources however,\n * whose component classes will set this to false.\n */\n public get isEditable() {\n return true;\n }\n\n constructor(protected i18n:I18nService,\n protected injector:Injector) {\n super();\n }\n\n protected setChangesetOptions(values:{ [key:string]:unknown; }) {\n let changeset = new WidgetChangeset(this.resource);\n\n changeset.setValue('options', Object.assign({}, this.resource.options, values));\n\n return changeset;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {IFCGonDefinition} from \"../../bim/ifc_models/pages/viewer/ifc-models-data.service\";\n\ndeclare global {\n interface Window {\n gon:GonType;\n }\n}\n\nexport interface GonType {\n [key:string]:unknown;\n ifc_models:IFCGonDefinition;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class GonService {\n get(...path:string[]):unknown|null {\n return _.get(window.gon, path, null);\n }\n\n /**\n * Get the gon object\n */\n get gon():GonType {\n return window.gon;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component, Input} from '@angular/core';\nimport {BackRoutingService} from \"core-app/modules/common/back-routing/back-routing.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n template: `\n
    \n \n \n \n
    \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'back-button',\n})\nexport class BackButtonComponent {\n @Input() public linkClass:string;\n @Input() public customBackMethod:Function;\n\n public text = {\n goBack: this.I18n.t('js.button_back')\n };\n\n constructor(readonly backRoutingService:BackRoutingService,\n readonly I18n:I18nService) {\n }\n\n public goBack() {\n if (this.customBackMethod) {\n this.customBackMethod();\n } else {\n this.backRoutingService.goBack();\n }\n }\n\n public classes():string {\n let classes = 'button ';\n classes += this.linkClass ? this.linkClass : '';\n\n return classes;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {InputState} from 'reactivestates';\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\n\nexport class SchemaResource extends HalResource {\n\n public get state():InputState {\n return this.states.schemas.get(this.href as string) as any;\n }\n\n public get availableAttributes() {\n return _.keys(this.$source).filter(name => name.indexOf('_') !== 0);\n }\n\n // Find the attribute name with a matching (localized) name;\n public attributeFromLocalizedName(name:string):string|null {\n let match:string|null = null;\n\n for (let attribute of this.availableAttributes) {\n let fieldSchema = this[attribute];\n if (fieldSchema?.name === name) {\n match = attribute;\n break;\n }\n }\n\n return match;\n }\n}\n\nexport class SchemaAttributeObject {\n public type:string;\n public name:string;\n public required:boolean;\n public hasDefault:boolean;\n public writable:boolean;\n public allowedValues:T[] | CollectionResource;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {QueryFormResource} from 'core-app/modules/hal/resources/query-form-resource';\nimport {States} from '../states.service';\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {WorkPackagesListInvalidQueryService} from './wp-list-invalid-query.service';\nimport {WorkPackageStatesInitializationService} from './wp-states-initialization.service';\nimport {AuthorisationService} from 'core-app/modules/common/model-auth/model-auth.service';\nimport {StateService} from '@uirouter/core';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {from, Observable, of} from 'rxjs';\nimport {input} from \"reactivestates\";\nimport {catchError, mergeMap, share, switchMap, take} from \"rxjs/operators\";\nimport {\n PaginationUpdateObject,\n WorkPackageViewPaginationService\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service\";\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\nimport {PaginationService} from \"core-components/table-pagination/pagination-service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {APIv3QueriesPaths} from \"core-app/modules/apiv3/endpoints/queries/apiv3-queries-paths\";\nimport {APIv3QueryPaths} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-paths\";\n\nexport interface QueryDefinition {\n queryParams:{ query_id?:string, query_props?:string };\n projectIdentifier?:string;\n}\n\n@Injectable()\nexport class WorkPackagesListService {\n\n // We remember the query requests coming in so we can ensure only the latest request is being tended to\n private queryRequests = input();\n\n // This mapped observable requests the latest query automatically.\n private queryLoading = this.queryRequests\n .values$()\n .pipe(\n switchMap((q:QueryDefinition) => {\n return from(this.ensurePerPageKnown().then(() => q));\n }),\n // Stream the query request, switchMap will call previous requests to be cancelled\n switchMap((q:QueryDefinition) =>\n this.streamQueryRequest(q.queryParams, q.projectIdentifier)\n ),\n // Map the observable from the stream to a new one that completes when states are loaded\n mergeMap((query:QueryResource) => {\n // load the form if needed\n this.conditionallyLoadForm(query);\n\n // Project the loaded query into the table states and confirm the query is fully loaded\n this.wpStatesInitialization.initialize(query, query.results);\n return of(query);\n }),\n // Share any consecutive requests to the same resource, this is due to switchMap\n // diverting observables to the LATEST emitted.\n share()\n );\n\n constructor(protected NotificationsService:NotificationsService,\n readonly I18n:I18nService,\n protected UrlParamsHelper:UrlParamsHelperService,\n protected authorisationService:AuthorisationService,\n protected $state:StateService,\n protected apiV3Service:APIV3Service,\n protected states:States,\n protected querySpace:IsolatedQuerySpace,\n protected pagination:PaginationService,\n protected configuration:ConfigurationService,\n protected wpTablePagination:WorkPackageViewPaginationService,\n protected wpStatesInitialization:WorkPackageStatesInitializationService,\n protected wpListInvalidQueryService:WorkPackagesListInvalidQueryService) {\n }\n\n /**\n * Stream a query request as a HTTP observable. Each request to this method will\n * result in a new HTTP request.\n *\n * @param queryParams\n * @param projectIdentifier\n */\n private streamQueryRequest(queryParams:{ query_id?:string, query_props?:string }, projectIdentifier ?:string):Observable {\n const decodedProps = this.getCurrentQueryProps(queryParams);\n const queryData = this.UrlParamsHelper.buildV3GetQueryFromJsonParams(decodedProps);\n const stream = this\n .apiV3Service\n .queries\n .find(queryData, queryParams.query_id, projectIdentifier);\n\n return stream.pipe(\n catchError((error) => {\n // Load a default query\n const queryProps = this.UrlParamsHelper.buildV3GetQueryFromJsonParams(decodedProps);\n return from(this.handleQueryLoadingError(error, queryProps, queryParams.query_id, projectIdentifier));\n })\n );\n }\n\n /**\n * Load a query.\n * The query is either a persisted query, identified by the query_id parameter, or the default query. Both will be modified by the parameters in the query_props parameter.\n */\n public fromQueryParams(queryParams:{ query_id?:string, query_props?:string }, projectIdentifier ?:string):Observable {\n this.queryRequests.clear();\n this.queryRequests.putValue({ queryParams: queryParams, projectIdentifier: projectIdentifier });\n\n return this\n .queryLoading\n .pipe(\n take(1)\n );\n }\n\n /**\n * Get the current decoded query props, if any\n */\n public getCurrentQueryProps(params:{ query_props?:string }):string|null {\n if (!!params.query_props) {\n return decodeURIComponent(params.query_props);\n }\n\n return null;\n }\n\n /**\n * Load the default query.\n */\n public loadDefaultQuery(projectIdentifier ?:string):Promise {\n return this.fromQueryParams({}, projectIdentifier).toPromise();\n }\n\n /**\n * Reloads the current query and set the pagination to the first page.\n */\n public reloadQuery(query:QueryResource, projectIdentifier?:string):Observable {\n const pagination = { ...this.wpTablePagination.current, page: 1 };\n const queryParams = this.UrlParamsHelper.encodeQueryJsonParams(query, pagination);\n\n this.queryRequests.clear();\n this.queryRequests.putValue({\n queryParams: { query_id: query.id || undefined, query_props: queryParams },\n projectIdentifier: projectIdentifier\n });\n\n return this\n .queryLoading\n .pipe(\n take(1)\n );\n }\n\n /**\n * Update the query from an existing (probably unsaved) query.\n *\n * Will choose the correct path:\n * - If the query is unsaved, use `/api/v3(/projects/:identifier)/queries/default`\n * - If the query is saved, use `/api/v3/queries/:id`\n *\n */\n public loadQueryFromExisting(query:QueryResource, additionalParams:Object, projectIdentifier?:string):Observable {\n const params = this.UrlParamsHelper.buildV3GetQueryFromQueryResource(query, additionalParams);\n\n let path:APIv3QueriesPaths|APIv3QueryPaths;\n\n if (query.id) {\n path = this.apiV3Service.queries.id(query.id);\n } else {\n path = this.apiV3Service.withOptionalProject(projectIdentifier).queries;\n }\n\n return path.parameterised(params);\n }\n\n /**\n * Load the query from the given state params\n */\n public loadCurrentQueryFromParams(projectIdentifier?:string) {\n return this\n .fromQueryParams(this.$state.params as any, projectIdentifier)\n .toPromise();\n }\n\n public loadForm(query:QueryResource):Promise {\n return this\n .apiV3Service\n .queries\n .form\n .load(query)\n .toPromise()\n .then(([form, _]) => {\n this.wpStatesInitialization.updateStatesFromForm(query, form);\n\n return form;\n });\n }\n\n /**\n * Persist the current query in the backend.\n * After the update, the new query is reloaded (e.g. for the work packages)\n */\n public create(query:QueryResource, name:string):Promise {\n let form = this.querySpace.queryForm.value!;\n\n query.name = name;\n\n let promise = this\n .apiV3Service\n .queries\n .post(query, form)\n .toPromise();\n\n promise\n .then(query => {\n this.NotificationsService.addSuccess(this.I18n.t('js.notice_successful_create'));\n\n // Reload the query, and then reload the menu\n this.reloadQuery(query).subscribe(() => {\n this.states.changes.queries.next(query.id!);\n });\n\n return query;\n });\n\n return promise;\n }\n\n /**\n * Destroy the current query.\n */\n public delete() {\n let query = this.currentQuery;\n\n let promise = this\n .apiV3Service\n .queries\n .id(query)\n .delete()\n .toPromise();\n\n promise\n .then(() => {\n this.NotificationsService.addSuccess(this.I18n.t('js.notice_successful_delete'));\n\n let id;\n if (query.project) {\n id = query.project.$href!.split('/').pop();\n }\n\n this.loadDefaultQuery(id);\n\n this.states.changes.queries.next(query.id!);\n });\n\n\n return promise;\n }\n\n public save(query?:QueryResource) {\n query = query || this.currentQuery;\n\n let form = this.querySpace.queryForm.value!;\n\n let promise = this\n .apiV3Service\n .queries\n .id(query)\n .patch(query, form)\n .toPromise();\n\n promise\n .then(() => {\n this.NotificationsService.addSuccess(this.I18n.t('js.notice_successful_update'));\n\n this.$state.go('.', { query_id: query!.id, query_props: null }, { reload: true });\n this.states.changes.queries.next(query!.id!);\n })\n .catch((error:ErrorResource) => {\n this.NotificationsService.addError(error.message);\n });\n\n return promise;\n }\n\n public toggleStarred(query:QueryResource):Promise {\n let promise = this\n .apiV3Service\n .queries\n .toggleStarred(query);\n\n promise.then((query:QueryResource) => {\n this.querySpace.query.putValue(query);\n\n this.NotificationsService.addSuccess(this.I18n.t('js.notice_successful_update'));\n\n this.states.changes.queries.next(query!.id!);\n });\n\n return promise;\n }\n\n public getPaginationInfo() {\n return this.wpTablePagination.paginationObject;\n }\n\n private conditionallyLoadForm(query:QueryResource):void {\n let currentForm = this.querySpace.queryForm.value;\n\n if (!currentForm || query.$links.update.$href !== currentForm.$href) {\n setTimeout(() => this.loadForm(query), 0);\n }\n }\n\n private updateStatesFromQueryOnPromise(promise:Promise):Promise {\n promise\n .then(query => {\n this.wpStatesInitialization.initialize(query, query.results);\n return query;\n });\n\n return promise;\n }\n\n public get currentQuery() {\n return this.querySpace.query.value!;\n }\n\n private handleQueryLoadingError(error:ErrorResource, queryProps:any, queryId?:string, projectIdentifier?:string|null):Promise {\n this.NotificationsService.addError(this.I18n.t('js.work_packages.faulty_query.description'), error.message);\n\n return new Promise((resolve, reject) => {\n this\n .apiV3Service\n .queries\n .form\n .loadWithParams(queryProps, queryId, projectIdentifier)\n .toPromise()\n .then(([form, _]) => {\n this\n .apiV3Service\n .queries\n .find({ pageSize: 0}, undefined, projectIdentifier)\n .toPromise()\n .then((query:QueryResource) => {\n this.wpListInvalidQueryService.restoreQuery(query, form);\n\n query.results.pageSize = queryProps.pageSize;\n query.results.total = 0;\n\n if (queryId) {\n query.id = queryId;\n }\n\n this.wpStatesInitialization.initialize(query, query.results);\n this.wpStatesInitialization.updateStatesFromForm(query, form);\n\n resolve(query);\n })\n .catch(reject);\n })\n .catch(reject);\n });\n }\n\n private async ensurePerPageKnown() {\n if (this.pagination.isPerPageKnown) {\n return true;\n } else {\n return this.configuration.initialized;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectorRef, Directive, Injector, OnDestroy, OnInit} from '@angular/core';\nimport {StateService, TransitionService} from '@uirouter/core';\nimport {AuthorisationService} from 'core-app/modules/common/model-auth/model-auth.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {filter, take, withLatestFrom} from 'rxjs/operators';\nimport {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageStaticQueriesService} from 'core-components/wp-query-select/wp-static-queries.service';\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {States} from \"core-components/states.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {WorkPackageViewSumService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageViewPaginationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {WorkPackagesListChecksumService} from \"core-components/wp-list/wp-list-checksum.service\";\nimport {WorkPackageQueryStateService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service\";\nimport {WorkPackageStatesInitializationService} from \"core-components/wp-list/wp-states-initialization.service\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {WorkPackageViewDisplayRepresentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {HalEvent, HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Directive()\nexport abstract class WorkPackagesViewBase extends UntilDestroyedMixin implements OnInit, OnDestroy {\n\n @InjectField() $state:StateService;\n @InjectField() states:States;\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() authorisationService:AuthorisationService;\n @InjectField() wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() wpTableHighlighting:WorkPackageViewHighlightingService;\n @InjectField() wpTableSortBy:WorkPackageViewSortByService;\n @InjectField() wpTableGroupBy:WorkPackageViewGroupByService;\n @InjectField() wpTableFilters:WorkPackageViewFiltersService;\n @InjectField() wpTableSum:WorkPackageViewSumService;\n @InjectField() wpTableTimeline:WorkPackageViewTimelineService;\n @InjectField() wpTableHierarchies:WorkPackageViewHierarchiesService;\n @InjectField() wpTablePagination:WorkPackageViewPaginationService;\n @InjectField() wpTableOrder:WorkPackageViewOrderService;\n @InjectField() wpListService:WorkPackagesListService;\n @InjectField() wpListChecksumService:WorkPackagesListChecksumService;\n @InjectField() loadingIndicatorService:LoadingIndicatorService;\n @InjectField() $transitions:TransitionService;\n @InjectField() I18n!:I18nService;\n @InjectField() wpStaticQueries:WorkPackageStaticQueriesService;\n @InjectField() wpStatesInitialization:WorkPackageStatesInitializationService;\n @InjectField() cdRef:ChangeDetectorRef;\n @InjectField() wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService;\n @InjectField() halEvents:HalEventsService;\n @InjectField() deviceService:DeviceService;\n @InjectField() currentProject:CurrentProjectService;\n\n /** Determine when query is initially loaded */\n queryLoaded = false;\n\n /** Remember explicitly when this component was destroyed */\n destroyed = false;\n\n constructor(public injector:Injector) {\n super();\n }\n\n ngOnInit() {\n // Listen to changes on the query state objects\n this.setupQueryObservers();\n\n // Listen for refresh changes\n this.setupRefreshObserver();\n\n // Mark tableInformationLoaded when initially loading done\n this.setupQueryLoadedListener();\n }\n\n private setupQueryObservers() {\n this.wpTablePagination\n .updates$()\n .pipe(\n this.untilDestroyed(),\n withLatestFrom(this.querySpace.query.values$())\n ).subscribe(([pagination, query]) => {\n if (this.wpListChecksumService.isQueryOutdated(query, pagination)) {\n this.wpListChecksumService.update(query, pagination);\n this.refresh(true, false);\n }\n });\n\n this.setupChangeObserver(this.wpTableFilters, true);\n this.setupChangeObserver(this.wpTableGroupBy);\n this.setupChangeObserver(this.wpTableSortBy);\n this.setupChangeObserver(this.wpTableSum);\n this.setupChangeObserver(this.wpTableTimeline);\n this.setupChangeObserver(this.wpTableHierarchies);\n this.setupChangeObserver(this.wpTableColumns);\n this.setupChangeObserver(this.wpTableHighlighting);\n this.setupChangeObserver(this.wpTableOrder);\n this.setupChangeObserver(this.wpDisplayRepresentation);\n }\n\n /**\n * Listen to changes in the given service and reload the query / results if\n * the service requests that.\n *\n * @param service Work package query state service to listento\n * @param firstPage If the service requests a change, load the first page\n */\n protected setupChangeObserver(service:WorkPackageQueryStateService, firstPage:boolean = false) {\n const queryState = this.querySpace.query;\n\n service\n .updates$()\n .pipe(\n this.untilDestroyed(),\n filter(() => queryState.hasValue() && service.hasChanged(queryState.value!))\n )\n .subscribe(() => {\n const newQuery = queryState.value!;\n const triggerUpdate = service.applyToQuery(newQuery);\n this.querySpace.query.putValue(newQuery);\n\n // Update the current checksum\n this.wpListChecksumService\n .updateIfDifferent(newQuery, this.wpTablePagination.current)\n .then(() => {\n // Update the page, if the change requires it\n if (triggerUpdate) {\n this.refresh(true, firstPage);\n }\n });\n });\n }\n\n public get projectIdentifier() {\n return this.currentProject.identifier || undefined;\n }\n\n /**\n * Setup the listener for members of the table to request a refresh of the entire table\n * through the refresh service.\n */\n protected setupRefreshObserver() {\n this.halEvents\n .aggregated$('WorkPackage')\n .pipe(\n this.untilDestroyed(),\n filter((events:HalEvent[]) => this.filterRefreshEvents(events))\n )\n .subscribe((events:HalEvent[]) => {\n this.refresh(false, false);\n });\n }\n\n\n /**\n * Refresh the set of results,\n * showing the loading indicator if visibly is set.\n *\n * @param A refresh request\n */\n public abstract refresh(visibly:boolean, firstPage:boolean):Promise;\n\n\n /**\n * Set the loading indicator for this set instance\n * @param promise\n */\n protected abstract set loadingIndicator(promise:Promise);\n\n /**\n * Filter the given work package events for something interesting\n * @param events HalEvent[]\n *\n * @return {boolean} whether any of these events should trigger the view reloading\n */\n protected filterRefreshEvents(events:HalEvent[]):boolean {\n let rendered = new Set(this.querySpace.renderedWorkPackageIds.getValueOr([]));\n\n for (let i = 0; i < events.length; i++) {\n const item = events[i];\n if (rendered.has(item.id) || item.eventType === 'created') {\n return true;\n }\n }\n\n return false;\n }\n\n protected setupQueryLoadedListener() {\n this\n .querySpace\n .initialized\n .values$()\n .pipe(\n take(1),\n filter(() => !this.componentDestroyed)\n )\n .subscribe(() => {\n this.queryLoaded = true;\n this.cdRef.detectChanges();\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ConfirmDialogModal, ConfirmDialogOptions} from \"core-components/modals/confirm-dialog/confirm-dialog.modal\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {Injectable, Injector} from \"@angular/core\";\n\n@Injectable()\nexport class ConfirmDialogService {\n\n constructor(readonly opModalService:OpModalService,\n readonly injector:Injector) {\n }\n\n /**\n * Confirm an action with an ng dialog with the given options\n */\n public confirm(options:ConfirmDialogOptions):Promise {\n return new Promise((resolve, reject) => {\n const confirmModal = this.opModalService.show(ConfirmDialogModal, this.injector, { options: options });\n confirmModal.closingEvent.subscribe((modal:ConfirmDialogModal) => {\n if (modal.confirmed) {\n resolve();\n } else {\n reject();\n }\n });\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n\nimport {ComponentType} from \"@angular/cdk/portal\";\nimport {ApplicationRef} from \"@angular/core\";\nimport {filter, take} from \"rxjs/operators\";\n\n/**\n * Optional bootstrap definition to allow selecting all matching\n * DOM nodes to manually bootstrap them.\n *\n * This differs from Angular's bootstrap module definition since it expects these\n * entries to be present on ALL pages. This is never the case for our optional\n * bootstrapped components.\n */\nexport interface OptionalBootstrapDefinition {\n // The DOM selector used to locate an optional node\n selector:string;\n // The component class tied to it.\n cls:ComponentType;\n // Whether the component may be embeddable in dynamically generated responses\n // e.g., previews\n embeddable?:boolean;\n}\n\n/**\n * Static lookup table for dynamically bootstrapped components within our application\n */\nexport class DynamicBootstrapper {\n private static optionalBoostrapComponents:OptionalBootstrapDefinition[] = [];\n\n /**\n * Register an optional bootstrap component to be dynamically bootstrapped\n * whenever it occurs in the initially loaded DOM.\n *\n * @param {OptionalBootstrapDefinition} definition\n */\n public static register(...defs:OptionalBootstrapDefinition[]) {\n this.optionalBoostrapComponents.push(...defs);\n }\n\n /**\n * Perform bootstrapping of matched elements within the given document.\n *\n * @param {ApplicationRef} appRef The application reference to lookup elements.\n * @param {Document} doc The document element\n * @param {OptionalBootstrapDefinition[]|undefined} definitions An optional set of components to bootstrap\n */\n public static bootstrapOptionalDocument(appRef:ApplicationRef, doc:Document, definitions = this.optionalBoostrapComponents) {\n this.performBootstrap(appRef, doc, false, definitions);\n }\n\n /**\n * Perform bootstrapping of embeddable elements within the given node.\n *\n * @param {ApplicationRef} appRef The application reference to lookup elements.\n * @param {HTMLElement} element A node to bootstrap elements within.\n * @param {OptionalBootstrapDefinition[]|undefined} definitions An optional set of components to bootstrap\n */\n public static bootstrapOptionalEmbeddable(appRef:ApplicationRef, element:HTMLElement, definitions = this.optionalBoostrapComponents) {\n // Delay the execution to avoid bootstrapping the embedded components while\n // the app is running the Change Detection. This was throwing \"ApplicationRef.tick\n // is called recursively\" error because of bootstrapOptionalEmbeddable and\n // bootstrapOptionalDocument were called too close (ie: ckEditor macros).\n Promise.resolve().then(() => this.performBootstrap(appRef, element, true, definitions));\n }\n\n /**\n * Get embeddable components\n */\n public static getEmbeddable() {\n return this.optionalBoostrapComponents.filter(el => el.embeddable);\n }\n\n /**\n * Bootstrap within a given document (globally, all components available) or within an element (embeddable compoennts\n * only).\n *\n * @param {ApplicationRef} appRef\n * @param {Document | HTMLElement} root\n * @param {boolean} embedded\n */\n private static performBootstrap(appRef:ApplicationRef, root:Document|HTMLElement, embedded:boolean, definitions:OptionalBootstrapDefinition[]) {\n definitions\n .forEach(el => {\n\n // Skip non-embeddable components in an embedded bootstrap.\n if (embedded && !el.embeddable) {\n return;\n }\n\n const elements = root.querySelectorAll(el.selector);\n for (let i = 0; i < elements.length; i++) {\n appRef.bootstrap(el.cls, elements[i]);\n }\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from '@angular/core';\nimport {WorkPackagesListChecksumService} from \"core-components/wp-list/wp-list-checksum.service\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {TransitionService} from \"@uirouter/core\";\nimport {Subject} from \"rxjs\";\n\n@Injectable()\nexport class QueryParamListenerService {\n readonly wpListChecksumService:WorkPackagesListChecksumService = this.injector.get(WorkPackagesListChecksumService);\n readonly wpListService:WorkPackagesListService = this.injector.get(WorkPackagesListService);\n readonly $transitions:TransitionService = this.injector.get(TransitionService);\n\n public observe$ = new Subject();\n public queryChangeListener:Function;\n\n constructor(readonly injector:Injector) {\n this.listenForQueryParamsChanged();\n }\n\n public listenForQueryParamsChanged():any {\n // Listen for param changes\n return this.queryChangeListener = this.$transitions.onSuccess({}, (transition):any => {\n let options = transition.options();\n const params = transition.params('to');\n\n let newChecksum = this.wpListService.getCurrentQueryProps(params);\n let newId:string = params.query_id ? params.query_id.toString() : null;\n\n // Avoid performing any changes when we're going to reload\n if (options.reload || (options.custom && options.custom.notify === false)) {\n return true;\n }\n\n return this.wpListChecksumService\n .executeIfOutdated(newId,\n newChecksum,\n () => {\n this.observe$.next(newChecksum);\n });\n });\n }\n\n public removeQueryChangeListener() {\n this.queryChangeListener();\n }\n}\n","import {derive, input, InputState, State, StatesGroup} from 'reactivestates';\nimport {Subject} from 'rxjs';\nimport {Injectable} from '@angular/core';\nimport {map} from 'rxjs/operators';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {GroupObject, WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {QueryColumn} from \"core-components/wp-query/query-column\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\n\n@Injectable()\nexport class IsolatedQuerySpace extends StatesGroup {\n\n constructor() {\n super();\n }\n\n name = 'IsolatedQuerySpace';\n\n // The query that results in this table state\n query:InputState = input();\n\n // the query form associated with the table\n queryForm = input();\n\n // the results associated with the table\n results = input();\n // all groups returned as results\n groups = input();\n // Set of columns in strict order of appearance\n columns = input();\n\n // Current state of collapsed groups (if any)\n collapsedGroups = input<{ [identifier:string]:boolean }>();\n\n // State to be updated when the table is up to date\n tableRendered = input();\n\n // Event to be raised when the timeline is up to date\n timelineRendered = new Subject();\n\n renderedWorkPackages:State = derive(this.tableRendered, $ => $.pipe(\n map(rows => rows.filter(row => !!row.workPackageId)))\n );\n\n renderedWorkPackageIds:State = derive(this.renderedWorkPackages, $ => $.pipe(\n map(rows => rows.map(row => row.workPackageId!.toString())))\n );\n\n // Subject used to unregister all listeners of states above.\n stopAllSubscriptions = new Subject();\n\n // Required work packages to be rendered by hierarchy mode + relation columns\n additionalRequiredWorkPackages = input();\n\n // Input state that emits whenever table services have initialized\n initialized = input();\n}\n","export enum keyCodes {\n BACKSPACE = 8,\n TAB = 9,\n ENTER = 13,\n SHIFT = 16,\n CTRL = 17,\n ALT = 18,\n PAUSE = 19,\n CAPS_LOCK = 20,\n ESCAPE = 27,\n SPACE = 32,\n PAGE_UP = 33,\n PAGE_DOWN = 34,\n END = 35,\n HOME = 36,\n LEFT_ARROW = 37,\n UP_ARROW = 38,\n RIGHT_ARROW = 39,\n DOWN_ARROW = 40,\n INSERT = 45,\n DELETE = 46,\n KEY_0 = 48,\n KEY_1 = 49,\n KEY_2 = 50,\n KEY_3 = 51,\n KEY_4 = 52,\n KEY_5 = 53,\n KEY_6 = 54,\n KEY_7 = 55,\n KEY_8 = 56,\n KEY_9 = 57,\n KEY_A = 65,\n KEY_B = 66,\n KEY_C = 67,\n KEY_D = 68,\n KEY_E = 69,\n KEY_F = 70,\n KEY_G = 71,\n KEY_H = 72,\n KEY_I = 73,\n KEY_J = 74,\n KEY_K = 75,\n KEY_L = 76,\n KEY_M = 77,\n KEY_N = 78,\n KEY_O = 79,\n KEY_P = 80,\n KEY_Q = 81,\n KEY_R = 82,\n KEY_S = 83,\n KEY_T = 84,\n KEY_U = 85,\n KEY_V = 86,\n KEY_W = 87,\n KEY_X = 88,\n KEY_Y = 89,\n KEY_Z = 90,\n LEFT_META = 91,\n RIGHT_META = 92,\n SELECT = 93,\n NUMPAD_0 = 96,\n NUMPAD_1 = 97,\n NUMPAD_2 = 98,\n NUMPAD_3 = 99,\n NUMPAD_4 = 100,\n NUMPAD_5 = 101,\n NUMPAD_6 = 102,\n NUMPAD_7 = 103,\n NUMPAD_8 = 104,\n NUMPAD_9 = 105,\n MULTIPLY = 106,\n ADD = 107,\n SUBTRACT = 109,\n DECIMAL = 110,\n DIVIDE = 111,\n F1 = 112,\n F2 = 113,\n F3 = 114,\n F4 = 115,\n F5 = 116,\n F6 = 117,\n F7 = 118,\n F8 = 119,\n F9 = 120,\n F10 = 121,\n F11 = 122,\n F12 = 123,\n NUM_LOCK = 144,\n SCROLL_LOCK = 145,\n SEMICOLON = 186,\n EQUALS = 187,\n COMMA = 188,\n DASH = 189,\n PERIOD = 190,\n FORWARD_SLASH = 191,\n GRAVE_ACCENT = 192,\n OPEN_BRACKET = 219,\n BACK_SLASH = 220,\n CLOSE_BRACKET = 221,\n SINGLE_QUOTE = 222\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\n\n@Injectable()\nexport class WorkPackageViewSumService extends WorkPackageQueryStateService {\n\n public constructor(querySpace:IsolatedQuerySpace) {\n super(querySpace);\n }\n\n public valueFromQuery(query:QueryResource) {\n return !!query.sums;\n }\n\n public initialize(query:QueryResource) {\n this.pristineState.putValue(!!query.sums);\n }\n\n public hasChanged(query:QueryResource) {\n return query.sums !== this.isEnabled;\n }\n\n public applyToQuery(query:QueryResource) {\n query.sums = this.isEnabled;\n return true;\n }\n\n public toggle() {\n this.updatesState.putValue(!this.current);\n }\n\n public setEnabled(value:boolean) {\n this.updatesState.putValue(value);\n }\n\n public get isEnabled() {\n return this.current;\n }\n\n public get current():boolean {\n return this.lastUpdatedState.getValueOr(false);\n }\n}\n","import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Inject, OnInit} from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {HalLink} from \"core-app/modules/hal/hal-link/hal-link\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport * as URI from 'urijs';\nimport {HttpClient, HttpErrorResponse} from '@angular/common/http';\nimport {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\nimport {Observable} from 'rxjs';\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {JobStatusModal} from \"core-app/modules/job-status/job-status-modal/job-status.modal\";\n\ninterface ExportLink extends HalLink {\n identifier:string;\n}\n\n/**\n Modal for exporting work packages to different formats. The user may choose from a variety of formats (e.g. PDF and CSV).\n The modal might also be used to only display the progress of an export. This will happen if a link for exporting is provided via the locals.\n */\n@Component({\n templateUrl: './wp-table-export.modal.html',\n styleUrls: ['./wp-table-export.modal.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WpTableExportModal extends OpModalComponent implements OnInit {\n\n /* Close on escape? */\n public closeOnEscape = true;\n\n /* Close on outside click */\n public closeOnOutsideClick = true;\n\n public $element:JQuery;\n public exportOptions:{ identifier:string, label:string, url:string }[];\n\n public text = {\n title: this.I18n.t('js.label_export'),\n closePopup: this.I18n.t('js.close_popup_title'),\n exportPreparing: this.I18n.t('js.label_export_preparing')\n };\n\n constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly I18n:I18nService,\n readonly elementRef:ElementRef,\n readonly querySpace:IsolatedQuerySpace,\n readonly cdRef:ChangeDetectorRef,\n readonly httpClient:HttpClient,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly notifications:NotificationsService) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n super.ngOnInit();\n\n if (this.locals.link) {\n this.requestExport(this.locals.link);\n } else {\n this.querySpace.results\n .valuesPromise()\n .then((results) => this.exportOptions = this.buildExportOptions(results!));\n }\n }\n\n private buildExportOptions(results:WorkPackageCollectionResource) {\n return results.representations.map(format => {\n const link = format.$link as ExportLink;\n\n return {\n identifier: link.identifier,\n label: link.title,\n url: this.addColumnsToHref(format.href!)\n };\n });\n }\n\n private triggerByLink(url:string, event:MouseEvent) {\n event.preventDefault();\n this.requestExport(url);\n }\n\n /**\n * Request the export link and return the job ID to observe\n *\n * @param url\n */\n private requestExport(url:string):void {\n this\n .httpClient\n .get(url, { observe: 'body', responseType: 'json' })\n .subscribe(\n (json:{ job_id:string }) => this.replaceWithJobModal(json.job_id),\n error => this.handleError(error)\n );\n\n }\n\n private replaceWithJobModal(jobId:string) {\n this.service.show(JobStatusModal, 'global', { jobId: jobId });\n }\n\n private handleError(error:HttpErrorResponse) {\n // There was an error but the status code is actually a 200.\n // If that is the case the response's content-type probably does not match\n // the expected type (json).\n // Currently this happens e.g. when exporting Atom which actually is not an export\n // but rather a feed to follow.\n if (error.status === 200 && error.url) {\n window.open(error.url);\n } else {\n this.showError(error);\n }\n }\n\n private showError(error:HttpErrorResponse) {\n this.notifications.addError(error.message || this.I18n.t('js.error.internal'));\n }\n\n private addColumnsToHref(href:string) {\n let columns = this.wpTableColumns.getColumns();\n\n let columnIds = columns.map(function (column) {\n return column.id;\n });\n\n let url = URI(href);\n // Remove current columns\n url.removeSearch('columns[]');\n url.addSearch('columns[]', columnIds);\n\n return url.toString();\n }\n\n protected get afterFocusOn():JQuery {\n return jQuery('#work-packages-settings-button');\n }\n}\n","
    \n
    \n
    \n

    \n\n \n \n \n \n
    \n\n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {Injectable} from '@angular/core';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {QuerySchemaResource} from 'core-app/modules/hal/resources/query-schema-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {combine, input, InputState} from 'reactivestates';\nimport {cloneHalResourceCollection} from 'core-app/modules/hal/helpers/hal-resource-builder';\nimport {QueryFilterResource} from \"core-app/modules/hal/resources/query-filter-resource\";\nimport {QueryFilterInstanceSchemaResource} from \"core-app/modules/hal/resources/query-filter-instance-schema-resource\";\nimport {States} from \"core-components/states.service\";\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {mapTo, take} from \"rxjs/operators\";\n\n@Injectable()\nexport class WorkPackageViewFiltersService extends WorkPackageQueryStateService {\n public hidden:string[] = [\n 'datesInterval',\n 'precedes',\n 'follows',\n 'relates',\n 'duplicates',\n 'duplicated',\n 'blocks',\n 'blocked',\n 'partof',\n 'includes',\n 'requires',\n 'required',\n 'search',\n // The filter should be named subjectOrId but for some reason\n // it is only named subjectOr\n 'subjectOrId',\n 'subjectOr',\n 'manualSort'\n ];\n\n /** Flag state to determine whether the filters are incomplete */\n private incomplete = input(false);\n\n constructor(protected readonly states:States,\n readonly querySpace:IsolatedQuerySpace) {\n super(querySpace);\n }\n\n /**\n * Load all schemas for the current filters and fill respective states\n * @param query\n * @param schema\n */\n public initializeFilters(query:QueryResource, schema:QuerySchemaResource) {\n let filters = cloneHalResourceCollection(query.filters);\n\n this.availableState.putValue(schema.filtersSchemas.elements);\n this.pristineState.putValue(filters);\n }\n\n /**\n * Return whether the filters are empty\n */\n public get isEmpty() {\n const value = this.lastUpdatedState.value;\n return !value || value.length === 0;\n }\n\n public get availableState():InputState {\n return this.states.queries.filters;\n }\n\n /** Return whether the filters the user is working on are incomplete */\n public get incomplete$() {\n return this.incomplete.values$();\n }\n\n\n /**\n * Add a filter instantiation from the set of available filter schemas\n *\n * @param filter\n */\n public add(filter:QueryFilterInstanceResource) {\n this.updatesState.putValue([...this.rawFilters, filter]);\n }\n\n /**\n * Replace a filter, or add a new one\n */\n public replace(id:string, modifier:(filter:QueryFilterInstanceResource) => void):void {\n let filter:QueryFilterInstanceResource = this.instantiate(id);\n\n let newFilters = [...this.rawFilters];\n modifier(filter);\n\n const index = this.findIndex(id);\n if (index === -1) {\n newFilters.push(filter);\n } else {\n newFilters.splice(index, 1, filter);\n }\n\n this.update(newFilters);\n }\n\n /**\n * Modify a live filter and push it to the state.\n * Avoids copying the resource.\n *\n * Returns whether the filter was found and modified\n */\n public modify(id:string, modifier:(filter:QueryFilterInstanceResource) => void):boolean {\n const index = this.findIndex(id);\n\n if (index === -1) {\n return false;\n }\n\n let filters = [...this.rawFilters];\n modifier(filters[index]!);\n this.update(filters);\n\n return true;\n }\n\n /**\n * Get an instantiated filter without adding it to the current state\n * @param filterOrId The query filter or id to instantiate\n */\n public instantiate(filterOrId:QueryFilterResource|string):QueryFilterInstanceResource {\n let id = (filterOrId instanceof QueryFilterResource) ? filterOrId.id : filterOrId;\n\n let schema = _.find(\n this.availableSchemas,\n schema => (schema.filter.allowedValues as HalResource)[0].id === id\n )!;\n\n return schema.getFilter();\n }\n\n /**\n * Remove one or more filters from the live state of filters.\n * @param filters Filters to be removed\n */\n public remove(...filters:(QueryFilterInstanceResource|string)[]) {\n let mapper = (f:QueryFilterInstanceResource|string) => (f instanceof QueryFilterInstanceResource) ? f.id : f;\n let set = new Set(filters.map(mapper));\n\n this.update(\n this.rawFilters.filter(f => !set.has(mapper(f)))\n );\n }\n\n /**\n * Return the remaining visible filters from the given filters set.\n * @param filters Array of active filters, defaults to the current live state.\n */\n public remainingVisibleFilters(filters = this.current) {\n return this\n .remainingFilters(filters)\n .filter((filter) => this.hidden.indexOf(filter.id) === -1);\n }\n\n /**\n * Return all available filter resources.\n * They need to be instantiated before using them in this service.\n */\n public get availableFilters():QueryFilterResource[] {\n return this.availableSchemas.map(schema => schema.allowedFilterValue);\n }\n\n private get availableSchemas():QueryFilterInstanceSchemaResource[] {\n return this.availableState.getValueOr([]);\n }\n\n /**\n * Determine whether all given filters are completely defined.\n * @param filters\n */\n public isComplete(filters:QueryFilterInstanceResource[]):boolean {\n return _.every(filters, filter => filter.isCompletelyDefined());\n }\n\n /**\n * Compare the current set of filters to the given query.\n * @param query\n */\n public hasChanged(query:QueryResource) {\n const comparer = (filter:HalResource[]) => filter.map(el => el.$source);\n\n return !_.isEqual(\n comparer(query.filters),\n comparer(this.rawFilters)\n );\n }\n\n public valueFromQuery(query:QueryResource) {\n return undefined;\n }\n\n update(value:QueryFilterInstanceResource[]) {\n super.update(value);\n this.incomplete.putValue(false);\n }\n\n /**\n * Returns the live filter instance for the given ID, or undefined\n * if it does not exist.\n *\n * @param id Identifier of the filter\n */\n public find(id:string):QueryFilterInstanceResource|undefined {\n const index = this.findIndex(id);\n\n if (index === -1) {\n return;\n }\n\n return this.rawFilters[index];\n }\n\n /**\n * Returns the index of the filter, or -1 if it does not exist\n * @param id Identifier of the filter\n */\n public findIndex(id:string):number {\n return _.findIndex(this.current, f => f.id === id);\n }\n\n public applyToQuery(query:QueryResource) {\n query.filters = this.cloneFilters();\n return true;\n }\n\n /**\n * Returns a shallow copy of the current filters.\n * Modifications to filters themselves will still\n */\n public get current():QueryFilterInstanceResource[] {\n return [...this.rawFilters];\n }\n\n /**\n * Returns a deep clone of the current filters set, may be used\n * to modify the filters without altering this state.\n */\n public cloneFilters() {\n return cloneHalResourceCollection(this.rawFilters);\n }\n\n /**\n * Returns the live state array, used for inspection of the filters\n * without modification.\n */\n protected get rawFilters():QueryFilterInstanceResource[] {\n return this.lastUpdatedState.value || [];\n }\n\n public get currentlyVisibleFilters() {\n const invisibleFilters = new Set(this.hidden);\n invisibleFilters.delete('search');\n\n return _.reject(this.currentFilterResources, (filter) => invisibleFilters.has(filter.id));\n }\n\n /**\n * Replace this filter state, but only if the given filters are complete\n * @param newState\n */\n public replaceIfComplete(newState:QueryFilterInstanceResource[]) {\n if (this.isComplete(newState)) {\n this.update(newState);\n } else {\n this.incomplete.putValue(true);\n }\n }\n\n /**\n * Filters service depends on two states\n */\n public onReady() {\n return combine(this.pristineState, this.availableState)\n .values$()\n .pipe(\n take(1),\n mapTo(null)\n )\n .toPromise();\n }\n\n /**\n * Get all filters that are not in the current active set\n */\n private remainingFilters(filters = this.rawFilters) {\n return _.differenceBy(this.availableFilters, filters, filter => filter.id);\n }\n\n /**\n * Map current filter instances to their FilterResource\n */\n private get currentFilterResources():QueryFilterResource[] {\n return this.rawFilters.map((filter:QueryFilterInstanceResource) => filter.filter);\n }\n\n isAvailable(el:QueryFilterInstanceResource):boolean {\n return !!this.availableFilters.find(available => available.id === el.id);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageViewColumnsService} from './wp-view-columns.service';\nimport {WorkPackageViewBaseService} from './wp-view-base.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageViewRelationColumns} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-relation-columns\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {RelationsStateValue, WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {Injectable} from \"@angular/core\";\nimport {\n QueryColumn,\n queryColumnTypes,\n RelationQueryColumn,\n TypeRelationQueryColumn\n} from \"core-components/wp-query/query-column\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport type RelationColumnType = 'toType'|'ofType';\n\n@Injectable()\nexport class WorkPackageViewRelationColumnsService extends WorkPackageViewBaseService {\n constructor(public querySpace:IsolatedQuerySpace,\n public wpTableColumns:WorkPackageViewColumnsService,\n public halResourceService:HalResourceService,\n public apiV3Service:APIV3Service,\n public wpRelations:WorkPackageRelationsService) {\n super(querySpace);\n }\n\n public valueFromQuery(query:QueryResource):WorkPackageViewRelationColumns {\n // Take over current expanded values\n // which are not yet saved\n return this.current;\n }\n\n /**\n * Returns a subset of all relations that the user has currently expanded.\n *\n * @param workPackage\n * @param relation\n */\n public relationsToExtendFor(workPackage:WorkPackageResource,\n relations:RelationsStateValue|undefined,\n eachCallback:(relation:RelationResource, column:QueryColumn, type:RelationColumnType) => void) {\n // Only if any relation columns or stored expansion state exist\n if (!(this.wpTableColumns.hasRelationColumns() && this.lastUpdatedState.hasValue())) {\n return;\n }\n\n // Only if any relations exist for this work package\n if (_.isNil(relations)) {\n return;\n }\n\n // Only if the work package has anything expanded\n const expanded = this.getExpandFor(workPackage.id!);\n if (expanded === undefined) {\n return;\n }\n\n const column = this.wpTableColumns.findById(expanded)!;\n const type = this.relationColumnType(column);\n\n if (type !== null) {\n _.each(this.relationsForColumn(workPackage, relations, column),\n (relation) => eachCallback(relation, column, type));\n }\n }\n\n /**\n * Get the subset of relations for the work package that belong to this relation column\n *\n * @param workPackage A work package resource\n * @param relations The RelationStateValue of this work package\n * @param column The relation column to filter for\n * @return The filtered relations\n */\n public relationsForColumn(workPackage:WorkPackageResource, relations:RelationsStateValue|undefined, column:QueryColumn) {\n if (_.isNil(relations)) {\n return [];\n }\n\n // Get the type of TO work package\n const type = this.relationColumnType(column);\n if (type === 'toType') {\n const typeHref = (column as TypeRelationQueryColumn).type.href;\n\n return _.filter(relations, (relation:RelationResource) => {\n const denormalized = relation.denormalized(workPackage);\n const target = this.apiV3Service.work_packages.cache.state(denormalized.targetId).value;\n\n return _.get(target, 'type.href') === typeHref;\n });\n }\n\n // Get the relation types for OF relation columns\n if (type === 'ofType') {\n const relationType = (column as RelationQueryColumn).relationType;\n\n return _.filter(relations, (relation:RelationResource) => {\n return relation.denormalized(workPackage).relationType === relationType;\n });\n }\n\n return [];\n }\n\n public relationColumnType(column:QueryColumn):RelationColumnType|null {\n switch (column._type) {\n case queryColumnTypes.RELATION_TO_TYPE:\n return 'toType';\n case queryColumnTypes.RELATION_OF_TYPE:\n return 'ofType';\n default:\n return null;\n }\n }\n\n public getExpandFor(workPackageId:string):string|undefined {\n return this.current[workPackageId];\n }\n\n public setExpandFor(workPackageId:string, columnId:string) {\n const nextState = { ...this.current };\n nextState[workPackageId] = columnId;\n\n this.update(nextState);\n }\n\n public collapse(workPackageId:string) {\n const nextState = { ...this.current };\n delete nextState[workPackageId];\n\n this.update(nextState);\n }\n\n public get current():WorkPackageViewRelationColumns {\n return this.lastUpdatedState.getValueOr({});\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector, OnDestroy} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Subject} from \"rxjs\";\nimport {ComponentType} from \"@angular/cdk/portal\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n@Injectable()\nexport class WorkPackageInlineCreateService implements OnDestroy {\n\n @InjectField() I18n!:I18nService;\n @InjectField() protected readonly authorisationService:AuthorisationService;\n\n constructor(readonly injector:Injector) {\n }\n\n /**\n * A separate reference pane for the inline create component\n */\n public readonly referenceComponentClass:ComponentType|null = null;\n\n /**\n * A related work package for the inline create context\n */\n public referenceTarget:WorkPackageResource|null = null;\n\n /**\n * Reference button text\n */\n public readonly buttonTexts = {\n reference: '',\n create: this.I18n.t('js.label_create_work_package'),\n };\n\n public get canAdd() {\n return this.canCreateWorkPackages || this.authorisationService.can('work_package', 'addChild');\n }\n\n public get canReference() {\n return false;\n }\n\n public get canCreateWorkPackages() {\n return this.authorisationService.can('work_packages', 'createWorkPackage') &&\n this.authorisationService.can('work_packages', 'editWorkPackage');\n }\n\n /** Allow callbacks to happen on newly created inline work packages */\n public newInlineWorkPackageCreated = new Subject();\n\n /** Allow callbacks to happen on newly created inline work packages */\n public newInlineWorkPackageReferenced = new Subject();\n\n /**\n * Ensure hierarchical injected versions of this service correctly unregister\n */\n ngOnDestroy() {\n this.newInlineWorkPackageCreated.complete();\n this.newInlineWorkPackageReferenced.complete();\n }\n}\n","import {QueryColumn} from \"core-components/wp-query/query-column\";\n\nexport const internalSortColumn = {\n id: '__internal-sorthandle'\n} as QueryColumn;\n\nexport const internalContextMenuColumn = {\n id: '__internal-contextMenu'\n} as QueryColumn;\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n// 'Global' dependencies\n//\n// dependencies required by classic (Rails) and Angular application.\n\n// Angular 4 deps. Must be loaded early!\n// require('reflect-metadata');\n// require('zone.js');\n// require('@angular/core');\n\n// ES6 Promise polyfill\nrequire('expose-loader?Promise!es6-promise');\n\n// Lodash\nrequire('expose-loader?_!lodash');\n\n// jQuery\nrequire('expose-loader?jQuery!jquery');\nrequire('jquery-ujs');\n\nrequire('expose-loader?mousetrap!mousetrap/mousetrap.js');\n\n// Angular dependencies\nrequire('expose-loader?dragula!dragula/dist/dragula.min.js');\nrequire('@uirouter/angular');\n\n// Jquery UI\nrequire('jquery-ui/ui/core.js');\nrequire('jquery-ui/ui/position.js');\nrequire('jquery-ui/ui/disable-selection.js');\nrequire('jquery-ui/ui/widgets/sortable.js');\nrequire('jquery-ui/ui/widgets/autocomplete.js');\nrequire('jquery-ui/ui/widgets/dialog.js');\nrequire('jquery-ui/ui/widgets/tooltip.js');\n\nrequire('expose-loader?moment!moment');\nrequire('moment/locale/en-gb.js');\nrequire('moment/locale/de.js');\n\nrequire('jquery.caret');\n// Text highlight for autocompleter\nrequire('mark.js/dist/jquery.mark.min.js');\n// Micro Text fuzzy search library\nrequire('fuse.js');\n\nrequire('moment-timezone/builds/moment-timezone-with-data.min.js');\n\nrequire('expose-loader?URI!urijs');\nrequire('urijs/src/URITemplate');\n\nrequire(\"expose-loader?I18n!core-vendor/i18n\");\n\n// Localization for fullcalendar\nrequire(\"@fullcalendar/core/locales-all\");\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ApplicationRef, ComponentFactoryResolver, ComponentRef, Injectable, Injector} from \"@angular/core\";\nimport {DynamicBootstrapper} from \"core-app/globals/dynamic-bootstrapper\";\n\n@Injectable()\nexport class CKEditorPreviewService {\n\n constructor(private readonly componentFactoryResolver:ComponentFactoryResolver,\n private readonly appRef:ApplicationRef,\n private readonly injector:Injector) {\n }\n\n /**\n * Render preview into the given element, return a remover function to disconnect all\n * dynamic components (if any).\n *\n * @param {HTMLElement} hostElement\n * @param {string} preview\n * @returns {() => void}\n */\n public render(hostElement:HTMLElement, preview:string):() => void {\n hostElement.innerHTML = preview;\n let refs:ComponentRef[] = [];\n\n DynamicBootstrapper\n .getEmbeddable()\n .forEach((entry) => {\n const matchedElements = hostElement.querySelectorAll(entry.selector);\n\n for (let i = 0, l = matchedElements.length; i < l; i++) {\n const factory = this.componentFactoryResolver.resolveComponentFactory(entry.cls);\n const componentRef = factory.create(this.injector, [], matchedElements[i]);\n\n refs.push(componentRef);\n this.appRef.attachView(componentRef.hostView);\n componentRef.changeDetectorRef.detectChanges();\n }\n });\n\n return () => {\n refs.forEach(ref => {\n this.appRef.detachView(ref.hostView);\n ref.destroy();\n });\n refs.length = 0;\n hostElement.innerHTML = '';\n };\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {\n SchemaAttributeObject,\n SchemaResource\n} from 'core-app/modules/hal/resources/schema-resource';\nimport {SchemaDependencyResource} from 'core-app/modules/hal/resources/schema-dependency-resource';\nimport {QueryOperatorResource} from 'core-app/modules/hal/resources/query-operator-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {HalLink} from \"core-app/modules/hal/hal-link/hal-link\";\n\nexport interface QueryFilterInstanceSchemaResourceLinks {\n self:HalLink;\n filter:QueryFilterResource;\n}\n\nexport class QueryFilterInstanceSchemaResource extends SchemaResource {\n\n public $links:QueryFilterInstanceSchemaResourceLinks;\n\n public operator:SchemaAttributeObject;\n public filter:SchemaAttributeObject;\n public dependency:SchemaDependencyResource;\n public values:SchemaAttributeObject|null;\n public type = 'QueryFilterInstanceSchema';\n\n public get availableOperators():HalResource[] | CollectionResource {\n return this.operator.allowedValues;\n }\n\n public get allowedFilterValue():QueryFilterResource {\n if (this.filter.allowedValues instanceof CollectionResource) {\n return this.filter.allowedValues.elements[0];\n }\n\n return this.filter.allowedValues[0];\n }\n\n public $initialize(source:any) {\n super.$initialize(source);\n\n if (source._dependencies) {\n this.dependency = new SchemaDependencyResource(this.injector, source._dependencies[0], true, this.halInitializer, 'SchemaDependency');\n }\n }\n\n public getFilter():QueryFilterInstanceResource {\n let operator = (this.operator.allowedValues as HalResource[])[0];\n let filter = (this.filter.allowedValues as HalResource[])[0];\n let source:any = {\n name: filter.name,\n _links: {\n filter: filter.$source._links.self,\n schema: this.$source._links.self,\n operator: operator.$source._links.self\n }\n };\n\n if (this.definesAllowedValues()) {\n source._links['values'] = [];\n } else {\n source['values'] = [];\n }\n\n return new QueryFilterInstanceResource(this.injector, source, true, this.halInitializer, 'QueryFilterInstance');\n }\n\n public isValueRequired():boolean {\n return !!(this.values);\n }\n\n public isResourceValue():boolean {\n return !!(this.values && this.values.allowedValues);\n }\n\n public resultingSchema(operator:QueryOperatorResource):QueryFilterInstanceSchemaResource {\n let staticSchema = this.$source;\n let dependentSchema = this.dependency.forValue(operator.href!.toString());\n let resultingSchema = {};\n\n _.merge(resultingSchema, staticSchema, dependentSchema);\n\n return new QueryFilterInstanceSchemaResource(this.injector, resultingSchema, true, this.halInitializer, 'QueryFilterInstanceSchema');\n }\n\n private definesAllowedValues() {\n return _.some(this._dependencies[0].dependencies,\n (dependency:any) => dependency.values && dependency.values._links && dependency.values._links.allowedValues);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpenprojectCommonModule} from 'core-app/modules/common/openproject-common.module';\nimport {OpenprojectFieldsModule} from 'core-app/modules/fields/openproject-fields.module';\nimport {NgModule} from '@angular/core';\nimport {OpenprojectHalModule} from \"core-app/modules/hal/openproject-hal.module\";\n\n\n@NgModule({\n imports: [\n // Commons\n OpenprojectCommonModule,\n\n OpenprojectHalModule,\n OpenprojectFieldsModule,\n ]\n})\nexport class OpenprojectProjectsModule {\n}\n","\nimport {debugLog} from '../../../helpers/debug_output';\nexport namespace ClickPositionMapper {\n\n /**\n * Try to set the position on the given input element.\n *\n * @param element The element to set the cursor to\n * @param offset The character offset retrieved from getPosition.\n */\n export function setPosition(element:HTMLInputElement, offset:number):void {\n try {\n element.setSelectionRange(offset, offset);\n } catch (e) {\n debugLog('Failed to set click position for edit field.', e);\n }\n }\n\n /**\n * Get the cursor offset from the click event.\n *\n * @param evt\n * @return {number}\n */\n export function getPosition(evt:any):number {\n const originalEvt = evt.originalEvent;\n\n try {\n if (document.caretRangeFromPoint) {\n return document\n .caretRangeFromPoint(evt.clientX!, evt.clientY!)\n .startOffset;\n } else if (originalEvt.rangeParent) {\n let range = document.createRange();\n range.setStart(originalEvt.rangeParent, originalEvt.rangeOffset);\n return range.startOffset;\n }\n\n return 0;\n } catch (e) {\n debugLog('Failed to get click position for edit field.', e);\n return 0;\n }\n }\n}\n","export type ChangeItem = {\n from:unknown;\n to:unknown;\n};\nexport type ChangeMap = { [attribute:string]:ChangeItem };\n\nexport class Changeset {\n private changes:ChangeMap = {};\n\n /**\n * Return whether a change value exist for the given attribute key.\n * @param {string} key\n * @return {boolean}\n */\n public contains(key:string) {\n return this.changes.hasOwnProperty(key);\n }\n\n /**\n * Get changed attribute names\n * @returns {string[]}\n */\n public get changed():string[] {\n return _.keys(this.changes);\n }\n\n /**\n * Returns the live set of the changes.\n */\n public get all():ChangeMap {\n return this.changes;\n }\n\n /**\n * Reset one or multiple changes\n * @param key\n */\n public reset(...keys:string[]) {\n keys.forEach((k) => {\n delete this.changes[k];\n });\n }\n\n /**\n * Reset the entire changeset\n */\n public clear():void {\n this.changes = {};\n }\n\n public set(key:string, value:unknown, pristineValue:unknown):void {\n this.changes[key] = {\n from: pristineValue,\n to: value\n };\n }\n\n /**\n * Get a change item for the given key, if any\n * @param key\n */\n public getItem(key:string):ChangeItem|undefined {\n return this.changes[key];\n }\n\n /**\n * Get a single value from the changeset\n * @param key\n */\n public getValue(key:string):unknown|undefined {\n return this.getItem(key)?.to;\n }\n\n /**\n * Get a single pristine value from the changeset\n * @param key\n */\n public getPristine(key:string):unknown|undefined {\n return this.changes[key]?.from;\n }\n}\n","import {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ChangeItem, ChangeMap, Changeset} from \"core-app/modules/fields/changeset/changeset\";\nimport {input, InputState} from \"reactivestates\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {take} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport { Injector } from '@angular/core';\nimport {SchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\n\nexport const PROXY_IDENTIFIER = '__is_changeset_proxy';\n\n/**\n * Temporary class living while a resource is being edited\n * Maintains references to:\n * - The source resource (a pristine base)\n * - The open set of changes (a changeset object)\n * - The current form (due to temporary type/project changes)\n *\n * Provides access to:\n * - The projected resource with all changes applied as properties\n */\nexport class ResourceChangeset {\n /** Maintain a single change set while editing */\n protected changeset = new Changeset();\n\n /** Reference and load promise for the current form */\n protected form$ = input();\n\n /** Request cache for objects within the changeset for the current form */\n protected cache:{ [key:string]:Promise } = {};\n\n /** Flag whether this is currently being saved */\n public inFlight = false;\n\n /** Keep a reference to the original resource */\n protected _pristineResource:T;\n\n /** The projected resource, which will proxy values from the changeset */\n public projectedResource:T;\n\n /** The cache to all the schemas. Used to maintain the schema of the projectedResource which does not stem from a form.\n * The schema of the form is kept inside the changeset.\n * */\n protected schemaCache:SchemaCacheService;\n\n constructor(pristineResource:T,\n public readonly state?:InputState>,\n loadedForm:FormResource|null = null) {\n this.updatePristineResource(pristineResource);\n\n this.schemaCache = (pristineResource.injector as Injector).get(SchemaCacheService);\n\n if (loadedForm) {\n this.form$.putValue(loadedForm);\n }\n }\n\n /**\n * Push the change to the editing state to notify others.\n * This will happen internally on resource wide changes\n */\n public push() {\n if (this.state) {\n this.state.putValue(this);\n }\n }\n\n /**\n * Build the request attributes against the fresh form\n */\n public buildRequestPayload():Promise {\n return this\n .getForm()\n .then(() => this.buildPayloadFromChanges());\n }\n\n /**\n * Update the pristine resource in case it changed\n *\n * @param attribute\n */\n public updatePristineResource(resource:T) {\n // Ensure we're not passing in a proxy\n if ((resource as any)[PROXY_IDENTIFIER]) {\n throw \"You're trying to pass proxy object as a pristine resource. This will cause errors\";\n }\n\n this._pristineResource = resource;\n this.projectedResource = new Proxy(\n this._pristineResource,\n {\n get: (_, key:string) => this.proxyGet(key),\n set: (_, key:string, val:any) => {\n this.setValue(key, val);\n return true;\n },\n }\n );\n }\n\n public get pristineResource():T {\n return this._pristineResource;\n }\n\n /**\n * Returns the cached form or loads it if necessary.\n */\n public getForm():Promise {\n if (this.form$.isPristine() && !this.form$.hasActivePromiseRequest()) {\n return this.updateForm();\n }\n\n return this\n .form$\n .values$()\n .pipe(take(1))\n .toPromise();\n }\n\n /**\n * Cache some promised value in the course of this changeset.\n * Will get cleared automatically by the changeset on destroy/submission\n */\n\n /**\n * Posts to the form with the current changes\n * to get the up to date projected object.\n */\n protected updateForm():Promise {\n let payload = this.buildPayloadFromChanges();\n\n const promise = this.pristineResource\n .$links\n .update(payload)\n .then((form:FormResource) => {\n this.cache = {};\n this.form$.putValue(form);\n this.setNewDefaults(form);\n this.push();\n return form;\n });\n\n this.form$.putFromPromiseIfPristine(() => promise);\n return promise;\n }\n\n /**\n * Return whether no changes were made to the work package\n */\n public isEmpty() {\n return this.changeset.changed.length === 0;\n }\n\n /**\n * Return the ID of the resource we're editing\n */\n public get id():string {\n return this.pristineResource.id!.toString();\n }\n\n /**\n * Return the HAL href of the resource we're editing\n */\n public get href():string {\n return this.pristineResource.href as string;\n }\n\n /**\n * Returns the changed `to` values of the ChangeMap\n */\n public get changes():{ [key:string]:unknown } {\n let changes:{ [key:string]:unknown } = {};\n\n _.each(this.changeset.all, (item, key) => {\n changes[key] = item.to;\n });\n\n return changes;\n }\n\n /**\n * Returns the change map with from and to values\n */\n public get changeMap():ChangeMap {\n return { ...this.changeset.all };\n }\n\n /**\n * Return the changed attributes in this change;\n */\n public get changedAttributes():string[] {\n return this.changeset.changed;\n }\n\n /**\n * Return whether the element is writable\n * given the current best schema.\n *\n * @param key\n */\n public isWritable(key:string):boolean {\n const fieldSchema = this.schema.ofProperty(key) as IFieldSchema|null;\n return !!(fieldSchema && fieldSchema.writable);\n }\n\n /**\n * Return the best humanized name for this attribute\n * @param attribute\n */\n public humanName(attribute:string):string {\n return _.get(this.schema, `${attribute}.name`, attribute);\n }\n\n /**\n * Returns whether the given attribute was changed\n */\n public contains(key:string) {\n return this.changeset.contains(key);\n }\n\n /**\n * Proxy getters to base or changeset.\n * @param key\n */\n private proxyGet(key:string) {\n if (key === '__is_proxy') {\n return true;\n }\n\n return this.value(key);\n }\n\n /**\n * Retrieve the editing value for the given attribute\n *\n * @param {string} key The attribute to read\n * @return {any} Either the value from the overriden change, or the default value\n */\n public value(key:string) {\n // Overridden value by user?\n if (this.changeset.contains(key)) {\n return this.changeset.getValue(key);\n }\n\n // Return whatever is on the base.\n return this.pristineResource[key];\n }\n\n /**\n * Return whether the given value exists,\n * even if its undefined.\n *\n * @param key\n */\n public valueExists(key:string):boolean {\n return this.changeset.contains(key) || this.pristineResource.hasOwnProperty(key);\n }\n\n /**\n * Change the value of the projected resource to some value\n *\n * @param key\n * @param val\n */\n public setValue(key:string, val:any) {\n this.changeset.set(key, val, this.pristineResource[key]);\n }\n\n /**\n * Clear the changed value of the projected resource\n *\n * @param keys A set of keys to reset\n */\n public clearValue(...keys:string[]) {\n this.changeset.reset(...keys);\n }\n\n public clear() {\n this.state && this.state.clear();\n this.changeset.clear();\n this.cache = {};\n this.form$.clear();\n }\n\n /**\n * Reset the given changed attribute\n * @param key\n */\n public reset(key:string) {\n this.changeset.reset(key);\n }\n\n /**\n * Return whether a change value exist for the given attribute key.\n * @param {string} key\n * @return {boolean}\n */\n public isOverridden(key:string) {\n return this.changes.hasOwnProperty(key);\n }\n\n /**\n * Get the best schema currently available, either the default resource schema (must exist).\n * If loaded, return the form schema, which provides better information on writable status\n * and contains available values.\n */\n public get schema():SchemaResource {\n if (this.form$.hasValue()) {\n return SchemaProxy.create(this.form$.value!.schema, this.projectedResource);\n } else {\n return this.schemaCache.of(this.pristineResource);\n }\n }\n\n /**\n * Access some promised value\n * that should be cached for the lifetime duration of the form.\n */\n public cacheValue(key:string, request:() => Promise):Promise {\n if (this.cache[key]) {\n return this.cache[key] as Promise;\n }\n\n return this.cache[key] = request();\n }\n\n protected get minimalPayload() {\n return { lockVersion: this.pristineResource.lockVersion, _links: {} };\n }\n\n /**\n * Merge the current changes into the payload resource.\n *\n * @param {plainPayload:unknown} A set of attributes to merge into the payload\n * @return {any}\n */\n protected applyChanges(plainPayload:any) {\n // Fall back to the last known state of the HalResource should the form not be loaded.\n let reference = this.pristineResource.$source;\n if (this.form$.value) {\n reference = this.form$.value.payload.$source;\n }\n\n _.each(this.changeset.all, (val:ChangeItem, key:string) => {\n if (!this.schema.isAttributeEditable(key)) {\n debugLog(`Trying to write ${key} but is not writable in schema`);\n return;\n }\n\n const fieldSchema:IFieldSchema|null = this.schema.ofProperty(key);\n // Override in _links if it is a linked property\n if (fieldSchema && reference._links[key]) {\n plainPayload._links[key] = this.getLinkedValue(val.to, fieldSchema);\n } else {\n plainPayload[key] = val.to;\n }\n });\n\n return plainPayload;\n }\n\n /**\n * Create the payload from the current changes, and extend it with the current lock version.\n * -- This is the place to add additional logic when the lockVersion changed in between --\n */\n protected buildPayloadFromChanges() {\n let payload;\n\n if (this.pristineResource.isNew) {\n // If the resource is new, we need to pass the entire form payload\n // to let all default values be transmitted (type, status, etc.)\n // We clone the object to avoid later manipulations to affect the original resource.\n if (this.form$.value) {\n payload = _.cloneDeep(this.form$.value.payload.$source);\n } else {\n payload = _.cloneDeep(this.pristineResource.$source);\n }\n\n // Add attachments to be assigned.\n // They will already be created on the server but now\n // we need to claim them for the newly created work package.\n if (this.pristineResource.attachments) {\n payload['_links']['attachments'] = this.pristineResource\n .attachments\n .elements\n .map((a:HalResource) => {\n return { href: a.href };\n });\n }\n\n } else {\n // Otherwise, simply use the bare minimum\n payload = this.minimalPayload;\n }\n\n return this.applyChanges(payload);\n }\n\n /**\n * Extract the link(s) in the given changed value\n */\n protected getLinkedValue(val:any, fieldSchema:IFieldSchema) {\n // Links should always be nullified as { href: null }, but\n // this wasn't always the case, so ensure null values are returned as such.\n if (_.isNil(val)) {\n return { href: null };\n }\n\n // Test if we either have a CollectionResource or a HAL array,\n // or a single hal value.\n let isArrayType = (fieldSchema.type || '').startsWith('[]');\n let isArray = false;\n\n if (val.forEach || val.elements) {\n isArray = true;\n }\n\n if (isArray && isArrayType) {\n let links:{ href:string }[] = [];\n\n if (val) {\n let elements = (val.forEach && val) || val.elements;\n\n elements.forEach((link:{ href:string }) => {\n if (link.href) {\n links.push({ href: link.href });\n }\n });\n }\n\n return links;\n } else {\n return { href: _.get(val, 'href', null) };\n }\n }\n\n /**\n * When changing type or project, new custom fields may be present\n * that we need to set.\n */\n protected setNewDefaults(form:FormResource) {\n _.each(form.payload, (val:unknown, key:string) => {\n const fieldSchema:IFieldSchema|null = this.schema.ofProperty(key);\n if (!fieldSchema?.writable) {\n return;\n }\n\n this.setNewDefaultFor(key, val);\n });\n }\n\n /**\n * Set the default for the given attribute\n */\n protected setNewDefaultFor(key:string, val:unknown) {\n if (!this.valueExists(key)) {\n debugLog(\"Taking over default value from form for \" + key);\n this.setValue(key, val);\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\n\nexport class HalPayloadHelper {\n\n /**\n * Extract payload from the given request with schema.\n * This will ensure we will only write writable attributes and so on.\n *\n * @param resource\n * @param schema\n */\n static extractPayload(resource:T|Object|null, schema:SchemaResource|null = null):Object {\n if (resource instanceof HalResource && schema) {\n return this.extractPayloadFromSchema(resource, schema);\n } else if (resource && !(resource instanceof HalResource)) {\n return resource;\n } else {\n return {};\n }\n }\n\n /**\n * Extract writable payload from a HAL resource class to be used for API calls.\n *\n * The schema contains writable information about attributes, which is what this method\n * iterates in order to build the HAL-compatible object.\n *\n * @param resource A HalResource to extract payload from\n * @param schema The associated schema to determine writable state of attributes\n */\n static extractPayloadFromSchema(resource:T, schema:SchemaResource) {\n let payload:any = {\n '_links': {}\n };\n\n let nonLinkProperties = [];\n\n for (let key in schema) {\n if (schema.hasOwnProperty(key) && schema[key] && schema[key].writable) {\n if (resource.$links[key]) {\n if (Array.isArray(resource[key])) {\n payload['_links'][key] = _.map(resource[key], element => {\n return { href: (element as HalResource).$href };\n });\n } else {\n payload['_links'][key] = {\n href: (resource[key] && resource[key].$href)\n };\n }\n } else {\n nonLinkProperties.push(key);\n }\n }\n }\n\n _.each(nonLinkProperties, property => {\n if (resource.hasOwnProperty(property) || resource[property]) {\n if (Array.isArray(resource[property])) {\n payload[property] = _.map(resource[property], (element:any) => {\n if (element instanceof HalResource) {\n return this.extractPayloadFromSchema(element, element.currentSchema || element.schema);\n } else {\n return element;\n }\n });\n } else {\n payload[property] = resource[property];\n }\n }\n });\n\n return payload;\n }\n}\n","/**\n * A PortalOutlet that lets multiple components live for the lifetime of the outlet,\n * allowing faster switching and persistent data.\n */\nimport {ComponentPortal} from '@angular/cdk/portal';\nimport {\n ApplicationRef,\n ComponentFactoryResolver,\n ComponentRef,\n EmbeddedViewRef,\n Injector\n} from '@angular/core';\n\nexport interface TabInterface {\n name:string;\n title:string;\n disableBecause?:string;\n componentClass:{ new(...args:any[]):TabComponent };\n}\n\nexport interface TabComponent {\n onSave:() => void;\n}\n\nexport interface ActiveTabInterface {\n name:string;\n portal:ComponentPortal;\n componentRef:ComponentRef;\n dispose:() => void;\n}\n\nexport class TabPortalOutlet {\n\n // Active tabs that have been instantiated\n public activeTabs:{ [name:string]:ActiveTabInterface } = {};\n\n // The current tab\n public currentTab:ActiveTabInterface|null = null;\n\n constructor(\n public availableTabs:TabInterface[],\n public outletElement:HTMLElement,\n private componentFactoryResolver:ComponentFactoryResolver,\n private appRef:ApplicationRef,\n private injector:Injector) {\n }\n\n public get activeComponents():TabComponent[] {\n const tabs = _.values(this.activeTabs);\n return tabs.map((tab:ActiveTabInterface) => tab.componentRef.instance);\n }\n\n public switchTo(name:string) {\n const tab = _.find(this.availableTabs, tab => tab.name === name);\n\n if (!tab) {\n throw(`Trying to switch to unknown tab ${name}.`);\n }\n\n if (tab.disableBecause != null) {\n return false;\n }\n\n // Detach any current instance\n this.detach();\n\n // Get existing or new component instance\n const instance = this.activateInstance(tab);\n\n // At this point the component has been instantiated, so we move it to the location in the DOM\n // where we want it to be rendered.\n this.outletElement.innerHTML = '';\n this.outletElement.appendChild(this._getComponentRootNode(instance.componentRef));\n this.outletElement.dataset.tabName = tab.title;\n this.currentTab = instance;\n\n return false;\n }\n\n public detach():void {\n const current = this.currentTab;\n if (current !== null) {\n current.portal.setAttachedHost(null);\n this.currentTab = null;\n }\n }\n\n /**\n * Clears out a portal from the DOM.\n */\n dispose():void {\n // Dispose all active tabs\n _.each(this.activeTabs, active => active.dispose());\n\n // Remove outlet element\n if (this.outletElement.parentNode != null) {\n this.outletElement.parentNode.removeChild(this.outletElement);\n }\n }\n\n private activateInstance(tab:TabInterface):ActiveTabInterface {\n if (!this.activeTabs[tab.name]) {\n this.activeTabs[tab.name] = this.createComponent(tab);\n }\n\n return this.activeTabs[tab.name] || null;\n }\n\n private createComponent(tab:TabInterface):ActiveTabInterface {\n const componentFactory = this.componentFactoryResolver.resolveComponentFactory(tab.componentClass);\n const componentRef = componentFactory.create(this.injector);\n const portal = new ComponentPortal(tab.componentClass, null, this.injector);\n\n // Attach component view\n this.appRef.attachView(componentRef.hostView);\n\n return {\n name: tab.name,\n portal: portal,\n componentRef: componentRef,\n dispose: () => {\n this.appRef.detachView(componentRef.hostView);\n componentRef.destroy();\n }\n };\n }\n\n /** Gets the root HTMLElement for an instantiated component. */\n private _getComponentRootNode(componentRef:ComponentRef):HTMLElement {\n return (componentRef.hostView as EmbeddedViewRef).rootNodes[0] as HTMLElement;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Directive, ElementRef, Injector} from '@angular/core';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {OpTableActionsService} from \"core-components/wp-table/table-actions/table-actions.service\";\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {WorkPackageViewPaginationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageViewSumService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service\";\nimport {WorkPackageViewAdditionalElementsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-additional-elements.service\";\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {WorkPackageCreateService} from \"core-components/wp-new/wp-create.service\";\nimport {WorkPackageStatesInitializationService} from \"core-components/wp-list/wp-states-initialization.service\";\nimport {WorkPackageViewFocusService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {WorkPackageService} from \"core-components/work-packages/work-package.service\";\nimport {WorkPackageRelationsHierarchyService} from \"core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service\";\nimport {WorkPackageFiltersService} from \"core-components/filters/wp-filters/wp-filters.service\";\nimport {WorkPackageContextMenuHelperService} from \"core-components/wp-table/context-menu-helper/wp-context-menu-helper.service\";\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WpChildrenInlineCreateService} from \"core-components/wp-relations/embedded/children/wp-children-inline-create.service\";\nimport {WpRelationInlineCreateService} from \"core-components/wp-relations/embedded/relations/wp-relation-inline-create.service\";\nimport {WorkPackagesListChecksumService} from \"core-components/wp-list/wp-list-checksum.service\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {TableDragActionsRegistryService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-actions-registry.service\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {CausedUpdatesService} from \"core-app/modules/boards/board/caused-updates/caused-updates.service\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {WorkPackageViewDisplayRepresentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageViewHierarchyIdentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy-indentation.service\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {TimeEntryCreateService} from \"core-app/modules/time_entries/create/create.service\";\nimport {WorkPackageViewCollapsedGroupsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service\";\n\n/**\n * Directive to open a work package query 'space', an isolated injector hierarchy\n * that provides access to query-bound data and services, especially around the querySpace services.\n *\n * If you add services that depend on a table state, they should be provided here, not globally\n * in a module.\n */\n@Directive({\n selector: '[wp-isolated-query-space]',\n providers: [\n // Override the hal notification service\n { provide: HalResourceNotificationService, useExisting: WorkPackageNotificationService },\n\n // Open the isolated space first, order is important here\n IsolatedQuerySpace,\n OpTableActionsService,\n\n // Work package table services\n WorkPackagesListChecksumService,\n WorkPackagesListService,\n WorkPackageViewRelationColumnsService,\n WorkPackageViewPaginationService,\n WorkPackageViewGroupByService,\n WorkPackageViewCollapsedGroupsService,\n WorkPackageViewHierarchiesService,\n WorkPackageViewSortByService,\n WorkPackageViewColumnsService,\n WorkPackageViewFiltersService,\n WorkPackageViewTimelineService,\n WorkPackageViewSelectionService,\n WorkPackageViewSumService,\n WorkPackageViewAdditionalElementsService,\n WorkPackageViewFocusService,\n WorkPackageViewHighlightingService,\n WorkPackageViewDisplayRepresentationService,\n WorkPackageViewOrderService,\n WorkPackageViewHierarchyIdentationService,\n CausedUpdatesService,\n\n WorkPackageService,\n WorkPackageRelationsHierarchyService,\n WorkPackageFiltersService,\n WorkPackageContextMenuHelperService,\n\n // Provide a separate service for creation events of WP Inline create\n // This can be hierarchically injected to provide isolated events on an embedded table\n WorkPackageInlineCreateService,\n WpChildrenInlineCreateService,\n WpRelationInlineCreateService,\n\n WorkPackageCardViewService,\n\n HalResourceEditingService,\n TimeEntryCreateService,\n WorkPackageCreateService,\n\n WorkPackageStatesInitializationService,\n\n // Table Drag & Drop actions\n TableDragActionsRegistryService,\n ]\n})\nexport class WorkPackageIsolatedQuerySpaceDirective {\n\n constructor(private elementRef:ElementRef,\n public querySpace:IsolatedQuerySpace,\n private injector:Injector) {\n debugLog(\"Opening isolated query space %O in %O\", injector, elementRef.nativeElement);\n }\n}\n","import {\n HttpEvent,\n HttpInterceptor,\n HttpHandler,\n HttpRequest,\n} from '@angular/common/http';\nimport {Observable} from 'rxjs';\nimport { Injectable } from \"@angular/core\";\n\n@Injectable()\nexport class OpenProjectHeaderInterceptor implements HttpInterceptor {\n intercept(req:HttpRequest, next:HttpHandler):Observable> {\n const csrf_token:string|undefined = jQuery('meta[name=csrf-token]').attr('content');\n\n if (req.withCredentials !== false) {\n\n let newHeaders = req.headers\n .set('X-Authentication-Scheme', 'Session')\n .set('X-Requested-With', 'XMLHttpRequest');\n\n if (csrf_token) {\n newHeaders = newHeaders.set('X-CSRF-TOKEN', csrf_token);\n }\n\n // Clone the request to add the new header\n const clonedRequest = req.clone({\n withCredentials: true,\n headers: newHeaders\n });\n\n // Pass the cloned request instead of the original request to the next handle\n return next.handle(clonedRequest);\n }\n\n return next.handle(req);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {MultiInputState, State} from 'reactivestates';\nimport {Observable} from \"rxjs\";\nimport {auditTime, map, share, startWith, take} from \"rxjs/operators\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\n\nexport interface HasId {\n id:string|null;\n}\n\nexport class StateCacheService {\n protected cacheDurationInMs:number;\n protected multiState:MultiInputState;\n\n constructor(state:MultiInputState, holdValuesForSeconds:number = 3600) {\n this.multiState = state;\n this.cacheDurationInMs = holdValuesForSeconds * 1000;\n }\n\n public state(id:string):State {\n return this.multiState.get(id);\n }\n\n /**\n * Touch the current state to fire subscribers.\n */\n public touch(id:string):void {\n const state = this.multiState.get(id);\n state.putValue(state.value, 'Touching the state');\n }\n\n /**\n * Get the current value\n */\n public current(id:string, fallback?:T):T|undefined {\n return this.state(id).getValueOr(fallback);\n }\n\n /**\n * Sets a promise to the state\n */\n public clearAndLoad(id:string, loader:Observable):Observable {\n const observable =\n loader\n .pipe(\n take(1),\n share()\n );\n\n this\n .multiState.get(id)\n .clearAndPutFromPromise(observable.toPromise());\n\n return observable;\n }\n\n /**\n * Update the value due to application changes.\n *\n * @param id The value's identifier.\n * @param val The value.\n *\n * @return a promise of the value when it was inserted into cache\n */\n public updateValue(id:string, val:T):Promise {\n this.putValue(id, val);\n return Promise.resolve(val);\n }\n\n /**\n * Update the value due to application changes.\n *\n * @param resource The value.\n */\n public updateFor(resource:HasId):Promise {\n return this.updateValue(resource.id!, resource as any);\n }\n\n\n /**\n * Observe the value of the given id\n */\n public observe(id:string):Observable {\n return this.state(id).values$();\n }\n\n /**\n * Observe the changes of the given id\n */\n public changes$(id:string):Observable {\n return this.state(id).changes$();\n }\n\n /**\n * Observe the entire set of loaded results\n */\n public observeAll():Observable {\n return this.multiState\n .observeChange()\n .pipe(\n startWith([]),\n auditTime(250),\n map(() => {\n let mapped:T[] = [];\n _.each(this.multiState.getValueOr({}), (state:State) => {\n if (state.value) {\n mapped.push(state.value);\n }\n });\n\n return mapped;\n })\n );\n }\n\n /**\n * Clear a set of cached states.\n * @param ids\n */\n public clearSome(...ids:string[]) {\n ids.forEach(id => this.multiState.get(id).clear());\n }\n\n /**\n * Returns whether the state\n * @param id ID of the state\n * @return {boolean}\n */\n public stale(id:string):boolean {\n const state = this.multiState.get(id);\n\n // If there is an active request that is still pending\n if (state.hasActivePromiseRequest()) {\n return false;\n }\n\n return state.isPristine() || state.isValueOlderThan(this.cacheDurationInMs);\n }\n\n /**\n * Actually insert the value in the state right now.\n *\n * @param id\n * @param val\n */\n protected putValue(id:string, val:T) {\n this.multiState.get(id).putValue(val);\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, OnInit, OnDestroy} from '@angular/core';\n\n@Component({\n selector: 'col[highlight-col]',\n template: ''\n})\n\nexport class HighlightColDirective implements OnInit, OnDestroy {\n private $element:JQuery;\n private thead:JQuery;\n\n constructor(private elementRef:ElementRef) {\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n this.thead = this.$element\n .parent('colgroup')\n .siblings('thead');\n\n // Separate handling instead of toggle is necessary to avoid\n // unwanted side effects when adding/removing columns via keyboard in the modal\n this.thead.on('mouseenter', 'th', (evt:JQuery.TriggeredEvent) => {\n if (this.$element.index() === jQuery(evt.currentTarget).index()) {\n this.$element.addClass('hover');\n }\n });\n\n this.thead.on('mouseleave', 'th', (evt:JQuery.TriggeredEvent) => {\n if (this.$element.index() === jQuery(evt.currentTarget).index()) {\n this.$element.removeClass('hover');\n }\n });\n }\n\n ngOnDestroy() {\n this.thead.off('mouseenter mouseleave');\n }\n}\n\nexport const highlightColBootstrap = {\n selector: 'col[highlight-col]',\n cls: HighlightColDirective\n};\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, EventEmitter, Injector, Input, OnInit, Output, ViewChild} from '@angular/core';\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {ApiV3FilterBuilder, FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {Observable} from \"rxjs\";\nimport {map} from \"rxjs/operators\";\nimport {DebouncedRequestSwitchmap, errorNotificationHandler} from \"core-app/helpers/rxjs/debounced-input-switchmap\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const usersAutocompleterSelector = 'user-autocompleter';\n\n@Component({\n templateUrl: './user-autocompleter.component.html',\n selector: usersAutocompleterSelector\n})\nexport class UserAutocompleterComponent implements OnInit {\n userTracker = (item:any) => item.href || item.id;\n\n @ViewChild(NgSelectComponent, { static: true }) public ngSelectComponent:NgSelectComponent;\n @Output() public onChange = new EventEmitter();\n @Input() public clearAfterSelection:boolean = false;\n\n // Load all users as default\n @Input() public url:string = this.apiV3Service.users.path;\n @Input() public allowEmpty:boolean = false;\n @Input() public appendTo:string = '';\n @Input() public multiple:boolean = false;\n\n @Input() public initialSelection:number|null = null;\n\n // Update an input field after changing, used when externally loaded\n private updateInputField:HTMLInputElement|undefined;\n\n /** Keep a switchmap for search term and loading state */\n public requests = new DebouncedRequestSwitchmap(\n (searchTerm:string) => this.getAvailableUsers(this.url, searchTerm),\n errorNotificationHandler(this.halNotification)\n );\n\n public inputFilters:ApiV3FilterBuilder = new ApiV3FilterBuilder();\n\n constructor(protected elementRef:ElementRef,\n protected halResourceService:HalResourceService,\n protected I18n:I18nService,\n protected halNotification:HalResourceNotificationService,\n readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly injector:Injector) {\n }\n\n ngOnInit() {\n const input = this.elementRef.nativeElement.dataset['updateInput'];\n const allowEmpty = this.elementRef.nativeElement.dataset['allowEmpty'];\n const appendTo = this.elementRef.nativeElement.dataset['appendTo'];\n const multiple = this.elementRef.nativeElement.dataset['multiple'];\n const url = this.elementRef.nativeElement.dataset['url'];\n\n if (input) {\n this.updateInputField = document.getElementsByName(input)[0] as HTMLInputElement|undefined;\n this.setInitialSelection();\n }\n\n let filterInput = this.elementRef.nativeElement.dataset['additionalFilter'];\n if (filterInput) {\n JSON.parse(filterInput).forEach((filter:{selector:string; operator:FilterOperator, values:string[]}) => {\n this.inputFilters.add(filter['selector'], filter['operator'], filter['values']);\n });\n }\n\n if (allowEmpty === 'true') {\n this.allowEmpty = true;\n }\n\n if (appendTo) {\n this.appendTo = appendTo;\n }\n\n if (multiple === 'true') {\n this.multiple = true;\n }\n\n if (url) {\n this.url = url;\n }\n }\n\n public onFocus() {\n if (!this.requests.lastRequestedValue) {\n this.requests.input$.next('');\n }\n }\n\n public onModelChange(user:any) {\n if (user) {\n this.onChange.emit(user);\n this.requests.input$.next('');\n\n if (this.clearAfterSelection) {\n this.ngSelectComponent.clearItem(user);\n }\n\n if (this.updateInputField) {\n if (this.multiple) {\n this.updateInputField.value = user.map((u:UserResource) => u.id);\n } else {\n this.updateInputField.value = user.id;\n }\n }\n }\n }\n\n protected getAvailableUsers(url:string, searchTerm:any):Observable<{[key:string]:string|null}[]> {\n // Need to clone the filters to not add additional filters on every\n // search term being processed.\n let searchFilters = this.inputFilters.clone();\n\n if (searchTerm && searchTerm.length) {\n searchFilters.add('name', '~', [searchTerm]);\n }\n\n return this.halResourceService\n .get(url, { filters: searchFilters.toJson() })\n .pipe(\n map(res => {\n let options = res.elements.map((el:any) => {\n return {name: el.name, id: el.id, href: el.href, avatar: el.avatar};\n });\n\n if (this.allowEmpty) {\n options.unshift({name: this.I18n.t('js.timelines.filter.noneSelection'), href: null, id: null});\n }\n\n return options;\n })\n );\n }\n\n private setInitialSelection() {\n if (this.updateInputField) {\n const id = parseInt(this.updateInputField.value);\n this.initialSelection = isNaN(id) ? null : id;\n }\n }\n}\n\n","\n \n \n \n {{ item.name }}\n \n","import {\n ApplicationRef,\n ComponentFactoryResolver,\n ComponentRef,\n Injectable,\n InjectionToken,\n Injector\n} from '@angular/core';\nimport {ComponentPortal, ComponentType, DomPortalOutlet, PortalInjector} from '@angular/cdk/portal';\nimport {TransitionService} from '@uirouter/core';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {FocusHelperService} from 'core-app/modules/common/focus/focus-helper';\n\nexport const OpModalLocalsToken = new InjectionToken('OP_MODAL_LOCALS');\n\n@Injectable({ providedIn: 'root' })\nexport class OpModalService {\n public active:OpModalComponent|null = null;\n\n // Hold a reference to the DOM node we're using as a host\n private portalHostElement:HTMLElement;\n // And a reference to the actual portal host interface on top of the element\n private bodyPortalHost:DomPortalOutlet;\n\n // Remember when we're opening a new modal to avoid the outside click bubbling up.\n private opening:boolean = false;\n\n constructor(private componentFactoryResolver:ComponentFactoryResolver,\n readonly FocusHelper:FocusHelperService,\n private appRef:ApplicationRef,\n private $transitions:TransitionService,\n private injector:Injector) {\n\n const hostElement = this.portalHostElement = document.createElement('div');\n hostElement.classList.add('op-modals--overlay');\n document.body.appendChild(hostElement);\n\n // Listen to keyups on window to close context menus\n jQuery(window).on('keydown', (evt:JQuery.TriggeredEvent) => {\n if (this.active && this.active.closeOnEscape && evt.which === keyCodes.ESCAPE) {\n this.active.closeOnEscapeFunction(evt);\n }\n\n return true;\n });\n\n // Listen to any click when should close outside modal\n jQuery(window).on('click', (evt:JQuery.TriggeredEvent) => {\n if (this.active &&\n !this.opening &&\n this.active.closeOnOutsideClick &&\n this.activeModal[0] === evt.target as Element) {\n this.close();\n }\n });\n\n this.bodyPortalHost = new DomPortalOutlet(\n hostElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n }\n\n /**\n * Open a Modal reference and append it to the portal\n *\n * @param modal The modal component class to show\n * @param injector The injector to pass into the component. Ensure this is the hierarchical injector if needed.\n * Can be passed 'global' to take the default (global!) injector of this service.\n * @param locals A map to be injected via token into the component.\n */\n public show(modal:ComponentType, injector:Injector|'global', locals:any = {}):T {\n this.close();\n\n // Prevent closing events during the opening time frame.\n this.opening = true;\n\n // Allow users to pass the global injector when deliberately requested.\n if (injector === 'global') {\n injector = this.injector;\n }\n\n // Create a portal for the given component class and render it\n const portal = new ComponentPortal(modal, null, this.injectorFor(injector, locals));\n const ref:ComponentRef = this.bodyPortalHost.attach(portal) as ComponentRef;\n const instance = ref.instance as T;\n this.active = instance;\n this.portalHostElement.style.display = 'block';\n\n setTimeout(() => {\n // Focus on the first element\n this.active && this.active.onOpen(this.activeModal);\n\n // Mark that we've opened the modal now\n this.opening = false;\n }, 20);\n\n jQuery('.op-modal--modal-container').focus();\n\n return this.active as T;\n }\n\n public isActive(modal:OpModalComponent) {\n return this.active && this.active === modal;\n }\n\n /**\n * Closes currently open modal window\n */\n public close() {\n // Detach any component currently in the portal\n if (this.active && this.active.onClose()) {\n this.active.closingEvent.emit(this.active);\n this.bodyPortalHost.detach();\n this.portalHostElement.style.display = 'none';\n this.active = null;\n }\n }\n\n public get activeModal():JQuery {\n return jQuery(this.portalHostElement).find('.op-modal--portal');\n }\n\n /**\n * Create an augmented injector that is equal to this service's injector + the additional data\n * passed into +show+.\n * This allows callers to pass data into the newly created modal.\n *\n */\n private injectorFor(injector:Injector, data:any) {\n const injectorTokens = new WeakMap();\n // Pass the service because otherwise we're getting a cyclic dependency between the portal\n // host service and the bound portal\n data.service = this;\n\n injectorTokens.set(OpModalLocalsToken, data);\n\n return new PortalInjector(injector, injectorTokens);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {Injector} from '@angular/core';\nimport {FocusHelperService} from 'core-app/modules/common/focus/focus-helper';\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {ClickPositionMapper} from \"core-app/modules/common/set-click-position/set-click-position\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {Subject} from 'rxjs';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {EditForm} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HalResourceEditFieldHandler extends EditFieldHandler {\n // Injections\n @InjectField() FocusHelper:FocusHelperService;\n @InjectField() ConfigurationService:ConfigurationService;\n @InjectField() I18n!:I18nService;\n\n // Subject to fire when user demanded activation\n public $onUserActivate = new Subject();\n\n // Current errors of the field\n public errors:string[];\n\n constructor(public injector:Injector,\n public form:EditForm,\n public fieldName:string,\n public schema:IFieldSchema,\n public element:HTMLElement,\n protected pathHelper:PathHelperService,\n protected withErrors?:string[]) {\n\n super();\n\n if (withErrors !== undefined) {\n this.setErrors(withErrors);\n }\n\n this.htmlId = `wp-${this.resource.id}-inline-edit--field-${this.fieldName}`;\n this.fieldLabel = this.schema.name || this.fieldName;\n }\n\n /**\n * Stop this event from propagating out of the edit field context.\n */\n public stopPropagation(evt:JQuery.TriggeredEvent) {\n evt.stopPropagation();\n return false;\n }\n\n public get inEditMode() {\n return this.form.editMode;\n }\n\n public get inFlight() {\n return this.form.change.inFlight;\n }\n\n public focus(setClickOffset?:number) {\n const target = this.element.querySelector('.inline-edit--field') as HTMLElement;\n\n if (!target) {\n debugLog(`Tried to focus on ${this.fieldName}, but element does not (yet) exist.`);\n return;\n }\n\n // Focus the input\n target.focus();\n\n // Set selection state if input element\n if (setClickOffset && target.tagName === 'INPUT') {\n ClickPositionMapper.setPosition(target as HTMLInputElement, setClickOffset);\n }\n }\n\n public onFocusOut() {\n // In case of inline create or erroneous forms: do not save on focus loss\n // const specialField = this.resource.shouldCloseOnFocusOut(this.fieldName);\n if (this.resource.subject && this.withErrors && this.withErrors!.length === 0) {\n this.handleUserSubmit();\n }\n }\n\n public setErrors(newErrors:string[]) {\n this.errors = newErrors;\n this.element.classList.toggle('-error', this.isErrorenous);\n }\n\n /**\n * Handle a user submitting the field (e.g, ng-change)\n */\n public handleUserSubmit():Promise {\n this.onBeforeSubmit();\n\n if (this.inFlight || this.form.editMode) {\n return Promise.resolve();\n }\n\n return this\n .onSubmit()\n .then(() => this.form.submit());\n }\n\n /**\n * Handle users pressing enter inside an edit mode.\n * Outside an edit mode, the regular save event is captured by handleUserSubmit (submit event).\n * In an edit mode, we can't derive from a submit event wheteher the user pressed enter\n * (and on what field he did that).\n */\n public handleUserKeydown(event:JQuery.TriggeredEvent, onlyCancel:boolean = false) {\n // Only handle submission in edit mode\n if (this.inEditMode && !onlyCancel) {\n if (event.which === keyCodes.ENTER) {\n this.form.submit();\n return false;\n }\n return true;\n }\n\n // Escape editing when not in edit mode\n if (event.which === keyCodes.ESCAPE) {\n this.handleUserCancel();\n return false;\n }\n\n // If enter is pressed here, it will continue to handleUserSubmit()\n // due to the form submission event.\n return true;\n }\n\n /**\n * Cancel edit\n */\n public handleUserCancel() {\n this.reset();\n }\n\n /**\n * Cancel any pending changes\n */\n public reset() {\n this.form.change.reset(this.fieldName);\n this.deactivate(true);\n }\n\n /**\n * Close the field, resetting it with its display value.\n */\n public deactivate(focus:boolean = false) {\n delete this.form.activeFields[this.fieldName];\n this.onDestroy.next();\n this.onDestroy.complete();\n this.form.reset(this.fieldName, focus);\n }\n\n /**\n * Returns whether the field has any errors set.\n */\n public get isErrorenous():boolean {\n return this.errors.length > 0;\n }\n\n /**\n * Returns whether the field has been changed\n */\n public isChanged():boolean {\n return this.form.change.contains(this.fieldName);\n }\n\n /**\n * Reference the form's resource\n */\n public get resource():HalResource {\n return this.form.resource;\n }\n\n /**\n * Reference the current set project\n */\n public get project() {\n return this.form.change.projectedResource.project;\n }\n\n public errorMessageOnLabel() {\n if (!this.isErrorenous) {\n return '';\n } else {\n return this.I18n.t('js.inplace.errors.messages_on_field',\n {messages: this.errors.join(' ')});\n }\n }\n\n public previewContext(resource:HalResource) {\n return resource.previewPath();\n }\n}\n","/**\n * A CDK portal implementation to wrap edit-fields in non-angular contexts.\n */\nimport {ApplicationRef, ComponentFactoryResolver, Injectable, Injector} from \"@angular/core\";\nimport {ComponentPortal, DomPortalOutlet} from \"@angular/cdk/portal\";\nimport {EditFormPortalComponent} from \"core-app/modules/fields/edit/editing-portal/edit-form-portal.component\";\nimport {createLocalInjector} from \"core-app/modules/fields/edit/editing-portal/edit-form-portal.injector\";\nimport {take} from \"rxjs/operators\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {EditForm} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {HalResourceEditFieldHandler} from \"core-app/modules/fields/edit/field-handler/hal-resource-edit-field-handler\";\n\n@Injectable({ providedIn: 'root' })\nexport class EditingPortalService {\n\n constructor(private readonly appRef:ApplicationRef,\n private readonly componentFactoryResolver:ComponentFactoryResolver,\n private readonly pathHelper:PathHelperService) {\n\n }\n\n public create(container:HTMLElement,\n injector:Injector,\n form:EditForm,\n schema:IFieldSchema,\n fieldName:string,\n errors:string[]):Promise {\n\n // Create the portal outlet\n const outlet = this.createDomOutlet(container, injector);\n\n // Create a field handler for the newly active field\n const fieldHandler = new HalResourceEditFieldHandler(\n injector,\n form,\n fieldName,\n schema,\n container,\n this.pathHelper,\n errors\n );\n\n fieldHandler\n .onDestroy\n .pipe(take(1))\n // Don't call .dispose() on the outlet, it destroys the DOM element\n .subscribe(() => outlet.detach());\n\n // Create an injector that contains injectable reference to the edit field and handler\n const localInjector = createLocalInjector(injector, form.change, fieldHandler, schema);\n\n // Create a portal for the edit-form/field\n const portal = new ComponentPortal(EditFormPortalComponent, null, localInjector);\n\n // Clear the container\n container.innerHTML = '';\n\n // Attach the portal to the outlet\n const ref = outlet.attachComponentPortal(portal);\n\n // Wait until the content is initialized\n return ref\n .instance\n .onEditFieldReady\n .pipe(\n take(1)\n )\n .toPromise()\n .then(() => fieldHandler);\n }\n\n /**\n * Creates a dom outlet for attaching the portal.\n *\n * @param {HTMLElement} hostElement The element where the portal will be attached into\n * @returns {DomPortalOutlet}\n */\n private createDomOutlet(hostElement:HTMLElement, injector:Injector) {\n return new DomPortalOutlet(\n hostElement,\n this.componentFactoryResolver,\n this.appRef,\n injector\n );\n }\n}\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from '@angular/core';\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {AbstractFieldService, IFieldType} from \"core-app/modules/fields/field.service\";\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\n\nexport interface IDisplayFieldType extends IFieldType {\n new(resource:HalResource, attributeType:string, schema:IFieldSchema, context:DisplayFieldContext):DisplayField;\n}\n\nexport interface DisplayFieldContext {\n /** The injector to use for the context of this field. Relevant for embedded service injection */\n injector:Injector;\n\n /** Where will the field be rendered? This may result in different styles (Multi select field, e.g.,) */\n container:'table'|'single-view'|'timeline';\n\n /** Options passed to the display field */\n options:{ [key:string]:any };\n}\n\n@Injectable({ providedIn: 'root' })\nexport class DisplayFieldService extends AbstractFieldService {\n\n /**\n * Create an instance of the field type T given the required arguments\n * with either in descending order:\n *\n * 1. The registered field name (most specific)\n * 2. The registered field for the schema attribute type\n * 3. The default field type\n *\n * @param resource\n * @param {string} fieldName\n * @param {IFieldSchema} schema\n * @param {string} context\n * @returns {T}\n */\n public getField(resource:HalResource, fieldName:string, schema:IFieldSchema, context:DisplayFieldContext):DisplayField {\n const fieldClass = this.getSpecificClassFor(resource._type, fieldName, schema.type);\n let instance = new fieldClass(fieldName, context);\n instance.apply(resource, schema);\n return instance;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {States} from 'core-components/states.service';\nimport {Injectable} from '@angular/core';\nimport {cloneHalResourceCollection} from 'core-app/modules/hal/helpers/hal-resource-builder';\nimport {QueryColumn, queryColumnTypes} from \"core-components/wp-query/query-column\";\nimport {combine} from \"reactivestates\";\nimport {mapTo, take} from \"rxjs/operators\";\n\n@Injectable()\nexport class WorkPackageViewColumnsService extends WorkPackageQueryStateService {\n\n public constructor(readonly states:States, readonly querySpace:IsolatedQuerySpace) {\n super(querySpace);\n }\n\n public initialize(query:any, results:any, schema?:any) {\n super.initialize(query, results, schema);\n }\n\n public valueFromQuery(query:QueryResource):QueryColumn[] {\n return [...query.columns];\n }\n\n public hasChanged(query:QueryResource) {\n return !this.isCurrentlyEqualTo(query.columns);\n }\n\n public isCurrentlyEqualTo(a:QueryColumn[]) {\n const comparer = (columns:QueryColumn[]) => columns.map(c => c.href);\n\n return _.isEqual(\n comparer(a),\n comparer(this.getColumns())\n );\n }\n\n public applyToQuery(query:QueryResource) {\n const toApply = this.getColumns();\n\n const oldColumns = query.columns.map(el => el.id);\n const newColumns = toApply.map(el => el.id);\n query.columns = cloneHalResourceCollection(toApply);\n\n // We can avoid reloading even with relation columns if we only removed columns\n const onlyRemoved = _.difference(newColumns, oldColumns).length === 0;\n\n // Reload the table visibly if adding relation columns.\n return !onlyRemoved && this.hasRelationColumns();\n }\n\n /**\n * Returns whether the current set of columns include relations\n */\n public hasRelationColumns() {\n const relationColumns = [queryColumnTypes.RELATION_OF_TYPE, queryColumnTypes.RELATION_TO_TYPE];\n return !!_.find(this.getColumns(), (c) => relationColumns.indexOf(c._type) >= 0);\n }\n\n /**\n * Retrieve the QueryColumn objects for the selected columns.\n * Returns a shallow copy with the original column objects.\n */\n public getColumns():QueryColumn[] {\n return [ ...this.current ];\n }\n\n /**\n * Return the index of the given column or -1 if it is not contained.\n */\n public index(id:string):number {\n return _.findIndex(this.getColumns(), column => column.id === id);\n }\n\n /**\n * Return the column object for the given id.\n * @param id\n */\n public findById(id:string):QueryColumn|undefined {\n return _.find(this.getColumns(), column => column.id === id);\n }\n\n /**\n * Return the previous column of the given column name\n * @param column\n */\n public previous(column:QueryColumn):QueryColumn|null {\n let index = this.index(column.id);\n\n if (index <= 0) {\n return null;\n }\n\n return this.getColumns()[index - 1];\n }\n\n /**\n * Return the next column of the given column name\n * @param column\n */\n public next(column:QueryColumn):QueryColumn|null {\n let index = this.index(column.id);\n\n if (index === -1 || this.isLast(name)) {\n return null;\n }\n\n return this.getColumns()[index + 1];\n }\n\n /**\n * Returns true if the column is the first selected\n */\n public isFirst(column:QueryColumn):boolean {\n return this.index(column.id) === 0;\n }\n\n /**\n * Returns true if the column is the last selected\n */\n public isLast(column:QueryColumn):boolean {\n return this.index(column.id) === this.columnCount - 1;\n }\n\n /**\n * Update the selected columns to a new set of columns.\n */\n public setColumns(columns:QueryColumn[]) {\n // Don't publish if this is the same content\n if (this.isCurrentlyEqualTo(columns)) {\n return;\n }\n\n this.update(columns);\n }\n\n public setColumnsById(columnIds:string[]) {\n const mapped = columnIds.map(id => _.find(this.all, c => c.id === id));\n this.setColumns(_.compact(mapped));\n }\n\n /**\n * Move the column at index {fromIndex} to {toIndex}.\n * - If toIndex is larger than all columns, insert at the end.\n * - If toIndex is less than zero, insert at the start.\n */\n public moveColumn(fromIndex:number, toIndex:number) {\n let columns = this.getColumns();\n\n if (toIndex >= columns.length) {\n toIndex = columns.length - 1;\n }\n\n if (toIndex < 0) {\n toIndex = 0;\n }\n\n let element = columns[fromIndex];\n columns.splice(fromIndex, 1);\n columns.splice(toIndex, 0, element);\n\n this.setColumns(columns);\n }\n\n /**\n * Shift the given column name X indices,\n * where X is the offset in indices (-1 = shift one to left)\n */\n public shift(column:QueryColumn, offset:number) {\n let index = this.index(column.id);\n if (index === -1) {\n return;\n }\n\n this.moveColumn(index, index + offset);\n }\n\n /**\n * Add a new column to the selection at the given position\n */\n public addColumn(id:string, position?:number) {\n let columns = this.getColumns();\n\n if (position === undefined) {\n position = columns.length;\n }\n\n if (this.index(id) === -1) {\n let newColumn = _.find(this.all, (column) => column.id === id);\n\n if (!newColumn) {\n throw \"Column with provided name is not found\";\n }\n\n columns.splice(position, 0, newColumn);\n this.setColumns(columns);\n }\n }\n\n /**\n * Remove a column from the active list\n */\n public removeColumn(column:QueryColumn) {\n let index = this.index(column.id);\n\n if (index !== -1) {\n let columns = this.getColumns();\n columns.splice(index, 1);\n this.setColumns(columns);\n }\n }\n\n // only exists to cast the state\n protected get current() {\n return this.lastUpdatedState.getValueOr([]);\n }\n\n // Get the available state\n protected get availableState() {\n return this.states.queries.columns;\n }\n\n /**\n * Return the number of selected rows.\n */\n public get columnCount():number {\n return this.getColumns().length;\n }\n\n /**\n * Get all available columns (regardless of whether they are selected already)\n */\n public get all():QueryColumn[] {\n return this.availableState.getValueOr([]);\n }\n\n public get allPropertyColumns():QueryColumn[] {\n return this\n .all\n .filter((column:QueryColumn) => column._type === queryColumnTypes.PROPERTY);\n }\n\n /**\n * Get columns not yet selected\n */\n public get unused():QueryColumn[] {\n return _.differenceBy(this.all, this.getColumns(), '$href');\n }\n\n /**\n * Columns service depends on two states\n */\n public onReady() {\n return combine(this.pristineState, this.availableState)\n .values$()\n .pipe(\n take(1),\n mapTo(null)\n )\n .toPromise();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\n\nclass Apiv3Paths {\n readonly apiV3Base:string;\n\n constructor(basePath:string) {\n this.apiV3Base = basePath + '/api/v3';\n }\n\n /**\n * Preview markup path\n *\n * Primarily used from ckeditor\n * https://github.com/opf/commonmark-ckeditor-build/\n *\n * @param context\n */\n public previewMarkup(context:string) {\n let base = `${this.apiV3Base}/render/markdown`;\n\n if (context) {\n return `${base}?context=${context}`;\n } else {\n return base;\n }\n }\n\n /**\n * Principals autocompleter path\n *\n * Primarily used from ckeditor\n * https://github.com/opf/commonmark-ckeditor-build/\n *\n */\n public principals(projectId:string|number, term:string|null) {\n let filters:ApiV3FilterBuilder = new ApiV3FilterBuilder();\n // Only real and activated users:\n filters.add('status', '!', ['3']);\n // that are members of that project:\n filters.add('member', '=', [projectId.toString()]);\n // That are users:\n filters.add('type', '=', ['User', 'Group']);\n // That are not the current user:\n filters.add('id', '!', ['me']);\n\n if (term && term.length > 0) {\n // Containing the that substring:\n filters.add('name', '~', [term]);\n }\n\n return this.apiV3Base +\n '/principals?' +\n filters.toParams({ sortBy: '[[\"name\",\"asc\"]]', offset: '1', pageSize: '10' });\n }\n}\n\n@Injectable({ providedIn: 'root' })\nexport class PathHelperService {\n public readonly appBasePath = window.appBasePath || '';\n public readonly api = {\n v3: new Apiv3Paths(this.appBasePath)\n };\n\n public get staticBase() {\n return this.appBasePath;\n }\n\n public attachmentDownloadPath(attachmentIdentifier:string, slug:string|undefined) {\n let path = `${this.staticBase}/attachments/${attachmentIdentifier}`;\n\n if (slug) {\n return `${path}/${slug}`;\n } else {\n return path;\n }\n }\n\n public attachmentContentPath(attachmentIdentifier:number|string) {\n return `${this.staticBase}/attachments/${attachmentIdentifier}/content`;\n }\n\n public ifcModelsPath(projectIdentifier:string) {\n return `${this.staticBase}/projects/${projectIdentifier}/ifc_models`;\n }\n\n public bimDetailsPath(projectIdentifier:string, workPackageId:string, viewpoint:number|string|null = null) {\n let path = `${this.projectPath(projectIdentifier)}/bcf/split/details/${workPackageId}`;\n\n if (viewpoint !== null) {\n path += `?viewpoint=${viewpoint}`;\n }\n\n return path;\n }\n\n public highlightingCssPath() {\n return `${this.staticBase}/highlighting/styles`;\n }\n\n public forumPath(projectIdentifier:string, forumIdentifier:string) {\n return `${this.projectForumPath(projectIdentifier)}/${forumIdentifier}`;\n }\n\n public keyboardShortcutsHelpPath() {\n return `${this.staticBase}/help/keyboard_shortcuts`;\n }\n\n public messagePath(messageIdentifier:string) {\n return `${this.staticBase}/topics/${messageIdentifier}`;\n }\n\n public myPagePath() {\n return `${this.staticBase}/my/page`;\n }\n\n public newsPath(newsId:string) {\n return `${this.staticBase}/news/${newsId}`;\n }\n\n public loginPath() {\n return `${this.staticBase}/login`;\n }\n\n public projectsPath() {\n return `${this.staticBase}/projects`;\n }\n\n public projectPath(projectIdentifier:string) {\n return `${this.projectsPath()}/${projectIdentifier}`;\n }\n\n public projectActivityPath(projectIdentifier:string) {\n return `${this.projectPath(projectIdentifier)}/activity`;\n }\n\n public projectForumPath(projectIdentifier:string) {\n return `${this.projectPath(projectIdentifier)}/forums`;\n }\n\n public projectCalendarPath(projectId:string) {\n return `${this.projectPath(projectId)}/work_packages/calendar`;\n }\n\n public projectMembershipsPath(projectId:string) {\n return `${this.projectPath(projectId)}/members`;\n }\n\n public projectNewsPath(projectId:string) {\n return `${this.projectPath(projectId)}/news`;\n }\n\n public projectTimeEntriesPath(projectIdentifier:string) {\n return `${this.projectPath(projectIdentifier)}/cost_reports`;\n }\n\n public projectWikiPath(projectId:string) {\n return `${this.projectPath(projectId)}/wiki`;\n }\n\n public projectWorkPackagePath(projectId:string, wpId:string|number) {\n return `${this.projectWorkPackagesPath(projectId)}/${wpId}`;\n }\n\n public projectWorkPackagesPath(projectId:string) {\n return `${this.projectPath(projectId)}/work_packages`;\n }\n\n public projectWorkPackageNewPath(projectId:string) {\n return `${this.projectWorkPackagesPath(projectId)}/new`;\n }\n\n public projectBoardsPath(projectIdentifier:string|null) {\n if (projectIdentifier) {\n return `${this.projectPath(projectIdentifier)}/boards`;\n } else {\n return `${this.staticBase}/boards`;\n }\n }\n\n public projectDashboardsPath(projectIdentifier:string) {\n return `${this.projectPath(projectIdentifier)}/dashboards`;\n }\n\n public timeEntriesPath(workPackageId:string|number) {\n let suffix = '/time_entries';\n\n if (workPackageId) {\n return this.workPackagePath(workPackageId) + suffix;\n } else {\n return this.staticBase + suffix; // time entries root path\n }\n }\n\n public usersPath() {\n return `${this.staticBase}/users`;\n }\n\n public groupsPath() {\n return `${this.staticBase}/groups`;\n }\n\n public placeholderUsersPath() {\n return `${this.staticBase}/placeholder_users`;\n }\n\n public userPath(id:string|number) {\n return `${this.usersPath()}/${id}`;\n }\n\n public placeholderUserPath(id:string|number) {\n return `${this.placeholderUsersPath()}/${id}`;\n }\n\n public groupPath(id:string|number) {\n return `${this.groupsPath()}/${id}`;\n }\n\n public versionsPath() {\n return `${this.staticBase}/versions`;\n }\n\n public versionEditPath(id:string|number) {\n return `${this.staticBase}/versions/${id}/edit`;\n }\n\n public versionShowPath(id:string|number) {\n return `${this.staticBase}/versions/${id}`;\n }\n\n public workPackagesPath() {\n return `${this.staticBase}/work_packages`;\n }\n\n public workPackagePath(id:string|number) {\n return `${this.staticBase}/work_packages/${id}`;\n }\n\n public workPackageCopyPath(workPackageId:string|number) {\n return `${this.workPackagePath(workPackageId)}/copy`;\n }\n\n public workPackageDetailsCopyPath(projectIdentifier:string, workPackageId:string|number) {\n return `${this.projectWorkPackagesPath(projectIdentifier)}/details/${workPackageId}/copy`;\n }\n\n public workPackagesBulkDeletePath() {\n return `${this.workPackagesPath()}/bulk`;\n }\n\n public projectLevelListPath() {\n return `${this.projectsPath()}/level_list.json`;\n }\n\n public textFormattingHelp() {\n return `${this.staticBase}/help/text_formatting`;\n }\n}\n","import {Injectable} from '@angular/core';\n\n@Injectable({ providedIn: 'root' })\nexport class DeviceService {\n\n public mobileWidthTreshold:number = 680;\n\n public get isMobile():boolean {\n return (window.innerWidth < this.mobileWidthTreshold);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {StateService} from '@uirouter/core';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {Directive, ElementRef, Input} from \"@angular/core\";\nimport {OpContextMenuTrigger} from \"core-components/op-context-menu/handlers/op-context-menu-trigger.directive\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Directive({\n selector: '[wpStatusDropdown]'\n})\nexport class WorkPackageStatusDropdownDirective extends OpContextMenuTrigger {\n @Input('wpStatusDropdown-workPackage') public workPackage:WorkPackageResource;\n\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly $state:StateService,\n protected workPackageNotificationService:WorkPackageNotificationService,\n protected halEditing:HalResourceEditingService,\n protected notificationService:NotificationsService,\n protected I18n:I18nService,\n protected halEvents:HalEventsService) {\n\n super(elementRef, opContextMenu);\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n const change = this.halEditing.changeFor(this.workPackage);\n\n change.getForm().then((form:any) => {\n const statuses = form.schema.status.allowedValues;\n this.buildItems(statuses);\n\n const writable = change.schema.status.writable;\n if (!writable) {\n this.notificationService.addError(this.I18n.t('js.work_packages.message_work_package_status_blocked'));\n } else {\n this.opContextMenu.show(this, evt);\n }\n });\n }\n\n public get locals() {\n return {\n items: this.items,\n contextMenuId: 'wp-status-context-menu'\n };\n }\n\n private updateStatus(status:HalResource) {\n const change = this.halEditing.changeFor(this.workPackage);\n change.projectedResource.status = status;\n\n if (!this.workPackage.isNew) {\n this.halEditing\n .save(change)\n .then(() => {\n this.workPackageNotificationService.showSave(this.workPackage);\n });\n }\n }\n\n private buildItems(statuses:CollectionResource) {\n this.items = statuses.map((status:HalResource) => {\n return {\n disabled: false,\n linkText: status.name,\n postIcon: status.isReadonly ? 'icon-locked' : null,\n postIconTitle: this.I18n.t('js.work_packages.message_work_package_read_only'),\n class: Highlighting.inlineClass('status', status.id!),\n onClick: () => {\n this.updateStatus(status);\n return true;\n }\n };\n });\n }\n}\n\n","
    \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {ISchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\n\n@Component({\n selector: 'wp-status-button',\n styleUrls: ['./wp-status-button.component.sass'],\n templateUrl: './wp-status-button.html'\n})\nexport class WorkPackageStatusButtonComponent extends UntilDestroyedMixin implements OnInit {\n @Input('workPackage') public workPackage:WorkPackageResource;\n @Input('containerClass') public containerClass:string;\n\n public text = {\n explanation: this.I18n.t('js.label_edit_status'),\n workPackageReadOnly: this.I18n.t('js.work_packages.message_work_package_read_only'),\n workPackageStatusBlocked: this.I18n.t('js.work_packages.message_work_package_status_blocked')\n };\n\n constructor(readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly schemaCache:SchemaCacheService,\n readonly halEditing:HalResourceEditingService) {\n super();\n }\n\n ngOnInit() {\n this.halEditing\n .temporaryEditResource(this.workPackage)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp) => {\n this.workPackage = wp;\n\n if (this.workPackage.status) {\n this.workPackage.status.$load();\n }\n\n this.cdRef.detectChanges();\n });\n }\n\n public get buttonTitle() {\n if (this.schema.isReadonly) {\n return this.text.workPackageReadOnly;\n } else if (this.schema.isEditable && !this.allowed) {\n return this.text.workPackageStatusBlocked;\n } else {\n return '';\n }\n }\n\n public get statusHighlightClass() {\n let status = this.status;\n if (!status) {\n return;\n }\n return Highlighting.backgroundClass('status', status.id!);\n }\n\n public get status():HalResource {\n return this.workPackage.status;\n }\n\n public get isReadonly() {\n return this.schema.isReadonly;\n }\n\n public get allowed() {\n return this.schema.isAttributeEditable('status');\n }\n\n private get schema() {\n if (this.halEditing.typedState(this.workPackage).hasValue()) {\n return this.halEditing.typedState(this.workPackage).value!.schema;\n } else {\n return this.schemaCache.of(this.workPackage) as ISchemaProxy;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ResourcesDisplayField} from \"./resources-display-field.module\";\nimport {cssClassCustomOption} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class MultipleLinesCustomOptionsDisplayField extends ResourcesDisplayField {\n\n public render(element:HTMLElement, displayText:string):void {\n const values = this.value;\n element.setAttribute('title', displayText);\n element.textContent = displayText;\n\n element.innerHTML = '';\n\n if (values.length === 0) {\n this.renderEmpty(element);\n } else {\n this.renderValues(values, element);\n }\n }\n\n protected renderValues(values:string[], element:HTMLElement) {\n values.forEach((value) => {\n const div = document.createElement('div');\n div.classList.add(cssClassCustomOption, '-multiple-lines');\n div.setAttribute('title', value);\n div.textContent = value;\n\n element.appendChild(div);\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ProgressDisplayField} from './progress-display-field.module';\n\nexport class ProgressTextDisplayField extends ProgressDisplayField {\n public render(element:HTMLElement, displayText:string):void {\n const label = this.percentLabel;\n element.setAttribute('title', label);\n element.innerHTML = '';\n element.textContent = label;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ResourcesDisplayField} from \"./resources-display-field.module\";\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {UserAvatarRendererService} from \"core-components/user/user-avatar/user-avatar-renderer.service\";\n\nexport class MultipleLinesUserFieldModule extends ResourcesDisplayField {\n @InjectField() avatarRenderer:UserAvatarRendererService;\n\n public render(element:HTMLElement, displayText:string):void {\n const values = this.attribute;\n element.setAttribute('title', displayText);\n element.textContent = displayText;\n\n element.innerHTML = '';\n\n if (values.length === 0) {\n this.renderEmpty(element);\n } else {\n this.renderValues(values, element);\n }\n }\n\n protected renderValues(values:UserResource[], element:HTMLElement) {\n this.avatarRenderer.renderMultiple(element, values, true, true);\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {DisplayFieldContext, DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {MultipleLinesCustomOptionsDisplayField} from \"core-app/modules/fields/display/field-types/multiple-lines-custom-options-display-field.module\";\nimport {ProgressTextDisplayField} from \"core-app/modules/fields/display/field-types/progress-text-display-field.module\";\nimport {MultipleLinesUserFieldModule} from \"core-app/modules/fields/display/field-types/multiple-lines-user-display-field.module\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {ISchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DateDisplayField} from \"core-app/modules/fields/display/field-types/date-display-field.module\";\n\nexport const editableClassName = '-editable';\nexport const requiredClassName = '-required';\nexport const readOnlyClassName = '-read-only';\nexport const placeholderClassName = '-placeholder';\nexport const displayClassName = 'inline-edit--display-field';\nexport const editFieldContainerClass = 'inline-edit--container';\nexport const cellEmptyPlaceholder = '-';\n\nexport class DisplayFieldRenderer {\n\n @InjectField() displayFieldService:DisplayFieldService;\n @InjectField() schemaCache:SchemaCacheService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() I18n!:I18nService;\n\n /** We cache the previously used fields to avoid reinitialization */\n private fieldCache:{ [key:string]:DisplayField } = {};\n\n constructor(public readonly injector:Injector,\n public readonly container:'table'|'single-view'|'timeline',\n public readonly options:{ [key:string]:any } = {}) {\n }\n\n public render(resource:T,\n name:string,\n change:ResourceChangeset|null,\n placeholder?:string):HTMLSpanElement {\n\n const [field, span] = this.renderFieldValue(resource, name, change, placeholder);\n\n if (field === null) {\n return span;\n }\n\n this.setSpanAttributes(span, field, name, resource, change);\n\n return span;\n }\n\n public renderFieldValue(resource:T,\n requestedAttribute:string,\n change:ResourceChangeset|null,\n placeholder?:string):[DisplayField|null, HTMLSpanElement] {\n const span = document.createElement('span');\n const schema = this.schema(resource, change);\n const attributeName = this.attributeName(requestedAttribute, schema);\n const fieldSchema = schema.ofProperty(attributeName);\n\n // If the resource does not have that field, return an empty\n // span (e.g., for the table).\n if (!fieldSchema) {\n return [null, span];\n }\n\n const field = this.getField(resource, fieldSchema, attributeName, change);\n field.render(span, this.getText(field, fieldSchema, placeholder), fieldSchema.options);\n\n const title = field.title;\n if (title) {\n span.setAttribute('title', title);\n }\n span.setAttribute('aria-label', this.getAriaLabel(field, schema));\n\n return [field, span];\n }\n\n public getField(resource:T,\n fieldSchema:IFieldSchema,\n attributeName:string,\n change:ResourceChangeset|null):DisplayField {\n let field = this.fieldCache[attributeName];\n\n if (!field) {\n field = this.fieldCache[attributeName] = this.getFieldForCurrentContext(resource, attributeName, fieldSchema);\n }\n\n field.apply(resource, fieldSchema);\n field.activeChange = change;\n\n return field;\n }\n\n private getFieldForCurrentContext(resource:T, attributeName:string, fieldSchema:IFieldSchema):DisplayField {\n const context:DisplayFieldContext = {container: this.container, injector: this.injector, options: this.options};\n\n // We handle multi value fields differently in the single view context\n const isCustomMultiLinesField = ['[]CustomOption'].indexOf(fieldSchema.type) >= 0;\n if (this.container === 'single-view' && isCustomMultiLinesField) {\n return new MultipleLinesCustomOptionsDisplayField(attributeName, context) as DisplayField;\n }\n const isUserMultiLinesField = ['[]User'].indexOf(fieldSchema.type) >= 0;\n if (this.container === 'single-view' && isUserMultiLinesField) {\n return new MultipleLinesUserFieldModule(attributeName, context) as DisplayField;\n }\n\n // We handle progress differently in the timeline\n if (this.container === 'timeline' && attributeName === 'percentageDone') {\n return new ProgressTextDisplayField(attributeName, context);\n }\n\n // We want to render an combined edit field but the display field must\n // show the original attribute\n if (this.container === 'table' && ['startDate', 'dueDate', 'date'].includes(attributeName)) {\n return new DateDisplayField(attributeName, context);\n }\n\n return this.displayFieldService.getField(resource, attributeName, fieldSchema, context);\n }\n\n private getText(field:DisplayField, fieldSchema:IFieldSchema, placeholder?:string):string {\n if (field.isEmpty()) {\n return placeholder || this.getDefaultPlaceholder(fieldSchema);\n } else {\n return field.valueString;\n }\n }\n\n private setSpanAttributes(span:HTMLElement, field:DisplayField, name:string, resource:T, change:ResourceChangeset|null):void {\n span.classList.add(displayClassName, name);\n span.dataset.fieldName = name;\n\n // Make span tabbable unless it's an id field\n span.setAttribute('tabindex', name === 'id' ? '-1' : '0');\n\n if (field.required) {\n span.classList.add(requiredClassName);\n }\n\n if (field.isEmpty()) {\n span.classList.add(placeholderClassName);\n }\n\n const schema = this.schema(resource, change);\n if (this.isAttributeEditable(schema, name)) {\n span.classList.add(editableClassName);\n span.setAttribute('role', 'button');\n } else {\n span.classList.add(readOnlyClassName);\n }\n }\n\n private isAttributeEditable(schema:SchemaResource, fieldName:string) {\n // We need to handle start/due date cases like they were combined dates\n if (['startDate', 'dueDate', 'date'].includes(fieldName)) {\n fieldName = 'combinedDate';\n }\n\n return schema.isAttributeEditable(fieldName);\n }\n\n private getAriaLabel(field:DisplayField, schema:SchemaResource):string {\n let titleContent;\n let labelContent = this.getLabelContent(field);\n\n if (field.isFormattable && !field.isEmpty()) {\n try {\n titleContent = _.escape(jQuery(`
    ${labelContent}
    `).text());\n } catch (e) {\n console.error(\"Failed to parse formattable labelContent\");\n titleContent = \"Label for \" + field.displayName;\n }\n\n } else {\n titleContent = labelContent;\n }\n\n if (field.writable && schema.isAttributeEditable(field.name)) {\n return this.I18n.t('js.inplace.button_edit', {attribute: `${field.displayName} ${titleContent}`});\n } else {\n return `${field.displayName} ${titleContent}`;\n }\n }\n\n private getLabelContent(field:DisplayField):string {\n if (field.isEmpty()) {\n return this.I18n.t('js.inplace.null_value_label');\n } else {\n return field.valueString;\n }\n }\n\n /**\n * Get the attribute name from either the schema if the mappedName method is implemented or\n * return the attribute itself.\n *\n * @param schema\n * @param attribute\n */\n private attributeName(attribute:string, schema:SchemaResource) {\n if (schema.mappedName) {\n return schema.mappedName(attribute);\n } else {\n return attribute;\n }\n }\n\n private getDefaultPlaceholder(fieldSchema:IFieldSchema):string {\n if (fieldSchema.type === 'Formattable') {\n return this.I18n.t('js.work_packages.placeholders.formattable', {name: fieldSchema.name});\n }\n\n return cellEmptyPlaceholder;\n }\n\n private schema(resource:T, change:ResourceChangeset|null) {\n if (!!change) {\n return change.schema;\n } else if (this.halEditing.typedState(resource).hasValue()) {\n return this.halEditing.typedState(resource).value!.schema;\n } else {\n return this.schemaCache.of(resource) as ISchemaProxy;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {Injectable} from \"@angular/core\";\nimport {input} from \"reactivestates\";\nimport {Observable} from \"rxjs\";\nimport {takeUntil} from \"rxjs/operators\";\n\nexport type ModelLinks = {[action:string]:any};\nexport type ModelLinksHash = { [model:string]:ModelLinks };\n\n@Injectable({ providedIn: 'root' })\nexport class AuthorisationService {\n private links = input({});\n\n public initModelAuth(modelName:string, modelLinks:ModelLinks) {\n this.links.doModify((value:ModelLinksHash) => {\n let links = { ...value };\n links[modelName] = modelLinks;\n return links;\n });\n }\n\n public observeUntil(unsubscribe:Observable) {\n return this.links.values$().pipe(takeUntil(unsubscribe));\n }\n\n public can(modelName:string, action:string) {\n const links:ModelLinksHash = this.links.getValueOr({});\n return links[modelName] && (action in links[modelName]);\n }\n\n public cannot(modelName:string, action:string) {\n return !this.can(modelName, action);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {AttachmentCollectionResource} from 'core-app/modules/hal/resources/attachment-collection-resource';\nimport {OpenProjectFileUploadService, UploadFile} from 'core-components/api/op-file-upload/op-file-upload.service';\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {HttpErrorResponse} from \"@angular/common/http\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport { OpenProjectDirectFileUploadService } from 'core-app/components/api/op-file-upload/op-direct-file-upload.service';\n\ntype Constructor = new (...args:any[]) => T;\n\nexport function Attachable>(Base:TBase) {\n return class extends Base {\n public attachments:AttachmentCollectionResource;\n\n private NotificationsService:NotificationsService;\n private halNotification:HalResourceNotificationService;\n private opFileUpload:OpenProjectFileUploadService;\n private opDirectFileUpload:OpenProjectDirectFileUploadService;\n private pathHelper:PathHelperService;\n private apiV3Service:APIV3Service;\n private config:ConfigurationService;\n\n /**\n * Can be used in the mixed in class to disable\n * attempts to upload attachments right away.\n */\n private attachmentsBackend:boolean|null;\n\n /**\n * Return whether the user is able to upload an attachment.\n *\n * If either the `addAttachment` link is provided or the resource is being created,\n * adding attachments is allowed.\n */\n public get canAddAttachments():boolean {\n return !!this.$links.addAttachment || this.isNew;\n }\n\n /**\n *\n */\n public get hasAttachments():boolean {\n return _.get(this.attachments, 'elements.length', 0) > 0;\n }\n\n /**\n * Try to find an existing file's download URL given its filename\n * @param file\n */\n public lookupDownloadLocationByName(file:string):string|null {\n if (!(this.attachments && this.attachments.elements)) {\n return null;\n }\n\n const match = _.find(this.attachments.elements, (res:HalResource) => res.name === file);\n return _.get(match, 'staticDownloadLocation.href', null);\n }\n\n /**\n * Remove the given attachment either from the pending attachments or from\n * the attachment collection, if it is a resource.\n *\n * Removing it from the elements array assures that the view gets updated immediately.\n * If an error occurs, the user gets notified and the attachment is pushed to the elements.\n */\n public removeAttachment(attachment:any):Promise {\n _.pull(this.attachments.elements, attachment);\n\n if (attachment.$isHal) {\n return attachment.delete()\n .then(() => {\n if (!!this.attachmentsBackend) {\n this.updateAttachments();\n } else {\n this.attachments.count = Math.max(this.attachments.count - 1, 0);\n }\n })\n .catch((error:any) => {\n this.halNotification.handleRawError(error, this as any);\n this.attachments.elements.push(attachment);\n });\n }\n return Promise.resolve();\n }\n\n /**\n * Get updated attachments from the server and push the state\n *\n * Return a promise that returns the attachments. Reject, if the work package has\n * no attachments.\n */\n public updateAttachments():Promise {\n return this\n .attachments\n .updateElements()\n .then(() => {\n this.updateState();\n return this.attachments;\n });\n }\n\n /**\n * Upload the given attachments, update the resource and notify the user.\n * Return an updated AttachmentCollectionResource.\n */\n public uploadAttachments(files:UploadFile[]):Promise<{ response:HalResource, uploadUrl:string }[]> {\n const {uploads, finished} = this.performUpload(files);\n\n const message = I18n.t('js.label_upload_notification');\n const notification = this.NotificationsService.addAttachmentUpload(message, uploads);\n\n return finished\n .then((result:{ response:HalResource, uploadUrl:string }[]) => {\n setTimeout(() => this.NotificationsService.remove(notification), 700);\n\n this.attachments.count += result.length;\n result.forEach(r => {\n this.attachments.elements.push(r.response);\n });\n this.updateState();\n\n return result;\n })\n .catch((error:HttpErrorResponse) => {\n let message:undefined|string;\n console.error(\"Error while uploading: %O\", error);\n\n if (error.error instanceof ErrorEvent) {\n // A client-side or network error occurred.\n message = this.I18n.t('js.error_attachment_upload', {error: error});\n } else if (_.get(error, 'error._type') === 'Error') {\n message = error.error.message;\n } else {\n // The backend returned an unsuccessful response code.\n message = error.error;\n }\n\n this.halNotification.handleRawError(message);\n return message || I18n.t('js.error.internal');\n });\n }\n\n private performUpload(files:UploadFile[]) {\n let href:string = this.directUploadURL || '';\n\n if (href) {\n return this.opDirectFileUpload.uploadAndMapResponse(href, files);\n } else if (this.isNew || !this.id || !this.attachmentsBackend) {\n href = this.apiV3Service.attachments.path;\n } else {\n href = this.addAttachment.$link.href;\n }\n\n return this.opFileUpload.uploadAndMapResponse(href, files);\n }\n\n private get directUploadURL():string|null {\n if (this.$links.prepareAttachment) {\n return this.$links.prepareAttachment.href;\n }\n\n if (this.isNew) {\n return this.config.prepareAttachmentURL;\n } else {\n return null;\n }\n }\n\n private updateState() {\n if (this.state) {\n this.state.putValue(this as any);\n }\n }\n\n public $initialize(source:any) {\n if (!this.NotificationsService) {\n this.NotificationsService = this.injector.get(NotificationsService);\n }\n if (!this.halNotification) {\n this.halNotification = this.injector.get(HalResourceNotificationService);\n }\n if (!this.opFileUpload) {\n this.opFileUpload = this.injector.get(OpenProjectFileUploadService);\n }\n if (!this.opDirectFileUpload) {\n this.opDirectFileUpload = this.injector.get(OpenProjectDirectFileUploadService);\n }\n if (!this.config) {\n this.config = this.injector.get(ConfigurationService);\n }\n if (!this.pathHelper) {\n this.pathHelper = this.injector.get(PathHelperService);\n }\n\n if (!this.apiV3Service) {\n this.apiV3Service = this.injector.get(APIV3Service);\n }\n\n super.$initialize(source);\n\n let attachments = this.attachments || {$source: {}, elements: []};\n this.attachments = new AttachmentCollectionResource(\n this.injector,\n attachments,\n false,\n this.halInitializer,\n 'HalResource'\n );\n }\n };\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayFieldContext} from \"core-app/modules/fields/display/display-field.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport interface IFieldSchema {\n type:string;\n writable:boolean;\n allowedValues?:any;\n required?:boolean;\n hasDefault:boolean;\n name?:string;\n options?:any;\n}\n\nexport class Field extends UntilDestroyedMixin {\n public static type:string;\n public resource:any;\n public name:string;\n public schema:IFieldSchema;\n public context:DisplayFieldContext;\n\n public get displayName():string {\n return this.schema.name || this.name;\n }\n\n public get value() {\n return this.resource[this.name];\n }\n\n public get type():string {\n return (this.constructor as typeof Field).type;\n }\n\n public get required():boolean {\n return !!this.schema.required;\n }\n\n public get writable():boolean {\n return this.schema.writable && this.context.options.writable !== false;\n }\n\n public get hasDefault():boolean {\n return this.schema.hasDefault;\n }\n\n public get options():boolean {\n return this.schema.options;\n }\n\n public isEmpty():boolean {\n return !this.value;\n }\n\n public get unknownAttribute():boolean {\n return this.isEmpty && !this.schema;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n AfterContentInit,\n ChangeDetectorRef,\n Component,\n EventEmitter, HostListener,\n Input,\n Output,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {from, Observable, of, Subject} from \"rxjs\";\nimport {catchError, debounceTime, distinctUntilChanged, map, switchMap, tap} from \"rxjs/operators\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {ApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Component({\n selector: 'wp-relations-autocomplete',\n templateUrl: './wp-relations-autocomplete.html',\n\n // Allow styling the embedded ng-select\n encapsulation: ViewEncapsulation.None,\n styleUrls: ['./wp-relations-autocomplete.sass']\n})\nexport class WorkPackageRelationsAutocomplete implements AfterContentInit {\n readonly text = {\n placeholder: this.I18n.t('js.relations_autocomplete.placeholder')\n };\n\n @Input() inputPlaceholder:string = this.text.placeholder;\n @Input() workPackage:WorkPackageResource;\n @Input() selectedRelationType:string;\n @Input() filterCandidatesFor:string;\n\n /** Do we take the current query filters into account? */\n @Input() additionalFilters:ApiV3Filter[] = [];\n\n @Input() hiddenOverflowContainer:string = 'body';\n @ViewChild(NgSelectComponent, { static: true }) public ngSelectComponent:NgSelectComponent;\n\n @Output() onCancel = new EventEmitter();\n @Output() onSelected = new EventEmitter();\n @Output() onEmptySelected = new EventEmitter();\n\n // Whether we're currently loading\n public isLoading = false;\n\n // Search input from ng-select\n public searchInput$ = new Subject();\n\n public appendToContainer = 'body';\n\n // Search results mapped to input\n public results$:Observable = this.searchInput$.pipe(\n debounceTime(250),\n distinctUntilChanged(),\n tap(() => this.isLoading = true),\n switchMap(queryString => this.autocompleteWorkPackages(queryString))\n );\n\n constructor(private readonly querySpace:IsolatedQuerySpace,\n private readonly pathHelper:PathHelperService,\n private readonly notificationService:WorkPackageNotificationService,\n private readonly CurrentProject:CurrentProjectService,\n private readonly halResourceService:HalResourceService,\n private readonly schemaCacheService:SchemaCacheService,\n private readonly cdRef:ChangeDetectorRef,\n private readonly I18n:I18nService) {\n }\n\n @HostListener('keydown.escape')\n public reset() {\n this.cancel();\n }\n\n ngAfterContentInit():void {\n if (!this.ngSelectComponent) {\n return;\n }\n\n setTimeout(() => {\n this.ngSelectComponent.focus();\n }, 25);\n }\n\n cancel() {\n this.onCancel.emit();\n }\n\n public onWorkPackageSelected(workPackage?:WorkPackageResource) {\n if (workPackage) {\n this.schemaCacheService\n .ensureLoaded(workPackage)\n .then(() => {\n this.onSelected.emit(workPackage);\n this.ngSelectComponent.close();\n });\n }\n }\n\n private autocompleteWorkPackages(query:string):Observable {\n // Return when the search string is empty\n if (query === null || query.length === 0) {\n this.isLoading = false;\n return of([]);\n }\n\n // Remove prefix # from search\n query = query.replace(/^#/, '');\n\n return from(\n this.workPackage.availableRelationCandidates.$link.$fetch({\n query: query,\n filters: JSON.stringify(this.additionalFilters),\n type: this.filterCandidatesFor || this.selectedRelationType\n }) as Promise\n )\n .pipe(\n map(collection => collection.elements),\n catchError((error:unknown) => {\n this.notificationService.handleRawError(error);\n return of([]);\n }),\n tap(() => this.isLoading = false)\n );\n }\n\n onOpen() {\n // Force reposition as a workaround for BUG\n // https://github.com/ng-select/ng-select/issues/1259\n setTimeout(() => {\n const component = (this.ngSelectComponent) as any;\n if (component && component.dropdownPanel) {\n component.dropdownPanel._updatePosition();\n }\n\n jQuery(this.hiddenOverflowContainer).one('scroll', () => {\n this.ngSelectComponent.close();\n });\n }, 25);\n\n }\n}\n","
    \n\n \n {{item.type.name }} #{{ item.id }} {{ item.subject }}\n \n \n {{item.type.name }} #{{ item.id }} {{ item.subject }}\n \n\n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {InputState} from \"reactivestates\";\nimport {HalLinkInterface} from 'core-app/modules/hal/hal-link/hal-link';\nimport {Injector} from '@angular/core';\nimport {States} from 'core-components/states.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport interface HalResourceClass {\n new(injector:Injector,\n source:any,\n $loaded:boolean,\n halInitializer:(halResource:T) => void,\n $halType:string):T;\n}\n\nexport type HalSourceLink = { href:string|null };\n\nexport type HalSourceLinks = {\n [key:string]:HalSourceLink\n};\n\nexport type HalSource = {\n [key:string]:string|number|null|HalSourceLinks,\n _links:HalSourceLinks\n};\n\nexport class HalResource {\n // TODO this is the source of many issues in the frontend\n // because it no longer properly type checks stuff\n // Since 2019-10-21 I'm documenting what bugs this caused:\n // https://community.openproject.com/wp/31462\n [attribute:string]:any;\n\n // The API type reported from API\n public _type:string;\n\n // Internal initialization time for objects\n // created in the frontend\n public __initialized_at:Number;\n\n // The HalResource that this type maps to\n // This will almost always be equal to _type, however may be different for dynamic types\n // e.g., { _type: 'StatusFilterInstance', $halType: 'QueryFilterInstance' }.\n //\n // This is required for attributes to be correctly mapped according to their configuration.\n public $halType:string;\n\n @InjectField() states:States;\n @InjectField() I18n!:I18nService;\n\n /**\n * Constructs and initializes the HalResource. For this, the halResoureFactory is required.\n *\n * However, We can't inject the HalResourceFactory here because it itself depends on this class.\n * So if you need to initialize a HalResource, use +HalResourceFactory.createHalResource+ instead.\n *\n * @param {Injector} injector\n * @param $halType The HalResource type that this instance maps to\n * @param $source\n * @param {boolean} $loaded\n * @param {Function} initializer The initializer callback to HAL-transform all linked and embedded resources.\n *\n */\n public constructor(public injector:Injector,\n public $source:any,\n public $loaded:boolean,\n public halInitializer:(halResource:any) => void,\n $halType:string) {\n this.$halType = $halType;\n this.$initialize($source);\n }\n\n public static getEmptyResource(self:{ href:string|null } = {href: null}):any {\n return {_links: {self: self}};\n }\n\n public $links:any = {};\n public $embedded:any = {};\n public $self:Promise;\n\n public _name:string;\n\n public static idFromLink(href:string):string {\n return href.split('/').pop()!;\n }\n\n public get idFromLink():string {\n if (this.$href) {\n return HalResource.idFromLink(this.$href);\n }\n\n return '';\n }\n\n public $initialize(source:any) {\n this.$source = source.$source || source;\n this.halInitializer(this);\n }\n\n /**\n * Override toString to ensure the resource can\n * be printed nicely on console and in errors\n */\n public toString() {\n if (this.$href) {\n return `[HalResource href=${this.$href}]`;\n } else {\n return `[HalResource id=${this.id}]`;\n }\n }\n\n /**\n * Returns the ID and ensures it's a string, null.\n * Returns a string when:\n * - The embedded ID is actually set\n * - The self link is terminated by a number.\n */\n public get id():string|null {\n if (this.$source.id) {\n return this.$source.id.toString();\n }\n\n const id = this.idFromLink;\n if (id.match(/^\\d+$/)) {\n return id;\n }\n\n return null;\n }\n\n public set id(val:string|null) {\n this.$source.id = val;\n }\n\n public get isNew():boolean {\n return !this.id || this.id === 'new';\n }\n\n public get persisted() {\n return !!(this.id && this.id !== 'new');\n }\n\n /**\n * Retain the internal tracking identifier from the given other work package.\n * This is due to us needing to identify a work package beyond its actual ID,\n * because that changes upon saving.\n *\n * @param other\n */\n public retainFrom(other:HalResource) {\n this.__initialized_at = other.__initialized_at;\n }\n\n\n /**\n * Create a HalResource from the copied source of the given, other HalResource.\n *\n * @param {HalResource} other\n * @returns A HalResource with the identitical copied source of other.\n */\n public $copy(source:Object = {}):T {\n let clone:HalResourceClass = this.constructor as any;\n\n return new clone(this.injector, _.merge(this.$plain(), source), this.$loaded, this.halInitializer, this.$halType);\n }\n\n public $plain():any {\n return _.cloneDeep(this.$source);\n }\n\n public get $isHal():boolean {\n return true;\n }\n\n public get $link():HalLinkInterface {\n return this.$links.self.$link;\n }\n\n public get name():string {\n return this._name || this.$link.title || '';\n }\n\n public set name(name:string) {\n this._name = name;\n }\n\n /**\n * Alias for $href.\n */\n public get href():string|null {\n return this.$link.href;\n }\n\n public get $href():string|null {\n return this.$link.href;\n }\n\n /**\n * Return the associated state to this HAL resource, if any.\n */\n public get state():InputState|null {\n return null;\n }\n\n /**\n * Update the state\n */\n public push(newValue:this):Promise {\n if (this.state) {\n this.state.putValue(newValue);\n }\n\n return Promise.resolve();\n }\n\n public previewPath():string|undefined {\n if (this.isNew && this.project) {\n return this.project.href;\n }\n\n return undefined;\n }\n\n public getEditorTypeFor(_fieldName:string):'full'|'constrained' {\n return 'constrained';\n }\n\n public $load(force = false):Promise {\n if (!this.state) {\n return this.$loadResource(force);\n }\n\n const state = this.state;\n\n if (force) {\n state.clear();\n }\n\n // If nobody has asked yet for the resource to be $loaded, do it ourselves.\n // Otherwise, we risk returning a promise, that will never be resolved.\n state.putFromPromiseIfPristine(() => this.$loadResource(force));\n\n return >state.valuesPromise().then((source:any) => {\n this.$initialize(source);\n this.$loaded = true;\n return this;\n });\n }\n\n protected $loadResource(force = false):Promise {\n if (!force) {\n if (this.$loaded) {\n return Promise.resolve(this);\n }\n\n if (!this.$loaded && this.$self) {\n return this.$self;\n }\n }\n\n // Reset and load this resource\n this.$loaded = false;\n this.$self = this.$links.self({}).then((source:any) => {\n this.$loaded = true;\n this.$initialize(source.$source);\n return this;\n });\n\n return this.$self;\n }\n\n /**\n * Update the resource ignoring the cache.\n */\n public $update() {\n return this.$load(true);\n }\n\n /**\n * Specify this resource's embedded keys that should be transformed with resources.\n * Use this to restrict, e.g., links that should not be made properties if you have a custom get/setter.\n */\n public $embeddableKeys():string[] {\n const properties = Object.keys(this.$source);\n return _.without(properties, '_links', '_embedded', 'id');\n }\n\n /**\n * Specify this resource's keys that should not be transformed with resources.\n * Use this to restrict, e.g., links that should not be made properties if you have a custom get/setter.\n */\n public $linkableKeys():string[] {\n const properties = Object.keys(this.$links);\n return _.without(properties, 'self');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input} from '@angular/core';\n\n@Component({\n selector: 'op-icon',\n host: { 'class': 'op-icon--wrapper' },\n template: `\n \n \n `\n})\nexport class OpIcon {\n @Input('icon-classes') iconClasses:string;\n @Input('icon-title') iconTitle:string = '';\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\nexport interface RelationResourceLinks {\n delete():Promise;\n\n updateImmediately(payload:any):Promise;\n}\n\nexport class RelationResource extends HalResource {\n\n static RELATION_TYPES(includeParentChild:boolean = true):string[] {\n const types = [\n 'relates',\n 'duplicates',\n 'duplicated',\n 'blocks',\n 'blocked',\n 'precedes',\n 'follows',\n 'includes',\n 'partof',\n 'requires',\n 'required'\n ];\n\n if (includeParentChild) {\n types.push('parent', 'children');\n }\n\n return types;\n }\n\n static LOCALIZED_RELATION_TYPES(includeParentchild:boolean = true) {\n const relationTypes = RelationResource.RELATION_TYPES(includeParentchild);\n\n return relationTypes.map((key:string) => {\n return {name: key, label: I18n.t('js.relation_labels.' + key)};\n });\n }\n\n static DEFAULT() {\n return 'relates';\n }\n\n // Properties\n public description:string|null;\n public type:any;\n public reverseType:string;\n\n // Links\n public $links:RelationResourceLinks;\n public to:WorkPackageResource;\n public from:WorkPackageResource;\n\n public normalizedType(workPackage:WorkPackageResource) {\n return this.denormalized(workPackage).relationType;\n }\n\n /**\n * Return the denormalized relation data, seeing the relation.from to be `workPackage`.\n *\n * @param workPackage\n * @return {{id, href, relationType: string, workPackageType}}\n */\n public denormalized(workPackage:WorkPackageResource):DenormalizedRelationData {\n const target = (this.to.href === workPackage.$href) ? 'from' : 'to';\n\n return {\n target: this[target],\n targetId: this[target].id!,\n relationType: target === 'from' ? this.reverseType : this.type,\n reverseRelationType: target === 'from' ? this.type : this.reverseType\n };\n }\n\n /**\n * Return whether the given work package id is involved in this relation.\n * @param wpId\n * @return {boolean}\n */\n public isInvolved(wpId:string) {\n return _.values(this.ids).indexOf(wpId.toString()) >= 0;\n }\n\n /**\n * Get the involved IDs, returning an object to the ids.\n */\n public get ids() {\n return {\n from: WorkPackageResource.idFromLink(this.from.href!),\n to: WorkPackageResource.idFromLink(this.to.href!)\n };\n }\n\n public updateDescription(description:string) {\n return this.$links.updateImmediately({description: description});\n }\n\n public updateType(type:any) {\n return this.$links.updateImmediately({type: type});\n }\n}\n\nexport interface RelationResource extends RelationResourceLinks {\n}\n\nexport interface DenormalizedRelationData {\n target:WorkPackageResource;\n targetId:string;\n relationType:string;\n reverseRelationType:string;\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HttpParameterCodec} from '@angular/common/http';\n\nexport class URLParamsEncoder implements HttpParameterCodec {\n encodeKey(key:string):string {\n return encodeURIComponent(key);\n }\n\n encodeValue(value:string):string {\n return encodeURIComponent(value);\n }\n\n decodeKey(key:string):string {\n return decodeURIComponent(key);\n }\n\n decodeValue(value:string):string {\n return decodeURIComponent(value);\n }\n}\n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class VersionResource extends HalResource {\n status:string;\n\n public definingProject:HalResource;\n\n public isLocked() {\n return this.status === 'locked';\n }\n\n public isOpen() {\n return this.status === 'open';\n }\n\n public isClosed() {\n return this.status === 'closed';\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {take} from 'rxjs/operators';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageCreateComponent} from 'core-components/wp-new/wp-create.component';\nimport {WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {Directive} from \"@angular/core\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n@Directive()\nexport class WorkPackageCopyController extends WorkPackageCreateComponent {\n private __initialized_at:Number;\n private copiedWorkPackageId:string;\n\n /** Are we in the copying substates ? */\n public copying = true;\n\n @InjectField() wpRelations:WorkPackageRelationsService;\n @InjectField() halEditing:HalResourceEditingService;\n\n ngOnInit() {\n super.ngOnInit();\n\n this.wpCreate.onNewWorkPackage()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n if (wp.__initialized_at === this.__initialized_at) {\n this.wpRelations.addCommonRelation(wp.id!, 'relates', this.copiedWorkPackageId);\n }\n });\n }\n\n protected createdWorkPackage() {\n this.copiedWorkPackageId = this.stateParams.copiedFromWorkPackageId;\n return new Promise((resolve, reject) => {\n this\n .apiV3Service\n .work_packages\n .id(this.copiedWorkPackageId)\n .get()\n .pipe(\n take(1)\n )\n .subscribe((wp:WorkPackageResource) => {\n this.createCopyFrom(wp).then(resolve, reject);\n });\n });\n }\n\n protected setTitle() {\n this.titleService.setFirstPart(this.I18n.t('js.work_packages.copy.title'));\n }\n\n private createCopyFrom(wp:WorkPackageResource) {\n let sourceChangeset = this.halEditing.changeFor(wp) as WorkPackageChangeset;\n\n return this.wpCreate\n .copyWorkPackage(sourceChangeset)\n .then((copyChangeset:WorkPackageChangeset) => {\n this.__initialized_at = copyChangeset.pristineResource.__initialized_at;\n\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(copyChangeset.pristineResource, true);\n\n this.halEditing.updateValue('new', copyChangeset);\n\n return copyChangeset;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class ProgressDisplayField extends DisplayField {\n public get value() {\n if (this.schema) {\n return this.resource[this.name] || 0;\n }\n else {\n return null;\n }\n }\n\n public get percentLabel() {\n return this.roundedProgress + '%';\n }\n\n public get roundedProgress() {\n return Math.round(Number(this.value)) || 0;\n }\n\n public render(element:HTMLElement, displayText:string):void {\n element.setAttribute('title', displayText);\n element.innerHTML = `\n \n \n \n \n \n ${this.percentLabel}\n \n `;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {ActivityPanelBaseController} from 'core-components/wp-single-view-tabs/activity-panel/activity-base.controller';\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\n\n@Component({\n templateUrl: './activity-tab.html',\n selector: 'wp-activity-tab',\n})\nexport class WorkPackageActivityTabComponent extends ActivityPanelBaseController {\n public workPackage:WorkPackageResource;\n public tabName = this.I18n.t('js.work_packages.tabs.activity');\n public trackByHref = AngularTrackingHelpers.trackByHrefAndProperty('version');\n\n ngOnInit() {\n this.workPackageId = this.$transition.params('to').workPackageId;\n super.ngOnInit();\n }\n}\n","\n \n
    \n
    \n
    \n

    \n \n \n \n \n

    \n\n \n \n
    \n
    \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageViewColumnsService} from './wp-view-columns.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageViewHierarchiesService} from './wp-view-hierarchy.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {RelationsStateValue, WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageViewAdditionalElementsService {\n\n constructor(readonly querySpace:IsolatedQuerySpace,\n readonly wpTableHierarchies:WorkPackageViewHierarchiesService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly notificationService:WorkPackageNotificationService,\n readonly halResourceService:HalResourceService,\n readonly apiV3Service:APIV3Service,\n readonly schemaCache:SchemaCacheService,\n readonly wpRelations:WorkPackageRelationsService) {\n }\n\n public initialize(query:QueryResource, results:WorkPackageCollectionResource) {\n const rows = results.elements;\n\n // Add relations to the stack\n Promise.all([\n this.requireInvolvedRelations(rows.map(el => el.id!)),\n this.requireHierarchyElements(rows),\n this.requireSumsSchema(results)\n ]).then((results:string[][]) => {\n this.loadAdditional(_.flatten(results));\n });\n }\n\n private loadAdditional(wpIds:string[]) {\n this\n .apiV3Service\n .work_packages\n .requireAll(wpIds)\n .then(() => {\n this.querySpace.additionalRequiredWorkPackages.putValue(null, 'All required work packages are loaded');\n })\n .catch((e) => {\n this.querySpace.additionalRequiredWorkPackages.putValue(null, 'Failure loading required work packages');\n this.notificationService.handleRawError(e);\n });\n }\n\n /**\n * Requires both the relation resource of the given work package ids as well\n * as the `to` work packages returned from the relations\n */\n private requireInvolvedRelations(rows:string[]):Promise {\n\n if (!this.wpTableColumns.hasRelationColumns()) {\n return Promise.resolve([]);\n }\n return this.wpRelations\n .requireAll(rows)\n .then(() => {\n const ids = this.getInvolvedWorkPackages(rows.map(id => {\n return this.wpRelations.state(id).value!;\n }));\n return _.flatten(ids);\n });\n }\n\n /**\n * Return the id of all ancestors for visible rows in the table.\n * @param rows\n * @return {string[]}\n */\n private requireHierarchyElements(rows:WorkPackageResource[]):Promise {\n if (!this.wpTableHierarchies.isEnabled) {\n return Promise.resolve([]);\n }\n\n const ids = _.flatten(rows.map(el => el.ancestorIds));\n return Promise.resolve(ids);\n }\n\n /**\n * From a set of relations state values, return all involved IDs.\n * @param states\n * @return {string[]}\n */\n private getInvolvedWorkPackages(states:RelationsStateValue[]) {\n const ids:string[] = [];\n _.each(states, (relations:RelationsStateValue) => {\n _.each(relations, (resource:RelationResource) => {\n ids.push(resource.ids.from, resource.ids.to);\n });\n });\n\n return ids;\n }\n\n private requireSumsSchema(results:WorkPackageCollectionResource):Promise {\n if (results.sumsSchema) {\n return this\n .schemaCache\n .ensureLoaded(results.sumsSchema.$href!)\n .then(() => []);\n }\n\n return Promise.resolve([]);\n }\n}\n","import {createPointCB, getClientRect as getRect, pointInside} from 'dom-plane';\n\nexport class DomAutoscrollService {\n public elements:Element[];\n public scrolling:boolean;\n public down:boolean = false;\n public scrollWhenOutside:boolean;\n public autoScroll:() => boolean;\n public maxSpeed:number;\n public margin:number;\n public animationFrame:number;\n public windowAnimationFrame:number;\n public current:HTMLElement[];\n public outerScrollContainer:HTMLElement;\n public point:any;\n public pointCB:any;\n\n constructor(elements:Element[],\n params:any) {\n this.elements = elements;\n this.scrollWhenOutside = params.scrollWhenOutside || false;\n this.maxSpeed = params.maxSpeed || 5;\n this.margin = params.margin || 10;\n this.scrollWhenOutside = params.scrollWhenOutside || false;\n this.autoScroll = params.autoScroll;\n this.point = {};\n this.pointCB = createPointCB(this.point);\n\n this.init();\n }\n\n public init() {\n jQuery(window).on('mousemove.domautoscroll touchmove.domautoscroll', (evt:any) => {\n if (this.down) {\n this.pointCB(evt);\n this.onMove(evt);\n }\n });\n jQuery(window).on('mousedown.domautoscroll touchstart.domautoscroll', () => this.down = true);\n jQuery(window).on('mouseup.domautoscroll touchend.domautoscroll', () => this.onUp());\n jQuery(window).on('scroll.domautoscroll', (evt:any) => this.setScroll(evt));\n }\n\n public destroy() {\n jQuery(window).off('.domautoscroll');\n\n this.elements = [];\n this.cleanAnimation();\n }\n\n public add(el:Element|Element[]) {\n if (Array.isArray(el)) {\n this.elements = this.elements.concat(el);\n\n // Remove duplicates\n this.elements = Array.from(new Set(this.elements));\n } else {\n this.elements.push(el);\n }\n }\n\n public onUp() {\n this.down = false;\n cancelAnimationFrame(this.animationFrame);\n cancelAnimationFrame(this.windowAnimationFrame);\n }\n\n public setScroll(e:any) {\n for (let i = 0; i < this.elements.length; i++) {\n if (this.elements[i] === e.target) {\n this.scrolling = true;\n break;\n }\n }\n\n if (this.scrolling) {\n requestAnimationFrame(() => this.scrolling = false);\n }\n }\n\n public cleanAnimation() {\n cancelAnimationFrame(this.animationFrame);\n cancelAnimationFrame(this.windowAnimationFrame);\n }\n\n public getTarget(target:HTMLElement):HTMLElement[] {\n if (!target) {\n return [];\n }\n\n let results = [];\n if (this.elements.includes(target)) {\n results.push(target);\n }\n\n let targetObject = target;\n while (targetObject = targetObject.parentNode as HTMLElement) {\n if (this.elements.includes(targetObject)) {\n results.push(targetObject);\n }\n }\n\n return results;\n }\n\n public getElementsUnderPoint():HTMLElement[] {\n let underPoint = [];\n\n for (var i = 0; i < this.elements.length; i++) {\n if (this.inside(this.point, this.elements[i])) {\n underPoint.push(this.elements[i] as HTMLElement);\n }\n }\n\n return underPoint;\n }\n\n public onMove(event:any) {\n if (!this.autoScroll()) {\n return;\n }\n\n if (event.dispatched) {\n return;\n }\n\n let target = [] as HTMLElement[];\n if (event.target !== null) {\n target.push(event.target as HTMLElement);\n }\n let body = document.body;\n\n if (target.length > 0 && target[0].parentNode === body) {\n //The special condition to improve speed.\n target = this.getElementsUnderPoint();\n } else {\n target = this.getTarget(target[0]);\n\n if (target.length === 0) {\n target = this.getElementsUnderPoint();\n }\n }\n\n this.current = target;\n\n if (this.current.length === 0) {\n this.current = [this.outerScrollContainer];\n }\n\n cancelAnimationFrame(this.animationFrame);\n this.animationFrame = requestAnimationFrame(this.scrollTick.bind(this));\n }\n\n public setOuterScrollContainer(el:HTMLElement) {\n this.outerScrollContainer = el;\n }\n\n public scrollTick() {\n if (this.current.length === 0) {\n return;\n }\n\n this.current.forEach((e?:Element) => {\n if (e) {\n this.scrollAutomatically(e);\n }\n });\n\n cancelAnimationFrame(this.animationFrame);\n this.animationFrame = requestAnimationFrame(this.scrollTick.bind(this));\n\n }\n\n\n public scrollAutomatically(el:Element) {\n let rect = getRect(el);\n let scrollx:number;\n let scrolly:number;\n\n if (this.point.x < rect.left + this.margin) {\n scrollx = -this.maxSpeed;\n } else if (this.point.x > rect.right - this.margin) {\n scrollx = this.maxSpeed;\n } else {\n scrollx = 0;\n }\n\n if (this.point.y < rect.top + this.margin) {\n scrolly = -this.maxSpeed;\n } else if (this.point.y > rect.bottom - this.margin) {\n scrolly = this.maxSpeed;\n } else {\n scrolly = 0;\n }\n\n setTimeout(() => {\n if (scrolly) {\n this.scrollY(el, scrolly);\n }\n\n if (scrollx) {\n this.scrollX(el, scrollx);\n }\n });\n }\n\n public scrollY(el:any, amount:number) {\n if (el === window) {\n window.scrollTo(el.pageXOffset, el.pageYOffset + amount);\n } else {\n el.scrollTop += amount;\n }\n }\n\n public scrollX(el:any, amount:number) {\n if (el === window) {\n window.scrollTo(el.pageXOffset + amount, el.pageYOffset);\n } else {\n el.scrollLeft += amount;\n }\n }\n\n public inside(point:any, el:Element, rect?:any) {\n if (!rect) {\n return pointInside(point, el);\n } else {\n return (point.y > rect.top && point.y < rect.bottom &&\n point.x > rect.left && point.x < rect.right);\n }\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {StateService} from '@uirouter/core';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\n\nexport class WorkPackageAuthorization {\n\n public project:any;\n\n constructor(public workPackage:WorkPackageResource,\n readonly PathHelper:PathHelperService,\n readonly $state:StateService) {\n this.project = workPackage.project;\n }\n\n public get allActions():any {\n return {\n workPackage: this.workPackage,\n project: this.project\n };\n }\n\n public copyLink() {\n const stateName = this.$state.current.name as string;\n if (stateName.indexOf('work-packages.partitioned.list.details') === 0) {\n return this.PathHelper.workPackageDetailsCopyPath(this.project.identifier, this.workPackage.id!);\n } else {\n return this.PathHelper.workPackageCopyPath(this.workPackage.id!);\n }\n }\n\n public linkForAction(action:any) {\n if (action.key === 'copy') {\n action.link = this.copyLink();\n }\n else {\n action.link = this.allActions[action.resource][action.link].href;\n }\n\n return action;\n }\n\n public isPermitted(action:any) {\n return this.allActions[action.resource] !== undefined &&\n this.allActions[action.resource][action.link] !== undefined;\n }\n\n public permittedActionKeys(allowedActions:any) {\n var validActions = _.filter(allowedActions, (action:any) => this.isPermitted(action));\n\n return _.map(validActions, function (action:any) {\n return action.key;\n });\n }\n\n public permittedActionsWithLinks(allowedActions:any) {\n var validActions = _.filter(_.cloneDeep(allowedActions), (action:any) => this.isPermitted(action));\n\n var allowed = _.map(validActions, (action:any) => this.linkForAction(action));\n\n return allowed;\n }\n}\n","import {Directive, ElementRef, Injector, Input} from '@angular/core';\nimport {StateService} from '@uirouter/core';\nimport {LinkHandling} from 'core-app/modules/common/link-handling/link-handling';\nimport {AuthorisationService} from 'core-app/modules/common/model-auth/model-auth.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HookService} from 'core-app/modules/plugins/hook-service';\nimport {WpDestroyModal} from 'core-components/modals/wp-destroy-modal/wp-destroy.modal';\nimport {OpContextMenuTrigger} from 'core-components/op-context-menu/handlers/op-context-menu-trigger.directive';\nimport {OPContextMenuService} from 'core-components/op-context-menu/op-context-menu.service';\nimport {OpContextMenuItem} from 'core-components/op-context-menu/op-context-menu.types';\nimport {PERMITTED_CONTEXT_MENU_ACTIONS} from 'core-components/op-context-menu/wp-context-menu/wp-static-context-menu-actions';\nimport {OpModalService} from 'core-components/op-modals/op-modal.service';\nimport {WorkPackageAuthorization} from 'core-components/work-packages/work-package-authorization.service';\nimport {WorkPackageAction} from 'core-components/wp-table/context-menu-helper/wp-context-menu-helper.service';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {TimeEntryCreateService} from \"core-app/modules/time_entries/create/create.service\";\n\n@Directive({\n selector: '[wpSingleContextMenu]'\n})\nexport class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger {\n @Input('wpSingleContextMenu-workPackage') public workPackage:WorkPackageResource;\n\n @InjectField() public timeEntryCreateService:TimeEntryCreateService;\n\n constructor(readonly HookService:HookService,\n readonly $state:StateService,\n readonly injector:Injector,\n readonly PathHelper:PathHelperService,\n readonly elementRef:ElementRef,\n readonly opModalService:OpModalService,\n readonly opContextMenuService:OPContextMenuService,\n readonly authorisationService:AuthorisationService) {\n super(elementRef, opContextMenuService);\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n this.workPackage.project.$load().then(() => {\n this.authorisationService.initModelAuth('work_package', this.workPackage.$links);\n\n var authorization = new WorkPackageAuthorization(this.workPackage, this.PathHelper, this.$state);\n const permittedActions = this.getPermittedActions(authorization);\n\n this.buildItems(permittedActions);\n this.opContextMenu.show(this, evt);\n });\n }\n\n public triggerContextMenuAction(action:WorkPackageAction, key:string) {\n const link = action.link;\n\n switch (key) {\n case 'copy':\n this.$state.go('work-packages.copy', { copiedFromWorkPackageId: this.workPackage.id });\n break;\n case 'delete':\n this.opModalService.show(WpDestroyModal, this.injector, { workPackages: [this.workPackage] });\n break;\n case 'log_time':\n this.timeEntryCreateService\n .create(moment(new Date()), this.workPackage, false)\n .catch(() => {\n // do nothing, the user closed without changes\n });\n break;\n\n default:\n window.location.href = link!;\n break;\n }\n }\n\n /**\n * Positioning args for jquery-ui position.\n *\n * @param {Event} openerEvent\n */\n public positionArgs(evt:JQuery.TriggeredEvent) {\n let additionalPositionArgs = {\n my: 'right top',\n at: 'right bottom'\n };\n\n let position = super.positionArgs(evt);\n _.assign(position, additionalPositionArgs);\n\n return position;\n }\n\n private getPermittedActions(authorization:WorkPackageAuthorization) {\n let actions:WorkPackageAction[] = authorization.permittedActionsWithLinks(PERMITTED_CONTEXT_MENU_ACTIONS);\n\n // Splice plugin actions onto the core actions\n _.each(this.getPermittedPluginActions(authorization), (action:WorkPackageAction) => {\n let index = action.indexBy ? action.indexBy(actions) : actions.length;\n actions.splice(index, 0, action);\n });\n\n return actions;\n }\n\n private getPermittedPluginActions(authorization:WorkPackageAuthorization) {\n let actions:WorkPackageAction[] = this.HookService.call('workPackageSingleContextMenu');\n return authorization.permittedActionsWithLinks(actions);\n }\n\n protected buildItems(permittedActions:WorkPackageAction[]):OpContextMenuItem[] {\n const configureFormLink = this.workPackage.configureForm;\n\n this.items = permittedActions.map((action:WorkPackageAction) => {\n const key = action.key;\n return {\n disabled: false,\n linkText: I18n.t('js.button_' + key),\n href: action.link,\n icon: action.icon || `icon-${key}`,\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (action.link && LinkHandling.isClickedWithModifier($event)) {\n return false;\n }\n\n this.triggerContextMenuAction(action, key);\n return true;\n }\n };\n });\n\n if (configureFormLink) {\n this.items.push(\n {\n href: configureFormLink.href,\n icon: 'icon-settings3',\n linkText: I18n.t('js.button_configure-form'),\n onClick: () => false\n }\n );\n }\n\n return this.items;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport * as moment from 'moment';\nimport flatpickr from 'flatpickr';\nimport {Instance} from 'flatpickr/dist/types/instance';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport DateOption = flatpickr.Options.DateOption;\n\nexport class DatePicker {\n private datepickerFormat = 'Y-m-d';\n\n private datepickerCont:HTMLElement = document.querySelector(this.datepickerElemIdentifier)! as HTMLElement;\n public datepickerInstance:Instance;\n private reshowTimeout:any;\n\n constructor(private datepickerElemIdentifier:string,\n private date:any,\n private options:any,\n private datepickerTarget?:HTMLElement,\n private configurationService?:ConfigurationService) {\n this.initialize(options);\n }\n\n private initialize(options:any) {\n const I18n = new I18nService();\n const firstDayOfWeek =\n this.configurationService?.startOfWeekPresent() ? this.configurationService.startOfWeek() : 1;\n\n const mergedOptions = _.extend({}, options, {\n weekNumbers: true,\n getWeek(dateObj:Date) {\n return moment(dateObj).week();\n },\n dateFormat: this.datepickerFormat,\n defaultDate: this.date,\n locale: {\n weekdays: {\n shorthand: I18n.t('date.abbr_day_names'),\n longhand: I18n.t('date.day_names'),\n },\n months: {\n shorthand: (I18n.t('date.abbr_month_names') as any).slice(1),\n longhand: (I18n.t('date.month_names') as any).slice(1),\n },\n firstDayOfWeek: firstDayOfWeek,\n weekAbbreviation: I18n.t('date.abbr_week')\n },\n });\n\n var datePickerInstances:Instance|Instance[];\n if (this.datepickerTarget) {\n datePickerInstances = flatpickr(this.datepickerTarget as Node, mergedOptions);\n } else {\n datePickerInstances = flatpickr(this.datepickerElemIdentifier, mergedOptions);\n }\n\n this.datepickerInstance = Array.isArray(datePickerInstances) ? datePickerInstances[0] : datePickerInstances;\n\n document.addEventListener('scroll', this.hideDuringScroll, true);\n }\n\n public clear() {\n this.datepickerInstance.clear();\n }\n\n public destroy() {\n this.hide();\n this.datepickerInstance.destroy();\n }\n\n public hide() {\n if (this.isOpen) {\n this.datepickerInstance.close();\n }\n\n document.removeEventListener('scroll', this.hideDuringScroll, true);\n }\n\n public show() {\n this.datepickerInstance.open();\n document.addEventListener('scroll', this.hideDuringScroll, true);\n }\n\n public setDates(dates:DateOption|DateOption[]) {\n this.datepickerInstance.setDate(dates);\n }\n\n public get isOpen():boolean {\n return this.datepickerInstance.isOpen;\n }\n\n private hideDuringScroll = (event:Event) => {\n // Prevent Firefox quirk: flatPicker emits\n // multiple scrolls event when it is open\n const target = event.target! as HTMLInputElement;\n\n if (target.classList.contains('flatpickr-monthDropdown-months')) {\n return;\n }\n\n this.datepickerInstance.close();\n\n if (this.reshowTimeout) {\n clearTimeout(this.reshowTimeout);\n }\n\n this.reshowTimeout = setTimeout(() => {\n if (this.visibleAndActive()) {\n this.datepickerInstance.open();\n }\n }, 50);\n }\n\n private visibleAndActive() {\n try {\n return this.isInViewport(this.datepickerCont) &&\n document.activeElement === this.datepickerCont;\n } catch (e) {\n console.error('Failed to test visibleAndActive ' + e);\n return false;\n }\n }\n\n private isInViewport(element:HTMLElement) {\n const rect = element.getBoundingClientRect();\n\n return (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\n rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\n\nexport class GridWidgetResource extends HalResource {\n @InjectField() protected halResource:HalResourceService;\n public identifier:string;\n public startRow:number;\n public endRow:number;\n public startColumn:number;\n public endColumn:number;\n\n public options:{[key:string]:unknown};\n\n public get height() {\n return this.endRow - this.startRow;\n }\n\n public get width() {\n return this.endColumn - this.startColumn;\n }\n\n public grid:GridResource;\n\n public get schema():SchemaResource {\n return this.halResource.createHalResource({'_type': 'Schema' }, true);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {StateService} from '@uirouter/core';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injectable, Injector} from '@angular/core';\nimport {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HttpErrorResponse} from \"@angular/common/http\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Injectable()\nexport class HalResourceNotificationService {\n\n @InjectField() protected I18n:I18nService;\n @InjectField() protected $state:StateService;\n @InjectField() protected halResourceService:HalResourceService;\n @InjectField() protected NotificationsService:NotificationsService;\n @InjectField() protected loadingIndicator:LoadingIndicatorService;\n @InjectField() protected schemaCache:SchemaCacheService;\n\n constructor(public injector:Injector) {\n }\n\n public showSave(resource:HalResource, isCreate:boolean = false) {\n let message:any = {\n message: this.I18n.t('js.notice_successful_' + (isCreate ? 'create' : 'update')),\n };\n\n this.NotificationsService.addSuccess(message);\n }\n\n /**\n * Handle any kind of error response:\n * - HAL ErrorResources\n * - Angular HttpErrorResponses\n * - Older .data error responses\n * - String error messages\n *\n * @param response\n * @param resource\n */\n public handleRawError(response:unknown, resource?:HalResource) {\n console.error(\"Handling error message %O for work package %O\", response, resource);\n\n // Some transformation may already have returned the error as a HAL resource,\n // which we will forward to handleErrorResponse\n if (response instanceof ErrorResource) {\n return this.handleErrorResponse(response, resource);\n }\n\n const errorBody = this.retrieveError(response);\n\n if (errorBody instanceof HalResource) {\n return this.handleErrorResponse(errorBody, resource);\n }\n\n if (typeof (response) === 'string') {\n this.NotificationsService.addError(response);\n return;\n }\n\n if (response instanceof Error) {\n this.NotificationsService.addError(response.message);\n return;\n }\n\n this.showGeneralError(errorBody || response);\n }\n\n /**\n * Retrieve an error message string from the given unknown response.\n * @param response\n */\n public retrieveErrorMessage(response:unknown):string {\n const error = this.retrieveError(response);\n\n if (error instanceof ErrorResource) {\n return error.message;\n }\n\n if (typeof (error) === 'string') {\n return error;\n }\n\n return this.I18n.t('js.error.internal');\n }\n\n public retrieveError(response:unknown):ErrorResource|unknown {\n // we try to detect what we got, this may either be an HttpErrorResponse,\n // some older XHR response object or a string\n let errorBody:any = response;\n\n // Angular http response have an error body attribute\n if (response instanceof HttpErrorResponse) {\n errorBody = response.message || response.error;\n }\n\n // Some older response may have a data attribute\n if (_.get(response, 'data._type') === 'Error') {\n errorBody = (response as any).data;\n }\n\n if (errorBody && errorBody._type === 'Error') {\n return this.halResourceService.createHalResourceOfClass(ErrorResource, errorBody);\n }\n\n return errorBody;\n }\n\n protected handleErrorResponse(errorResource:any, resource?:HalResource) {\n if (!(errorResource instanceof ErrorResource)) {\n return this.showGeneralError(errorResource);\n }\n\n if (resource) {\n return this.showError(errorResource, resource);\n }\n\n this.showApiErrorMessages(errorResource);\n }\n\n public showError(errorResource:any, resource:HalResource) {\n this.showCustomError(errorResource, resource) || this.showApiErrorMessages(errorResource);\n }\n\n public showGeneralError(message?:unknown) {\n let error = this.I18n.t('js.error.internal');\n\n if (typeof (message) === 'string' || _.has(message, 'toString')) {\n error += ' ' + (message as any).toString();\n }\n\n this.NotificationsService.addError(error);\n }\n\n public showEditingBlockedError(attribute:string) {\n this.NotificationsService.addError(this.I18n.t(\n 'js.hal.error.edit_prohibited',\n {attribute: attribute}\n ));\n }\n\n protected showCustomError(errorResource:any, resource:HalResource) {\n\n if (errorResource.errorIdentifier === 'urn:openproject-org:api:v3:errors:PropertyFormatError') {\n\n let schema = this.schemaCache.of(resource).ofProperty(errorResource.details.attribute);\n let attributeName = schema.name;\n let attributeType = schema.type.toLowerCase();\n let i18nString = 'js.hal.error.format.' + attributeType;\n\n if (this.I18n.lookup(i18nString) === undefined) {\n return false;\n }\n\n this.NotificationsService.addError(this.I18n.t(i18nString,\n {attribute: attributeName}));\n\n return true;\n }\n return false;\n }\n\n protected showApiErrorMessages(errorResource:any) {\n let messages = errorResource.errorMessages;\n\n if (messages.length > 1) {\n this.NotificationsService.addError('', messages);\n } else {\n this.NotificationsService.addError(messages[0]);\n }\n\n return true;\n }\n}\n","import {AfterViewInit, Directive, ElementRef} from \"@angular/core\";\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {OpContextMenuHandler} from \"core-components/op-context-menu/op-context-menu-handler\";\nimport {OpContextMenuItem} from \"core-components/op-context-menu/op-context-menu.types\";\n\n@Directive({\n selector: '[opContextMenuTrigger]'\n})\nexport class OpContextMenuTrigger extends OpContextMenuHandler implements AfterViewInit {\n protected $element:JQuery;\n protected items:OpContextMenuItem[] = [];\n\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService) {\n super(opContextMenu);\n }\n\n ngAfterViewInit():void {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n // Open by clicking the element\n this.$element.on('click', (evt:JQuery.TriggeredEvent) => {\n evt.preventDefault();\n evt.stopPropagation();\n\n // When clicking the same trigger twice, close the element instead.\n if (this.opContextMenu.isActive(this)) {\n this.opContextMenu.close();\n return false;\n }\n\n this.open(evt);\n return false;\n });\n\n // Open with keyboard combination as well\n Mousetrap(this.$element[0]).bind('shift+alt+f10', (evt:any) => {\n this.open(evt);\n });\n }\n\n /**\n * Positioning args for jquery-ui position.\n *\n * @param {Event} openerEvent\n */\n public positionArgs(openerEvent:JQuery.TriggeredEvent) {\n return {\n my: 'left top',\n at: 'left bottom',\n of: this.$element,\n collision: 'flipfit'\n };\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport namespace OpenprojectHalModuleHelpers {\n export function lazy(obj:HalResource,\n property:string,\n getter:{ ():any },\n setter?:{ (value:any):void }):void {\n\n if (_.isObject(obj)) {\n let done = false;\n let value:any;\n let config:any = {\n get() {\n if (!done) {\n value = getter();\n done = true;\n }\n return value;\n },\n set: ():void => undefined,\n\n configurable: true,\n enumerable: true\n };\n\n if (setter) {\n config.set = (val:any) => {\n value = setter(val);\n done = true;\n };\n }\n\n Object.defineProperty(obj, property, config);\n }\n }\n}\n","import {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {OpenprojectHalModuleHelpers} from 'core-app/modules/hal/helpers/lazy-accessor';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {HalLink} from 'core-app/modules/hal/hal-link/hal-link';\n\nimport * as ObservableArray from 'observable-array';\n\ninterface HalSource {\n _links:any;\n _embedded:any;\n _type?:string;\n type?:any;\n}\n\nexport function cloneHalResourceCollection(values:T[]|undefined):T[] {\n if (_.isNil(values)) {\n return [];\n } else {\n return values.map(v => v.$copy());\n }\n}\n\nexport function cloneHalResource(value:T|undefined):T|undefined {\n if (_.isNil(value)) {\n return value;\n } else {\n return value.$copy();\n }\n}\n\nexport function initializeHalProperties(halResourceService:HalResourceService, halResource:T) {\n setSource();\n setupLinks();\n setupEmbedded();\n proxyProperties();\n setLinksAsProperties();\n setEmbeddedAsProperties();\n\n function setSource() {\n if (!halResource.$source._links) {\n halResource.$source._links = {};\n }\n\n if (!halResource.$source._links.self) {\n halResource.$source._links.self = { href: null };\n }\n }\n\n function asHalResource(value?:HalSource, loaded:boolean = true):HalResource|HalSource|undefined|null {\n if (_.isNil(value)) {\n return value;\n }\n\n if (value._links || value._embedded || value._type) {\n return halResourceService.createHalResource(value, loaded);\n }\n\n return value;\n }\n\n function proxyProperties() {\n halResource.$embeddableKeys().forEach((property:any) => {\n Object.defineProperty(halResource, property, {\n get() {\n const value = halResource.$source[property];\n return asHalResource(value, true);\n },\n\n set(value) {\n halResource.$source[property] = value;\n },\n\n enumerable: true,\n configurable: true\n });\n });\n }\n\n function setLinksAsProperties() {\n halResource.$linkableKeys().forEach((linkName:string) => {\n OpenprojectHalModuleHelpers.lazy(halResource, linkName,\n () => {\n const link:any = halResource.$links[linkName].$link || halResource.$links[linkName];\n\n if (Array.isArray(link)) {\n var items = link.map(item => halResourceService.createLinkedResource(halResource,\n linkName,\n item.$link));\n var property:HalResource[] = new ObservableArray(...items).on('change', () => {\n property.forEach(item => {\n if (!item.$link) {\n property.splice(property.indexOf(item), 1);\n }\n });\n\n halResource.$source._links[linkName] = property.map(item => item.$link);\n });\n\n return property;\n }\n\n if (link.href) {\n if (link.method !== 'get') {\n return HalLink.fromObject(halResourceService, link).$callable();\n }\n\n return halResourceService.createLinkedResource(halResource, linkName, link);\n }\n\n return null;\n },\n (val:any) => setter(val, linkName)\n );\n });\n }\n\n function setEmbeddedAsProperties() {\n if (!halResource.$source._embedded) {\n return;\n }\n\n Object.keys(halResource.$source._embedded).forEach(name => {\n OpenprojectHalModuleHelpers.lazy(halResource,\n name,\n () => halResource.$embedded[name],\n (val:any) => setter(val, name));\n });\n }\n\n function setupProperty(name:string, callback:(element:any) => any) {\n const instanceName = '$' + name;\n const sourceName = '_' + name;\n const sourceObj:any = halResource.$source[sourceName];\n\n if (_.isObject(sourceObj)) {\n Object.keys(sourceObj).forEach(propName => {\n OpenprojectHalModuleHelpers.lazy((halResource)[instanceName],\n propName,\n () => callback((sourceObj as any)[propName]));\n });\n }\n }\n\n function setupLinks() {\n setupProperty('links',\n (link) => {\n if (Array.isArray(link)) {\n return link.map(l => HalLink.fromObject(halResourceService, l).$callable());\n } else {\n return HalLink.fromObject(halResourceService, link).$callable();\n }\n });\n }\n\n function setupEmbedded() {\n setupProperty('embedded', (element:any) => {\n\n if (Array.isArray(element)) {\n return element.map((source) => asHalResource(source, true));\n }\n\n if (_.isObject(element)) {\n _.each(element, (child:any, name:string) => {\n if (child && (child._embedded || child._links)) {\n OpenprojectHalModuleHelpers.lazy(element as any,\n name,\n () => asHalResource(child, true));\n }\n });\n }\n\n return asHalResource(element, true);\n });\n }\n\n function setter(val:HalResource[]|HalResource|{ href?:string }, linkName:string) {\n const isArray = Array.isArray(val);\n\n if (!val) {\n halResource.$source._links[linkName] = { href: null };\n } else if (isArray) {\n halResource.$source._links[linkName] = (val as HalResource[]).map((el:any) => {\n return { href: el.href };\n });\n } else if (val.hasOwnProperty('$link')) {\n const link = (val as HalResource).$link;\n\n if (link.href) {\n halResource.$source._links[linkName] = link;\n }\n } else if ('href' in val) {\n halResource.$source._links[linkName] = { href: val.href };\n }\n\n if (halResource.$embedded && halResource.$embedded[linkName]) {\n halResource.$embedded[linkName] = val;\n\n if (isArray) {\n halResource.$source._embedded[linkName] = (val as HalResource[]).map(el => el.$source);\n } else {\n halResource.$source._embedded[linkName] = _.get(val, '$source', val);\n }\n }\n\n return val;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {StateService, Transition, TransitionService} from '@uirouter/core';\nimport {ReplaySubject} from 'rxjs';\nimport {Injectable} from \"@angular/core\";\n\n@Injectable({ providedIn: 'root' })\nexport class KeepTabService {\n protected currentTab:string = 'overview';\n\n protected subject = new ReplaySubject<{ [tab:string]:string; }>(1);\n\n constructor(protected $state:StateService,\n protected $transitions:TransitionService) {\n\n this.updateTabs();\n $transitions.onSuccess({}, (transition:Transition) => {\n this.updateTabs(transition.to().name);\n });\n }\n\n public get observable() {\n return this.subject;\n }\n\n /**\n * Return the last active tab.\n */\n public get lastActiveTab():string {\n if (this.isCurrentState('show')) {\n return this.currentShowTab;\n }\n\n return this.currentDetailsTab;\n }\n\n public get currentShowState():string {\n return 'work-packages.show.' + this.currentShowTab;\n }\n\n public get currentDetailsState():string {\n return 'work-packages.partitioned.list.details.' + this.currentDetailsTab;\n }\n\n public get currentDetailsSubState():string {\n return '.details.' + this.currentDetailsTab;\n }\n\n public isDetailsState(stateName:string) {\n return !!stateName && stateName.includes('.details');\n }\n\n public get currentShowTab():string {\n // Show view doesn't have overview\n // use activity instead\n if (this.currentTab === 'overview') {\n return 'activity';\n }\n\n return this.currentTab;\n }\n\n public get currentDetailsTab():string {\n return this.currentTab;\n }\n\n protected notify() {\n // Notify when updated\n this.subject.next({\n active: this.lastActiveTab,\n show: this.currentShowState,\n details: this.currentDetailsState\n });\n }\n\n protected updateTab(stateName:string) {\n if (this.isCurrentState(stateName)) {\n const current = this.$state.current.name as string;\n this.currentTab = (current.split('.') as any[]).pop();\n\n this.notify();\n }\n }\n\n protected isCurrentState(stateName:string):boolean {\n if (stateName === 'show') {\n return this.$state.includes('work-packages.show.*');\n }\n if (stateName === 'details') {\n return this.$state.includes('**.details.*');\n }\n\n return false;\n }\n\n public updateTabs(stateName?:string) {\n // Ignore the switch from show#activity to details#activity\n // and show details#overview instead\n if (stateName === 'work-packages.show.activity') {\n this.currentTab = 'overview';\n return this.notify();\n }\n this.updateTab('show');\n this.updateTab('details');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {QueryResource, TimelineLabels, TimelineZoomLevel} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {input} from 'reactivestates';\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {WorkPackageTimelineState} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-timeline\";\nimport {zoomLevelOrder} from \"core-components/wp-table/timeline/wp-timeline\";\n\n@Injectable()\nexport class WorkPackageViewTimelineService extends WorkPackageQueryStateService {\n\n /** Remember the computed zoom level to correct zooming after leaving autozoom */\n public appliedZoomLevel$ = input('auto');\n\n public constructor(protected readonly querySpace:IsolatedQuerySpace) {\n super(querySpace);\n }\n\n public valueFromQuery(query:QueryResource) {\n return {\n ...this.defaultState,\n visible: query.timelineVisible,\n zoomLevel: query.timelineZoomLevel,\n labels: query.timelineLabels\n };\n }\n\n public set appliedZoomLevel(val:TimelineZoomLevel) {\n this.appliedZoomLevel$.putValue(val);\n }\n\n public get appliedZoomLevel() {\n return this.appliedZoomLevel$.value!;\n }\n\n public hasChanged(query:QueryResource) {\n const visibilityChanged = this.isVisible !== query.timelineVisible;\n const zoomLevelChanged = this.zoomLevel !== query.timelineZoomLevel;\n const labelsChanged = !_.isEqual(this.current.labels, query.timelineLabels);\n\n return visibilityChanged || zoomLevelChanged || labelsChanged;\n }\n\n public applyToQuery(query:QueryResource) {\n query.timelineVisible = this.isVisible;\n query.timelineZoomLevel = this.zoomLevel;\n query.timelineLabels = this.current.labels;\n\n return false;\n }\n\n public toggle() {\n let currentState = this.current;\n this.setVisible(!currentState.visible);\n }\n\n public setVisible(value:boolean) {\n this.updatesState.putValue({...this.current, visible: value});\n }\n\n public get isVisible() {\n return this.current.visible;\n }\n\n public get zoomLevel() {\n return this.current.zoomLevel;\n }\n\n public get labels() {\n if (_.isEmpty(this.current.labels)) {\n return this.defaultLabels;\n }\n\n return this.current.labels;\n }\n\n public updateLabels(labels:TimelineLabels) {\n this.modify({ labels: labels });\n }\n\n public getNormalizedLabels(workPackage:WorkPackageResource) {\n let labels:TimelineLabels = this.defaultLabels;\n\n _.each(this.current.labels, (attribute:string | null, positionAsString:string) => {\n // RR: Lodash typings declare the position as string. However, it is save to cast\n // to `keyof TimelineLabels` because `this.current.labels` is of type TimelineLabels.\n const position:keyof TimelineLabels = positionAsString as keyof TimelineLabels;\n\n // Set to null to explicitly disable\n if (attribute === '') {\n labels[position] = null;\n } else {\n labels[position] = attribute;\n }\n });\n\n return labels;\n }\n\n public setZoomLevel(level:TimelineZoomLevel) {\n this.modify({ zoomLevel: level });\n }\n\n public updateZoomWithDelta(delta:number):void {\n let level = this.current.zoomLevel;\n if (level !== 'auto') {\n return this.applyZoomLevel(level, delta);\n }\n\n const applied = this.appliedZoomLevel;\n if (applied && applied !== 'auto') {\n // When we have a real zoom value, use delta on that one\n this.applyZoomLevel(applied, delta);\n } else {\n // Use the maximum zoom value\n const target = delta < 0 ? 'days' : 'years';\n this.setZoomLevel(target);\n }\n }\n\n public isAutoZoom():boolean {\n return this.current.zoomLevel === 'auto';\n }\n\n public enableAutozoom() {\n this.modify({ zoomLevel: \"auto\" });\n }\n\n public get current():WorkPackageTimelineState {\n return this.lastUpdatedState.getValueOr(this.defaultState);\n }\n\n /**\n * Modify the state, updating with parts of properties\n * @param update\n */\n private modify(update:Partial) {\n this.update({ ...this.current, ...update } as WorkPackageTimelineState);\n }\n\n /**\n * Apply a zoom level\n *\n * @param level Any zoom level except auto.\n * @param delta The delta (e.g., 1, -1) to apply.\n */\n private applyZoomLevel(level:Exclude, delta:number) {\n let idx = zoomLevelOrder.indexOf(level);\n idx += delta;\n\n if (idx >= 0 && idx < zoomLevelOrder.length) {\n this.setZoomLevel(zoomLevelOrder[idx]);\n }\n }\n\n private get defaultLabels():TimelineLabels {\n return {\n left: '',\n right: '',\n farRight: 'subject'\n };\n }\n\n private get defaultState():WorkPackageTimelineState {\n return {\n zoomLevel: 'auto',\n visible: false,\n labels: this.defaultLabels\n };\n }\n}\n","import { Injectable } from '@angular/core';\n\n@Injectable({ providedIn: 'root' })\nexport class ColorsService {\n public toHsl(value:string) {\n return `hsl(${this.valueHash(value)}, 50%, 50%)`;\n }\n\n public toHsla(value:string, opacity:number) {\n return `hsla(${this.valueHash(value)}, 50%, 50%, ${opacity}%)`;\n }\n\n protected valueHash(value:string) {\n let hash = 0;\n for (let i = 0; i < value.length; i++) {\n hash = value.charCodeAt(i) + ((hash << 5) - hash);\n }\n\n return hash % 360;\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {Component, Input} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\n@Component({\n selector: 'wp-details-toolbar',\n templateUrl: './wp-details-toolbar.html'\n})\nexport class WorkPackageSplitViewToolbarComponent {\n @Input('workPackage') workPackage:WorkPackageResource;\n\n public text = {\n button_more: this.I18n.t('js.button_more')\n }\n\nconstructor(readonly I18n:I18nService,\n readonly halEditing:HalResourceEditingService) {}\n}\n","
    \n
    \n
      \n \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n \n
    • \n
    • \n \n \n
    • \n
    • \n \n \n
    • \n
    • \n \n \n
    • \n
    \n
    \n
    \n \n \n\n \n\n \n
    \n \n \n\n
    \n \n
    \n
    \n\n
    \n
    \n
    \n\n
    \n \n
    \n\n
    \n \n
    \n
    \n","
    \n \n \n\n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component, Injector, OnInit} from '@angular/core';\nimport {StateService} from '@uirouter/core';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {States} from \"core-components/states.service\";\nimport {FirstRouteService} from \"core-app/modules/router/first-route-service\";\nimport {KeepTabService} from \"core-components/wp-single-view-tabs/keep-tab/keep-tab.service\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageSingleViewBase} from \"core-app/modules/work_packages/routing/wp-view-base/work-package-single-view.base\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {BackRoutingService} from \"core-app/modules/common/back-routing/back-routing.service\";\n\n@Component({\n templateUrl: './wp-split-view.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-split-view-entry',\n providers: [\n { provide: HalResourceNotificationService, useClass: WorkPackageNotificationService }\n ]\n})\nexport class WorkPackageSplitViewComponent extends WorkPackageSingleViewBase implements OnInit {\n\n /** Reference to the base route e.g., work-packages.partitioned.list or bim.partitioned.split */\n private baseRoute:string = this.$state.current.data.baseRoute;\n\n constructor(public injector:Injector,\n public states:States,\n public firstRoute:FirstRouteService,\n public keepTab:KeepTabService,\n public wpTableSelection:WorkPackageViewSelectionService,\n public wpTableFocus:WorkPackageViewFocusService,\n readonly $state:StateService,\n readonly backRouting:BackRoutingService) {\n super(injector, $state.params['workPackageId']);\n }\n\n ngOnInit():void {\n this.observeWorkPackage();\n\n let wpId = this.$state.params['workPackageId'];\n let focusedWP = this.wpTableFocus.focusedWorkPackage;\n\n if (!focusedWP) {\n // Focus on the work package if we're the first route\n const isFirstRoute = this.firstRoute.name === `${this.baseRoute}.details.overview`;\n const isSameID = this.firstRoute.params && wpId === this.firstRoute.params.workPackageI;\n this.wpTableFocus.updateFocus(wpId, (isFirstRoute && isSameID));\n } else {\n this.wpTableFocus.updateFocus(wpId, false);\n }\n\n if (this.wpTableSelection.isEmpty) {\n this.wpTableSelection.setRowState(wpId, true);\n }\n\n this.wpTableFocus.whenChanged()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(newId => {\n const idSame = wpId.toString() === newId.toString();\n if (!idSame && this.$state.includes(`${this.baseRoute}.details`)) {\n this.$state.go(\n (this.$state.current.name as string),\n { workPackageId: newId, focus: false }\n );\n }\n });\n }\n\n\n public close() {\n this.$state.go(this.baseRoute, this.$state.params);\n }\n\n public switchToFullscreen() {\n this.$state.go(this.keepTab.currentShowState, this.$state.params);\n }\n\n public get shouldFocus() {\n return this.$state.params.focus === true;\n }\n\n public showBackButton():boolean {\n return this.baseRoute.includes('bim');\n }\n\n public backToList() {\n this.backRouting.goToBaseState();\n }\n\n protected initializeTexts() {\n super.initializeTexts();\n this.text.closeDetailsView = this.I18n.t('js.button_close_details');\n this.text.goTofullScreen = this.I18n.t('js.work_packages.message_successful_show_in_fullscreen');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {cssClassCustomOption, DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class ResourcesDisplayField extends DisplayField {\n public isEmpty():boolean {\n return _.isEmpty(this.value);\n }\n\n public get value() {\n let cf = this.resource[this.name];\n if (this.schema && cf) {\n\n if (cf.elements) {\n return cf.elements.map((e:any) => e.name);\n } else if (cf.map) {\n return cf.map((e:any) => e.name);\n } else if (cf.name) {\n return [cf.name];\n } else {\n return [\"error: \" + JSON.stringify(cf)];\n }\n }\n\n return [];\n }\n\n public render(element:HTMLElement, displayText:string):void {\n const values = this.value;\n element.innerHTML = '';\n element.setAttribute('title', values.join(', '));\n\n if (values.length === 0) {\n this.renderEmpty(element);\n } else {\n this.renderValues(values, element);\n }\n }\n\n /**\n * Renders at most the first two values, followed by a badge indicating\n * the total count.\n */\n protected renderValues(values:any[], element:HTMLElement) {\n const content = document.createDocumentFragment();\n const abridged = this.optionDiv(this.valueAbridged(values));\n\n content.appendChild(abridged);\n\n if (values.length > 2) {\n const badge = this.optionDiv(values.length.toString(), 'badge', '-secondary');\n content.appendChild(badge);\n }\n\n element.appendChild(content);\n }\n\n /**\n * Build .custom-option div/span nodes with the given text\n */\n protected optionDiv(text:string, ...classes:string[]) {\n const div = document.createElement('div');\n const span = document.createElement('span');\n div.classList.add(cssClassCustomOption);\n span.classList.add(...classes);\n span.textContent = text;\n\n div.appendChild(span);\n\n return div;\n }\n\n /**\n * Return the first two joined values, if any.\n */\n protected valueAbridged(values:any[]) {\n const valueForDisplay = _.take(values, 2);\n\n if (values.length > 2) {\n valueForDisplay.push('... ');\n }\n\n return valueForDisplay.join(', ');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Injectable} from \"@angular/core\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageViewHierarchyIdentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy-indentation.service\";\nimport {WorkPackageViewDisplayRepresentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\n\nexport type WorkPackageAction = {\n text:string;\n key:string;\n icon?:string;\n indexBy?:(actions:WorkPackageAction[]) => number,\n link?:string;\n href?:string;\n};\n\n@Injectable()\nexport class WorkPackageContextMenuHelperService {\n\n private BULK_ACTIONS = [\n {\n text: I18n.t('js.work_packages.bulk_actions.edit'),\n key: 'edit',\n link: 'update',\n href: this.PathHelper.staticBase + '/work_packages/bulk/edit'\n },\n {\n text: I18n.t('js.work_packages.bulk_actions.move'),\n key: 'move',\n link: 'move',\n href: this.PathHelper.staticBase + '/work_packages/move/new'\n },\n {\n text: I18n.t('js.work_packages.bulk_actions.copy'),\n key: 'copy',\n link: 'copy',\n href: this.PathHelper.staticBase + '/work_packages/move/new?copy=true'\n },\n {\n text: I18n.t('js.work_packages.bulk_actions.delete'),\n key: 'delete',\n link: 'delete',\n href: this.PathHelper.staticBase + '/work_packages/bulk?_method=delete'\n }\n ];\n\n constructor(private HookService:HookService,\n private UrlParamsHelper:UrlParamsHelperService,\n private wpViewRepresentation:WorkPackageViewDisplayRepresentationService,\n private wpViewTimeline:WorkPackageViewTimelineService,\n private wpViewIndent:WorkPackageViewHierarchyIdentationService,\n private PathHelper:PathHelperService) {\n }\n\n public getPermittedActionLinks(workPackage:WorkPackageResource, permittedActionConstants:any, allowSplitScreenActions:boolean):WorkPackageAction[] {\n let singularPermittedActions:any[] = [];\n\n let allowedActions = this.getAllowedActions(workPackage, permittedActionConstants);\n\n allowedActions = allowedActions.concat(this.getAllowedParentActions(workPackage));\n\n allowedActions = allowedActions.concat(this.getAllowedRelationActions(workPackage, allowSplitScreenActions));\n\n _.each(allowedActions, (allowedAction) => {\n singularPermittedActions.push({\n key: allowedAction.key,\n text: allowedAction.text,\n icon: allowedAction.icon,\n link: allowedAction.link ? workPackage[allowedAction.link].href : undefined\n });\n });\n\n return singularPermittedActions;\n }\n\n public getIntersectOfPermittedActions(workPackages:any) {\n let bulkPermittedActions:any = [];\n\n let permittedActions = _.filter(this.BULK_ACTIONS, (action:any) => {\n return _.every(workPackages, (workPackage:WorkPackageResource) => {\n return this.getAllowedActions(workPackage, [action]).length >= 1;\n });\n });\n\n _.each(permittedActions, (permittedAction:any) => {\n bulkPermittedActions.push({\n key: permittedAction.key,\n text: permittedAction.text,\n link: this.getBulkActionLink(permittedAction, workPackages)\n });\n });\n\n return bulkPermittedActions;\n }\n\n public getBulkActionLink(action:any, workPackages:any) {\n let workPackageIdParams = {\n 'ids[]': workPackages.map(function(wp:any) {\n return wp.id;\n })\n };\n let serializedIdParams = this.UrlParamsHelper.buildQueryString(workPackageIdParams);\n\n let linkAndQueryString = action.href.split('?');\n let link = linkAndQueryString.shift();\n let queryParts = linkAndQueryString.concat(new Array(serializedIdParams));\n\n return link + '?' + queryParts.join('&');\n }\n\n private getAllowedActions(workPackage:WorkPackageResource, actions:WorkPackageAction[]):WorkPackageAction[] {\n let allowedActions:WorkPackageAction[] = [];\n\n _.each(actions, (action) => {\n if (action.link && workPackage.hasOwnProperty(action.link)) {\n action.text = action.text || I18n.t('js.button_' + action.key);\n allowedActions.push(action);\n }\n });\n\n _.each(this.HookService.call('workPackageTableContextMenu'), (action) => {\n if (workPackage.hasOwnProperty(action.link)) {\n let index = action.indexBy ? action.indexBy(allowedActions) : allowedActions.length;\n allowedActions.splice(index, 0, action);\n }\n });\n\n return allowedActions;\n }\n\n private getAllowedParentActions(workPackage:WorkPackageResource) {\n let actions:WorkPackageAction[] = [];\n\n // Do not add these actions unless we're in the table\n if (!this.wpViewRepresentation.isList) {\n return [];\n }\n\n // Can only outdent this item if it has ancestors\n if (this.wpViewIndent.canOutdent(workPackage)) {\n actions.push({\n key: 'hierarchy-outdent',\n icon: 'icon-paragraph-left',\n text: I18n.t(\"js.relation_buttons.hierarchy_outdent\")\n });\n }\n\n // Can only indent if not first and immediate predecessor is not the parent\n if (this.wpViewIndent.canIndent(workPackage)) {\n actions.push({\n key: 'hierarchy-indent',\n icon: 'icon-paragraph-right',\n text: I18n.t(\"js.relation_buttons.hierarchy_indent\")\n });\n }\n\n return actions;\n }\n\n private getAllowedRelationActions(workPackage:WorkPackageResource, allowSplitScreenActions:boolean) {\n let allowedActions:WorkPackageAction[] = [];\n\n if (workPackage.addRelation && this.wpViewTimeline.isVisible) {\n allowedActions.push({\n key: \"relation-precedes\",\n text: I18n.t(\"js.relation_buttons.add_predecessor\"),\n link: \"addRelation\"\n });\n allowedActions.push({\n key: \"relation-follows\",\n text: I18n.t(\"js.relation_buttons.add_follower\"),\n link: \"addRelation\"\n });\n }\n\n if (!!workPackage.addChild && allowSplitScreenActions) {\n allowedActions.push({\n key: \"relation-new-child\",\n text: I18n.t(\"js.relation_buttons.add_new_child\"),\n link: \"addChild\"\n });\n }\n\n return allowedActions;\n }\n\n\n public getPermittedActions(workPackages:WorkPackageResource[], permittedActionConstants:any, allowSplitScreenActions:boolean):WorkPackageAction[] {\n if (workPackages.length === 1) {\n return this.getPermittedActionLinks(workPackages[0], permittedActionConstants, allowSplitScreenActions);\n } else {\n return this.getIntersectOfPermittedActions(workPackages);\n }\n }\n}\n","\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nexport const queryColumnTypes = {\n PROPERTY: 'QueryColumn::Property',\n RELATION_OF_TYPE: 'QueryColumn::RelationOfType',\n RELATION_TO_TYPE: 'QueryColumn::RelationToType',\n};\n\nexport function isRelationColumn(column:QueryColumn) {\n const relationTypes = [queryColumnTypes.RELATION_TO_TYPE, queryColumnTypes.RELATION_OF_TYPE];\n return relationTypes.indexOf(column._type) >= 0;\n}\n\n/**\n * A reference to a query column object as returned from the API.\n */\nexport interface QueryColumn extends HalResource {\n id:string;\n name:string;\n custom_field?:any;\n _links?: {\n self:{ href:string, title:string };\n };\n}\n\nexport interface TypeRelationQueryColumn extends QueryColumn {\n type:{ href: string, name:string },\n _links?: {\n self:{ href:string, title:string },\n type:{ href:string, title:string }\n }\n}\n\nexport interface RelationQueryColumn extends QueryColumn {\n relationType: string;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input} from '@angular/core';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\n\n@Component({\n selector: 'op-date-time',\n template: `\n \n \n  \n \n \n `\n})\nexport class OpDateTimeComponent {\n\n @Input('dateTimeValue') dateTimeValue:any;\n\n public date:any;\n public time:any;\n\n constructor(readonly timezoneService:TimezoneService) {\n }\n\n ngOnInit() {\n var c = this.timezoneService.formattedDatetimeComponents(this.dateTimeValue);\n this.date = c[0];\n this.time = c[1];\n }\n}\n","export const enterpriseEditionUrl = \"https://www.openproject.org/enterprise-edition/?op_edtion=community-edition\";\n\nexport const enterpriseDemoUrl = \"https://www.openproject.org/enterprise-demo/\";\n","export function randomString(length:number = 16) {\n let pattern = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let random = '';\n for (let _element of new Array(length)) {\n random += pattern.charAt(Math.floor(Math.random() * pattern.length));\n }\n return random;\n}\n","export namespace Highlighting {\n export function backgroundClass(property:string, id:string|number) {\n return `__hl_background_${property}_${id}`;\n }\n\n export function inlineClass(property:string, id:string|number) {\n return `__hl_inline_${property}_${id}`;\n }\n\n export function colorClass(highlightColorTextInline:boolean, id:string|number) {\n if (highlightColorTextInline) {\n return `__hl_inline_color_${id}_text`;\n } else {\n return `__hl_inline_color_${id}_dot`;\n }\n }\n\n /**\n * Given the difference from today (negative = n days in the past),\n * output the fixed overdue classes\n * @param diff\n */\n export function overdueDate(diff:number):string {\n if (diff === 0) {\n return '__hl_date_due_today';\n }\n // At least one day\n if (diff <= -1) {\n return '__hl_date_overdue';\n }\n\n return '__hl_date_not_overdue';\n }\n\n export function isBright(styles:CSSStyleDeclaration, property:string, id:string|number) {\n const variable = `--hl-${property}-${id}-dark`;\n return styles.getPropertyValue(variable) !== '';\n }\n}\n","import { AfterContentInit, Directive, ElementRef, Input } from '@angular/core';\nimport {FocusHelperService} from \"core-app/modules/common/focus/focus-helper\";\n\n@Directive({\n selector: '[autoFocus]'\n})\nexport class AutofocusDirective implements AfterContentInit {\n @Input('autoFocus-condition') public condition:boolean = true;\n\n public constructor(private el:ElementRef,\n private focusHelper:FocusHelperService) {\n\n }\n\n public ngAfterContentInit() {\n if (!this.condition) {\n return;\n }\n\n setTimeout(() => {\n this.focusHelper.focusElement(jQuery(this.el.nativeElement));\n }, 100);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport interface CustomActionResourceLinks {\n self():Promise;\n executeImmediately(payload:any):Promise;\n}\n\nexport class CustomActionResource extends HalResource {\n public description:string;\n}\n\nexport interface CustomActionResource extends CustomActionResourceLinks {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nexport type FilterOperator = '='|'!*'|'!'|'~'|'o'|'>t-'|'<>d'|'**'|'ow' ;\nexport const FalseValue = ['f'];\nexport const TrueValue = ['t'];\n\nexport interface ApiV3FilterValue {\n operator:FilterOperator;\n values:unknown[];\n}\n\nexport interface ApiV3Filter {\n [filter:string]:ApiV3FilterValue;\n}\n\nexport type ApiV3FilterObject = { [filter:string]:ApiV3FilterValue };\n\nexport class ApiV3FilterBuilder {\n\n private filterMap:ApiV3FilterObject = {};\n\n public add(name:string, operator:FilterOperator, values:unknown[]|boolean):this {\n if (values === true) {\n values = TrueValue;\n }\n\n if (values === false) {\n values = FalseValue;\n }\n\n this.filterMap[name] = {\n operator: operator,\n values: values\n };\n\n return this;\n }\n\n /**\n * Remove from the filter set\n * @param name\n */\n public remove(name:string) {\n delete this.filterMap[name];\n }\n\n /**\n * Turns the array-map style of query filters to an actual object\n *\n * @param filters APIv3 filter array [ {foo: { operator: '=', val: ['bar'] } }, ...]\n * @return A map { foo: { operator: '=', val: ['bar'] } , ... }\n */\n public toFilterObject(filters:ApiV3Filter[]):ApiV3FilterObject {\n let map:ApiV3FilterObject = {};\n\n filters.forEach((item:ApiV3Filter) => {\n _.each(item, (val:ApiV3FilterValue, filter:string) => {\n map[filter] = val;\n });\n });\n\n return map;\n }\n\n /**\n * Merges the other filters into the current set,\n * replacing them if the are duplicated.\n *\n * @param filters\n * @param only Only apply the given filters\n */\n public merge(filters:ApiV3Filter[], ...only:string[]) {\n const toAdd:ApiV3FilterObject = _.pickBy(\n this.toFilterObject(filters),\n (_, filter:string) => only.includes(filter)\n );\n\n this.filterMap = {\n ...this.filterMap,\n ...toAdd\n };\n }\n\n public get filters():ApiV3Filter[] {\n let filters:ApiV3Filter[] = [];\n _.each(this.filterMap, (val:ApiV3FilterValue, filter:string) => {\n filters.push({ [filter]: val });\n });\n\n return filters;\n }\n\n public toJson():string {\n return JSON.stringify(this.filters);\n }\n\n public toParams(mergeParams:{ [key:string]:string } = {}):string {\n let transformedFilters:string[] = [];\n\n transformedFilters = this.filters.map((filter:ApiV3Filter) => {\n return this.serializeFilter(filter);\n });\n\n let params = { filters: `[${transformedFilters.join(\",\")}]`, ...mergeParams };\n return new URLSearchParams(params).toString();\n }\n\n public clone() {\n let newFilters = new ApiV3FilterBuilder();\n\n this.filters.forEach(filter => {\n Object.keys(filter).forEach(name => {\n newFilters.add(name, filter[name].operator, filter[name].values);\n });\n });\n\n return newFilters;\n }\n\n private serializeFilter(filter:ApiV3Filter) {\n let transformedFilter:string;\n let keys:Array;\n\n keys = Object.keys(filter);\n\n let typeName = keys[0];\n let operatorAndValues:any = filter[typeName];\n\n transformedFilter = `{\"${typeName}\":{\"operator\":\"${operatorAndValues['operator']}\",\"values\":[${operatorAndValues['values']\n .map((val:any) => this.serializeFilterValue(val))\n .join(',')}]}}`;\n\n return transformedFilter;\n }\n\n private serializeFilterValue(filterValue:any) {\n return `\"${filterValue}\"`;\n }\n}\n\nexport function buildApiV3Filter(name:string, operator:FilterOperator, values:any) {\n return new ApiV3FilterBuilder().add(name, operator, values);\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Directive, ViewChild} from \"@angular/core\";\nimport {WorkPackageEmbeddedTableComponent} from \"core-components/wp-table/embedded/wp-embedded-table.component\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Directive()\nexport abstract class WorkPackageRelationQueryBase extends UntilDestroyedMixin {\n public workPackage:WorkPackageResource;\n\n /** Input is either a query resource, or directly query props */\n public query:QueryResource|Object;\n\n /** Query props are derived from the query resource, if any */\n public queryProps:Object;\n\n /** Whether this section should be hidden completely (due to missing permissions e.g.) */\n public hidden:boolean = false;\n\n /** Reference to the embedded table instance */\n @ViewChild('embeddedTable') protected embeddedTable:WorkPackageEmbeddedTableComponent;\n\n constructor(protected queryUrlParamsHelper:UrlParamsHelperService) {\n super();\n }\n\n /**\n * Request to refresh the results of the embedded table\n */\n public refreshTable() {\n this.embeddedTable.isInitialized && this.embeddedTable.loadQuery(true, false);\n }\n\n /**\n * Special handling for query loading when a project filter is involved.\n *\n * Ensure that at least one project was visible to the user or otherwise,\n * hide the creation from them.\n * cf. OP#30106\n * @param query\n */\n public handleQueryLoaded(loaded:QueryResource) {\n // We only handle loaded queries\n if (!(this.query instanceof QueryResource)) {\n return;\n }\n\n const filtersLength = this.projectValuesCount(this.query);\n const loadedFiltersLength = this.projectValuesCount(loaded);\n\n // Does the default have a project filter, but the other does not?\n if (filtersLength !== null && loadedFiltersLength === null) {\n this.hidden = true;\n }\n\n // Has a project filter been reduced to zero elements?\n if (filtersLength && loadedFiltersLength && filtersLength > 0 && loadedFiltersLength === 0) {\n this.hidden = true;\n }\n }\n\n /**\n * Get the filters of the query props\n */\n protected projectValuesCount(query:QueryResource):number|null {\n const project = query.filters.find(f => f.id === 'project');\n return project ? project.values.length : null;\n }\n\n /**\n * Set up the query props from input\n */\n protected buildQueryProps() {\n if (this.query instanceof QueryResource) {\n return this.queryUrlParamsHelper.buildV3GetQueryFromQueryResource(\n this.query,\n { valid_subset: true },\n { id: this.workPackage.id! }\n );\n } else {\n return this.query;\n }\n }\n}\n","var map = {\n\t\"./af\": \"K/tc\",\n\t\"./af.js\": \"K/tc\",\n\t\"./ar\": \"jnO4\",\n\t\"./ar-dz\": \"o1bE\",\n\t\"./ar-dz.js\": \"o1bE\",\n\t\"./ar-kw\": \"Qj4J\",\n\t\"./ar-kw.js\": \"Qj4J\",\n\t\"./ar-ly\": \"HP3h\",\n\t\"./ar-ly.js\": \"HP3h\",\n\t\"./ar-ma\": \"CoRJ\",\n\t\"./ar-ma.js\": \"CoRJ\",\n\t\"./ar-sa\": \"gjCT\",\n\t\"./ar-sa.js\": \"gjCT\",\n\t\"./ar-tn\": \"bYM6\",\n\t\"./ar-tn.js\": \"bYM6\",\n\t\"./ar.js\": \"jnO4\",\n\t\"./az\": \"SFxW\",\n\t\"./az.js\": \"SFxW\",\n\t\"./be\": \"H8ED\",\n\t\"./be.js\": \"H8ED\",\n\t\"./bg\": \"hKrs\",\n\t\"./bg.js\": \"hKrs\",\n\t\"./bm\": \"p/rL\",\n\t\"./bm.js\": \"p/rL\",\n\t\"./bn\": \"kEOa\",\n\t\"./bn.js\": \"kEOa\",\n\t\"./bo\": \"0mo+\",\n\t\"./bo.js\": \"0mo+\",\n\t\"./br\": \"aIdf\",\n\t\"./br.js\": \"aIdf\",\n\t\"./bs\": \"JVSJ\",\n\t\"./bs.js\": \"JVSJ\",\n\t\"./ca\": \"1xZ4\",\n\t\"./ca.js\": \"1xZ4\",\n\t\"./cs\": \"PA2r\",\n\t\"./cs.js\": \"PA2r\",\n\t\"./cv\": \"A+xa\",\n\t\"./cv.js\": \"A+xa\",\n\t\"./cy\": \"l5ep\",\n\t\"./cy.js\": \"l5ep\",\n\t\"./da\": \"DxQv\",\n\t\"./da.js\": \"DxQv\",\n\t\"./de\": \"tGlX\",\n\t\"./de-at\": \"s+uk\",\n\t\"./de-at.js\": \"s+uk\",\n\t\"./de-ch\": \"u3GI\",\n\t\"./de-ch.js\": \"u3GI\",\n\t\"./de.js\": \"tGlX\",\n\t\"./dv\": \"WYrj\",\n\t\"./dv.js\": \"WYrj\",\n\t\"./el\": \"jUeY\",\n\t\"./el.js\": \"jUeY\",\n\t\"./en-SG\": \"zavE\",\n\t\"./en-SG.js\": \"zavE\",\n\t\"./en-au\": \"Dmvi\",\n\t\"./en-au.js\": \"Dmvi\",\n\t\"./en-ca\": \"OIYi\",\n\t\"./en-ca.js\": \"OIYi\",\n\t\"./en-gb\": \"Oaa7\",\n\t\"./en-gb.js\": \"Oaa7\",\n\t\"./en-ie\": \"4dOw\",\n\t\"./en-ie.js\": \"4dOw\",\n\t\"./en-il\": \"czMo\",\n\t\"./en-il.js\": \"czMo\",\n\t\"./en-nz\": \"b1Dy\",\n\t\"./en-nz.js\": \"b1Dy\",\n\t\"./eo\": \"Zduo\",\n\t\"./eo.js\": \"Zduo\",\n\t\"./es\": \"iYuL\",\n\t\"./es-do\": \"CjzT\",\n\t\"./es-do.js\": \"CjzT\",\n\t\"./es-us\": \"Vclq\",\n\t\"./es-us.js\": \"Vclq\",\n\t\"./es.js\": \"iYuL\",\n\t\"./et\": \"7BjC\",\n\t\"./et.js\": \"7BjC\",\n\t\"./eu\": \"D/JM\",\n\t\"./eu.js\": \"D/JM\",\n\t\"./fa\": \"jfSC\",\n\t\"./fa.js\": \"jfSC\",\n\t\"./fi\": \"gekB\",\n\t\"./fi.js\": \"gekB\",\n\t\"./fo\": \"ByF4\",\n\t\"./fo.js\": \"ByF4\",\n\t\"./fr\": \"nyYc\",\n\t\"./fr-ca\": \"2fjn\",\n\t\"./fr-ca.js\": \"2fjn\",\n\t\"./fr-ch\": \"Dkky\",\n\t\"./fr-ch.js\": \"Dkky\",\n\t\"./fr.js\": \"nyYc\",\n\t\"./fy\": \"cRix\",\n\t\"./fy.js\": \"cRix\",\n\t\"./ga\": \"USCx\",\n\t\"./ga.js\": \"USCx\",\n\t\"./gd\": \"9rRi\",\n\t\"./gd.js\": \"9rRi\",\n\t\"./gl\": \"iEDd\",\n\t\"./gl.js\": \"iEDd\",\n\t\"./gom-latn\": \"DKr+\",\n\t\"./gom-latn.js\": \"DKr+\",\n\t\"./gu\": \"4MV3\",\n\t\"./gu.js\": \"4MV3\",\n\t\"./he\": \"x6pH\",\n\t\"./he.js\": \"x6pH\",\n\t\"./hi\": \"3E1r\",\n\t\"./hi.js\": \"3E1r\",\n\t\"./hr\": \"S6ln\",\n\t\"./hr.js\": \"S6ln\",\n\t\"./hu\": \"WxRl\",\n\t\"./hu.js\": \"WxRl\",\n\t\"./hy-am\": \"1rYy\",\n\t\"./hy-am.js\": \"1rYy\",\n\t\"./id\": \"UDhR\",\n\t\"./id.js\": \"UDhR\",\n\t\"./is\": \"BVg3\",\n\t\"./is.js\": \"BVg3\",\n\t\"./it\": \"bpih\",\n\t\"./it-ch\": \"bxKX\",\n\t\"./it-ch.js\": \"bxKX\",\n\t\"./it.js\": \"bpih\",\n\t\"./ja\": \"B55N\",\n\t\"./ja.js\": \"B55N\",\n\t\"./jv\": \"tUCv\",\n\t\"./jv.js\": \"tUCv\",\n\t\"./ka\": \"IBtZ\",\n\t\"./ka.js\": \"IBtZ\",\n\t\"./kk\": \"bXm7\",\n\t\"./kk.js\": \"bXm7\",\n\t\"./km\": \"6B0Y\",\n\t\"./km.js\": \"6B0Y\",\n\t\"./kn\": \"PpIw\",\n\t\"./kn.js\": \"PpIw\",\n\t\"./ko\": \"Ivi+\",\n\t\"./ko.js\": \"Ivi+\",\n\t\"./ku\": \"JCF/\",\n\t\"./ku.js\": \"JCF/\",\n\t\"./ky\": \"lgnt\",\n\t\"./ky.js\": \"lgnt\",\n\t\"./lb\": \"RAwQ\",\n\t\"./lb.js\": \"RAwQ\",\n\t\"./lo\": \"sp3z\",\n\t\"./lo.js\": \"sp3z\",\n\t\"./lt\": \"JvlW\",\n\t\"./lt.js\": \"JvlW\",\n\t\"./lv\": \"uXwI\",\n\t\"./lv.js\": \"uXwI\",\n\t\"./me\": \"KTz0\",\n\t\"./me.js\": \"KTz0\",\n\t\"./mi\": \"aIsn\",\n\t\"./mi.js\": \"aIsn\",\n\t\"./mk\": \"aQkU\",\n\t\"./mk.js\": \"aQkU\",\n\t\"./ml\": \"AvvY\",\n\t\"./ml.js\": \"AvvY\",\n\t\"./mn\": \"lYtQ\",\n\t\"./mn.js\": \"lYtQ\",\n\t\"./mr\": \"Ob0Z\",\n\t\"./mr.js\": \"Ob0Z\",\n\t\"./ms\": \"6+QB\",\n\t\"./ms-my\": \"ZAMP\",\n\t\"./ms-my.js\": \"ZAMP\",\n\t\"./ms.js\": \"6+QB\",\n\t\"./mt\": \"G0Uy\",\n\t\"./mt.js\": \"G0Uy\",\n\t\"./my\": \"honF\",\n\t\"./my.js\": \"honF\",\n\t\"./nb\": \"bOMt\",\n\t\"./nb.js\": \"bOMt\",\n\t\"./ne\": \"OjkT\",\n\t\"./ne.js\": \"OjkT\",\n\t\"./nl\": \"+s0g\",\n\t\"./nl-be\": \"2ykv\",\n\t\"./nl-be.js\": \"2ykv\",\n\t\"./nl.js\": \"+s0g\",\n\t\"./nn\": \"uEye\",\n\t\"./nn.js\": \"uEye\",\n\t\"./pa-in\": \"8/+R\",\n\t\"./pa-in.js\": \"8/+R\",\n\t\"./pl\": \"jVdC\",\n\t\"./pl.js\": \"jVdC\",\n\t\"./pt\": \"8mBD\",\n\t\"./pt-br\": \"0tRk\",\n\t\"./pt-br.js\": \"0tRk\",\n\t\"./pt.js\": \"8mBD\",\n\t\"./ro\": \"lyxo\",\n\t\"./ro.js\": \"lyxo\",\n\t\"./ru\": \"lXzo\",\n\t\"./ru.js\": \"lXzo\",\n\t\"./sd\": \"Z4QM\",\n\t\"./sd.js\": \"Z4QM\",\n\t\"./se\": \"//9w\",\n\t\"./se.js\": \"//9w\",\n\t\"./si\": \"7aV9\",\n\t\"./si.js\": \"7aV9\",\n\t\"./sk\": \"e+ae\",\n\t\"./sk.js\": \"e+ae\",\n\t\"./sl\": \"gVVK\",\n\t\"./sl.js\": \"gVVK\",\n\t\"./sq\": \"yPMs\",\n\t\"./sq.js\": \"yPMs\",\n\t\"./sr\": \"zx6S\",\n\t\"./sr-cyrl\": \"E+lV\",\n\t\"./sr-cyrl.js\": \"E+lV\",\n\t\"./sr.js\": \"zx6S\",\n\t\"./ss\": \"Ur1D\",\n\t\"./ss.js\": \"Ur1D\",\n\t\"./sv\": \"X709\",\n\t\"./sv.js\": \"X709\",\n\t\"./sw\": \"dNwA\",\n\t\"./sw.js\": \"dNwA\",\n\t\"./ta\": \"PeUW\",\n\t\"./ta.js\": \"PeUW\",\n\t\"./te\": \"XLvN\",\n\t\"./te.js\": \"XLvN\",\n\t\"./tet\": \"V2x9\",\n\t\"./tet.js\": \"V2x9\",\n\t\"./tg\": \"Oxv6\",\n\t\"./tg.js\": \"Oxv6\",\n\t\"./th\": \"EOgW\",\n\t\"./th.js\": \"EOgW\",\n\t\"./tl-ph\": \"Dzi0\",\n\t\"./tl-ph.js\": \"Dzi0\",\n\t\"./tlh\": \"z3Vd\",\n\t\"./tlh.js\": \"z3Vd\",\n\t\"./tr\": \"DoHr\",\n\t\"./tr.js\": \"DoHr\",\n\t\"./tzl\": \"z1FC\",\n\t\"./tzl.js\": \"z1FC\",\n\t\"./tzm\": \"wQk9\",\n\t\"./tzm-latn\": \"tT3J\",\n\t\"./tzm-latn.js\": \"tT3J\",\n\t\"./tzm.js\": \"wQk9\",\n\t\"./ug-cn\": \"YRex\",\n\t\"./ug-cn.js\": \"YRex\",\n\t\"./uk\": \"raLr\",\n\t\"./uk.js\": \"raLr\",\n\t\"./ur\": \"UpQW\",\n\t\"./ur.js\": \"UpQW\",\n\t\"./uz\": \"Loxo\",\n\t\"./uz-latn\": \"AQ68\",\n\t\"./uz-latn.js\": \"AQ68\",\n\t\"./uz.js\": \"Loxo\",\n\t\"./vi\": \"KSF8\",\n\t\"./vi.js\": \"KSF8\",\n\t\"./x-pseudo\": \"/X5v\",\n\t\"./x-pseudo.js\": \"/X5v\",\n\t\"./yo\": \"fzPg\",\n\t\"./yo.js\": \"fzPg\",\n\t\"./zh-cn\": \"XDpg\",\n\t\"./zh-cn.js\": \"XDpg\",\n\t\"./zh-hk\": \"SatO\",\n\t\"./zh-hk.js\": \"SatO\",\n\t\"./zh-tw\": \"kOpN\",\n\t\"./zh-tw.js\": \"kOpN\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"RnhZ\";","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Subject} from \"rxjs\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Injectable()\nexport class CommentService {\n\n // Replacement for ng1 $scope.$emit on activty-entry to mark comments to be quoted.\n // Should be generalized if needed for more than that.\n public quoteEvents = new Subject();\n\n constructor(\n readonly I18n:I18nService,\n private workPackageNotificationService:WorkPackageNotificationService,\n private NotificationsService:NotificationsService) {\n }\n\n public createComment(workPackage:WorkPackageResource, comment:{ raw:string }) {\n return workPackage.addComment(\n { comment: comment },\n { 'Content-Type': 'application/json; charset=UTF-8' }\n )\n .catch((error:any) => this.errorAndReject(error, workPackage));\n }\n\n public updateComment(activity:HalResource, comment:string) {\n const options = {\n ajax: {\n method: 'PATCH',\n data: JSON.stringify({ comment: comment }),\n contentType: 'application/json; charset=utf-8'\n }\n };\n\n return activity.update(\n { comment: comment },\n { 'Content-Type': 'application/json; charset=UTF-8' }\n ).then((activity:HalResource) => {\n this.NotificationsService.addSuccess(\n this.I18n.t('js.work_packages.comment_updated')\n );\n\n return activity;\n }).catch((error:any) => this.errorAndReject(error));\n }\n\n private errorAndReject(error:HalResource, workPackage?:WorkPackageResource) {\n this.workPackageNotificationService.handleRawError(error, workPackage);\n\n // returning a reject will enable to correctly work with subsequent then/catch handlers.\n return Promise.reject(error);\n }\n}\n","import {Component, Input, OnInit} from '@angular/core';\nimport {WorkPackageRelationsService} from '../../wp-relations/wp-relations.service';\nimport {combineLatest} from 'rxjs';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './wp-relations-count.html',\n selector: 'wp-relations-count',\n})\nexport class WorkPackageRelationsCountComponent extends UntilDestroyedMixin implements OnInit {\n @Input('wpId') wpId:string;\n public count:number = 0;\n\n constructor(protected apiV3Service:APIV3Service,\n protected wpRelations:WorkPackageRelationsService) {\n super();\n }\n\n ngOnInit():void {\n this.wpRelations.require(this.wpId.toString());\n\n combineLatest([\n this\n .wpRelations\n .state(this.wpId.toString())\n .values$(),\n this\n .apiV3Service\n .work_packages\n .id(this.wpId)\n .requireAndStream()\n ]).pipe(\n this.untilDestroyed()\n ).subscribe(([relations, workPackage]) => {\n let relationCount = _.size(relations);\n let childrenCount = _.size(workPackage.children);\n\n this.count = relationCount + childrenCount;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n Input, OnChanges,\n OnInit,\n Output, SimpleChanges\n} from '@angular/core';\n\nexport const slideToggleSelector = 'slide-toggle';\n\n@Component({\n templateUrl: './slide-toggle.component.html',\n selector: slideToggleSelector,\n styleUrls: ['./slide-toggle.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\n\nexport class SlideToggleComponent implements OnInit, OnChanges {\n @Input() containerId:string;\n @Input() containerClasses:string;\n @Input() inputId:string;\n @Input() inputName:string;\n @Input() active:boolean;\n\n @Output() valueChanged = new EventEmitter();\n\n constructor(private elementRef:ElementRef,\n private cdRef:ChangeDetectorRef) {\n }\n\n ngOnChanges(changes:SimpleChanges) {\n console.warn(JSON.stringify(changes));\n }\n\n ngOnInit() {\n const dataset = this.elementRef.nativeElement.dataset;\n\n // Allow taking over values from dataset (Rails)\n if (dataset.inputName) {\n this.containerId = dataset.containerId;\n this.containerClasses = dataset.containerClasses;\n this.inputId = dataset.inputId;\n this.inputName = dataset.inputName;\n this.active = dataset.active.toString() === 'true';\n }\n }\n\n public onValueChanged(val:any) {\n this.active = val;\n this.valueChanged.emit(val);\n this.cdRef.detectChanges();\n }\n}\n","
    \n \n
    \n ","import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n Input,\n OnInit,\n Output\n} from \"@angular/core\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {checkedClassName, uiStateLinkClass} from \"core-components/wp-fast-table/builders/ui-state-link-builder\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {StateService} from \"@uirouter/core\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CardHighlightingMode} from \"core-components/wp-fast-table/builders/highlighting/highlighting-mode.const\";\nimport {CardViewOrientation} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {WorkPackageViewFocusService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service\";\nimport {splitViewRoute} from \"core-app/modules/work_packages/routing/split-view-routes.helper\";\n\n@Component({\n selector: 'wp-single-card',\n styleUrls: ['./wp-single-card.component.sass'],\n templateUrl: './wp-single-card.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageSingleCardComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public showInfoButton:boolean = false;\n @Input() public showStatusButton:boolean = true;\n @Input() public showRemoveButton:boolean = false;\n @Input() public highlightingMode:CardHighlightingMode = 'inline';\n @Input() public draggable:boolean = false;\n @Input() public orientation:CardViewOrientation = 'vertical';\n @Input() public shrinkOnMobile:boolean = false;\n\n @Output() onRemove = new EventEmitter();\n @Output() stateLinkClicked = new EventEmitter<{ workPackageId:string, requestedState:string }>();\n\n public uiStateLinkClass:string = uiStateLinkClass;\n\n public text = {\n removeCard: this.I18n.t('js.card.remove_from_list'),\n detailsView: this.I18n.t('js.button_open_details')\n };\n\n constructor(readonly pathHelper:PathHelperService,\n readonly I18n:I18nService,\n readonly $state:StateService,\n readonly wpTableSelection:WorkPackageViewSelectionService,\n readonly wpTableFocus:WorkPackageViewFocusService,\n readonly cardView:WorkPackageCardViewService,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit():void {\n // Update selection state\n this.wpTableSelection.live$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.cdRef.detectChanges();\n });\n }\n\n public classIdentifier(wp:WorkPackageResource) {\n return this.cardView.classIdentifier(wp);\n }\n\n public emitStateLinkClicked(wp:WorkPackageResource, detail?:boolean) {\n const classIdentifier = this.classIdentifier(wp);\n const stateToEmit = detail ? splitViewRoute(this.$state) : 'work-packages.show';\n\n this.wpTableSelection.setSelection(wp.id!, this.cardView.findRenderedCard(classIdentifier));\n this.wpTableFocus.updateFocus(wp.id!);\n this.stateLinkClicked.emit({ workPackageId:wp.id!, requestedState: stateToEmit });\n }\n\n public cardClasses() {\n let classes = this.isSelected(this.workPackage) ? checkedClassName : '';\n classes += this.draggable ? ' -draggable' : '';\n classes += this.workPackage.isNew ? ' -new' : '';\n classes += ' wp-card-' + this.workPackage.id;\n classes += ' -' + this.orientation;\n classes += this.shrinkOnMobile ? ' -shrink' : '';\n return classes;\n }\n\n public wpTypeAttribute(wp:WorkPackageResource) {\n return wp.type.name;\n }\n\n public wpSubject(wp:WorkPackageResource) {\n return wp.subject;\n }\n\n public wpProjectName(wp:WorkPackageResource) {\n return wp.project?.name;\n }\n\n public fullWorkPackageLink(wp:WorkPackageResource) {\n return this.$state.href('work-packages.show', { workPackageId: wp.id });\n }\n\n public cardHighlightingClass(wp:WorkPackageResource) {\n return this.cardHighlighting(wp);\n }\n\n public typeHighlightingClass(wp:WorkPackageResource) {\n return this.attributeHighlighting('type', wp);\n }\n\n public onRemoved(wp:WorkPackageResource) {\n this.onRemove.emit(wp);\n }\n\n public cardCoverImageShown(wp:WorkPackageResource):boolean {\n return this.bcfSnapshotPath(wp) !== null;\n }\n\n public bcfSnapshotPath(wp:WorkPackageResource) {\n return wp.bcfViewpoints && wp.bcfViewpoints.length > 0 ? wp.bcfViewpoints[0].href + '/snapshot' : null;\n }\n\n private isSelected(wp:WorkPackageResource):boolean {\n return this.wpTableSelection.isSelected(wp.id!);\n }\n\n private cardHighlighting(wp:WorkPackageResource) {\n if (['status', 'priority', 'type'].includes(this.highlightingMode)) {\n return Highlighting.backgroundClass(this.highlightingMode, wp[this.highlightingMode].id);\n }\n return '';\n }\n\n private attributeHighlighting(type:string, wp:WorkPackageResource) {\n return Highlighting.inlineClass(type, wp.type.id!);\n }\n}\n","
    \n\n
    \n
    \n\n
    \n \n \n \n \n \n \n
    \n \n
    \n \n \n \n \n
    \n
    \n\n
    \n \n \n \n \n \n #{{workPackage.id}}\n \n \n \n \n \n \n \n \n
    \n
    ","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {combine, deriveRaw, InputState, multiInput, MultiInputState, State, StatesGroup} from 'reactivestates';\nimport {filter, map} from 'rxjs/operators';\nimport {Injectable, Injector} from '@angular/core';\nimport {Subject} from \"rxjs\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {ChangeMap} from \"core-app/modules/fields/changeset/changeset\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nclass ChangesetStates extends StatesGroup {\n name = 'Changesets';\n\n changesets = multiInput();\n\n constructor() {\n super();\n this.initializeMembers();\n }\n}\n\n/**\n * Wrapper class for the saved change of a work package,\n * used to access the previous save and or previous state\n * of the work package (e.g., whether it was new).\n */\nexport class ResourceChangesetCommit {\n /**\n * The work package id of the change\n * (This is the new work package ID if +wasNew+ is true.\n */\n public readonly id:string;\n\n /**\n * The resulting, saved work package.\n */\n public readonly resource:T;\n\n /** Whether the commit saved an initial work package */\n public readonly wasNew:boolean = false;\n\n /** The previous changes */\n public readonly changes:ChangeMap;\n\n /**\n * Create a change commit from the change object\n * @param change The change object that resulted in the save\n * @param saved The returned work package\n */\n constructor(change:ResourceChangeset, saved:T) {\n this.id = saved.id!.toString();\n this.wasNew = change.pristineResource.isNew;\n this.resource = saved;\n this.changes = change.changeMap;\n }\n}\n\nexport interface ResourceChangesetClass {\n new(...args:any[]):ResourceChangeset;\n}\n\n@Injectable()\nexport class HalResourceEditingService extends StateCacheService {\n\n /** Committed / saved changes to work packages observable */\n public committedChanges = new Subject();\n\n constructor(protected readonly injector:Injector,\n protected readonly halEvents:HalEventsService,\n protected readonly hook:HookService) {\n super(new ChangesetStates().changesets);\n }\n\n public async save>(change:T):Promise> {\n // Form the payload we're going to save\n const payload = await change.buildRequestPayload();\n const savedResource = await change.pristineResource.$links.updateImmediately(payload);\n\n // Initialize any potentially new HAL values\n savedResource.retainFrom(change.pristineResource);\n\n await this.onSaved(savedResource);\n\n // Complete the change\n return this.complete(change, savedResource);\n }\n\n /**\n * Mark the given change as completed, notify changes\n * and reset it.\n */\n private complete>(change:T, saved:V):ResourceChangesetCommit {\n const commit = new ResourceChangesetCommit(change, saved);\n this.committedChanges.next(commit);\n this.reset(change);\n\n const eventType = commit.wasNew ? 'created' : 'updated';\n this.halEvents.push(commit.resource, { eventType, commit });\n\n return commit;\n }\n\n /**\n * Reset the given change, either due to cancelling or successful submission.\n * @param change\n */\n public reset>(change:T) {\n change.clear();\n this.clearSome(change.href);\n }\n\n /**\n * Returns the typed state value. Use this to get a changeset\n * for a subtype of ResourceChangeset.\n * @param resource\n */\n public typedState>(resource:V):State {\n return this.multiState.get(resource.href!) as InputState;\n }\n\n /**\n * Create a new changeset for the given work package, discarding any previous changeset that might exist.\n *\n * @param resource\n * @param form\n *\n * @return The state for the created changeset\n */\n public edit>(resource:V, form?:FormResource):T {\n const state = this.multiState.get(resource.href!) as InputState;\n const changeset = this.newChangeset(resource, state, form);\n\n state.putValue(changeset);\n\n return changeset;\n }\n\n protected newChangeset>(resource:V, state:InputState, form?:FormResource):T {\n // we take the last registered group component which means that\n // plugins will have their say if they register for it.\n const cls = this.hook.call('halResourceChangesetClass', resource).pop() || ResourceChangeset;\n return new cls(resource, state, form) as T;\n }\n\n /**\n * Start or continue editing the work package with a given edit context\n * @param fallback Fallback resource to use\n * @return {ResourceChangeset} Change object to work on\n */\n public changeFor>(fallback:V):T {\n const state = this.multiState.get(fallback.href!) as InputState;\n let resource = fallback;\n if (fallback.state) {\n resource = fallback.state.getValueOr(fallback);\n }\n let changeset = state.value;\n\n // If there is no changeset, or\n // If there is an empty one for a older work package reference\n // build a new changeset\n if (changeset && !changeset.isEmpty()) {\n return changeset;\n }\n\n if (!changeset) {\n return this.edit(resource);\n }\n\n if (resource.hasOwnProperty('lockVersion') && changeset.pristineResource.lockVersion < resource.lockVersion) {\n return this.edit(resource);\n }\n\n changeset.updatePristineResource(resource);\n return changeset;\n }\n\n /**\n * Get a temporary view on the resource being edited.\n * IF there is a changeset:\n * - Merge the changeset, including its form, into the work package resource\n * IF there is no changeset:\n * - The work package itself is returned.\n *\n * This resource has a read only index signature to make it clear it is NOT\n * meant for editing.\n *\n * @return {State}\n */\n public temporaryEditResource>(resource:V):State {\n const combined = combine(resource.state! as State, this.typedState(resource) as State);\n\n return deriveRaw(combined,\n ($) => $\n .pipe(\n filter(([resource, _]) => !!resource),\n map(([resource, change]) => {\n if (change) {\n change.updatePristineResource(resource as V);\n return change.projectedResource;\n }\n\n return resource;\n })\n )\n );\n }\n\n public stopEditing(resource:HalResource|{ href:string }) {\n this.multiState.get(resource.href!).clear();\n }\n\n protected onSaved(saved:HalResource):Promise {\n if (saved.state) {\n return saved.push(saved);\n }\n\n return Promise.resolve();\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n(function ($) {\n \"use strict\";\n\n $(function() {\n // set selected page for menu tree if provided.\n $('[data-selected-page]').closest('.tree-menu--container').each(function(_i:number, tree:HTMLElement) {\n let selectedPage = $(tree).data('selected-page');\n\n if (selectedPage) {\n let selected = $('[slug=\"' + selectedPage + '\"]', tree);\n selected.toggleClass('-selected', true);\n if (selected.length > 1) {\n selected[0].scrollIntoView();\n }\n }\n });\n\n function toggle (event:any) {\n // ignore the event if a key different from ENTER was pressed.\n if (event.type === 'keypress' && event.which !== 13) { return false; }\n\n let target = $(event.target);\n let targetList = target.closest('ul.-with-hierarchy > li');\n targetList.toggleClass('-hierarchy-collapsed -hierarchy-expanded');\n return false;\n }\n\n // set click handlers for expanding and collapsing tree nodes\n $('.pages-hierarchy.-with-hierarchy .tree-menu--hierarchy-span').on('click keypress', toggle);\n });\n}(jQuery));\n","import { ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy, OnInit, Directive } from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {OpModalService} from 'core-components/op-modals/op-modal.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Directive()\nexport abstract class OpModalComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n\n /* Close on escape? */\n public closeOnEscape:boolean = true;\n public closeOnEscapeFunction = this.closeMe;\n\n /* Close on outside click */\n public closeOnOutsideClick:boolean = true;\n\n /* Reference to service */\n protected service:OpModalService = this.locals.service;\n\n public $element:JQuery;\n\n /** Closing event called from the service when closing this modal */\n public closingEvent = new EventEmitter();\n\n public openingEvent = new EventEmitter();\n\n protected constructor(public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef) {\n super();\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n }\n\n ngOnDestroy() {\n this.closingEvent.complete();\n this.openingEvent.complete();\n }\n\n /**\n * Called when the user attempts to close the modal window.\n * The service will close this modal if this method returns true\n * @returns {boolean}\n */\n public onClose():boolean {\n this.afterFocusOn && this.afterFocusOn.focus();\n return true;\n }\n\n public closeMe(evt?:JQuery.TriggeredEvent) {\n this.service.close();\n\n if (evt) {\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n\n public onOpen(modalElement:JQuery) {\n this.openingEvent.emit();\n this.cdRef.detectChanges();\n }\n\n protected get afterFocusOn():JQuery {\n return this.$element;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from '@angular/core';\nimport {BehaviorSubject} from 'rxjs';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {DeviceService} from \"app/modules/common/browser/device.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n@Injectable({ providedIn: 'root' })\nexport class MainMenuToggleService {\n public toggleTitle:string;\n private elementWidth:number;\n private elementMinWidth = 11;\n private readonly defaultWidth:number = 230;\n private readonly localStorageKey:string = 'openProject-mainMenuWidth';\n private readonly localStorageStateKey:string = 'openProject-mainMenuCollapsed';\n\n @InjectField() currentProject:CurrentProjectService;\n\n private global = (window as any);\n private htmlNode = document.getElementsByTagName('html')[0];\n private mainMenu = jQuery('#main-menu')[0]; // main menu, containing sidebar and resizer\n private hideElements = jQuery('.can-hide-navigation');\n\n // Title needs to be sync in main-menu-toggle.component.ts and main-menu-resizer.component.ts\n private titleData = new BehaviorSubject('');\n public titleData$ = this.titleData.asObservable();\n\n // Notes all changes of the menu size (currently needed in wp-resizer.component.ts)\n private changeData = new BehaviorSubject({});\n public changeData$ = this.changeData.asObservable();\n\n constructor(protected I18n:I18nService,\n public injector:Injector,\n readonly deviceService:DeviceService) {\n }\n\n public initializeMenu():void {\n if (!this.mainMenu) { return; }\n\n this.elementWidth = parseInt(window.OpenProject.guardedLocalStorage(this.localStorageKey) as string);\n const menuCollapsed = window.OpenProject.guardedLocalStorage(this.localStorageStateKey) as string;\n\n if (!this.elementWidth) {\n this.saveWidth(this.mainMenu.offsetWidth);\n } else if (menuCollapsed && JSON.parse(menuCollapsed)) {\n this.closeMenu();\n }\n else {\n this.setWidth();\n }\n\n let currentProject:CurrentProjectService = this.injector.get(CurrentProjectService);\n if (jQuery(document.body).hasClass('controller-my') && this.elementWidth === 0 || currentProject.id === null) {\n this.saveWidth(this.defaultWidth);\n }\n\n // mobile version default: hide menu on initialization\n this.closeWhenOnMobile();\n }\n\n // click on arrow or hamburger icon\n public toggleNavigation(event?:JQuery.TriggeredEvent):void {\n if (event) {\n event.stopPropagation();\n event.preventDefault();\n }\n\n if (!this.showNavigation) { // sidebar is hidden -> show menu\n if (this.deviceService.isMobile) { // mobile version\n this.setWidth(window.innerWidth);\n } else { // desktop version\n const savedWidth = parseInt(window.OpenProject.guardedLocalStorage(this.localStorageKey) as string);\n const widthToSave = savedWidth >= this.elementMinWidth ? savedWidth : this.defaultWidth;\n\n this.saveWidth(widthToSave);\n }\n } else { // sidebar is expanded -> close menu\n this.closeMenu();\n }\n\n // Set focus on first visible main menu item.\n // This needs to be called after AngularJS has rendered the menu, which happens some when after(!) we leave this\n // method here. So we need to set the focus after a timeout.\n setTimeout(function () {\n jQuery('#main-menu [class*=\"-menu-item\"]:visible').first().focus();\n }, 500);\n }\n\n public closeMenu():void {\n this.setWidth(0);\n window.OpenProject.guardedLocalStorage(this.localStorageStateKey, 'true');\n jQuery('.collapsible-menu--search-input').blur();\n }\n\n public closeWhenOnMobile():void {\n if (this.deviceService.isMobile) {\n this.closeMenu();\n window.OpenProject.guardedLocalStorage(this.localStorageStateKey, 'false');\n }\n }\n public saveWidth(width?:number):void {\n this.setWidth(width);\n window.OpenProject.guardedLocalStorage(this.localStorageKey, String(this.elementWidth));\n window.OpenProject.guardedLocalStorage(this.localStorageStateKey, String(this.elementWidth === 0));\n }\n\n public setWidth(width?:any):void {\n if (width !== undefined) {\n // Leave a minimum amount of space for space fot the content\n let maxMenuWidth = this.deviceService.isMobile ? window.innerWidth - 120 : window.innerWidth - 520;\n if (width > maxMenuWidth) {\n this.elementWidth = maxMenuWidth;\n } else {\n this.elementWidth = width as number;\n }\n }\n\n this.snapBack();\n this.setToggleTitle();\n this.toggleClassHidden();\n\n this.global.showNavigation = this.showNavigation;\n this.htmlNode.style.setProperty(\"--main-menu-width\", this.elementWidth + 'px');\n\n // Send change event when size of menu is changing (menu toggled or resized)\n // Event should only be fired, when transition is finished\n let changeEvent = jQuery.Event(\"change\");\n jQuery('#content-wrapper').on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', () => {\n this.changeData.next(changeEvent);\n });\n }\n\n public get showNavigation():boolean {\n return (this.elementWidth >= this.elementMinWidth);\n }\n\n private snapBack():void {\n if (this.elementWidth < this.elementMinWidth) {\n this.elementWidth = 0;\n }\n }\n\n private setToggleTitle():void {\n if (this.showNavigation) {\n this.toggleTitle = this.I18n.t('js.label_hide_project_menu');\n } else {\n this.toggleTitle = this.I18n.t('js.label_expand_project_menu');\n }\n this.titleData.next(this.toggleTitle);\n }\n\n private toggleClassHidden():void {\n this.hideElements.toggleClass('hidden-navigation', !this.showNavigation);\n }\n}\n","import {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\n\nexport function groupIdentifier(group:GroupObject) {\n let value = group.value || 'nullValue';\n\n if (group.href) {\n try {\n value += group.href.map(el => el.href).join('-');\n } catch (e) {\n console.error('Failed to extract group identifier for ' + group.value);\n }\n }\n\n value = value.toLowerCase().replace(/[^a-z0-9]+/g, '-');\n return `${groupByProperty(group)}-${value}`;\n}\n\nexport function groupName(group:GroupObject) {\n let value = group.value;\n if (value === null) {\n return '-';\n } else {\n return value;\n }\n}\n\nexport function groupByProperty(group:GroupObject):string {\n return group._links.groupBy.href.split('/').pop()!;\n}\n\n/**\n * Get the row group class name for the given group id.\n */\nexport function groupedRowClassName(groupIndex:number) {\n return `__row-group-${groupIndex}`;\n}\n\n/**\n * Get the group type from its identifier.\n */\nexport function groupTypeFromIdentifier(groupIdentifier:string) {\n return groupIdentifier.split('-')[0];\n}\n\n/**\n * Get the group id from its identifier.\n */\nexport function groupIdFromIdentifier(groupIdentifier:string) {\n return groupIdentifier.split('-').pop();\n}\n","var map = {\n\t\"./apl/apl.js\": [\n\t\t\"4kmW\",\n\t\t0,\n\t\t45\n\t],\n\t\"./asciiarmor/asciiarmor.js\": [\n\t\t\"Jt+K\",\n\t\t0,\n\t\t46\n\t],\n\t\"./asn.1/asn.1.js\": [\n\t\t\"0OHD\",\n\t\t0,\n\t\t47\n\t],\n\t\"./asterisk/asterisk.js\": [\n\t\t\"yGjk\",\n\t\t0,\n\t\t48\n\t],\n\t\"./brainfuck/brainfuck.js\": [\n\t\t\"oF4/\",\n\t\t0,\n\t\t49\n\t],\n\t\"./clike/clike.js\": [\n\t\t\"S6bl\",\n\t\t0,\n\t\t5\n\t],\n\t\"./clojure/clojure.js\": [\n\t\t\"LA1u\",\n\t\t0,\n\t\t50\n\t],\n\t\"./cmake/cmake.js\": [\n\t\t\"qE+Q\",\n\t\t0,\n\t\t51\n\t],\n\t\"./cobol/cobol.js\": [\n\t\t\"JNJg\",\n\t\t0,\n\t\t52\n\t],\n\t\"./coffeescript/coffeescript.js\": [\n\t\t\"oL3q\",\n\t\t0,\n\t\t1\n\t],\n\t\"./commonlisp/commonlisp.js\": [\n\t\t\"kmAK\",\n\t\t0,\n\t\t53\n\t],\n\t\"./crystal/crystal.js\": [\n\t\t\"JRJP\",\n\t\t0,\n\t\t54\n\t],\n\t\"./css/css.js\": [\n\t\t\"ewDg\",\n\t\t0,\n\t\t3\n\t],\n\t\"./cypher/cypher.js\": [\n\t\t\"vW+e\",\n\t\t0,\n\t\t55\n\t],\n\t\"./d/d.js\": [\n\t\t\"zRyg\",\n\t\t0,\n\t\t56\n\t],\n\t\"./dart/dart.js\": [\n\t\t\"6q/U\",\n\t\t0,\n\t\t5,\n\t\t57\n\t],\n\t\"./diff/diff.js\": [\n\t\t\"3fnu\",\n\t\t0,\n\t\t58\n\t],\n\t\"./django/django.js\": [\n\t\t\"SzTn\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t36\n\t],\n\t\"./dockerfile/dockerfile.js\": [\n\t\t\"R6x9\",\n\t\t0,\n\t\t1,\n\t\t59\n\t],\n\t\"./dtd/dtd.js\": [\n\t\t\"/YIB\",\n\t\t0,\n\t\t60\n\t],\n\t\"./dylan/dylan.js\": [\n\t\t\"PLH4\",\n\t\t0,\n\t\t61\n\t],\n\t\"./ebnf/ebnf.js\": [\n\t\t\"AvIz\",\n\t\t0,\n\t\t62\n\t],\n\t\"./ecl/ecl.js\": [\n\t\t\"rSpl\",\n\t\t0,\n\t\t63\n\t],\n\t\"./eiffel/eiffel.js\": [\n\t\t\"t86p\",\n\t\t0,\n\t\t64\n\t],\n\t\"./elm/elm.js\": [\n\t\t\"Rba3\",\n\t\t0,\n\t\t65\n\t],\n\t\"./erlang/erlang.js\": [\n\t\t\"9RTS\",\n\t\t0,\n\t\t66\n\t],\n\t\"./factor/factor.js\": [\n\t\t\"yv4w\",\n\t\t0,\n\t\t1,\n\t\t67\n\t],\n\t\"./fcl/fcl.js\": [\n\t\t\"xvvs\",\n\t\t0,\n\t\t68\n\t],\n\t\"./forth/forth.js\": [\n\t\t\"CDkR\",\n\t\t0,\n\t\t69\n\t],\n\t\"./fortran/fortran.js\": [\n\t\t\"UYub\",\n\t\t0,\n\t\t70\n\t],\n\t\"./gas/gas.js\": [\n\t\t\"Upog\",\n\t\t0,\n\t\t71\n\t],\n\t\"./gfm/gfm.js\": [\n\t\t\"RKCW\",\n\t\t0,\n\t\t8,\n\t\t1,\n\t\t72\n\t],\n\t\"./gherkin/gherkin.js\": [\n\t\t\"tkAH\",\n\t\t0,\n\t\t73\n\t],\n\t\"./go/go.js\": [\n\t\t\"T/QY\",\n\t\t0,\n\t\t74\n\t],\n\t\"./groovy/groovy.js\": [\n\t\t\"X7TR\",\n\t\t0,\n\t\t75\n\t],\n\t\"./haml/haml.js\": [\n\t\t\"c+b1\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t37\n\t],\n\t\"./handlebars/handlebars.js\": [\n\t\t\"4d6s\",\n\t\t0,\n\t\t1\n\t],\n\t\"./haskell-literate/haskell-literate.js\": [\n\t\t\"INem\",\n\t\t0,\n\t\t1,\n\t\t76\n\t],\n\t\"./haskell/haskell.js\": [\n\t\t\"0+DK\",\n\t\t0,\n\t\t1\n\t],\n\t\"./haxe/haxe.js\": [\n\t\t\"We/1\",\n\t\t0,\n\t\t77\n\t],\n\t\"./htmlembedded/htmlembedded.js\": [\n\t\t\"dLt8\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t38\n\t],\n\t\"./htmlmixed/htmlmixed.js\": [\n\t\t\"1p+/\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t43\n\t],\n\t\"./http/http.js\": [\n\t\t\"scEK\",\n\t\t0,\n\t\t78\n\t],\n\t\"./idl/idl.js\": [\n\t\t\"HqpV\",\n\t\t0,\n\t\t79\n\t],\n\t\"./javascript/javascript.js\": [\n\t\t\"+dQi\",\n\t\t0,\n\t\t2\n\t],\n\t\"./jinja2/jinja2.js\": [\n\t\t\"ToA7\",\n\t\t0,\n\t\t80\n\t],\n\t\"./jsx/jsx.js\": [\n\t\t\"onn/\",\n\t\t0,\n\t\t2,\n\t\t44\n\t],\n\t\"./julia/julia.js\": [\n\t\t\"NGrM\",\n\t\t0,\n\t\t81\n\t],\n\t\"./livescript/livescript.js\": [\n\t\t\"5RX+\",\n\t\t0,\n\t\t82\n\t],\n\t\"./lua/lua.js\": [\n\t\t\"jrMQ\",\n\t\t0,\n\t\t83\n\t],\n\t\"./markdown/markdown.js\": [\n\t\t\"lZu9\",\n\t\t0,\n\t\t8\n\t],\n\t\"./mathematica/mathematica.js\": [\n\t\t\"ztbM\",\n\t\t0,\n\t\t84\n\t],\n\t\"./mbox/mbox.js\": [\n\t\t\"6mA5\",\n\t\t0,\n\t\t85\n\t],\n\t\"./mirc/mirc.js\": [\n\t\t\"o5kb\",\n\t\t0,\n\t\t86\n\t],\n\t\"./mllike/mllike.js\": [\n\t\t\"NU+Z\",\n\t\t0,\n\t\t87\n\t],\n\t\"./modelica/modelica.js\": [\n\t\t\"lQiH\",\n\t\t0,\n\t\t88\n\t],\n\t\"./mscgen/mscgen.js\": [\n\t\t\"6gTk\",\n\t\t0,\n\t\t89\n\t],\n\t\"./mumps/mumps.js\": [\n\t\t\"Q7su\",\n\t\t0,\n\t\t90\n\t],\n\t\"./nginx/nginx.js\": [\n\t\t\"srmC\",\n\t\t0,\n\t\t91\n\t],\n\t\"./nsis/nsis.js\": [\n\t\t\"bYLO\",\n\t\t0,\n\t\t1,\n\t\t92\n\t],\n\t\"./ntriples/ntriples.js\": [\n\t\t\"PWBO\",\n\t\t0,\n\t\t93\n\t],\n\t\"./octave/octave.js\": [\n\t\t\"mybg\",\n\t\t0,\n\t\t94\n\t],\n\t\"./oz/oz.js\": [\n\t\t\"yhmh\",\n\t\t0,\n\t\t95\n\t],\n\t\"./pascal/pascal.js\": [\n\t\t\"lB9V\",\n\t\t0,\n\t\t96\n\t],\n\t\"./pegjs/pegjs.js\": [\n\t\t\"ZGb1\",\n\t\t0,\n\t\t2,\n\t\t97\n\t],\n\t\"./perl/perl.js\": [\n\t\t\"kG+r\",\n\t\t0,\n\t\t98\n\t],\n\t\"./php/php.js\": [\n\t\t\"RNWO\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t5,\n\t\t39\n\t],\n\t\"./pig/pig.js\": [\n\t\t\"860+\",\n\t\t0,\n\t\t99\n\t],\n\t\"./powershell/powershell.js\": [\n\t\t\"naPG\",\n\t\t0,\n\t\t100\n\t],\n\t\"./properties/properties.js\": [\n\t\t\"3Fvf\",\n\t\t0,\n\t\t101\n\t],\n\t\"./protobuf/protobuf.js\": [\n\t\t\"cHwl\",\n\t\t0,\n\t\t102\n\t],\n\t\"./pug/pug.js\": [\n\t\t\"W+/v\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t7\n\t],\n\t\"./puppet/puppet.js\": [\n\t\t\"cwoo\",\n\t\t0,\n\t\t103\n\t],\n\t\"./python/python.js\": [\n\t\t\"25Eh\",\n\t\t0,\n\t\t1\n\t],\n\t\"./q/q.js\": [\n\t\t\"MiqB\",\n\t\t0,\n\t\t104\n\t],\n\t\"./r/r.js\": [\n\t\t\"kD6b\",\n\t\t0,\n\t\t105\n\t],\n\t\"./rpm/rpm.js\": [\n\t\t\"Qs4+\",\n\t\t0,\n\t\t106\n\t],\n\t\"./rst/rst.js\": [\n\t\t\"jIQM\",\n\t\t0,\n\t\t1,\n\t\t107\n\t],\n\t\"./ruby/ruby.js\": [\n\t\t\"hTYL\",\n\t\t0,\n\t\t1\n\t],\n\t\"./rust/rust.js\": [\n\t\t\"sY4N\",\n\t\t0,\n\t\t1,\n\t\t108\n\t],\n\t\"./sas/sas.js\": [\n\t\t\"Sh3j\",\n\t\t0,\n\t\t109\n\t],\n\t\"./sass/sass.js\": [\n\t\t\"G2Pi\",\n\t\t0,\n\t\t3,\n\t\t1\n\t],\n\t\"./scheme/scheme.js\": [\n\t\t\"8wdy\",\n\t\t0,\n\t\t110\n\t],\n\t\"./shell/shell.js\": [\n\t\t\"AvDn\",\n\t\t0,\n\t\t111\n\t],\n\t\"./sieve/sieve.js\": [\n\t\t\"1dRh\",\n\t\t0,\n\t\t112\n\t],\n\t\"./slim/slim.js\": [\n\t\t\"VI2i\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t40\n\t],\n\t\"./smalltalk/smalltalk.js\": [\n\t\t\"n4Nj\",\n\t\t0,\n\t\t113\n\t],\n\t\"./smarty/smarty.js\": [\n\t\t\"QWhe\",\n\t\t0,\n\t\t114\n\t],\n\t\"./solr/solr.js\": [\n\t\t\"xhF3\",\n\t\t0,\n\t\t115\n\t],\n\t\"./soy/soy.js\": [\n\t\t\"vH+N\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t41\n\t],\n\t\"./sparql/sparql.js\": [\n\t\t\"++e5\",\n\t\t0,\n\t\t116\n\t],\n\t\"./spreadsheet/spreadsheet.js\": [\n\t\t\"bEWP\",\n\t\t0,\n\t\t117\n\t],\n\t\"./sql/sql.js\": [\n\t\t\"/9rB\",\n\t\t0,\n\t\t118\n\t],\n\t\"./stex/stex.js\": [\n\t\t\"+NIl\",\n\t\t0,\n\t\t1\n\t],\n\t\"./stylus/stylus.js\": [\n\t\t\"dtKC\",\n\t\t0,\n\t\t11\n\t],\n\t\"./swift/swift.js\": [\n\t\t\"wOIU\",\n\t\t0,\n\t\t119\n\t],\n\t\"./tcl/tcl.js\": [\n\t\t\"BEBj\",\n\t\t0,\n\t\t120\n\t],\n\t\"./textile/textile.js\": [\n\t\t\"TD3l\",\n\t\t0,\n\t\t121\n\t],\n\t\"./tiddlywiki/tiddlywiki.js\": [\n\t\t\"9+NH\",\n\t\t0,\n\t\t122\n\t],\n\t\"./tiki/tiki.js\": [\n\t\t\"Km7L\",\n\t\t0,\n\t\t123\n\t],\n\t\"./toml/toml.js\": [\n\t\t\"0sou\",\n\t\t0,\n\t\t124\n\t],\n\t\"./tornado/tornado.js\": [\n\t\t\"xbNY\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t42\n\t],\n\t\"./troff/troff.js\": [\n\t\t\"s1o1\",\n\t\t0,\n\t\t125\n\t],\n\t\"./ttcn-cfg/ttcn-cfg.js\": [\n\t\t\"hmTv\",\n\t\t0,\n\t\t126\n\t],\n\t\"./ttcn/ttcn.js\": [\n\t\t\"TYrp\",\n\t\t0,\n\t\t127\n\t],\n\t\"./turtle/turtle.js\": [\n\t\t\"P3N9\",\n\t\t0,\n\t\t128\n\t],\n\t\"./twig/twig.js\": [\n\t\t\"SII/\",\n\t\t0,\n\t\t1,\n\t\t129\n\t],\n\t\"./vb/vb.js\": [\n\t\t\"Kr55\",\n\t\t0,\n\t\t130\n\t],\n\t\"./vbscript/vbscript.js\": [\n\t\t\"axah\",\n\t\t0,\n\t\t131\n\t],\n\t\"./velocity/velocity.js\": [\n\t\t\"/kYp\",\n\t\t0,\n\t\t132\n\t],\n\t\"./verilog/verilog.js\": [\n\t\t\"m2bc\",\n\t\t0,\n\t\t133\n\t],\n\t\"./vhdl/vhdl.js\": [\n\t\t\"PP56\",\n\t\t0,\n\t\t134\n\t],\n\t\"./vue/vue.js\": [\n\t\t\"aT2M\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t11,\n\t\t7,\n\t\t1,\n\t\t135\n\t],\n\t\"./webidl/webidl.js\": [\n\t\t\"PVgs\",\n\t\t0,\n\t\t136\n\t],\n\t\"./xml/xml.js\": [\n\t\t\"1eCo\",\n\t\t0,\n\t\t137\n\t],\n\t\"./xquery/xquery.js\": [\n\t\t\"bJEP\",\n\t\t0,\n\t\t138\n\t],\n\t\"./yacas/yacas.js\": [\n\t\t\"WThJ\",\n\t\t0,\n\t\t139\n\t],\n\t\"./yaml-frontmatter/yaml-frontmatter.js\": [\n\t\t\"0gIM\",\n\t\t0,\n\t\t1,\n\t\t140\n\t],\n\t\"./yaml/yaml.js\": [\n\t\t\"ztCB\",\n\t\t0,\n\t\t1\n\t],\n\t\"./z80/z80.js\": [\n\t\t\"dRHf\",\n\t\t0,\n\t\t141\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tvar ids = map[req], id = ids[0];\n\treturn Promise.all(ids.slice(1).map(__webpack_require__.e)).then(function() {\n\t\treturn __webpack_require__.t(id, 7);\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = \"TKcc\";\nmodule.exports = webpackAsyncContext;","export const PERMITTED_CONTEXT_MENU_ACTIONS = [\n {\n key: 'log_time',\n link: 'logTime',\n resource: 'workPackage'\n },\n {\n key: 'change_project',\n icon: 'icon-move',\n link: 'move',\n resource: 'workPackage'\n },\n {\n key: 'copy',\n link: 'copy',\n resource: 'workPackage'\n },\n {\n key: 'delete',\n link: 'delete',\n resource: 'workPackage'\n },\n {\n key: 'export-pdf',\n link: 'pdf',\n resource: 'workPackage'\n },\n {\n key: 'export-atom',\n link: 'atom',\n resource: 'workPackage'\n }\n];\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DateDisplayField} from \"core-app/modules/fields/display/field-types/date-display-field.module\";\n\nexport class CombinedDateDisplayField extends DateDisplayField {\n text = {\n placeholder: {\n startDate: this.I18n.t('js.label_no_start_date'),\n dueDate: this.I18n.t('js.label_no_due_date')\n },\n };\n\n public render(element:HTMLElement, displayText:string):void {\n element.innerHTML = '';\n\n let startDateElement = this.createDateDisplayField('startDate');\n let dueDateElement = this.createDateDisplayField('dueDate');\n\n let separator = document.createElement('span');\n separator.textContent = ' - ';\n\n element.appendChild(startDateElement);\n element.appendChild(separator);\n element.appendChild(dueDateElement);\n }\n\n private createDateDisplayField(date:'dueDate'|'startDate'):HTMLElement {\n let dateElement = document.createElement('span');\n let dateDisplayField = new DateDisplayField(date, this.context);\n let text = this.resource[date] ?\n this.timezoneService.formattedDate(this.resource[date]) :\n this.text.placeholder[date];\n\n dateDisplayField.apply(this.resource, this.schema);\n dateDisplayField.render(dateElement, text);\n\n return dateElement;\n }\n}\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n
    \n
    \n \n
    \n \n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n
    \n\n
    \n
    \n \n
    \n
    \n

    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {\n AfterViewInit,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Inject,\n ViewChild\n} from \"@angular/core\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {TypeResource} from \"core-app/modules/hal/resources/type-resource\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\n\n@Component({\n templateUrl: './wp-button-macro.modal.html'\n})\nexport class WpButtonMacroModal extends OpModalComponent implements AfterViewInit {\n\n public changed = false;\n public showClose = true;\n public closeOnEscape = true;\n public closeOnOutsideClick = true;\n\n public selectedType:string;\n public buttonStyle:boolean;\n\n public availableTypes:TypeResource[];\n public type:string = '';\n public classes:string = '';\n\n @ViewChild('typeSelect', { static: true }) typeSelect:ElementRef;\n\n public text:any = {\n title: this.I18n.t('js.editor.macro.work_package_button.button'),\n none: this.I18n.t('js.label_none'),\n selected_type: this.I18n.t('js.editor.macro.work_package_button.type'),\n button_style: this.I18n.t('js.editor.macro.work_package_button.button_style'),\n button_style_hint: this.I18n.t('js.editor.macro.work_package_button.button_style_hint'),\n button_save: this.I18n.t('js.button_save'),\n button_cancel: this.I18n.t('js.button_cancel'),\n close_popup: this.I18n.t('js.close_popup_title')\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n protected currentProject:CurrentProjectService,\n protected apiV3Service:APIV3Service,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n\n super(locals, cdRef, elementRef);\n this.selectedType = this.type = this.locals.type;\n this.classes = this.locals.classes;\n this.buttonStyle = this.classes === 'button';\n\n this\n .apiV3Service\n .withOptionalProject(this.currentProject.identifier)\n .work_packages\n .form\n .post({})\n .subscribe((form:FormResource) => {\n this.availableTypes = form.schema.type.allowedValues;\n });\n }\n\n public applyAndClose(evt:JQuery.TriggeredEvent) {\n this.changed = true;\n this.classes = this.buttonStyle ? 'button' : '';\n this.type = this.selectedType;\n this.closeMe(evt);\n }\n\n ngAfterViewInit() {\n this.typeSelect.nativeElement.focus();\n }\n}\n\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n
    \n
    \n \n
    \n \n \n
    \n
    \n \n
    \n
    \n

    \n

    project-identifier:my-wiki-page

    \n
    \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {AfterViewInit, ChangeDetectorRef, Component, ElementRef, Inject, ViewChild} from \"@angular/core\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n templateUrl: './wiki-include-page-macro.modal.html'\n})\nexport class WikiIncludePageMacroModal extends OpModalComponent implements AfterViewInit {\n\n public changed = false;\n public showClose = true;\n public closeOnEscape = true;\n public closeOnOutsideClick = true;\n\n public selectedPage:string;\n public page:string = '';\n\n @ViewChild('selectedPageInput', { static: true }) selectedPageInput:ElementRef;\n\n public text:any = {\n title: this.I18n.t('js.editor.macro.wiki_page_include.button'),\n hint: this.I18n.t('js.editor.macro.wiki_page_include.hint'),\n page: this.I18n.t('js.editor.macro.wiki_page_include.page'),\n button_save: this.I18n.t('js.button_save'),\n button_cancel: this.I18n.t('js.button_cancel'),\n close_popup: this.I18n.t('js.close_popup_title')\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n\n super(locals, cdRef, elementRef);\n this.selectedPage = this.page = this.locals.page;\n\n // We could provide an autocompleter here to get correct page names\n }\n\n public applyAndClose(evt:JQuery.TriggeredEvent) {\n this.changed = true;\n this.page = this.selectedPage;\n this.closeMe(evt);\n }\n\n ngAfterViewInit() {\n this.selectedPageInput.nativeElement.focus();\n }\n}\n\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n
    \n \n
    \n
    \n \n \n
    \n
    \n \n
    \n
    \n

    \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {AfterViewInit, ChangeDetectorRef, Component, ElementRef, Inject, ViewChild} from \"@angular/core\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n templateUrl: './code-block-macro.modal.html'\n})\nexport class CodeBlockMacroModal extends OpModalComponent implements AfterViewInit {\n\n public changed = false;\n public showClose = true;\n public closeOnEscape = true;\n public closeOnOutsideClick = true;\n\n // Language class from markdown, something like 'language-ruby'\n public languageClass:string;\n\n // Language string, e.g, 'ruby'\n public _language:string = '';\n public content:string;\n\n // Codemirror instance\n public codeMirrorInstance:undefined|any;\n\n public debouncedLanguageLoader = _.debounce(() => this.loadLanguageAsMode(this.language), 300);\n\n @ViewChild('codeMirrorPane', { static: true }) codeMirrorPane:ElementRef;\n\n public text:any = {\n title: this.I18n.t('js.editor.macro.code_block.title'),\n language: this.I18n.t('js.editor.macro.code_block.language'),\n language_hint: this.I18n.t('js.editor.macro.code_block.language_hint'),\n button_save: this.I18n.t('js.button_save'),\n button_cancel: this.I18n.t('js.button_cancel'),\n close_popup: this.I18n.t('js.close_popup_title')\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n\n super(locals, cdRef, elementRef);\n this.languageClass = locals.languageClass || 'language-text';\n this.content = locals.content;\n\n const match = this.languageClass.match(/language-(\\w+)/);\n if (match) {\n this.language = match[1];\n } else {\n this.language = 'text';\n }\n }\n\n public applyAndClose(evt:JQuery.TriggeredEvent) {\n this.content = this.codeMirrorInstance.getValue();\n const lang = this.language || 'text';\n this.languageClass = `language-${lang}`;\n\n this.changed = true;\n this.closeMe(evt);\n }\n\n ngAfterViewInit() {\n import('codemirror').then((imported:any) => {\n const CodeMirror = imported.default;\n this.codeMirrorInstance = CodeMirror.fromTextArea(\n this.codeMirrorPane.nativeElement,\n {\n lineNumbers: true,\n smartIndent: true,\n autofocus: true,\n value: this.content,\n mode: ''\n }\n );\n });\n }\n\n get language() {\n return this._language;\n }\n\n set language(val:string) {\n this._language = val;\n this.debouncedLanguageLoader();\n }\n\n loadLanguageAsMode(language:string) {\n // For the special language 'text', don't try to load anything\n if (!language || language === 'text') {\n return this.updateCodeMirrorMode('');\n }\n\n import(/* webpackChunkName: \"codemirror-mode\" */ `codemirror/mode/${language}/${language}.js`)\n .then(() => {\n this.updateCodeMirrorMode(language);\n })\n .catch((e) => {\n console.error(`Failed to load language ${language}: ${e}`);\n this.updateCodeMirrorMode('');\n });\n }\n\n updateCodeMirrorMode(newLanguage:string) {\n const editor = this.codeMirrorInstance;\n editor && editor.setOption('mode', newLanguage);\n }\n\n updateLanguage(newValue?:string) {\n if (!newValue) {\n this.language = '';\n return;\n }\n\n if (newValue.match(/^\\w+$/)) {\n this.language = newValue;\n } else {\n console.error(\"Not updating non-matching language: \" + newValue);\n }\n }\n}\n\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n
    \n
    \n \n
    \n \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n

    \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {AfterViewInit, ChangeDetectorRef, Component, ElementRef, Inject, ViewChild} from \"@angular/core\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n templateUrl: './child-pages-macro.modal.html'\n})\nexport class ChildPagesMacroModal extends OpModalComponent implements AfterViewInit {\n\n public changed = false;\n public showClose = true;\n public closeOnEscape = true;\n public closeOnOutsideClick = true;\n\n public selectedPage:string;\n public selectedIncludeParent:boolean;\n public page:string = '';\n public includeParent:boolean = false;\n\n @ViewChild('selectedPageInput', { static: true }) selectedPageInput:ElementRef;\n\n public text:any = {\n title: this.I18n.t('js.editor.macro.child_pages.button'),\n hint: this.I18n.t('js.editor.macro.child_pages.hint'),\n page: this.I18n.t('js.editor.macro.child_pages.page'),\n include_parent: this.I18n.t('js.editor.macro.child_pages.include_parent'),\n button_save: this.I18n.t('js.button_save'),\n button_cancel: this.I18n.t('js.button_cancel'),\n close_popup: this.I18n.t('js.close_popup_title')\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n\n super(locals, cdRef, elementRef);\n this.selectedPage = this.page = this.locals.page;\n this.selectedIncludeParent = this.includeParent = this.locals.includeParent;\n\n // We could provide an autocompleter here to get correct page names\n }\n\n public applyAndClose(evt:JQuery.TriggeredEvent) {\n this.changed = true;\n this.page = this.selectedPage;\n this.includeParent = this.selectedIncludeParent;\n this.closeMe(evt);\n }\n\n ngAfterViewInit() {\n this.selectedPageInput.nativeElement.focus();\n }\n\n updateIncludeParent(val:boolean) {\n this.selectedIncludeParent = val;\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {Injectable, Injector} from \"@angular/core\";\nimport {WpButtonMacroModal} from \"core-components/modals/editor/macro-wp-button-modal/wp-button-macro.modal\";\nimport {WikiIncludePageMacroModal} from \"core-components/modals/editor/macro-wiki-include-page-modal/wiki-include-page-macro.modal\";\nimport {CodeBlockMacroModal} from \"core-components/modals/editor/macro-code-block-modal/code-block-macro.modal\";\nimport {ChildPagesMacroModal} from \"core-components/modals/editor/macro-child-pages-modal/child-pages-macro.modal\";\n\n@Injectable()\nexport class EditorMacrosService {\n\n constructor(readonly opModalService:OpModalService,\n readonly injector:Injector) {\n }\n\n /**\n * Show a modal to edit the work package button macro settings.\n * Used from within ckeditor.\n */\n public configureWorkPackageButton(typeName?:string, classes?:string):Promise<{ type:string, classes:string }> {\n return new Promise<{ type:string, classes:string }>((resolve, reject) => {\n const modal = this.opModalService.show(WpButtonMacroModal, this.injector, { type: typeName, classes: classes });\n modal.closingEvent.subscribe((modal:WpButtonMacroModal) => {\n if (modal.changed) {\n resolve({type: modal.type, classes: modal.classes});\n }\n });\n });\n }\n\n /**\n * Show a modal to edit the wiki include macro.\n * Used from within ckeditor.\n */\n public configureWikiPageInclude(page:string):Promise {\n return new Promise((resolve, _) => {\n const pageValue = page || '';\n const modal = this.opModalService.show(WikiIncludePageMacroModal, this.injector, { page: pageValue });\n modal.closingEvent.subscribe((modal:WikiIncludePageMacroModal) => {\n if (modal.changed) {\n resolve(modal.page);\n }\n });\n });\n }\n\n /**\n * Show a modal to show an enhanced code editor for editing code blocks.\n * Used from within ckeditor.\n */\n public editCodeBlock(content:string, languageClass:string):Promise<{ content:string, languageClass:string }> {\n return new Promise<{ content:string, languageClass:string }>((resolve, _) => {\n const modal = this.opModalService.show(CodeBlockMacroModal, this.injector, { content: content, languageClass: languageClass });\n modal.closingEvent.subscribe((modal:CodeBlockMacroModal) => {\n if (modal.changed) {\n resolve({languageClass: modal.languageClass, content: modal.content});\n }\n });\n });\n }\n\n /**\n * Show a modal to edit the child pages macro.\n * Used from within ckeditor.\n */\n public configureChildPages(page:string, includeParent:string):Promise {\n return new Promise((resolve, _) => {\n const modal = this.opModalService.show(ChildPagesMacroModal, this.injector,{ page: page, includeParent: includeParent });\n modal.closingEvent.subscribe((modal:ChildPagesMacroModal) => {\n if (modal.changed) {\n resolve({\n page: modal.page,\n includeParent: modal.includeParent\n });\n }\n });\n });\n }\n}\n","import {Component, Input, OnInit} from \"@angular/core\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\n\n@Component({\n selector: 'activity-link',\n template: `\n \n \n `\n})\nexport class ActivityLinkComponent implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public activityNo:number;\n\n public activityHtmlId:string;\n public activityLabel:string;\n\n ngOnInit() {\n this.activityHtmlId = `activity-${this.activityNo}`;\n this.activityLabel = `#${this.activityNo}`;\n }\n}\n\nfunction activityLink() {\n return {\n restrict: 'E',\n template: `\n `,\n scope: {\n },\n link: function(scope:any) {\n scope.workPackageId = scope.workPackage.id!;\n scope.activityHtmlId = 'activity-' + scope.activityNo;\n }\n };\n}\n","
    \n
    \n \n \n
    \n\n \n \n\n \n \n\n \n \n \n \n \n \n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit} from \"@angular/core\";\n\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'revision-activity',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './revision-activity.component.html'\n})\nexport class RevisionActivityComponent implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public activity:any;\n @Input() public activityNo:number;\n\n public userId:string | number;\n public userName:string;\n public userActive:boolean;\n public userPath:string | null;\n public userLabel:string;\n public userAvatar:string;\n\n public project:ProjectResource;\n public revision:string;\n public message:string;\n\n public revisionLink:string;\n\n constructor(readonly I18n:I18nService,\n readonly timezoneService:TimezoneService,\n readonly cdRef:ChangeDetectorRef,\n readonly apiV3Service:APIV3Service) {\n }\n\n ngOnInit() {\n this.loadAuthor();\n\n this.project = this.workPackage.project;\n this.revision = this.activity.identifier;\n this.message = this.activity.message.html;\n\n const revisionPath = this.activity.showRevision.$link.href;\n const formattedRevision = this.activity.formattedIdentifier;\n\n const link = document.createElement('a');\n link.href = revisionPath;\n link.title = this.revision;\n link.textContent = this.I18n.t(\n \"js.label_committed_link\",\n {revision_identifier: formattedRevision}\n );\n\n this.revisionLink = this.I18n.t(\"js.label_committed_at\",\n {\n committed_revision_link: link.outerHTML,\n date: this.timezoneService.formattedDatetime(this.activity.createdAt)\n });\n }\n\n private loadAuthor() {\n if (this.activity.author === undefined) {\n this.userName = this.activity.authorName;\n } else {\n this\n .apiV3Service\n .users\n .id(this.activity.author.idFromLink)\n .get()\n .subscribe((user:UserResource) => {\n this.userId = user.id!;\n this.userName = user.name;\n this.userActive = user.isActive;\n this.userAvatar = user.avatar;\n this.userPath = user.showUser.href;\n this.userLabel = this.I18n.t('js.label_author', {user: this.userName});\n this.cdRef.detectChanges();\n });\n }\n }\n}\n","/**\n * Allows to dynamically render an HTML string into any HTML node, dynamically\n * bootstrapping all its Angular components and directives.\n *\n * ```\n * \">\n * \n * ```\n * @module\n * @public\n */\nimport {ApplicationRef, Component, ElementRef, Input} from '@angular/core';\nimport {DomSanitizer, SafeHtml} from '@angular/platform-browser';\nimport {DynamicBootstrapper} from 'core-app/globals/dynamic-bootstrapper';\n\n@Component({\n selector: 'op-dynamic-bootstrap',\n templateUrl: './dynamic-bootstrap.component.html',\n})\nexport class DynamicBootstrapComponent {\n /*\n * HTML string to be rendered.\n */\n @Input()\n set HTML(templateString:string) {\n this.innerHtml = this.domSanitizer.bypassSecurityTrustHtml(templateString);\n this.dynamicBootstrapper.bootstrapOptionalEmbeddable(this.appRef, this.elementRef.nativeElement);\n }\n\n innerHtml:SafeHtml;\n dynamicBootstrapper = DynamicBootstrapper;\n\n constructor(\n readonly domSanitizer:DomSanitizer,\n readonly elementRef:ElementRef,\n readonly appRef:ApplicationRef,\n ) { }\n}\n","
    \n \n \n\n \n \n \n \n {{ isInitial ? text.label_created_on : text.label_updated_on }}\n \n \n
    \n \n \n
    \n \n \n \n \n \n \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n \n \n
      \n
    • \n \n
    • \n
    \n
    \n
    \n","
    ","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackagesActivityService} from 'core-components/wp-single-view-tabs/activity-panel/wp-activity.service';\nimport {\n ApplicationRef,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input, NgZone,\n OnInit\n} from \"@angular/core\";\nimport {CommentService} from \"core-components/wp-activity/comment-service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageCommentFieldHandler} from \"core-components/work-packages/work-package-comment/work-package-comment-field-handler\";\nimport {DomSanitizer, SafeHtml} from \"@angular/platform-browser\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'user-activity',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './user-activity.component.html'\n})\nexport class UserActivityComponent extends WorkPackageCommentFieldHandler implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public activity:HalResource;\n @Input() public activityNo:number;\n @Input() public isInitial:boolean;\n\n public userCanEdit = false;\n public userCanQuote = false;\n\n public userId:string | number;\n public user:UserResource;\n public userName:string;\n public userAvatar:string;\n public details:any[] = [];\n public isComment:boolean;\n public isBcfComment:boolean;\n public postedComment:SafeHtml;\n\n public focused = false;\n\n public text = {\n label_created_on: this.I18n.t('js.label_created_on'),\n label_updated_on: this.I18n.t('js.label_updated_on'),\n quote_comment: this.I18n.t('js.label_quote_comment'),\n edit_comment: this.I18n.t('js.label_edit_comment'),\n };\n\n private $element:JQuery;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly sanitization:DomSanitizer,\n readonly PathHelper:PathHelperService,\n readonly wpLinkedActivities:WorkPackagesActivityService,\n readonly commentService:CommentService,\n readonly ConfigurationService:ConfigurationService,\n readonly apiV3Service:APIV3Service,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService,\n readonly ngZone:NgZone,\n protected appRef:ApplicationRef) {\n super(elementRef, injector);\n }\n\n public ngOnInit() {\n super.ngOnInit();\n\n\n this.htmlId = `user_activity_edit_field_${this.activityNo}`;\n this.updateCommentText();\n this.isComment = this.activity._type === 'Activity::Comment';\n this.isBcfComment = this.activity._type === 'Activity::BcfComment';\n\n this.$element = jQuery(this.elementRef.nativeElement);\n this.reset();\n this.userCanEdit = !!this.activity.update;\n this.userCanQuote = !!this.workPackage.addComment;\n\n this.$element.bind('focusin', this.focus.bind(this));\n this.$element.bind('focusout', this.blur.bind(this));\n\n _.each(this.activity.details, (detail:any) => {\n this.details.push(detail.html);\n });\n\n this\n .apiV3Service\n .users\n .id(this.activity.user.idFromLink)\n .get()\n .subscribe((user:UserResource) => {\n this.user = user;\n this.userId = user.id!;\n this.userName = user.name;\n this.userAvatar = user.avatar;\n this.cdRef.detectChanges();\n });\n\n if (window.location.hash === `#activity-${this.activityNo}`) {\n this.ngZone.runOutsideAngular(() => {\n setTimeout(() => {\n this.elementRef.nativeElement.scrollIntoView(true);\n });\n });\n }\n }\n\n public shouldHideIcons():boolean {\n return !((this.isComment || this.isBcfComment) && this.focussing());\n }\n\n public activate() {\n super.activate(this.activity.comment.raw);\n this.cdRef.detectChanges();\n }\n\n public handleUserSubmit() {\n if (this.inFlight || !this.rawComment) {\n return Promise.resolve();\n }\n return this.updateComment();\n }\n\n public quoteComment() {\n this.commentService.quoteEvents.next(this.quotedText(this.activity.comment.raw));\n }\n\n public get bcfSnapshotUrl() {\n if (_.get(this.activity, 'bcfViewpoints[0]')) {\n return `${_.get(this.activity, 'bcfViewpoints[0]').href}/snapshot`;\n } else {\n return null;\n }\n }\n\n public async updateComment() {\n this.inFlight = true;\n\n await this.onSubmit();\n return this.commentService.updateComment(this.activity, this.rawComment || '')\n .then((newActivity:HalResource) => {\n this.activity = newActivity;\n this.updateCommentText();\n this.wpLinkedActivities.require(this.workPackage, true);\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(this.workPackage);\n })\n .finally(() => {\n this.deactivate(true); this.inFlight = false;\n });\n }\n\n public focusEditIcon() {\n // Find the according edit icon and focus it\n jQuery('.edit-activity--' + this.activityNo + ' a').focus();\n }\n\n public focus() {\n this.focused = true;\n this.cdRef.detectChanges();\n }\n\n public blur() {\n this.focused = false;\n this.cdRef.detectChanges();\n }\n\n public focussing() {\n return this.focused;\n }\n\n setErrors(newErrors:string[]):void {\n // interface\n }\n\n public quotedText(rawComment:string) {\n let quoted = rawComment.split('\\n')\n .map(function(line:string) {\n return '\\n> ' + line;\n })\n .join('');\n return this.userName + ' wrote:\\n' + quoted;\n }\n\n deactivate(focus:boolean):void {\n super.deactivate(focus);\n\n if (focus) {\n this.focusEditIcon();\n }\n }\n\n private updateCommentText() {\n this.postedComment = this.activity.comment.html;\n }\n}\n","
    \n
    \n \n \n \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, OnInit} from \"@angular/core\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n\n@Component({\n selector: 'activity-entry',\n templateUrl: './activity-entry.component.html'\n})\nexport class ActivityEntryComponent implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public activity:any;\n @Input() public activityNo:number;\n @Input() public isInitial:boolean;\n\n public projectId:string;\n public activityType:string;\n\n constructor(readonly PathHelper:PathHelperService,\n readonly I18n:I18nService) {\n }\n\n\n ngOnInit() {\n this.projectId = this.workPackage.project.idFromLink;\n\n this.activityType = this.activity._type;\n }\n}\n\n","export const demoProjectName = 'Demo project';\nexport const scrumDemoProjectName = 'Scrum project';\nexport const onboardingTourStorageKey = 'openProject-onboardingTour';\nexport type OnboardingTourNames = 'backlogs'|'taskboard'|'homescreen'|'main';\n\nexport function waitForElement(element:string, container:string, execFunction:Function) {\n // Wait for the element to be ready\n var observer = new MutationObserver(function (mutations, observerInstance) {\n if (jQuery(element).length) {\n observerInstance.disconnect(); // stop observing\n execFunction();\n return;\n }\n });\n observer.observe(jQuery(container)[0], {\n childList: true,\n subtree: true\n });\n}\n\nexport function demoProjectsLinks() {\n let demoProjects = [];\n let demoProjectsLink = jQuery(\".widget-box.welcome a:contains(\" + demoProjectName + \")\");\n let scrumDemoProjectsLink = jQuery(\".widget-box.welcome a:contains(\" + scrumDemoProjectName + \")\");\n\n if (demoProjectsLink.length) {\n demoProjects.push(demoProjectsLink);\n }\n if (scrumDemoProjectsLink.length) {\n demoProjects.push(scrumDemoProjectsLink);\n }\n\n return demoProjects;\n}\n\nexport function preventClickHandler(e:any) {\n e.preventDefault();\n e.stopPropagation();\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nexport class PaginationInstance {\n\n constructor(public page:number,\n public total:number,\n public perPage:number) {\n }\n\n public getLowerPageBound() {\n return this.perPage * (this.page - 1) + 1;\n }\n\n public getUpperPageBound(limit:number) {\n return Math.min(this.perPage * this.page, limit);\n }\n\n public nextPage() {\n this.page += 1;\n }\n\n public previousPage() {\n this.page -= 1;\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nexport type WorkPackageTableConfigurationObject = Partial<{ [field in keyof WorkPackageTableConfiguration]:string|boolean }>;\n\nexport class WorkPackageTableConfiguration {\n /** Render the table results, set to false when only wanting the table initialization */\n public tableVisible:boolean = true;\n\n /** Render the table as compact style */\n public compactTableStyle:boolean = false;\n\n /** Render the action column (last column) with the actions defined in the TableActionsService */\n public actionsColumnEnabled:boolean = true;\n\n /** Whether the work package context menu is enabled*/\n public contextMenuEnabled:boolean = true;\n\n /** Whether the column dropdown menu is enabled*/\n public columnMenuEnabled:boolean = true;\n\n /** Whether the query should be resolved using the current project identifier */\n public projectContext:boolean = true;\n\n /** Whether the embedded table should live within a specific project context (e.g., given by its parent) */\n public projectIdentifier:string|null = null;\n\n /** Whether inline create is enabled*/\n public inlineCreateEnabled:boolean = true;\n\n /** Whether the hierarchy toggler item in the subject column is enabled */\n public hierarchyToggleEnabled:boolean = true;\n\n /** Whether this table supports drag and drop */\n public dragAndDropEnabled:boolean = false;\n\n /** Whether this table is in an embedded context*/\n public isEmbedded:boolean = false;\n\n /** Whether the work packages shall be shown in cards instead of a table */\n public isCardView:boolean = false;\n\n /** Whether this table provides a UI for filters*/\n public withFilters:boolean = false;\n\n /** Whether the filters are expanded */\n public filtersExpanded:boolean = false;\n\n /** Whether the button to open filters shall be visible*/\n public showFilterButton:boolean = false;\n\n /** Whether this table provides a UI for filters*/\n public filterButtonText:string = I18n.t(\"js.button_filter\");\n\n constructor(providedConfig:WorkPackageTableConfigurationObject) {\n _.each(providedConfig, (value, k) => {\n let key = (k as keyof WorkPackageTableConfiguration);\n (this as any)[key] = value;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackagesListService} from '../../wp-list/wp-list.service';\nimport {States} from '../../states.service';\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {ChangeDetectorRef, Component, ElementRef, Inject, OnInit} from \"@angular/core\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {StateService} from '@uirouter/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageService} from \"core-components/work-packages/work-package.service\";\nimport {BackRoutingService} from \"core-app/modules/common/back-routing/back-routing.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Component({\n templateUrl: './wp-destroy.modal.html'\n})\nexport class WpDestroyModal extends OpModalComponent implements OnInit {\n // When deleting multiple\n public workPackages:WorkPackageResource[];\n public workPackageLabel:string;\n\n // Single work package\n public singleWorkPackage:WorkPackageResource;\n public singleWorkPackageChildren:WorkPackageResource[];\n public busy = false;\n\n // Need to confirm deletion when children are involved\n public childrenDeletionConfirmed = false;\n\n public text:any = {\n label_visibility_settings: this.I18n.t('js.label_visibility_settings'),\n button_save: this.I18n.t('js.modals.button_save'),\n confirm: this.I18n.t('js.button_confirm'),\n warning: this.I18n.t('js.label_warning'),\n cancel: this.I18n.t('js.button_cancel'),\n close: this.I18n.t('js.close_popup_title'),\n label_confirm_children_deletion: this.I18n.t('js.modals.destroy_work_package.confirm_deletion_children'),\n };\n\n constructor(readonly elementRef:ElementRef,\n readonly WorkPackageService:WorkPackageService,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly $state:StateService,\n readonly states:States,\n readonly wpTableFocus:WorkPackageViewFocusService,\n readonly wpListService:WorkPackagesListService,\n readonly notificationService:WorkPackageNotificationService,\n readonly backRoutingService:BackRoutingService) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n super.ngOnInit();\n\n this.workPackages = this.locals.workPackages;\n this.workPackageLabel = this.I18n.t('js.units.workPackage', { count: this.workPackages.length });\n\n // Ugly way to provide the same view bindings as the ng-init in the previous template.\n if (this.workPackages.length === 1) {\n this.singleWorkPackage = this.workPackages[0];\n this.singleWorkPackageChildren = this.singleWorkPackage.children;\n }\n\n this.text.title = this.I18n.t('js.modals.destroy_work_package.title', { label: this.workPackageLabel }),\n this.text.text = this.I18n.t('js.modals.destroy_work_package.text', {\n label: this.workPackageLabel,\n count: this.workPackages.length\n });\n\n this.text.childCount = (wp:WorkPackageResource) => {\n const count = this.children(wp).length;\n return this.I18n.t('js.units.child_work_packages', { count: count });\n };\n\n this.text.hasChildren = (wp:WorkPackageResource) =>\n this.I18n.t('js.modals.destroy_work_package.has_children', { childUnits: this.text.childCount(wp) }),\n\n this.text.deletesChildren = this.I18n.t('js.modals.destroy_work_package.deletes_children');\n }\n\n public get blockedDueToUnconfirmedChildren() {\n return this.mustConfirmChildren && !this.childrenDeletionConfirmed;\n }\n\n public get mustConfirmChildren() {\n let result = false;\n\n if (this.singleWorkPackage && this.singleWorkPackageChildren) {\n let result = this.singleWorkPackageChildren.length > 0;\n }\n\n return result || !!_.find(this.workPackages, wp =>\n wp.children && wp.children.length > 0);\n }\n\n public confirmDeletion($event:JQuery.TriggeredEvent) {\n if (this.busy || this.blockedDueToUnconfirmedChildren) {\n return false;\n }\n\n this.busy = true;\n this.WorkPackageService.performBulkDelete(this.workPackages.map(el => el.id!), true)\n .then(() => {\n this.busy = false;\n this.closeMe($event);\n this.wpTableFocus.clear('Clearing after destroying work packages');\n\n // Go back to a previous list state if we're in a split or full view\n if (this.$state.current.data.baseRoute) {\n this.backRoutingService.goBack(true);\n }\n })\n .catch(() => {\n this.busy = false;\n });\n\n return false;\n }\n\n public children(workPackage:WorkPackageResource) {\n if (workPackage.hasOwnProperty('children')) {\n return workPackage.children;\n } else {\n return [];\n }\n }\n}\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n \n

    \n \n
    \n \n {{ singleWorkPackage.type.name }}\n #{{ singleWorkPackage.id }}\n {{ singleWorkPackage.subject }}\n \n

    \n
    0\">\n

    \n \n :\n \n

    \n
      \n
    • \n #\n \n
    • \n
    \n

    \n \n

    \n
    \n
    \n 1\">\n

    \n \n \n

    \n
      \n
    • \n #\n &ngsp;\n \n 0\">\n (+ {{ text.childCount(wp) }})\n \n
    • \n
    \n
    \n
    \n \n
    \n
    \n\n
    \n \n \n
    \n
    \n
    \n","import {debugLog, timeOutput} from \"core-app/helpers/debug_output\";\nimport {QueryOrder} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-order\";\n\n// min allowed position\nexport const MIN_ORDER = -2147483647;\n// max postgres 4-byte integer position\nexport const MAX_ORDER = 2147483647;\n// default position to insert\nexport const DEFAULT_ORDER = 0;\n// The distance to keep between each element\nexport const ORDER_DISTANCE = 16384;\n\n/**\n * Computes the delta of positions for a given\n * operation and order\n */\nexport class ReorderDeltaBuilder {\n\n // We are building a delta of positions we need to update\n // ideally this will only be one, but more may need to be set (initially)\n // or shifted in case of spacing issues\n private delta:QueryOrder = {};\n\n /**\n * Create a delta builder\n *\n * @param order The current order of work packages that contains the user movement\n * @param positions The current positions as loaded from backend / persisted from previous calls\n * @param wpId The work package that got moved\n * @param index The index a work package got moved into\n * @param fromIndex If moved within the order, the previous index used for movement optimzation\n */\n constructor(readonly order:string[],\n readonly positions:QueryOrder,\n readonly wpId:string,\n readonly index:number,\n readonly fromIndex:number|null) {\n }\n\n public buildDelta():QueryOrder {\n timeOutput(`Building delta for ${this.wpId}@${this.index}`, () => {\n\n // Ensure positions are strictly ascending. There may be cases were this does not happen\n // e.g., having a flat sorted list and turning on hierarchy mode\n if (!this.isAscendingOrder()) {\n this.rebuildPositions();\n } else {\n // Insert only the new element\n this.buildInsertPosition();\n }\n });\n\n debugLog(\"Order DELTA was built as %O\", this.delta);\n\n return this.delta;\n }\n\n\n /**\n * Ensure +order+ is already ascending with the exception of +index+,\n * or otherwise reorder the positions starting from the first element.\n */\n private isAscendingOrder() {\n let current:number|undefined;\n\n for (let i = 0, l = this.order.length; i < l; i++) {\n const id = this.order[i];\n const position = this.positions[id];\n\n // Skip our insertion point\n if (i === this.index) {\n continue;\n }\n\n // If neither position is set\n if (current === undefined || position === undefined) {\n current = position;\n continue;\n }\n\n // If the next position is not larger, rebuild positions\n if (position < current) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Reassign mixed positions so that they are strictly ascending again,\n * but try to keep relative positions alive\n */\n private rebuildPositions() {\n let [min, max] = this.minMaxPositions;\n this.redistribute(min, max);\n }\n\n /**\n * Insert +wpId+ at +index+ in a position that is determined either\n * by its neighbors, one of them in case both do not yet have a position\n */\n private buildInsertPosition() {\n // Special case, order is empty or only contains wpId\n // Then simply insert as the default position unless it already has a position\n if (this.order.length <= 1 && this.positions[this.wpId] === undefined) {\n this.delta[this.wpId] = DEFAULT_ORDER;\n return;\n }\n\n // Special case, shifted movement by one\n if (this.fromIndex !== null && Math.abs(this.fromIndex - this.index) === 1 && this.positionSwap()) {\n return;\n }\n\n // Special case, index is 0\n if (this.index === 0) {\n return this.insertAsFirst();\n }\n\n // Ensure previous positions exist so we can insert wpId @ index\n const predecessorPosition = this.buildUpPredecessorPosition();\n\n // Ensure we reorder when predecessor is at max already\n if (predecessorPosition >= MAX_ORDER) {\n debugLog(`Predecessor position is at max order, need to reorder`);\n return this.reorderedInsert();\n }\n\n // Get the actual successor position, it might vary wildly from the optimal position\n const successorPosition = this.positionFor(this.index + 1);\n\n if (successorPosition === undefined) {\n // Successor does not have a position yet (is NULL), any position will work\n // so let's use the optimal one which is halfway to a potential successor\n this.delta[this.wpId] = predecessorPosition + (ORDER_DISTANCE / 2);\n return;\n }\n\n // Ensure we reorder when successor is at max already\n if (successorPosition >= MAX_ORDER) {\n debugLog(`Successor position is at max order, need to reorder`);\n return this.reorderedInsert();\n }\n\n // successor exists and has a position\n // We will want to insert at the half way from predecessorPosition ... successorPosition\n const distance = Math.floor((successorPosition - predecessorPosition) / 2);\n\n // If there is no space to insert, we're going to optimize the available space\n if (distance < 1) {\n debugLog(\"Cannot insert at optimal position, no space left. Need to reorder\");\n return this.reorderedInsert();\n }\n\n this.delta[this.wpId] = predecessorPosition + distance;\n }\n\n /**\n * Insert wpId as the first element\n */\n private insertAsFirst() {\n // Get the actual successor position, it might vary wildly from the optimal position\n const successorPosition = this.positionFor(this.index + 1);\n\n // If the successor also has no position yet, simply assign the default\n if (successorPosition === undefined) {\n this.delta[this.wpId] = DEFAULT_ORDER;\n } else {\n this.delta[this.wpId] = successorPosition - (ORDER_DISTANCE / 2);\n }\n }\n\n /**\n * Since from and to index or only one apart,\n * we can swap the positions.\n */\n private positionSwap():boolean {\n const myPosition = this.positionFor(this.index!);\n const neighbor = this.order[this.fromIndex!];\n const neighborPosition = this.positionFor(this.fromIndex!);\n\n // If either the neighbor or wpid have no position yet,\n // go through the regular update flow\n if (myPosition === undefined || neighborPosition === undefined) {\n return false;\n }\n\n // Simply swap the two positions\n this.delta[this.wpId] = neighborPosition;\n this.delta[neighbor] = myPosition;\n\n return true;\n }\n\n\n /**\n * Builds any previous unset position from 0 .. index\n * so we can properly insert the wpId @ index.\n */\n private buildUpPredecessorPosition() {\n let predecessorPosition:number = DEFAULT_ORDER - ORDER_DISTANCE;\n\n for (let i = 0; i < this.index; i++) {\n const id = this.order[i];\n const position = this.positions[id];\n\n // If this current ID has no position yet, assign the current one\n if (position === undefined) {\n predecessorPosition = this.delta[id] = predecessorPosition + ORDER_DISTANCE;\n } else {\n predecessorPosition = position;\n }\n }\n\n return predecessorPosition;\n }\n\n /**\n * Return the position number for the given index\n */\n private positionFor(index:number):number|undefined {\n const wpId = this.order[index];\n return this.livePosition(wpId);\n }\n\n /**\n * Return either the delta position or the previous persisted position,\n * in that order.\n *\n * @param wpId\n */\n private livePosition(wpId:string):number|undefined {\n // Explicitly check for undefined here as the delta might be 0 which is falsey.\n return this.delta[wpId] === undefined ? this.positions[wpId] : this.delta[wpId];\n }\n\n /**\n * There was no space left at the desired insert position,\n * we're going to evenly distribute all items again\n */\n private reorderedInsert() {\n // Get the current distance between orders\n // Both must be set by now due to +buildUpPredecessorPosition+ having run.\n let min = this.firstPosition!;\n let max = this.lastPosition!;\n\n this.redistribute(min, max);\n }\n\n /**\n * Distribute the items over a given min/max\n */\n private redistribute(min:number, max:number) {\n const itemsToDistribute = this.order.length;\n\n // We can keep min and max orders if distance/(items to distribute) >= 1\n let space = Math.floor((max - min) / (itemsToDistribute - 1));\n\n // If no space is left, first try to add to the max item\n // Or subtract from the min item\n if (space < 1) {\n if ((max + itemsToDistribute) <= MAX_ORDER) {\n max += itemsToDistribute;\n } else if ((min - itemsToDistribute) >= MIN_ORDER) {\n min -= itemsToDistribute;\n } else {\n // This should not happen in a 4-byte integer with our frontend\n throw \"Elements cannot be moved further and no space is left. Too many elements\";\n }\n\n // Rebuild space\n space = Math.floor((max - min) / (itemsToDistribute - 1));\n }\n\n // Assign positions for all values in between min/max\n for (let i = 0; i < itemsToDistribute; i++) {\n const wpId = this.order[i];\n this.delta[wpId] = min + (i * space);\n }\n }\n\n /**\n * Get the absolute minimum and maximum positions\n * currently assigned in the slot.\n *\n * If there is at least two positions assigned, returns the maximum\n * between them.\n *\n * Otherwise, returns the optimum min max for the given order length.\n */\n private get minMaxPositions():[number, number] {\n let min:number = MAX_ORDER;\n let max:number = MIN_ORDER;\n let any:boolean = false;\n\n for (let i = this.order.length - 1; i >= 0; i--) {\n let wpId = this.order[i];\n let position = this.livePosition(wpId);\n\n if (position !== undefined) {\n min = Math.min(position, min);\n max = Math.max(position, max);\n any = true;\n }\n }\n\n if (any && min !== max) {\n return [min, max];\n } else {\n return [DEFAULT_ORDER, this.order.length * ORDER_DISTANCE];\n }\n }\n\n\n /**\n * Returns the minimal position assigned currently\n */\n private get firstPosition():number {\n const wpId = this.order[0]!;\n return this.livePosition(wpId)!;\n }\n\n /**\n * Returns the maximum position assigned currently.\n * Note that a list can be unpositioned at the beginning, so this may return undefined\n */\n private get lastPosition():number|undefined {\n for (let i = this.order.length - 1; i >= 0; i--) {\n let wpId = this.order[i];\n let position = this.livePosition(wpId);\n\n // Return the first set position.\n if (position !== undefined) {\n return position;\n }\n }\n\n return;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {Injectable} from '@angular/core';\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {States} from \"core-components/states.service\";\nimport {QuerySchemaResource} from \"core-app/modules/hal/resources/query-schema-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {MAX_ORDER, ReorderDeltaBuilder} from \"core-app/modules/common/drag-and-drop/reorder-delta-builder\";\nimport {take} from \"rxjs/operators\";\nimport {InputState} from \"reactivestates\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {CausedUpdatesService} from \"core-app/modules/boards/board/caused-updates/caused-updates.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {QueryOrder} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-order\";\n\n\n@Injectable()\nexport class WorkPackageViewOrderService extends WorkPackageQueryStateService {\n\n constructor(protected readonly querySpace:IsolatedQuerySpace,\n protected readonly apiV3Service:APIV3Service,\n protected readonly states:States,\n protected readonly causedUpdates:CausedUpdatesService,\n protected readonly wpTableSortBy:WorkPackageViewSortByService,\n protected readonly pathHelper:PathHelperService) {\n super(querySpace);\n }\n\n public initialize(query:QueryResource, results:WorkPackageCollectionResource, schema?:QuerySchemaResource):Promise {\n // Take over our current value if the query is not saved\n if (!query.persisted && this.positions.hasValue()) {\n this.applyToQuery(query);\n }\n\n\n if (this.wpTableSortBy.isManualSortingMode) {\n return this.withLoadedPositions();\n }\n\n return Promise.resolve();\n }\n\n /**\n * Move an item in the list\n */\n public async move(order:string[], wpId:string, toIndex:number):Promise {\n // Find index of the work package\n let fromIndex:number = order.findIndex((id) => id === wpId);\n\n order.splice(fromIndex, 1);\n order.splice(toIndex, 0, wpId);\n\n await this.assignPosition(order, wpId, toIndex, fromIndex);\n\n return order;\n }\n\n /**\n * Pull an item from the rendered list\n */\n public remove(order:string[], wpId:string):string[] {\n _.remove(order, id => id === wpId);\n this.update({ [wpId]: -1 });\n return order;\n }\n\n /**\n * Add an item to the list\n */\n public async add(order:string[], wpId:string, toIndex:number = -1):Promise {\n if (toIndex === -1) {\n order.push(wpId);\n toIndex = order.length - 1;\n } else {\n order.splice(toIndex, 0, wpId);\n }\n\n await this.assignPosition(order, wpId, toIndex);\n\n return order;\n }\n\n public get applicable() {\n return this.currentQuery.persisted;\n }\n\n protected get currentQuery():QueryResource {\n return this.querySpace.query.value!;\n }\n\n /**\n * Assign a position for the given work package and its index given the current order\n * @param order Current order the work package was inserted to\n * @param wpId The work package ID that was moved\n * @param toIndex The id of the work package in order\n */\n protected async assignPosition(order:string[], wpId:string, toIndex:number, fromIndex:number|null = null) {\n const positions = await this.withLoadedPositions();\n const delta = new ReorderDeltaBuilder(order, positions, wpId, toIndex, fromIndex).buildDelta();\n\n await this.update(delta);\n }\n\n protected get positions():InputState {\n return this.updatesState;\n }\n\n /**\n * Update the order state\n */\n public async update(delta:QueryOrder) {\n let current = this.positions.getValueOr({});\n this.positions.putValue({ ...current, ...delta });\n\n // Push the update if the query is saved\n if (this.currentQuery.persisted) {\n const updatedAt = await this\n .apiV3Service\n .queries.id(this.currentQuery)\n .order\n .update(delta);\n\n this.currentQuery.updatedAt = updatedAt;\n\n // Remember that we caused this update\n this.causedUpdates.add(this.currentQuery);\n }\n\n // Push into the query object\n this.applyToQuery(this.currentQuery);\n\n // Update the query\n this.querySpace.query.putValue(this.currentQuery);\n }\n\n /**\n * Initialize (or load if persisted) the order for the query space\n */\n public withLoadedPositions():Promise {\n if (this.currentQuery.persisted) {\n const value = this.positions.value;\n\n // Remove empty or stale values given we can reload them\n if ((value === {} || this.positions.isValueOlderThan(60000))) {\n this.positions.clear(\"Clearing old positions value\");\n }\n\n // Load the current order from backend\n this.positions.putFromPromiseIfPristine(\n () => this\n .apiV3Service\n .queries.id(this.currentQuery)\n .order\n .get()\n );\n } else if (this.positions.isPristine()) {\n // Insert an empty fallback in case we have no data yet\n this.positions.putValue({});\n }\n\n return this.positions\n .values$()\n .pipe(take(1))\n .toPromise();\n }\n\n public valueFromQuery(query:QueryResource) {\n return undefined;\n }\n\n /**\n * Return ordered work packages\n */\n orderedWorkPackages():WorkPackageResource[] {\n const upstreamOrder = this.querySpace\n .results\n .value!\n .elements\n .map(wp => this.states.workPackages.get(wp.id!).getValueOr(wp));\n\n if (this.currentQuery.persisted || this.positions.isPristine()) {\n return upstreamOrder;\n } else {\n const positions = this.positions.value!;\n return _.sortBy(upstreamOrder, (wp) => {\n const pos = positions[wp.id!];\n return pos !== undefined ? pos : MAX_ORDER;\n });\n }\n }\n\n applyToQuery(query:QueryResource):boolean {\n query.orderedWorkPackages = this.positions.getValueOr({});\n return false;\n }\n\n hasChanged(query:QueryResource):boolean {\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {States} from '../../../states.service';\nimport {displayClassName, editableClassName, readOnlyClassName} from 'core-app/modules/fields/display/display-field-renderer';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ClickOrEnterHandler} from '../click-or-enter-handler';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {ClickPositionMapper} from \"core-app/modules/common/set-click-position/set-click-position\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class EditCellHandler extends ClickOrEnterHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public states:States;\n @InjectField() public halEditing:HalResourceEditingService;\n\n // Keep a reference to all\n\n public get EVENT() {\n return 'click.table.cell, keydown.table.cell';\n }\n\n public get SELECTOR() {\n return `.${displayClassName}.${editableClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n constructor(public readonly injector:Injector) {\n super();\n }\n\n protected processEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean {\n debugLog('Starting editing on cell: ', evt.target);\n evt.preventDefault();\n\n // Locate the cell from event\n let target = jQuery(evt.target).closest(`.${displayClassName}`);\n // Get the target field name\n let fieldName = target.data('fieldName');\n\n if (!fieldName) {\n debugLog('Click handled by cell not a field? ', evt.target);\n return true;\n }\n\n // Locate the row\n const rowElement = target.closest(`.${tableRowClassName}`);\n // Get the work package we're editing\n const workPackageId = rowElement.data('workPackageId');\n const workPackage = this.states.workPackages.get(workPackageId).value!;\n // Get the row context\n const classIdentifier = rowElement.data('classIdentifier');\n\n // Get any existing edit state for this work package\n const form = table.editing.startEditing(workPackage, classIdentifier);\n\n // Get the position where the user clicked.\n const positionOffset = ClickPositionMapper.getPosition(evt);\n\n // Activate the field\n form.activate(fieldName)\n .then((handler) => {\n handler.$onUserActivate.next();\n handler.focus(positionOffset);\n })\n .catch(() => target.addClass(readOnlyClassName));\n\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {relationCellIndicatorClassName, relationCellTdClassName} from '../../builders/relation-cell-builder';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ClickOrEnterHandler} from '../click-or-enter-handler';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RelationsCellHandler extends ClickOrEnterHandler implements TableEventHandler {\n\n // Injections\n @InjectField() wpTableRelationColumns:WorkPackageViewRelationColumnsService;\n\n public get EVENT() {\n return 'click.table.relationsCell, keydown.table.relationsCell';\n }\n\n public get SELECTOR() {\n return `.${relationCellIndicatorClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n constructor(public readonly injector:Injector) {\n super();\n }\n\n protected processEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean {\n debugLog('Handled click on relation cell %o', evt.target);\n evt.preventDefault();\n\n // Locate the relation td\n const td = jQuery(evt.target).closest(`.${relationCellTdClassName}`);\n const columnId = td.data('columnId');\n\n // Locate the row\n const rowElement = jQuery(evt.target).closest(`.${tableRowClassName}`);\n const workPackageId = rowElement.data('workPackageId');\n\n // If currently expanded\n if (this.wpTableRelationColumns.getExpandFor(workPackageId) === columnId) {\n this.wpTableRelationColumns.collapse(workPackageId);\n } else {\n this.wpTableRelationColumns.setExpandFor(workPackageId, columnId);\n }\n\n return false;\n }\n}\n","import {Injector} from \"@angular/core\";\nimport {WorkPackageAction} from \"core-components/wp-table/context-menu-helper/wp-context-menu-helper.service\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewContextMenu} from \"core-components/op-context-menu/wp-context-menu/wp-view-context-menu.directive\";\nimport {WorkPackageViewHierarchyIdentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy-indentation.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class WorkPackageTableContextMenu extends WorkPackageViewContextMenu {\n\n @InjectField() wpViewIndentation:WorkPackageViewHierarchyIdentationService;\n\n constructor(public injector:Injector,\n protected workPackageId:string,\n protected $element:JQuery,\n protected additionalPositionArgs:any = {},\n protected table:WorkPackageTable) {\n super(injector, workPackageId, $element, additionalPositionArgs, true);\n }\n\n public triggerContextMenuAction(action:WorkPackageAction) {\n switch (action.key) {\n case 'relation-precedes':\n this.table.timelineController.startAddRelationPredecessor(this.workPackage);\n break;\n\n case 'relation-follows':\n this.table.timelineController.startAddRelationFollower(this.workPackage);\n break;\n\n case 'hierarchy-indent':\n this.wpViewIndentation.indent(this.workPackage);\n break;\n\n case 'hierarchy-outdent':\n this.wpViewIndentation.outdent(this.workPackage);\n break;\n\n default:\n super.triggerContextMenuAction(action);\n break;\n }\n }\n}\n","import {Injector} from '@angular/core';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {WorkPackageTableContextMenu} from \"core-components/op-context-menu/wp-context-menu/wp-table-context-menu.directive\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport abstract class ContextMenuHandler implements TableEventHandler {\n // Injections\n @InjectField() public opContextMenu:OPContextMenuService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get rowSelector() {\n return `.${tableRowClassName}`;\n }\n\n public abstract get EVENT():string;\n\n public abstract get SELECTOR():string;\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n public abstract handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent):boolean;\n\n protected openContextMenu(table:WorkPackageTable, evt:JQuery.TriggeredEvent, workPackageId:string, positionArgs?:any):void {\n const handler = new WorkPackageTableContextMenu(this.injector, workPackageId, jQuery(evt.target) as JQuery, positionArgs, table);\n this.opContextMenu.show(handler, evt);\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {uiStateLinkClass} from '../../builders/ui-state-link-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ContextMenuHandler} from './context-menu-handler';\nimport {contextMenuLinkClassName} from \"core-components/wp-table/table-actions/table-action\";\nimport {TableEventComponent} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\n\nexport class ContextMenuClickHandler extends ContextMenuHandler {\n\n constructor(public readonly injector:Injector) {\n super(injector);\n }\n\n public get EVENT() {\n return 'click.table.contextmenu';\n }\n\n public get SELECTOR() {\n return `.${contextMenuLinkClassName}`;\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent):boolean {\n let target = jQuery(evt.target);\n\n // We want to keep the original context menu on hrefs\n // (currently, this is only the id\n if (target.closest(`.${uiStateLinkClass}`).length) {\n debugLog('Allowing original context menu on state link');\n return true;\n }\n\n evt.preventDefault();\n evt.stopPropagation();\n\n // Locate the row from event\n const element = target.closest(this.rowSelector);\n const wpId = element.data('workPackageId');\n\n if (wpId) {\n this.openContextMenu(view.workPackageTable, evt, wpId);\n }\n\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ContextMenuHandler} from './context-menu-handler';\nimport {TableEventComponent} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\n\nexport class ContextMenuKeyboardHandler extends ContextMenuHandler {\n\n constructor(public readonly injector:Injector) {\n super(injector);\n }\n\n public get EVENT() {\n return 'keydown.table.contextmenu';\n }\n\n public get SELECTOR() {\n return this.rowSelector;\n }\n\n public handleEvent(component:TableEventComponent, evt:JQuery.TriggeredEvent):boolean {\n if (!component.workPackageTable.configuration.contextMenuEnabled) {\n return false;\n }\n\n let target = jQuery(evt.target);\n\n if (!(evt.keyCode === keyCodes.F10 && evt.shiftKey && evt.altKey)) {\n return true;\n }\n\n evt.preventDefault();\n evt.stopPropagation();\n\n // Locate the row from event\n const element = target.closest(this.SELECTOR);\n const wpId = element.data('workPackageId');\n\n // Set position args to open at element\n let position = { my: 'left top', at: 'left bottom', of: target };\n\n super.openContextMenu(component.workPackageTable, evt, wpId, position);\n\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {timelineCellClassName} from '../../builders/timeline/timeline-row-builder';\nimport {uiStateLinkClass} from '../../builders/ui-state-link-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ContextMenuHandler} from './context-menu-handler';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {TableEventComponent} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\n\nexport class ContextMenuRightClickHandler extends ContextMenuHandler {\n\n @InjectField() readonly wpTableSelection:WorkPackageViewSelectionService;\n\n constructor(public readonly injector:Injector) {\n super(injector);\n }\n\n public get EVENT() {\n return 'contextmenu.table.rightclick';\n }\n\n public get SELECTOR() {\n return `.${tableRowClassName},.${timelineCellClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent):boolean {\n if (!view.workPackageTable.configuration.contextMenuEnabled) {\n return false;\n }\n let target = jQuery(evt.target);\n\n // We want to keep the original context menu on hrefs\n // (currently, this is only the id\n if (target.closest(`.${uiStateLinkClass}`).length) {\n debugLog('Allowing original context menu on state link');\n return true;\n }\n\n evt.preventDefault();\n evt.stopPropagation();\n\n // Locate the row from event\n const element = target.closest(this.SELECTOR);\n const wpId = element.data('workPackageId');\n\n if (wpId) {\n let [index,] = view.workPackageTable.findRenderedRow(wpId);\n\n if (!this.wpTableSelection.isSelected(wpId)) {\n this.wpTableSelection.setSelection(wpId, index);\n }\n\n this.openContextMenu(view.workPackageTable, evt, wpId);\n }\n\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {StateService} from '@uirouter/core';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {States} from '../../../states.service';\nimport {KeepTabService} from '../../../wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {displayClassName} from \"core-app/modules/fields/display/display-field-renderer\";\nimport {activeFieldClassName} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RowClickHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public $state:StateService;\n @InjectField() public states:States;\n @InjectField() public keepTab:KeepTabService;\n @InjectField() public wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() public wpTableFocus:WorkPackageViewFocusService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get EVENT() {\n return 'click.table.row';\n }\n\n public get SELECTOR() {\n return `.${tableRowClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tbody);\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // Ignore links\n if (target.is('a') || target.parent().is('a')) {\n return true;\n }\n\n // Shortcut to any clicks within a cell\n // We don't want to handle these.\n if (target.hasClass(`${displayClassName}`) || target.hasClass(`${activeFieldClassName}`)) {\n debugLog('Skipping click on inner cell');\n return true;\n }\n\n // Locate the row from event\n let element = target.closest(this.SELECTOR);\n let wpId = element.data('workPackageId');\n let classIdentifier = element.data('classIdentifier');\n\n if (!wpId) {\n return true;\n }\n\n let [index, row] = view.workPackageTable.findRenderedRow(classIdentifier);\n\n // Update single selection if no modifier present\n if (!(evt.ctrlKey || evt.metaKey || evt.shiftKey)) {\n this.wpTableSelection.setSelection(wpId, index);\n view.itemClicked.emit({ workPackageId: wpId, double: false });\n }\n\n // Multiple selection if shift present\n if (evt.shiftKey) {\n this.wpTableSelection.setMultiSelectionFrom(view.workPackageTable.renderedRows, wpId, index);\n }\n\n // Single selection expansion if ctrl / cmd(mac)\n if (evt.ctrlKey || evt.metaKey) {\n this.wpTableSelection.toggleRow(wpId);\n }\n\n view.selectionChanged.emit(this.wpTableSelection.getSelectedWorkPackageIds());\n\n // The current row is the last selected work package\n // not matter what other rows are (de-)selected below.\n // Thus save that row for the details view button.\n this.wpTableFocus.updateFocus(wpId);\n return false;\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {StateService} from '@uirouter/core';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {States} from '../../../states.service';\nimport {tdClassName} from '../../builders/cell-builder';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {LinkHandling} from \"core-app/modules/common/link-handling/link-handling\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {displayClassName} from \"core-app/modules/fields/display/display-field-renderer\";\nimport {activeFieldClassName} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RowDoubleClickHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public $state:StateService;\n @InjectField() public states:States;\n @InjectField() public wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() public wpTableFocus:WorkPackageViewFocusService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get EVENT() {\n return 'dblclick.table.row';\n }\n\n public get SELECTOR() {\n return `.${tdClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tbody);\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // Skip clicks with modifiers\n if (LinkHandling.isClickedWithModifier(evt)) {\n return true;\n }\n\n // Shortcut to any clicks within a cell\n // We don't want to handle these.\n if (target.hasClass(`${displayClassName}`) || target.hasClass(`${activeFieldClassName}`)) {\n debugLog('Skipping click on inner cell');\n return true;\n }\n\n // Locate the row from event\n let element = target.closest(this.SELECTOR).closest(`.${tableRowClassName}`);\n let wpId = element.data('workPackageId');\n\n // Ignore links\n if (target.is('a') || target.parent().is('a')) {\n return true;\n }\n\n // Save the currently focused work package\n this.wpTableFocus.updateFocus(wpId);\n\n view.itemClicked.emit({ workPackageId: wpId, double: true });\n\n return false;\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {IsolatedQuerySpace} from 'core-app/modules/work_packages/query-space/isolated-query-space';\nimport {rowGroupClassName} from 'core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants';\nimport {InjectField} from 'core-app/helpers/angular/inject-field.decorator';\nimport {WorkPackageViewCollapsedGroupsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service';\n\nexport class GroupRowHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public querySpace:IsolatedQuerySpace;\n @InjectField() public workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get EVENT() {\n return 'click.table.groupheader';\n }\n\n public get SELECTOR() {\n return `.${rowGroupClassName} .expander`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tbody);\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n evt.preventDefault();\n evt.stopPropagation();\n\n let groupHeader = jQuery(evt.target).parents(`.${rowGroupClassName}`);\n let groupIdentifier = groupHeader.data('groupIdentifier');\n\n this.workPackageViewCollapsedGroupsService.toggleGroupCollapseState(groupIdentifier);\n }\n}\n","import {Injector} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ClickOrEnterHandler} from '../click-or-enter-handler';\nimport {TableEventComponent, TableEventHandler} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HierarchyClickHandler extends ClickOrEnterHandler implements TableEventHandler {\n // Injections\n @InjectField() public states:States;\n @InjectField() public wpTableHierarchies:WorkPackageViewHierarchiesService;\n\n constructor(public readonly injector:Injector) {\n super();\n }\n\n public get EVENT() {\n return 'click.table.hierarchy';\n }\n\n public get SELECTOR() {\n return `.wp-table--hierarchy-indicator`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tbody);\n }\n\n public processEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean {\n let target = jQuery(evt.target);\n\n // Locate the row from event\n let element = target.closest(`.${tableRowClassName}`);\n let wpId = element.data('workPackageId');\n\n this.wpTableHierarchies.toggle(wpId);\n\n evt.stopImmediatePropagation();\n evt.preventDefault();\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../../../states.service';\nimport {KeepTabService} from '../../../wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {uiStateLinkClass} from '../../builders/ui-state-link-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {StateService} from '@uirouter/core';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class WorkPackageStateLinksHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public $state:StateService;\n @InjectField() public keepTab:KeepTabService;\n @InjectField() public states:States;\n @InjectField() public wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() public wpTableFocus:WorkPackageViewFocusService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get EVENT() {\n return 'click.table.wpLink';\n }\n\n public get SELECTOR() {\n return `.${uiStateLinkClass}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n protected workPackage:WorkPackageResource;\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n // Avoid the state capture when clicking with modifier\n if (evt.shiftKey || evt.ctrlKey || evt.metaKey || evt.altKey) {\n return true;\n }\n\n // Locate the details link from event\n const target = jQuery(evt.target);\n const element = target.closest(this.SELECTOR);\n const state = element.data('wpState');\n const workPackageId = element.data('workPackageId');\n\n // Blur the target to avoid focus being kept there\n target.closest('a').blur();\n\n // The current row is the last selected work package\n // not matter what other rows are (de-)selected below.\n // Thus save that row for the details view button.\n // Locate the row from event\n let row = target.closest(`.${tableRowClassName}`);\n let classIdentifier = row.data('classIdentifier');\n let [index, _] = view.workPackageTable.findRenderedRow(classIdentifier);\n\n // Update single selection if no modifier present\n this.wpTableSelection.setSelection(workPackageId, index);\n\n view.stateLinkClicked.emit({ workPackageId: workPackageId, requestedState: state });\n\n evt.preventDefault();\n evt.stopPropagation();\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {takeUntil} from \"rxjs/operators\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class ColumnsTransformer {\n\n @InjectField() public querySpace:IsolatedQuerySpace;\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n\n constructor(public readonly injector:Injector,\n public table:WorkPackageTable) {\n\n this.wpTableColumns\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe(() => {\n if (table.originalRows.length > 0) {\n\n var t0 = performance.now();\n // Redraw the table section, ignore timeline\n table.redrawTable();\n\n var t1 = performance.now();\n\n debugLog('column redraw took ' + (t1 - t0) + ' milliseconds.');\n }\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {scrollTableRowIntoView} from 'core-components/wp-fast-table/helpers/wp-table-row-helpers';\nimport {distinctUntilChanged, filter, map, takeUntil} from 'rxjs/operators';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {\n collapsedGroupClass,\n hierarchyGroupClass,\n hierarchyRootClass\n} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\nimport {indicatorCollapsedClass} from \"core-components/wp-fast-table/builders/modes/hierarchy/single-hierarchy-row-builder\";\nimport {tableRowClassName} from \"core-components/wp-fast-table/builders/rows/single-row-builder\";\nimport {WorkPackageViewHierarchies} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-hierarchies\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HierarchyTransformer {\n\n @InjectField() public wpTableHierarchies:WorkPackageViewHierarchiesService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n\n this.wpTableHierarchies\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n map((state) => state.isVisible),\n distinctUntilChanged()\n )\n .subscribe(() => {\n // We don't have to reload all results when _disabling_ the hierarchy mode.\n if (!this.wpTableHierarchies.isEnabled) {\n table.redrawTableAndTimeline();\n }\n });\n\n let lastValue = this.wpTableHierarchies.isEnabled;\n\n this.wpTableHierarchies\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n filter(() => this.querySpace.tableRendered.hasValue())\n )\n .subscribe((state:WorkPackageViewHierarchies) => {\n\n if (state.isVisible === lastValue) {\n this.renderHierarchyState(state);\n }\n\n lastValue = state.isVisible;\n });\n }\n\n /**\n * Update all currently visible rows to match the selection state.\n */\n private renderHierarchyState(state:WorkPackageViewHierarchies) {\n const rendered = this.querySpace.tableRendered.value!;\n\n // Show all hierarchies\n jQuery('[class^=\"__hierarchy-group-\"]').removeClass((i:number, classNames:string):string => {\n return (classNames.match(/__collapsed-group-\\d+/g) || []).join(' ');\n });\n\n // Mark which rows were hidden by some other hierarchy group\n // (e.g., by a collapsed parent)\n const collapsed:{ [index:number]:boolean } = {};\n\n // Hide all collapsed hierarchies\n _.each(state.collapsed, (isCollapsed:boolean, wpId:string) => {\n // Toggle the root style\n jQuery(`.${hierarchyRootClass(wpId)} .wp-table--hierarchy-indicator`).toggleClass(indicatorCollapsedClass, isCollapsed);\n\n // Get parent row and mark/unmark it as collapsed\n const hierarchyRoot = document.querySelector(`.wp-timeline-cell.__hierarchy-root-${wpId}`);\n\n if (hierarchyRoot) {\n if (isCollapsed) {\n hierarchyRoot.classList.add(`__hierarchy-root-collapsed`);\n } else {\n hierarchyRoot.classList.remove(`__hierarchy-root-collapsed`);\n }\n }\n\n // Get all affected children rows\n const affected = jQuery(`.${hierarchyGroupClass(wpId)}`);\n\n // Hide/Show the descendants.\n affected.toggleClass(collapsedGroupClass(wpId), isCollapsed);\n\n // Update the hidden section of the rendered state\n affected.filter(`.${tableRowClassName}`).each((i, el) => {\n // Get the index of this row\n const index = jQuery(el).index();\n\n // Update the hidden state\n if (!collapsed[index]) {\n rendered[index].hidden = isCollapsed;\n collapsed[index] = isCollapsed;\n }\n });\n });\n\n // Keep focused on the last element, if any.\n // Based on https://stackoverflow.com/a/3782959\n if (state.last) {\n scrollTableRowIntoView(state.last);\n }\n\n\n this.querySpace.tableRendered.putValue(rendered, 'Updated hidden state of rows after hierarchy change.');\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {takeUntil} from \"rxjs/operators\";\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RelationsTransformer {\n\n @InjectField() public wpTableRelationColumns:WorkPackageViewRelationColumnsService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n\n this.wpTableRelationColumns\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe(() => {\n table.redrawTableAndTimeline();\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {filter, takeUntil} from 'rxjs/operators';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {States} from 'core-components/states.service';\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RowsTransformer {\n\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() wpTableSortBy:WorkPackageViewSortByService;\n @InjectField() wpTableOrder:WorkPackageViewOrderService;\n @InjectField() states:States;\n\n constructor(public readonly injector:Injector,\n public table:WorkPackageTable) {\n\n // Redraw table if the current row state changed\n this.querySpace\n .initialized\n .values$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe(() => {\n let rows:WorkPackageResource[];\n\n if (this.wpTableSortBy.isManualSortingMode) {\n rows = this.wpTableOrder.orderedWorkPackages();\n } else {\n rows = this.querySpace.results.value!.elements;\n }\n\n table.initialSetup(rows);\n });\n\n // Refresh a single row if it exists\n this.states.workPackages.observeChange()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions.asObservable()),\n filter(() => {\n let rendered = this.querySpace.tableRendered.getValueOr([]);\n return rendered && rendered.length > 0;\n })\n )\n .subscribe(([changedId, wp]) => {\n if (wp === undefined) {\n return;\n }\n\n this.table.refreshRows(wp);\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {takeUntil} from 'rxjs/operators';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {checkedClassName} from '../../builders/ui-state-link-builder';\nimport {locateTableRow, scrollTableRowIntoView} from '../../helpers/wp-table-row-helpers';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {FocusHelperService} from 'core-app/modules/common/focus/focus-helper';\nimport {\n WorkPackageViewSelectionService,\n WorkPackageViewSelectionState\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class SelectionTransformer {\n\n @InjectField() public wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() public wpTableFocus:WorkPackageViewFocusService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n @InjectField() public FocusHelper:FocusHelperService;\n\n constructor(public readonly injector:Injector,\n public readonly table:WorkPackageTable) {\n\n // Focus a single selection when active\n this.querySpace.tableRendered.values$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe(() => {\n\n this.wpTableFocus.ifShouldFocus((wpId:string) => {\n const element = locateTableRow(wpId);\n if (element.length) {\n scrollTableRowIntoView(wpId);\n this.FocusHelper.focusElement(element, true);\n }\n });\n });\n\n\n // Update selection state\n this.wpTableSelection.live$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe((state:WorkPackageViewSelectionState) => {\n this.renderSelectionState(state);\n });\n\n\n this.wpTableSelection.registerSelectAllListener(() => {\n return table.renderedRows;\n });\n this.wpTableSelection.registerDeselectAllListener();\n }\n\n /**\n * Update all currently visible rows to match the selection state.\n */\n private renderSelectionState(state:WorkPackageViewSelectionState) {\n const context = jQuery(this.table.tableAndTimelineContainer);\n\n context.find(`.${tableRowClassName}.${checkedClassName}`).removeClass(checkedClassName);\n\n _.each(state.selected, (selected:boolean, workPackageId:any) => {\n context.find(`.${tableRowClassName}[data-work-package-id=\"${workPackageId}\"]`).toggleClass(checkedClassName, selected);\n });\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {takeUntil} from 'rxjs/operators';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageTimelineState} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-timeline\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class TimelineTransformer {\n\n @InjectField() public querySpace:IsolatedQuerySpace;\n @InjectField() public wpTableTimeline:WorkPackageViewTimelineService;\n\n constructor(readonly injector:Injector,\n readonly table:WorkPackageTable) {\n\n this.wpTableTimeline\n .live$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe((state:WorkPackageTimelineState) => {\n this.renderVisibility(state.visible);\n });\n }\n\n /**\n * Update all currently visible rows to match the selection state.\n */\n private renderVisibility(visible:boolean) {\n const container = jQuery(this.table.tableAndTimelineContainer).parent();\n container.find('.work-packages-tabletimeline--timeline-side').toggle(visible);\n container.find('.work-packages-tabletimeline--table-side').toggleClass('-timeline-visible', visible);\n }\n}\n","import {Injector} from '@angular/core';\nimport {distinctUntilChanged, takeUntil} from 'rxjs/operators';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageViewHighlightingService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HighlightingTransformer {\n\n @InjectField() public wpTableHighlighting:WorkPackageViewHighlightingService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n this.wpTableHighlighting\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n distinctUntilChanged()\n )\n .subscribe(() => table.redrawTable());\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {take, takeUntil} from \"rxjs/operators\";\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {TableDragActionsRegistryService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-actions-registry.service\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {States} from \"core-components/states.service\";\nimport {tableRowClassName} from \"core-components/wp-fast-table/builders/rows/single-row-builder\";\nimport {DragAndDropService} from \"core-app/modules/common/drag-and-drop/drag-and-drop.service\";\nimport {DragAndDropHelpers} from \"core-app/modules/common/drag-and-drop/drag-and-drop.helpers\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {isInsideCollapsedGroup} from \"core-components/wp-fast-table/helpers/wp-table-row-helpers\";\nimport {collapsedGroupClass} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\n\nexport class DragAndDropTransformer {\n\n @InjectField() private readonly states:States;\n @InjectField() private readonly querySpace:IsolatedQuerySpace;\n @InjectField() private readonly inlineCreateService:WorkPackageInlineCreateService;\n @InjectField() private readonly halNotification:HalResourceNotificationService;\n @InjectField() private readonly wpTableSortBy:WorkPackageViewSortByService;\n @InjectField() private readonly wpTableOrder:WorkPackageViewOrderService;\n @InjectField() private readonly browserDetector:BrowserDetector;\n @InjectField() private readonly apiV3Service:APIV3Service;\n @InjectField() private readonly wpListService:WorkPackagesListService;\n @InjectField() private readonly dragActionRegistry:TableDragActionsRegistryService;\n @InjectField(DragAndDropService, null) private readonly dragService:DragAndDropService|null;\n\n constructor(public readonly injector:Injector,\n public table:WorkPackageTable) {\n\n // The DragService may not have been provided\n // in which case we do not provide drag and drop\n if (this.dragService === null) {\n return;\n }\n\n this.inlineCreateService.newInlineWorkPackageCreated\n .pipe(takeUntil(this.querySpace.stopAllSubscriptions))\n .subscribe(async (wpId) => {\n const newOrder = await this.wpTableOrder.add(this.currentOrder, wpId);\n this.updateRenderedOrder(newOrder);\n });\n\n this.querySpace.stopAllSubscriptions\n .pipe(take(1))\n .subscribe(() => {\n this.dragService!.remove(this.table.tbody);\n });\n\n this.dragService.register({\n dragContainer: this.table.tbody,\n scrollContainers: [this.table.scrollContainer],\n accepts: () => true,\n moves: (el:any, source:any, handle:HTMLElement) => {\n if (!handle.classList.contains('wp-table--drag-and-drop-handle')) {\n return false;\n }\n\n const wpId:string = el.dataset.workPackageId!;\n const workPackage = this.states.workPackages.get(wpId).value;\n return !!workPackage && this.actionService.canPickup(workPackage);\n },\n onMoved: async (el:HTMLElement, target:HTMLElement, source:HTMLElement, sibling:HTMLElement|null) => {\n const wpId:string = el.dataset.workPackageId!;\n let rowIndex;\n\n try {\n const workPackage = await this.apiV3Service.work_packages.id(wpId).get().toPromise();\n\n if (isInsideCollapsedGroup(sibling)) {\n const collapsedGroupCSSClass = Array.from(sibling!.classList).find(listClass => listClass.includes(collapsedGroupClass()))!;\n const collapsedGroupId = collapsedGroupCSSClass.replace(collapsedGroupClass(), '');\n const collapsedGroupElements = source.getElementsByClassName(collapsedGroupClass(collapsedGroupId));\n const collapsedGroupLastChild = collapsedGroupElements[collapsedGroupElements.length - 1];\n rowIndex = this.findRowIndex(collapsedGroupLastChild as HTMLElement);\n } else {\n rowIndex = this.findRowIndex(el);\n }\n\n const newOrder = await this.wpTableOrder.move(this.currentOrder, wpId, rowIndex);\n\n await this.actionService.handleDrop(workPackage, el);\n this.updateRenderedOrder(newOrder);\n this.actionService.onNewOrder(newOrder);\n\n // Save the query when switching to manual\n let query = this.querySpace.query.value;\n if (query && this.wpTableSortBy.switchToManualSorting(query)) {\n await this.wpListService.save(query);\n }\n } catch (e) {\n this.halNotification.handleRawError(e);\n\n // Restore original element's styles\n this.actionService.changeShadowElement(el, true);\n // Restore element in from container\n DragAndDropHelpers.reinsert(el, el.dataset.sourceIndex || -1, source);\n }\n },\n onRemoved: (el:HTMLElement) => {\n const wpId:string = el.dataset.workPackageId!;\n const newOrder = this.wpTableOrder.remove(this.currentOrder, wpId);\n this.updateRenderedOrder(newOrder);\n },\n onAdded: async (el:HTMLElement) => {\n const wpId:string = el.dataset.workPackageId!;\n const workPackage = await this.apiV3Service.work_packages.id(wpId).get().toPromise();\n const rowIndex = this.findRowIndex(el);\n\n return this.actionService\n .handleDrop(workPackage, el)\n .then(async () => {\n const newOrder = await this.wpTableOrder.add(this.currentOrder, wpId, rowIndex);\n this.updateRenderedOrder(newOrder);\n this.actionService.onNewOrder(newOrder);\n\n return true;\n })\n .catch(() => false);\n },\n onCloned: async (clone:HTMLElement, original:HTMLElement) => {\n // Replace clone with one TD of the subject\n const wpId:string = original.dataset.workPackageId!;\n const workPackage = await this.apiV3Service.work_packages.id(wpId).get().toPromise();\n\n const colspan = clone.children.length;\n const td = document.createElement('td');\n td.textContent = workPackage.subjectWithId();\n td.colSpan = colspan;\n td.classList.add('wp-table--cell-td', 'subject');\n\n clone.style.maxWidth = '500px';\n clone.innerHTML = td.outerHTML;\n },\n onShadowInserted: (el:HTMLElement) => {\n if (!this.browserDetector.isEdge) {\n this.actionService.changeShadowElement(el);\n }\n },\n onCancel: (el:HTMLElement) => {\n if (!this.browserDetector.isEdge) {\n this.actionService.changeShadowElement(el, true);\n }\n },\n });\n }\n\n /**\n * Update current rendered order\n */\n private async updateRenderedOrder(order:string[]) {\n order = _.uniq(order);\n\n const mappedOrder = await Promise.all(\n order.map(\n wpId => this.apiV3Service.work_packages.id(wpId).get().toPromise()\n )\n );\n\n /** Re-render the table */\n this.table.initialSetup(mappedOrder);\n }\n\n protected get actionService():TableDragActionService {\n return this.dragActionRegistry.get(this.injector);\n }\n\n protected get currentOrder():string[] {\n return this\n .currentRenderedOrder\n .map((row) => row.workPackageId!);\n }\n\n protected get currentRenderedOrder():RenderedWorkPackage[] {\n return this\n .querySpace\n .renderedWorkPackages\n .getValueOr([]);\n }\n\n /**\n * Find the index of the row in the set of rendered work packages.\n * This will skip non-work-package rows such as group headers\n * @param el\n */\n private findRowIndex(el:HTMLElement):number {\n const rows = Array.from(this.table.tbody.getElementsByClassName(tableRowClassName));\n return rows.indexOf(el) || 0;\n }\n}\n","import {Injector} from '@angular/core';\nimport {distinctUntilChanged, takeUntil} from 'rxjs/operators';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {WorkPackageViewCollapsedGroupsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service\";\n\nexport class GroupFoldTransformer {\n\n @InjectField() public workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n this.workPackageViewCollapsedGroupsService\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n distinctUntilChanged()\n )\n .subscribe((groupsCollapseEvent) => table.setGroupsCollapseState(groupsCollapseEvent.state));\n }\n}\n","import {EventEmitter, Injector} from '@angular/core';\nimport {WorkPackageTable} from '../wp-fast-table';\nimport {EditCellHandler} from './cell/edit-cell-handler';\nimport {RelationsCellHandler} from './cell/relations-cell-handler';\nimport {ContextMenuClickHandler} from './context-menu/context-menu-click-handler';\nimport {ContextMenuKeyboardHandler} from './context-menu/context-menu-keyboard-handler';\nimport {ContextMenuRightClickHandler} from './context-menu/context-menu-rightclick-handler';\nimport {RowClickHandler} from './row/click-handler';\nimport {RowDoubleClickHandler} from './row/double-click-handler';\nimport {GroupRowHandler} from './row/group-row-handler';\nimport {HierarchyClickHandler} from './row/hierarchy-click-handler';\nimport {WorkPackageStateLinksHandler} from './row/wp-state-links-handler';\nimport {ColumnsTransformer} from './state/columns-transformer';\nimport {HierarchyTransformer} from './state/hierarchy-transformer';\nimport {RelationsTransformer} from './state/relations-transformer';\nimport {RowsTransformer} from './state/rows-transformer';\nimport {SelectionTransformer} from './state/selection-transformer';\nimport {TimelineTransformer} from './state/timeline-transformer';\nimport {HighlightingTransformer} from \"core-components/wp-fast-table/handlers/state/highlighting-transformer\";\nimport {DragAndDropTransformer} from \"core-components/wp-fast-table/handlers/state/drag-and-drop-transformer\";\nimport {\n WorkPackageViewEventHandler, WorkPackageViewOutputs,\n WorkPackageViewHandlerRegistry\n} from \"core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry\";\nimport {WorkPackageFocusContext} from \"core-components/wp-table/wp-table.component\";\nimport {GroupFoldTransformer} from \"core-components/wp-fast-table/handlers/state/group-fold-transformer\";\n\ntype StateTransformers = {\n // noinspection JSUnusedLocalSymbols\n new(injector:Injector, table:WorkPackageTable):any;\n};\n\nexport interface TableEventComponent extends WorkPackageViewOutputs {\n // Reference to the fast table instance\n workPackageTable:WorkPackageTable;\n}\n\nexport type TableEventHandler = WorkPackageViewEventHandler;\n\nexport class TableHandlerRegistry extends WorkPackageViewHandlerRegistry {\n\n protected eventHandlers:((t:TableEventComponent) => TableEventHandler)[] = [\n // Hierarchy expansion/collapsing\n () => new HierarchyClickHandler(this.injector),\n // Clicking or pressing Enter on a single cell, editable or not\n () => new EditCellHandler(this.injector),\n // Clicking on the details view\n () => new WorkPackageStateLinksHandler(this.injector),\n // Clicking on the row (not within a cell)\n () => new RowClickHandler(this.injector),\n // Double Clicking on the cell within the row\n () => new RowDoubleClickHandler(this.injector),\n // Clicking on group headers\n () => new GroupRowHandler(this.injector),\n // Right clicking on rows\n () => new ContextMenuRightClickHandler(this.injector),\n // Left clicking on the dropdown icon\n () => new ContextMenuClickHandler(this.injector),\n // SHIFT+ALT+F10 on rows\n () => new ContextMenuKeyboardHandler(this.injector),\n // Clicking on relations cells\n () => new RelationsCellHandler(this.injector)\n ];\n\n protected readonly stateTransformers:StateTransformers[] = [\n SelectionTransformer,\n RowsTransformer,\n ColumnsTransformer,\n GroupFoldTransformer,\n TimelineTransformer,\n HierarchyTransformer,\n RelationsTransformer,\n HighlightingTransformer,\n DragAndDropTransformer\n ];\n\n attachTo(viewRef:TableEventComponent) {\n this.stateTransformers.map((cls) => {\n return new cls(this.injector, viewRef.workPackageTable);\n });\n\n super.attachTo(viewRef);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nconst cssClassRowHovered = 'row-hovered';\n\nexport class WpTableHoverSync {\n\n private lastHoveredElement:Element | null = null;\n\n private eventListener = (evt:MouseEvent) => {\n const target = evt.target as Element|null;\n if (target && target !== this.lastHoveredElement) {\n this.handleHover(target);\n }\n this.lastHoveredElement = target;\n }\n\n constructor(private tableAndTimeline:JQuery) {\n }\n\n activate() {\n window.addEventListener('mousemove', this.eventListener, { passive: true });\n }\n\n deactivate() {\n window.removeEventListener('mousemove', this.eventListener);\n this.removeAllHoverClasses();\n }\n\n private locateHoveredTableRow(child:JQuery):Element | null {\n const parent = child.closest('tr');\n if (parent.length === 0) {\n return null;\n }\n return parent[0];\n }\n\n private locateHoveredTimelineRow(child:JQuery):Element | null {\n const parent = child.closest('div.wp-timeline-cell');\n if (parent.length === 0) {\n return null;\n }\n return parent[0];\n }\n\n private handleHover(element:Element) {\n const $element = jQuery(element) as JQuery;\n const parentTableRow = this.locateHoveredTableRow($element);\n const parentTimelineRow = this.locateHoveredTimelineRow($element);\n\n // remove all hover classes if cursor does not hover a row\n if (parentTableRow === null && parentTimelineRow === null) {\n this.removeAllHoverClasses();\n return;\n }\n\n this.removeOldAndAddNewHoverClass(parentTableRow, parentTimelineRow);\n }\n\n private extractWorkPackageId(row:Element):number {\n return parseInt(row.getAttribute('data-work-package-id')!);\n }\n\n private removeOldAndAddNewHoverClass(parentTableRow:Element | null, parentTimelineRow:Element | null) {\n const hovered = parentTableRow !== null ? parentTableRow : parentTimelineRow;\n const wpId = this.extractWorkPackageId(hovered!);\n\n const tableRow:JQuery = this.tableAndTimeline.find('tr.wp-row-' + wpId).first();\n const timelineRow:JQuery = this.tableAndTimeline.find('div.wp-row-' + wpId).length ?\n this.tableAndTimeline.find('div.wp-row-' + wpId).first() :\n this.tableAndTimeline.find('div.wp-ancestor-row-' + wpId).first();\n\n requestAnimationFrame(() => {\n this.removeAllHoverClasses();\n timelineRow.addClass(cssClassRowHovered);\n tableRow.addClass(cssClassRowHovered);\n });\n }\n\n private removeAllHoverClasses() {\n this.tableAndTimeline\n .find(`.${cssClassRowHovered}`)\n .removeClass(cssClassRowHovered);\n }\n}\n","
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n\n \n \n \n \n\n \n \n
    \n {{text.tableSummary}}\n \n {{text.tableSummaryHints}}\n
    \n
    \n \n
    \n
    \n \n \n \n
    \n \n \n
    \n
    \n \n \n \n {{text.noResults.title}}\n {{text.noResults.description}}\n \n \n
    \n
    \n\n
    \n \n
    \n\n
    \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef, EventEmitter,\n Injector,\n Input,\n NgZone,\n OnInit, Output,\n ViewEncapsulation\n} from '@angular/core';\nimport {QueryGroupByResource} from 'core-app/modules/hal/resources/query-group-by-resource';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {TableEventComponent, TableHandlerRegistry} from 'core-components/wp-fast-table/handlers/table-handler-registry';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {combineLatest} from 'rxjs';\nimport {States} from '../states.service';\nimport {\n WorkPackageTableConfiguration,\n WorkPackageTableConfigurationObject\n} from 'core-app/components/wp-table/wp-table-configuration';\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {createScrollSync} from \"core-components/wp-table/wp-table-scroll-sync\";\nimport {WpTableHoverSync} from \"core-components/wp-table/wp-table-hover-sync\";\nimport {WorkPackageTimelineTableController} from \"core-components/wp-table/timeline/container/wp-timeline-container.directive\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport interface WorkPackageFocusContext {\n /** Work package that was focused */\n workPackageId:string;\n /** Through what action did the focus happen */\n through:'row-double-click'|'id-click'|'details-icon';\n}\n\n@Component({\n templateUrl: './wp-table.directive.html',\n styleUrls: ['./wp-table.styles.sass'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-table',\n})\nexport class WorkPackagesTableComponent extends UntilDestroyedMixin implements OnInit, TableEventComponent {\n\n @Input() projectIdentifier:string;\n @Input('configuration') configurationObject:WorkPackageTableConfigurationObject;\n\n @Output() selectionChanged = new EventEmitter();\n @Output() itemClicked = new EventEmitter<{ workPackageId:string, double:boolean }>();\n @Output() stateLinkClicked = new EventEmitter<{ workPackageId:string, requestedState:string }>();\n\n public trackByHref = AngularTrackingHelpers.trackByHref;\n\n public configuration:WorkPackageTableConfiguration;\n\n private $element:JQuery;\n\n private scrollSyncUpdate:(timelineVisible:boolean) => any;\n\n private wpTableHoverSync:WpTableHoverSync;\n\n public tableElement:HTMLElement;\n\n public workPackageTable:WorkPackageTable;\n\n public tbody:JQuery;\n\n public query:QueryResource;\n\n public timeline:HTMLElement;\n\n public locale:string;\n\n public text:any;\n\n public results:WorkPackageCollectionResource;\n\n public groupBy:QueryGroupByResource|null;\n\n public columns:QueryColumn[];\n\n public numTableColumns:number;\n\n public timelineVisible:boolean;\n\n public manualSortEnabled:boolean;\n\n public limitedResults = false;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly states:States,\n readonly querySpace:IsolatedQuerySpace,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly zone:NgZone,\n readonly wpTableGroupBy:WorkPackageViewGroupByService,\n readonly wpTableTimeline:WorkPackageViewTimelineService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly wpTableSortBy:WorkPackageViewSortByService) {\n super();\n }\n\n ngOnInit():void {\n this.configuration = new WorkPackageTableConfiguration(this.configurationObject);\n this.$element = jQuery(this.elementRef.nativeElement);\n\n // Clear any old table subscribers\n this.querySpace.stopAllSubscriptions.next();\n\n this.locale = I18n.locale;\n\n this.text = {\n cancel: I18n.t('js.button_cancel'),\n noResults: {\n title: I18n.t('js.work_packages.no_results.title'),\n description: I18n.t('js.work_packages.no_results.description')\n },\n limitedResults: (count:number, total:number) => {\n return I18n.t('js.work_packages.limited_results', { count: count, total: total });\n },\n tableSummary: I18n.t('js.work_packages.table.summary'),\n tableSummaryHints: [\n I18n.t('js.work_packages.table.text_inline_edit'),\n I18n.t('js.work_packages.table.text_select_hint'),\n I18n.t('js.work_packages.table.text_sort_hint')\n ].join(' ')\n };\n\n let statesCombined = combineLatest([\n this.querySpace.results.values$(),\n this.wpTableGroupBy.live$(),\n this.wpTableColumns.live$(),\n this.wpTableTimeline.live$(),\n this.wpTableSortBy.live$()\n ]);\n\n statesCombined.pipe(\n this.untilDestroyed()\n ).subscribe(([results, groupBy, columns, timelines, sort]) => {\n this.query = this.querySpace.query.value!;\n\n this.results = results;\n\n this.groupBy = groupBy;\n this.columns = columns;\n // Total columns = all available columns + id + checkbox\n this.numTableColumns = this.columns.length + 2;\n\n if (this.scrollSyncUpdate && this.timelineVisible !== timelines.visible) {\n this.scrollSyncUpdate(timelines.visible);\n }\n\n this.timelineVisible = timelines.visible;\n\n this.manualSortEnabled = this.wpTableSortBy.isManualSortingMode;\n this.limitedResults = this.manualSortEnabled && results.total > results.count;\n\n this.cdRef.detectChanges();\n });\n\n this.cdRef.detectChanges();\n }\n\n public ngOnDestroy():void {\n super.ngOnDestroy();\n this.wpTableHoverSync.deactivate();\n }\n\n public registerTimeline(controller:WorkPackageTimelineTableController, timelineBody:HTMLElement) {\n const tbody = this.$element.find('.work-package--results-tbody');\n const scrollContainer = this.$element.find('.work-package-table--container')[0];\n this.workPackageTable = new WorkPackageTable(\n this.injector,\n // Outer container for both table + Timeline\n this.$element[0],\n // Scroll container for the table/timeline\n scrollContainer,\n // Table tbody to insert into\n tbody[0],\n // Timeline body to insert into\n timelineBody,\n // Timeline controller\n controller,\n // Table configuration\n this.configuration\n );\n this.tbody = tbody;\n controller.workPackageTable = this.workPackageTable;\n new TableHandlerRegistry(this.injector).attachTo(this);\n\n // Locate table and timeline elements\n const tableAndTimeline = this.getTableAndTimelineElement();\n this.tableElement = tableAndTimeline[0];\n this.timeline = tableAndTimeline[1];\n\n // sync hover from table to timeline\n this.wpTableHoverSync = new WpTableHoverSync(this.$element);\n this.wpTableHoverSync.activate();\n\n // sync scroll from table to timeline\n this.scrollSyncUpdate = createScrollSync(this.$element);\n this.scrollSyncUpdate(this.timelineVisible);\n\n this.cdRef.detectChanges();\n }\n\n public get isEmbedded() {\n return this.configuration.isEmbedded;\n }\n\n private getTableAndTimelineElement():[HTMLElement, HTMLElement] {\n const $tableSide = this.$element.find('.work-packages-tabletimeline--table-side');\n const $timelineSide = this.$element.find('.work-packages-tabletimeline--timeline-side');\n\n if ($timelineSide.length === 0 || $tableSide.length === 0) {\n throw new Error('invalid state');\n }\n\n return [$tableSide[0], $timelineSide[0]];\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectorRef,\n Directive,\n ElementRef,\n Inject,\n InjectionToken,\n Injector,\n OnDestroy,\n OnInit\n} from \"@angular/core\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {Field, IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\n\nexport const OpEditingPortalSchemaToken = new InjectionToken('editing-portal--schema');\nexport const OpEditingPortalHandlerToken = new InjectionToken('editing-portal--handler');\nexport const OpEditingPortalChangesetToken = new InjectionToken('editing-portal--changeset');\n\nexport const overflowingContainerSelector = '.__overflowing_element_container';\nexport const overflowingContainerAttribute = 'overflowingIdentifier';\n\nexport const editModeClassName = '-editing';\n\n@Directive()\nexport abstract class EditFieldComponent extends Field implements OnInit, OnDestroy {\n /** Self reference */\n public self = this;\n\n /** JQuery accessor to element ref */\n protected $element:JQuery;\n\n constructor(readonly I18n:I18nService,\n readonly elementRef:ElementRef,\n @Inject(OpEditingPortalChangesetToken) protected change:ResourceChangeset,\n @Inject(OpEditingPortalSchemaToken) public schema:IFieldSchema,\n @Inject(OpEditingPortalHandlerToken) readonly handler:EditFieldHandler,\n readonly cdRef:ChangeDetectorRef,\n readonly injector:Injector) {\n super();\n\n this.updateFromChangeset(change);\n\n if (this.change.state) {\n this.change.state\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((change) => {\n const fieldSchema = change.schema.ofProperty(this.name);\n\n if (!fieldSchema) {\n return handler.deactivate(false);\n }\n\n this.updateFromChangeset(change);\n this.initialize();\n this.cdRef.markForCheck();\n });\n }\n }\n\n ngOnInit():void {\n this.$element = jQuery(this.elementRef.nativeElement);\n this.initialize();\n }\n\n public get overflowingSelector() {\n if (this.$element) {\n return this.$element\n .closest(overflowingContainerSelector)\n .data(overflowingContainerAttribute);\n } else {\n return null;\n }\n }\n\n public get inFlight() {\n return this.handler.inFlight;\n }\n\n public get value() {\n return this.resource[this.name];\n }\n\n public set value(value:any) {\n this.resource[this.name] = this.parseValue(value);\n }\n\n public get placeholder() {\n if (this.name === 'subject') {\n return this.I18n.t('js.placeholders.subject');\n }\n\n return '';\n }\n\n /**\n * Initialize the field after constructor was called.\n */\n protected initialize() {\n }\n\n /**\n * Update resource and properties from changeset\n */\n private updateFromChangeset(change:ResourceChangeset) {\n this.change = change;\n this.resource = this.change.projectedResource;\n this.schema = this.change.schema.ofProperty(this.handler.fieldName) || this.schema;\n\n // Get the mapped schema name, as this is not always the attribute\n // e.g., startDate in table for milestone => date attribute\n this.name = this.change.schema.mappedName(this.handler.fieldName);\n }\n\n /**\n * Parse the value from the model for setting\n */\n protected parseValue(val:any) {\n return val;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {WorkPackageLinkedResourceCache} from 'core-components/wp-single-view-tabs/wp-linked-resource-cache.service';\n\n@Injectable()\nexport class WorkPackageWatchersService extends WorkPackageLinkedResourceCache {\n\n protected load(workPackage:WorkPackageResource) {\n return workPackage.watchers.$update()\n .then((collection:CollectionResource) => {\n return collection.elements;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {States} from 'core-components/states.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\n\n\nexport const wpDisplayListRepresentation = 'list';\nexport const wpDisplayCardRepresentation = 'card';\nexport type WorkPackageDisplayRepresentationValue = 'list'|'card';\n\n@Injectable()\nexport class WorkPackageViewDisplayRepresentationService extends WorkPackageQueryStateService {\n public constructor(readonly states:States,\n readonly querySpace:IsolatedQuerySpace) {\n super(querySpace);\n }\n\n public hasChanged(query:QueryResource) {\n return this.current !== query.displayRepresentation;\n }\n\n valueFromQuery(query:QueryResource) {\n return query.displayRepresentation || null;\n }\n\n public applyToQuery(query:QueryResource) {\n const current = this.current;\n query.displayRepresentation = current === null ? undefined : current;\n\n return false;\n }\n\n public get current():string|null {\n return this.lastUpdatedState.getValueOr(null);\n }\n\n public get isList():boolean {\n const current = this.current;\n return !current || current === wpDisplayListRepresentation;\n }\n\n public get isCards():boolean {\n return this.current === wpDisplayCardRepresentation;\n }\n\n public setDisplayRepresentation(representation:WorkPackageDisplayRepresentationValue) {\n this.update(representation);\n }\n}\n","var map = {\n\t\"./admin_users\": [\n\t\t\"FyB/\",\n\t\t7,\n\t\t12\n\t],\n\t\"./admin_users.js\": [\n\t\t\"FyB/\",\n\t\t7,\n\t\t12\n\t],\n\t\"./administration_settings\": [\n\t\t\"pIQB\",\n\t\t7,\n\t\t13\n\t],\n\t\"./administration_settings.js\": [\n\t\t\"pIQB\",\n\t\t7,\n\t\t13\n\t],\n\t\"./backlogs\": [\n\t\t\"1cF+\",\n\t\t7,\n\t\t1,\n\t\t6\n\t],\n\t\"./backlogs.js\": [\n\t\t\"1cF+\",\n\t\t7,\n\t\t1,\n\t\t6\n\t],\n\t\"./backlogs/backlog\": [\n\t\t\"VbDW\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/backlog.js\": [\n\t\t\"VbDW\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/burndown\": [\n\t\t\"n+FW\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/burndown.js\": [\n\t\t\"n+FW\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/common\": [\n\t\t\"+TUS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/common.js\": [\n\t\t\"+TUS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/editable_inplace\": [\n\t\t\"xOUI\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/editable_inplace.js\": [\n\t\t\"xOUI\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/impediment\": [\n\t\t\"CO8W\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/impediment.js\": [\n\t\t\"CO8W\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/master_backlog\": [\n\t\t\"QrsS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/master_backlog.js\": [\n\t\t\"QrsS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/model\": [\n\t\t\"vTya\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/model.js\": [\n\t\t\"vTya\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/show_main\": [\n\t\t\"ySs4\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/show_main.js\": [\n\t\t\"ySs4\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/sprint\": [\n\t\t\"gFIQ\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/sprint.js\": [\n\t\t\"gFIQ\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/story\": [\n\t\t\"6Ibq\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/story.js\": [\n\t\t\"6Ibq\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/task\": [\n\t\t\"qE9B\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/task.js\": [\n\t\t\"qE9B\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/taskboard\": [\n\t\t\"g/gS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/taskboard.js\": [\n\t\t\"g/gS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/work_package\": [\n\t\t\"UHLX\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/work_package.js\": [\n\t\t\"UHLX\",\n\t\t7,\n\t\t1\n\t],\n\t\"./custom_fields\": [\n\t\t\"aLwj\",\n\t\t7,\n\t\t14\n\t],\n\t\"./custom_fields.js\": [\n\t\t\"aLwj\",\n\t\t7,\n\t\t14\n\t],\n\t\"./forums\": [\n\t\t\"9SdV\",\n\t\t7,\n\t\t15\n\t],\n\t\"./forums.js\": [\n\t\t\"9SdV\",\n\t\t7,\n\t\t15\n\t],\n\t\"./global_roles\": [\n\t\t\"qOGe\",\n\t\t7,\n\t\t10\n\t],\n\t\"./global_roles.ts\": [\n\t\t\"qOGe\",\n\t\t7,\n\t\t10\n\t],\n\t\"./meeting\": [\n\t\t\"dVjf\",\n\t\t7,\n\t\t16\n\t],\n\t\"./meeting.js\": [\n\t\t\"dVjf\",\n\t\t7,\n\t\t16\n\t],\n\t\"./members_form\": [\n\t\t\"jeHl\",\n\t\t7,\n\t\t17\n\t],\n\t\"./members_form.js\": [\n\t\t\"jeHl\",\n\t\t7,\n\t\t17\n\t],\n\t\"./new_user\": [\n\t\t\"1z6l\",\n\t\t7,\n\t\t18\n\t],\n\t\"./new_user.js\": [\n\t\t\"1z6l\",\n\t\t7,\n\t\t18\n\t],\n\t\"./project\": [\n\t\t\"y2NQ\",\n\t\t7,\n\t\t19\n\t],\n\t\"./project.js\": [\n\t\t\"y2NQ\",\n\t\t7,\n\t\t19\n\t],\n\t\"./project_form_listener\": [\n\t\t\"Y9rl\",\n\t\t7,\n\t\t20\n\t],\n\t\"./project_form_listener.js\": [\n\t\t\"Y9rl\",\n\t\t7,\n\t\t20\n\t],\n\t\"./repository_navigation\": [\n\t\t\"wJjJ\",\n\t\t7,\n\t\t21\n\t],\n\t\"./repository_navigation.js\": [\n\t\t\"wJjJ\",\n\t\t7,\n\t\t21\n\t],\n\t\"./repository_settings\": [\n\t\t\"815p\",\n\t\t7,\n\t\t22\n\t],\n\t\"./repository_settings.js\": [\n\t\t\"815p\",\n\t\t7,\n\t\t22\n\t],\n\t\"./two_factor_authentication\": [\n\t\t\"Q8SW\",\n\t\t9,\n\t\t9\n\t],\n\t\"./two_factor_authentication.ts\": [\n\t\t\"Q8SW\",\n\t\t9,\n\t\t9\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tvar ids = map[req], id = ids[0];\n\treturn Promise.all(ids.slice(2).map(__webpack_require__.e)).then(function() {\n\t\treturn __webpack_require__.t(id, ids[1])\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = \"VbPg\";\nmodule.exports = webpackAsyncContext;","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../../states.service';\nimport {StateService} from '@uirouter/core';\nimport {Injectable} from '@angular/core';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageRelationsHierarchyService {\n constructor(protected $state:StateService,\n protected states:States,\n protected halEvents:HalEventsService,\n protected notificationService:WorkPackageNotificationService,\n protected pathHelper:PathHelperService,\n protected apiV3Service:APIV3Service) {\n\n }\n\n public changeParent(workPackage:WorkPackageResource, parentId:string|null) {\n let payload:any = {\n lockVersion: workPackage.lockVersion\n };\n\n if (parentId) {\n payload['_links'] = {\n parent: {\n href: this.apiV3Service.work_packages.id(parentId).path\n }\n };\n } else {\n payload['_links'] = {\n parent: {\n href: null\n }\n };\n }\n\n return workPackage\n .changeParent(payload)\n .then((wp:WorkPackageResource) => {\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(wp);\n this.notificationService.showSave(wp);\n this.halEvents.push(workPackage, {\n eventType: 'association',\n relatedWorkPackage: parentId,\n relationType: 'parent'\n });\n\n return wp;\n })\n .catch((error) => {\n this.notificationService.handleRawError(error, workPackage);\n return Promise.reject(error);\n });\n }\n\n public removeParent(workPackage:WorkPackageResource) {\n return this.changeParent(workPackage, null);\n }\n\n public addExistingChildWp(workPackage:WorkPackageResource, childWpId:string):Promise {\n return this\n .apiV3Service\n .work_packages\n .id(childWpId)\n .get()\n .toPromise()\n .then((wpToBecomeChild:WorkPackageResource|undefined) => {\n return this.changeParent(wpToBecomeChild!, workPackage.id!)\n .then(wp => {\n // Reload work package\n this\n .apiV3Service\n .work_packages\n .id(workPackage)\n .refresh();\n\n this.halEvents.push(workPackage, {\n eventType: 'association',\n relatedWorkPackage: wpToBecomeChild!.id!,\n relationType: 'child'\n });\n\n return wp;\n });\n });\n }\n\n public addNewChildWp(baseRoute:string, workPackage:WorkPackageResource) {\n workPackage.project.$load()\n .then(() => {\n const args = [\n baseRoute + '.new',\n {\n parent_id: workPackage.id\n }\n ];\n\n if (this.$state.includes('work-packages.show')) {\n args[0] = 'work-packages.new';\n }\n\n (this.$state).go(...args);\n });\n }\n\n public removeChild(childWorkPackage:WorkPackageResource) {\n return childWorkPackage.$load().then(() => {\n let parentWorkPackage = childWorkPackage.parent;\n return childWorkPackage.changeParent({\n _links: {\n parent: {\n href: null\n }\n },\n lockVersion: childWorkPackage.lockVersion\n }).then(wp => {\n if (parentWorkPackage) {\n this\n .apiV3Service\n .work_packages\n .id(parentWorkPackage)\n .refresh()\n .then((wp) => {\n this.halEvents.push(wp, {\n eventType: 'association',\n relatedWorkPackage: null,\n relationType: 'child'\n });\n });\n }\n\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(wp);\n })\n .catch((error) => {\n this.notificationService.handleRawError(error, childWorkPackage);\n return Promise.reject(error);\n });\n });\n }\n}\n","import {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SingleRowBuilder} from \"core-components/wp-fast-table/builders/rows/single-row-builder\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {groupedRowClassName} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-rows-helpers\";\n\nexport class GroupSumsBuilder extends SingleRowBuilder {\n\n @InjectField() readonly querySpace:IsolatedQuerySpace;\n @InjectField() readonly schemaCache:SchemaCacheService;\n @InjectField() readonly displayFieldService:DisplayFieldService;\n\n public text = {\n sum: this.I18n.t('js.label_sum')\n };\n\n public buildSumsRow(group:GroupObject) {\n const tr:HTMLTableRowElement = document.createElement('tr');\n tr.classList.add('wp-table--sums-row', 'wp-table--row', groupedRowClassName(group.index));\n\n this.renderColumns(group.sums, tr);\n\n return tr;\n }\n\n public renderColumns(sums:{[key:string]:any}, tr:HTMLTableRowElement) {\n this.augmentedColumns.forEach((column, i:number) => {\n const td = document.createElement('td');\n const div = this.renderContent(sums, column.id, this.sumsSchema[column.id]);\n\n if (i === 0) {\n this.appendFirstLabel(div);\n }\n\n td.appendChild(div);\n tr.append(td);\n });\n }\n\n private appendFirstLabel(div:HTMLElement) {\n const span = document.createElement('span');\n span.textContent = `${this.text.sum}`;\n span.title = `${this.text.sum}`;\n div.prepend(span);\n }\n\n private get sumsSchema():SchemaResource {\n // The schema is ensured to be loaded by wpViewAdditionalElementsService\n const results = this.querySpace.results.value!;\n const href = results.sumsSchema!.$href!;\n\n return this.schemaCache.state(href).value!;\n }\n\n private renderContent(sums:any, name:string, fieldSchema:IFieldSchema) {\n const div = document.createElement('div');\n div.classList.add('wp-table--sum-container', name);\n\n // The field schema for this element may be undefined\n // because it is not summable.\n if (!fieldSchema) {\n return div;\n }\n\n const field = this.displayFieldService.getField(\n sums,\n name,\n fieldSchema,\n { injector: this.injector, container: 'table', options: {} }\n );\n\n if (!field.isEmpty()) {\n field.render(div, field.valueString);\n }\n\n return div;\n }\n}\n","
    \n
    \n \n \n \n {{ descriptor.label }}\n *\n \n \n
    \n
    \n\n \n \n
    \n \n
    \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Injector, Input, AfterViewInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {FieldDescriptor, GroupDescriptor} from 'core-components/work-packages/wp-single-view/wp-single-view.component';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {fromEvent} from \"rxjs\";\nimport {debounceTime} from \"rxjs/operators\";\n\n@Component({\n selector: 'wp-attribute-group',\n templateUrl: './wp-attribute-group.template.html'\n})\nexport class WorkPackageFormAttributeGroupComponent extends UntilDestroyedMixin implements AfterViewInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public group:GroupDescriptor;\n\n constructor(readonly I18n:I18nService,\n public wpEditForm:EditFormComponent,\n protected injector:Injector) {\n super();\n }\n\n ngAfterViewInit() {\n setTimeout(() => this.fixColumns());\n\n // Listen to resize event and fix column start again\n fromEvent(window, 'resize', { passive: true })\n .pipe(\n this.untilDestroyed(),\n debounceTime(250)\n )\n .subscribe(() => {\n this.fixColumns();\n });\n }\n\n public trackByName(_index:number, elem:{ name:string }) {\n return elem.name;\n }\n\n /**\n * Hide read-only fields, but only when in the create mode\n * @param {FieldDescriptor} field\n */\n public shouldHideField(descriptor:FieldDescriptor) {\n const field = descriptor.field || descriptor.fields![0];\n return this.wpEditForm.editMode && !field.writable;\n }\n\n public fieldName(name:string) {\n if (name === 'startDate') {\n return 'combinedDate';\n } else {\n return name;\n }\n }\n\n /**\n * Fix the top of the columns after view has been loaded\n * to prevent columns from repositioning (e.g. when editing multi-select fields)\n */\n private fixColumns() {\n let lastOffset = 0;\n // Find corresponding HTML of attribute fields for each group\n let htmlAttributes = jQuery('div.attributes-group:contains(' + this.group.name + ')').find('.attributes-key-value');\n\n htmlAttributes.each(function() {\n let offset = jQuery(this).position().top;\n\n if (offset < lastOffset) {\n // Fix position of the column start\n jQuery(this).addClass('-column-start');\n }\n lastOffset = offset;\n });\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injector} from '@angular/core';\nimport * as moment from 'moment';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {RenderInfo} from '../wp-timeline';\nimport {TimelineCellRenderer} from './timeline-cell-renderer';\nimport {WorkPackageCellLabels} from './wp-timeline-cell';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport Moment = moment.Moment;\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {take} from \"rxjs/operators\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const classNameBar = 'bar';\nexport const classNameLeftHandle = 'leftHandle';\nexport const classNameRightHandle = 'rightHandle';\nexport const classNameBarLabel = 'bar-label';\n\n\nexport function registerWorkPackageMouseHandler(this:void,\n injector:Injector,\n getRenderInfo:() => RenderInfo,\n workPackageTimeline:WorkPackageTimelineTableController,\n halEditing:HalResourceEditingService,\n halEvents:HalEventsService,\n notificationService:WorkPackageNotificationService,\n loadingIndicator:LoadingIndicatorService,\n cell:HTMLElement,\n bar:HTMLDivElement,\n labels:WorkPackageCellLabels,\n renderer:TimelineCellRenderer,\n renderInfo:RenderInfo) {\n\n const querySpace:IsolatedQuerySpace = injector.get(IsolatedQuerySpace);\n\n let mouseDownStartDay:number|null = null; // also flag to signal active drag'n'drop\n renderInfo.change = halEditing.changeFor(renderInfo.workPackage) as WorkPackageChangeset;\n\n let dateStates:any;\n let placeholderForEmptyCell:HTMLElement;\n const jBody = jQuery('body');\n\n // handles change to existing work packages\n bar.onmousedown = (ev:MouseEvent) => {\n if (ev.which === 1) {\n // Left click only\n workPackageMouseDownFn(bar, ev);\n }\n };\n\n // handles initial creation of start/due values\n cell.onmousemove = handleMouseMoveOnEmptyCell;\n\n function applyDateValues(renderInfo:RenderInfo, dates:{ [name:string]:Moment }) {\n // Let the renderer decide which fields we change\n renderer.assignDateValues(renderInfo.change, labels, dates);\n }\n\n function getCursorOffsetInDaysFromLeft(renderInfo:RenderInfo, ev:MouseEvent) {\n const leftOffset = workPackageTimeline.getAbsoluteLeftCoordinates();\n const cursorOffsetLeftInPx = ev.clientX - leftOffset;\n const cursorOffsetLeftInDays = Math.floor(cursorOffsetLeftInPx / renderInfo.viewParams.pixelPerDay);\n return cursorOffsetLeftInDays;\n }\n\n function workPackageMouseDownFn(bar:HTMLDivElement, ev:MouseEvent) {\n ev.preventDefault();\n\n // add/remove css class while drag'n'drop is active\n const classNameActiveDrag = 'active-drag';\n bar.classList.add(classNameActiveDrag);\n jBody.on('mouseup.timelinecell', () => bar.classList.remove(classNameActiveDrag));\n\n workPackageTimeline.disableViewParamsCalculation = true;\n mouseDownStartDay = getCursorOffsetInDaysFromLeft(renderInfo, ev);\n\n // If this wp is a parent element, changing it is not allowed\n // if it is not on 'Manual scheduling' mode\n // But adding a relation to it is.\n if (!renderInfo.workPackage.isLeaf && !renderInfo.viewParams.activeSelectionMode && !renderInfo.workPackage.scheduleManually) {\n return;\n }\n\n // Determine what attributes of the work package should be changed\n const direction = renderer.onMouseDown(ev, null, renderInfo, labels, bar);\n\n jBody.on('mousemove.timelinecell', createMouseMoveFn(direction));\n jBody.on('keyup.timelinecell', keyPressFn);\n jBody.on('mouseup.timelinecell', () => deactivate(false));\n }\n\n function createMouseMoveFn(direction:'left'|'right'|'both'|'create'|'dragright') {\n return (ev:JQuery.MouseMoveEvent) => {\n const days = getCursorOffsetInDaysFromLeft(renderInfo, ev.originalEvent!) - mouseDownStartDay!;\n const offsetDayCurrent = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n const dayUnderCursor = renderInfo.viewParams.dateDisplayStart.clone().add(offsetDayCurrent, 'days');\n\n dateStates = renderer.onDaysMoved(renderInfo.change, dayUnderCursor, days, direction);\n applyDateValues(renderInfo, dateStates);\n renderer.update(bar, labels, renderInfo);\n };\n }\n\n function keyPressFn(ev:JQuery.TriggeredEvent) {\n const kev:KeyboardEvent = ev as any;\n if (kev.keyCode === keyCodes.ESCAPE) {\n deactivate(true);\n }\n }\n\n function handleMouseMoveOnEmptyCell(ev:MouseEvent) {\n const wp = renderInfo.workPackage;\n\n if (!renderer.isEmpty(wp)) {\n return;\n }\n\n const isEditable = (wp.isLeaf || wp.scheduleManually) && renderer.canMoveDates(wp);\n\n if (!isEditable) {\n cell.style.cursor = 'not-allowed';\n return;\n }\n\n // placeholder logic\n cell.style.cursor = '';\n placeholderForEmptyCell && placeholderForEmptyCell.remove();\n placeholderForEmptyCell = renderer.displayPlaceholderUnderCursor(ev, renderInfo);\n cell.appendChild(placeholderForEmptyCell);\n\n // abort if mouse leaves cell\n cell.onmouseleave = () => {\n placeholderForEmptyCell.remove();\n };\n\n // create logic\n cell.onmousedown = (ev) => {\n placeholderForEmptyCell.remove();\n bar.style.pointerEvents = 'none';\n ev.preventDefault();\n\n const offsetDayStart = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n const clickStart = renderInfo.viewParams.dateDisplayStart.clone().add(offsetDayStart, 'days');\n const dateForCreate = clickStart.format('YYYY-MM-DD');\n const mouseDownType = renderer.onMouseDown(ev, dateForCreate, renderInfo, labels, bar);\n renderer.update(bar, labels, renderInfo);\n\n if (mouseDownType === 'create') {\n deactivate(false);\n ev.preventDefault();\n return;\n }\n\n cell.onmousemove = (ev) => {\n const offsetDayCurrent = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n const dayUnderCursor = renderInfo.viewParams.dateDisplayStart.clone().add(offsetDayCurrent, 'days');\n const widthInDays = offsetDayCurrent - offsetDayStart;\n const moved = renderer.onDaysMoved(renderInfo.change, dayUnderCursor, widthInDays, mouseDownType);\n renderer.assignDateValues(renderInfo.change, labels, moved);\n renderer.update(bar, labels, renderInfo);\n };\n\n cell.onmouseleave = () => {\n deactivate(true);\n };\n\n cell.onmouseup = () => {\n deactivate(false);\n };\n\n jBody.on('keyup.timelinecell', keyPressFn);\n };\n }\n\n function deactivate(cancelled:boolean) {\n workPackageTimeline.disableViewParamsCalculation = false;\n\n cell.onmousemove = handleMouseMoveOnEmptyCell;\n cell.onmousedown = _.noop;\n cell.onmouseleave = _.noop;\n cell.onmouseup = _.noop;\n\n bar.style.pointerEvents = 'auto';\n\n jBody.off('.timelinecell');\n workPackageTimeline.resetCursor();\n mouseDownStartDay = null;\n dateStates = {};\n\n // const renderInfo = getRenderInfo();\n if (cancelled || renderInfo.change.isEmpty()) {\n cancelChange();\n } else {\n const stopAndRefresh = () => {\n renderInfo.change.clear();\n renderer.onMouseDownEnd(labels, renderInfo.change);\n };\n\n // Persist the changes\n saveWorkPackage(renderInfo.change)\n .then(stopAndRefresh)\n .catch(error => {\n notificationService.handleRawError(error, renderInfo.workPackage);\n cancelChange();\n });\n }\n }\n\n function cancelChange() {\n renderInfo.change.clear();\n renderer.update(bar, labels, renderInfo);\n renderer.onMouseDownEnd(labels, renderInfo.change);\n workPackageTimeline.refreshView();\n }\n\n function saveWorkPackage(change:WorkPackageChangeset) {\n const apiv3Service:APIV3Service = injector.get(APIV3Service);\n const querySpace:IsolatedQuerySpace = injector.get(IsolatedQuerySpace);\n\n // Remember the time before saving the work package to know which work packages to update\n const updatedAt = moment().toISOString();\n\n return loadingIndicator.table.promise = halEditing\n .save(change)\n .then((result) => {\n notificationService.showSave(result.resource);\n const ids = _.map(querySpace.tableRendered.value!, row => row.workPackageId);\n return apiv3Service\n .work_packages\n .filterUpdatedSince(ids, updatedAt)\n .get()\n .toPromise()\n .then(() => {\n halEvents.push(result.resource, { eventType: 'updated' });\n return querySpace.timelineRendered.pipe(take(1)).toPromise();\n });\n });\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../../../states.service';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {RenderInfo} from '../wp-timeline';\nimport {TimelineCellRenderer} from './timeline-cell-renderer';\nimport {TimelineMilestoneCellRenderer} from './timeline-milestone-cell-renderer';\nimport {registerWorkPackageMouseHandler} from './wp-timeline-cell-mouse-handler';\nimport {Injector} from '@angular/core';\nimport {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\nexport const classNameLeftLabel = 'labelLeft';\nexport const classNameRightContainer = 'containerRight';\nexport const classNameRightLabel = 'labelRight';\nexport const classNameLeftHoverLabel = 'labelHoverLeft';\nexport const classNameRightHoverLabel = 'labelHoverRight';\nexport const classNameHoverStyle = '-label-style';\nexport const classNameFarRightLabel = 'labelFarRight';\nexport const classNameShowOnHover = 'show-on-hover';\nexport const classNameHideOnHover = 'hide-on-hover';\n\nexport class WorkPackageCellLabels {\n\n constructor(public readonly center:HTMLDivElement|null,\n public readonly left:HTMLDivElement,\n public readonly leftHover:HTMLDivElement|null,\n public readonly right:HTMLDivElement,\n public readonly rightHover:HTMLDivElement|null,\n public readonly farRight:HTMLDivElement,\n public readonly withAlternativeLabels?:boolean) {\n }\n\n}\n\nexport class WorkPackageTimelineCell {\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() halEvents:HalEventsService;\n @InjectField() notificationService:WorkPackageNotificationService;\n @InjectField() states:States;\n @InjectField() loadingIndicator:LoadingIndicatorService;\n @InjectField() schemaCache:SchemaCacheService;\n\n private wpElement:HTMLDivElement|null = null;\n\n private elementShape:string;\n\n private labels:WorkPackageCellLabels;\n\n constructor(public readonly injector:Injector,\n public workPackageTimeline:WorkPackageTimelineTableController,\n public renderers:{ milestone:TimelineMilestoneCellRenderer, generic:TimelineCellRenderer },\n public latestRenderInfo:RenderInfo,\n public classIdentifier:string,\n public workPackageId:string) {\n }\n\n getMarginLeftOfLeftSide():number {\n const renderer = this.cellRenderer(this.latestRenderInfo.workPackage);\n return renderer.getMarginLeftOfLeftSide(this.latestRenderInfo);\n }\n\n getMarginLeftOfRightSide():number {\n const renderer = this.cellRenderer(this.latestRenderInfo.workPackage);\n return renderer.getMarginLeftOfRightSide(this.latestRenderInfo);\n }\n\n getPaddingLeftForIncomingRelationLines():number {\n const renderer = this.cellRenderer(this.latestRenderInfo.workPackage);\n return renderer.getPaddingLeftForIncomingRelationLines(this.latestRenderInfo);\n }\n\n getPaddingRightForOutgoingRelationLines():number {\n const renderer = this.cellRenderer(this.latestRenderInfo.workPackage);\n return renderer.getPaddingRightForOutgoingRelationLines(this.latestRenderInfo);\n }\n\n canConnectRelations():boolean {\n const wp = this.latestRenderInfo.workPackage;\n if (this.schemaCache.of(wp).isMilestone) {\n return !_.isNil(wp.date);\n }\n\n return !_.isNil(wp.startDate) || !_.isNil(wp.dueDate);\n }\n\n public clear() {\n this.cellElement.html('');\n this.wpElement = null;\n }\n\n private get cellContainer() {\n return this.workPackageTimeline.timelineBody;\n }\n\n private get cellElement():JQuery {\n return this.cellContainer.find(`.${this.classIdentifier}`);\n }\n\n private lazyInit(renderer:TimelineCellRenderer, renderInfo:RenderInfo):Promise {\n const body = this.workPackageTimeline.timelineBody[0];\n const cell = this.cellElement;\n\n if (!cell.length) {\n return Promise.reject('uninitialized');\n }\n\n const wasRendered = this.wpElement !== null && body.contains(this.wpElement);\n\n // If already rendered with correct shape, ignore\n if (wasRendered && this.elementShape === renderer.type) {\n return Promise.resolve();\n }\n\n // Remove the element first if we're redrawing\n if (!renderInfo.isDuplicatedCell) {\n this.clear();\n }\n\n // Render the given element\n this.wpElement = renderer.render(renderInfo);\n this.labels = renderer.createAndAddLabels(renderInfo, this.wpElement);\n this.elementShape = renderer.type;\n\n // Register the element\n cell.append(this.wpElement);\n\n // Allow editing if editable\n if (renderer.canMoveDates(renderInfo.workPackage)) {\n this.wpElement.classList.add('-editable');\n\n registerWorkPackageMouseHandler(\n this.injector,\n () => this.latestRenderInfo,\n this.workPackageTimeline,\n this.halEditing,\n this.halEvents,\n this.notificationService,\n this.loadingIndicator,\n cell[0],\n this.wpElement,\n this.labels,\n renderer,\n renderInfo);\n }\n\n return Promise.resolve();\n }\n\n private cellRenderer(workPackage:WorkPackageResource):TimelineCellRenderer {\n if (this.schemaCache.of(workPackage).isMilestone) {\n return this.renderers.milestone;\n }\n\n return this.renderers.generic;\n }\n\n public refreshView(renderInfo:RenderInfo) {\n this.latestRenderInfo = renderInfo;\n\n const renderer = this.cellRenderer(renderInfo.workPackage);\n\n // Render initial element if necessary\n this.lazyInit(renderer, renderInfo)\n .then(() => {\n // Render the upgrade from renderInfo\n const shouldBeDisplayed = renderer.update(\n this.wpElement as HTMLDivElement,\n this.labels,\n renderInfo);\n\n if (!shouldBeDisplayed) {\n this.clear();\n }\n })\n .catch(() => null);\n }\n\n}\n","import * as moment from 'moment';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {\n calculatePositionValueForDayCount,\n calculatePositionValueForDayCountingPx,\n RenderInfo,\n timelineBackgroundElementClass,\n timelineElementCssClass,\n timelineMarkerSelectionStartClass\n} from '../wp-timeline';\nimport {\n classNameFarRightLabel,\n classNameHideOnHover,\n classNameHoverStyle,\n classNameLeftHoverLabel,\n classNameLeftLabel,\n classNameRightContainer,\n classNameRightHoverLabel,\n classNameRightLabel,\n classNameShowOnHover,\n WorkPackageCellLabels\n} from './wp-timeline-cell';\nimport {classNameBarLabel, classNameLeftHandle, classNameRightHandle} from './wp-timeline-cell-mouse-handler';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {DisplayFieldRenderer} from 'core-app/modules/fields/display/display-field-renderer';\nimport {Injector} from '@angular/core';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {HierarchyRenderPass} from \"core-components/wp-fast-table/builders/modes/hierarchy/hierarchy-render-pass\";\nimport Moment = moment.Moment;\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\nexport interface CellDateMovement {\n // Target values to move work package to\n startDate?:moment.Moment;\n dueDate?:moment.Moment;\n // Target value to move milestone to\n date?:moment.Moment;\n}\n\nexport type LabelPosition = 'left'|'right'|'farRight';\n\nexport class TimelineCellRenderer {\n @InjectField() wpTableTimeline:WorkPackageViewTimelineService;\n @InjectField() TimezoneService:TimezoneService;\n @InjectField() schemaCache:SchemaCacheService;\n @InjectField() I18n!:I18nService;\n\n public text = {\n label_children_derived_duration: this.I18n.t('js.label_children_derived_duration')\n };\n\n public ganttChartRowHeight:number;\n\n public fieldRenderer:DisplayFieldRenderer = new DisplayFieldRenderer(this.injector, 'timeline');\n\n protected dateDisplaysOnMouseMove:{ left?:HTMLElement; right?:HTMLElement } = {};\n\n constructor(readonly injector:Injector,\n readonly workPackageTimeline:WorkPackageTimelineTableController) {\n this.ganttChartRowHeight = +getComputedStyle(document.documentElement)\n .getPropertyValue('--table-timeline--row-height')\n .replace('px', '');\n }\n\n public get type():string {\n return 'bar';\n }\n\n public canMoveDates(wp:WorkPackageResource) {\n const schema = this.schemaCache.of(wp);\n return schema.startDate.writable && schema.dueDate.writable && schema.isAttributeEditable('startDate');\n }\n\n public isEmpty(wp:WorkPackageResource) {\n const start = moment(wp.startDate as any);\n const due = moment(wp.dueDate as any);\n const noStartAndDueValues = _.isNaN(start.valueOf()) && _.isNaN(due.valueOf());\n return noStartAndDueValues;\n }\n\n public displayPlaceholderUnderCursor(ev:MouseEvent, renderInfo:RenderInfo):HTMLElement {\n const days = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n\n const placeholder = document.createElement('div');\n placeholder.style.pointerEvents = 'none';\n placeholder.style.position = 'absolute';\n placeholder.style.height = '1em';\n placeholder.style.width = '30px';\n placeholder.style.zIndex = '9999';\n placeholder.style.left = (days * renderInfo.viewParams.pixelPerDay) + 'px';\n\n this.applyTypeColor(renderInfo, placeholder);\n\n return placeholder;\n }\n\n /**\n * Assign changed dates to the work package.\n * For generic work packages, assigns start and finish date.\n *\n */\n public assignDateValues(change:WorkPackageChangeset,\n labels:WorkPackageCellLabels,\n dates:any):void {\n\n this.assignDate(change, 'startDate', dates.startDate);\n this.assignDate(change, 'dueDate', dates.dueDate);\n\n this.updateLabels(true, labels, change);\n }\n\n /**\n * Handle movement by days of the work package to either (or both) edge(s)\n * depending on which initial date was set.\n */\n public onDaysMoved(change:WorkPackageChangeset,\n dayUnderCursor:Moment,\n delta:number,\n direction:'left'|'right'|'both'|'create'|'dragright'):CellDateMovement {\n\n const initialStartDate = change.pristineResource.startDate;\n const initialDueDate = change.pristineResource.dueDate;\n\n const now = moment().format('YYYY-MM-DD');\n\n const startDate = moment(change.projectedResource.startDate);\n const dueDate = moment(change.projectedResource.dueDate);\n\n let dates:CellDateMovement = {};\n\n if (direction === 'left') {\n dates.startDate = moment(initialStartDate || initialDueDate).add(delta, 'days');\n } else if (direction === 'right') {\n dates.dueDate = moment(initialDueDate || now).add(delta, 'days');\n } else if (direction === 'both') {\n if (initialStartDate) {\n dates.startDate = moment(initialStartDate).add(delta, 'days');\n }\n if (initialDueDate) {\n dates.dueDate = moment(initialDueDate).add(delta, 'days');\n }\n } else if (direction === 'dragright') {\n dates.dueDate = startDate.clone().add(delta, 'days');\n }\n\n // avoid negative \"overdrag\" if only start or due are changed\n if (direction !== 'both') {\n if (dates.startDate !== undefined && dates.startDate.isAfter(dueDate)) {\n dates.startDate = dueDate;\n } else if (dates.dueDate !== undefined && dates.dueDate.isBefore(startDate)) {\n dates.dueDate = startDate;\n }\n }\n\n return dates;\n }\n\n public onMouseDown(ev:MouseEvent,\n dateForCreate:string|null,\n renderInfo:RenderInfo,\n labels:WorkPackageCellLabels,\n elem:HTMLElement):'left'|'right'|'both'|'dragright'|'create' {\n\n // check for active selection mode\n if (renderInfo.viewParams.activeSelectionMode) {\n renderInfo.viewParams.activeSelectionMode(renderInfo.workPackage);\n ev.preventDefault();\n return 'both'; // irrelevant\n }\n\n const projection = renderInfo.change.projectedResource;\n let direction:'left'|'right'|'both'|'dragright';\n\n // Update the cursor and maybe set start/due values\n if (jQuery(ev.target!).hasClass(classNameLeftHandle)) {\n // only left\n direction = 'left';\n this.workPackageTimeline.forceCursor('col-resize');\n if (projection.startDate === null) {\n projection.startDate = projection['dueDate'];\n }\n } else if (jQuery(ev.target!).hasClass(classNameRightHandle) || dateForCreate) {\n // only right\n direction = 'right';\n this.workPackageTimeline.forceCursor('col-resize');\n } else {\n // both\n direction = 'both';\n this.workPackageTimeline.forceCursor('ew-resize');\n }\n\n if (dateForCreate) {\n projection.startDate = dateForCreate;\n projection.dueDate = dateForCreate;\n direction = 'dragright';\n }\n\n this.updateLabels(true, labels, renderInfo.change);\n\n return direction;\n }\n\n public onMouseDownEnd(labels:WorkPackageCellLabels, change:WorkPackageChangeset) {\n this.updateLabels(false, labels, change);\n }\n\n /**\n * @return true, if the element should still be displayed.\n * false, if the element must be removed from the timeline.\n */\n public update(element:HTMLDivElement, labels:WorkPackageCellLabels|null, renderInfo:RenderInfo):boolean {\n const change = renderInfo.change;\n const bar = element.querySelector(`.${timelineBackgroundElementClass}`) as HTMLElement;\n let start = moment(change.projectedResource.startDate);\n let due = moment(change.projectedResource.dueDate);\n\n if (_.isNaN(start.valueOf()) && _.isNaN(due.valueOf())) {\n element.style.visibility = 'hidden';\n } else {\n element.style.visibility = 'visible';\n }\n\n // only start date, fade out bar to the right\n if (_.isNaN(due.valueOf()) && !_.isNaN(start.valueOf())) {\n // Set due date to today\n due = moment();\n bar.style.backgroundImage = `linear-gradient(90deg, rgba(255,255,255,0) 0%, #F1F1F1 100%)`;\n }\n\n // only finish date, fade out bar to the left\n if (_.isNaN(start.valueOf()) && !_.isNaN(due.valueOf())) {\n start = due.clone();\n bar.style.backgroundImage = `linear-gradient(90deg, #F1F1F1 0%, rgba(255,255,255,0) 80%)`;\n }\n\n this.setElementPositionAndSize(element, renderInfo, start, due);\n\n // Update labels if any\n if (labels) {\n this.updateLabels(false, labels, change);\n }\n\n this.checkForActiveSelectionMode(renderInfo, bar);\n this.checkForSpecialDisplaySituations(renderInfo, bar);\n this.applyTypeColor(renderInfo, bar);\n\n return true;\n }\n\n protected checkForActiveSelectionMode(renderInfo:RenderInfo, element:HTMLElement) {\n if (renderInfo.viewParams.activeSelectionMode) {\n element.style.backgroundImage = ''; // required! unable to disable \"fade out bar\" with css\n\n if (renderInfo.viewParams.selectionModeStart === '' + renderInfo.workPackage.id!) {\n jQuery(element).addClass(timelineMarkerSelectionStartClass);\n element.style.background = 'none';\n }\n }\n }\n\n getMarginLeftOfLeftSide(renderInfo:RenderInfo):number {\n const projection = renderInfo.change.projectedResource;\n\n let start = moment(projection.startDate);\n let due = moment(projection.dueDate);\n start = _.isNaN(start.valueOf()) ? due.clone() : start;\n\n const offsetStart = start.diff(renderInfo.viewParams.dateDisplayStart, 'days');\n\n return calculatePositionValueForDayCountingPx(renderInfo.viewParams, offsetStart);\n }\n\n getMarginLeftOfRightSide(renderInfo:RenderInfo):number {\n const projection = renderInfo.change.projectedResource;\n\n let start = moment(projection.startDate);\n let due = moment(projection.dueDate);\n\n start = _.isNaN(start.valueOf()) ? due.clone() : start;\n due = _.isNaN(due.valueOf()) ? start.clone() : due;\n\n const offsetStart = start.diff(renderInfo.viewParams.dateDisplayStart, 'days');\n const duration = due.diff(start, 'days') + 1;\n\n return calculatePositionValueForDayCountingPx(renderInfo.viewParams, offsetStart + duration);\n }\n\n getPaddingLeftForIncomingRelationLines(renderInfo:RenderInfo):number {\n return renderInfo.viewParams.pixelPerDay / 8;\n }\n\n getPaddingRightForOutgoingRelationLines(renderInfo:RenderInfo):number {\n return 0;\n }\n\n /**\n * Render the generic cell element, a bar spanning from\n * start to finish date.\n */\n public render(renderInfo:RenderInfo):HTMLDivElement {\n const container = document.createElement('div');\n const bar = document.createElement('div');\n const left = document.createElement('div');\n const right = document.createElement('div');\n\n container.className = timelineElementCssClass + ' ' + this.type;\n bar.className = timelineBackgroundElementClass;\n left.className = classNameLeftHandle;\n right.className = classNameRightHandle;\n container.appendChild(bar);\n container.appendChild(left);\n container.appendChild(right);\n\n return container;\n }\n\n createAndAddLabels(renderInfo:RenderInfo, element:HTMLElement):WorkPackageCellLabels {\n // create center label\n const labelCenter = document.createElement('div');\n labelCenter.classList.add(classNameBarLabel);\n this.applyTypeColor(renderInfo, labelCenter);\n element.appendChild(labelCenter);\n\n // create left label\n const labelLeft = document.createElement('div');\n labelLeft.classList.add(classNameLeftLabel, classNameHideOnHover);\n element.appendChild(labelLeft);\n\n // create right container\n const containerRight = document.createElement('div');\n containerRight.classList.add(classNameRightContainer);\n element.appendChild(containerRight);\n\n // create right label\n const labelRight = document.createElement('div');\n labelRight.classList.add(classNameRightLabel, classNameHideOnHover);\n containerRight.appendChild(labelRight);\n\n // create far right label\n const labelFarRight = document.createElement('div');\n labelFarRight.classList.add(classNameFarRightLabel, classNameHideOnHover);\n containerRight.appendChild(labelFarRight);\n\n // create left hover label\n const labelHoverLeft = document.createElement('div');\n labelHoverLeft.classList.add(classNameLeftHoverLabel, classNameShowOnHover, classNameHoverStyle);\n element.appendChild(labelHoverLeft);\n\n // create right hover label\n const labelHoverRight = document.createElement('div');\n labelHoverRight.classList.add(classNameRightHoverLabel, classNameShowOnHover, classNameHoverStyle);\n element.appendChild(labelHoverRight);\n\n const labels = new WorkPackageCellLabels(labelCenter, labelLeft, labelHoverLeft, labelRight, labelHoverRight, labelFarRight);\n this.updateLabels(false, labels, renderInfo.change);\n\n return labels;\n }\n\n protected applyTypeColor(renderInfo:RenderInfo, bg:HTMLElement):void {\n let wp = renderInfo.workPackage;\n let type = wp.type;\n let selectionMode = renderInfo.viewParams.activeSelectionMode;\n\n // Don't apply the class in selection mode\n const id = type.id;\n if (selectionMode) {\n bg.classList.remove(Highlighting.backgroundClass('type', id!));\n } else {\n bg.classList.add(Highlighting.backgroundClass('type', id!));\n }\n }\n\n protected assignDate(change:WorkPackageChangeset, attributeName:string, value:moment.Moment) {\n if (value) {\n change.projectedResource[attributeName] = value.format('YYYY-MM-DD');\n }\n }\n\n setElementPositionAndSize(element:HTMLElement, renderInfo:RenderInfo, start:moment.Moment, due:moment.Moment) {\n const viewParams = renderInfo.viewParams;\n // offset left\n const offsetStart = start.diff(viewParams.dateDisplayStart, 'days');\n element.style.left = calculatePositionValueForDayCount(viewParams, offsetStart);\n\n // duration\n const duration = due.diff(start, 'days') + 1;\n element.style.width = calculatePositionValueForDayCount(viewParams, duration);\n\n // ensure minimum width\n if (!_.isNaN(start.valueOf()) || !_.isNaN(due.valueOf())) {\n const minWidth = _.max([renderInfo.viewParams.pixelPerDay, 2]);\n element.style.minWidth = minWidth + 'px';\n }\n }\n\n /**\n * Changes the presentation of the work package.\n *\n * Known cases:\n * 1. Display a clamp if this work package is a parent element\n * and display a box wrapping all the visible children when the\n * parent is hovered\n */\n checkForSpecialDisplaySituations(renderInfo:RenderInfo, bar:HTMLElement) {\n const wp = renderInfo.workPackage;\n const row = bar.parentElement!.parentElement!;\n let selectionMode = renderInfo.viewParams.activeSelectionMode;\n\n // Cannot edit the work package if it has children\n // and it is not on 'Manual scheduling' mode\n if (!wp.isLeaf && !selectionMode && !wp.scheduleManually) {\n bar.classList.add('-readonly');\n } else {\n bar.classList.remove('-readonly');\n }\n\n // Display the children's duration clamp\n if (wp.derivedStartDate && wp.derivedDueDate) {\n const derivedStartDate = moment(wp.derivedStartDate);\n const derivedDueDate = moment(wp.derivedDueDate);\n const startDate = moment(renderInfo.change.projectedResource.startDate);\n const dueDate = moment(renderInfo.change.projectedResource.dueDate);\n const previousChildrenDurationBar = row.querySelector('.children-duration-bar');\n const childrenDurationBar = document.createElement('div');\n const childrenDurationHoverContainer = document.createElement('div');\n const visibleChildren = document.querySelectorAll(`.wp-timeline-cell.__hierarchy-group-${wp.id}:not([class*='__collapsed-group'])`).length || 0;\n\n childrenDurationBar.classList.add('children-duration-bar', '-clamp-style');\n childrenDurationBar.title = this.text.label_children_derived_duration;\n childrenDurationHoverContainer.classList.add('children-duration-hover-container');\n childrenDurationHoverContainer.style.height = this.ganttChartRowHeight * visibleChildren + 10 + 'px';\n\n if (derivedStartDate.isBefore(startDate) || derivedDueDate.isAfter(dueDate)) {\n childrenDurationBar.classList.add('-duration-overflow');\n }\n\n this.setElementPositionAndSize(childrenDurationBar, renderInfo, derivedStartDate, derivedDueDate);\n\n if (previousChildrenDurationBar) {\n previousChildrenDurationBar.remove();\n }\n\n childrenDurationBar.appendChild(childrenDurationHoverContainer);\n row!.appendChild(childrenDurationBar);\n }\n }\n\n protected updateLabels(activeDragNDrop:boolean,\n labels:WorkPackageCellLabels,\n change:WorkPackageChangeset) {\n\n const labelConfiguration = this.wpTableTimeline.getNormalizedLabels(change.projectedResource);\n\n if (!activeDragNDrop) {\n // normal display\n this.renderLabel(change, labels, 'left', labelConfiguration.left);\n this.renderLabel(change, labels, 'right', labelConfiguration.right);\n this.renderLabel(change, labels, 'farRight', labelConfiguration.farRight);\n }\n\n // Update hover labels\n this.renderHoverLabels(labels, change);\n }\n\n protected renderHoverLabels(labels:WorkPackageCellLabels, change:WorkPackageChangeset) {\n this.renderLabel(change, labels, 'leftHover', 'startDate');\n this.renderLabel(change, labels, 'rightHover', 'dueDate');\n }\n\n protected renderLabel(change:WorkPackageChangeset,\n labels:WorkPackageCellLabels,\n position:LabelPosition|'leftHover'|'rightHover',\n attribute:string|null) {\n\n // Get the label position\n // Skip label if it does not exist (milestones)\n let label = labels[position];\n if (!label) {\n return;\n }\n\n // Reset label value\n label.innerHTML = '';\n\n if (attribute === null) {\n label.classList.remove('not-empty');\n return;\n }\n\n // Get the rendered field\n let [field, span] = this.fieldRenderer.renderFieldValue(change.projectedResource, attribute, change);\n\n if (label && field && span) {\n span.classList.add('label-content');\n label.appendChild(span);\n label.classList.add('not-empty');\n } else if (label) {\n label.classList.remove('not-empty');\n }\n }\n\n protected isParentWithVisibleChildren(wp:WorkPackageResource):boolean {\n if (!this.workPackageTimeline.inHierarchyMode) {\n return false;\n }\n\n const renderPass = this.workPackageTimeline.workPackageTable.lastRenderPass as HierarchyRenderPass|null;\n if (renderPass) {\n return !!renderPass.parentsWithVisibleChildren[wp.id!];\n }\n\n return false;\n }\n}\n","import * as moment from 'moment';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {\n calculatePositionValueForDayCountingPx,\n RenderInfo,\n timelineElementCssClass\n} from '../wp-timeline';\nimport {CellDateMovement, LabelPosition, TimelineCellRenderer} from './timeline-cell-renderer';\nimport {\n classNameFarRightLabel,\n classNameHideOnHover,\n classNameHoverStyle,\n classNameLeftHoverLabel,\n classNameLeftLabel,\n classNameRightContainer,\n classNameRightHoverLabel,\n classNameRightLabel,\n classNameShowOnHover,\n WorkPackageCellLabels\n} from './wp-timeline-cell';\nimport Moment = moment.Moment;\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\n\nexport class TimelineMilestoneCellRenderer extends TimelineCellRenderer {\n public get type():string {\n return 'milestone';\n }\n\n public isEmpty(wp:WorkPackageResource) {\n const date = moment(wp.date as any);\n return _.isNaN(date.valueOf());\n }\n\n public canMoveDates(wp:WorkPackageResource) {\n const schema = this.schemaCache.of(wp);\n return schema.date.writable && schema.isAttributeEditable('date');\n }\n\n public displayPlaceholderUnderCursor(ev:MouseEvent, renderInfo:RenderInfo):HTMLElement {\n const days = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n\n const placeholder = document.createElement('div');\n placeholder.className = 'timeline-element milestone';\n placeholder.style.pointerEvents = 'none';\n placeholder.style.height = '1em';\n placeholder.style.width = '1em';\n placeholder.style.left = (days * renderInfo.viewParams.pixelPerDay) + 'px';\n\n const diamond = document.createElement('div');\n diamond.className = 'diamond';\n diamond.style.left = '0.5em';\n diamond.style.height = '1em';\n diamond.style.width = '1em';\n placeholder.appendChild(diamond);\n\n this.applyTypeColor(renderInfo, diamond);\n\n return placeholder;\n }\n\n /**\n * Assign changed dates to the work package.\n * For generic work packages, assigns start and finish date .\n *\n */\n public assignDateValues(change:WorkPackageChangeset,\n labels:WorkPackageCellLabels,\n dates:any):void {\n\n this.assignDate(change, 'date', dates.date);\n this.updateLabels(true, labels, change);\n }\n\n /**\n * Handle movement by days of milestone.\n */\n public onDaysMoved(change:WorkPackageChangeset,\n dayUnderCursor:Moment,\n delta:number,\n direction:'left' | 'right' | 'both' | 'create' | 'dragright') {\n\n const initialDate = change.pristineResource.date;\n let dates:CellDateMovement = {};\n\n if (initialDate) {\n dates.date = moment(initialDate).add(delta, 'days');\n }\n\n return dates;\n }\n\n public onMouseDown(ev:MouseEvent,\n dateForCreate:string | null,\n renderInfo:RenderInfo,\n labels:WorkPackageCellLabels,\n elem:HTMLElement):'left' | 'right' | 'both' | 'create' | 'dragright' {\n\n // check for active selection mode\n if (renderInfo.viewParams.activeSelectionMode) {\n renderInfo.viewParams.activeSelectionMode(renderInfo.workPackage);\n ev.preventDefault();\n return 'both'; // irrelevant\n }\n\n let direction:'both' | 'create' = 'both';\n this.workPackageTimeline.forceCursor('ew-resize');\n\n if (dateForCreate) {\n renderInfo.change.projectedResource.date = dateForCreate;\n direction = 'create';\n return direction;\n }\n\n this.updateLabels(true, labels, renderInfo.change);\n\n return direction;\n }\n\n public update(element:HTMLDivElement, labels:WorkPackageCellLabels|null, renderInfo:RenderInfo):boolean {\n const viewParams = renderInfo.viewParams;\n const date = moment(renderInfo.change.projectedResource.date);\n\n // abort if no date\n if (_.isNaN(date.valueOf())) {\n return false;\n }\n\n const diamond = jQuery('.diamond', element)[0];\n\n diamond.style.width = 15 + 'px';\n diamond.style.height = 15 + 'px';\n diamond.style.width = 15 + 'px';\n diamond.style.height = 15 + 'px';\n diamond.style.marginLeft = -(15 / 2) + (renderInfo.viewParams.pixelPerDay / 2) + 'px';\n this.applyTypeColor(renderInfo, diamond);\n\n // offset left\n const offsetStart = date.diff(viewParams.dateDisplayStart, 'days');\n element.style.left = calculatePositionValueForDayCountingPx(viewParams, offsetStart) + 'px';\n\n // Update labels if any\n if (labels) {\n this.updateLabels(false, labels, renderInfo.change);\n }\n\n this.checkForActiveSelectionMode(renderInfo, diamond);\n\n return true;\n }\n\n getMarginLeftOfLeftSide(renderInfo:RenderInfo):number {\n const change = renderInfo.change;\n let start = moment(change.projectedResource.date);\n const offsetStart = start.diff(renderInfo.viewParams.dateDisplayStart, 'days');\n return calculatePositionValueForDayCountingPx(renderInfo.viewParams, offsetStart);\n }\n\n getMarginLeftOfRightSide(ri:RenderInfo):number {\n return this.getMarginLeftOfLeftSide(ri) + ri.viewParams.pixelPerDay;\n }\n\n getPaddingLeftForIncomingRelationLines(renderInfo:RenderInfo):number {\n return (renderInfo.viewParams.pixelPerDay / 2) - 1;\n }\n\n getPaddingRightForOutgoingRelationLines(renderInfo:RenderInfo):number {\n return (15 / 2);\n }\n\n /**\n * Render a milestone element, a single day event with no resize, but\n * move functionality.\n */\n public render(renderInfo:RenderInfo):HTMLDivElement {\n const element = document.createElement('div');\n element.className = timelineElementCssClass + ' ' + this.type;\n\n const diamond = document.createElement('div');\n diamond.className = 'diamond';\n element.appendChild(diamond);\n\n return element;\n }\n\n createAndAddLabels(renderInfo:RenderInfo, element:HTMLElement):WorkPackageCellLabels {\n // create left label\n const labelLeft = document.createElement('div');\n labelLeft.classList.add(classNameLeftLabel, classNameHideOnHover);\n element.appendChild(labelLeft);\n\n // create right container\n const containerRight = document.createElement('div');\n containerRight.classList.add(classNameRightContainer);\n element.appendChild(containerRight);\n\n // create right label\n const labelRight = document.createElement('div');\n labelRight.classList.add(classNameRightLabel, classNameHideOnHover);\n containerRight.appendChild(labelRight);\n\n // create far right label\n const labelFarRight = document.createElement('div');\n labelFarRight.classList.add(classNameFarRightLabel, classNameHideOnHover);\n containerRight.appendChild(labelFarRight);\n\n // Create right hover label\n const labelHoverRight = document.createElement('div');\n labelHoverRight.classList.add(classNameRightHoverLabel, classNameShowOnHover, classNameHoverStyle);\n element.appendChild(labelHoverRight);\n\n // Create left hover label\n const labelHoverLeft = document.createElement('div');\n labelHoverLeft.classList.add(classNameLeftHoverLabel, classNameShowOnHover, classNameHoverStyle);\n element.appendChild(labelHoverLeft);\n\n const labels = new WorkPackageCellLabels(null, labelLeft, labelHoverLeft, labelRight, labelHoverRight, labelFarRight, renderInfo.withAlternativeLabels);\n this.updateLabels(false, labels, renderInfo.change);\n\n return labels;\n }\n\n protected renderHoverLabels(labels:WorkPackageCellLabels, change:WorkPackageChangeset) {\n if (labels.withAlternativeLabels) {\n this.renderLabel(change, labels, 'leftHover', 'date');\n this.renderLabel(change, labels, 'rightHover', 'subject');\n } else {\n this.renderLabel(change, labels, 'rightHover', 'date');\n }\n }\n\n protected updateLabels(activeDragNDrop:boolean,\n labels:WorkPackageCellLabels,\n change:WorkPackageChangeset) {\n\n const labelConfiguration = this.wpTableTimeline.getNormalizedLabels(change.projectedResource);\n\n if (!activeDragNDrop) {\n // normal display\n\n if (labels.withAlternativeLabels) {\n this.renderLabel(change, labels, 'right', 'subject');\n } else {\n // Show only one date field if left=start, right=dueDate\n if (labelConfiguration.left === 'startDate' && labelConfiguration.right === 'dueDate') {\n this.renderLabel(change, labels, 'left', null);\n this.renderLabel(change, labels, 'right', 'date');\n } else {\n this.renderLabel(change, labels, 'left', labelConfiguration.left);\n this.renderLabel(change, labels, 'right', labelConfiguration.right);\n }\n }\n\n this.renderLabel(change, labels, 'farRight', labelConfiguration.farRight);\n }\n\n // Update hover labels\n this.renderHoverLabels(labels, change);\n }\n\n protected renderLabel(change:WorkPackageChangeset,\n labels:WorkPackageCellLabels,\n position:LabelPosition|'leftHover'|'rightHover',\n attribute:string|null) {\n // Normalize attribute\n if (attribute === 'startDate' || attribute === 'dueDate') {\n attribute = 'date';\n }\n\n super.renderLabel(change, labels, position, attribute);\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injector} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {RenderInfo} from '../wp-timeline';\nimport {TimelineCellRenderer} from './timeline-cell-renderer';\nimport {TimelineMilestoneCellRenderer} from './timeline-milestone-cell-renderer';\nimport {WorkPackageTimelineCell} from './wp-timeline-cell';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class WorkPackageTimelineCellsRenderer {\n\n // Injections\n @InjectField() public states:States;\n @InjectField() public halEditing:HalResourceEditingService;\n\n public cells:{ [classIdentifier:string]:WorkPackageTimelineCell } = {};\n\n private cellRenderers:{ milestone:TimelineMilestoneCellRenderer, generic:TimelineCellRenderer };\n\n constructor(readonly injector:Injector,\n readonly wpTimeline:WorkPackageTimelineTableController) {\n this.cellRenderers = {\n milestone: new TimelineMilestoneCellRenderer(this.injector, wpTimeline),\n generic: new TimelineCellRenderer(this.injector, wpTimeline)\n };\n }\n\n public hasCell(wpId:string) {\n return this.getCellsFor(wpId).length > 0;\n }\n\n public getCellsFor(wpId:string):WorkPackageTimelineCell[] {\n return _.filter(this.cells, (cell) => cell.workPackageId === wpId) || [];\n }\n\n /**\n * Synchronize the currently active cells and render them all\n */\n public refreshAllCells() {\n // Create new cells and delete old ones\n this.synchronizeCells();\n\n // Update all cells\n _.each(this.cells, (cell) => this.refreshSingleCell(cell));\n }\n\n public refreshCellsFor(wpId:string) {\n _.each(this.getCellsFor(wpId), (cell) => this.refreshSingleCell(cell));\n }\n\n public refreshSingleCell(cell:WorkPackageTimelineCell, isDuplicatedCell?:boolean, withAlternativeLabels?:boolean) {\n const renderInfo = this.renderInfoFor(cell.workPackageId, isDuplicatedCell, withAlternativeLabels);\n\n if (renderInfo.workPackage) {\n cell.refreshView(renderInfo);\n }\n }\n\n /**\n * Synchronize the current cells:\n *\n * 1. Create new cells in workPackageIdOrder not yet tracked\n * 2. Remove old cells no longer contained.\n */\n private synchronizeCells() {\n const currentlyActive:string[] = Object.keys(this.cells);\n const newCells:string[] = [];\n\n _.each(this.wpTimeline.workPackageIdOrder, (renderedRow:RenderedWorkPackage) => {\n const wpId = renderedRow.workPackageId;\n\n // Ignore extra rows not tied to a work package\n if (!wpId) {\n return;\n }\n\n const state = this.states.workPackages.get(wpId);\n if (state.isPristine()) {\n return;\n }\n\n // As work packages may occur several times, get the unique identifier\n // to identify the cell\n const identifier = renderedRow.classIdentifier;\n\n // Create a cell unless we already have an active cell\n if (!this.cells[identifier]) {\n this.cells[identifier] = this.buildCell(identifier, wpId.toString());\n }\n\n newCells.push(identifier);\n });\n\n _.difference(currentlyActive, newCells).forEach((identifier:string) => {\n this.cells[identifier].clear();\n delete this.cells[identifier];\n });\n }\n\n private buildCell(classIdentifier:string, workPackageId:string) {\n return new WorkPackageTimelineCell(\n this.injector,\n this.wpTimeline,\n this.cellRenderers,\n this.renderInfoFor(workPackageId),\n classIdentifier,\n workPackageId\n );\n }\n\n private renderInfoFor(wpId:string, isDuplicatedCell?:boolean, withAlternativeLabels?:boolean):RenderInfo {\n const wp = this.states.workPackages.get(wpId).value!;\n return {\n viewParams: this.wpTimeline.viewParameters,\n workPackage: wp,\n change: this.halEditing.changeFor(wp) as WorkPackageChangeset,\n isDuplicatedCell,\n withAlternativeLabels,\n };\n }\n\n public buildCellsAndRenderOnRow(workPackageIds:string[], rowClassIdentifier:string, isDuplicatedCell?:boolean):WorkPackageTimelineCell[] {\n const cells = workPackageIds.map(workPackageId => this.buildCell(rowClassIdentifier, workPackageId!));\n\n cells.forEach((cell:WorkPackageTimelineCell) => this.refreshSingleCell(cell, isDuplicatedCell, true));\n\n return cells;\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, Component, ElementRef, Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {INotification, NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {IsolatedQuerySpace} from 'core-app/modules/work_packages/query-space/isolated-query-space';\nimport * as moment from 'moment';\nimport {Moment} from 'moment';\nimport {filter, takeUntil} from 'rxjs/operators';\nimport {\n calculateDaySpan,\n getPixelPerDayForZoomLevel,\n requiredPixelMarginLeft,\n timelineElementCssClass,\n timelineHeaderSelector,\n timelineMarkerSelectionStartClass,\n TimelineViewParameters,\n zoomLevelOrder\n} from '../wp-timeline';\nimport {input, InputState} from 'reactivestates';\nimport {WorkPackageTable} from 'core-components/wp-fast-table/wp-fast-table';\nimport {WorkPackageTimelineCellsRenderer} from 'core-components/wp-table/timeline/cells/wp-timeline-cells-renderer';\nimport {States} from 'core-components/states.service';\nimport {WorkPackageViewTimelineService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service';\nimport {WorkPackageRelationsService} from 'core-components/wp-relations/wp-relations.service';\nimport {WorkPackageViewHierarchiesService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service';\nimport {WorkPackageTimelineCell} from 'core-components/wp-table/timeline/cells/wp-timeline-cell';\nimport {selectorTimelineSide} from 'core-components/wp-table/wp-table-scroll-sync';\nimport {debugLog, timeOutput} from 'core-app/helpers/debug_output';\nimport {RenderedWorkPackage} from 'core-app/modules/work_packages/render-info/rendered-work-package.type';\nimport {HalEventsService} from 'core-app/modules/hal/services/hal-events.service';\nimport {WorkPackageNotificationService} from 'core-app/modules/work_packages/notifications/work-package-notification.service';\nimport {combineLatest, Observable} from 'rxjs';\nimport {UntilDestroyedMixin} from 'core-app/helpers/angular/until-destroyed.mixin';\nimport {WorkPackagesTableComponent} from 'core-components/wp-table/wp-table.component';\nimport {\n groupIdFromIdentifier,\n groupTypeFromIdentifier\n} from 'core-components/wp-fast-table/builders/modes/grouped/grouped-rows-helpers';\nimport {WorkPackageViewCollapsedGroupsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service';\n\n@Component({\n selector: 'wp-timeline-container',\n templateUrl: './wp-timeline-container.html'\n})\nexport class WorkPackageTimelineTableController extends UntilDestroyedMixin implements AfterViewInit {\n private $element:JQuery;\n\n public workPackageTable:WorkPackageTable;\n\n private _viewParameters:TimelineViewParameters = new TimelineViewParameters();\n\n public disableViewParamsCalculation = false;\n\n public workPackageIdOrder:RenderedWorkPackage[] = [];\n\n private renderers:{ [name:string]:(vp:TimelineViewParameters) => void } = {};\n\n private cellsRenderer = new WorkPackageTimelineCellsRenderer(this.injector, this);\n\n public outerContainer:JQuery;\n\n public timelineBody:JQuery;\n\n private selectionParams:{ notification:INotification|null } = {\n notification: null\n };\n\n private text:{ selectionMode:string };\n\n private refreshRequest = input();\n\n private collapsedGroupsCellsMap:IGroupCellsMap = {};\n\n private orderedRows:RenderedWorkPackage[] = [];\n\n get commonPipes() {\n return (source:Observable) => {\n return source.pipe(\n this.untilDestroyed(),\n takeUntil(this.querySpace.stopAllSubscriptions),\n filter(() => this.initialized && this.wpTableTimeline.isVisible),\n );\n };\n }\n\n get workPackagesWithGroupHeaderCell():RenderedWorkPackage[] {\n const tableWorkPackages = this.querySpace.results.value!.elements;\n const wpsWithGroupHeaderCell = tableWorkPackages\n .filter(tableWorkPackage => this.shouldBeShownInCollapsedGroupHeaders(tableWorkPackage))\n .map(tableWorkPackage => tableWorkPackage.id);\n const workPackagesWithGroupHeaderCell = this.orderedRows.filter(row => wpsWithGroupHeaderCell.includes(row.workPackageId!) && !this.workPackageIdOrder.includes(row));\n\n return workPackagesWithGroupHeaderCell;\n }\n\n constructor(public readonly injector:Injector,\n private elementRef:ElementRef,\n private states:States,\n public wpTableComponent:WorkPackagesTableComponent,\n private NotificationsService:NotificationsService,\n private wpTableTimeline:WorkPackageViewTimelineService,\n private notificationService:WorkPackageNotificationService,\n private wpRelations:WorkPackageRelationsService,\n private wpTableHierarchies:WorkPackageViewHierarchiesService,\n private halEvents:HalEventsService,\n private querySpace:IsolatedQuerySpace,\n readonly I18n:I18nService,\n private workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService) {\n super();\n }\n\n ngAfterViewInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.text = {\n selectionMode: this.I18n.t('js.timelines.selection_mode.notification')\n };\n\n // Get the outer container for width computation\n this.outerContainer = this.$element.find('.wp-table-timeline--outer');\n this.timelineBody = this.$element.find('.wp-table-timeline--body');\n\n // Register this instance to the table\n this.wpTableComponent.registerTimeline(this, this.timelineBody[0]);\n\n // Refresh on window resize events\n window.addEventListener('wp-resize.timeline', () => this.refreshRequest.putValue(undefined));\n\n combineLatest([\n this.querySpace.tableRendered.values$(),\n this.refreshRequest.changes$(),\n this.wpTableTimeline.live$()\n ]).pipe(\n this.commonPipes,\n )\n .subscribe(([orderedRows, changes, timelineState]) => {\n // Remember all visible rows in their order of appearance.\n this.workPackageIdOrder = orderedRows.filter((row:RenderedWorkPackage) => !row.hidden);\n this.orderedRows = orderedRows;\n this.refreshView();\n });\n\n this.setupManageCollapsedGroupHeaderCells();\n }\n\n workPackageCells(wpId:string):WorkPackageTimelineCell[] {\n return this.cellsRenderer.getCellsFor(wpId);\n }\n\n /**\n * Return the index of a given row by its class identifier\n */\n workPackageIndex(classIdentifier:string):number {\n return this.workPackageIdOrder.findIndex((el) => el.classIdentifier === classIdentifier);\n }\n\n onRefreshRequested(name:string, callback:(vp:TimelineViewParameters) => void) {\n this.renderers[name] = callback;\n }\n\n getAbsoluteLeftCoordinates():number {\n return this.$element.offset()!.left;\n }\n\n getParentScrollContainer() {\n return this.outerContainer.closest(selectorTimelineSide)[0];\n }\n\n get viewParameters():TimelineViewParameters {\n return this._viewParameters;\n }\n\n get inHierarchyMode():boolean {\n return this.wpTableHierarchies.isEnabled;\n }\n\n get initialized():boolean {\n return this.workPackageTable && this.querySpace.tableRendered.hasValue();\n }\n\n refreshView() {\n if (!this.wpTableTimeline.isVisible) {\n debugLog('refreshView() requested, but TL is invisible.');\n return;\n }\n\n if (this.wpTableTimeline.isAutoZoom()) {\n // Update autozoom level\n this.applyAutoZoomLevel();\n } else {\n this._viewParameters.settings.zoomLevel = this.wpTableTimeline.zoomLevel;\n this.wpTableTimeline.appliedZoomLevel = this.wpTableTimeline.zoomLevel;\n }\n\n timeOutput('refreshView() in timeline container', () => {\n // Reset the width of the outer container if its content shrinks\n this.outerContainer.css('width', 'auto');\n\n this.calculateViewParams(this._viewParameters);\n\n // Update all cells\n this.cellsRenderer.refreshAllCells();\n\n _.each(this.renderers, (cb, key) => {\n debugLog(`Refreshing timeline member ${key}`);\n cb(this._viewParameters);\n });\n\n this.refreshCollapsedGroupsHeaderCells(this.collapsedGroupsCellsMap, this.cellsRenderer);\n\n // Calculate overflowing width to set to outer container\n // required to match width in all child divs.\n // The header is the only one reliable, as it already has the final width.\n const currentWidth = this.$element.find(timelineHeaderSelector)[0].scrollWidth;\n this.outerContainer.width(currentWidth);\n\n // Mark rendering event in a timeout to give DOM some time\n setTimeout(() => {\n this.querySpace.timelineRendered.next(null);\n });\n });\n }\n\n startAddRelationPredecessor(start:WorkPackageResource) {\n this.activateSelectionMode(start.id!, end => {\n this.wpRelations\n .addCommonRelation(start.id!, 'follows', end.id!)\n .then(() => {\n this.halEvents.push(start, {\n eventType: 'association',\n relatedWorkPackage: end.id!,\n relationType: 'follows'\n });\n })\n .catch((error:any) => this.notificationService.handleRawError(error, end));\n });\n }\n\n startAddRelationFollower(start:WorkPackageResource) {\n this.activateSelectionMode(start.id!, end => {\n this.wpRelations\n .addCommonRelation(start.id!, 'precedes', end.id!)\n .then(() => {\n this.halEvents.push(start, {\n eventType: 'association',\n relatedWorkPackage: end.id!,\n relationType: 'precedes'\n });\n })\n .catch((error:any) => this.notificationService.handleRawError(error, end));\n });\n }\n\n getFirstDayInViewport() {\n const outerContainer = this.getParentScrollContainer();\n const scrollLeft = outerContainer.scrollLeft;\n const nonVisibleDaysLeft = Math.floor(scrollLeft / this.viewParameters.pixelPerDay);\n return this.viewParameters.dateDisplayStart.clone().add(nonVisibleDaysLeft, 'days');\n }\n\n getLastDayInViewport() {\n const outerContainer = this.getParentScrollContainer();\n const scrollLeft = outerContainer.scrollLeft;\n const width = outerContainer.offsetWidth;\n const viewPortRight = scrollLeft + width;\n const daysUntilViewPortEnds = Math.ceil(viewPortRight / this.viewParameters.pixelPerDay) + 1;\n return this.viewParameters.dateDisplayStart.clone().add(daysUntilViewPortEnds, 'days');\n }\n\n forceCursor(cursor:string) {\n jQuery('.' + timelineElementCssClass).css('cursor', cursor);\n jQuery('.wp-timeline-cell').css('cursor', cursor);\n jQuery('.hascontextmenu').css('cursor', cursor);\n jQuery('.leftHandle').css('cursor', cursor);\n jQuery('.rightHandle').css('cursor', cursor);\n }\n\n resetCursor() {\n jQuery('.' + timelineElementCssClass).css('cursor', '');\n jQuery('.wp-timeline-cell').css('cursor', '');\n jQuery('.hascontextmenu').css('cursor', '');\n jQuery('.leftHandle').css('cursor', '');\n jQuery('.rightHandle').css('cursor', '');\n }\n\n private resetSelectionMode() {\n this._viewParameters.activeSelectionMode = null;\n this._viewParameters.selectionModeStart = null;\n\n if (this.selectionParams.notification) {\n this.NotificationsService.remove(this.selectionParams.notification);\n }\n\n Mousetrap.unbind('esc');\n\n this.$element.removeClass('active-selection-mode');\n jQuery('.' + timelineMarkerSelectionStartClass).removeClass(timelineMarkerSelectionStartClass);\n this.refreshView();\n }\n\n private activateSelectionMode(start:string, callback:(wp:WorkPackageResource) => any) {\n start = start.toString(); // old system bug: ID can be a 'number'\n\n this._viewParameters.activeSelectionMode = (wp:WorkPackageResource) => {\n callback(wp);\n this.resetSelectionMode();\n };\n\n this._viewParameters.selectionModeStart = start;\n Mousetrap.bind('esc', () => this.resetSelectionMode());\n this.selectionParams.notification = this.NotificationsService.addNotice(this.text.selectionMode);\n\n this.$element.addClass('active-selection-mode');\n\n this.refreshView();\n }\n\n private calculateViewParams(currentParams:TimelineViewParameters):boolean {\n if (this.disableViewParamsCalculation) {\n return false;\n }\n\n const newParams = new TimelineViewParameters();\n let changed = false;\n const workPackagesToCalculateTimelineWidthFrom = this.getWorkPackagesToCalculateTimelineWidthFrom();\n\n workPackagesToCalculateTimelineWidthFrom.forEach((renderedRow) => {\n const wpId = renderedRow.workPackageId;\n\n if (!wpId) {\n return;\n }\n const workPackageState:InputState = this.states.workPackages.get(wpId);\n const workPackage:WorkPackageResource|undefined = workPackageState.value;\n\n if (!workPackage) {\n return;\n }\n\n // We may still have a reference to a row that, e.g., just got deleted\n const startDate = workPackage.startDate ? moment(workPackage.startDate) : currentParams.now;\n const dueDate = workPackage.dueDate ? moment(workPackage.dueDate) : currentParams.now;\n const date = workPackage.date ? moment(workPackage.date) : currentParams.now;\n\n // start date\n newParams.dateDisplayStart = moment.min(\n newParams.dateDisplayStart,\n currentParams.now,\n startDate,\n date);\n\n // finish date\n newParams.dateDisplayEnd = moment.max(\n newParams.dateDisplayEnd,\n currentParams.now,\n dueDate,\n date);\n });\n\n // left spacing\n newParams.dateDisplayStart = newParams.dateDisplayStart.subtract(currentParams.dayCountForMarginLeft, 'days');\n\n // right spacing\n // RR: kept both variants for documentation purpose.\n // A: calculate the minimal width based on the width of the timeline view\n // B: calculate the minimal width based on the window width\n const width = this.$element.children().width()!; // A\n // const width = jQuery('body').width(); // B\n\n const pixelPerDay = currentParams.pixelPerDay;\n const visibleDays = Math.ceil((width / pixelPerDay) * 1.5);\n newParams.dateDisplayEnd = newParams.dateDisplayEnd.add(visibleDays, 'days');\n\n // Check if view params changed:\n\n // start date\n if (!newParams.dateDisplayStart.isSame(this._viewParameters.dateDisplayStart)) {\n changed = true;\n this._viewParameters.dateDisplayStart = newParams.dateDisplayStart;\n }\n\n // end date\n if (!newParams.dateDisplayEnd.isSame(this._viewParameters.dateDisplayEnd)) {\n changed = true;\n this._viewParameters.dateDisplayEnd = newParams.dateDisplayEnd;\n }\n\n // Calculate the visible viewport\n const firstDayInViewport = this.getFirstDayInViewport();\n const lastDayInViewport = this.getLastDayInViewport();\n const viewport:[Moment, Moment] = [firstDayInViewport, lastDayInViewport];\n this._viewParameters.visibleViewportAtCalculationTime = viewport;\n\n return changed;\n }\n\n private applyAutoZoomLevel() {\n if (this.workPackageIdOrder.length === 0) {\n return;\n }\n\n const workPackagesToCalculateWidthFrom = this.getWorkPackagesToCalculateTimelineWidthFrom();\n const daysSpan = calculateDaySpan(workPackagesToCalculateWidthFrom, this.states.workPackages, this._viewParameters);\n const timelineWidthInPx = this.$element.parent().width()! - (2 * requiredPixelMarginLeft);\n\n for (let zoomLevel of zoomLevelOrder) {\n const pixelPerDay = getPixelPerDayForZoomLevel(zoomLevel);\n const visibleDays = timelineWidthInPx / pixelPerDay;\n\n if (visibleDays >= daysSpan || zoomLevel === _.last(zoomLevelOrder)) {\n // Zoom level is enough\n const previousZoomLevel = this._viewParameters.settings.zoomLevel;\n\n // did the zoom level changed?\n if (previousZoomLevel !== zoomLevel) {\n this._viewParameters.settings.zoomLevel = zoomLevel;\n this.wpTableComponent.timeline.scrollLeft = 0;\n }\n\n this.wpTableTimeline.appliedZoomLevel = zoomLevel;\n return;\n }\n }\n }\n\n setupManageCollapsedGroupHeaderCells() {\n this.workPackageViewCollapsedGroupsService.updates$()\n .pipe(\n this.commonPipes,\n )\n .subscribe((groupsCollapseEvent:IGroupsCollapseEvent) => {\n this.manageCollapsedGroupHeaderCells(\n groupsCollapseEvent,\n this.querySpace.results.value!.elements,\n this.collapsedGroupsCellsMap,\n );\n });\n }\n\n manageCollapsedGroupHeaderCells(groupsCollapseConfig:IGroupsCollapseEvent,\n tableWorkPackages:WorkPackageResource[],\n collapsedGroupsCellsMap:IGroupCellsMap) {\n const refreshAllGroupHeaderCells = groupsCollapseConfig.allGroupsChanged;\n const collapsedGroupsChange = groupsCollapseConfig.state;\n const collapsedGroupsChangeArray = Object.keys(collapsedGroupsChange);\n let groupsToUpdate:string[] = [];\n\n if (!collapsedGroupsChangeArray.length) { return; }\n\n if (refreshAllGroupHeaderCells) {\n groupsToUpdate = collapsedGroupsChangeArray.filter(groupIdentifier => this.shouldManageCollapsedGroupHeaderCells(groupIdentifier, groupsCollapseConfig));\n } else {\n const groupIdentifier = groupsCollapseConfig.lastChangedGroup!;\n if (this.shouldManageCollapsedGroupHeaderCells(groupIdentifier, groupsCollapseConfig)) {\n groupsToUpdate = [groupIdentifier];\n }\n }\n\n groupsToUpdate.forEach(groupIdentifier => {\n const groupIsCollapsed = collapsedGroupsChange[groupIdentifier];\n\n if (groupIsCollapsed) {\n this.createCollapsedGroupHeaderCells(groupIdentifier, tableWorkPackages, collapsedGroupsCellsMap);\n } else {\n this.removeCollapsedGroupHeaderCells(groupIdentifier, collapsedGroupsCellsMap);\n }\n });\n }\n\n shouldManageCollapsedGroupHeaderCells(groupIdentifier:string, groupsCollapseConfig:IGroupsCollapseEvent) {\n const keyGroupType = groupTypeFromIdentifier(groupIdentifier);\n\n return this.workPackageViewCollapsedGroupsService.groupTypesWithHeaderCellsWhenCollapsed.includes(keyGroupType) &&\n this.workPackageViewCollapsedGroupsService.groupTypesWithHeaderCellsWhenCollapsed.includes(groupsCollapseConfig.groupedBy!);\n }\n\n createCollapsedGroupHeaderCells(groupIdentifier:string, tableWorkPackages:WorkPackageResource[], collapsedGroupsCellsMap:IGroupCellsMap) {\n this.removeCollapsedGroupHeaderCells(groupIdentifier, collapsedGroupsCellsMap);\n\n const changedGroupId = groupIdFromIdentifier(groupIdentifier);\n const changedGroupType = groupTypeFromIdentifier(groupIdentifier);\n const changedGroupTableWorkPackages = tableWorkPackages.filter(tableWorkPackage => tableWorkPackage[changedGroupType].id === changedGroupId);\n const changedGroupWpsWithHeaderCells = changedGroupTableWorkPackages.filter(tableWorkPackage => this.shouldBeShownInCollapsedGroupHeaders(tableWorkPackage) &&\n (tableWorkPackage.date || tableWorkPackage.startDate));\n const changedGroupWpsWithHeaderCellsIds = changedGroupWpsWithHeaderCells.map(workPackage => workPackage.id!);\n\n this.collapsedGroupsCellsMap[groupIdentifier!] = this.cellsRenderer.buildCellsAndRenderOnRow(changedGroupWpsWithHeaderCellsIds, `group-${groupIdentifier}-timeline`, true);\n }\n\n removeCollapsedGroupHeaderCells(groupIdentifier:string, collapsedGroupsCellsMap:IGroupCellsMap) {\n if (collapsedGroupsCellsMap[groupIdentifier!]) {\n collapsedGroupsCellsMap[groupIdentifier!].forEach((cell:WorkPackageTimelineCell) => cell.clear());\n collapsedGroupsCellsMap[groupIdentifier!] = [];\n }\n }\n\n refreshCollapsedGroupsHeaderCells(collapsedGroupsCellsMap:IGroupCellsMap, cellsRenderer:WorkPackageTimelineCellsRenderer) {\n Object.keys(collapsedGroupsCellsMap).forEach(collapsedGroupKey => {\n const collapsedGroupCells = collapsedGroupsCellsMap[collapsedGroupKey];\n\n collapsedGroupCells.forEach(cell => cellsRenderer.refreshSingleCell(cell, false, true));\n });\n }\n\n shouldBeShownInCollapsedGroupHeaders(workPackage:WorkPackageResource) {\n return this.workPackageViewCollapsedGroupsService\n .wpTypesToShowInCollapsedGroupHeaders\n .some(wpTypeFunction => wpTypeFunction(workPackage));\n }\n\n getWorkPackagesToCalculateTimelineWidthFrom() {\n // Include work packages that are show in collapsed group\n // headers into the calculation, if not they could be rendered out\n // of the timeline (ie: milestones are shown on collapsed row groups).\n return [...this.workPackageIdOrder, ...this.workPackagesWithGroupHeaderCell];\n }\n}\n","
    \n
    \n \n \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Directive, ElementRef, Injector, Input} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\n\nimport {OpContextMenuTrigger} from 'core-components/op-context-menu/handlers/op-context-menu-trigger.directive';\nimport {OPContextMenuService} from 'core-components/op-context-menu/op-context-menu.service';\nimport {OpModalService} from 'core-components/op-modals/op-modal.service';\nimport {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service';\nimport {WorkPackageViewGroupByService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service';\nimport {WorkPackageViewHierarchiesService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service';\nimport {WorkPackageViewSortByService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service';\nimport {WorkPackageTable} from 'core-components/wp-fast-table/wp-fast-table';\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {WpTableConfigurationModalComponent} from 'core-components/wp-table/configuration-modal/wp-table-configuration.modal';\nimport {ConfirmDialogService} from \"core-components/modals/confirm-dialog/confirm-dialog.service\";\nimport {QUERY_SORT_BY_ASC, QUERY_SORT_BY_DESC} from \"core-app/modules/hal/resources/query-sort-by-resource\";\n\n@Directive({\n selector: '[opColumnsContextMenu]'\n})\nexport class OpColumnsContextMenu extends OpContextMenuTrigger {\n @Input('opColumnsContextMenu-column') public column:QueryColumn;\n @Input('opColumnsContextMenu-table') public table:WorkPackageTable;\n\n public text = {\n confirmDelete: {\n text: this.I18n.t('js.work_packages.table_configuration.sorting_mode.warning'),\n title: this.I18n.t('js.modals.form_submit.title')\n },\n };\n\n\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly wpTableSortBy:WorkPackageViewSortByService,\n readonly wpTableGroupBy:WorkPackageViewGroupByService,\n readonly wpTableHierarchies:WorkPackageViewHierarchiesService,\n readonly opModalService:OpModalService,\n readonly injector:Injector,\n readonly I18n:I18nService,\n readonly confirmDialog:ConfirmDialogService) {\n\n super(elementRef, opContextMenu);\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n if (!this.table.configuration.columnMenuEnabled) {\n return;\n }\n this.buildItems();\n this.opContextMenu.show(this, evt);\n }\n\n public get locals() {\n return {\n showAnchorRight: this.column && this.column.id !== 'id',\n contextMenuId: 'column-context-menu',\n items: this.items\n };\n }\n\n /**\n * Positioning args for jquery-ui position.\n *\n * @param {Event} openerEvent\n */\n public positionArgs(evt:JQuery.TriggeredEvent) {\n let additionalPositionArgs = {\n of: this.$element.find('.generic-table--sort-header-outer'),\n };\n\n let position = super.positionArgs(evt);\n _.assign(position, additionalPositionArgs);\n\n return position;\n }\n\n protected get afterFocusOn():JQuery {\n return this.$element.find(`#${this.column.id}`);\n }\n\n private buildItems() {\n let c = this.column;\n\n this.items = [\n {\n // Sort ascending\n hidden: !this.wpTableSortBy.isSortable(c),\n linkText: this.I18n.t('js.work_packages.query.sort_descending'),\n icon: 'icon-sort-descending',\n onClick: (evt:any) => {\n if (this.wpTableSortBy.isManualSortingMode) {\n this.confirmDialog.confirm({\n text: this.text.confirmDelete,\n }).then(() => {\n this.wpTableSortBy.setAsSingleSortCriteria(c, QUERY_SORT_BY_DESC);\n return true;\n });\n return false;\n } else {\n this.wpTableSortBy.addSortCriteria(c, QUERY_SORT_BY_DESC);\n return true;\n }\n }\n },\n {\n // Sort descending\n hidden: !this.wpTableSortBy.isSortable(c),\n linkText: this.I18n.t('js.work_packages.query.sort_ascending'),\n icon: 'icon-sort-ascending',\n onClick: (evt:any) => {\n if (this.wpTableSortBy.isManualSortingMode) {\n this.confirmDialog.confirm({\n text: this.text.confirmDelete,\n }).then(() => {\n this.wpTableSortBy.setAsSingleSortCriteria(c, QUERY_SORT_BY_ASC);\n return true;\n });\n return false;\n } else {\n this.wpTableSortBy.addSortCriteria(c, QUERY_SORT_BY_ASC);\n return true;\n }\n }\n },\n {\n // Group by\n hidden: !this.wpTableGroupBy.isGroupable(c) || this.wpTableGroupBy.isCurrentlyGroupedBy(c),\n linkText: this.I18n.t('js.work_packages.query.group'),\n icon: 'icon-group-by',\n onClick: () => {\n if (this.wpTableHierarchies.isEnabled) {\n this.wpTableHierarchies.setEnabled(false);\n }\n this.wpTableGroupBy.setBy(c);\n return true;\n }\n },\n {\n // Move left\n hidden: this.wpTableColumns.isFirst(c),\n linkText: this.I18n.t('js.work_packages.query.move_column_left'),\n icon: 'icon-column-left',\n onClick: () => {\n this.wpTableColumns.shift(c, -1);\n return true;\n }\n },\n {\n // Move right\n hidden: this.wpTableColumns.isLast(c),\n linkText: this.I18n.t('js.work_packages.query.move_column_right'),\n icon: 'icon-column-right',\n onClick: () => {\n this.wpTableColumns.shift(c, 1);\n return true;\n }\n },\n {\n // Hide column\n linkText: this.I18n.t('js.work_packages.query.hide_column'),\n icon: 'icon-delete',\n onClick: () => {\n let focusColumn = this.wpTableColumns.previous(c) || this.wpTableColumns.next(c);\n this.wpTableColumns.removeColumn(c);\n\n setTimeout(() => {\n if (focusColumn) {\n jQuery(`#${focusColumn.id}`).focus();\n }\n });\n return true;\n }\n },\n {\n // Insert columns\n linkText: this.I18n.t('js.work_packages.query.insert_columns'),\n icon: 'icon-columns',\n onClick: () => {\n this.opModalService.show(\n WpTableConfigurationModalComponent,\n this.injector,\n { initialTab: 'columns' }\n );\n return true;\n }\n }\n ];\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, OnInit} from '@angular/core';\nimport {TimelineZoomLevel} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageTimelineTableController} from 'core-components/wp-table/timeline/container/wp-timeline-container.directive';\nimport * as moment from 'moment';\nimport {\n calculatePositionValueForDayCount,\n getTimeSlicesForHeader,\n timelineHeaderCSSClass,\n timelineHeaderSelector,\n TimelineViewParameters\n} from '../wp-timeline';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport Moment = moment.Moment;\n\n@Component({\n selector: timelineHeaderSelector,\n templateUrl: './wp-timeline-header.html'\n})\nexport class WorkPackageTimelineHeaderController implements OnInit {\n\n public $element:JQuery;\n\n private activeZoomLevel:TimelineZoomLevel;\n\n private innerHeader:JQuery;\n\n constructor(elementRef:ElementRef,\n readonly I18n:I18nService,\n readonly wpTimelineService:WorkPackageViewTimelineService,\n readonly workPackageTimelineTableController:WorkPackageTimelineTableController) {\n\n this.$element = jQuery(elementRef.nativeElement);\n }\n\n ngOnInit() {\n this.workPackageTimelineTableController\n .onRefreshRequested('header', (vp:TimelineViewParameters) => this.refreshView(vp));\n }\n\n refreshView(vp:TimelineViewParameters) {\n this.innerHeader = this.$element.find('.wp-table-timeline--header-inner');\n this.renderLabels(vp);\n }\n\n private renderLabels(vp:TimelineViewParameters) {\n if (this.activeZoomLevel === vp.settings.zoomLevel) {\n return;\n }\n\n this.innerHeader.empty();\n this.innerHeader.attr('data-current-zoom-level', this.wpTimelineService.zoomLevel);\n\n switch (vp.settings.zoomLevel) {\n case 'days':\n return this.renderLabelsDays(vp);\n case 'weeks':\n return this.renderLabelsWeeks(vp);\n case 'months':\n return this.renderLabelsMonths(vp);\n case 'quarters':\n return this.renderLabelsQuarters(vp);\n case 'years':\n return this.renderLabelsYears(vp);\n }\n\n this.activeZoomLevel = vp.settings.zoomLevel;\n }\n\n private renderLabelsDays(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'month', 0, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('MMM YYYY');\n cell.classList.add('wp-timeline--header-top-bold-element');\n cell.style.height = '13px';\n });\n\n this.renderTimeSlices(vp, 'week', 13, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('ww');\n cell.classList.add('-top-border');\n cell.style.height = '32px';\n });\n\n this.renderTimeSlices(vp, 'day', 23, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('D');\n cell.classList.add('-top-border');\n cell.style.height = '22px';\n });\n\n this.renderTimeSlices(vp, 'day', 33, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('dd');\n cell.classList.add('wp-timeline--header-day-element');\n });\n }\n\n private renderLabelsWeeks(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'month', 0, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('MMM YYYY');\n cell.classList.add('wp-timeline--header-top-bold-element');\n });\n\n this.renderTimeSlices(vp, 'week', 15, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('ww');\n cell.classList.add('-top-border');\n cell.style.height = '22px';\n });\n\n this.renderTimeSlices(vp, 'day', 25, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('D');\n cell.classList.add('wp-timeline--header-middle-element');\n });\n }\n\n private renderLabelsMonths(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'year', 0, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('YYYY');\n cell.classList.add('wp-timeline--header-top-bold-element');\n });\n\n this.renderTimeSlices(vp, 'month', 15, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('MMM');\n cell.classList.add('-top-border');\n cell.style.height = '30px';\n });\n\n this.renderTimeSlices(vp, 'week', 25, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('ww');\n cell.classList.add('wp-timeline--header-middle-element');\n });\n }\n\n private renderLabelsQuarters(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'year', 0, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.classList.add('wp-timeline--header-top-bold-element');\n cell.innerHTML = start.format('YYYY');\n });\n\n this.renderTimeSlices(vp, 'quarter', 15, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = this.I18n.t('js.timelines.quarter_label',\n { quarter_number: start.format('Q') });\n cell.classList.add('-top-border');\n cell.style.height = '30px';\n });\n\n this.renderTimeSlices(vp, 'month', 25, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('MMM');\n cell.classList.add('wp-timeline--header-middle-element');\n });\n }\n\n private renderLabelsYears(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'year', 0, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('YYYY');\n cell.classList.add('wp-timeline--header-top-bold-element');\n\n });\n\n this.renderTimeSlices(vp, 'quarter', 15, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = this.I18n.t('js.timelines.quarter_label',\n { quarter_number: start.format('Q') });\n cell.classList.add('-top-border');\n cell.style.height = '30px';\n });\n\n this.renderTimeSlices(vp, 'month', 25, vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.innerHTML = start.format('M');\n cell.classList.add('wp-timeline--header-middle-element');\n });\n }\n\n private renderTimeSlices(vp:TimelineViewParameters,\n unit:moment.unitOfTime.DurationConstructor,\n marginTop:number,\n startView:Moment,\n endView:Moment,\n cellCallback:(start:Moment, cell:HTMLElement) => void) {\n\n const {inViewportAndBoundaries, rest} = getTimeSlicesForHeader(vp, unit, startView, endView);\n\n for (let [start, end] of inViewportAndBoundaries) {\n const cell = this.addLabelCell();\n cell.style.top = marginTop + 'px';\n cell.style.left = calculatePositionValueForDayCount(vp, start.diff(startView, 'days'));\n cell.style.width = calculatePositionValueForDayCount(vp, end.diff(start, 'days') + 1);\n cellCallback(start, cell);\n }\n setTimeout(() => {\n for (let [start, end] of rest) {\n const cell = this.addLabelCell();\n cell.style.top = marginTop + 'px';\n cell.style.left = calculatePositionValueForDayCount(vp, start.diff(startView, 'days'));\n cell.style.width = calculatePositionValueForDayCount(vp, end.diff(start, 'days') + 1);\n cellCallback(start, cell);\n }\n }, 0);\n }\n\n private addLabelCell():HTMLElement {\n const label = document.createElement('div');\n label.className = timelineHeaderCSSClass;\n\n this.innerHeader.append(label);\n return label;\n }\n}\n","
    \n
    \n
    \n","import {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\n\nexport function workPackagePrefix(workPackageId:string) {\n return `__tl-relation-${workPackageId}`;\n}\n\nexport class TimelineRelationElement {\n\n constructor(public belongsToId:string, public relation:RelationResource) {\n }\n\n public get classNames():string[] {\n return [\n workPackagePrefix(this.relation.ids.from),\n workPackagePrefix(this.relation.ids.to)\n ];\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, Injector, OnInit} from '@angular/core';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {State} from 'reactivestates';\nimport {combineLatest} from 'rxjs';\nimport {filter, map, take} from 'rxjs/operators';\nimport {States} from '../../../states.service';\nimport {RelationsStateValue, WorkPackageRelationsService} from '../../../wp-relations/wp-relations.service';\nimport {WorkPackageTimelineCell} from '../cells/wp-timeline-cell';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {timelineElementCssClass, TimelineViewParameters} from '../wp-timeline';\nimport {TimelineRelationElement, workPackagePrefix} from './timeline-relation-element';\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nconst DEBUG_DRAW_RELATION_LINES_WITH_COLOR = false;\n\nexport const timelineGlobalElementCssClassname = 'relation-line';\n\nfunction newSegment(vp:TimelineViewParameters,\n classNames:string[],\n yPosition:number,\n top:number,\n left:number,\n width:number,\n height:number,\n color?:string):HTMLElement {\n\n const segment = document.createElement('div');\n segment.classList.add(\n timelineElementCssClass,\n timelineGlobalElementCssClassname,\n ...classNames\n );\n\n // segment.style.backgroundColor = color;\n segment.style.top = ((yPosition * 40) + top) + 'px';\n segment.style.left = left + 'px';\n segment.style.width = width + 'px';\n segment.style.height = height + 'px';\n\n if (DEBUG_DRAW_RELATION_LINES_WITH_COLOR && color !== undefined) {\n segment.style.zIndex = '9999999';\n segment.style.backgroundColor = color;\n }\n return segment;\n}\n\n@Component({\n selector: 'wp-timeline-relations',\n template: '
    '\n})\nexport class WorkPackageTableTimelineRelations extends UntilDestroyedMixin implements OnInit {\n\n @InjectField() querySpace:IsolatedQuerySpace;\n\n private container:JQuery;\n\n private workPackagesWithRelations:{ [workPackageId:string]:State } = {};\n\n constructor(public readonly injector:Injector,\n public elementRef:ElementRef,\n public states:States,\n public workPackageTimelineTableController:WorkPackageTimelineTableController,\n public wpTableTimeline:WorkPackageViewTimelineService,\n public wpRelations:WorkPackageRelationsService) {\n super();\n }\n\n ngOnInit() {\n const $element = jQuery(this.elementRef.nativeElement);\n this.container = $element.find('.wp-table-timeline--relations');\n this.workPackageTimelineTableController\n .onRefreshRequested('relations', (vp:TimelineViewParameters) => this.refreshView());\n\n this.setupRelationSubscription();\n }\n\n private refreshView() {\n this.update();\n }\n\n private get workPackageIdOrder() {\n return this.workPackageTimelineTableController.workPackageIdOrder;\n }\n\n /**\n * Refresh relations of visible rows.\n */\n private setupRelationSubscription() {\n // for all visible WorkPackage rows...\n combineLatest([\n this.querySpace.renderedWorkPackages.values$(),\n this.wpTableTimeline.live$()\n ])\n .pipe(\n filter(([_, timeline]) => timeline.visible),\n this.untilDestroyed(),\n map(([rendered, _]) => rendered)\n )\n .subscribe(list => {\n // ... make sure that the corresponding relations are loaded ...\n const wps = _.compact(list.map(row => row.workPackageId) as string[]);\n this.wpRelations.requireAll(wps);\n\n wps.forEach(wpId => {\n const relationsForWorkPackage = this.wpRelations.state(wpId);\n this.workPackagesWithRelations[wpId] = relationsForWorkPackage;\n\n // ... once they are loaded, display them.\n relationsForWorkPackage.values$()\n .pipe(\n take(1)\n )\n .subscribe(() => {\n this.renderWorkPackagesRelations([wpId]);\n });\n });\n });\n\n // When a WorkPackage changes, redraw the corresponding relations\n this.states.workPackages.observeChange()\n .pipe(\n this.untilDestroyed(),\n filter(() => this.wpTableTimeline.isVisible)\n )\n .subscribe(([workPackageId]) => {\n this.renderWorkPackagesRelations([workPackageId]);\n });\n\n }\n\n private renderWorkPackagesRelations(workPackageIds:string[]) {\n workPackageIds.forEach(workPackageId => {\n const workPackageWithRelation = this.workPackagesWithRelations[workPackageId];\n if (_.isNil(workPackageWithRelation)) {\n return;\n }\n\n this.removeRelationElementsForWorkPackage(workPackageId);\n const relations = _.values(workPackageWithRelation.value!);\n const relationsList = _.values(relations);\n relationsList.forEach(relation => {\n\n if (!(relation.type === 'precedes'\n || relation.type === 'follows')) {\n return;\n }\n\n const elem = new TimelineRelationElement(relation.ids.from, relation);\n this.renderElement(this.workPackageTimelineTableController.viewParameters, elem);\n });\n\n });\n }\n\n private update() {\n this.removeAllVisibleElements();\n this.renderElements();\n }\n\n private removeRelationElementsForWorkPackage(workPackageId:string) {\n const className = workPackagePrefix(workPackageId);\n const found = this.container.find('.' + className);\n found.remove();\n }\n\n private removeAllVisibleElements() {\n this.container.find('.' + timelineGlobalElementCssClassname).remove();\n }\n\n private renderElements() {\n const wpIdsWithRelations:string[] = _.keys(this.workPackagesWithRelations);\n this.renderWorkPackagesRelations(wpIdsWithRelations);\n\n }\n\n /**\n * Render a single relation to all shown work packages. Since work packages may occur multiple\n * times in the timeline, iterate all potential combinations and render them.\n * @param vp\n * @param e\n */\n private renderElement(vp:TimelineViewParameters, e:TimelineRelationElement) {\n const involved = e.relation.ids;\n\n const startCells = this.workPackageTimelineTableController.workPackageCells(involved.to);\n const endCells = this.workPackageTimelineTableController.workPackageCells(involved.from);\n\n // If either sources or targets are not rendered, ignore this relation\n if (startCells.length === 0 || endCells.length === 0) {\n return;\n }\n\n // Now, render all sources to all targets\n startCells.forEach((startCell) => {\n const idxFrom = this.workPackageTimelineTableController.workPackageIndex(startCell.classIdentifier);\n endCells.forEach((endCell) => {\n const idxTo = this.workPackageTimelineTableController.workPackageIndex(endCell.classIdentifier);\n this.renderRelation(vp, e, idxFrom, idxTo, startCell, endCell);\n });\n });\n }\n\n private renderRelation(vp:TimelineViewParameters,\n e:TimelineRelationElement,\n idxFrom:number,\n idxTo:number,\n startCell:WorkPackageTimelineCell,\n endCell:WorkPackageTimelineCell) {\n\n const rowFrom = this.workPackageIdOrder[idxFrom];\n const rowTo = this.workPackageIdOrder[idxTo];\n\n // If any of the targets are hidden in the table, skip\n if (!(rowFrom && rowTo) || (rowFrom.hidden || rowTo.hidden)) {\n return;\n }\n\n // Skip if relations cannot be drawn between these cells\n if (!startCell.canConnectRelations() || !endCell.canConnectRelations()) {\n return;\n }\n\n // Get X values\n // const hookLength = endCell.getPaddingLeftForIncomingRelationLines();\n const startX = startCell.getMarginLeftOfRightSide() - startCell.getPaddingRightForOutgoingRelationLines();\n const targetX = endCell.getMarginLeftOfLeftSide() + endCell.getPaddingLeftForIncomingRelationLines();\n\n // Vertical direction\n const directionY:'toUp'|'toDown' = idxFrom < idxTo ? 'toDown' : 'toUp';\n\n // Horizontal direction\n const directionX:'toLeft'|'beneath'|'toRight' =\n targetX > startX ? 'toRight' : targetX < startX ? 'toLeft' : 'beneath';\n\n // start\n if (!startCell) {\n return;\n }\n\n // Draw the first line next to the bar/milestone element\n const paddingRight = startCell.getPaddingRightForOutgoingRelationLines();\n const startLineWith = endCell.getPaddingLeftForIncomingRelationLines()\n + (paddingRight > 0 ? paddingRight : 0);\n this.container.append(newSegment(vp, e.classNames, idxFrom, 19, startX, startLineWith, 1, 'red'));\n let lastX = startX + startLineWith;\n // lastX += hookLength;\n\n // Draw vertical line between rows\n const height = Math.abs(idxTo - idxFrom);\n if (directionY === 'toDown') {\n if (directionX === 'toRight' || directionX === 'beneath') {\n this.container.append(newSegment(vp, e.classNames, idxFrom, 19, lastX, 1, height * 40, 'black'));\n } else if (directionX === 'toLeft') {\n this.container.append(newSegment(vp, e.classNames, idxFrom, 19, lastX, 1, (height * 40) - 10, 'black'));\n }\n } else if (directionY === 'toUp') {\n this.container.append(newSegment(vp, e.classNames, idxTo, 30, lastX, 1, (height * 40) - 10, 'black'));\n }\n\n // Draw end corner to the target\n if (directionX === 'toRight') {\n if (directionY === 'toDown') {\n this.container.append(newSegment(vp, e.classNames, idxTo, 19, lastX, targetX - lastX, 1, 'red'));\n } else if (directionY === 'toUp') {\n this.container.append(newSegment(vp, e.classNames, idxTo, 20, lastX, 1, 10, 'green'));\n this.container.append(newSegment(vp, e.classNames, idxTo, 20, lastX, targetX - lastX, 1, 'lightsalmon'));\n }\n } else if (directionX === 'toLeft') {\n if (directionY === 'toDown') {\n this.container.append(newSegment(vp, e.classNames, idxTo, 0, lastX, 1, 8, 'red'));\n this.container.append(newSegment(vp, e.classNames, idxTo, 8, targetX, lastX - targetX, 1, 'green'));\n this.container.append(newSegment(vp, e.classNames, idxTo, 8, targetX, 1, 11, 'blue'));\n } else if (directionY === 'toUp') {\n this.container.append(newSegment(vp, e.classNames, idxTo, 30, targetX + 1, lastX - targetX, 1, 'red'));\n this.container.append(newSegment(vp, e.classNames, idxTo, 19, targetX + 1, 1, 11, 'blue'));\n }\n }\n\n }\n}\n\n","import {TimelineViewParameters} from \"../wp-timeline\";\nexport const timelineStaticElementCssClassname = \"wp-timeline--static-element\";\n\nexport abstract class TimelineStaticElement {\n constructor() {\n }\n\n /**\n * Render the static element according to the current ViewParameters\n * @param vp Current timeline view paraemters\n * @returns {HTMLElement} The finished static element\n */\n public render(vp:TimelineViewParameters):HTMLElement {\n const elem = document.createElement(\"div\");\n elem.id = this.identifier;\n elem.classList.add(...this.classNames);\n\n return this.finishElement(elem, vp);\n }\n\n protected abstract finishElement(elem:HTMLElement, vp:TimelineViewParameters):HTMLElement;\n\n public abstract get identifier():string;\n\n public get classNames():string[] {\n return [timelineStaticElementCssClassname];\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport * as moment from 'moment';\nimport {calculatePositionValueForDayCount, TimelineViewParameters} from '../wp-timeline';\nimport {TimelineStaticElement} from './timeline-static-element';\n\n\nexport class TodayLineElement extends TimelineStaticElement {\n\n protected finishElement(elem:HTMLElement, vp:TimelineViewParameters):HTMLElement {\n const offsetToday = vp.now.diff(vp.dateDisplayStart, 'days');\n const dayProgress = moment().hour() / 24;\n elem.style.left = calculatePositionValueForDayCount(vp, offsetToday + dayProgress);\n\n return elem;\n }\n\n public get identifier():string {\n return 'wp-timeline-static-element-today-line';\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {Component, ElementRef, OnInit} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {TimelineViewParameters} from '../wp-timeline';\nimport {TimelineStaticElement, timelineStaticElementCssClassname} from './timeline-static-element';\nimport {TodayLineElement} from './wp-timeline.today-line';\n\n@Component({\n selector: 'wp-timeline-static-elements',\n template: '
    '\n})\nexport class WorkPackageTableTimelineStaticElements implements OnInit {\n\n public $element:JQuery;\n\n private container:JQuery;\n\n private elements:TimelineStaticElement[];\n\n constructor(elementRef:ElementRef,\n public states:States,\n public workPackageTimelineTableController:WorkPackageTimelineTableController) {\n\n this.$element = jQuery(elementRef.nativeElement);\n\n this.elements = [\n new TodayLineElement()\n ];\n }\n\n ngOnInit() {\n this.container = this.$element.find('.wp-table-timeline--static-elements');\n this.workPackageTimelineTableController\n .onRefreshRequested('static elements', (vp:TimelineViewParameters) => this.update(vp));\n }\n\n private update(vp:TimelineViewParameters) {\n this.removeAllVisibleElements();\n this.renderElements(vp);\n }\n\n private removeAllVisibleElements() {\n jQuery('.' + timelineStaticElementCssClassname).remove();\n }\n\n private renderElements(vp:TimelineViewParameters) {\n for (const e of this.elements) {\n this.container[0].appendChild(e.render(vp));\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {AfterViewInit, Component, ElementRef} from '@angular/core';\nimport * as moment from 'moment';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {\n calculatePositionValueForDayCount,\n getTimeSlicesForHeader,\n timelineElementCssClass,\n timelineGridElementCssClass,\n TimelineViewParameters\n} from '../wp-timeline';\nimport Moment = moment.Moment;\nimport {TimelineZoomLevel} from 'core-app/modules/hal/resources/query-resource';\n\nfunction checkForWeekendHighlight(date:Moment, cell:HTMLElement) {\n const day = date.day();\n\n // Sunday = 0\n // Monday = 6\n if (day === 0 || day === 6) {\n cell.classList.add('grid-weekend');\n }\n}\n\n@Component({\n selector: 'wp-timeline-grid',\n template: '
    '\n})\nexport class WorkPackageTableTimelineGrid implements AfterViewInit {\n\n private activeZoomLevel:TimelineZoomLevel;\n\n private gridContainer:JQuery;\n\n constructor(private elementRef:ElementRef,\n public wpTimeline:WorkPackageTimelineTableController) {\n }\n\n ngAfterViewInit() {\n const $element = jQuery(this.elementRef.nativeElement);\n this.gridContainer = $element.find('.wp-table-timeline--grid');\n this.wpTimeline.onRefreshRequested('grid', (vp:TimelineViewParameters) => this.refreshView(vp));\n }\n\n refreshView(vp:TimelineViewParameters) {\n this.renderLabels(vp);\n }\n\n private renderLabels(vp:TimelineViewParameters) {\n if (this.activeZoomLevel === vp.settings.zoomLevel) {\n return;\n }\n\n this.gridContainer.empty();\n\n switch (vp.settings.zoomLevel) {\n case 'days':\n return this.renderLabelsDays(vp);\n case 'weeks':\n return this.renderLabelsWeeks(vp);\n case 'months':\n return this.renderLabelsMonths(vp);\n case 'quarters':\n return this.renderLabelsQuarters(vp);\n case 'years':\n return this.renderLabelsYears(vp);\n }\n\n this.activeZoomLevel = vp.settings.zoomLevel;\n }\n\n private renderLabelsDays(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'day', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.style.paddingTop = '1px';\n checkForWeekendHighlight(start, cell);\n });\n\n this.renderTimeSlices(vp, 'year', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.classList.add('-grid-highlight');\n cell.style.zIndex = '2';\n });\n }\n\n private renderLabelsWeeks(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'day', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n checkForWeekendHighlight(start, cell);\n });\n\n this.renderTimeSlices(vp, 'week', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.classList.add('-grid-highlight');\n });\n\n this.renderTimeSlices(vp, 'year', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.classList.add('-grid-highlight');\n cell.style.zIndex = '2';\n });\n }\n\n private renderLabelsMonths(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'week', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n });\n\n this.renderTimeSlices(vp, 'month', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.classList.add('-grid-highlight');\n });\n\n this.renderTimeSlices(vp, 'year', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.classList.add('-grid-highlight');\n cell.style.zIndex = '2';\n });\n }\n\n private renderLabelsQuarters(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'month', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n });\n\n this.renderTimeSlices(vp, 'quarter', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.classList.add('-grid-highlight');\n });\n\n this.renderTimeSlices(vp, 'year', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.classList.add('-grid-highlight');\n cell.style.zIndex = '2';\n });\n }\n\n private renderLabelsYears(vp:TimelineViewParameters) {\n this.renderTimeSlices(vp, 'month', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n });\n\n this.renderTimeSlices(vp, 'year', vp.dateDisplayStart, vp.dateDisplayEnd, (start, cell) => {\n cell.classList.add('-grid-highlight');\n });\n }\n\n renderTimeSlices(vp:TimelineViewParameters,\n unit:moment.unitOfTime.DurationConstructor,\n startView:Moment,\n endView:Moment,\n cellCallback:(start:Moment, cell:HTMLElement) => void) {\n\n const {inViewportAndBoundaries, rest} = getTimeSlicesForHeader(vp, unit, startView, endView);\n\n for (let [start, end] of inViewportAndBoundaries) {\n const cell = document.createElement('div');\n cell.classList.add(timelineElementCssClass, timelineGridElementCssClass);\n cell.style.left = calculatePositionValueForDayCount(vp, start.diff(startView, 'days'));\n cell.style.width = calculatePositionValueForDayCount(vp, end.diff(start, 'days') + 1);\n this.gridContainer[0].appendChild(cell);\n cellCallback(start, cell);\n }\n setTimeout(() => {\n for (let [start, end] of rest) {\n const cell = document.createElement('div');\n cell.classList.add(timelineElementCssClass, timelineGridElementCssClass);\n cell.style.left = calculatePositionValueForDayCount(vp, start.diff(startView, 'days'));\n cell.style.width = calculatePositionValueForDayCount(vp, end.diff(start, 'days') + 1);\n this.gridContainer[0].appendChild(cell);\n cellCallback(start, cell);\n }\n }, 0);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageWatchersTabComponent} from './watchers-tab.component';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\n\n@Component({\n templateUrl: './wp-watcher-entry.html',\n selector: 'wp-watcher-entry',\n})\nexport class WorkPackageWatcherEntryComponent implements OnInit {\n @Input('watcher') public watcher:UserResource;\n public deleting = false;\n public text:{ remove:string };\n\n constructor(readonly I18n:I18nService,\n readonly panelCtrl:WorkPackageWatchersTabComponent) {\n }\n\n ngOnInit() {\n this.text = {\n remove: this.I18n.t('js.label_remove_watcher', { name: this.watcher.name })\n };\n }\n\n public remove() {\n this.deleting = true;\n this.panelCtrl.removeWatcher(this.watcher);\n }\n}\n","
    \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, Directive, ElementRef, Injector, Input} from '@angular/core';\nimport {takeUntil} from 'rxjs/operators';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {States} from '../../states.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {QueryColumn} from \"core-components/wp-query/query-column\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {WorkPackageViewSumService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service\";\nimport {combineLatest} from \"rxjs\";\nimport {GroupSumsBuilder} from \"core-components/wp-fast-table/builders/modes/grouped/group-sums-builder\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Directive({\n selector: '[wpTableSumsRow]',\n host: {\n '[class.-hidden]': 'isHidden'\n },\n})\nexport class WorkPackageTableSumsRowController implements AfterViewInit {\n\n @Input('wpTableSumsRow-table') workPackageTable:WorkPackageTable;\n\n public isHidden = true;\n\n private text:{ sum:string };\n\n private element:HTMLTableRowElement;\n\n private groupSumsBuilder:GroupSumsBuilder;\n\n constructor(readonly injector:Injector,\n readonly elementRef:ElementRef,\n readonly querySpace:IsolatedQuerySpace,\n readonly states:States,\n readonly schemaCache:SchemaCacheService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly wpTableSums:WorkPackageViewSumService,\n readonly I18n:I18nService) {\n\n this.text = {\n sum: I18n.t('js.label_total_sum')\n };\n }\n\n ngAfterViewInit():void {\n this.element = this.elementRef.nativeElement;\n\n combineLatest([\n this.wpTableColumns.live$(),\n this.wpTableSums.live$(),\n this.querySpace.results.values$(),\n ])\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe(([columns, sum, resource]) => {\n this.isHidden = !sum;\n if (sum && resource.sumsSchema) {\n this.schemaCache\n .ensureLoaded(resource.sumsSchema.$href!)\n .then((schema:SchemaResource) => {\n this.refresh(columns, resource, schema);\n });\n } else {\n this.clear();\n }\n });\n }\n\n private clear() {\n this.element.innerHTML = '';\n }\n\n private refresh(columns:QueryColumn[], resource:WorkPackageCollectionResource, schema:SchemaResource) {\n this.clear();\n this.render(columns, resource, schema);\n }\n\n private render(columns:QueryColumn[], resource:WorkPackageCollectionResource, schema:SchemaResource) {\n this.groupSumsBuilder = new GroupSumsBuilder(this.injector, this.workPackageTable);\n this.groupSumsBuilder.text = this.text;\n this.groupSumsBuilder.renderColumns(resource.totalSums!, this.element);\n }\n}\n","\n
    \n
    \n

    \n
    \n
    \n\n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Inject, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {OpUnlinkTableAction} from 'core-components/wp-table/table-actions/actions/unlink-table-action';\nimport {OpTableActionFactory} from 'core-components/wp-table/table-actions/table-action';\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WorkPackageRelationQueryBase} from \"core-components/wp-relations/embedded/wp-relation-query.base\";\nimport {WpRelationInlineCreateService} from \"core-components/wp-relations/embedded/relations/wp-relation-inline-create.service\";\nimport {WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {filter} from \"rxjs/operators\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {GroupDescriptor} from \"core-components/work-packages/wp-single-view/wp-single-view.component\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Component({\n selector: 'wp-relation-query',\n templateUrl: '../wp-relation-query.html',\n providers: [\n { provide: WorkPackageInlineCreateService, useClass: WpRelationInlineCreateService }\n ]\n})\nexport class WorkPackageRelationQueryComponent extends WorkPackageRelationQueryBase implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n\n @Input() public query:QueryResource;\n @Input() public group:GroupDescriptor;\n\n public tableActions:OpTableActionFactory[] = [\n OpUnlinkTableAction.factoryFor(\n 'remove-relation-action',\n this.I18n.t('js.relation_buttons.remove'),\n (relatedTo:WorkPackageResource) => {\n this.embeddedTable.loadingIndicator = this.wpRelations.require(relatedTo.id!)\n .then(() => this.wpInlineCreate.remove(this.workPackage, relatedTo))\n .then(() => this.refreshTable())\n .catch((error) => this.notificationService.handleRawError(error, this.workPackage));\n },\n (child:WorkPackageResource) => !!child.changeParent\n )\n ];\n\n constructor(protected readonly PathHelper:PathHelperService,\n @Inject(WorkPackageInlineCreateService) protected readonly wpInlineCreate:WpRelationInlineCreateService,\n protected readonly wpRelations:WorkPackageRelationsService,\n protected readonly halEvents:HalEventsService,\n protected readonly queryUrlParamsHelper:UrlParamsHelperService,\n protected readonly notificationService:WorkPackageNotificationService,\n protected readonly I18n:I18nService) {\n super(queryUrlParamsHelper);\n }\n\n ngOnInit() {\n let relationType = this.getRelationTypeFromQuery();\n\n // Set reference target and reference class\n this.wpInlineCreate.referenceTarget = this.workPackage;\n this.wpInlineCreate.relationType = relationType;\n\n // Set up the query props\n this.queryProps = this.buildQueryProps();\n\n // Wire the successful saving of a new addition to refreshing the embedded table\n this.wpInlineCreate.newInlineWorkPackageCreated\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((toId:string) => this.addRelation(toId));\n\n // When relations have changed, refresh this table\n this.wpRelations.observe(this.workPackage.id!)\n .pipe(\n filter(val => !_.isEmpty(val)),\n this.untilDestroyed()\n )\n .subscribe(() => this.refreshTable());\n }\n\n private addRelation(toId:string) {\n this.wpInlineCreate\n .add(this.workPackage, toId)\n .then(() => {\n this.halEvents.push(this.workPackage, {\n eventType: 'association',\n relatedWorkPackage: toId,\n relationType: this.getRelationTypeFromQuery()\n });\n })\n .catch(error => this.notificationService.handleRawError(error, this.workPackage));\n }\n\n private getRelationTypeFromQuery() {\n return this.group.relationType!;\n }\n}\n","import {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {Component, OnInit, Injector} from '@angular/core';\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {WpTableConfigurationModalComponent} from \"core-components/wp-table/configuration-modal/wp-table-configuration.modal\";\n\n@Component({\n templateUrl: './config-menu.template.html',\n selector: 'wp-table-config-menu',\n})\nexport class WorkPackagesTableConfigMenu implements OnInit {\n public text:any;\n\n constructor(readonly I18n:I18nService,\n readonly injector:Injector,\n readonly opModalService:OpModalService,\n readonly opContextMenu:OPContextMenuService) {\n }\n\n ngOnInit():void {\n this.text = {\n configureTable: I18n.t('js.toolbar.settings.configure_view')\n };\n }\n\n public openTableConfigurationModal() {\n this.opContextMenu.close();\n this.opModalService.show(WpTableConfigurationModalComponent, this.injector);\n }\n}\n","\n \n\n","import {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport { TimeEntryResource } from 'core-app/modules/hal/resources/time-entry-resource';\n\nexport class TimeEntryChangeset extends ResourceChangeset {\n\n public setValue(key:string, val:any) {\n super.setValue(key, val);\n\n // Update the form for fields that may alter the form itself\n if (key === 'workPackage') {\n this.updateForm();\n }\n }\n\n protected buildPayloadFromChanges() {\n let payload = super.buildPayloadFromChanges();\n\n // we ignore the project and instead rely completely on the work package.\n delete payload['_links']['project'];\n\n return payload;\n }\n}\n","
    \n\n \n \n \n \n\n \n {{headerColumn.name}}\n {{headerColumn.name}}\n\n \n \n\n \n \n \n {{columnName}}\n \n \n \n\n \n \n\n \n\n \n {{headerColumn.name}}\n\n {{headerColumn.name}}\n\n \n \n\n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, ChangeDetectorRef, Component, ElementRef, Input} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {RelationQueryColumn, TypeRelationQueryColumn} from 'core-components/wp-query/query-column';\nimport {WorkPackageTable} from 'core-components/wp-fast-table/wp-fast-table';\nimport {QUERY_SORT_BY_ASC, QUERY_SORT_BY_DESC} from 'core-app/modules/hal/resources/query-sort-by-resource';\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {combineLatest} from \"rxjs\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n\n@Component({\n selector: 'sortHeader',\n templateUrl: './sort-header.directive.html'\n})\nexport class SortHeaderDirective extends UntilDestroyedMixin implements AfterViewInit {\n\n @Input() headerColumn:any;\n\n @Input() locale:string;\n\n @Input() table:WorkPackageTable;\n\n sortable:boolean;\n\n directionClass:string;\n\n public text = {\n toggleHierarchy: this.I18n.t('js.work_packages.hierarchy.show'),\n openMenu: this.I18n.t('js.label_open_menu'),\n sortColumn: 'Sorting column' // TODO\n };\n\n isHierarchyColumn:boolean;\n\n columnType:'hierarchy'|'relation'|'sort';\n\n columnName:string;\n\n hierarchyIcon:string;\n\n isHierarchyDisabled:boolean;\n\n private element:JQuery;\n\n private currentSortDirection:any;\n\n constructor(private wpTableHierarchies:WorkPackageViewHierarchiesService,\n private wpTableSortBy:WorkPackageViewSortByService,\n private wpTableGroupBy:WorkPackageViewGroupByService,\n private wpTableRelationColumns:WorkPackageViewRelationColumnsService,\n private elementRef:ElementRef,\n private cdRef:ChangeDetectorRef,\n private I18n:I18nService) {\n super();\n }\n\n ngAfterViewInit() {\n setTimeout(() => this.initialize());\n }\n\n private initialize():void {\n this.element = jQuery(this.elementRef.nativeElement);\n\n combineLatest([\n this.wpTableSortBy.onReadyWithAvailable(),\n this.wpTableSortBy.live$()\n ])\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n let latestSortElement = this.wpTableSortBy.current[0];\n\n if (!latestSortElement || this.headerColumn.$href !== latestSortElement.column.$href) {\n this.currentSortDirection = null;\n } else {\n this.currentSortDirection = latestSortElement.direction;\n }\n this.setActiveColumnClass();\n\n this.sortable = this.wpTableSortBy.isSortable(this.headerColumn);\n\n this.directionClass = this.getDirectionClass();\n\n this.cdRef.detectChanges();\n });\n\n // Place the hierarchy icon left to the subject column\n this.isHierarchyColumn = this.headerColumn.id === 'subject';\n\n if (this.headerColumn.id === 'sortHandle') {\n this.columnType = 'sort';\n }\n if (this.isHierarchyColumn) {\n this.columnType = 'hierarchy';\n } else if (this.wpTableRelationColumns.relationColumnType(this.headerColumn) === 'toType') {\n this.columnType = 'relation';\n this.columnName = (this.headerColumn as TypeRelationQueryColumn).type.name;\n } else if (this.wpTableRelationColumns.relationColumnType(this.headerColumn) === 'ofType') {\n this.columnType = 'relation';\n this.columnName = I18n.t('js.relation_labels.' + (this.headerColumn as RelationQueryColumn).relationType);\n }\n\n\n if (this.isHierarchyColumn) {\n this.hierarchyIcon = 'icon-hierarchy';\n this.isHierarchyDisabled = this.wpTableGroupBy.isEnabled;\n\n // Disable hierarchy mode when group by is active\n this.wpTableGroupBy\n .live$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.isHierarchyDisabled = this.wpTableGroupBy.isEnabled;\n this.cdRef.detectChanges();\n });\n\n // Update hierarchy icon when updated elsewhere\n this.wpTableHierarchies\n .live$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.setHierarchyIcon();\n this.cdRef.detectChanges();\n });\n\n // Set initial icon\n this.setHierarchyIcon();\n }\n\n this.cdRef.detectChanges();\n }\n\n public get displayDropdownIcon() {\n return this.table && this.table.configuration.columnMenuEnabled;\n }\n\n public get displayHierarchyIcon() {\n return this.table && this.table.configuration.hierarchyToggleEnabled;\n }\n\n toggleHierarchy(evt:JQuery.TriggeredEvent) {\n if (this.wpTableHierarchies.toggleState()) {\n this.wpTableGroupBy.disable();\n }\n\n this.setHierarchyIcon();\n\n evt.stopPropagation();\n return false;\n }\n\n setHierarchyIcon() {\n if (this.wpTableHierarchies.isEnabled) {\n this.text.toggleHierarchy = I18n.t('js.work_packages.hierarchy.hide');\n this.hierarchyIcon = 'icon-hierarchy';\n } else {\n this.text.toggleHierarchy = I18n.t('js.work_packages.hierarchy.show');\n this.hierarchyIcon = 'icon-no-hierarchy';\n }\n }\n\n private getDirectionClass():string {\n if (!this.currentSortDirection) {\n return '';\n }\n\n switch (this.currentSortDirection.$href) {\n case QUERY_SORT_BY_ASC:\n return 'asc';\n case QUERY_SORT_BY_DESC:\n return 'desc';\n default:\n return '';\n }\n }\n\n setActiveColumnClass() {\n this.element.toggleClass('active-column', !!this.currentSortDirection);\n }\n\n}\n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpenprojectCommonModule} from 'core-app/modules/common/openproject-common.module';\nimport {WorkPackageFormAttributeGroupComponent} from 'core-components/wp-form-group/wp-attribute-group.component';\nimport {OpenprojectFieldsModule} from 'core-app/modules/fields/openproject-fields.module';\nimport {Injector, NgModule} from '@angular/core';\nimport {\n GroupDescriptor,\n WorkPackageSingleViewComponent\n} from 'core-components/work-packages/wp-single-view/wp-single-view.component';\nimport {HookService} from 'core-app/modules/plugins/hook-service';\nimport {WorkPackageEmbeddedTableComponent} from 'core-components/wp-table/embedded/wp-embedded-table.component';\nimport {WorkPackageEmbeddedTableEntryComponent} from 'core-components/wp-table/embedded/wp-embedded-table-entry.component';\nimport {WorkPackageTablePaginationComponent} from 'core-components/wp-table/table-pagination/wp-table-pagination.component';\nimport {WpResizerDirective} from 'core-components/resizer/wp-resizer.component';\nimport {WorkPackageTimelineTableController} from 'core-components/wp-table/timeline/container/wp-timeline-container.directive';\nimport {WorkPackageInlineCreateComponent} from 'core-components/wp-inline-create/wp-inline-create.component';\nimport {OpTypesContextMenuDirective} from 'core-components/op-context-menu/handlers/op-types-context-menu.directive';\nimport {OpColumnsContextMenu} from 'core-components/op-context-menu/handlers/op-columns-context-menu.directive';\nimport {OpSettingsMenuDirective} from 'core-components/op-context-menu/handlers/op-settings-dropdown-menu.directive';\nimport {WorkPackageStatusDropdownDirective} from 'core-components/op-context-menu/handlers/wp-status-dropdown-menu.directive';\nimport {WorkPackageCreateSettingsMenuDirective} from 'core-components/op-context-menu/handlers/wp-create-settings-menu.directive';\nimport {WorkPackageSingleContextMenuDirective} from 'core-components/op-context-menu/wp-context-menu/wp-single-context-menu';\nimport {WorkPackageQuerySelectDropdownComponent} from 'core-components/wp-query-select/wp-query-select-dropdown.component';\nimport {WorkPackageTimelineHeaderController} from 'core-components/wp-table/timeline/header/wp-timeline-header.directive';\nimport {WorkPackageTableTimelineRelations} from 'core-components/wp-table/timeline/global-elements/wp-timeline-relations.directive';\nimport {WorkPackageTableTimelineStaticElements} from 'core-components/wp-table/timeline/global-elements/wp-timeline-static-elements.directive';\nimport {WorkPackageTableTimelineGrid} from 'core-components/wp-table/timeline/grid/wp-timeline-grid.directive';\nimport {WorkPackageTimelineButtonComponent} from 'core-components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.component';\nimport {WorkPackageOverviewTabComponent} from 'core-components/wp-single-view-tabs/overview-tab/overview-tab.component';\nimport {WorkPackageStatusButtonComponent} from 'core-components/wp-buttons/wp-status-button/wp-status-button.component';\nimport {WorkPackageReplacementLabelComponent} from 'core-components/wp-edit/wp-edit-field/wp-replacement-label.component';\nimport {NewestActivityOnOverviewComponent} from 'core-components/wp-single-view-tabs/activity-panel/activity-on-overview.component';\nimport {UserLinkComponent} from 'core-components/user/user-link/user-link.component';\nimport {WorkPackageCommentComponent} from 'core-components/work-packages/work-package-comment/work-package-comment.component';\nimport {WorkPackageCommentFieldComponent} from 'core-components/work-packages/work-package-comment/wp-comment-field.component';\nimport {ActivityEntryComponent} from 'core-components/wp-activity/activity-entry.component';\nimport {UserActivityComponent} from 'core-components/wp-activity/user/user-activity.component';\nimport {RevisionActivityComponent} from 'core-components/wp-activity/revision/revision-activity.component';\nimport {ActivityLinkComponent} from 'core-components/wp-activity/activity-link.component';\nimport {WorkPackageActivityTabComponent} from 'core-components/wp-single-view-tabs/activity-panel/activity-tab.component';\nimport {OpenprojectAttachmentsModule} from 'core-app/modules/attachments/openproject-attachments.module';\nimport {WpCustomActionComponent} from 'core-components/wp-custom-actions/wp-custom-actions/wp-custom-action.component';\nimport {WpCustomActionsComponent} from 'core-components/wp-custom-actions/wp-custom-actions.component';\nimport {WorkPackageRelationsCountComponent} from 'core-components/work-packages/wp-relations-count/wp-relations-count.component';\nimport {WorkPackageWatchersCountComponent} from 'core-components/work-packages/wp-relations-count/wp-watchers-count.component';\nimport {WorkPackageBreadcrumbComponent} from 'core-components/work-packages/wp-breadcrumb/wp-breadcrumb.component';\nimport {WorkPackageSplitViewToolbarComponent} from 'core-components/wp-details/wp-details-toolbar.component';\nimport {WorkPackageWatcherButtonComponent} from 'core-components/work-packages/wp-watcher-button/wp-watcher-button.component';\nimport {WorkPackageSubjectComponent} from 'core-components/work-packages/wp-subject/wp-subject.component';\nimport {WorkPackageRelationsTabComponent} from 'core-components/wp-single-view-tabs/relations-tab/relations-tab.component';\nimport {WorkPackageRelationsComponent} from 'core-components/wp-relations/wp-relations.component';\nimport {WorkPackageRelationsGroupComponent} from 'core-components/wp-relations/wp-relations-group/wp-relations-group.component';\nimport {WorkPackageRelationRowComponent} from 'core-components/wp-relations/wp-relation-row/wp-relation-row.component';\nimport {WorkPackageRelationsCreateComponent} from 'core-components/wp-relations/wp-relations-create/wp-relations-create.component';\nimport {WorkPackageRelationsHierarchyComponent} from 'core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.directive';\nimport {WorkPackageCreateButtonComponent} from 'core-components/wp-buttons/wp-create-button/wp-create-button.component';\nimport {WorkPackageBreadcrumbParentComponent} from 'core-components/work-packages/wp-breadcrumb/wp-breadcrumb-parent.component';\nimport {WorkPackageFilterButtonComponent} from 'core-components/wp-buttons/wp-filter-button/wp-filter-button.component';\nimport {WorkPackageFilterContainerComponent} from 'core-components/filters/filter-container/filter-container.directive';\nimport {QueryFiltersComponent} from 'core-components/filters/query-filters/query-filters.component';\nimport {QueryFilterComponent} from 'core-components/filters/query-filter/query-filter.component';\nimport {FilterBooleanValueComponent} from 'core-components/filters/filter-boolean-value/filter-boolean-value.component';\nimport {FilterDateValueComponent} from 'core-components/filters/filter-date-value/filter-date-value.component';\nimport {FilterDatesValueComponent} from 'core-components/filters/filter-dates-value/filter-dates-value.component';\nimport {FilterDateTimeValueComponent} from 'core-components/filters/filter-date-time-value/filter-date-time-value.component';\nimport {FilterDateTimesValueComponent} from 'core-components/filters/filter-date-times-value/filter-date-times-value.component';\nimport {FilterIntegerValueComponent} from 'core-components/filters/filter-integer-value/filter-integer-value.component';\nimport {FilterStringValueComponent} from 'core-components/filters/filter-string-value/filter-string-value.component';\nimport {FilterToggledMultiselectValueComponent} from 'core-components/filters/filter-toggled-multiselect-value/filter-toggled-multiselect-value.component';\nimport {FilterSearchableMultiselectValueComponent} from 'core-components/filters/filter-searchable-multiselect-value/filter-searchable-multiselect-value.component';\nimport {WorkPackageDetailsViewButtonComponent} from 'core-components/wp-buttons/wp-details-view-button/wp-details-view-button.component';\nimport {WorkPackageFoldToggleButtonComponent} from 'core-components/wp-buttons/wp-fold-toggle-button/wp-fold-toggle-button.component';\nimport {WpTableConfigurationModalComponent} from 'core-components/wp-table/configuration-modal/wp-table-configuration.modal';\nimport {WpTableConfigurationColumnsTab} from 'core-components/wp-table/configuration-modal/tabs/columns-tab.component';\nimport {WpTableConfigurationDisplaySettingsTab} from 'core-components/wp-table/configuration-modal/tabs/display-settings-tab.component';\nimport {WpTableConfigurationFiltersTab} from 'core-components/wp-table/configuration-modal/tabs/filters-tab.component';\nimport {WpTableConfigurationSortByTab} from 'core-components/wp-table/configuration-modal/tabs/sort-by-tab.component';\nimport {WpTableConfigurationTimelinesTab} from 'core-components/wp-table/configuration-modal/tabs/timelines-tab.component';\nimport {WpTableConfigurationHighlightingTab} from 'core-components/wp-table/configuration-modal/tabs/highlighting-tab.component';\nimport {WpTableConfigurationRelationSelectorComponent} from \"core-components/wp-table/configuration-modal/wp-table-configuration-relation-selector\";\nimport {WorkPackageWatchersTabComponent} from 'core-components/wp-single-view-tabs/watchers-tab/watchers-tab.component';\nimport {WorkPackageWatcherEntryComponent} from 'core-components/wp-single-view-tabs/watchers-tab/wp-watcher-entry.component';\nimport {WorkPackageCopyFullViewComponent} from 'core-components/wp-copy/wp-copy-full-view.component';\nimport {WorkPackageCopySplitViewComponent} from 'core-components/wp-copy/wp-copy-split-view.component';\nimport {WorkPackageTypeStatusComponent} from 'core-components/work-packages/wp-type-status/wp-type-status.component';\nimport {WorkPackageNewSplitViewComponent} from 'core-components/wp-new/wp-new-split-view.component';\nimport {WorkPackageNewFullViewComponent} from 'core-components/wp-new/wp-new-full-view.component';\nimport {WpTableExportModal} from 'core-components/modals/export-modal/wp-table-export.modal';\nimport {QuerySharingModal} from 'core-components/modals/share-modal/query-sharing.modal';\nimport {SaveQueryModal} from 'core-components/modals/save-modal/save-query.modal';\nimport {WpDestroyModal} from 'core-components/modals/wp-destroy-modal/wp-destroy.modal';\nimport {QuerySharingForm} from 'core-components/modals/share-modal/query-sharing-form.component';\nimport {EmbeddedTablesMacroComponent} from 'core-components/wp-table/embedded/embedded-tables-macro.component';\nimport {WpButtonMacroModal} from 'core-components/modals/editor/macro-wp-button-modal/wp-button-macro.modal';\nimport {OpenprojectEditorModule} from 'core-app/modules/editor/openproject-editor.module';\nimport {WorkPackageTableSumsRowController} from 'core-components/wp-table/wp-table-sums-row/wp-table-sums-row.directive';\nimport {ExternalQueryConfigurationComponent} from 'core-components/wp-table/external-configuration/external-query-configuration.component';\nimport {ExternalQueryConfigurationService} from 'core-components/wp-table/external-configuration/external-query-configuration.service';\nimport {ExternalRelationQueryConfigurationComponent} from \"core-components/wp-table/external-configuration/external-relation-query-configuration.component\";\nimport {ExternalRelationQueryConfigurationService} from \"core-components/wp-table/external-configuration/external-relation-query-configuration.service\";\nimport {WorkPackageStaticQueriesService} from 'core-components/wp-query-select/wp-static-queries.service';\nimport {WorkPackagesListInvalidQueryService} from 'core-components/wp-list/wp-list-invalid-query.service';\nimport {SchemaCacheService} from 'core-components/schemas/schema-cache.service';\nimport {WorkPackageWatchersService} from 'core-components/wp-single-view-tabs/watchers-tab/wp-watchers.service';\nimport {WorkPackagesActivityService} from 'core-components/wp-single-view-tabs/activity-panel/wp-activity.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageChildrenQueryComponent} from \"core-components/wp-relations/embedded/children/wp-children-query.component\";\nimport {WpRelationInlineAddExistingComponent} from \"core-components/wp-relations/embedded/inline/add-existing/wp-relation-inline-add-existing.component\";\nimport {WorkPackageRelationQueryComponent} from \"core-components/wp-relations/embedded/relations/wp-relation-query.component\";\nimport {WorkPackagesBaseComponent} from \"core-app/modules/work_packages/routing/wp-base/wp--base.component\";\nimport {WorkPackageSplitViewComponent} from \"core-app/modules/work_packages/routing/wp-split-view/wp-split-view.component\";\nimport {WorkPackagesFullViewComponent} from \"core-app/modules/work_packages/routing/wp-full-view/wp-full-view.component\";\nimport {AttachmentsUploadComponent} from 'core-app/modules/attachments/attachments-upload/attachments-upload.component';\nimport {AttachmentListComponent} from 'core-app/modules/attachments/attachment-list/attachment-list.component';\nimport {WorkPackageFilterByTextInputComponent} from \"core-components/filters/quick-filter-by-text-input/quick-filter-by-text-input.component\";\nimport {QueryFiltersService} from \"core-components/wp-query/query-filters.service\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageIsolatedQuerySpaceDirective} from \"core-app/modules/work_packages/query-space/wp-isolated-query-space.directive\";\nimport {WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {OpenprojectBcfModule} from \"core-app/modules/bim/bcf/openproject-bcf.module\";\nimport {WorkPackageRelationsAutocomplete} from \"core-components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.component\";\nimport {CustomDateActionAdminComponent} from 'core-components/wp-custom-actions/date-action/custom-date-action-admin.component';\nimport {WorkPackagesTableConfigMenu} from \"core-components/wp-table/config-menu/config-menu.component\";\nimport {WorkPackageIsolatedGraphQuerySpaceDirective} from \"core-app/modules/work_packages/query-space/wp-isolated-graph-query-space.directive\";\nimport {WorkPackageViewToggleButton} from \"core-components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component\";\nimport {WorkPackagesGridComponent} from \"core-components/wp-grid/wp-grid.component\";\nimport {WorkPackageViewDropdownMenuDirective} from \"core-components/op-context-menu/handlers/wp-view-dropdown-menu.directive\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {OpenprojectProjectsModule} from \"core-app/modules/projects/openproject-projects.module\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {WorkPackageEditActionsBarComponent} from \"core-app/modules/common/edit-actions-bar/wp-edit-actions-bar.component\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {WorkPackageSingleCardComponent} from \"core-components/wp-card-view/wp-single-card/wp-single-card.component\";\nimport {TimeEntryChangeset} from 'core-app/components/time-entries/time-entry-changeset';\nimport {WorkPackageListViewComponent} from \"core-app/modules/work_packages/routing/wp-list-view/wp-list-view.component\";\nimport {PartitionedQuerySpacePageComponent} from \"core-app/modules/work_packages/routing/partitioned-query-space-page/partitioned-query-space-page.component\";\nimport {WorkPackageViewPageComponent} from \"core-app/modules/work_packages/routing/wp-view-page/wp-view-page.component\";\nimport {WorkPackageSettingsButtonComponent} from \"core-components/wp-buttons/wp-settings-button/wp-settings-button.component\";\nimport {BackButtonComponent} from \"core-app/modules/common/back-routing/back-button.component\";\nimport {DatePickerModal} from \"core-components/datepicker/datepicker.modal\";\nimport {WorkPackagesTableComponent} from \"core-components/wp-table/wp-table.component\";\nimport {WorkPackageGroupToggleDropdownMenuDirective} from \"core-components/op-context-menu/handlers/wp-group-toggle-dropdown-menu.directive\";\n\n@NgModule({\n imports: [\n // Commons\n OpenprojectCommonModule,\n // Display + Edit field functionality\n OpenprojectFieldsModule,\n // CKEditor\n OpenprojectEditorModule,\n\n OpenprojectAttachmentsModule,\n\n OpenprojectBcfModule,\n\n OpenprojectProjectsModule,\n ],\n providers: [\n // Notification service\n WorkPackageNotificationService,\n\n // External query configuration\n ExternalQueryConfigurationService,\n ExternalRelationQueryConfigurationService,\n\n // Global work package states / services\n SchemaCacheService,\n\n // Global query/table state services\n // For any service that depends on the isolated query space,\n // they should be provided in wp-isolated-query-space.directive instead\n QueryFiltersService,\n WorkPackageStaticQueriesService,\n WorkPackagesListInvalidQueryService,\n\n // Provide a separate service for creation events of WP Inline create\n // This can be hierarchically injected to provide isolated events on an embedded table\n WorkPackageRelationsService,\n\n WorkPackagesActivityService,\n WorkPackageRelationsService,\n WorkPackageWatchersService,\n\n HalEventsService,\n ],\n declarations: [\n // Routing\n WorkPackagesBaseComponent,\n PartitionedQuerySpacePageComponent,\n WorkPackageViewPageComponent,\n\n // WP list side\n WorkPackageListViewComponent,\n WorkPackageSettingsButtonComponent,\n\n // Query injector isolation\n WorkPackageIsolatedQuerySpaceDirective,\n WorkPackageIsolatedGraphQuerySpaceDirective,\n\n // WP New\n WorkPackageNewFullViewComponent,\n WorkPackageNewSplitViewComponent,\n WorkPackageTypeStatusComponent,\n WorkPackageEditActionsBarComponent,\n\n // WP Copy\n WorkPackageCopyFullViewComponent,\n WorkPackageCopySplitViewComponent,\n\n // Embedded table\n WorkPackageEmbeddedTableComponent,\n WorkPackageEmbeddedTableEntryComponent,\n\n // External query configuration\n ExternalQueryConfigurationComponent,\n ExternalRelationQueryConfigurationComponent,\n\n // Inline create\n WorkPackageInlineCreateComponent,\n WpRelationInlineAddExistingComponent,\n\n WorkPackagesGridComponent,\n\n WorkPackagesTableComponent,\n WorkPackagesTableConfigMenu,\n WorkPackageTablePaginationComponent,\n\n WpResizerDirective,\n\n WorkPackageTableSumsRowController,\n\n // Fold/Unfold button on wp list\n WorkPackageFoldToggleButtonComponent,\n\n // Filters\n QueryFiltersComponent,\n QueryFilterComponent,\n FilterBooleanValueComponent,\n FilterDateValueComponent,\n FilterDatesValueComponent,\n FilterDateTimeValueComponent,\n FilterDateTimesValueComponent,\n FilterIntegerValueComponent,\n FilterStringValueComponent,\n FilterToggledMultiselectValueComponent,\n FilterSearchableMultiselectValueComponent,\n\n WorkPackageFilterContainerComponent,\n WorkPackageFilterButtonComponent,\n\n // Context menus\n OpTypesContextMenuDirective,\n OpColumnsContextMenu,\n OpSettingsMenuDirective,\n WorkPackageStatusDropdownDirective,\n WorkPackageCreateSettingsMenuDirective,\n WorkPackageSingleContextMenuDirective,\n WorkPackageQuerySelectDropdownComponent,\n WorkPackageViewDropdownMenuDirective,\n WorkPackageGroupToggleDropdownMenuDirective,\n\n // Timeline\n WorkPackageTimelineButtonComponent,\n WorkPackageTimelineHeaderController,\n WorkPackageTableTimelineRelations,\n WorkPackageTableTimelineStaticElements,\n WorkPackageTableTimelineGrid,\n WorkPackageTimelineTableController,\n\n WorkPackageCreateButtonComponent,\n WorkPackageFilterByTextInputComponent,\n\n // Single view\n WorkPackageOverviewTabComponent,\n WorkPackageSingleViewComponent,\n WorkPackageStatusButtonComponent,\n WorkPackageReplacementLabelComponent,\n UserLinkComponent,\n WorkPackageChildrenQueryComponent,\n WorkPackageRelationQueryComponent,\n WorkPackageFormAttributeGroupComponent,\n BackButtonComponent,\n\n // Activity Tab\n NewestActivityOnOverviewComponent,\n WorkPackageCommentComponent,\n WorkPackageCommentFieldComponent,\n ActivityEntryComponent,\n UserActivityComponent,\n RevisionActivityComponent,\n ActivityLinkComponent,\n WorkPackageActivityTabComponent,\n\n // Watchers tab\n WorkPackageWatchersTabComponent,\n WorkPackageWatcherEntryComponent,\n\n // Relations\n WorkPackageRelationsTabComponent,\n WorkPackageRelationsComponent,\n WorkPackageRelationsGroupComponent,\n WorkPackageRelationRowComponent,\n WorkPackageRelationsCreateComponent,\n WorkPackageRelationsHierarchyComponent,\n WorkPackageRelationsAutocomplete,\n WorkPackageBreadcrumbParentComponent,\n\n // Split view\n WorkPackageDetailsViewButtonComponent,\n WorkPackageSplitViewComponent,\n WorkPackageRelationsCountComponent,\n WorkPackageWatchersCountComponent,\n WorkPackageBreadcrumbComponent,\n WorkPackageSplitViewToolbarComponent,\n WorkPackageWatcherButtonComponent,\n WorkPackageSubjectComponent,\n\n // Full view\n WorkPackagesFullViewComponent,\n\n // Modals\n WpTableConfigurationModalComponent,\n WpTableConfigurationColumnsTab,\n WpTableConfigurationDisplaySettingsTab,\n WpTableConfigurationFiltersTab,\n WpTableConfigurationSortByTab,\n WpTableConfigurationTimelinesTab,\n WpTableConfigurationHighlightingTab,\n WpTableConfigurationRelationSelectorComponent,\n WpTableExportModal,\n QuerySharingForm,\n QuerySharingModal,\n SaveQueryModal,\n WpDestroyModal,\n DatePickerModal,\n\n // CustomActions\n WpCustomActionComponent,\n WpCustomActionsComponent,\n CustomDateActionAdminComponent,\n\n // CKEditor macros which could not be included in the\n // editor module to avoid circular dependencies\n EmbeddedTablesMacroComponent,\n WpButtonMacroModal,\n\n // Card view\n WorkPackageCardViewComponent,\n WorkPackageSingleCardComponent,\n WorkPackageViewToggleButton,\n\n\n ],\n exports: [\n WorkPackagesTableComponent,\n WorkPackageTablePaginationComponent,\n WorkPackageEmbeddedTableComponent,\n WorkPackageEmbeddedTableEntryComponent,\n WorkPackageCardViewComponent,\n WorkPackageSingleCardComponent,\n WorkPackageFilterButtonComponent,\n WorkPackageFilterContainerComponent,\n WorkPackageIsolatedQuerySpaceDirective,\n WorkPackageIsolatedGraphQuerySpaceDirective,\n QueryFiltersComponent,\n\n WpResizerDirective,\n WorkPackageBreadcrumbComponent,\n WorkPackageBreadcrumbParentComponent,\n WorkPackageSplitViewToolbarComponent,\n WorkPackageSubjectComponent,\n WorkPackageWatchersCountComponent,\n WorkPackageRelationsCountComponent,\n WorkPackagesGridComponent,\n\n // Modals\n WpTableConfigurationModalComponent,\n WpTableConfigurationFiltersTab,\n\n // Needed so that e.g. IFC can access it.\n WorkPackageCreateButtonComponent,\n WorkPackageTypeStatusComponent,\n WorkPackageEditActionsBarComponent,\n WorkPackageSingleViewComponent,\n WorkPackageSplitViewComponent,\n BackButtonComponent,\n ]\n})\nexport class OpenprojectWorkPackagesModule {\n static bootstrapAttributeGroupsCalled = false;\n\n constructor(injector:Injector) {\n OpenprojectWorkPackagesModule.bootstrapAttributeGroups(injector);\n }\n\n // The static property prevents running the function\n // multiple times. This happens e.g. when the module is included\n // into a plugin's module.\n public static bootstrapAttributeGroups(injector:Injector):void {\n if (this.bootstrapAttributeGroupsCalled) {\n return;\n }\n\n this.bootstrapAttributeGroupsCalled = true;\n\n const hookService = injector.get(HookService);\n\n hookService.register('attributeGroupComponent', (group:GroupDescriptor, workPackage:WorkPackageResource) => {\n if (group.type === 'WorkPackageFormAttributeGroup') {\n return WorkPackageFormAttributeGroupComponent;\n } else if (!workPackage.isNew && group.type === 'WorkPackageFormChildrenQueryGroup') {\n return WorkPackageChildrenQueryComponent;\n } else if (!workPackage.isNew && group.type === 'WorkPackageFormRelationQueryGroup') {\n return WorkPackageRelationQueryComponent;\n } else {\n return null;\n }\n });\n\n hookService.register('workPackageAttachmentUploadComponent', (workPackage:WorkPackageResource) => {\n return AttachmentsUploadComponent;\n });\n\n hookService.register('workPackageAttachmentListComponent', (workPackage:WorkPackageResource) => {\n return AttachmentListComponent;\n });\n\n /** Return specialized work package changeset for editing service */\n hookService.register('halResourceChangesetClass', (resource:HalResource) => {\n switch (resource._type) {\n case 'WorkPackage':\n return WorkPackageChangeset;\n case 'TimeEntry':\n return TimeEntryChangeset;\n default:\n return null;\n }\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {StateService, TransitionPromise} from '@uirouter/core';\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {Injectable} from '@angular/core';\nimport {WorkPackageViewPagination} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-pagination\";\n\n@Injectable()\nexport class WorkPackagesListChecksumService {\n constructor(protected UrlParamsHelper:UrlParamsHelperService,\n protected $state:StateService) {\n }\n\n public id:string|null;\n public checksum:string|null;\n public visibleChecksum:string|null;\n\n public updateIfDifferent(query:QueryResource,\n pagination:WorkPackageViewPagination):Promise {\n\n let newQueryChecksum = this.getNewChecksum(query, pagination);\n let routePromise:Promise = Promise.resolve();\n\n if (this.isUninitialized()) {\n // Do nothing\n } else if (this.isIdDifferent(query.id)) {\n routePromise = this.maintainUrlQueryState(query.id, null);\n\n this.clear();\n\n } else if (this.isChecksumDifferent(newQueryChecksum)) {\n routePromise = this.maintainUrlQueryState(query.id, newQueryChecksum);\n }\n\n this.set(query.id, newQueryChecksum);\n return routePromise;\n }\n\n public update(query:QueryResource, pagination:WorkPackageViewPagination) {\n let newQueryChecksum = this.getNewChecksum(query, pagination);\n\n this.set(query.id, newQueryChecksum);\n\n this.maintainUrlQueryState(query.id, newQueryChecksum);\n }\n\n public setToQuery(query:QueryResource, pagination:WorkPackageViewPagination) {\n let newQueryChecksum = this.getNewChecksum(query, pagination);\n\n this.set(query.id, newQueryChecksum);\n\n return this.maintainUrlQueryState(query.id, null);\n }\n\n public isQueryOutdated(query:QueryResource,\n pagination:WorkPackageViewPagination) {\n let newQueryChecksum = this.getNewChecksum(query, pagination);\n\n return this.isOutdated(query.id, newQueryChecksum);\n }\n\n public executeIfOutdated(newId:string,\n newChecksum:string|null,\n callback:Function) {\n if (this.isUninitialized() || this.isOutdated(newId, newChecksum)) {\n this.set(newId, newChecksum);\n\n callback();\n }\n }\n\n private set(id:string|null, checksum:string|null) {\n this.id = id;\n this.checksum = checksum;\n }\n\n public clear() {\n this.id = null;\n this.checksum = null;\n this.visibleChecksum = null;\n }\n\n public isUninitialized() {\n return !this.id && !this.checksum;\n }\n\n private isIdDifferent(otherId:string|null) {\n return this.id !== otherId;\n }\n\n private isChecksumDifferent(otherChecksum:string) {\n return this.checksum && otherChecksum !== this.checksum;\n }\n\n private isOutdated(otherId:string|null, otherChecksum:string|null) {\n const hasCurrentQueryID = !!this.id;\n const hasCurrentChecksum = !!this.checksum;\n const idChanged = (this.id !== otherId);\n\n const checksumChanged = (otherChecksum !== this.checksum);\n const visibleChecksumChanged = (this.checksum && !otherChecksum && this.visibleChecksum);\n\n return (\n // Can only be outdated if either ID or props set\n (hasCurrentQueryID || hasCurrentChecksum) &&\n (\n // Query ID changed\n idChanged ||\n // Query ID same + query props changed\n (!idChanged && checksumChanged && (otherChecksum || this.visibleChecksum)) ||\n // No query ID set\n (!hasCurrentQueryID && visibleChecksumChanged)\n )\n );\n }\n\n private getNewChecksum(query:QueryResource, pagination:WorkPackageViewPagination) {\n return this.UrlParamsHelper.encodeQueryJsonParams(query, _.pick(pagination, ['page', 'perPage']));\n }\n\n private maintainUrlQueryState(id:string|null, checksum:string|null):TransitionPromise {\n this.visibleChecksum = checksum;\n\n return this.$state.go(\n '.',\n { query_props: checksum, query_id: id },\n { custom: { notify: false } }\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n/*\n The action menu is a menu that usually belongs to an OpenProject entity (like an Issue, WikiPage, Meeting, ..).\n Most likely it looks like this:\n \n The following code is responsible to open and close the \"more functions\" submenu.\n*/\nimport {ANIMATION_RATE_MS} from \"core-app/globals/global-listeners/top-menu\";\nimport ClickEvent = JQuery.ClickEvent;\n\nfunction menu_top_position(menu:JQuery) {\n // if an h2 tag follows the submenu should unfold out at the border\n var menu_start_position;\n if (menu.next().get(0) !== undefined && (menu.next().get(0).tagName === 'H2')) {\n menu_start_position = menu.next().innerHeight()! + menu.next().position().top;\n }\n else if (menu.next().hasClass(\"wiki-content\") && menu.next().children().next().first().get(0) != undefined && menu.next().children().next().first().get(0).tagName == 'H1') {\n var wiki_heading = menu.next().children().next().first();\n menu_start_position = wiki_heading.innerHeight()! + wiki_heading.position().top;\n }\n return menu_start_position;\n}\n\nfunction close_menu(event:any) {\n var menu = jQuery(event.data.menu);\n // do not close the menu, if the user accidentally clicked next to a menu item (but still within the menu)\n if (event.target !== menu.find(\" > li.drop-down.open > ul\").get(0)) {\n menu.find(\" > li.drop-down.open\").removeClass(\"open\").find(\"> ul\").slideUp(ANIMATION_RATE_MS);\n // no need to watch for clicks, when the menu is already closed\n jQuery('html').off('click', close_menu);\n }\n}\n\nfunction open_menu(menu:JQuery) {\n var drop_down = menu.find(\" > li.drop-down\");\n // do not open a menu, which is already open\n if (!drop_down.hasClass('open')) {\n drop_down.find('> ul').slideDown(ANIMATION_RATE_MS, function () {\n drop_down.find('li > a:first').focus();\n // when clicking on something, which is not the menu, close the menu\n jQuery('html').on('click', {menu: menu.get(0)}, close_menu);\n });\n drop_down.addClass('open');\n }\n}\n\n// open the given submenu when clicking on it\nexport function install_menu_logic(menu:JQuery) {\n menu.find(\" > li.drop-down\").on('click', (event:ClickEvent) => {\n open_menu(menu);\n // and prevent default action (href) for that element\n // but not for the menu items.\n var target = jQuery(event.target);\n if (target.is('.drop-down') || target.closest('li, ul').is('.drop-down')) {\n event.preventDefault();\n }\n });\n}\n","import {EventEmitter, InjectionToken, Injector} from '@angular/core';\n\nexport interface WorkPackageViewEventHandler {\n /** Event name to register **/\n EVENT:string;\n\n /** Event context CSS selector */\n SELECTOR:string;\n\n /** Event callback handler */\n handleEvent(view:T, evt:JQuery.TriggeredEvent):void;\n\n /** Event scope method */\n eventScope(view:T):JQuery;\n}\n\nexport interface WorkPackageViewOutputs {\n // On selection updated\n selectionChanged:EventEmitter;\n // On row (double) clicked\n itemClicked:EventEmitter<{ workPackageId:string, double:boolean }>;\n // On work package link / details icon clicked\n stateLinkClicked:EventEmitter<{ workPackageId:string, requestedState:string }>;\n}\n\nexport const WorkPackageViewHandlerToken = new InjectionToken>('CardEventHandler');\n\n/**\n * Abstract view handler registry for globally handling arbitrary event on the\n * view container. Used e.g., for table to register single event callbacks for the entirety\n * of the table.\n */\nexport abstract class WorkPackageViewHandlerRegistry {\n\n constructor(public readonly injector:Injector) {\n }\n\n protected abstract eventHandlers:((view:T) => WorkPackageViewEventHandler)[];\n\n attachTo(viewRef:T) {\n this.eventHandlers.map(factory => {\n let handler = factory(viewRef);\n let target = handler.eventScope(viewRef);\n\n target.on(handler.EVENT, handler.SELECTOR, (evt:JQuery.TriggeredEvent) => {\n handler.handleEvent(viewRef, evt);\n });\n\n return handler;\n });\n }\n}\n","import {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\n\n@Injectable()\nexport class WorkPackageCardViewService {\n public constructor(readonly querySpace:IsolatedQuerySpace) {\n }\n\n public classIdentifier(wp:WorkPackageResource) {\n // The same class names are used for the proximity to the table representation.\n return `wp-row-${wp.id}`;\n }\n\n public get renderedCards() {\n return this.querySpace.tableRendered.getValueOr([]);\n }\n\n public findRenderedCard(classIdentifier:string):number {\n const index = _.findIndex(this.renderedCards, (card) => card.classIdentifier === classIdentifier);\n\n return index;\n }\n\n public updateRenderedCardsValues(workPackages:WorkPackageResource[]) {\n this.querySpace.tableRendered.putValue(\n workPackages.map((wp) => {\n return {\n classIdentifier: this.classIdentifier(wp),\n workPackageId: wp.id,\n hidden: false\n };\n })\n )\n }\n}\n","import {Injector} from '@angular/core';\nimport {CardEventHandler} from \"core-components/wp-card-view/event-handler/card-view-handler-registry\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageViewFocusService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {StateService} from \"@uirouter/core\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class CardClickHandler implements CardEventHandler {\n\n // Injections\n @InjectField() deviceService:DeviceService;\n @InjectField() $state:StateService;\n @InjectField() wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() wpTableFocus:WorkPackageViewFocusService;\n @InjectField() wpCardView:WorkPackageCardViewService;\n\n constructor(public readonly injector:Injector,\n card:WorkPackageCardViewComponent) {\n }\n\n public get EVENT() {\n return 'click.cardView.card';\n }\n\n public get SELECTOR() {\n return `.wp-card`;\n }\n\n public eventScope(card:WorkPackageCardViewComponent) {\n return jQuery(card.container.nativeElement);\n }\n\n public handleEvent(card:WorkPackageCardViewComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // Ignore links\n if (target.is('a') || target.parent().is('a')) {\n return true;\n }\n\n // Locate the card from event\n let element = target.closest('wp-single-card');\n let wpId = element.data('workPackageId');\n\n if (!wpId) {\n return true;\n }\n\n this.handleWorkPackage(card, wpId, element, evt);\n\n return false;\n }\n\n\n protected handleWorkPackage(card:WorkPackageCardViewComponent, wpId:any, element:JQuery, evt:JQuery.TriggeredEvent) {\n this.setSelection(card, wpId, element, evt);\n\n card.itemClicked.emit({ workPackageId: wpId, double: false });\n }\n\n protected setSelection(card:WorkPackageCardViewComponent, wpId:string, element:JQuery, evt:JQuery.TriggeredEvent) {\n let classIdentifier = element.data('classIdentifier');\n let index = this.wpCardView.findRenderedCard(classIdentifier);\n\n // Update single selection if no modifier present\n if (!(evt.ctrlKey || evt.metaKey || evt.shiftKey)) {\n this.wpTableSelection.setSelection(wpId, index);\n }\n\n // Multiple selection if shift present\n if (evt.shiftKey) {\n this.wpTableSelection.setMultiSelectionFrom(this.wpCardView.renderedCards, wpId, index);\n }\n\n // Single selection expansion if ctrl / cmd(mac)\n if (evt.ctrlKey || evt.metaKey) {\n this.wpTableSelection.toggleRow(wpId);\n }\n\n card.selectionChanged.emit(this.wpTableSelection.getSelectedWorkPackageIds());\n\n // The current card is the last selected work package\n // not matter what other card are (de-)selected below.\n // Thus save that card for the details view button.\n this.wpTableFocus.updateFocus(wpId);\n }\n\n}\n","import {Injector} from '@angular/core';\nimport {CardEventHandler} from \"core-components/wp-card-view/event-handler/card-view-handler-registry\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {StateService} from \"@uirouter/core\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class CardDblClickHandler implements CardEventHandler {\n @InjectField() $state:StateService;\n @InjectField() wpTableSelection:WorkPackageViewSelectionService;\n\n constructor(public readonly injector:Injector,\n card:WorkPackageCardViewComponent) {\n }\n\n public get EVENT() {\n return 'dblclick.cardView.card';\n }\n\n public get SELECTOR() {\n return `.wp-card`;\n }\n\n public eventScope(card:WorkPackageCardViewComponent) {\n return jQuery(card.container.nativeElement);\n }\n\n public handleEvent(card:WorkPackageCardViewComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // Ignore links\n if (target.is('a') || target.parent().is('a')) {\n return true;\n }\n\n // Locate the row from event\n let element = target.closest('wp-single-card');\n let wpId = element.data('workPackageId');\n\n if (!wpId) {\n return true;\n }\n\n card.itemClicked.emit({ workPackageId: wpId, double: true });\n return false;\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {CardEventHandler} from \"core-components/wp-card-view/event-handler/card-view-handler-registry\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {uiStateLinkClass} from \"core-components/wp-fast-table/builders/ui-state-link-builder\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {WorkPackageViewContextMenu} from \"core-components/op-context-menu/wp-context-menu/wp-view-context-menu.directive\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class CardRightClickHandler implements CardEventHandler {\n\n // Injections\n @InjectField() wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() wpCardView:WorkPackageCardViewService;\n @InjectField() opContextMenu:OPContextMenuService;\n\n constructor(public readonly injector:Injector,\n card:WorkPackageCardViewComponent) {\n }\n\n public get EVENT() {\n return 'contextmenu.cardView.rightclick';\n }\n\n public get SELECTOR() {\n return `.wp-card`;\n }\n\n public eventScope(card:WorkPackageCardViewComponent) {\n return jQuery(card.container.nativeElement);\n }\n\n public handleEvent(card:WorkPackageCardViewComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // We want to keep the original context menu on hrefs\n // (currently, this is only the id)\n if (target.closest(`.${uiStateLinkClass}`).length) {\n debugLog('Allowing original context menu on state link');\n return true;\n }\n\n evt.preventDefault();\n evt.stopPropagation();\n\n // Locate the card from event\n const element = target.closest('wp-single-card');\n const wpId = element.data('workPackageId');\n\n if (!wpId) {\n return true;\n } else {\n let classIdentifier = element.data('classIdentifier');\n let index = this.wpCardView.findRenderedCard(classIdentifier);\n\n if (!this.wpTableSelection.isSelected(wpId)) {\n this.wpTableSelection.setSelection(wpId, index);\n }\n\n const handler = new WorkPackageViewContextMenu(this.injector, wpId, jQuery(evt.target) as JQuery, {}, card.showInfoButton);\n this.opContextMenu.show(handler, evt);\n }\n\n return false;\n }\n}\n\n","import {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {CardClickHandler} from \"core-components/wp-card-view/event-handler/click-handler\";\nimport {CardDblClickHandler} from \"core-components/wp-card-view/event-handler/double-click-handler\";\nimport {CardRightClickHandler} from \"core-components/wp-card-view/event-handler/right-click-handler\";\nimport {\n WorkPackageViewEventHandler,\n WorkPackageViewHandlerRegistry\n} from \"core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry\";\n\n\nexport type CardEventHandler = WorkPackageViewEventHandler;\n\nexport class CardViewHandlerRegistry extends WorkPackageViewHandlerRegistry {\n\n protected eventHandlers:((c:WorkPackageCardViewComponent) => CardEventHandler)[] = [\n // Clicking on the card (not within a cell)\n c => new CardClickHandler(this.injector, c),\n // Double Clicking on the row (not within a cell)\n c => new CardDblClickHandler(this.injector, c),\n // Right clicking on cards\n t => new CardRightClickHandler(this.injector, t),\n ];\n}\n","import {AfterViewInit, ChangeDetectorRef, Component, Inject, OnInit, ViewChild} from '@angular/core';\nimport {WorkPackageEmbeddedTableComponent} from 'core-components/wp-table/embedded/wp-embedded-table.component';\nimport {WpTableConfigurationService} from 'core-components/wp-table/configuration-modal/wp-table-configuration.service';\nimport {RestrictedWpTableConfigurationService} from 'core-components/wp-table/external-configuration/restricted-wp-table-configuration.service';\nimport {OpQueryConfigurationLocalsToken} from \"core-components/wp-table/external-configuration/external-query-configuration.constants\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\n\nexport interface QueryConfigurationLocals {\n service:any;\n currentQuery:any;\n urlParams?:boolean;\n disabledTabs?:{ [key:string]:string };\n callback:(newQuery:any) => void;\n}\n\n@Component({\n templateUrl: './external-query-configuration.template.html',\n providers: [[{ provide: WpTableConfigurationService, useClass: RestrictedWpTableConfigurationService }]]\n})\nexport class ExternalQueryConfigurationComponent implements OnInit, AfterViewInit {\n\n @ViewChild('embeddedTableForConfiguration', { static: true }) private embeddedTable:WorkPackageEmbeddedTableComponent;\n\n queryProps:string;\n\n constructor(@Inject(OpQueryConfigurationLocalsToken) readonly locals:QueryConfigurationLocals,\n readonly urlParamsHelper:UrlParamsHelperService,\n readonly cdRef:ChangeDetectorRef) {\n }\n\n ngOnInit() {\n if (this.locals.urlParams) {\n this.queryProps = this.urlParamsHelper.buildV3GetQueryFromJsonParams(this.locals.currentQuery);\n } else {\n this.queryProps = this.locals.currentQuery;\n }\n }\n\n ngAfterViewInit() {\n // Open the configuration modal in an asynchronous step\n // to avoid nesting components in the view initialization.\n setTimeout(() => {\n this.embeddedTable.openConfigurationModal(() => {\n this.service.detach();\n if (this.locals.urlParams) {\n this.locals.callback(this.embeddedTable.buildUrlParams());\n } else {\n this.locals.callback(this.embeddedTable.buildQueryProps());\n }\n });\n this.cdRef.detectChanges();\n });\n }\n\n public get service():any {\n return this.locals.service;\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {BoardListsService} from \"core-app/modules/boards/board/board-list/board-lists.service\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {Board, BoardType} from \"core-app/modules/boards/board/board\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {BoardActionsRegistryService} from \"core-app/modules/boards/board/board-actions/board-actions-registry.service\";\nimport {BehaviorSubject, Observable} from \"rxjs\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport interface CreateBoardParams {\n type:BoardType;\n boardName?:string;\n attribute?:string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class BoardService {\n\n public currentBoard$:BehaviorSubject = new BehaviorSubject(null);\n\n private loadAllPromise:Promise|undefined;\n\n private text = {\n unnamed_board: this.I18n.t('js.boards.label_unnamed_board'),\n action_board: (attr:string) => this.I18n.t('js.boards.board_type.action_by_attribute',\n { attribute: this.I18n.t('js.boards.board_type.action_type.' + attr) }),\n unnamed_list: this.I18n.t('js.boards.label_unnamed_list'),\n };\n\n constructor(protected apiV3Service:APIV3Service,\n protected PathHelper:PathHelperService,\n protected CurrentProject:CurrentProjectService,\n protected halResourceService:HalResourceService,\n protected boardActions:BoardActionsRegistryService,\n protected I18n:I18nService,\n protected boardsList:BoardListsService) {\n }\n\n /**\n * Return all boards in the current scope of the project\n *\n * @param projectIdentifier\n */\n public loadAllBoards(projectIdentifier:string|null = this.CurrentProject.identifier, force = false) {\n if (!(force || this.loadAllPromise === undefined)) {\n return this.loadAllPromise;\n }\n\n return this.loadAllPromise = this\n .apiV3Service\n .boards\n .allInScope(projectIdentifier!)\n .toPromise();\n }\n\n /**\n * Check whether the current user can manage board-type grids.\n */\n public canManage(board:Board):boolean {\n return !!board.grid.$links.delete;\n }\n\n\n /**\n * Save the changes to the board\n */\n public save(board:Board):Observable {\n this.reorderWidgets(board);\n return this\n .apiV3Service\n .boards\n .id(board)\n .save(board);\n }\n\n /**\n * Create a new board\n * @param name\n */\n public async create(params:CreateBoardParams):Promise {\n const board = await this\n .apiV3Service\n .boards\n .create(params.type, this.boardName(params), this.CurrentProject.identifier!, params.attribute).toPromise();\n\n if (params.type === 'free') {\n await this.boardsList.addFreeQuery(board, { name: this.text.unnamed_list });\n } else {\n await this.boardActions.get(params.attribute!).addInitialColumnsForAction(board);\n }\n\n await this.save(board).toPromise();\n\n return board;\n }\n\n public delete(board:Board):Promise {\n return this\n .apiV3Service\n .boards\n .id(board)\n .delete()\n .toPromise();\n }\n\n /**\n * Build a default board name\n */\n private boardName(params:CreateBoardParams) {\n if (params.boardName) {\n return params.boardName;\n }\n\n if (params.type === \"action\") {\n return this.text.action_board(params.attribute!);\n }\n\n return this.text.unnamed_board;\n }\n\n /**\n * Reorders the widgets to correspond to the available columns\n * @param board\n */\n private reorderWidgets(board:Board) {\n board.grid.columnCount = Math.max(board.grid.widgets.length, 1);\n board.grid.widgets.map((el:GridWidgetResource, index:number) => {\n el.startColumn = index + 1;\n el.endColumn = index + 2;\n return el;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Component, Input} from '@angular/core';\n\n@Component({\n selector: 'wp-type-status',\n templateUrl: './wp-type-status.html'\n})\nexport class WorkPackageTypeStatusComponent {\n @Input('workPackage') workPackage:WorkPackageResource;\n}\n","
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {HttpErrorResponse} from \"@angular/common/http\";\n\nexport const v3ErrorIdentifierQueryInvalid = 'urn:openproject-org:api:v3:errors:InvalidQuery';\nexport const v3ErrorIdentifierMultipleErrors = 'urn:openproject-org:api:v3:errors:MultipleErrors';\n\nexport class ErrorResource extends HalResource {\n public errors:any[];\n public message:string;\n public details:any;\n public errorIdentifier:string;\n\n /** We may get a reference to the underlying http error */\n public httpError?:HttpErrorResponse;\n\n public isValidationError:boolean = false;\n\n /**\n * Override toString to ensure the resource can\n * be printed nicely on console and in errors\n */\n public toString() {\n return `[ErrorResource ${this.message}]`;\n }\n\n public get errorMessages():string[] {\n if (this.isMultiErrorMessage()) {\n return this.errors.map(error => error.message);\n }\n\n return [this.message];\n }\n\n public isMultiErrorMessage() {\n return this.errorIdentifier === v3ErrorIdentifierMultipleErrors;\n }\n\n public getInvolvedAttributes():string[] {\n var columns = [];\n\n if (this.details) {\n columns = [{ details: this.details }];\n }\n else if (this.errors) {\n columns = this.errors;\n }\n\n return _.flatten(columns.map((resource:ErrorResource) => {\n if (resource.errorIdentifier === v3ErrorIdentifierMultipleErrors) {\n return this.extractMultiError(resource)[0];\n } else {\n return resource.details.attribute;\n }\n }));\n }\n\n public getMessagesPerAttribute():{ [attribute:string]:string[] } {\n let perAttribute:any = {};\n\n if (this.details) {\n perAttribute[this.details.attribute] = [this.message];\n }\n else {\n _.forEach(this.errors, (error:any) => {\n if (error.errorIdentifier === v3ErrorIdentifierMultipleErrors) {\n const [attribute, messages] = this.extractMultiError(error);\n let current = perAttribute[attribute] || [];\n perAttribute[attribute] = current.concat(messages);\n } else if (perAttribute[error.details.attribute]) {\n perAttribute[error.details.attribute].push(error.message);\n }\n else {\n perAttribute[error.details.attribute] = [error.message];\n }\n });\n }\n\n return perAttribute;\n }\n\n protected extractMultiError(resource:ErrorResource):[string, string[]] {\n let attribute = resource.errors[0].details.attribute;\n let messages = resource.errors.map((el:ErrorResource) => el.message);\n\n return [attribute, messages];\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {WikiIncludePageMacroModal} from 'core-components/modals/editor/macro-wiki-include-page-modal/wiki-include-page-macro.modal';\nimport {CodeBlockMacroModal} from 'core-components/modals/editor/macro-code-block-modal/code-block-macro.modal';\nimport {ChildPagesMacroModal} from 'core-components/modals/editor/macro-child-pages-modal/child-pages-macro.modal';\nimport {CkeditorAugmentedTextareaComponent} from 'core-app/ckeditor/ckeditor-augmented-textarea.component';\nimport {OpenprojectAttachmentsModule} from 'core-app/modules/attachments/openproject-attachments.module';\nimport {OpCkeditorComponent} from 'core-app/modules/common/ckeditor/op-ckeditor.component';\nimport {FormsModule} from '@angular/forms';\nimport {EditorMacrosService} from 'core-components/modals/editor/editor-macros.service';\nimport {CKEditorSetupService} from 'core-app/modules/common/ckeditor/ckeditor-setup.service';\nimport {CKEditorPreviewService} from 'core-app/modules/common/ckeditor/ckeditor-preview.service';\nimport {CommonModule} from \"@angular/common\";\n\n@NgModule({\n imports: [\n FormsModule,\n CommonModule,\n OpenprojectAttachmentsModule\n ],\n providers: [\n // CKEditor\n EditorMacrosService,\n CKEditorSetupService,\n CKEditorPreviewService,\n ],\n exports: [\n CkeditorAugmentedTextareaComponent,\n OpCkeditorComponent,\n ],\n declarations: [\n // CKEditor and Macros\n CkeditorAugmentedTextareaComponent,\n OpCkeditorComponent,\n WikiIncludePageMacroModal,\n CodeBlockMacroModal,\n ChildPagesMacroModal,\n ]\n})\nexport class OpenprojectEditorModule {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Observable} from 'rxjs';\nimport {distinctUntilChanged, map} from 'rxjs/operators';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageViewBaseService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\n\nexport interface WPFocusState {\n workPackageId:string;\n focusAfterRender:boolean;\n}\n\n@Injectable()\nexport class WorkPackageViewFocusService extends WorkPackageViewBaseService {\n\n constructor(public querySpace:IsolatedQuerySpace,\n public wpTableSelection:WorkPackageViewSelectionService) {\n super(querySpace);\n }\n\n public isFocused(workPackageId:string) {\n return this.focusedWorkPackage === workPackageId;\n }\n\n public ifShouldFocus(callback:(workPackageId:string) => void) {\n const value = this.current;\n\n if (value && value.focusAfterRender) {\n callback(value.workPackageId);\n value.focusAfterRender = false;\n this.update(value);\n }\n }\n\n public get focusedWorkPackage():string|null {\n const value = this.current;\n\n if (value) {\n return value.workPackageId;\n }\n\n // Return the first result if none selected\n const results = this.querySpace.results.value;\n if (results && results.elements.length > 0) {\n return results.elements[0].id!.toString();\n }\n\n return null;\n }\n\n public whenChanged():Observable {\n return this.live$()\n .pipe(\n map((val:WPFocusState) => val.workPackageId),\n distinctUntilChanged()\n );\n }\n\n public updateFocus(workPackageId:string, setFocusAfterRender:boolean = false) {\n // Set the selection to this row, if nothing else is selected.\n if (this.wpTableSelection.isEmpty) {\n this.wpTableSelection.setRowState(workPackageId, true);\n }\n this.update({ workPackageId: workPackageId, focusAfterRender: setFocusAfterRender });\n }\n\n valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource):WPFocusState|undefined {\n return undefined;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {Observable} from \"rxjs\";\nimport {tap} from \"rxjs/operators\";\n\nexport const indicatorLocationSelector = '.loading-indicator--location';\nexport const indicatorBackgroundSelector = '.loading-indicator--background';\n\nexport function withLoadingIndicator(indicator:LoadingIndicator, delayStopTime?:number):(source:Observable) => Observable {\n return (source$:Observable) => {\n indicator.start();\n\n return source$.pipe(\n tap(\n () => indicator.delayedStop(delayStopTime),\n () => indicator.stop(),\n () => indicator.stop()\n )\n );\n };\n}\n\nexport function withDelayedLoadingIndicator(indicator:() => LoadingIndicator):(source:Observable) => Observable {\n return (source$:Observable) => {\n setTimeout(() => indicator().start());\n\n return source$.pipe(\n tap(\n () => undefined,\n () => indicator().stop(),\n () => indicator().stop()\n )\n );\n };\n}\n\n\nexport class LoadingIndicator {\n\n private indicatorTemplate:string =\n `
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n `;\n\n constructor(public indicator:JQuery) {\n }\n\n public set promise(promise:Promise) {\n this.start();\n\n // Keep bound method around\n const stopper = () => this.delayedStop();\n\n promise\n .then(stopper)\n .catch(stopper);\n }\n\n public start() {\n // If we're currently having an active indicator, remove that one\n this.stop();\n this.indicator.prepend(this.indicatorTemplate);\n }\n\n public delayedStop(time = 25) {\n setTimeout(() => this.stop(), time);\n }\n\n public stop() {\n this.indicator.find('.loading-indicator--background').remove();\n }\n}\n\n@Injectable({ providedIn: 'root' })\nexport class LoadingIndicatorService {\n\n // Provide shortcut to the primarily used indicators\n public get table() {\n return this.indicator('table');\n }\n\n public get wpDetails() {\n return this.indicator('wpDetails');\n }\n\n public get modal() {\n return this.indicator('modal');\n }\n\n // Returns a getter function to an indicator\n // in case the indicator is shown conditionally\n public getter(name:string):() => LoadingIndicator {\n return this.indicator.bind(this, name);\n }\n\n // Return an indicator by name or element\n public indicator(indicator:string|JQuery):LoadingIndicator {\n if (typeof indicator === 'string') {\n indicator = this.getIndicatorAt(indicator) as JQuery;\n }\n\n return new LoadingIndicator(indicator);\n }\n\n private getIndicatorAt(name:string):JQuery {\n return jQuery(indicatorLocationSelector).filter(`[data-indicator-name=\"${name}\"]`);\n }\n}\n","import {EventEmitter} from '@angular/core';\nimport {Observable, Subject} from 'rxjs';\nimport {debounceTime, takeUntil} from 'rxjs/operators';\n\nexport class DebouncedEventEmitter {\n\n private emitter = new EventEmitter();\n private debouncer:Subject;\n\n constructor(takeUntil$:Observable, debounceTimeInMs:number = 250) {\n this.debouncer = new Subject();\n this.debouncer\n .pipe(\n debounceTime(debounceTimeInMs),\n takeUntil(takeUntil$)\n )\n .subscribe((val) => this.emitter.emit(val));\n }\n\n public emit(value?:T):void {\n this.debouncer.next(value);\n }\n\n public subscribe(generatorOrNext?:any, error?:any, complete?:any):any {\n return this.emitter.subscribe(generatorOrNext, error, complete);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector, OnDestroy} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WpRelationInlineAddExistingComponent} from \"core-components/wp-relations/embedded/inline/add-existing/wp-relation-inline-add-existing.component\";\nimport {WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {WpRelationInlineCreateServiceInterface} from \"core-components/wp-relations/embedded/wp-relation-inline-create.service.interface\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n@Injectable()\nexport class WpRelationInlineCreateService extends WorkPackageInlineCreateService implements WpRelationInlineCreateServiceInterface, OnDestroy {\n @InjectField() wpRelations:WorkPackageRelationsService;\n\n constructor(public injector:Injector) {\n super(injector);\n }\n\n /**\n * A separate reference pane for the inline create component\n */\n public readonly referenceComponentClass = WpRelationInlineAddExistingComponent;\n\n /**\n * Defines the relation type for the relations inline create\n */\n public relationType = '';\n\n /**\n * Add a new relation of the above type\n */\n public add(from:WorkPackageResource, toId:string):Promise {\n return this.wpRelations.addCommonRelation(toId, this.relationType, from.id!);\n }\n\n /**\n * Remove a given relation\n */\n public remove(from:WorkPackageResource, to:WorkPackageResource):Promise {\n // Find the relation matching relationType and from->to which are unique together\n const relation = this.wpRelations.find(to, from, this.relationType);\n\n if (relation !== undefined) {\n return this.wpRelations.removeRelation(relation);\n } else {\n return Promise.reject();\n }\n }\n\n /**\n * A related work package for the inline create context\n */\n public referenceTarget:WorkPackageResource|null = null;\n\n\n public get canAdd() {\n return !!(this.referenceTarget && this.canCreateWorkPackages && this.referenceTarget.addRelation);\n }\n\n public get canReference() {\n return !!this.canAdd;\n }\n\n /**\n * Reference button text\n */\n public readonly buttonTexts = {\n reference: this.I18n.t('js.relation_buttons.add_existing'),\n create: this.I18n.t('js.relation_buttons.create_new')\n };\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Transition} from \"@uirouter/core\";\nimport {Injectable} from \"@angular/core\";\nimport {EditFormRoutingService} from \"core-app/modules/fields/edit/edit-form/edit-form-routing.service\";\n\n@Injectable()\nexport class WorkPackageEditFormRoutingService extends EditFormRoutingService {\n /**\n * Return whether the given transition is cancelled during the editing of this form\n *\n * @param transition The transition that is underway.\n * @return A boolean marking whether the transition should be blocked.\n */\n public blockedTransition(transition:Transition):boolean {\n const toState = transition.to();\n const fromState = transition.from();\n const fromParams = transition.params('from');\n const toParams = transition.params('to');\n\n // In new/copy mode, transitions to the same controller are allowed\n if (fromState.name && fromState.name.match(/\\.(new|copy)$/)) {\n return !(toState.data && toState.data.allowMovingInEditMode);\n }\n\n // When editing an existing WP, transitions on the same WP id are allowed\n return toParams.workPackageId === undefined || toParams.workPackageId !== fromParams.workPackageId;\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from \"@angular/core\";\nimport {EditFormRoutingService} from \"core-app/modules/fields/edit/edit-form/edit-form-routing.service\";\nimport {WorkPackageEditFormRoutingService} from \"core-app/modules/work_packages/routing/wp-edit-form/wp-edit-form-routing.service\";\n\nexport const wpBaseSelector = 'work-packages-base';\n\n@Component({\n selector: wpBaseSelector,\n template: `\n
    \n \n
    \n `,\n providers: [\n { provide: EditFormRoutingService, useClass: WorkPackageEditFormRoutingService }\n ]\n})\nexport class WorkPackagesBaseComponent {\n}\n","import {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {WorkPackageTable} from \"../wp-fast-table\";\nimport {TableEventComponent} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\n\n\n/**\n * Execute the callback if the given JQuery Event is either an ENTER key or a click\n */\nexport function onClickOrEnter(evt:JQuery.TriggeredEvent, callback:() => void) {\n if (evt.type === 'click' || (evt.type === 'keydown' && evt.which === keyCodes.ENTER)) {\n callback();\n return false;\n }\n\n return true;\n}\n\n\nexport abstract class ClickOrEnterHandler {\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n onClickOrEnter(evt, () => this.processEvent(view.workPackageTable, evt));\n }\n\n protected abstract processEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, OnInit} from '@angular/core';\nimport {UIRouterGlobals} from '@uirouter/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {randomString} from \"core-app/helpers/random-string\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-subject',\n templateUrl: './wp-subject.html'\n})\nexport class WorkPackageSubjectComponent extends UntilDestroyedMixin implements OnInit {\n @Input('workPackage') workPackage:WorkPackageResource;\n\n public readonly uniqueElementIdentifier = `work-packages--subject-type-row-${randomString(16)}`;\n\n constructor(protected uiRouterGlobals:UIRouterGlobals,\n protected apiV3Service:APIV3Service) {\n super();\n }\n\n ngOnInit() {\n if (!this.workPackage) {\n this\n .apiV3Service\n .work_packages\n .id(this.uiRouterGlobals.params['workPackageId'])\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n });\n }\n }\n}\n","
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n","import {ChangeDetectorRef, Component, ElementRef, Inject, OnInit, ViewChild} from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {HttpClient, HttpErrorResponse, HttpResponse} from '@angular/common/http';\nimport {Observable, timer} from \"rxjs\";\nimport {switchMap, takeWhile} from \"rxjs/operators\";\nimport {\n LoadingIndicatorService,\n withDelayedLoadingIndicator\n} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {JobStatusEnum, JobStatusInterface} from \"core-app/modules/job-status/job-status.interface\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Component({\n templateUrl: './job-status.modal.html',\n styleUrls: ['./job-status.modal.sass']\n})\nexport class JobStatusModal extends OpModalComponent implements OnInit {\n\n /* Close on escape? */\n public closeOnEscape = false;\n\n /* Close on outside click */\n public closeOnOutsideClick = false;\n\n public text = {\n title: this.I18n.t('js.job_status.title'),\n closePopup: this.I18n.t('js.close_popup_title'),\n redirect: this.I18n.t('js.job_status.redirect'),\n redirect_errors: this.I18n.t('js.job_status.redirect_errors') + ' ',\n redirect_link: this.I18n.t('js.job_status.redirect_link'),\n errors: this.I18n.t('js.job_status.errors'),\n download_starts: this.I18n.t('js.job_status.download_starts'),\n click_to_download: this.I18n.t('js.job_status.click_to_download'),\n };\n\n /** The job ID reference */\n public jobId:string;\n\n /** Whether to show the loading indicator */\n public isLoading = false;\n\n /** The current status */\n public status:JobStatusEnum;\n\n /** An associated icon to render, if any */\n public statusIcon:string|null;\n\n /** Public message to show */\n public message:string;\n\n /** Payload object of the response */\n public payload:any;\n\n /** Title to show */\n public title:string = this.text.title;\n\n /** A link in case the job results in a download */\n public downloadHref:string|null = null;\n\n @ViewChild('downloadLink') private downloadLink:ElementRef;\n\n constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService,\n readonly elementRef:ElementRef,\n readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly notifications:NotificationsService,\n readonly httpClient:HttpClient) {\n super(locals, cdRef, elementRef);\n\n this.jobId = locals.jobId;\n }\n\n ngOnInit() {\n super.ngOnInit();\n this.listenOnJobStatus();\n }\n\n private listenOnJobStatus() {\n timer(0, 2000)\n .pipe(\n switchMap(() => this.performRequest()),\n takeWhile(response => !!response.body && this.continuedStatus(response.body), true),\n this.untilDestroyed(),\n withDelayedLoadingIndicator(this.loadingIndicator.getter('modal')),\n ).subscribe(\n response => this.onResponse(response),\n error => this.handleError(error),\n () => this.isLoading = false\n );\n }\n\n private iconForStatus():string|null {\n switch (this.status) {\n case \"cancelled\":\n case \"failure\":\n case \"error\":\n return 'icon-error';\n break;\n case \"success\":\n return \"icon-checkmark\";\n break;\n default:\n return null;\n }\n }\n\n /**\n * Determine whether the given status continues the timer\n * @param response\n */\n private continuedStatus(response:JobStatusInterface) {\n return ['in_queue', 'in_process'].includes(response.status);\n }\n\n private onResponse(response:HttpResponse) {\n let body = response.body;\n\n if (!body) {\n throw new Error(response as any);\n }\n\n let status = this.status = body.status;\n\n this.message = body.message ||\n this.I18n.t(`js.job_status.generic_messages.${status}`, { defaultValue: status });\n\n this.payload = body.payload;\n if (body.payload) {\n this.title = body.payload.title || this.text.title;\n this.handleRedirect(body.payload);\n this.handleDownload(body.payload?.download);\n }\n\n this.statusIcon = this.iconForStatus();\n this.cdRef.detectChanges();\n }\n\n private handleRedirect(payload:any) {\n if (payload?.redirect && !payload?.errors) {\n setTimeout(() => window.location.href = payload.redirect, 2000);\n this.message += `. ${this.text.redirect}`;\n }\n }\n\n private handleDownload(redirectionUrl?:string) {\n if (redirectionUrl !== undefined) {\n // Get the file url from the redirectionUrl\n this.httpClient\n .get(redirectionUrl, {\n observe: 'response',\n responseType: 'text'\n })\n .subscribe(response => {\n this.downloadHref = response.url;\n\n this.cdRef.detectChanges();\n this.downloadLink.nativeElement.click();\n });\n }\n }\n\n private performRequest():Observable> {\n return this\n .httpClient\n .get(\n this.jobUrl,\n { observe: 'response', responseType: 'json' }\n );\n }\n\n private handleError(error:HttpErrorResponse) {\n if (error?.status === 404) {\n this.statusIcon = 'icon-help';\n this.message = this.I18n.t('js.job_status.generic_messages.not_found');\n return;\n }\n\n\n this.statusIcon = 'icon-error';\n this.message = error?.message || this.I18n.t('js.error.internal');\n this.notifications.addError(this.message);\n }\n\n private get jobUrl():string {\n return this.apiV3Service.job_statuses.id(this.jobId).toString();\n }\n}\n","
    \n
    \n
    \n

    \n \n \n \n \n
    \n\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n {{ text.download_starts }}\n \n \n \n \n

    \n
      \n
    • \n
    \n\n

    \n \n \n \n

    \n
    \n
    \n
    \n
    \n
    \n","import {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {EditFormComponent} from 'core-app/modules/fields/edit/edit-form/edit-form.component';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\n\n@Component({\n templateUrl: './form.component.html',\n selector: 'te-form',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TimeEntryFormComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n @Input() changeset:ResourceChangeset;\n @Input() showWorkPackageField:boolean = true;\n\n @Output() modifiedEntry = new EventEmitter<{ savedResource:TimeEntryResource, isInital:boolean }>();\n\n @ViewChild('editForm', { static: true }) editForm:EditFormComponent;\n\n text = {\n attributes: {\n comment: this.i18n.t('js.time_entry.comment'),\n hours: this.i18n.t('js.time_entry.hours'),\n activity: this.i18n.t('js.time_entry.activity'),\n workPackage: this.i18n.t('js.time_entry.work_package'),\n spentOn: this.i18n.t('js.time_entry.spent_on'),\n },\n wpRequired: this.i18n.t('js.time_entry.work_package_required')\n };\n\n public workPackageSelected:boolean = false;\n public customFields:{ key:string, label:string }[] = [];\n\n constructor(readonly halEditing:HalResourceEditingService,\n readonly cdRef:ChangeDetectorRef,\n readonly i18n:I18nService) {\n super();\n }\n\n ngOnInit() {\n this.halEditing\n .temporaryEditResource(this.changeset.projectedResource)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(changeset => {\n if (changeset && changeset.workPackage) {\n this.workPackageSelected = true;\n this.cdRef.markForCheck();\n }\n });\n\n this.setCustomFields();\n this.cdRef.detectChanges();\n }\n\n public get entry() {\n return this.changeset.projectedResource;\n }\n\n public signalModifiedEntry($event:{ savedResource:HalResource, isInital:boolean }) {\n this.modifiedEntry.emit($event as { savedResource:TimeEntryResource, isInital:boolean });\n }\n\n public save() {\n return this.editForm.submit();\n }\n\n public get inEditMode() {\n // For now, we always want the form in edit mode.\n // Alternatively, this.entry.isNew can be used.\n return true;\n }\n\n public isRequired(field:string) {\n // Other than defined in the schema, we consider the work package to be required.\n // Remove once the schema requires it explicitly.\n if (field === 'workPackage') {\n return true;\n } else {\n return this.schema.ofProperty(field).required;\n }\n }\n\n private setCustomFields() {\n Object.entries(this.schema).forEach(([key, keySchema]) => {\n if (key.match(/customField\\d+/)) {\n this.customFields.push({ key: key, label: keySchema.name });\n }\n });\n }\n\n private get schema() {\n return this.changeset.schema;\n }\n}\n","\n
    \n\n
    \n
    \n
    \n \n \n
    \n\n
    \n
    \n
    \n \n \n
    \n\n
    \n
    \n
    \n \n \n
    \n\n
    \n
    \n
    \n \n \n \n \n
    \n\n
    \n
    \n
    \n \n \n
    \n\n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {PaginationInstance} from 'core-components/table-pagination/pagination-instance';\n\nexport class WorkPackageViewPagination {\n public current:PaginationInstance;\n\n constructor(results:WorkPackageCollectionResource) {\n this.current = new PaginationInstance(results.offset, results.total, results.pageSize);\n }\n\n public get page() {\n return this.current.page;\n }\n\n public set page(val) {\n this.current.page = val;\n }\n\n public get perPage() {\n return this.current.perPage;\n }\n\n public set perPage(val) {\n this.current.perPage = val;\n }\n\n public get total() {\n return this.current.total;\n }\n\n public set total(val) {\n this.current.total = val;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {PaginationObject, PaginationService} from 'core-components/table-pagination/pagination-service';\nimport {WorkPackageViewPagination} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-pagination\";\nimport {WorkPackageViewBaseService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service\";\n\nexport interface PaginationUpdateObject {\n page?:number;\n perPage?:number;\n total?:number;\n count?:number;\n}\n\n@Injectable()\nexport class WorkPackageViewPaginationService extends WorkPackageViewBaseService {\n public constructor(querySpace:IsolatedQuerySpace,\n readonly paginationService:PaginationService) {\n super(querySpace);\n }\n\n public get paginationObject():PaginationObject {\n if (this.current) {\n return {\n pageSize: this.current.perPage,\n offset: this.current.page\n };\n } else {\n return {\n pageSize: this.paginationService.getCachedPerPage([]),\n offset: 1\n };\n }\n\n }\n\n public valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource) {\n return new WorkPackageViewPagination(results);\n }\n\n public updateFromObject(object:PaginationUpdateObject) {\n let currentState = this.current;\n\n if (object.page) {\n currentState.page = object.page;\n }\n if (object.perPage) {\n currentState.perPage = object.perPage;\n }\n if (object.total) {\n currentState.total = object.total;\n }\n\n this.updatesState.putValue(currentState);\n }\n\n public updateFromResults(results:WorkPackageCollectionResource) {\n let update = {\n page: results.offset,\n perPage: results.pageSize,\n total: results.total,\n count: results.count\n };\n\n this.updateFromObject(update);\n }\n\n public get current():WorkPackageViewPagination {\n return this.lastUpdatedState.value!;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {HttpClient, HttpEvent, HttpEventType, HttpResponse} from \"@angular/common/http\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Observable} from \"rxjs\";\nimport {filter, map, share} from \"rxjs/operators\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\n\nexport interface UploadFile extends File {\n description?:string;\n customName?:string;\n}\n\n\nexport interface UploadBlob extends Blob {\n description?:string;\n customName?:string;\n name?:string;\n}\n\nexport type UploadHttpEvent = HttpEvent;\nexport type UploadInProgress = [UploadFile, Observable];\n\nexport interface UploadResult {\n uploads:UploadInProgress[];\n finished:Promise;\n}\n\nexport interface MappedUploadResult {\n uploads:UploadInProgress[];\n finished:Promise<{ response:any, uploadUrl:string }[]>;\n}\n\n@Injectable()\nexport class OpenProjectFileUploadService {\n constructor(protected http:HttpClient,\n protected halResource:HalResourceService) {\n }\n\n /**\n * Upload multiple files and return a promise for each uploading file and a single promise for all processed uploads\n * with their accessible URLs returned.\n * @param {string} url\n * @param {UploadFile[]} files\n * @param {string} method\n * @returns {Promise<{response:HalResource; uploadUrl:any}[]>}\n */\n public uploadAndMapResponse(url:string, files:UploadFile[], method:string = 'post') {\n const { uploads, finished } = this.upload(url, files);\n const mapped = finished\n .then((result:HalResource[]) => result.map((el:HalResource) => {\n return { response: el, uploadUrl: el.staticDownloadLocation.href };\n })) as Promise<{ response:HalResource, uploadUrl:string }[]>;\n\n return { uploads: uploads, finished: mapped } as MappedUploadResult;\n }\n\n /**\n * Upload multiple files and return a promise for each uploading file and a single promise for all processed uploads\n * Ignore directories.\n */\n public upload(url:string, files:UploadFile[], method:string = 'post'):UploadResult {\n files = _.filter(files, (file:UploadFile) => file.type !== 'directory');\n const uploads:UploadInProgress[] = _.map(files, (file:UploadFile) => this.uploadSingle(url, file, method));\n\n const finished = this.whenFinished(uploads);\n return {uploads, finished} as UploadResult;\n }\n\n /**\n * Upload a single file, get an UploadResult observable\n * @param {string} url\n * @param {UploadFile} file\n * @param {string} method\n */\n public uploadSingle(url:string, file:UploadFile|UploadBlob, method:string = 'post', responseType:'text'|'json' = 'json') {\n const formData = new FormData();\n const metadata = {\n description: file.description,\n fileName: file.customName || file.name\n };\n\n // add the metadata object\n formData.append(\n 'metadata',\n JSON.stringify(metadata),\n );\n\n // Add the file\n formData.append('file', file, metadata.fileName);\n\n const observable = this\n .http\n .request(\n method,\n url,\n {\n body: formData,\n // Observe the response, not the body\n observe: 'events',\n withCredentials: true,\n responseType: responseType as any,\n // Subscribe to progress events. subscribe() will fire multiple times!\n reportProgress: true\n }\n )\n .pipe(\n share()\n );\n\n return [file, observable] as UploadInProgress;\n }\n\n /**\n * Create a promise for all uploaded responses when all uploads are fully uploaded.\n *\n * @param {UploadInProgress[]} uploads\n */\n private whenFinished(uploads:UploadInProgress[]):Promise {\n const promises = uploads.map(([_, observable]) => {\n return observable\n .pipe(\n filter((evt) => evt.type === HttpEventType.Response),\n map((evt:HttpResponse) => this.halResource.createHalResource(evt.body))\n )\n .toPromise();\n });\n\n return Promise.all(promises);\n }\n}\n","
    \n
    \n
    \n \n \n\n \n \n\n
      \n\n \n
    • \n \n \n
    • \n
      \n
    \n
    \n
    \n\n
    \n \n \n
    \n\n
    \n \n
    \n
    \n\n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from \"@angular/core\";\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {OpTitleService} from \"core-components/html/op-title.service\";\nimport {WorkPackagesViewBase} from \"core-app/modules/work_packages/routing/wp-view-base/work-packages-view.base\";\nimport {take} from \"rxjs/operators\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {QueryParamListenerService} from \"core-components/wp-query/query-param-listener.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {ComponentType} from \"@angular/cdk/overlay\";\nimport {Ng2StateDeclaration} from \"@uirouter/angular\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageFilterContainerComponent} from \"core-components/filters/filter-container/filter-container.directive\";\n\nexport interface DynamicComponentDefinition {\n component:ComponentType;\n inputs?:{ [inputName:string]:any };\n outputs?:{ [outputName:string]:Function };\n}\n\nexport interface ToolbarButtonComponentDefinition extends DynamicComponentDefinition {\n containerClasses?:string;\n show?:() => boolean;\n}\n\nexport type ViewPartitionState = '-split'|'-left-only'|'-right-only';\n\n@Component({\n selector: 'partitioned-query-space-page',\n templateUrl: './partitioned-query-space-page.component.html',\n styleUrls: ['./partitioned-query-space-page.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n /** We need to provide the wpNotification service here to get correct save notifications for WP resources */\n { provide: HalResourceNotificationService, useClass: WorkPackageNotificationService },\n QueryParamListenerService\n ]\n})\nexport class PartitionedQuerySpacePageComponent extends WorkPackagesViewBase implements OnInit, OnDestroy {\n @InjectField() I18n!:I18nService;\n @InjectField() titleService:OpTitleService;\n @InjectField() queryParamListener:QueryParamListenerService;\n\n text:{ [key:string]:string } = {\n 'jump_to_pagination': this.I18n.t('js.work_packages.jump_marks.pagination'),\n 'text_jump_to_pagination': this.I18n.t('js.work_packages.jump_marks.label_pagination'),\n };\n\n /** Whether the title can be edited */\n titleEditingEnabled:boolean;\n\n /** Current query title to render */\n selectedTitle?:string;\n currentQuery:QueryResource|undefined;\n\n /** Whether we're saving the query */\n toolbarDisabled:boolean;\n\n /** Do we currently have query props ? */\n showToolbarSaveButton:boolean;\n\n /** Listener callbacks */\n unRegisterTitleListener:Function;\n removeTransitionSubscription:Function;\n\n /** Determine when query is initially loaded */\n showToolbar = false;\n\n /** The toolbar buttons to render */\n toolbarButtonComponents:ToolbarButtonComponentDefinition[] = [];\n\n /** Whether filtering is allowed */\n filterAllowed:boolean = true;\n\n /** We need to pass the correct partition state to the view to manage the grid */\n currentPartition:ViewPartitionState = '-split';\n\n /** What route (if any) should we go back to using the back button left of the title? */\n backButtonCallback:Function|undefined;\n\n /** Which filter container component to mount */\n filterContainerDefinition:DynamicComponentDefinition = {\n component: WorkPackageFilterContainerComponent\n };\n\n ngOnInit() {\n super.ngOnInit();\n\n this.showToolbarSaveButton = !!this.$state.params.query_props;\n this.setPartition(this.$state.current);\n this.removeTransitionSubscription = this.$transitions.onSuccess({}, (transition):any => {\n const params = transition.params('to');\n const toState = transition.to();\n this.showToolbarSaveButton = !!params.query_props;\n this.setPartition(toState);\n this.cdRef.detectChanges();\n });\n\n // If the query was loaded, reload invisibly\n const isFirstLoad = !this.querySpace.initialized.hasValue();\n this.refresh(isFirstLoad, isFirstLoad);\n\n // Mark tableInformationLoaded when initially loading done\n this.setupInformationLoadedListener();\n\n // Load query on URL transitions\n this.queryParamListener\n .observe$\n .pipe(\n this.untilDestroyed()\n ).subscribe(() => {\n /** Ensure we reload the query from the changed props */\n this.currentQuery = undefined;\n this.refresh(true, true);\n });\n\n // Update title on entering this state\n this.unRegisterTitleListener = this.$transitions.onSuccess({}, () => {\n this.updateTitle(this.querySpace.query.value);\n });\n\n this.querySpace.query.values$().pipe(\n this.untilDestroyed()\n ).subscribe((query) => {\n this.onQueryUpdated(query);\n });\n }\n\n /**\n * We need to set the current partition to the grid to ensure\n * either side gets expanded to full width if we're not in '-split' mode.\n *\n * @param state The current or entering state\n */\n protected setPartition(state:Ng2StateDeclaration) {\n this.currentPartition = (state.data && state.data.partition) ? state.data.partition : '-split';\n }\n\n protected setupInformationLoadedListener() {\n this\n .querySpace\n .initialized\n .values$()\n .pipe(take(1))\n .subscribe(() => {\n this.showToolbar = true;\n this.cdRef.detectChanges();\n });\n }\n\n protected onQueryUpdated(query:QueryResource) {\n // Update the title whenever the query changes\n this.updateTitle(query);\n this.currentQuery = query;\n\n this.cdRef.detectChanges();\n }\n\n ngOnDestroy():void {\n super.ngOnDestroy();\n this.unRegisterTitleListener();\n this.removeTransitionSubscription();\n this.queryParamListener.removeQueryChangeListener();\n }\n\n public changeChangesFromTitle(val:string) {\n if (this.currentQuery && this.currentQuery.persisted) {\n this.updateTitleName(val);\n } else {\n this.wpListService\n .create(this.currentQuery!, val)\n .then(() => this.toolbarDisabled = false)\n .catch(() => this.toolbarDisabled = false);\n }\n }\n\n updateTitleName(val:string) {\n this.toolbarDisabled = true;\n this.currentQuery!.name = val;\n this.wpListService.save(this.currentQuery)\n .then(() => this.toolbarDisabled = false)\n .catch(() => this.toolbarDisabled = false);\n }\n\n updateTitle(query?:QueryResource) {\n\n // Too early for loaded query\n if (!query) {\n return;\n }\n\n\n if (query.persisted) {\n this.selectedTitle = query.name;\n } else {\n this.selectedTitle = this.wpStaticQueries.getStaticName(query);\n }\n\n this.titleEditingEnabled = this.authorisationService.can('query', 'updateImmediately');\n\n // Update the title if we're in the list state alone\n if (this.shouldUpdateHtmlTitle()) {\n this.titleService.setFirstPart(this.selectedTitle);\n }\n }\n\n refresh(visibly:boolean = false, firstPage:boolean = false):Promise {\n let promise:Promise;\n let query = this.currentQuery;\n\n if (firstPage || !query) {\n promise = this.loadFirstPage();\n } else {\n let pagination = this.wpListService.getPaginationInfo();\n promise = this.wpListService\n .loadQueryFromExisting(query, pagination, this.projectIdentifier)\n .toPromise();\n }\n\n if (visibly) {\n return this.loadingIndicator = promise.then((loadedQuery:QueryResource) => {\n this.wpStatesInitialization.initialize(loadedQuery, loadedQuery.results);\n return this.additionalLoadingTime();\n });\n }\n\n return promise.then((loadedQuery:QueryResource) => {\n this.wpStatesInitialization.initialize(loadedQuery, loadedQuery.results);\n });\n }\n\n protected loadFirstPage():Promise {\n if (this.currentQuery) {\n return this.wpListService.reloadQuery(this.currentQuery, this.projectIdentifier).toPromise();\n } else {\n return this.wpListService.loadCurrentQueryFromParams(this.projectIdentifier);\n }\n }\n\n protected additionalLoadingTime():Promise {\n return Promise.resolve();\n }\n\n protected set loadingIndicator(promise:Promise) {\n this.loadingIndicatorService.table.promise = promise;\n }\n\n protected shouldUpdateHtmlTitle():boolean {\n return true;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {Component, HostListener, Input} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {CustomActionResource} from 'core-app/modules/hal/resources/custom-action-resource';\nimport {WorkPackagesActivityService} from 'core-components/wp-single-view-tabs/activity-panel/wp-activity.service';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-custom-action',\n templateUrl: './wp-custom-action.component.html'\n})\nexport class WpCustomActionComponent {\n\n @Input() workPackage:WorkPackageResource;\n @Input() action:CustomActionResource;\n\n constructor(private halResourceService:HalResourceService,\n private apiV3Service:APIV3Service,\n private wpSchemaCacheService:SchemaCacheService,\n private wpActivity:WorkPackagesActivityService,\n private notificationService:WorkPackageNotificationService,\n private halEditing:HalResourceEditingService,\n private halEvents:HalEventsService) {\n }\n\n private fetchAction() {\n this.halResourceService.get(this.action.href!)\n .toPromise()\n .then((action) => {\n this.action = action;\n });\n }\n\n public update() {\n let payload = {\n lockVersion: this.workPackage.lockVersion,\n _links: {\n workPackage: {\n href: this.workPackage.href\n }\n }\n };\n\n this.halResourceService\n .post(this.action.href + '/execute', payload)\n .subscribe(\n (savedWp:WorkPackageResource) => {\n this.notificationService.showSave(savedWp, false);\n this.workPackage = savedWp;\n this.wpActivity.clear(this.workPackage.id!);\n // Loading the schema might be necessary in cases where the button switches\n // project or type.\n this.apiV3Service.work_packages.cache.updateWorkPackage(savedWp).then(() => {\n this.halEditing.stopEditing(savedWp);\n this.halEvents.push(savedWp, { eventType: \"updated\" });\n });\n },\n (errorResource:any) => this.notificationService.handleRawError(errorResource, this.workPackage)\n );\n }\n\n @HostListener('mouseenter') onMouseEnter() {\n this.fetchAction();\n }\n}\n\n","\n\n","\n {{action.name}}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {CustomActionResource} from \"core-app/modules/hal/resources/custom-action-resource\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Component({\n selector: 'wp-custom-actions',\n templateUrl: './wp-custom-actions.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WpCustomActionsComponent extends UntilDestroyedMixin implements OnInit {\n\n @Input() workPackage:WorkPackageResource;\n\n actions:CustomActionResource[] = [];\n\n constructor(readonly apiV3Service:APIV3Service,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage.id!)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp) => {\n this.actions = wp.customActions ? [...wp.customActions] : [];\n this.cdRef.detectChanges();\n });\n }\n\n}\n","
    \n
    \n \n
    \n\n
    \n \n \n \n\n
    \n :\n \n \n  \n .\n \n  \n .\n
    \n\n \n
    \n\n
    \n
    \n

    \n
    \n
    \n \n {{ descriptor.label }}\n *\n \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    \n \n
    \n \n \n

    \n
    \n
    \n\n \n \n \n \n\n
    \n
    \n \n \n
    \n
    \n\n
    \n\n \n \n \n \n\n \n
    \n
    \n

    \n
    \n
    \n\n \n \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n

    \n
    \n
    \n\n \n \n\n \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input,\n OnInit\n} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {distinctUntilChanged, map} from 'rxjs/operators';\nimport {debugLog} from '../../../helpers/debug_output';\nimport {CurrentProjectService} from '../../projects/current-project.service';\nimport {States} from '../../states.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DisplayFieldService} from 'core-app/modules/fields/display/display-field.service';\nimport {DisplayField} from 'core-app/modules/fields/display/display-field.module';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {HookService} from 'core-app/modules/plugins/hook-service';\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {Subject} from \"rxjs\";\nimport {randomString} from \"core-app/helpers/random-string\";\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {ISchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport interface FieldDescriptor {\n name:string;\n label:string;\n field?:DisplayField;\n fields?:DisplayField[];\n spanAll:boolean;\n multiple:boolean;\n}\n\nexport interface GroupDescriptor {\n name:string;\n id:string;\n members:FieldDescriptor[];\n query?:QueryResource;\n relationType?:string;\n isolated:boolean;\n type:string;\n}\n\nexport interface ResourceContextChange {\n isNew:boolean;\n schema:string|null;\n project:string|null;\n}\n\nexport const overflowingContainerAttribute = 'overflowingIdentifier';\n\n@Component({\n templateUrl: './wp-single-view.html',\n selector: 'wp-single-view',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageSingleViewComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n\n /** Should we show the project field */\n @Input() public showProject:boolean = false;\n\n // Grouped fields returned from API\n public groupedFields:GroupDescriptor[] = [];\n\n // State updated when structural changes to the single view may occur.\n // (e.g., when changing the type or project context).\n public resourceContextChange = new Subject();\n\n // Project context as an indicator\n // when editing the work package in a different project\n public projectContext:{\n matches:boolean,\n href:string|null,\n field?:FieldDescriptor[]\n };\n public text = {\n attachments: {\n label: this.I18n.t('js.label_attachments')\n },\n project: {\n required: this.I18n.t('js.project.required_outside_context'),\n context: this.I18n.t('js.project.context'),\n switchTo: this.I18n.t('js.project.click_to_switch_context'),\n },\n\n fields: {\n description: this.I18n.t('js.work_packages.properties.description'),\n },\n infoRow: {\n createdBy: this.I18n.t('js.label_created_by'),\n lastUpdatedOn: this.I18n.t('js.label_last_updated_on')\n },\n };\n\n protected firstTimeFocused:boolean = false;\n\n $element:JQuery;\n\n constructor(readonly I18n:I18nService,\n protected currentProject:CurrentProjectService,\n protected PathHelper:PathHelperService,\n protected states:States,\n protected halEditing:HalResourceEditingService,\n protected halResourceService:HalResourceService,\n protected displayFieldService:DisplayFieldService,\n protected schemaCache:SchemaCacheService,\n protected hook:HookService,\n protected injector:Injector,\n protected cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef,\n readonly browserDetector:BrowserDetector) {\n super();\n }\n\n public ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n const change = this.halEditing.changeFor(this.workPackage);\n this.resourceContextChange.next(this.contextFrom(change.projectedResource));\n this.refresh(change);\n\n // Whenever the resource context changes in any way,\n // update the visible fields.\n this.resourceContextChange\n .pipe(\n this.untilDestroyed(),\n distinctUntilChanged((a, b) => _.isEqual(a, b)),\n map(() => this.halEditing.changeFor(this.workPackage))\n )\n .subscribe((change:WorkPackageChangeset) => this.refresh(change));\n\n // Update the resource context on every update to the temporary resource.\n // This allows detecting a changed type value in a new work package.\n this.halEditing\n .temporaryEditResource(this.workPackage)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(resource => {\n this.resourceContextChange.next(this.contextFrom(resource));\n });\n }\n\n private refresh(change:WorkPackageChangeset) {\n // Prepare the fields that are required always\n const isNew = this.workPackage.isNew;\n const resource = change.projectedResource;\n\n if (!resource.project) {\n this.projectContext = { matches: false, href: null };\n } else {\n this.projectContext = {\n href: this.PathHelper.projectWorkPackagePath(resource.project.idFromLink, this.workPackage.id!),\n matches: resource.project.href === this.currentProject.apiv3Path\n };\n }\n\n if (isNew && !this.currentProject.inProjectContext) {\n this.projectContext.field = this.getFields(change, ['project']);\n }\n\n const attributeGroups = this.schema(resource)._attributeGroups;\n this.groupedFields = this.rebuildGroupedFields(change, attributeGroups);\n this.cdRef.detectChanges();\n }\n\n /**\n * Returns whether a group should be hidden due to being empty\n * (e.g., consists only of CFs and none of them are active in this project.\n */\n public shouldHideGroup(group:GroupDescriptor) {\n // Hide if the group is empty\n const isEmpty = group.members.length === 0;\n\n // Is a query in a new screen\n const queryInNew = this.workPackage.isNew && !!group.query;\n\n return isEmpty || queryInNew;\n }\n\n /**\n * angular 2 doesn't support track by property any more but requires a custom function\n * https://github.com/angular/angular/issues/12969\n * @param index\n * @param elem\n */\n public trackByName(_index:number, elem:{ name:string }) {\n return elem.name;\n }\n\n /**\n * Allow other modules to register groups to insert into the single view\n */\n public prependedAttributeGroupComponents() {\n return this.hook.call('prependedAttributeGroups', this.workPackage);\n }\n\n public attributeGroupComponent(group:GroupDescriptor) {\n // we take the last registered group component which means that\n // plugins will have their say if they register for it.\n return this.hook.call('attributeGroupComponent', group, this.workPackage).pop() || null;\n }\n\n public attachmentListComponent() {\n // we take the last registered group component which means that\n // plugins will have their say if they register for it.\n return this.hook.call('workPackageAttachmentListComponent', this.workPackage).pop() || null;\n }\n\n public attachmentUploadComponent() {\n // we take the last registered group component which means that\n // plugins will have their say if they register for it.\n return this.hook.call('workPackageAttachmentUploadComponent', this.workPackage).pop() || null;\n }\n\n /*\n * Returns the work package label\n */\n public get idLabel() {\n return `#${this.workPackage.id}`;\n }\n\n public get projectContextText():string {\n let id = this.workPackage.project.idFromLink;\n let projectPath = this.PathHelper.projectPath(id);\n let project = `${this.workPackage.project.name}`;\n return this.I18n.t('js.project.work_package_belongs_to', { projectname: project });\n }\n\n /*\n * Show two column layout for new WP per default, but disable in MS Edge (#29941)\n */\n public get enableTwoColumnLayout() {\n return this.workPackage.isNew && !this.browserDetector.isEdge;\n }\n\n private rebuildGroupedFields(change:WorkPackageChangeset, attributeGroups:any) {\n if (!attributeGroups) {\n return [];\n }\n\n return attributeGroups.map((group:any) => {\n let groupId = this.getAttributesGroupId(group);\n\n if (group._type === 'WorkPackageFormAttributeGroup') {\n return {\n name: group.name,\n id: groupId || randomString(16),\n members: this.getFields(change, group.attributes),\n type: group._type,\n isolated: false\n };\n } else {\n return {\n name: group.name,\n id: groupId || randomString(16),\n query: this.halResourceService.createHalResourceOfClass(QueryResource, group._embedded.query),\n relationType: group.relationType,\n members: [group._embedded.query],\n type: group._type,\n isolated: true\n };\n }\n });\n }\n\n /**\n * Maps the grouped fields into their display fields.\n * May return multiple fields (for the date virtual field).\n */\n private getFields(change:WorkPackageChangeset, fieldNames:string[]):FieldDescriptor[] {\n const descriptors:FieldDescriptor[] = [];\n\n fieldNames.forEach((fieldName:string) => {\n if (fieldName === 'date') {\n descriptors.push(this.getDateField(change));\n return;\n }\n\n if (!change.schema.ofProperty(fieldName)) {\n debugLog('Unknown field for current schema', fieldName);\n return;\n }\n\n const field:DisplayField = this.displayField(change, fieldName);\n descriptors.push({\n name: fieldName,\n label: field.label,\n multiple: false,\n spanAll: field.isFormattable,\n field: field\n });\n });\n\n return descriptors;\n }\n\n /**\n * We need to discern between milestones, which have a single\n * 'date' field vs. all other types which should display a\n * combined 'start' and 'due' date field.\n */\n private getDateField(change:WorkPackageChangeset):FieldDescriptor {\n let object:any = {\n label: this.I18n.t('js.work_packages.properties.date'),\n multiple: false\n };\n\n if (change.schema.ofProperty('date')) {\n object.field = this.displayField(change, 'date');\n object.name = 'date';\n } else {\n object.field = this.displayField(change, 'combinedDate');\n object.name = 'combinedDate';\n }\n\n return object;\n }\n\n /**\n * Get the current resource context change from the WP resource.\n * Used to identify changes in the schema or project that may result in visual changes\n * to the single view.\n *\n * @param {WorkPackage} workPackage\n * @returns {SchemaContext}\n */\n private contextFrom(workPackage:WorkPackageResource):ResourceContextChange {\n let schema = this.schema(workPackage);\n\n let schemaHref:string|null = null;\n let projectHref:string|null = workPackage.project && workPackage.project.href;\n\n if (schema.baseSchema) {\n schemaHref = schema.baseSchema.href;\n } else {\n schemaHref = schema.href;\n }\n\n\n return {\n isNew: workPackage.isNew,\n schema: schemaHref,\n project: projectHref\n };\n }\n\n private displayField(change:WorkPackageChangeset, name:string):DisplayField {\n return this.displayFieldService.getField(\n change.projectedResource,\n name,\n change.schema.ofProperty(name),\n { container: 'single-view', injector: this.injector, options: {} }\n ) as DisplayField;\n }\n\n private getAttributesGroupId(group:any):string {\n let overflowingIdentifier = this.$element\n .find(\"[data-group-name=\\'\" + group.name + \"\\']\")\n .data(overflowingContainerAttribute);\n\n if (overflowingIdentifier) {\n return overflowingIdentifier.replace('.__overflowing_', '');\n } else {\n return '';\n }\n }\n\n private schema(resource:WorkPackageResource) {\n if (this.halEditing.typedState(resource).hasValue()) {\n return this.halEditing.typedState(this.workPackage).value!.schema;\n } else {\n return this.schemaCache.of(resource) as ISchemaProxy;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {HighlightableDisplayField} from \"core-app/modules/fields/display/field-types/highlightable-display-field.module\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class DateDisplayField extends HighlightableDisplayField {\n @InjectField() timezoneService:TimezoneService;\n @InjectField() apiV3Service:APIV3Service;\n\n public render(element:HTMLElement, displayText:string):void {\n super.render(element, displayText);\n\n // Show scheduling mode in front of the start date field\n if (this.showSchedulingMode()) {\n const schedulingIcon = document.createElement('span');\n schedulingIcon.classList.add('icon-context');\n\n if (this.resource.scheduleManually) {\n schedulingIcon.classList.add('icon-pin');\n }\n\n element.prepend(schedulingIcon);\n }\n\n // Highlight overdue tasks\n if (this.shouldHighlight && this.canOverdue) {\n const diff = this.timezoneService.daysFromToday(this.value);\n\n this\n .apiV3Service\n .statuses\n .id(this.resource.status.id)\n .get()\n .toPromise()\n .then((status) => {\n if (!status.isClosed) {\n element.classList.add(Highlighting.overdueDate(diff));\n }\n });\n }\n }\n\n public get canOverdue():boolean {\n return ['dueDate', 'date'].indexOf(this.name) !== -1;\n }\n\n public get valueString() {\n if (this.value) {\n return this.timezoneService.formattedDate(this.value);\n } else {\n return '';\n }\n }\n\n private showSchedulingMode():boolean {\n return this.name === 'startDate' || this.name === 'date';\n }\n}\n","import {APIv3ResourcePath} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {Observable} from \"rxjs\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\n\nexport class APIv3FormResource extends APIv3ResourcePath {\n /**\n * POST to the form resource identified by this path\n * @param request The request payload\n */\n public post(request:Object = {}, schema:SchemaResource|null = null):Observable {\n return this\n .halResourceService\n .post(\n this.path,\n this.extractPayload(request, schema)\n );\n }\n\n /**\n * Extract payload for the form from the request and optional schema.\n *\n * @param request\n * @param schema\n */\n public extractPayload(request:T|Object, schema:SchemaResource|null = null) {\n return HalPayloadHelper.extractPayload(request, schema);\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {PasswordConfirmationModal} from \"core-components/modals/request-for-confirmation/password-confirmation.modal\";\n\nfunction registerListener(\n form:JQuery,\n $event:JQuery.TriggeredEvent,\n opModalService:OpModalService,\n modal:typeof PasswordConfirmationModal) {\n const passwordConfirm = form.find('_password_confirmation');\n\n if (passwordConfirm.length > 0) {\n return true;\n }\n\n $event.preventDefault();\n const confirmModal = opModalService.show(modal, 'global');\n confirmModal.closingEvent.subscribe((modal:any) => {\n if (modal.confirmed) {\n jQuery('')\n .attr({\n type: 'hidden',\n name: '_password_confirmation',\n value: modal.password_confirmation\n })\n .appendTo(form);\n\n form.trigger('submit');\n }\n });\n\n return false;\n}\n\nexport function registerRequestForConfirmation($:JQueryStatic) {\n window.OpenProject\n .getPluginContext()\n .then((context) => {\n const opModalService = context.services.opModalService;\n const passwordConfirmationModal = context.classes.modals.passwordConfirmation;\n\n $(document).on(\n 'submit',\n 'form[data-request-for-confirmation]',\n function(this:any, $event:JQuery.TriggeredEvent) {\n const form = jQuery(this);\n\n if (form.find('input[name=\"_password_confirmation\"]').length) {\n return true;\n }\n\n return registerListener(form, $event, opModalService, passwordConfirmationModal);\n });\n });\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nfunction createFieldsetToggleStateLabel(legend:JQuery, text:string) {\n var labelClass = 'fieldset-toggle-state-label';\n var toggleLabel = legend.find('a span.' + labelClass);\n var legendLink = legend.children('a');\n\n if (toggleLabel.length === 0) {\n toggleLabel = jQuery(\"\").addClass(labelClass)\n .addClass(\"hidden-for-sighted\");\n\n legendLink.append(toggleLabel);\n }\n\n toggleLabel.text(' ' + text);\n}\n\nfunction setFieldsetToggleState(fieldset:JQuery) {\n var legend = fieldset.children('legend');\n\n\n if (fieldset.hasClass('collapsed')) {\n createFieldsetToggleStateLabel(legend, I18n.t('js.label_collapsed'));\n } else {\n createFieldsetToggleStateLabel(legend, I18n.t('js.label_expanded'));\n }\n}\n\nfunction getFieldset(el:HTMLElement) {\n var element = jQuery(el);\n\n if (element.is('legend')) {\n return jQuery(el).parent();\n } else if (element.is('fieldset')) {\n return element;\n }\n\n throw \"Cannot derive fieldset from element!\";\n}\n\nfunction toggleFieldset(el:HTMLElement) {\n var fieldset = getFieldset(el);\n // Mark the fieldset that the user has touched it at least once\n fieldset.attr('data-touched', 'true');\n var contentArea = fieldset.find('> div').not('.form--toolbar');\n\n fieldset.toggleClass('collapsed');\n contentArea.slideToggle('fast');\n\n setFieldsetToggleState(fieldset);\n}\n\nexport function setupToggableFieldsets() {\n const fieldsets = jQuery('fieldset.form--fieldset.-collapsible');\n\n // Toggle on click\n fieldsets.on('click', '.form--fieldset-legend', function(evt) {\n toggleFieldset(this);\n evt.preventDefault();\n evt.stopPropagation();\n return false;\n });\n\n // Set initial state\n fieldsets\n .each(function() {\n var fieldset = getFieldset(this);\n\n let contentArea = fieldset.find('> div');\n if (fieldset.hasClass('collapsed')) {\n contentArea.hide();\n }\n\n setFieldsetToggleState(fieldset);\n });\n}\n","// Legacy code ported from app/assets/javascripts/application.js.erb\n// Do not add stuff here, but ideally remove into components whenver changes are necessary\nexport function setupServerResponse() {\n initMainMenuExpandStatus();\n focusFirstErroneousField();\n activateFlashNotice();\n activateFlashError();\n autoHideFlashMessage();\n flashCloseHandler();\n\n jQuery(document).ajaxComplete(activateFlashNotice);\n jQuery(document).ajaxComplete(activateFlashError);\n\n /*\n * 1 - registers a callback which copies the csrf token into the\n * X-CSRF-Token header with each ajax request. Necessary to\n * work with rails applications which have fixed\n * CVE-2011-0447\n * 2 - shows and hides ajax indicator\n */\n jQuery(document).ajaxSend(function (event, request) {\n if (jQuery(event.target.activeElement!).closest('[ajax-indicated]').length &&\n jQuery('ajax-indicator')) {\n jQuery('#ajax-indicator').show();\n }\n\n var csrf_meta_tag = jQuery('meta[name=csrf-token]');\n\n if (csrf_meta_tag) {\n var header = 'X-CSRF-Token',\n token = csrf_meta_tag.attr('content');\n\n request.setRequestHeader(header, token!);\n }\n\n request.setRequestHeader('X-Authentication-Scheme', \"Session\");\n });\n\n // ajaxStop gets called when ALL Requests finish, so we won't need a counter as in PT\n jQuery(document).ajaxStop(function () {\n if (jQuery('#ajax-indicator')) {\n jQuery('#ajax-indicator').hide();\n }\n addClickEventToAllErrorMessages();\n });\n\n // show/hide the files table\n jQuery(\".attachments h4\").click(function () {\n jQuery(this).toggleClass(\"closed\").next().slideToggle(100);\n });\n\n let resizeTo:any = null;\n jQuery(window).on('resize', function () {\n // wait 200 milliseconds for no further resize event\n // then readjust breadcrumb\n\n if (resizeTo) {\n clearTimeout(resizeTo);\n }\n resizeTo = setTimeout(function () {\n jQuery(window).trigger('resizeEnd');\n }, 200);\n });\n\n // Do not close the login window when using it\n jQuery('#nav-login-content').click(function (event) {\n event.stopPropagation();\n });\n\n // Set focus on first error message\n var error_focus = jQuery('a.afocus').first();\n var input_focus = jQuery('.autofocus').first();\n if (error_focus !== undefined) {\n error_focus.focus();\n } else if (input_focus !== undefined) {\n input_focus.focus();\n if (input_focus[0].tagName === \"INPUT\") {\n input_focus.select();\n }\n }\n // Focus on field with error\n addClickEventToAllErrorMessages();\n\n // Click handler for formatting help\n jQuery(document.body).on('click', '.formatting-help-link-button', function () {\n window.open(window.appBasePath + '/help/wiki_syntax',\n \"\",\n \"resizable=yes, location=no, width=600, height=640, menubar=no, status=no, scrollbars=yes\"\n );\n return false;\n });\n}\n\nfunction flashCloseHandler() {\n jQuery('body').on('click keydown touchend', '.close-handler,.notification-box--close', function (e) {\n if (e.type === 'click' || e.which === 13) {\n jQuery(this).parent('.flash, .errorExplanation, .notification-box')\n .not('.persistent-toggle--notification')\n .remove();\n }\n });\n}\n\nfunction autoHideFlashMessage() {\n setTimeout(function () {\n jQuery('.flash.autohide-notification').remove();\n }, 5000);\n}\n\nfunction addClickEventToAllErrorMessages() {\n jQuery('a.afocus').each(function () {\n var target = jQuery(this);\n target.click(function (evt) {\n var field = jQuery('#' + target.attr('href')!.substr(1));\n if (field === null) {\n // Cut off '_id' (necessary for select boxes)\n field = jQuery('#' + target.attr('href')!.substr(1).concat('_id'));\n }\n target.unbind(evt);\n return false;\n });\n });\n}\n\nfunction initMainMenuExpandStatus() {\n let wrapper = jQuery('#wrapper');\n let upToggle = jQuery('ul.menu_root.closed li.open a.arrow-left-to-project');\n\n if (upToggle.length === 1 && wrapper.hasClass('hidden-navigation')) {\n upToggle.trigger('click');\n }\n}\n\nfunction activateFlash(selector:any) {\n let flashMessages = jQuery(selector);\n\n flashMessages.each(function (ix, e) {\n const flashMessage = jQuery(e);\n flashMessage.show();\n });\n}\n\nfunction activateFlashNotice() {\n\n activateFlash('.flash');\n}\n\nfunction activateFlashError() {\n activateFlash('.errorExplanation[role=\"alert\"]');\n}\n\nfunction focusFirstErroneousField() {\n const firstErrorSpan = jQuery('span.errorSpan').first();\n const erroneousInput = firstErrorSpan.find('*').filter(\":input\");\n\n erroneousInput.trigger('focus');\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {performAnchorHijacking} from \"./global-listeners/link-hijacking\";\nimport {augmentedDatePicker} from \"./global-listeners/augmented-date-picker\";\nimport {refreshOnFormChanges} from 'core-app/globals/global-listeners/refresh-on-form-changes';\nimport {registerRequestForConfirmation} from \"core-app/globals/global-listeners/request-for-confirmation\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {scrollHeaderOnMobile} from \"core-app/globals/global-listeners/top-menu-scroll\";\nimport {setupToggableFieldsets} from \"core-app/globals/global-listeners/toggable-fieldset\";\nimport {TopMenu} from \"core-app/globals/global-listeners/top-menu\";\nimport {install_menu_logic} from \"core-app/globals/global-listeners/action-menu\";\nimport {makeColorPreviews} from \"core-app/globals/global-listeners/color-preview\";\nimport {dangerZoneValidation} from \"core-app/globals/global-listeners/danger-zone-validation\";\nimport {setupServerResponse} from \"core-app/globals/global-listeners/setup-server-response\";\nimport {listenToSettingChanges} from \"core-app/globals/global-listeners/settings\";\nimport {detectOnboardingTour} from \"core-app/globals/onboarding/onboarding_tour_trigger\";\n\n/**\n * A set of listeners that are relevant on every page to set sensible defaults\n */\n(function ($:JQueryStatic) {\n\n $(function () {\n $(document.documentElement!)\n .on('click', (evt:any) => {\n const target = jQuery(evt.target) as JQuery;\n\n // Create datepickers dynamically for Rails-based views\n augmentedDatePicker(evt, target);\n\n // Prevent angular handling clicks on href=\"#...\" links from other libraries\n // (especially jquery-ui and its datepicker) from routing to /#\n performAnchorHijacking(evt, target);\n\n return true;\n });\n\n // Jump to the element given by location.hash, if present\n const hash = window.location.hash;\n if (hash && hash.startsWith('#')) {\n try {\n const el = document.querySelector(hash);\n el && el.scrollIntoView();\n } catch (e) {\n // This is very likely an invalid selector such as a Google Analytics tag.\n // We can safely ignore this and just not scroll in this case.\n // Still log the error so one can confirm the reason there is no scrolling.\n console.log(\"Could not scroll to given location hash: \" + hash + \" ( \" + e.message + \")\");\n }\n }\n\n // Global submitting hook,\n // necessary to avoid a data loss warning on beforeunload\n $(document).on('submit', 'form', function () {\n window.OpenProject.pageIsSubmitted = true;\n });\n\n // Add to content if warnings displayed\n if (document.querySelector('.warning-bar--item')) {\n let content = document.querySelector('#content') as HTMLElement;\n if (content) {\n content.style.marginBottom = '100px';\n }\n }\n\n // Global beforeunload hook\n $(window).on('beforeunload', (e:JQuery.TriggeredEvent) => {\n const event = e.originalEvent as BeforeUnloadEvent;\n if (window.OpenProject.pageWasEdited && !window.OpenProject.pageIsSubmitted) {\n // Cancel the event\n event.preventDefault();\n // Chrome requires returnValue to be set\n event.returnValue = I18n.t(\"js.work_packages.confirm_edit_cancel\");\n }\n });\n\n // Disable global drag & drop handling, which results in the browser loading the image and losing the page\n $(document.documentElement!)\n .on('dragover drop', (evt:any) => {\n evt.preventDefault();\n return false;\n });\n\n refreshOnFormChanges();\n\n // Allow forms with [request-for-confirmation]\n // to show the password confirmation dialog\n registerRequestForConfirmation($);\n\n const deviceService:DeviceService = new DeviceService();\n // Register scroll handler on mobile header\n if (deviceService.isMobile) {\n scrollHeaderOnMobile();\n }\n\n // Detect and trigger the onboarding tour\n // through a lazy loaded script\n detectOnboardingTour();\n\n //\n // Legacy scripts from app/assets that are not yet component based\n //\n\n // Toggable fieldsets\n setupToggableFieldsets();\n\n // Top menu click handling\n new TopMenu(jQuery('#top-menu-items'));\n\n // Action menu logic\n jQuery('.project-actions, .toolbar-items').each(function (idx:number, menu:HTMLElement) {\n install_menu_logic(jQuery(menu));\n });\n\n // Legacy settings listener\n listenToSettingChanges();\n\n // Color patches preview the color\n makeColorPreviews();\n\n // Danger zone input validation\n dangerZoneValidation();\n\n // Bootstrap legacy app code\n setupServerResponse();\n });\n\n}(jQuery));\n","// Dynamically loads and triggers the onboarding tour\n// when on the correct spots\nimport {demoProjectsLinks, OnboardingTourNames, onboardingTourStorageKey} from \"core-app/globals/onboarding/helpers\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\n\nexport function detectOnboardingTour() {\n // ------------------------------- Global -------------------------------\n const url = new URL(window.location.href);\n const isMobile = document.body.classList.contains('-browser-mobile');\n const demoProjectsAvailable = jQuery('meta[name=demo_projects_available]').attr('content') === \"true\";\n let currentTourPart = sessionStorage.getItem(onboardingTourStorageKey);\n let tourCancelled = false;\n\n // ------------------------------- Initial start -------------------------------\n // Do not show the tutorial on mobile or when the demo data has been deleted\n if (!isMobile && demoProjectsAvailable) {\n\n // Start after the intro modal (language selection)\n // This has to be changed once the project selection is implemented\n if (url.searchParams.get(\"first_time_user\") && demoProjectsLinks().length === 2) {\n currentTourPart = '';\n sessionStorage.setItem(onboardingTourStorageKey, 'readyToStart');\n\n // Start automatically when the language selection is closed\n jQuery('.op-modal--modal-close-button').click(function () {\n tourCancelled = true;\n triggerTour('homescreen');\n });\n\n //Start automatically when the escape button is pressed\n document.addEventListener('keydown', function (event) {\n if (event.key === \"Escape\" && !tourCancelled) {\n tourCancelled = true;\n triggerTour('homescreen');\n }\n }, { once: true });\n }\n\n // ------------------------------- Tutorial Homescreen page -------------------------------\n if (currentTourPart === \"readyToStart\") {\n triggerTour('homescreen');\n }\n\n // ------------------------------- Tutorial WP page -------------------------------\n if (currentTourPart === \"startMainTourFromBacklogs\" || url.searchParams.get(\"start_onboarding_tour\")) {\n triggerTour('main');\n }\n\n // ------------------------------- Tutorial Backlogs page -------------------------------\n if (url.searchParams.get(\"start_scrum_onboarding_tour\")) {\n if (jQuery('.backlogs-menu-item').length > 0) {\n triggerTour('backlogs');\n }\n }\n\n // ------------------------------- Tutorial Task Board page -------------------------------\n if (currentTourPart === \"startTaskBoardTour\") {\n triggerTour('taskboard');\n }\n }\n}\n\nasync function triggerTour(name:OnboardingTourNames) {\n debugLog(\"Loading and triggering onboarding tour \" + name);\n const tour = await import(/* webpackChunkName: \"onboarding-tour\" */ './onboarding_tour');\n tour.start(name);\n}\n\n","import {DatePicker} from \"core-app/modules/common/op-date-picker/datepicker\";\n\n/**\n * Our application is still a hybrid one, meaning most routes are still\n * handled by Rails. As such, we disable the default link-hijacking that\n * Angular's HTML5-mode with results in\n * @param evt\n * @param target\n */\nexport function augmentedDatePicker(evt:JQuery.TriggeredEvent, target:JQuery) {\n if (target.hasClass('-augmented-datepicker')) {\n target\n .attr('autocomplete', 'off'); // Disable autocomplete for those fields\n\n window.OpenProject.getPluginContext()\n .then(context => {\n var datePicker = new DatePicker(\n '.-augmented-datepicker',\n target.val(),\n {\n weekNumbers: true,\n allowInput: true\n },\n target[0],\n context.services.configurationService\n );\n datePicker.show();\n });\n }\n}\n","/**\n * Our application is still a hybrid one, meaning most routes are still\n * handled by Rails. As such, we disable the default link-hijacking that\n * Angular's HTML5-mode with results in\n * @param evt\n * @param target\n */\nexport function performAnchorHijacking(evt:JQuery.TriggeredEvent, target:JQuery):void {\n // Avoid defaulting clicks on elements already removed from DOM\n if (!document.contains(evt.target as Element)) {\n evt.preventDefault();\n }\n\n // Avoid handling clicks on anything other than a\n const linkElement = target.closest('a');\n if (linkElement.length === 0) {\n return;\n }\n\n const link = linkElement.attr('href') || '';\n const hashPos = link.indexOf('#');\n\n // If link is neither empty nor starts with hash, ignore it\n if (link !== '' && hashPos !== 0) {\n return;\n }\n\n // Set the location to the hash if there is any\n // Since with the base tag, links like href=\"#whatever\" otherwise target to /#whatever\n if (hashPos !== -1 && link !== '#') {\n window.location.hash = link;\n }\n\n evt.preventDefault();\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n// Moved from app/assets/javascript/danger_zone_validation.js\n// Make the whole danger zone a component the next time this needs changes!\nexport function dangerZoneValidation() {\n // This will only work iff there is a single danger zone on the page\n var dangerZoneVerification = jQuery('.danger-zone--verification');\n var expectedValue = jQuery('.danger-zone--expected-value').text();\n\n dangerZoneVerification.find('input').on('input', function () {\n var actualValue = dangerZoneVerification.find('input').val() as String;\n if (expectedValue.toLowerCase() === actualValue.toLowerCase()) {\n dangerZoneVerification.find('button').prop('disabled', false);\n } else {\n dangerZoneVerification.find('button').prop('disabled', true);\n }\n });\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nexport function refreshOnFormChanges() {\n const matches = document.querySelectorAll('.augment--refresh-on-form-changes');\n\n for (let i = 0; i < matches.length; i++) {\n let element = matches[i];\n const form = jQuery(element);\n const url = form.data('refreshUrl');\n const inputId = form.data('inputSelector');\n\n form\n .find(inputId)\n .on('change', () => {\n window.location.href = url + '?' + form.serialize();\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\n// Scroll header on mobile in and out when user scrolls the container\nexport function scrollHeaderOnMobile() {\n const headerHeight = 55;\n let prevScrollPos = window.scrollY;\n\n window.addEventListener('scroll', function() {\n // Condition needed for safari browser to avoid negative positions\n let currentScrollPos = window.scrollY < 0 ? 0 : window.scrollY;\n // Only if sidebar is not opened or search bar is opened\n if (!(jQuery('#main').hasClass('hidden-navigation')) ||\n jQuery('#top-menu').hasClass('-global-search-expanded') ||\n Math.abs(currentScrollPos - prevScrollPos) <= headerHeight) { // to avoid flickering at the end of the page\n return;\n }\n\n if (prevScrollPos !== undefined && currentScrollPos !== undefined && (prevScrollPos > currentScrollPos)) {\n // Slide top menu in or out of viewport and change viewport height\n jQuery('#wrapper').removeClass('-header-scrolled');\n } else {\n jQuery('#wrapper').addClass('-header-scrolled');\n }\n prevScrollPos = currentScrollPos;\n });\n}\n","/**\n * Move from legacy app/assets/javascripts/application.js.erb\n *\n * This should not be loaded globally and ideally refactored into components\n */\nexport function listenToSettingChanges() {\n jQuery('#settings_session_ttl_enabled').on('change', function () {\n jQuery('#settings_session_ttl_container').toggle(jQuery(this).is(':checked'));\n }).trigger('change');\n\n\n /** Sync SCM vendor select when enabled SCMs are changed */\n jQuery('[name=\"settings[enabled_scm][]\"]').change(function (this:HTMLInputElement) {\n var wasDisabled = !this.checked,\n vendor = this.value,\n select = jQuery('#settings_repositories_automatic_managed_vendor'),\n option = select.find('option[value=\"' + vendor + '\"]');\n\n // Skip non-manageable SCMs\n if (option.length === 0) {\n return;\n }\n\n option.prop('disabled', wasDisabled);\n if (wasDisabled && option.prop('selected')) {\n select.val('');\n }\n });\n\n /* Javascript for Settings::TextSettingCell */\n let langSelectSwitchData = function (select:any) {\n let self = jQuery(select);\n let id:string = self.attr(\"id\") || '';\n let settingName = id.replace('lang-for-', '');\n let newLang = self.val();\n let textArea = jQuery(`#settings-${settingName}`);\n let editor = textArea.siblings('ckeditor-augmented-textarea').data('editor');\n\n return { id: id, settingName: settingName, newLang: newLang, textArea: textArea, editor: editor };\n };\n\n // Upon focusing:\n // * store the current value of the editor in the hidden field for that lang.\n // Upon change:\n // * get the current value from the hidden field for that lang and set the editor text to that value.\n // * Set the name of the textarea to reflect the current lang so that the value stored in the hidden field\n // is overwritten.\n jQuery(\".lang-select-switch\")\n .focus(function () {\n let data = langSelectSwitchData(this);\n\n jQuery(`#${data.id}-${data.newLang}`).val(data.editor.getData());\n })\n .change(function () {\n let data = langSelectSwitchData(this);\n\n let storedValue = jQuery(`#${data.id}-${data.newLang}`).val();\n\n data.editor.setData(storedValue);\n data.textArea.attr('name', `settings[${data.settingName}][${data.newLang}]`);\n });\n /* end Javascript for Settings::TextSettingCell */\n\n jQuery('.admin-settings--form').submit(function () {\n /* Update consent time if consent required */\n if (jQuery('#settings_consent_required').is(':checked') && jQuery('#toggle_consent_time').is(':checked')) {\n jQuery('#settings_consent_time')\n .val(new Date().toISOString())\n .prop('disabled', false);\n }\n\n return true;\n });\n\n /** Toggle notification settings fields */\n jQuery(\"#email_delivery_method_switch\").on(\"change\", function () {\n const delivery_method = jQuery(this).val();\n jQuery(\".email_delivery_method_settings\").hide();\n jQuery(\"#email_delivery_method_\" + delivery_method).show();\n }).trigger(\"change\");\n\n jQuery('#settings_smtp_authentication').on('change', function () {\n var isNone = jQuery(this).val() === 'none';\n jQuery('#settings_smtp_user_name,#settings_smtp_password')\n .closest('.form--field')\n .toggle(!isNone);\n });\n\n /** Toggle repository checkout fieldsets required when option is disabled */\n jQuery('.settings-repositories--checkout-toggle').change(function (this:HTMLInputElement) {\n var wasChecked = this.checked,\n fieldset = jQuery(this).closest('fieldset');\n\n fieldset\n .find('input,select')\n .filter(':not([type=checkbox])')\n .filter(':not([type=hidden])')\n .removeAttr('required') // Rails 4.0 still seems to use attribute\n .prop('required', wasChecked);\n });\n\n /** Toggle highlighted attributes visibility depending on if the highlighting mode 'inline' was selected*/\n jQuery('.settings--highlighting-mode select').change(function () {\n var highlightingMode = jQuery(this).val();\n jQuery(\".settings--highlighted-attributes\").toggle(highlightingMode === \"inline\");\n });\n\n /** Initialize hightlighted attributes checkboxes. If none is selected, it means we want them all. So let's\n * show them all as selected.\n * On submitting the form, we remove all checkboxes before sending to communicate, we actually want all and not\n * only the selected.*/\n if (jQuery(\".settings--highlighted-attributes input[type='checkbox']:checked\").length === 0) {\n jQuery(\".settings--highlighted-attributes input[type='checkbox']\").prop(\"checked\", true);\n }\n jQuery('#tab-content-work_packages form').submit(function () {\n var availableAttributes = jQuery(\".settings--highlighted-attributes input[type='checkbox']\");\n var selectedAttributes = jQuery(\".settings--highlighted-attributes input[type='checkbox']:checked\");\n if (selectedAttributes.length === availableAttributes.length) {\n availableAttributes.prop(\"checked\", false);\n }\n });\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n/**\n * Moved from app/assets/javascripts/colors.js\n *\n * Make this a component instead of modifying it the next time\n * this needs changes\n */\nexport function makeColorPreviews() {\n jQuery('.color--preview').each(function () {\n let preview = jQuery(this);\n let input:any;\n let func:any;\n let target = preview.data('target');\n\n if (target) {\n input = jQuery(target);\n } else {\n input = preview.next('input');\n }\n\n if (input.length === 0) {\n return;\n }\n\n func = function () {\n var previewColor = '';\n\n if (input.val() && input.val().length > 0) {\n previewColor = input.val();\n } else if (input.attr('placeholder') &&\n input.attr('placeholder').length > 0) {\n previewColor = input.attr('placeholder')\n }\n\n preview.css('background-color', previewColor);\n };\n\n input.keyup(func).change(func).focus(func);\n func();\n });\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n/**\n * A set of global helpers that were used in the app/assets/javascript namespace\n * but exposed globally.\n *\n * It is used in some `link_to_function` helpers in Rails templates\n */\nexport class GlobalHelpers {\n public checkAll(selector:any, checked:any) {\n jQuery('#' + selector + ' input:checkbox').not(':disabled').each(function(this:HTMLInputElement) {\n this.checked = checked;\n });\n }\n\n public toggleCheckboxesBySelector(selector:any) {\n const boxes = jQuery(selector);\n var all_checked = true;\n for (let i = 0; i < boxes.length; i++) { if (boxes[i].checked === false) { all_checked = false; } }\n for (let i = 0; i < boxes.length; i++) { boxes[i].checked = !all_checked; }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpenProjectPluginContext} from 'core-app/modules/plugins/plugin-context';\nimport {input, InputState} from 'reactivestates';\nimport {take} from 'rxjs/operators';\nimport {GlobalHelpers} from \"core-app/globals/global-helpers\";\n\n/**\n * OpenProject instance methods\n */\nexport class OpenProject {\n\n public pluginContext:InputState = input();\n\n public helpers = new GlobalHelpers();\n\n /** Globally setable variable whether the page was edited */\n public pageWasEdited:boolean = false;\n /** Globally setable variable whether the page form is submitted.\n * Necessary to avoid a data loss warning on beforeunload */\n public pageIsSubmitted:boolean = false;\n /** Globally setable variable whether any of the EditFormComponent\n * contain changes.\n * Necessary to show a data loss warning on beforeunload when clicking\n * on a link out of the Angular app (ie: main side menu)\n * */\n public editFormsContainModelChanges:boolean;\n\n public getPluginContext():Promise {\n return this.pluginContext\n .values$()\n .pipe(take(1))\n .toPromise();\n }\n\n public get urlRoot():string {\n return jQuery('meta[name=app_base_path]').attr('content') || '';\n }\n\n public get environment():string {\n return jQuery('meta[name=openproject_initializer]').data('environment');\n }\n\n public get edition():string {\n return jQuery('meta[name=openproject_initializer]').data('edition');\n }\n\n public get isStandardEdition():boolean {\n return this.edition === \"standard\";\n }\n\n public get isBimEdition():boolean {\n return this.edition === \"bim\";\n }\n\n /**\n * Guard access to reads and writes to the localstorage due to corrupted local databases\n * in Firefox happening in one larger client.\n *\n * NS_ERROR_FILE_CORRUPTED\n *\n * @param {string} key\n * @param {string} newValue\n * @returns {string | undefined}\n */\n public guardedLocalStorage(key:string, newValue?:string):string | void {\n try {\n if (newValue !== undefined) {\n window.localStorage.setItem(key, newValue);\n } else {\n const value = window.localStorage.getItem(key);\n return value === null ? undefined : value;\n }\n } catch (e) {\n console.error('Failed to access your browsers local storage. Is your local database corrupted?');\n }\n }\n}\n\nwindow.OpenProject = new OpenProject();\n","import {Inject, Injectable} from \"@angular/core\";\nimport {DOCUMENT} from \"@angular/common\";\n\n@Injectable({ providedIn: 'root' })\nexport class BrowserDetector {\n\n constructor (@Inject(DOCUMENT) private documentElement:Document) {\n }\n\n /**\n * Detect mobile browser based on the Rails determined UA\n * and resulting body class.\n */\n public get isMobile() {\n return this.hasBodyClass('-browser-mobile');\n }\n\n /**\n * ToDo: Remove all occurences once Edge on Chromium is released\n */\n public get isEdge() {\n return this.hasBodyClass('-browser-edge');\n }\n\n private hasBodyClass(name:string):boolean {\n return this.documentElement.body.classList.contains(name);\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {input} from 'reactivestates';\nimport {HelpTextResource} from 'core-app/modules/hal/resources/help-text-resource';\nimport {Injectable} from '@angular/core';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {take} from \"rxjs/operators\";\n\n@Injectable({ providedIn: 'root' })\nexport class AttributeHelpTextsService {\n private helpTexts = input();\n\n constructor(private apiV3Service:APIV3Service) {\n }\n\n /**\n * Search for a given attribute help text\n *\n * @param attribute\n * @param scope\n */\n public require(attribute:string, scope:string):Promise {\n this.load();\n\n return new Promise((resolve, reject) => {\n this.helpTexts\n .valuesPromise()\n .then(() => resolve(this.find(attribute, scope)));\n });\n }\n\n /**\n * Search for a given attribute help text\n *\n */\n public requireById(id:string):Promise {\n this.load();\n\n return this\n .helpTexts\n .values$()\n .pipe(\n take(1)\n )\n .toPromise()\n .then(() => {\n const value = this.helpTexts.getValueOr([]);\n return _.find(value, element => element.id?.toString() === id);\n });\n }\n\n private load():void {\n this.helpTexts.putFromPromiseIfPristine(() =>\n this.apiV3Service\n .help_texts\n .get()\n .toPromise()\n .then((resources:CollectionResource) => resources.elements)\n );\n\n }\n\n private find(attribute:string, scope:string):HelpTextResource|undefined {\n const value = this.helpTexts.getValueOr([]);\n return _.find(value, (element) => element.scope === scope && element.attribute === attribute);\n }\n}\n","
    \n
    \n \n\n
    \n
    \n\n \n \n\n
    \n \n \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Inject, OnInit} from '@angular/core';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {HelpTextResource} from 'core-app/modules/hal/resources/help-text-resource';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\n\n@Component({\n templateUrl: './help-text.modal.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class AttributeHelpTextModal extends OpModalComponent implements OnInit {\n\n /* Close on escape? */\n public closeOnEscape = true;\n\n /* Close on outside click */\n public closeOnOutsideClick = false;\n\n readonly text = {\n 'edit': this.I18n.t('js.button_edit'),\n 'close': this.I18n.t('js.button_close')\n };\n\n public helpText:HelpTextResource = this.locals.helpText!;\n\n constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n super.ngOnInit();\n\n // Load the attachments\n this\n .helpText\n .attachments\n .$load()\n .then(() => this.cdRef.detectChanges());\n }\n\n public get helpTextLink() {\n if (this.helpText.editText) {\n return this.helpText.editText.$link.href;\n }\n\n return '';\n\n }\n}\n\n","\n \n {{ additionalLabel }}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AttributeHelpTextsService} from './attribute-help-text.service';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input,\n OnInit\n} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {OpModalService} from 'core-components/op-modals/op-modal.service';\nimport {AttributeHelpTextModal} from \"core-app/modules/fields/help-texts/attribute-help-text.modal\";\n\nexport const attributeHelpTextSelector = 'attribute-help-text';\n\n@Component({\n selector: attributeHelpTextSelector,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './attribute-help-text.component.html'\n})\nexport class AttributeHelpTextComponent implements OnInit {\n // Attribute to show help text for\n @Input() public attribute:string;\n @Input() public additionalLabel?:string;\n\n // Scope to search for\n @Input() public attributeScope:string;\n // Load single id entry if given\n @Input() public helpTextId?:string;\n\n public exists:boolean = false;\n\n readonly text = {\n open_dialog: this.I18n.t('js.help_texts.show_modal'),\n 'edit': this.I18n.t('js.button_edit'),\n 'close': this.I18n.t('js.button_close')\n };\n\n constructor(protected elementRef:ElementRef,\n protected attributeHelpTexts:AttributeHelpTextsService,\n protected opModalService:OpModalService,\n protected cdRef:ChangeDetectorRef,\n protected injector:Injector,\n protected I18n:I18nService) {\n }\n\n ngOnInit() {\n const element:HTMLElement = this.elementRef.nativeElement;\n // Fall back to values provided by data\n this.helpTextId = this.helpTextId || element.dataset.helpTextId!;\n this.attribute = this.attribute || element.dataset.attribute!;\n this.attributeScope = this.attributeScope || element.dataset.attributeScope!;\n this.additionalLabel = this.additionalLabel || element.dataset.additionalLabel!;\n\n if (this.helpTextId) {\n this.exists = true;\n } else {\n // Need to load the promise to find out if the attribute exists\n this.load().then((resource) => {\n this.exists = !!resource;\n this.cdRef.detectChanges();\n return resource;\n });\n }\n }\n\n public handleClick() {\n this.load().then((resource) => {\n this.opModalService.show(AttributeHelpTextModal, this.injector, { helpText: resource });\n });\n }\n\n private load() {\n if (this.helpTextId) {\n return this.attributeHelpTexts.requireById(this.helpTextId);\n } else {\n return this.attributeHelpTexts.require(this.attribute, this.attributeScope);\n }\n }\n}\n\n","module.exports = global[\"I18n\"] = require(\"-!./i18n.js\");","import {KeepTabService} from 'core-components/wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {StateService} from '@uirouter/core';\n\nexport const uiStateLinkClass = '__ui-state-link';\nexport const checkedClassName = '-checked';\n\nexport const currentDetailsState = 'currentDetailsState';\nexport const currentShowState = 'currentShowState';\n\nexport class UiStateLinkBuilder {\n\n constructor(public readonly $state:StateService,\n public readonly keepTab:KeepTabService) {\n }\n\n public linkToDetails(workPackageId:string, title:string, content:string) {\n return this.build(workPackageId, currentDetailsState, title, content);\n }\n\n public linkToShow(workPackageId:string, title:string, content:string) {\n return this.build(workPackageId, currentShowState, title, content);\n }\n\n private build(workPackageId:string, state:string, title:string, content:string) {\n let a = document.createElement('a');\n\n a.href = this.$state.href((this.keepTab as any)[state], {workPackageId: workPackageId});\n a.classList.add(uiStateLinkClass);\n a.dataset['workPackageId'] = workPackageId;\n a.dataset['wpState'] = state;\n\n a.setAttribute('title', title);\n a.textContent = content;\n\n return a;\n }\n}\n","function webpackEmptyAsyncContext(req) {\n\t// Here Promise.resolve().then() is used instead of new Promise() to prevent\n\t// uncaught exception popping up in devtools\n\treturn Promise.resolve().then(function() {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t});\n}\nwebpackEmptyAsyncContext.keys = function() { return []; };\nwebpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;\nmodule.exports = webpackEmptyAsyncContext;\nwebpackEmptyAsyncContext.id = \"crnd\";","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {input, State} from 'reactivestates';\nimport {Injectable} from '@angular/core';\nimport {UploadInProgress} from \"core-components/api/op-file-upload/op-file-upload.service\";\n\nexport function removeSuccessFlashMessages() {\n jQuery('.flash.notice').remove();\n}\n\nexport type NotificationType = 'success'|'error'|'warning'|'info'|'upload';\nexport const OPNotificationEvent = 'op:notifications:add';\n\nexport interface INotification {\n message:string;\n link?:{ text:string, target:Function };\n type:NotificationType;\n data?:any;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class NotificationsService {\n\n // The current stack of notifications\n private stack = input([]);\n\n constructor(readonly configurationService:ConfigurationService) {\n jQuery(window)\n .on(OPNotificationEvent,\n (event:JQuery.TriggeredEvent, notification:INotification) => {\n this.add(notification);\n });\n }\n\n /**\n * Get a read-only view of the current stack of notifications.\n */\n public get current():State {\n return this.stack;\n }\n\n public add(notification:INotification, timeoutAfter = 5000) {\n // Remove flash messages\n removeSuccessFlashMessages();\n\n this.stack.doModify((current) => {\n let nextValue = [notification].concat(current);\n _.remove(nextValue, (n, i) =>\n i > 0 && (n.type === 'success' || n.type === 'error')\n );\n return nextValue;\n });\n\n // auto-hide if success\n if (notification.type === 'success' && this.configurationService.autoHidePopups()) {\n setTimeout(() => this.remove(notification), timeoutAfter);\n }\n\n return notification;\n }\n\n public addError(message:INotification|string, errors:any[]|string = []) {\n if (!Array.isArray(errors)) {\n errors = [errors];\n }\n\n let notification:INotification = this.createNotification(message, 'error');\n notification.data = errors;\n\n return this.add(notification);\n }\n\n public addWarning(message:INotification|string) {\n return this.add(this.createNotification(message, 'warning'));\n }\n\n public addSuccess(message:INotification|string) {\n return this.add(this.createNotification(message, 'success'));\n }\n\n public addNotice(message:INotification|string) {\n return this.add(this.createNotification(message, 'info'));\n }\n\n public addAttachmentUpload(message:INotification|string, uploads:UploadInProgress[]) {\n return this.add(this.createAttachmentUploadNotification(message, uploads));\n }\n\n public remove(notification:INotification) {\n this.stack.doModify((current) => {\n _.remove(current, n => n === notification);\n return current;\n });\n }\n\n public clear() {\n this.stack.putValue([]);\n }\n\n private createNotification(message:INotification|string, type:NotificationType):INotification {\n if (typeof message === 'string') {\n return { message: message, type: type };\n } else {\n message.type = type;\n }\n\n return message;\n }\n\n private createAttachmentUploadNotification(message:INotification|string, uploads:UploadInProgress[]) {\n if (!uploads.length) {\n throw new Error('Cannot create an upload notification without uploads!');\n }\n\n let notification = this.createNotification(message, 'upload');\n notification.data = uploads;\n\n return notification;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceSchemaResource} from 'core-app/modules/hal/resources/query-filter-instance-schema-resource';\n\nexport interface QueryFilterResourceEmbedded {\n schema:QueryFilterInstanceSchemaResource;\n}\n\nexport class QueryFilterResource extends HalResource {\n public $embedded:QueryFilterResourceEmbedded;\n public values:any[];\n\n public get id():string {\n return this.$source.id || this.idFromLink;\n }\n\n public set id(newId:string) {\n this.$source.id = newId;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {MultiInputState, State} from 'reactivestates';\nimport {States} from '../states.service';\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Injectable} from '@angular/core';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {ISchemaProxy, SchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {WorkPackageSchemaProxy} from \"core-app/modules/hal/schemas/work-package-schema-proxy\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {Observable} from \"rxjs\";\nimport {take} from \"rxjs/operators\";\n\n@Injectable()\nexport class SchemaCacheService extends StateCacheService {\n\n constructor(readonly states:States,\n readonly halResourceService:HalResourceService) {\n super(states.schemas);\n }\n\n public state(id:string|HalResource):State {\n return super.state(this.stateKey(id));\n }\n\n /**\n * Returns the schema of the provided resource.\n * This method assumes the schema is loaded and will fail if it is not.\n * @deprecated Assuming the schema to be loaded is deprecated. Rely on the states instead.\n * @param resource The HalResource for which the schema is to be returned\n * @return The schema for the HalResource\n */\n of(resource:HalResource):ISchemaProxy {\n let schema = this.state(resource).value;\n\n if (!schema) {\n throw `Schema for resource ${resource} was expected to be loaded but isn't.`;\n }\n\n if (resource._type === 'WorkPackage') {\n return WorkPackageSchemaProxy.create(schema, resource);\n } else {\n return SchemaProxy.create(schema, resource);\n }\n }\n\n public getSchemaHref(resource:HalResource):string {\n let href = resource.$links.schema?.href;\n\n if (!href) {\n throw new Error(`Resource ${resource} has no schema to load.`);\n }\n\n return href;\n }\n\n /**\n * Ensure the given schema identified by its href is currently loaded.\n * @param resource The resource with a schema property or a string to the schema href.\n * @return A promise with the loaded schema.\n */\n ensureLoaded(resource:HalResource|string):Promise {\n let href = resource instanceof HalResource ? this.getSchemaHref(resource) : resource;\n\n return this\n .requireAndStream(href)\n .pipe(\n take(1)\n )\n .toPromise();\n }\n\n /**\n * Require the value to be loaded either when forced or the value is stale\n * according to the cache interval specified for this service.\n *\n * Returns an observable to the values stream of the state.\n *\n * @param id The state to require\n * @param force Load the value anyway.\n */\n public requireAndStream(href:string, force:boolean = false):Observable {\n // Refresh when stale or being forced\n if (this.stale(href) || force) {\n this.clearAndLoad(\n href,\n this.load(href)\n );\n }\n\n return this.state(href).values$();\n }\n\n /**\n * Load the associated schema for the given work package, if needed.\n */\n protected load(href:string):Observable {\n return this\n .halResourceService\n .get(href)\n .pipe(\n take(1)\n );\n }\n\n protected loadAll(hrefs:string[]):Promise {\n return Promise.all(hrefs.map(href => this.load(href)));\n }\n\n /**\n * Places the schema in the schema state of the resource.\n * @param resource The resource for which the schema is to be updated\n * @param schema\n */\n update(resource:HalResource, schema:SchemaResource) {\n this.multiState.get(this.stateKey(resource)).putValue(schema);\n }\n\n private stateKey(id:string|HalResource):string {\n if (id instanceof HalResource) {\n return this.getSchemaHref(id);\n } else {\n return id;\n }\n }\n}\n\n","import {Title} from \"@angular/platform-browser\";\nimport {Injectable} from \"@angular/core\";\n\nconst titlePartsSeparator = ' | ';\n\n@Injectable({ providedIn: 'root' })\nexport class OpTitleService {\n constructor(private titleService:Title) {\n\n }\n\n public get current():string {\n return this.titleService.getTitle();\n }\n\n public get titleParts():string[] {\n return this.current.split(titlePartsSeparator);\n }\n\n public setFirstPart(value:string) {\n let parts = this.titleParts;\n parts[0] = value;\n\n this.titleService.setTitle(parts.join(titlePartsSeparator));\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injector} from '@angular/core';\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {States} from 'core-components/states.service';\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\n\nimport {\n HalResourceEditingService,\n ResourceChangesetCommit\n} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport const activeFieldContainerClassName = 'inline-edit--active-field';\nexport const activeFieldClassName = 'inline-edit--field';\n\nexport abstract class EditForm {\n\n // Injections\n @InjectField() states:States;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() halNotification:HalResourceNotificationService;\n @InjectField() halEvents:HalEventsService;\n\n // All current active (open) edit fields\n public activeFields:{ [fieldName:string]:EditFieldHandler } = {};\n\n // Errors of the last operation (required when adding opening fields afterwards)\n public errorsPerAttribute:{ [fieldName:string]:string[] } = {};\n\n // Reference to the changeset used in this form\n public resource:T;\n\n // Whether this form exists in edit mode\n public editMode:boolean = false;\n\n protected constructor(public injector:Injector) {\n }\n\n /**\n * Activate the field, returning the element and associated field handler\n */\n protected abstract activateField(form:EditForm, schema:IFieldSchema, fieldName:string, errors:string[]):Promise;\n\n /**\n * Show this required field. E.g., add the necessary column\n */\n protected abstract requireVisible(fieldName:string):Promise;\n\n /**\n * Reset the field and re-render the current resource's value\n */\n abstract reset(fieldName:string, focus?:boolean):void;\n\n /**\n * Optional callback when the form is being saved\n */\n protected onSaved(commit:ResourceChangesetCommit):void {\n // Does nothing by default\n }\n\n protected abstract focusOnFirstError():void;\n\n /**\n * Return whether this form has any active fields\n */\n public hasActiveFields():boolean {\n return !_.isEmpty(this.activeFields);\n }\n\n\n /**\n * Return the current or a new change object for the given resource.\n * This will always return a valid (potentially empty) change.\n *\n * @return {ResourceChangeset}\n */\n public get change():ResourceChangeset {\n return this.halEditing.changeFor(this.resource);\n }\n\n /**\n * Active the edit field upon user's request.\n * @param fieldName\n * @param noWarnings Ignore warnings if the field cannot be opened\n */\n public activate(fieldName:string, noWarnings:boolean = false):Promise {\n return this.loadFieldSchema(fieldName, noWarnings)\n .then((schema:IFieldSchema) => {\n if (!schema.writable && !noWarnings) {\n this.halNotification.showEditingBlockedError(schema.name || fieldName);\n return Promise.reject();\n }\n\n return this.renderField(fieldName, schema);\n });\n }\n\n /**\n * Activate the field unless it is marked active already\n * (e.g., already being activated).\n */\n public activateWhenNeeded(fieldName:string):Promise {\n const activeField = this.activeFields[fieldName];\n if (activeField) {\n return Promise.resolve();\n }\n\n return this.requireVisible(fieldName).then(() => {\n return this.activate(fieldName, true);\n });\n }\n\n /**\n * Activate all fields that are returned in validation errors\n */\n public activateMissingFields() {\n this.change.getForm().then((form:any) => {\n _.each(form.validationErrors, (val:any, key:string) => {\n if (key === 'id') {\n return;\n }\n this.activateWhenNeeded(key);\n });\n });\n }\n\n /**\n * Save the active changeset.\n * @return {any}\n */\n public async submit():Promise {\n if (this.change.isEmpty() && !this.resource.isNew) {\n this.closeEditFields();\n return Promise.resolve(this.resource);\n }\n\n // Mark changeset as in flight\n this.change.inFlight = true;\n\n // Reset old error notifcations\n this.errorsPerAttribute = {};\n\n // Notify all fields of upcoming save\n const openFields = _.keys(this.activeFields);\n\n // Call onSubmit handlers\n await Promise.all(_.map(this.activeFields, (handler:EditFieldHandler) => handler.onSubmit()));\n\n return new Promise((resolve, reject) => {\n this.halEditing.save>(this.change)\n .then(result => {\n // Close all current fields\n this.closeEditFields(openFields);\n\n resolve(result.resource);\n\n this.halNotification.showSave(result.resource, result.wasNew);\n this.editMode = false;\n this.onSaved(result);\n this.change.inFlight = false;\n })\n .catch((error:ErrorResource|Object) => {\n this.halNotification.handleRawError(error, this.resource);\n\n if (error instanceof ErrorResource) {\n this.handleSubmissionErrors(error);\n reject();\n }\n\n this.change.inFlight = false;\n\n return Promise.reject(error);\n });\n });\n }\n\n /**\n * Close the given or all open fields.\n *\n * @param {string[]} fields\n * @param resetChange whether to undo any changes made\n */\n public closeEditFields(fields:string[]|'all' = 'all', resetChange:boolean = true) {\n if (fields === 'all') {\n fields = _.keys(this.activeFields);\n }\n\n fields.forEach((name:string) => {\n const handler = this.activeFields[name];\n handler && handler.deactivate(false);\n\n if (resetChange) {\n this.change.reset(name);\n }\n });\n }\n\n protected handleSubmissionErrors(error:any) {\n // Process single API errors\n this.handleErroneousAttributes(error);\n }\n\n protected handleErroneousAttributes(error:any) {\n // Get attributes withe errors\n const erroneousAttributes = error.getInvolvedAttributes();\n\n // Save erroneous fields for when new fields appear\n this.errorsPerAttribute = error.getMessagesPerAttribute();\n if (erroneousAttributes.length === 0) {\n return;\n }\n\n return this.setErrorsForFields(erroneousAttributes);\n }\n\n private setErrorsForFields(erroneousFields:string[]) {\n // Accumulate errors for the given response\n let promises:Promise[] = erroneousFields.map((fieldName:string) => {\n return this.requireVisible(fieldName).then(() => {\n if (this.activeFields[fieldName]) {\n this.activeFields[fieldName].setErrors(this.errorsPerAttribute[fieldName] || []);\n }\n\n return this.activateWhenNeeded(fieldName) as any;\n });\n });\n\n Promise.all(promises)\n .then(() => {\n setTimeout(() => this.focusOnFirstError());\n })\n .catch(() => {\n console.error('Failed to activate all erroneous fields.');\n });\n }\n\n /**\n * Load the resource form to get the current field schema with all\n * values loaded.\n * @param fieldName\n */\n protected loadFieldSchema(fieldName:string, noWarnings:boolean = false):Promise {\n return new Promise((resolve, reject) => {\n this.loadFormAndCheck(fieldName, noWarnings);\n const fieldSchema:IFieldSchema = this.change.schema.ofProperty(fieldName);\n\n if (!fieldSchema) {\n throw new Error();\n }\n\n resolve(fieldSchema);\n });\n }\n\n /**\n * Ensure the form gets loaded and we show an error when the field cannot be opened\n * @param fieldName\n * @param noWarnings\n */\n private loadFormAndCheck(fieldName:string, noWarnings:boolean = false) {\n // Ensure the form is being loaded if necessary\n this.change\n .getForm()\n .then(() => {\n // Look up whether we're actually editable\n const fieldSchema = this.change.schema.ofProperty(fieldName);\n if (!fieldSchema.writable && !noWarnings) {\n this.halNotification.showEditingBlockedError(fieldSchema.name || fieldName);\n this.closeEditFields([fieldName]);\n }\n })\n .catch((error:any) => {\n console.error('Failed to build edit field: %o', error);\n this.halNotification.handleRawError(error, this.resource);\n this.closeEditFields([fieldName]);\n });\n }\n\n private renderField(fieldName:string, schema:IFieldSchema):Promise {\n const promise:Promise = this.activateField(this,\n schema,\n fieldName,\n this.errorsPerAttribute[fieldName] || []);\n\n return promise\n .then((fieldHandler:EditFieldHandler) => {\n this.activeFields[fieldName] = fieldHandler;\n return fieldHandler;\n })\n .catch((error) => {\n console.error('Failed to render edit field:' + error);\n this.halNotification.handleRawError(error);\n });\n }\n}\n","// I18n.js\n// =======\n//\n// This small library provides the Rails I18n API on the Javascript.\n// You don't actually have to use Rails (or even Ruby) to use I18n.js.\n// Just make sure you export all translations in an object like this:\n//\n// I18n.translations.en = {\n// hello: \"Hello World\"\n// };\n//\n// See tests for specific formatting like numbers and dates.\n//\n\n// Using UMD pattern from\n// https://github.com/umdjs/umd#regular-module\n// `returnExports.js` version\n;(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(\"i18n\", function(){ return factory(root);});\n } else if (typeof module === 'object' && module.exports) {\n // Node. Does not work with strict CommonJS, but\n // only CommonJS-like environments that support module.exports,\n // like Node.\n module.exports = factory(root);\n } else {\n // Browser globals (root is window)\n root.I18n = factory(root);\n }\n}(this, function(global) {\n \"use strict\";\n\n // Use previously defined object if exists in current scope\n var I18n = global && global.I18n || {};\n\n // Just cache the Array#slice function.\n var slice = Array.prototype.slice;\n\n // Apply number padding.\n var padding = function(number) {\n return (\"0\" + number.toString()).substr(-2);\n };\n\n // Improved toFixed number rounding function with support for unprecise floating points\n // JavaScript's standard toFixed function does not round certain numbers correctly (for example 0.105 with precision 2).\n var toFixed = function(number, precision) {\n return decimalAdjust('round', number, -precision).toFixed(precision);\n };\n\n // Is a given variable an object?\n // Borrowed from Underscore.js\n var isObject = function(obj) {\n var type = typeof obj;\n return type === 'function' || type === 'object'\n };\n\n var isFunction = function(func) {\n var type = typeof func;\n return type === 'function'\n };\n\n // Check if value is different than undefined and null;\n var isSet = function(value) {\n return typeof(value) !== 'undefined' && value !== null;\n };\n\n // Is a given value an array?\n // Borrowed from Underscore.js\n var isArray = function(val) {\n if (Array.isArray) {\n return Array.isArray(val);\n };\n return Object.prototype.toString.call(val) === '[object Array]';\n };\n\n var isString = function(val) {\n return typeof value == 'string' || Object.prototype.toString.call(val) === '[object String]';\n };\n\n var isNumber = function(val) {\n return typeof val == 'number' || Object.prototype.toString.call(val) === '[object Number]';\n };\n\n var isBoolean = function(val) {\n return val === true || val === false;\n };\n\n var decimalAdjust = function(type, value, exp) {\n // If the exp is undefined or zero...\n if (typeof exp === 'undefined' || +exp === 0) {\n return Math[type](value);\n }\n value = +value;\n exp = +exp;\n // If the value is not a number or the exp is not an integer...\n if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {\n return NaN;\n }\n // Shift\n value = value.toString().split('e');\n value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));\n // Shift back\n value = value.toString().split('e');\n return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));\n }\n\n var lazyEvaluate = function(message, scope) {\n if (isFunction(message)) {\n return message(scope);\n } else {\n return message;\n }\n }\n\n var merge = function (dest, obj) {\n var key, value;\n for (key in obj) if (obj.hasOwnProperty(key)) {\n value = obj[key];\n if (isString(value) || isNumber(value) || isBoolean(value) || isArray(value)) {\n dest[key] = value;\n } else {\n if (dest[key] == null) dest[key] = {};\n merge(dest[key], value);\n }\n }\n return dest;\n };\n\n // Set default days/months translations.\n var DATE = {\n day_names: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]\n , abbr_day_names: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"]\n , month_names: [null, \"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"]\n , abbr_month_names: [null, \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\n , meridian: [\"AM\", \"PM\"]\n };\n\n // Set default number format.\n var NUMBER_FORMAT = {\n precision: 3\n , separator: \".\"\n , delimiter: \",\"\n , strip_insignificant_zeros: false\n };\n\n // Set default currency format.\n var CURRENCY_FORMAT = {\n unit: \"$\"\n , precision: 2\n , format: \"%u%n\"\n , sign_first: true\n , delimiter: \",\"\n , separator: \".\"\n };\n\n // Set default percentage format.\n var PERCENTAGE_FORMAT = {\n unit: \"%\"\n , precision: 3\n , format: \"%n%u\"\n , separator: \".\"\n , delimiter: \"\"\n };\n\n // Set default size units.\n var SIZE_UNITS = [null, \"kb\", \"mb\", \"gb\", \"tb\"];\n\n // Other default options\n var DEFAULT_OPTIONS = {\n // Set default locale. This locale will be used when fallback is enabled and\n // the translation doesn't exist in a particular locale.\n defaultLocale: \"en\"\n // Set the current locale to `en`.\n , locale: \"en\"\n // Set the translation key separator.\n , defaultSeparator: \".\"\n // Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.\n , placeholder: /(?:\\{\\{|%\\{)(.*?)(?:\\}\\}?)/gm\n // Set if engine should fallback to the default locale when a translation\n // is missing.\n , fallbacks: false\n // Set the default translation object.\n , translations: {}\n // Set missing translation behavior. 'message' will display a message\n // that the translation is missing, 'guess' will try to guess the string\n , missingBehaviour: 'message'\n // if you use missingBehaviour with 'message', but want to know that the\n // string is actually missing for testing purposes, you can prefix the\n // guessed string by setting the value here. By default, no prefix!\n , missingTranslationPrefix: ''\n };\n\n // Set default locale. This locale will be used when fallback is enabled and\n // the translation doesn't exist in a particular locale.\n I18n.reset = function() {\n var key;\n for (key in DEFAULT_OPTIONS) {\n this[key] = DEFAULT_OPTIONS[key];\n }\n };\n\n // Much like `reset`, but only assign options if not already assigned\n I18n.initializeOptions = function() {\n var key;\n for (key in DEFAULT_OPTIONS) if (!isSet(this[key])) {\n this[key] = DEFAULT_OPTIONS[key];\n }\n };\n I18n.initializeOptions();\n\n // Return a list of all locales that must be tried before returning the\n // missing translation message. By default, this will consider the inline option,\n // current locale and fallback locale.\n //\n // I18n.locales.get(\"de-DE\");\n // // [\"de-DE\", \"de\", \"en\"]\n //\n // You can define custom rules for any locale. Just make sure you return a array\n // containing all locales.\n //\n // // Default the Wookie locale to English.\n // I18n.locales[\"wk\"] = function(locale) {\n // return [\"en\"];\n // };\n //\n I18n.locales = {};\n\n // Retrieve locales based on inline locale, current locale or default to\n // I18n's detection.\n I18n.locales.get = function(locale) {\n var result = this[locale] || this[I18n.locale] || this[\"default\"];\n\n if (isFunction(result)) {\n result = result(locale);\n }\n\n if (isArray(result) === false) {\n result = [result];\n }\n\n return result;\n };\n\n // The default locale list.\n I18n.locales[\"default\"] = function(locale) {\n var locales = []\n , list = []\n ;\n\n // Handle the inline locale option that can be provided to\n // the `I18n.t` options.\n if (locale) {\n locales.push(locale);\n }\n\n // Add the current locale to the list.\n if (!locale && I18n.locale) {\n locales.push(I18n.locale);\n }\n\n // Add the default locale if fallback strategy is enabled.\n if (I18n.fallbacks && I18n.defaultLocale) {\n locales.push(I18n.defaultLocale);\n }\n\n // Locale code format 1:\n // According to RFC4646 (http://www.ietf.org/rfc/rfc4646.txt)\n // language codes for Traditional Chinese should be `zh-Hant`\n //\n // But due to backward compatibility\n // We use older version of IETF language tag\n // @see http://www.w3.org/TR/html401/struct/dirlang.html\n // @see http://en.wikipedia.org/wiki/IETF_language_tag\n //\n // Format: `language-code = primary-code ( \"-\" subcode )*`\n //\n // primary-code uses ISO639-1\n // @see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes\n // @see http://www.iso.org/iso/home/standards/language_codes.htm\n //\n // subcode uses ISO 3166-1 alpha-2\n // @see http://en.wikipedia.org/wiki/ISO_3166\n // @see http://www.iso.org/iso/country_codes.htm\n //\n // @note\n // subcode can be in upper case or lower case\n // defining it in upper case is a convention only\n\n\n // Locale code format 2:\n // Format: `code = primary-code ( \"-\" region-code )*`\n // primary-code uses ISO 639-1\n // script-code uses ISO 15924\n // region-code uses ISO 3166-1 alpha-2\n // Example: zh-Hant-TW, en-HK, zh-Hant-CN\n //\n // It is similar to RFC4646 (or actually the same),\n // but seems to be limited to language, script, region\n\n // Compute each locale with its country code.\n // So this will return an array containing\n // `de-DE` and `de`\n // or\n // `zh-hans-tw`, `zh-hans`, `zh`\n // locales.\n locales.forEach(function(locale) {\n var localeParts = locale.split(\"-\");\n var firstFallback = null;\n var secondFallback = null;\n if (localeParts.length === 3) {\n firstFallback = [\n localeParts[0],\n localeParts[1]\n ].join(\"-\");\n secondFallback = localeParts[0];\n }\n else if (localeParts.length === 2) {\n firstFallback = localeParts[0];\n }\n\n if (list.indexOf(locale) === -1) {\n list.push(locale);\n }\n\n if (! I18n.fallbacks) {\n return;\n }\n\n [\n firstFallback,\n secondFallback\n ].forEach(function(nullableFallbackLocale) {\n // We don't want null values\n if (typeof nullableFallbackLocale === \"undefined\") { return; }\n if (nullableFallbackLocale === null) { return; }\n // We don't want duplicate values\n //\n // Comparing with `locale` first is faster than\n // checking whether value's presence in the list\n if (nullableFallbackLocale === locale) { return; }\n if (list.indexOf(nullableFallbackLocale) !== -1) { return; }\n\n list.push(nullableFallbackLocale);\n });\n });\n\n // No locales set? English it is.\n if (!locales.length) {\n locales.push(\"en\");\n }\n\n return list;\n };\n\n // Hold pluralization rules.\n I18n.pluralization = {};\n\n // Return the pluralizer for a specific locale.\n // If no specify locale is found, then I18n's default will be used.\n I18n.pluralization.get = function(locale) {\n return this[locale] || this[I18n.locale] || this[\"default\"];\n };\n\n // The default pluralizer rule.\n // It detects the `zero`, `one`, and `other` scopes.\n I18n.pluralization[\"default\"] = function(count) {\n switch (count) {\n case 0: return [\"zero\", \"other\"];\n case 1: return [\"one\"];\n default: return [\"other\"];\n }\n };\n\n // Return current locale. If no locale has been set, then\n // the current locale will be the default locale.\n I18n.currentLocale = function() {\n return this.locale || this.defaultLocale;\n };\n\n // Check if value is different than undefined and null;\n I18n.isSet = isSet;\n\n // Find and process the translation using the provided scope and options.\n // This is used internally by some functions and should not be used as an\n // public API.\n I18n.lookup = function(scope, options) {\n options = options || {}\n\n var locales = this.locales.get(options.locale).slice()\n , requestedLocale = locales[0]\n , locale\n , scopes\n , fullScope\n , translations\n ;\n\n fullScope = this.getFullScope(scope, options);\n\n while (locales.length) {\n locale = locales.shift();\n scopes = fullScope.split(this.defaultSeparator);\n translations = this.translations[locale];\n\n if (!translations) {\n continue;\n }\n while (scopes.length) {\n translations = translations[scopes.shift()];\n\n if (translations === undefined || translations === null) {\n break;\n }\n }\n\n if (translations !== undefined && translations !== null) {\n return translations;\n }\n }\n\n if (isSet(options.defaultValue)) {\n return lazyEvaluate(options.defaultValue, scope);\n }\n };\n\n // lookup pluralization rule key into translations\n I18n.pluralizationLookupWithoutFallback = function(count, locale, translations) {\n var pluralizer = this.pluralization.get(locale)\n , pluralizerKeys = pluralizer(count)\n , pluralizerKey\n , message;\n\n if (isObject(translations)) {\n while (pluralizerKeys.length) {\n pluralizerKey = pluralizerKeys.shift();\n if (isSet(translations[pluralizerKey])) {\n message = translations[pluralizerKey];\n break;\n }\n }\n }\n\n return message;\n };\n\n // Lookup dedicated to pluralization\n I18n.pluralizationLookup = function(count, scope, options) {\n options = options || {}\n var locales = this.locales.get(options.locale).slice()\n , requestedLocale = locales[0]\n , locale\n , scopes\n , translations\n , message\n ;\n scope = this.getFullScope(scope, options);\n\n while (locales.length) {\n locale = locales.shift();\n scopes = scope.split(this.defaultSeparator);\n translations = this.translations[locale];\n\n if (!translations) {\n continue;\n }\n\n while (scopes.length) {\n translations = translations[scopes.shift()];\n if (!isObject(translations)) {\n break;\n }\n if (scopes.length == 0) {\n message = this.pluralizationLookupWithoutFallback(count, locale, translations);\n }\n }\n if (message != null && message != undefined) {\n break;\n }\n }\n\n if (message == null || message == undefined) {\n if (isSet(options.defaultValue)) {\n if (isObject(options.defaultValue)) {\n message = this.pluralizationLookupWithoutFallback(count, options.locale, options.defaultValue);\n } else {\n message = options.defaultValue;\n }\n translations = options.defaultValue;\n }\n }\n\n return { message: message, translations: translations };\n };\n\n // Rails changed the way the meridian is stored.\n // It started with `date.meridian` returning an array,\n // then it switched to `time.am` and `time.pm`.\n // This function abstracts this difference and returns\n // the correct meridian or the default value when none is provided.\n I18n.meridian = function() {\n var time = this.lookup(\"time\");\n var date = this.lookup(\"date\");\n\n if (time && time.am && time.pm) {\n return [time.am, time.pm];\n } else if (date && date.meridian) {\n return date.meridian;\n } else {\n return DATE.meridian;\n }\n };\n\n // Merge serveral hash options, checking if value is set before\n // overwriting any value. The precedence is from left to right.\n //\n // I18n.prepareOptions({name: \"John Doe\"}, {name: \"Mary Doe\", role: \"user\"});\n // #=> {name: \"John Doe\", role: \"user\"}\n //\n I18n.prepareOptions = function() {\n var args = slice.call(arguments)\n , options = {}\n , subject\n ;\n\n while (args.length) {\n subject = args.shift();\n\n if (typeof(subject) != \"object\") {\n continue;\n }\n\n for (var attr in subject) {\n if (!subject.hasOwnProperty(attr)) {\n continue;\n }\n\n if (isSet(options[attr])) {\n continue;\n }\n\n options[attr] = subject[attr];\n }\n }\n\n return options;\n };\n\n // Generate a list of translation options for default fallbacks.\n // `defaultValue` is also deleted from options as it is returned as part of\n // the translationOptions array.\n I18n.createTranslationOptions = function(scope, options) {\n var translationOptions = [{scope: scope}];\n\n // Defaults should be an array of hashes containing either\n // fallback scopes or messages\n if (isSet(options.defaults)) {\n translationOptions = translationOptions.concat(options.defaults);\n }\n\n // Maintain support for defaultValue. Since it is always a message\n // insert it in to the translation options as such.\n if (isSet(options.defaultValue)) {\n translationOptions.push({ message: options.defaultValue });\n }\n\n return translationOptions;\n };\n\n // Translate the given scope with the provided options.\n I18n.translate = function(scope, options) {\n options = options || {}\n\n var translationOptions = this.createTranslationOptions(scope, options);\n\n var translation;\n\n var optionsWithoutDefault = this.prepareOptions(options)\n delete optionsWithoutDefault.defaultValue\n\n // Iterate through the translation options until a translation\n // or message is found.\n var translationFound =\n translationOptions.some(function(translationOption) {\n if (isSet(translationOption.scope)) {\n translation = this.lookup(translationOption.scope, optionsWithoutDefault);\n } else if (isSet(translationOption.message)) {\n translation = lazyEvaluate(translationOption.message, scope);\n }\n\n if (translation !== undefined && translation !== null) {\n return true;\n }\n }, this);\n\n if (!translationFound) {\n return this.missingTranslation(scope, options);\n }\n\n if (typeof(translation) === \"string\") {\n translation = this.interpolate(translation, options);\n } else if (isObject(translation) && isSet(options.count)) {\n translation = this.pluralize(options.count, scope, options);\n }\n\n return translation;\n };\n\n // This function interpolates the all variables in the given message.\n I18n.interpolate = function(message, options) {\n options = options || {}\n var matches = message.match(this.placeholder)\n , placeholder\n , value\n , name\n , regex\n ;\n\n if (!matches) {\n return message;\n }\n\n var value;\n\n while (matches.length) {\n placeholder = matches.shift();\n name = placeholder.replace(this.placeholder, \"$1\");\n\n if (isSet(options[name])) {\n value = options[name].toString().replace(/\\$/gm, \"_#$#_\");\n } else if (name in options) {\n value = this.nullPlaceholder(placeholder, message, options);\n } else {\n value = this.missingPlaceholder(placeholder, message, options);\n }\n\n regex = new RegExp(placeholder.replace(/\\{/gm, \"\\\\{\").replace(/\\}/gm, \"\\\\}\"));\n message = message.replace(regex, value);\n }\n\n return message.replace(/_#\\$#_/g, \"$\");\n };\n\n // Pluralize the given scope using the `count` value.\n // The pluralized translation may have other placeholders,\n // which will be retrieved from `options`.\n I18n.pluralize = function(count, scope, options) {\n options = this.prepareOptions({count: String(count)}, options)\n var pluralizer, message, result;\n\n result = this.pluralizationLookup(count, scope, options);\n if (result.translations == undefined || result.translations == null) {\n return this.missingTranslation(scope, options);\n }\n\n if (result.message != undefined && result.message != null) {\n return this.interpolate(result.message, options);\n }\n else {\n pluralizer = this.pluralization.get(options.locale);\n return this.missingTranslation(scope + '.' + pluralizer(count)[0], options);\n }\n };\n\n // Return a missing translation message for the given parameters.\n I18n.missingTranslation = function(scope, options) {\n //guess intended string\n if(this.missingBehaviour == 'guess'){\n //get only the last portion of the scope\n var s = scope.split('.').slice(-1)[0];\n //replace underscore with space && camelcase with space and lowercase letter\n return (this.missingTranslationPrefix.length > 0 ? this.missingTranslationPrefix : '') +\n s.replace('_',' ').replace(/([a-z])([A-Z])/g,\n function(match, p1, p2) {return p1 + ' ' + p2.toLowerCase()} );\n }\n\n var localeForTranslation = (options != null && options.locale != null) ? options.locale : this.currentLocale();\n var fullScope = this.getFullScope(scope, options);\n var fullScopeWithLocale = [localeForTranslation, fullScope].join(this.defaultSeparator);\n\n return '[missing \"' + fullScopeWithLocale + '\" translation]';\n };\n\n // Return a missing placeholder message for given parameters\n I18n.missingPlaceholder = function(placeholder, message, options) {\n return \"[missing \" + placeholder + \" value]\";\n };\n\n I18n.nullPlaceholder = function() {\n return I18n.missingPlaceholder.apply(I18n, arguments);\n };\n\n // Format number using localization rules.\n // The options will be retrieved from the `number.format` scope.\n // If this isn't present, then the following options will be used:\n //\n // - `precision`: `3`\n // - `separator`: `\".\"`\n // - `delimiter`: `\",\"`\n // - `strip_insignificant_zeros`: `false`\n //\n // You can also override these options by providing the `options` argument.\n //\n I18n.toNumber = function(number, options) {\n options = this.prepareOptions(\n options\n , this.lookup(\"number.format\")\n , NUMBER_FORMAT\n );\n\n var negative = number < 0\n , string = toFixed(Math.abs(number), options.precision).toString()\n , parts = string.split(\".\")\n , precision\n , buffer = []\n , formattedNumber\n , format = options.format || \"%n\"\n , sign = negative ? \"-\" : \"\"\n ;\n\n number = parts[0];\n precision = parts[1];\n\n while (number.length > 0) {\n buffer.unshift(number.substr(Math.max(0, number.length - 3), 3));\n number = number.substr(0, number.length -3);\n }\n\n formattedNumber = buffer.join(options.delimiter);\n\n if (options.strip_insignificant_zeros && precision) {\n precision = precision.replace(/0+$/, \"\");\n }\n\n if (options.precision > 0 && precision) {\n formattedNumber += options.separator + precision;\n }\n\n if (options.sign_first) {\n format = \"%s\" + format;\n }\n else {\n format = format.replace(\"%n\", \"%s%n\");\n }\n\n formattedNumber = format\n .replace(\"%u\", options.unit)\n .replace(\"%n\", formattedNumber)\n .replace(\"%s\", sign)\n ;\n\n return formattedNumber;\n };\n\n // Format currency with localization rules.\n // The options will be retrieved from the `number.currency.format` and\n // `number.format` scopes, in that order.\n //\n // Any missing option will be retrieved from the `I18n.toNumber` defaults and\n // the following options:\n //\n // - `unit`: `\"$\"`\n // - `precision`: `2`\n // - `format`: `\"%u%n\"`\n // - `delimiter`: `\",\"`\n // - `separator`: `\".\"`\n //\n // You can also override these options by providing the `options` argument.\n //\n I18n.toCurrency = function(number, options) {\n options = this.prepareOptions(\n options\n , this.lookup(\"number.currency.format\")\n , this.lookup(\"number.format\")\n , CURRENCY_FORMAT\n );\n\n return this.toNumber(number, options);\n };\n\n // Localize several values.\n // You can provide the following scopes: `currency`, `number`, or `percentage`.\n // If you provide a scope that matches the `/^(date|time)/` regular expression\n // then the `value` will be converted by using the `I18n.toTime` function.\n //\n // It will default to the value's `toString` function.\n //\n I18n.localize = function(scope, value, options) {\n options || (options = {});\n\n switch (scope) {\n case \"currency\":\n return this.toCurrency(value);\n case \"number\":\n scope = this.lookup(\"number.format\");\n return this.toNumber(value, scope);\n case \"percentage\":\n return this.toPercentage(value);\n default:\n var localizedValue;\n\n if (scope.match(/^(date|time)/)) {\n localizedValue = this.toTime(scope, value);\n } else {\n localizedValue = value.toString();\n }\n\n return this.interpolate(localizedValue, options);\n }\n };\n\n // Parse a given `date` string into a JavaScript Date object.\n // This function is time zone aware.\n //\n // The following string formats are recognized:\n //\n // yyyy-mm-dd\n // yyyy-mm-dd[ T]hh:mm::ss\n // yyyy-mm-dd[ T]hh:mm::ss\n // yyyy-mm-dd[ T]hh:mm::ssZ\n // yyyy-mm-dd[ T]hh:mm::ss+0000\n // yyyy-mm-dd[ T]hh:mm::ss+00:00\n // yyyy-mm-dd[ T]hh:mm::ss.123Z\n //\n I18n.parseDate = function(date) {\n var matches, convertedDate, fraction;\n // we have a date, so just return it.\n if (typeof(date) == \"object\") {\n return date;\n };\n\n matches = date.toString().match(/(\\d{4})-(\\d{2})-(\\d{2})(?:[ T](\\d{2}):(\\d{2}):(\\d{2})([\\.,]\\d{1,3})?)?(Z|\\+00:?00)?/);\n\n if (matches) {\n for (var i = 1; i <= 6; i++) {\n matches[i] = parseInt(matches[i], 10) || 0;\n }\n\n // month starts on 0\n matches[2] -= 1;\n\n fraction = matches[7] ? 1000 * (\"0\" + matches[7]) : null;\n\n if (matches[8]) {\n convertedDate = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], fraction));\n } else {\n convertedDate = new Date(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], fraction);\n }\n } else if (typeof(date) == \"number\") {\n // UNIX timestamp\n convertedDate = new Date();\n convertedDate.setTime(date);\n } else if (date.match(/([A-Z][a-z]{2}) ([A-Z][a-z]{2}) (\\d+) (\\d+:\\d+:\\d+) ([+-]\\d+) (\\d+)/)) {\n // This format `Wed Jul 20 13:03:39 +0000 2011` is parsed by\n // webkit/firefox, but not by IE, so we must parse it manually.\n convertedDate = new Date();\n convertedDate.setTime(Date.parse([\n RegExp.$1, RegExp.$2, RegExp.$3, RegExp.$6, RegExp.$4, RegExp.$5\n ].join(\" \")));\n } else if (date.match(/\\d+ \\d+:\\d+:\\d+ [+-]\\d+ \\d+/)) {\n // a valid javascript format with timezone info\n convertedDate = new Date();\n convertedDate.setTime(Date.parse(date));\n } else {\n // an arbitrary javascript string\n convertedDate = new Date();\n convertedDate.setTime(Date.parse(date));\n }\n\n return convertedDate;\n };\n\n // Formats time according to the directives in the given format string.\n // The directives begins with a percent (%) character. Any text not listed as a\n // directive will be passed through to the output string.\n //\n // The accepted formats are:\n //\n // %a - The abbreviated weekday name (Sun)\n // %A - The full weekday name (Sunday)\n // %b - The abbreviated month name (Jan)\n // %B - The full month name (January)\n // %c - The preferred local date and time representation\n // %d - Day of the month (01..31)\n // %-d - Day of the month (1..31)\n // %H - Hour of the day, 24-hour clock (00..23)\n // %-H - Hour of the day, 24-hour clock (0..23)\n // %I - Hour of the day, 12-hour clock (01..12)\n // %-I - Hour of the day, 12-hour clock (1..12)\n // %m - Month of the year (01..12)\n // %-m - Month of the year (1..12)\n // %M - Minute of the hour (00..59)\n // %-M - Minute of the hour (0..59)\n // %p - Meridian indicator (AM or PM)\n // %S - Second of the minute (00..60)\n // %-S - Second of the minute (0..60)\n // %w - Day of the week (Sunday is 0, 0..6)\n // %y - Year without a century (00..99)\n // %-y - Year without a century (0..99)\n // %Y - Year with century\n // %z - Timezone offset (+0545)\n //\n I18n.strftime = function(date, format) {\n var options = this.lookup(\"date\")\n , meridianOptions = I18n.meridian()\n ;\n\n if (!options) {\n options = {};\n }\n\n options = this.prepareOptions(options, DATE);\n\n if (isNaN(date.getTime())) {\n throw new Error('I18n.strftime() requires a valid date object, but received an invalid date.');\n }\n\n var weekDay = date.getDay()\n , day = date.getDate()\n , year = date.getFullYear()\n , month = date.getMonth() + 1\n , hour = date.getHours()\n , hour12 = hour\n , meridian = hour > 11 ? 1 : 0\n , secs = date.getSeconds()\n , mins = date.getMinutes()\n , offset = date.getTimezoneOffset()\n , absOffsetHours = Math.floor(Math.abs(offset / 60))\n , absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60)\n , timezoneoffset = (offset > 0 ? \"-\" : \"+\") +\n (absOffsetHours.toString().length < 2 ? \"0\" + absOffsetHours : absOffsetHours) +\n (absOffsetMinutes.toString().length < 2 ? \"0\" + absOffsetMinutes : absOffsetMinutes)\n ;\n\n if (hour12 > 12) {\n hour12 = hour12 - 12;\n } else if (hour12 === 0) {\n hour12 = 12;\n }\n\n format = format.replace(\"%a\", options.abbr_day_names[weekDay]);\n format = format.replace(\"%A\", options.day_names[weekDay]);\n format = format.replace(\"%b\", options.abbr_month_names[month]);\n format = format.replace(\"%B\", options.month_names[month]);\n format = format.replace(\"%d\", padding(day));\n format = format.replace(\"%e\", day);\n format = format.replace(\"%-d\", day);\n format = format.replace(\"%H\", padding(hour));\n format = format.replace(\"%-H\", hour);\n format = format.replace(\"%I\", padding(hour12));\n format = format.replace(\"%-I\", hour12);\n format = format.replace(\"%m\", padding(month));\n format = format.replace(\"%-m\", month);\n format = format.replace(\"%M\", padding(mins));\n format = format.replace(\"%-M\", mins);\n format = format.replace(\"%p\", meridianOptions[meridian]);\n format = format.replace(\"%S\", padding(secs));\n format = format.replace(\"%-S\", secs);\n format = format.replace(\"%w\", weekDay);\n format = format.replace(\"%y\", padding(year));\n format = format.replace(\"%-y\", padding(year).replace(/^0+/, \"\"));\n format = format.replace(\"%Y\", year);\n format = format.replace(\"%z\", timezoneoffset);\n\n return format;\n };\n\n // Convert the given dateString into a formatted date.\n I18n.toTime = function(scope, dateString) {\n var date = this.parseDate(dateString)\n , format = this.lookup(scope)\n ;\n\n if (date.toString().match(/invalid/i)) {\n return date.toString();\n }\n\n if (!format) {\n return date.toString();\n }\n\n return this.strftime(date, format);\n };\n\n // Convert a number into a formatted percentage value.\n I18n.toPercentage = function(number, options) {\n options = this.prepareOptions(\n options\n , this.lookup(\"number.percentage.format\")\n , this.lookup(\"number.format\")\n , PERCENTAGE_FORMAT\n );\n\n return this.toNumber(number, options);\n };\n\n // Convert a number into a readable size representation.\n I18n.toHumanSize = function(number, options) {\n var kb = 1024\n , size = number\n , iterations = 0\n , unit\n , precision\n ;\n\n while (size >= kb && iterations < 4) {\n size = size / kb;\n iterations += 1;\n }\n\n if (iterations === 0) {\n unit = this.t(\"number.human.storage_units.units.byte\", {count: size});\n precision = 0;\n } else {\n unit = this.t(\"number.human.storage_units.units.\" + SIZE_UNITS[iterations]);\n precision = (size - Math.floor(size) === 0) ? 0 : 1;\n }\n\n options = this.prepareOptions(\n options\n , {unit: unit, precision: precision, format: \"%n%u\", delimiter: \"\"}\n );\n\n return this.toNumber(size, options);\n };\n\n I18n.getFullScope = function(scope, options) {\n options = options || {}\n\n // Deal with the scope as an array.\n if (isArray(scope)) {\n scope = scope.join(this.defaultSeparator);\n }\n\n // Deal with the scope option provided through the second argument.\n //\n // I18n.t('hello', {scope: 'greetings'});\n //\n if (options.scope) {\n scope = [options.scope, scope].join(this.defaultSeparator);\n }\n\n return scope;\n };\n /**\n * Merge obj1 with obj2 (shallow merge), without modifying inputs\n * @param {Object} obj1\n * @param {Object} obj2\n * @returns {Object} Merged values of obj1 and obj2\n *\n * In order to support ES3, `Object.prototype.hasOwnProperty.call` is used\n * Idea is from:\n * https://stackoverflow.com/questions/8157700/object-has-no-hasownproperty-method-i-e-its-undefined-ie8\n */\n I18n.extend = function ( obj1, obj2 ) {\n if (typeof(obj1) === \"undefined\" && typeof(obj2) === \"undefined\") {\n return {};\n }\n return merge(obj1, obj2);\n };\n\n // Set aliases, so we can save some typing.\n I18n.t = I18n.translate;\n I18n.l = I18n.localize;\n I18n.p = I18n.pluralize;\n\n return I18n;\n}));\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output} from \"@angular/core\";\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {CardViewOrientation} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {distinctUntilChanged, takeUntil} from \"rxjs/operators\";\nimport {HighlightingMode} from \"core-components/wp-fast-table/builders/highlighting/highlighting-mode.const\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {DragAndDropService} from \"core-app/modules/common/drag-and-drop/drag-and-drop.service\";\nimport {WorkPackageCardDragAndDropService} from \"core-components/wp-card-view/services/wp-card-drag-and-drop.service\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {WorkPackageTableConfiguration} from \"core-components/wp-table/wp-table-configuration\";\nimport {WorkPackageViewOutputs} from \"core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry\";\n\n@Component({\n selector: 'wp-grid',\n template: `\n \n \n\n
    \n \n
    \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n DragAndDropService,\n WorkPackageCardDragAndDropService\n ]\n})\nexport class WorkPackagesGridComponent implements WorkPackageViewOutputs {\n @Input() public configuration:WorkPackageTableConfiguration;\n @Input() public showResizer:boolean = false;\n @Input() public resizerClass:string = '';\n @Input() public resizerStorageKey:string = '';\n\n @Output() selectionChanged = new EventEmitter();\n @Output() itemClicked = new EventEmitter<{ workPackageId:string, double:boolean }>();\n @Output() stateLinkClicked = new EventEmitter<{ workPackageId:string, requestedState:string }>();\n\n public canDragOutOf:() => boolean;\n public dragInto:boolean;\n public gridOrientation:CardViewOrientation = 'horizontal';\n public highlightingMode:HighlightingMode = 'none';\n\n constructor(readonly wpTableHighlight:WorkPackageViewHighlightingService,\n readonly wpTableSortBy:WorkPackageViewSortByService,\n readonly wpList:WorkPackagesListService,\n readonly querySpace:IsolatedQuerySpace,\n readonly cdRef:ChangeDetectorRef) {\n }\n\n ngOnInit() {\n this.dragInto = this.configuration.dragAndDropEnabled;\n this.canDragOutOf = () => {\n return this.configuration.dragAndDropEnabled;\n };\n\n this.wpTableHighlight\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n distinctUntilChanged()\n )\n .subscribe(() => {\n this.highlightingMode = this.wpTableHighlight.current.mode;\n this.cdRef.detectChanges();\n });\n\n }\n\n public switchToManualSorting() {\n let query = this.querySpace.query.value;\n if (query && this.wpTableSortBy.switchToManualSorting(query)) {\n this.wpList.save(query);\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ViewEncapsulation\n} from '@angular/core';\nimport {WorkPackageViewFiltersService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service';\nimport {WorkPackageFiltersService} from 'core-components/filters/wp-filters/wp-filters.service';\nimport {DebouncedEventEmitter} from \"core-components/angular/debounced-event-emitter\";\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {Observable} from \"rxjs\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\n@Component({\n templateUrl: './filter-container.directive.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'filter-container'\n})\nexport class WorkPackageFilterContainerComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n @Input('showFilterButton') showFilterButton:boolean = false;\n @Input('filterButtonText') filterButtonText:string = I18n.t('js.button_filter');\n @Output() public filtersChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n public visible$:Observable;\n public filters = this.wpTableFilters.current;\n public loaded = false;\n\n constructor(readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly cdRef:ChangeDetectorRef,\n readonly wpFiltersService:WorkPackageFiltersService) {\n super();\n this.visible$ = this.wpFiltersService.observeUntil(componentDestroyed(this));\n }\n\n ngOnInit():void {\n this.wpTableFilters\n .pristine$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.filters = this.wpTableFilters.current;\n this.loaded = true;\n this.cdRef.detectChanges();\n });\n }\n\n public replaceIfComplete(filters:QueryFilterInstanceResource[]) {\n let available = filters.filter(el => this.wpTableFilters.isAvailable(el));\n this.wpTableFilters.replaceIfComplete(available);\n this.filtersChanged.emit(available);\n }\n}\n","\n\n
    \n
    \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, Component, ElementRef, EventEmitter, Input, OnDestroy, Output, ViewChild} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {DatePicker} from \"core-app/modules/common/op-date-picker/datepicker\";\nimport {DebouncedEventEmitter} from \"core-components/angular/debounced-event-emitter\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {keyCodes} from \"core-app/modules/common/keyCodes.enum\";\nimport {Instance} from \"flatpickr/dist/types/instance\";\n\n@Component({\n selector: 'op-date-picker',\n templateUrl: './op-date-picker.component.html'\n})\nexport class OpDatePickerComponent extends UntilDestroyedMixin implements OnDestroy, AfterViewInit {\n @Output() public onChange = new DebouncedEventEmitter(componentDestroyed(this));\n @Output() public onCancel = new EventEmitter();\n\n @Input() public initialDate:string = '';\n @Input() public appendTo?:HTMLElement = document.body;\n @Input() public classes:string = '';\n @Input() public id:string = '';\n @Input() public name:string = '';\n @Input() public required:boolean = false;\n @Input() public size:number = 20;\n @Input() public focus:boolean = false;\n @Input() public disabled:boolean = false;\n\n @ViewChild('dateInput') dateInput:ElementRef;\n\n private datePickerInstance:DatePicker;\n\n public constructor(private elementRef:ElementRef,\n private ConfigurationService:ConfigurationService,\n private timezoneService:TimezoneService) {\n super();\n\n if (!this.id) {\n this.id = 'datepicker-input-' + Math.floor(Math.random() * 1000).toString(3);\n }\n }\n\n ngAfterViewInit():void {\n this.initializeDatepicker();\n }\n\n ngOnDestroy() {\n this.datePickerInstance && this.datePickerInstance.destroy();\n }\n\n openOnClick() {\n if (!this.disabled) {\n this.datePickerInstance.show();\n }\n }\n\n onInputChange(_event:KeyboardEvent) {\n if (this.isEmpty()) {\n this.datePickerInstance.clear();\n } else if (this.inputIsValidDate()) {\n this.onChange.emit(this.currentValue);\n }\n }\n\n closeOnOutsideClick(event:any) {\n if (!(event.relatedTarget &&\n this.datePickerInstance.datepickerInstance.calendarContainer.contains(event.relatedTarget))) {\n this.datePickerInstance.hide();\n }\n }\n\n private isEmpty():boolean {\n return this.currentValue.trim() === '';\n }\n\n private get currentValue():string {\n return this.inputElement?.value || '';\n }\n\n private get inputElement():HTMLInputElement {\n return this.dateInput.nativeElement;\n }\n\n private inputIsValidDate():boolean {\n return this.currentValue.match(/\\d{4}-\\d{2}-\\d{2}/) !== null;\n }\n\n private initializeDatepicker() {\n let options:any = {\n allowInput: true,\n appendTo: this.appendTo,\n onChange:(selectedDates:Date[], dateStr:string) => {\n let val:string = dateStr;\n\n if (this.isEmpty()) {\n return;\n }\n\n this.inputElement.value = val;\n this.onChange.emit(val);\n },\n onKeyDown: (selectedDates:Date[], dateStr:string, instance:Instance, data:KeyboardEvent) => {\n if (data.which == keyCodes.ESCAPE) {\n this.onCancel.emit();\n }\n }\n };\n\n let initialValue;\n if (this.isEmpty && this.initialDate) {\n initialValue = this.timezoneService.parseISODate(this.initialDate).toDate();\n } else {\n initialValue = this.currentValue;\n }\n\n this.datePickerInstance = new DatePicker(\n '#' + this.id,\n initialValue,\n options\n );\n }\n}\n","\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {InputState} from 'reactivestates';\n\nexport class StatusResource extends HalResource {\n\n isClosed:boolean;\n isDefault:boolean;\n\n public get state():InputState {\n return this.states.statuses.get(this.href as string) as any;\n }\n}\n\n","import {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable, OnDestroy} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from 'core-components/states.service';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\nimport {WorkPackageViewBaseService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\n\nexport interface WorkPackageViewSelectionState {\n // Map of selected rows\n selected:{ [workPackageId:string]:boolean };\n // Index of current selection\n // required for shift-offsets\n activeRowIndex:number|null;\n}\n\n@Injectable()\nexport class WorkPackageViewSelectionService extends WorkPackageViewBaseService implements OnDestroy {\n\n public constructor(readonly querySpace:IsolatedQuerySpace,\n readonly states:States,\n readonly opContextMenu:OPContextMenuService) {\n super(querySpace);\n this.reset();\n }\n\n ngOnDestroy():void {\n Mousetrap.unbind(['command+d', 'ctrl+d']);\n Mousetrap.unbind(['command+a', 'ctrl+a']);\n }\n\n public initializeSelection(selectedWorkPackageIds:string[]) {\n let state:WorkPackageViewSelectionState = {\n selected: {},\n activeRowIndex: null\n };\n\n selectedWorkPackageIds.forEach(id => state.selected[id] = true);\n\n this.updatesState.clear();\n this.pristineState.putValue(state);\n }\n\n public isSelected(workPackageId:string):boolean {\n return !!this.current?.selected[workPackageId];\n }\n\n /**\n * Select all work packages\n */\n public selectAll(rows:RenderedWorkPackage[]) {\n const state:WorkPackageViewSelectionState = this._emptyState;\n\n rows.forEach((row) => {\n if (row.workPackageId) {\n state.selected[row.workPackageId] = true;\n }\n });\n\n this.update(state);\n }\n\n /**\n * Get the current work package resource form the selection state.\n */\n public getSelectedWorkPackages():WorkPackageResource[] {\n let wpState = this.states.workPackages;\n return this.getSelectedWorkPackageIds().map(id => wpState.get(id).value!);\n }\n\n public getSelectedWorkPackageIds():string[] {\n let selected:string[] = [];\n\n _.each(this.current?.selected, (isSelected:boolean, wpId:string) => {\n if (isSelected) {\n selected.push(wpId);\n }\n });\n\n return selected;\n }\n\n /**\n * Reset the selection state to an empty selection\n */\n public reset() {\n this.update(this._emptyState);\n }\n\n public get isEmpty() {\n return this.selectionCount === 0;\n }\n\n /**\n * Return the number of selected rows.\n */\n public get selectionCount():number {\n return _.size(this.current?.selected);\n }\n\n /**\n * Toggle a single row selection state and update the state.\n * @param workPackageId\n */\n public toggleRow(workPackageId:string) {\n let isSelected = this.current?.selected[workPackageId];\n this.setRowState(workPackageId, !isSelected);\n }\n\n /**\n * Force the given work package's selection state. Does not modify other states.\n * @param workPackageId\n * @param newState\n */\n public setRowState(workPackageId:string, newState:boolean) {\n let state = this.current || this._emptyState;\n state.selected[workPackageId] = newState;\n this.update(state);\n }\n\n /**\n * Override current selection with the given work package id.\n */\n public setSelection(wpId:string, position:number) {\n const current = this._emptyState;\n current.selected[wpId] = true;\n current.activeRowIndex = position;\n\n this.update(current);\n }\n\n /**\n * Select a number of rows from the current `activeRowIndex`\n * to the selected target.\n * (aka shift click expansion)\n */\n public setMultiSelectionFrom(rows:RenderedWorkPackage[], wpId:string, position:number) {\n let state = this.current || this._emptyState;\n\n // If there are no other selections, it does not matter what the index is\n if (this.selectionCount === 0 || state.activeRowIndex === null) {\n state.selected[wpId] = true;\n state.activeRowIndex = position;\n } else {\n let start = Math.min(position, state.activeRowIndex);\n let end = Math.max(position, state.activeRowIndex);\n\n rows.forEach((row, i) => {\n if (row.workPackageId) {\n state.selected[row.workPackageId] = i >= start && i <= end;\n }\n });\n }\n\n this.update(state);\n }\n\n public registerSelectAllListener(renderedElements:() => RenderedWorkPackage[]) {\n // Bind CTRL+A to select all work packages\n Mousetrap.bind(['command+a', 'ctrl+a'], (e) => {\n this.selectAll(renderedElements());\n e.preventDefault();\n\n this.opContextMenu.close();\n return false;\n });\n }\n\n public registerDeselectAllListener() {\n // Bind CTRL+D to deselect all work packages\n Mousetrap.bind(['command+d', 'ctrl+d'], (e) => {\n this.reset();\n e.preventDefault();\n\n this.opContextMenu.close();\n return false;\n });\n }\n\n private get _emptyState():WorkPackageViewSelectionState {\n return {\n selected: {},\n activeRowIndex: null\n };\n }\n\n valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource):WorkPackageViewSelectionState|undefined {\n return undefined;\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, Component, ElementRef, Input, OnInit, ChangeDetectionStrategy} from '@angular/core';\nimport {debounceTime, distinctUntilChanged} from 'rxjs/operators';\nimport {TransitionService} from '@uirouter/core';\nimport {MainMenuToggleService} from \"core-components/main-menu/main-menu-toggle.service\";\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {ResizeDelta} from \"core-app/modules/common/resizer/resizer.component\";\nimport {fromEvent} from \"rxjs\";\n\n@Component({\n selector: 'wp-resizer',\n template: `\n \n \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n\nexport class WpResizerDirective extends UntilDestroyedMixin implements OnInit, AfterViewInit {\n @Input() elementClass:string;\n @Input() resizeEvent:string;\n @Input() localStorageKey:string;\n @Input() resizeStyle:'flexBasis'|'width' = 'flexBasis';\n\n private resizingElement:HTMLElement;\n private elementWidth:number;\n private element:HTMLElement;\n private resizer:HTMLElement;\n // Min-width this element is allowed to have\n private elementMinWidth = 530;\n\n public moving:boolean = false;\n public resizerClass = 'work-packages--resizer icon-resizer-vertical-lines';\n\n constructor(readonly toggleService:MainMenuToggleService,\n private elementRef:ElementRef,\n readonly $transitions:TransitionService,\n readonly browserDetector:BrowserDetector) {\n super();\n }\n\n ngOnInit() {\n // Get element\n this.resizingElement = document.getElementsByClassName(this.elementClass)[0];\n\n // Get initial width from local storage and apply\n let localStorageValue = this.parseLocalStorageValue();\n this.elementWidth = localStorageValue ||\n (this.resizingElement.offsetWidth < this.elementMinWidth ?\n this.elementMinWidth :\n this.resizingElement.offsetWidth);\n\n // This case only happens when the timeline is loaded but not displayed.\n // Therefor the flexbasis will be set to 50%, just in px\n if (this.elementWidth === 0 && this.resizingElement.parentElement) {\n this.elementWidth = this.resizingElement.parentElement.offsetWidth / 2;\n }\n\n this.resizingElement.style[this.resizeStyle] = this.elementWidth + 'px';\n\n // Add event listener\n this.element = this.elementRef.nativeElement;\n\n // Listen on sidebar changes and toggle column layout, if necessary\n this.toggleService.changeData$\n .pipe(\n distinctUntilChanged(),\n this.untilDestroyed()\n )\n .subscribe(changeData => {\n this.toggleFullscreenColumns();\n });\n\n // Listen to event\n fromEvent(window, 'resize', { passive: true })\n .pipe(\n this.untilDestroyed(),\n debounceTime(250)\n )\n .subscribe(() => this.toggleFullscreenColumns());\n }\n\n ngAfterViewInit():void {\n // Get the reziser\n this.resizer = this.elementRef.nativeElement.getElementsByClassName(this.resizerClass)[0];\n\n this.applyColumnLayout(this.resizingElement, this.elementWidth);\n }\n\n ngOnDestroy() {\n super.ngOnDestroy();\n // Reset the style when killing this directive, otherwise the style remains\n this.resizingElement.style[this.resizeStyle] = '';\n }\n\n resizeStart() {\n // In case we dragged the resizer farther than the element can actually grow,\n // we reset it to the actual width at the start of the new resizing\n let localStorageValue = this.parseLocalStorageValue();\n let actualElementWidth = this.resizingElement.offsetWidth;\n if (localStorageValue && localStorageValue > actualElementWidth) {\n this.elementWidth = actualElementWidth;\n }\n }\n\n resizeEnd() {\n let localStorageValue = this.parseLocalStorageValue();\n if (localStorageValue) {\n this.elementWidth = localStorageValue;\n }\n\n // Send a event that we resized this element\n const event = new Event(this.resizeEvent);\n window.dispatchEvent(event);\n\n this.manageErrorClass(false);\n }\n\n resizeMove(deltas:ResizeDelta) {\n // Get new value depending on the delta\n this.elementWidth = this.elementWidth - deltas.relative.x;\n let newValue;\n\n // The resizingElement is not allowed to be smaller than the elementMinWidth\n if (this.elementWidth < this.elementMinWidth) {\n newValue = this.elementMinWidth;\n\n // Show the resizer red when it reaches its limit (min-width)\n this.manageErrorClass(true);\n } else {\n newValue = this.elementWidth;\n\n this.manageErrorClass(false);\n }\n\n // Store item in local storage\n window.OpenProject.guardedLocalStorage(this.localStorageKey, `${newValue}`);\n\n // Apply two column layout\n this.applyColumnLayout(this.resizingElement, newValue);\n\n // Set new width\n this.resizingElement.style[this.resizeStyle] = newValue + 'px';\n }\n\n private parseLocalStorageValue():number|undefined {\n let localStorageValue = window.OpenProject.guardedLocalStorage(this.localStorageKey);\n let number = parseInt(localStorageValue || '', 10);\n\n if (typeof number === 'number' && number !== NaN) {\n return number;\n }\n\n return undefined;\n }\n\n private applyColumnLayout(element:HTMLElement, newWidth:number) {\n // Apply two column layout in fullscreen view of a workpackage\n if (element === jQuery('.work-packages-full-view--split-right')[0]) {\n this.toggleFullscreenColumns();\n }\n // Apply two column layout when details view of wp is open\n else {\n this.toggleColumns(element, 700);\n }\n }\n\n private toggleColumns(element:HTMLElement, checkWidth:number = 750) {\n // Disable two column layout for MS Edge (#29941)\n if (element && !this.browserDetector.isEdge) {\n jQuery(element).toggleClass('-can-have-columns', element.offsetWidth > checkWidth);\n }\n }\n\n private toggleFullscreenColumns() {\n let fullScreenLeftView = jQuery('.work-packages-full-view--split-left')[0];\n this.toggleColumns(fullScreenLeftView);\n }\n\n private manageErrorClass(shouldBePresent:boolean) {\n   if (shouldBePresent && !this.resizer.classList.contains('-error-font')) {\n    this.resizer.classList.add('-error-font');\n   }\n\n if (!shouldBePresent && this.resizer.classList.contains('-error-font')) {\n this.resizer.classList.remove('-error-font');\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageRelationsHierarchyService} from \"core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service\";\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WpRelationInlineCreateServiceInterface} from \"core-components/wp-relations/embedded/wp-relation-inline-create.service.interface\";\nimport {WpRelationInlineAddExistingComponent} from \"core-components/wp-relations/embedded/inline/add-existing/wp-relation-inline-add-existing.component\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Injectable()\nexport class WpChildrenInlineCreateService extends WorkPackageInlineCreateService implements WpRelationInlineCreateServiceInterface {\n\n constructor(readonly injector:Injector,\n protected readonly wpRelationsHierarchyService:WorkPackageRelationsHierarchyService,\n protected readonly schemaCache:SchemaCacheService) {\n super(injector);\n }\n\n /**\n * A separate reference pane for the inline create component\n */\n public readonly referenceComponentClass = WpRelationInlineAddExistingComponent;\n\n /**\n * Define the reference type\n */\n public relationType:string = 'children';\n\n /**\n * Add a new relation of the above type\n */\n public add(from:WorkPackageResource, toId:string):Promise {\n return this.wpRelationsHierarchyService.addExistingChildWp(from, toId);\n }\n\n /**\n * Remove a given relation\n */\n public remove(from:WorkPackageResource, to:WorkPackageResource):Promise {\n return this.wpRelationsHierarchyService.removeChild(to);\n }\n\n /**\n * A related work package for the inline create context\n */\n public referenceTarget:WorkPackageResource|null = null;\n\n public get canAdd() {\n return !!(this.referenceTarget && this.canCreateWorkPackages && this.canAddChild);\n }\n\n public get canReference() {\n return !!(this.referenceTarget && this.canAddChild);\n }\n\n public get canAddChild() {\n return this.schema && !this.schema.isMilestone && this.referenceTarget!.changeParent;\n }\n\n /**\n * Reference button text\n */\n public readonly buttonTexts = {\n reference: this.I18n.t('js.relation_buttons.add_existing_child'),\n create: this.I18n.t('js.relation_buttons.add_new_child')\n };\n\n private get schema() {\n return this.referenceTarget && this.schemaCache.of(this.referenceTarget);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {HttpEvent, HttpResponse} from \"@angular/common/http\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {from, Observable, of} from \"rxjs\";\nimport {share, switchMap} from \"rxjs/operators\";\nimport {OpenProjectFileUploadService, UploadBlob, UploadFile, UploadInProgress} from './op-file-upload.service';\n\ninterface PrepareUploadResult {\n url:string;\n form:FormData;\n response:any;\n}\n\n@Injectable()\nexport class OpenProjectDirectFileUploadService extends OpenProjectFileUploadService {\n /**\n * Upload a single file, get an UploadResult observable\n * @param {string} url\n * @param {UploadFile} file\n * @param {string} method\n */\n public uploadSingle(url:string, file:UploadFile|UploadBlob, method:string = 'post', responseType:'text'|'json' = 'text') {\n const observable = from(this.getDirectUploadFormFrom(url, file))\n .pipe(\n switchMap(this.uploadToExternal(file, method, responseType)),\n share()\n );\n\n return [file, observable] as UploadInProgress;\n }\n\n private uploadToExternal(file:UploadFile|UploadBlob, method:string, responseType:string):(result:PrepareUploadResult) => Observable> {\n return result => {\n result.form.append('file', file, file.customName || file.name);\n\n return this\n .http\n .request(\n method,\n result.url,\n {\n body: result.form,\n // Observe the response, not the body\n observe: 'events',\n // This is important as the CORS policy for the bucket is * and you can't use credentals then,\n // besides we don't need them here anyway.\n withCredentials: false,\n responseType: responseType as any,\n // Subscribe to progress events. subscribe() will fire multiple times!\n reportProgress: true\n }\n )\n .pipe(switchMap(this.finishUpload(result)));\n };\n }\n\n private finishUpload(result:PrepareUploadResult):(result:HttpEvent) => Observable> {\n return event => {\n if (event instanceof HttpResponse) {\n return this\n .http\n .get(\n result.response._links.completeUpload.href,\n {\n observe: 'response'\n }\n );\n }\n\n // Return as new observable due to switchMap\n return of(event);\n };\n }\n\n public getDirectUploadFormFrom(url:string, file:UploadFile|UploadBlob):Promise {\n const formData = new FormData();\n const metadata = {\n description: file.description,\n fileName: file.customName || file.name,\n fileSize: file.size,\n contentType: file.type\n };\n\n /*\n * @TODO We could calculate the MD5 hash here too and pass that.\n * The MD5 hash can be used as the `content-md5` option during the upload to S3 for instance.\n * This way S3 can verify the integrity of the file which we currently don't do.\n */\n\n // add the metadata object\n formData.append(\n 'metadata',\n JSON.stringify(metadata),\n );\n\n const result = this\n .http\n .request(\n \"post\",\n url,\n {\n body: formData,\n withCredentials: true,\n responseType: \"json\" as any\n }\n )\n .toPromise()\n .then((res) => {\n let form = new FormData();\n\n _.each(res._links.addAttachment.form_fields, (value, key) => {\n form.append(key, value);\n });\n\n return { url: res._links.addAttachment.href, form: form, response: res };\n });\n\n return result;\n }\n}\n","import {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {CurrentUserService} from \"core-components/user/current-user.service\";\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injector} from '@angular/core';\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport compareByHrefOrString = AngularTrackingHelpers.compareByHrefOrString;\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\n\nexport class WorkPackageFilterValues {\n\n @InjectField() currentUser:CurrentUserService;\n @InjectField() halResourceService:HalResourceService;\n\n handlers:Partial void>> = {\n '=': this.applyFirstValue.bind(this),\n '!*': this.setToNull.bind(this)\n };\n\n constructor(public injector:Injector,\n private filters:QueryFilterInstanceResource[],\n private excluded:string[] = []) {\n\n }\n\n public applyDefaultsFromFilters(change:WorkPackageChangeset|Object) {\n _.each(this.filters, filter => {\n // Exclude filters specified in constructor\n if (this.excluded.indexOf(filter.id) !== -1) {\n return;\n }\n\n // Look for a handler with the filter's operator\n const operator = filter.operator.id as FilterOperator;\n const handler = this.handlers[operator];\n\n // Apply the filter if there is any\n handler?.call(this, change, filter);\n });\n }\n\n /**\n * Apply a positive value from a '=' [value] filter\n *\n * @param filter A positive '=' filter with at least one value\n * @private\n */\n private applyFirstValue(change:WorkPackageChangeset|{[id:string]:any}, filter:QueryFilterInstanceResource):void {\n // Avoid setting a value if current value is in filter list\n // and more than one value selected\n if (this.filterAlreadyApplied(change, filter)) {\n return;\n }\n\n // Select the first value\n let value = filter.values[0];\n\n // Avoid empty values\n if (value) {\n let attributeName = this.mapFilterToAttribute(filter);\n this.setValueFor(change, attributeName, value);\n }\n }\n\n /**\n * Set a value no null for a none type filter (!*)\n *\n * @param filter A none '!*' filter\n * @private\n */\n private setToNull(change:WorkPackageChangeset|{[id:string]:any}, filter:QueryFilterInstanceResource):void {\n let attributeName = this.mapFilterToAttribute(filter);\n\n this.setValue(change, attributeName,{ href: null });\n }\n\n private setValueFor(change:WorkPackageChangeset|Object, field:string, value:string|HalResource) {\n let newValue = this.findSpecialValue(value, field) || value;\n\n if (newValue) {\n this.setValue(change, field, newValue);\n }\n }\n\n private setValue(change:WorkPackageChangeset|{[id:string]:any}, field:string, value:any) {\n if (change instanceof WorkPackageChangeset) {\n change.setValue(field, value);\n } else {\n change[field] = value;\n }\n }\n\n /**\n * Returns special values for which no allowed values exist (e.g., parent ID in embedded queries)\n * @param {string | HalResource} value\n * @param {string} field\n */\n private findSpecialValue(value:string|HalResource, field:string):string|HalResource|undefined {\n if (field === 'parent') {\n return value;\n }\n\n if (value instanceof HalResource && value.$href === '/api/v3/users/me' && this.currentUser.isLoggedIn) {\n return this.halResourceService.fromSelfLink(`/api/v3/users/${this.currentUser.userId}`);\n }\n\n return undefined;\n }\n\n /**\n * Avoid applying filter values when\n * - more than one filter value selected\n * - changeset already matches one of the selected values\n * @param filter\n */\n private filterAlreadyApplied(change:WorkPackageChangeset|{[id:string]:any}, filter:any):boolean {\n // Only applicable if more than one selected\n if (filter.values.length <= 1) {\n return false;\n }\n\n const current = change instanceof WorkPackageChangeset ? change.projectedResource[filter.id] : change[filter.id];\n\n for (let i = 0; i < filter.values.length; i++) {\n if (compareByHrefOrString(current, filter.values[i])) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Some filter ids need to be mapped to a different attribute name\n * in order to be processed correctly.\n *\n * @param filter The filter to map\n * @returns An attribute name string to set\n * @private\n */\n private mapFilterToAttribute(filter:any):string {\n if (filter.id === 'onlySubproject') {\n return 'project';\n }\n\n // Default to returning the filter id\n return filter.id;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Inject, Injectable} from '@angular/core';\nimport {DOCUMENT} from \"@angular/common\";\n\n@Injectable({ providedIn: 'root' })\nexport class BannersService {\n\n private readonly _banners:boolean = true;\n\n constructor(@Inject(DOCUMENT) protected documentElement:Document) {\n this._banners = documentElement.body.classList.contains('ee-banners-visible');\n }\n\n public get eeShowBanners():boolean {\n return this._banners;\n }\n\n public conditional(bannersVisible?:() => void, bannersNotVisible?:() => void) {\n this._banners ? this.callMaybe(bannersVisible) : this.callMaybe(bannersNotVisible);\n }\n\n private callMaybe(func?:Function) {\n func && func();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Injector,\n OnInit,\n ElementRef,\n NgZone\n} from \"@angular/core\";\nimport {take} from \"rxjs/operators\";\nimport {CausedUpdatesService} from \"core-app/modules/boards/board/caused-updates/caused-updates.service\";\nimport {DragAndDropService} from \"core-app/modules/common/drag-and-drop/drag-and-drop.service\";\nimport {\n WorkPackageViewDisplayRepresentationService,\n wpDisplayCardRepresentation\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageTableConfigurationObject} from \"core-components/wp-table/wp-table-configuration\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {StateService} from \"@uirouter/core\";\nimport {KeepTabService} from \"core-components/wp-single-view-tabs/keep-tab/keep-tab.service\";\n\n@Component({\n selector: 'wp-list-view',\n templateUrl: './wp-list-view.component.html',\n styleUrls: ['./wp-list-view.component.sass'],\n host: { 'class': 'work-packages-split-view--tabletimeline-side' },\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n { provide: HalResourceNotificationService, useClass: WorkPackageNotificationService },\n DragAndDropService,\n CausedUpdatesService\n ]\n})\nexport class WorkPackageListViewComponent extends UntilDestroyedMixin implements OnInit {\n\n text = {\n 'jump_to_pagination': this.I18n.t('js.work_packages.jump_marks.pagination'),\n 'text_jump_to_pagination': this.I18n.t('js.work_packages.jump_marks.label_pagination'),\n 'button_settings': this.I18n.t('js.button_settings')\n };\n\n /** Switch between list and card view */\n showTableView:boolean = true;\n\n /** Determine when query is initially loaded */\n tableInformationLoaded = false;\n\n /** If loaded list of work packages is empty */\n noResults:boolean = false;\n\n /** Whether we should render a blocked view */\n showResultOverlay$ = this.wpViewFilters.incomplete$;\n\n /** */\n readonly wpTableConfiguration:WorkPackageTableConfigurationObject = {\n dragAndDropEnabled: true\n };\n\n constructor(readonly I18n:I18nService,\n readonly injector:Injector,\n readonly $state:StateService,\n readonly keepTab:KeepTabService,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpViewFilters:WorkPackageViewFiltersService,\n readonly deviceService:DeviceService,\n readonly CurrentProject:CurrentProjectService,\n readonly wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef,\n private ngZone:NgZone) {\n super();\n }\n\n ngOnInit() {\n // Mark tableInformationLoaded when initially loading done\n this.setupInformationLoadedListener();\n\n this.querySpace.query.values$().pipe(\n this.untilDestroyed()\n ).subscribe((query) => {\n // Update the visible representation\n this.updateViewRepresentation(query);\n this.noResults = query.results.total === 0;\n this.cdRef.detectChanges();\n });\n\n // Scroll into view the card/row that represents the last selected WorkPackage\n // so when the user opens a WP detail page on a split-view and then clicks on\n // the 'back button', the last selected card is visible on this list.\n // ngAfterViewInit doesn't find the .-checked elements on components\n // that inherit from this class (BcfListContainerComponent) so\n // opting for a timeout 'runOutsideAngular' to avoid running change\n // detection on the entire app\n this.ngZone.runOutsideAngular(() => {\n setTimeout(() => {\n const selectedRow = this.elementRef.nativeElement.querySelector('.wp-table--row.-checked');\n const selectedCard = this.elementRef.nativeElement.querySelector('.wp-card.-checked');\n\n // The header of the table hides the scrolledIntoView element\n // so we scrollIntoView the previous element, if any\n if (selectedRow && selectedRow.previousSibling) {\n selectedRow.previousSibling.scrollIntoView({block: \"start\"});\n }\n\n if (selectedCard) {\n selectedCard.scrollIntoView({block: \"start\"});\n }\n }, 0);\n });\n }\n\n protected setupInformationLoadedListener() {\n this\n .querySpace\n .initialized\n .values$()\n .pipe(take(1))\n .subscribe(() => {\n this.tableInformationLoaded = true;\n this.cdRef.detectChanges();\n });\n }\n\n public showResizerInCardView():boolean {\n return false;\n }\n\n protected updateViewRepresentation(query:QueryResource) {\n this.showTableView = !(this.deviceService.isMobile ||\n this.wpDisplayRepresentation.valueFromQuery(query) === wpDisplayCardRepresentation);\n }\n\n handleWorkPackageClicked(event:{ workPackageId:string; double:boolean }) {\n if (event.double) {\n this.openInFullView(event.workPackageId);\n }\n }\n\n openStateLink(event:{ workPackageId:string; requestedState:string }) {\n this.$state.go(\n (this.keepTab as any)[event.requestedState] || event.requestedState,\n { workPackageId: event.workPackageId, focus: true }\n );\n }\n\n /**\n * Special handling for clicking on cards.\n * If we are on mobile, a click on the card should directly open the full view\n */\n handleWorkPackageCardClicked(event:{ workPackageId:string; double:boolean }) {\n if (this.deviceService.isMobile) {\n this.openInFullView(event.workPackageId);\n } else {\n this.handleWorkPackageClicked(event);\n }\n }\n\n private openInFullView(workPackageId:string) {\n this.$state.go(\n 'work-packages.show',\n { workPackageId: workPackageId }\n );\n }\n}\n","
    \n\n\n\n\n\n\n
    \n \n \n
    \n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\n\n@Injectable()\nexport class HookService {\n private hooks:{[hook:string]:Function[]} = {};\n\n public register(id:string, callback:Function) {\n if (!callback) {\n return;\n }\n\n if (!this.hooks[id]) {\n this.hooks[id] = [];\n }\n\n this.hooks[id].push(callback);\n }\n\n public call(id:string, ...params:any[]):any[] {\n let results = [];\n\n if (this.hooks[id]) {\n for (let x = 0; x < this.hooks[id].length; x++) {\n let result = this.hooks[id][x](...params);\n\n if (result) {\n results.push(result);\n }\n }\n }\n\n return results;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n AfterViewInit,\n Component,\n} from '@angular/core';\nimport {CreateAutocompleterComponent} from \"core-app/modules/common/autocomplete/create-autocompleter.component\";\n\n@Component({\n templateUrl: './create-autocompleter.component.html',\n selector: 'wp-autocompleter'\n})\nexport class WorkPackageAutocompleterComponent extends CreateAutocompleterComponent implements AfterViewInit {\n}\n","\n \n : {{search}}\n \n \n
    {{ item.name }}
    \n
    \n
    ","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {input, InputState} from 'reactivestates';\nimport {take} from 'rxjs/operators';\n\nexport abstract class WorkPackageLinkedResourceCache {\n\n protected cacheDurationInSeconds = 120;\n\n // Cache activities for the last work package\n // to allow fast switching between work packages without refreshing.\n protected cache:{ id:string|null, state:InputState } = {\n id: null,\n state: input()\n };\n\n /**\n * Requires the linked resource for the given work package.\n * Caches a single value for subsequent requests for +cacheDurationInSeconds+ seconds.\n *\n * Whenever another work package's linked resource is requested, the cache is replaced.\n *\n * @param {WorkPackageResource} workPackage\n * @returns {Promise}\n */\n public require(workPackage:WorkPackageResource, force:boolean = false):Promise {\n const id = workPackage.id!;\n const state = this.cache.state;\n\n // Clear cache if requesting different resource\n if (force || this.cache.id !== id) {\n state.clear();\n }\n\n // Return cached value if id matches and value is present\n if (this.isCached(id)) {\n return Promise.resolve(state.value!);\n }\n\n // Ensure value is loaded only once\n this.cache.id = id;\n this.cache.state.putFromPromiseIfPristine(() => this.load(workPackage));\n\n return this.cache.state\n .values$()\n .pipe(take(1))\n .toPromise();\n }\n\n public clear(workPackageId:string|null) {\n if (this.cache.id === workPackageId) {\n this.cache.state.clear();\n }\n }\n\n /**\n * Return whether the given work package is cached.\n * @param {string} workPackageId\n * @returns {boolean}\n */\n public isCached(workPackageId:string) {\n const state = this.cache.state;\n return this.cache.id === workPackageId && state.hasValue() && !state.isValueOlderThan(this.cacheDurationInSeconds * 1000);\n }\n\n /**\n * Load the linked resource and return it as a promise\n * @param {WorkPackageResource} workPackage\n */\n protected abstract load(workPackage:WorkPackageResource):Promise;\n}\n","import {InjectionToken} from \"@angular/core\";\n\nexport const OpQueryConfigurationLocalsToken = new InjectionToken('OpQueryConfigurationLocalsToken');\n","
    \n
    \n \n \n
    \n\n \n \n \n\n
    \n
    \n
    \n\n
    \n \n
    \n\n\n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n Injector,\n Input,\n OnInit,\n Output,\n ViewChild\n} from \"@angular/core\";\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {QueryColumn} from \"app/components/wp-query/query-column\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WorkPackageCreateService} from \"core-components/wp-new/wp-create.service\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {CardHighlightingMode} from \"core-components/wp-fast-table/builders/highlighting/highlighting-mode.const\";\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {StateService} from \"@uirouter/core\";\nimport {States} from \"core-components/states.service\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {filter, map, withLatestFrom} from 'rxjs/operators';\nimport {CausedUpdatesService} from \"core-app/modules/boards/board/caused-updates/caused-updates.service\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {CardViewHandlerRegistry} from \"core-components/wp-card-view/event-handler/card-view-handler-registry\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {WorkPackageCardDragAndDropService} from \"core-components/wp-card-view/services/wp-card-drag-and-drop.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {\n WorkPackageViewHandlerToken,\n WorkPackageViewOutputs\n} from \"core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\n\nexport type CardViewOrientation = 'horizontal'|'vertical';\n\n@Component({\n selector: 'wp-card-view',\n styleUrls: ['./styles/wp-card-view.component.sass', './styles/wp-card-view-horizontal.sass', './styles/wp-card-view-vertical.sass'],\n templateUrl: './wp-card-view.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageCardViewComponent extends UntilDestroyedMixin implements OnInit, AfterViewInit, WorkPackageViewOutputs {\n @Input('dragOutOfHandler') public canDragOutOf:(wp:WorkPackageResource) => boolean;\n @Input() public dragInto:boolean;\n @Input() public highlightingMode:CardHighlightingMode;\n @Input() public workPackageAddedHandler:(wp:WorkPackageResource) => Promise;\n @Input() public showStatusButton:boolean = true;\n @Input() public showInfoButton:boolean = false;\n @Input() public orientation:CardViewOrientation = 'vertical';\n /** Whether cards are removable */\n @Input() public cardsRemovable:boolean = false;\n /** Whether a notification box shall be shown when there are no WP to display */\n @Input() public showEmptyResultsBox:boolean = false;\n /** Whether on special mobile version of the cards shall be shown */\n @Input() public shrinkOnMobile:boolean = false;\n\n /** Container reference */\n @ViewChild('container', { static: true }) public container:ElementRef;\n\n @Output() public onMoved = new EventEmitter();\n @Output() selectionChanged = new EventEmitter();\n @Output() itemClicked = new EventEmitter<{ workPackageId:string, double:boolean }>();\n @Output() stateLinkClicked = new EventEmitter<{ workPackageId:string, requestedState:string }>();\n\n public trackByHref = AngularTrackingHelpers.trackByHrefAndProperty('lockVersion');\n public query:QueryResource;\n public isResultEmpty:boolean = false;\n public columns:QueryColumn[];\n public text = {\n removeCard: this.I18n.t('js.card.remove_from_list'),\n addNewCard: this.I18n.t('js.card.add_new'),\n noResults: {\n title: this.I18n.t('js.work_packages.no_results.title'),\n description: this.I18n.t('js.work_packages.no_results.description')\n },\n };\n\n /** Inline create / reference properties */\n public canAdd = false;\n public canReference = false;\n public inReference = false;\n public referenceClass = this.wpInlineCreate.referenceComponentClass;\n // We need to mount a dynamic component into the view\n // but map the following output\n public referenceOutputs = {\n onCancel: () => this.setReferenceMode(false),\n onReferenced: (wp:WorkPackageResource) => this.cardDragDrop.addWorkPackageToQuery(wp, 0)\n };\n\n constructor(readonly querySpace:IsolatedQuerySpace,\n readonly states:States,\n readonly injector:Injector,\n readonly $state:StateService,\n readonly I18n:I18nService,\n readonly wpCreate:WorkPackageCreateService,\n readonly wpInlineCreate:WorkPackageInlineCreateService,\n readonly notificationService:WorkPackageNotificationService,\n readonly halEvents:HalEventsService,\n readonly authorisationService:AuthorisationService,\n readonly causedUpdates:CausedUpdatesService,\n readonly cdRef:ChangeDetectorRef,\n readonly pathHelper:PathHelperService,\n readonly wpTableSelection:WorkPackageViewSelectionService,\n readonly wpViewOrder:WorkPackageViewOrderService,\n readonly cardView:WorkPackageCardViewService,\n readonly cardDragDrop:WorkPackageCardDragAndDropService,\n readonly deviceService:DeviceService) {\n super();\n }\n\n ngOnInit() {\n this.registerCreationCallback();\n\n // Update permission on model updates\n this.authorisationService\n .observeUntil(componentDestroyed(this))\n .subscribe(() => {\n this.canAdd = this.wpInlineCreate.canAdd;\n this.canReference = this.wpInlineCreate.canReference;\n this.cdRef.detectChanges();\n });\n\n // Observe changes to the work packages in this view\n this.halEvents\n .aggregated$('WorkPackage')\n .pipe(\n map(events => events.filter(event => event.eventType === 'updated')),\n filter(events => {\n const wpIds:string[] = this.workPackages.map(el => el.id!.toString());\n return !!events.find(event => wpIds.indexOf(event.id) !== -1);\n })\n ).subscribe(() => {\n this.workPackages = this.workPackages.map(wp => this.states.workPackages.get(wp.id!).getValueOr(wp));\n this.cdRef.detectChanges();\n });\n\n this.querySpace.results\n .values$()\n .pipe(\n withLatestFrom(this.querySpace.query.values$()),\n this.untilDestroyed(),\n ).subscribe(([results, query]) => {\n this.query = query;\n this.workPackages = this.wpViewOrder.orderedWorkPackages();\n this.cardView.updateRenderedCardsValues(this.workPackages);\n this.isResultEmpty = this.workPackages.length === 0;\n this.cdRef.detectChanges();\n });\n }\n\n ngAfterViewInit() {\n this.cardDragDrop.init(this);\n\n // Register Drag & Drop only on desktop\n if (!this.deviceService.isMobile) {\n this.cardDragDrop.registerDragAndDrop();\n }\n\n // Register event handlers for the cards\n let registry = this.injector.get(WorkPackageViewHandlerToken, CardViewHandlerRegistry);\n if (registry instanceof CardViewHandlerRegistry) {\n registry.attachTo(this);\n } else {\n new registry(this.injector).attachTo(this);\n }\n this.wpTableSelection.registerSelectAllListener(() => {\n return this.cardView.renderedCards;\n });\n this.wpTableSelection.registerDeselectAllListener();\n }\n\n ngOnDestroy():void {\n super.ngOnDestroy();\n this.cardDragDrop.destroy();\n }\n\n public get workPackages():WorkPackageResource[] {\n return this.cardDragDrop.workPackages;\n }\n\n public set workPackages(workPackages:WorkPackageResource[]) {\n this.cardDragDrop.workPackages = workPackages;\n }\n\n public setReferenceMode(mode:boolean) {\n this.inReference = mode;\n this.cdRef.detectChanges();\n }\n\n public addNewCard() {\n this.cardDragDrop.addNewCard();\n }\n\n public removeCard(wp:WorkPackageResource) {\n this.cardDragDrop.removeCard(wp);\n }\n\n async onCardSaved(wp:WorkPackageResource) {\n await this.cardDragDrop.onCardSaved(wp);\n }\n\n public classes() {\n let classes = 'wp-cards-container ';\n classes += '-' + this.orientation;\n classes += this.shrinkOnMobile ? ' -shrink' : '';\n\n return classes;\n }\n\n /**\n * Listen to newly created work packages to detect whether the WP is the one we created,\n * and properly reset inline create in this case\n */\n private registerCreationCallback() {\n this.wpCreate\n .onNewWorkPackage()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(async (wp:WorkPackageResource) => {\n this.onCardSaved(wp);\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class CollectionResource extends HalResource {\n public elements:T[];\n public count:number;\n public total:number;\n public pageSize:number;\n public offset:number;\n\n /**\n * Update the collection's elements and return them in a promise.\n * This is useful, as angular does not recognize update made by $load.\n */\n public updateElements():Promise {\n if (this.$href) {\n return this.$load().then((collection:this) => this.elements = collection.elements);\n } else {\n return Promise.resolve();\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Inject} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WorkPackageInlineCreateComponent} from \"core-components/wp-inline-create/wp-inline-create.component\";\nimport {WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {WpRelationInlineCreateServiceInterface} from \"core-components/wp-relations/embedded/wp-relation-inline-create.service.interface\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {ApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\nimport {RelationResource} from \"core-app/modules/hal/resources/relation-resource\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './wp-relation-inline-add-existing.component.html'\n})\nexport class WpRelationInlineAddExistingComponent {\n public selectedWpId:string;\n public isDisabled = false;\n\n public queryFilters = this.buildQueryFilters();\n\n public text = {\n abort: this.I18n.t('js.relation_buttons.abort'),\n };\n\n constructor(protected readonly parent:WorkPackageInlineCreateComponent,\n @Inject(WorkPackageInlineCreateService) protected readonly wpInlineCreate:WpRelationInlineCreateServiceInterface,\n protected apiV3Service:APIV3Service,\n protected wpRelations:WorkPackageRelationsService,\n protected notificationService:WorkPackageNotificationService,\n protected halEvents:HalEventsService,\n protected urlParamsHelper:UrlParamsHelperService,\n protected querySpace:IsolatedQuerySpace,\n protected readonly I18n:I18nService) {\n }\n\n public addExisting() {\n if (_.isNil(this.selectedWpId)) {\n return;\n }\n\n const newRelationId = this.selectedWpId;\n this.isDisabled = true;\n\n this.wpInlineCreate.add(this.workPackage, newRelationId)\n .then(() => {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .refresh();\n\n this.halEvents.push(this.workPackage, {\n eventType: 'association',\n relatedWorkPackage: newRelationId,\n relationType: this.relationType,\n });\n\n this.isDisabled = false;\n this.wpInlineCreate.newInlineWorkPackageReferenced.next(newRelationId);\n this.cancel();\n })\n .catch((err:any) => {\n this.notificationService.handleRawError(err, this.workPackage);\n this.isDisabled = false;\n this.cancel();\n });\n }\n\n public onSelected(workPackage?:WorkPackageResource) {\n if (workPackage) {\n this.selectedWpId = workPackage.id!;\n this.addExisting();\n }\n }\n\n public get relationType() {\n return this.wpInlineCreate.relationType;\n }\n\n public get workPackage() {\n return this.wpInlineCreate.referenceTarget!;\n }\n\n public cancel() {\n this.parent.resetRow();\n }\n\n private buildQueryFilters():ApiV3Filter[] {\n const query = this.querySpace.query.value;\n\n if (!query) {\n return [];\n }\n\n const relationTypes = RelationResource.RELATION_TYPES(true);\n let filters = query.filters.filter(filter => {\n let id = this.urlParamsHelper.buildV3GetFilterIdFromFilter(filter);\n return relationTypes.indexOf(id) === -1;\n });\n\n return this.urlParamsHelper.buildV3GetFilters(filters);\n }\n}\n","
    \n
    \n
    \n \n \n
    \n
    \n \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\n@Injectable({ providedIn: 'root' })\nexport class HalResourceSortingService {\n\n /**\n * List of sortable properties by HAL type\n */\n private config:{ [typeName:string]:string } = {\n 'user': 'name',\n 'project': 'name'\n };\n\n constructor() {\n }\n\n /**\n * Sort the given HalResource based on its type.\n * If the type is not given, guess from the first element.\n *\n * @param {T[]} elements A collection of HalResources of type T\n * @param {string} type The HAL type of the collection\n * @returns {T[]} The sorted collection of HalResources\n */\n public sort(elements:T[], type?:string) {\n if (elements.length === 0) {\n return elements;\n }\n\n const halType = type || elements[0]._type;\n if (!halType) {\n return elements;\n }\n\n const property = this.sortingProperty(halType);\n if (property) {\n return _.sortBy(elements, v => v[property].toLowerCase());\n } else {\n return elements;\n }\n }\n\n /**\n * Transform the HAL type into the sorting property map.\n *\n * - Removes the leading multi identifier [] (e.g., from []User)\n * - Transforms to lowercase\n *\n * @param {string} type\n * @returns {string | undefined}\n */\n public sortingProperty(type:string):string | undefined {\n // Remove multi identifier and map to lowercase\n type = type\n .toLowerCase()\n .replace(/^\\[\\]/, '');\n\n return this.config[type];\n }\n\n public hasSortingProperty(type:string) {\n return this.sortingProperty(type) !== undefined;\n }\n\n}\n","import {ProjectResource} from 'core-app/modules/hal/resources/project-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {TypeResource} from 'core-app/modules/hal/resources/type-resource';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {input, InputState, multiInput, MultiInputState, StatesGroup} from 'reactivestates';\nimport {QueryColumn} from './wp-query/query-column';\nimport {PostResource} from 'core-app/modules/hal/resources/post-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {StatusResource} from \"core-app/modules/hal/resources/status-resource\";\nimport {QueryFilterInstanceSchemaResource} from \"core-app/modules/hal/resources/query-filter-instance-schema-resource\";\nimport {Subject} from \"rxjs\";\nimport {QuerySortByResource} from \"core-app/modules/hal/resources/query-sort-by-resource\";\nimport {QueryGroupByResource} from \"core-app/modules/hal/resources/query-group-by-resource\";\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {WorkPackageDisplayRepresentationValue} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\n\nexport class States extends StatesGroup {\n name = 'MainStore';\n\n /* /api/v3/projects */\n projects:MultiInputState = multiInput();\n\n /* /api/v3/work_packages */\n workPackages = multiInput();\n\n /* /api/v3/wiki_pages */\n posts = multiInput();\n\n /* /api/v3/schemas */\n schemas = multiInput();\n\n /* /api/v3/types */\n types = multiInput();\n\n /* /api/v3/statuses */\n statuses = multiInput();\n\n /* /api/v3/time_entries */\n timeEntries:MultiInputState = multiInput();\n\n /* /api/v3/versions */\n versions = multiInput();\n\n /* /api/v3/users */\n users = multiInput();\n\n // Work Package query states\n queries = new QueryAvailableDataStates();\n\n // Global events to isolated changes\n changes = new GlobalStateChanges();\n\n // Additional state map that can be dynamically registered.\n additional:{ [id:string]:MultiInputState } = {};\n\n forType(stateName:string):MultiInputState {\n let state = (this as any)[stateName] || this.additional[stateName];\n\n if (!state) {\n state = this.additional[stateName] = multiInput();\n }\n\n return state as any;\n }\n\n forResource(resource:T):InputState|undefined {\n const stateName = _.camelCase(resource._type) + 's';\n let state = this.forType(stateName);\n\n return state && state.get(resource.id!);\n }\n\n public add(name:string, state:MultiInputState) {\n this.additional[name] = state;\n }\n}\n\nexport class GlobalStateChanges {\n // Global subject on changes to the given query ID\n queries = new Subject();\n}\n\nexport class QueryAvailableDataStates {\n // Available columns\n columns = input();\n\n // Available SortBy Columns\n sortBy = input();\n\n // Available GroupBy columns\n groupBy = input();\n\n // Available filter schemas (derived from their schema)\n filters = input();\n\n // Display of the WP results\n displayRepresentation = input();\n}\n","import {Component, OnInit, ViewEncapsulation} from \"@angular/core\";\n\nexport const backlogsPageComponentSelector = 'op-backlogs-page';\n\n@Component({\n selector: backlogsPageComponentSelector,\n // Empty wrapper around legacy backlogs for CSS loading\n // that got removed in the Rails assets pipeline\n encapsulation: ViewEncapsulation.None,\n template: '',\n styleUrls: [\n './styles/backlogs.sass'\n ]\n})\nexport class BacklogsPageComponent implements OnInit {\n ngOnInit() {\n document.getElementById('projected-content')!.hidden = false;\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {AttachmentCollectionResource} from 'core-app/modules/hal/resources/attachment-collection-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {TypeResource} from 'core-app/modules/hal/resources/type-resource';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {\n OpenProjectFileUploadService,\n UploadFile\n} from 'core-components/api/op-file-upload/op-file-upload.service';\nimport {States} from 'core-components/states.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {Attachable} from 'core-app/modules/hal/resources/mixins/attachable-mixin';\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {InputState} from \"reactivestates\";\nimport {WorkPackagesActivityService} from \"core-components/wp-single-view-tabs/activity-panel/wp-activity.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport interface WorkPackageResourceEmbedded {\n activities:CollectionResource;\n ancestors:WorkPackageResource[];\n assignee:HalResource|any;\n attachments:AttachmentCollectionResource;\n author:HalResource|any;\n availableWatchers:HalResource|any;\n category:HalResource|any;\n children:WorkPackageResource[];\n parent:WorkPackageResource|null;\n priority:HalResource|any;\n project:HalResource|any;\n relations:CollectionResource;\n responsible:HalResource|any;\n revisions:CollectionResource|any;\n status:HalResource|any;\n timeEntries:HalResource[]|any[];\n type:TypeResource;\n version:HalResource|any;\n watchers:CollectionResource;\n // For regular work packages\n startDate:string;\n dueDate:string;\n // Only for milestones\n date:string;\n relatedBy:RelationResource|null;\n scheduleManually:boolean;\n}\n\nexport interface WorkPackageResourceLinks extends WorkPackageResourceEmbedded {\n addAttachment(attachment:HalResource):Promise;\n\n addChild(child:HalResource):Promise;\n\n addComment(comment:unknown, headers?:any):Promise;\n\n addRelation(relation:any):Promise;\n\n addWatcher(watcher:HalResource):Promise;\n\n changeParent(params:any):Promise;\n\n copy():Promise;\n\n delete():Promise;\n\n logTime():Promise;\n\n move():Promise;\n\n removeWatcher():Promise;\n\n self():Promise;\n\n update(payload:any):Promise>;\n\n updateImmediately(payload:any):Promise;\n\n watch():Promise;\n}\n\nexport interface WorkPackageLinksObject extends WorkPackageResourceLinks {\n schema:HalResource;\n}\n\nexport class WorkPackageBaseResource extends HalResource {\n public $embedded:WorkPackageResourceEmbedded;\n public $links:WorkPackageLinksObject;\n public subject:string;\n public updatedAt:Date;\n public lockVersion:number;\n public description:any;\n public activities:CollectionResource;\n public attachments:AttachmentCollectionResource;\n\n @InjectField() I18n!:I18nService;\n @InjectField() states:States;\n @InjectField() wpActivity:WorkPackagesActivityService;\n @InjectField() apiV3Service:APIV3Service;\n @InjectField() NotificationsService:NotificationsService;\n @InjectField() workPackageNotificationService:WorkPackageNotificationService;\n @InjectField() pathHelper:PathHelperService;\n @InjectField() opFileUpload:OpenProjectFileUploadService;\n\n readonly attachmentsBackend = true;\n\n /**\n * Return the ids of all its ancestors, if any\n */\n public get ancestorIds():string[] {\n const ancestors = (this as any).ancestors;\n return ancestors.map((el:WorkPackageResource) => el.id!);\n }\n\n /**\n * Return \": (#)\" if type and id are known.\n */\n public subjectWithType(truncateSubject:number = 40):string {\n const type = this.type ? `${this.type.name}: ` : '';\n const subject = this.subjectWithId(truncateSubject);\n\n return `${type}${subject}`;\n }\n\n /**\n * Return \" (#)\" if the id is known.\n */\n public subjectWithId(truncateSubject:number = 40):string {\n const id = this.isNew ? '' : ` (#${this.id})`;\n const subject = _.truncate(this.subject, {length: truncateSubject});\n\n return `${subject}${id}`;\n }\n\n public get isLeaf():boolean {\n let children = this.$links.children;\n return !(children && children.length > 0);\n }\n\n public previewPath() {\n if (!this.isNew) {\n return this.apiV3Service.work_packages.id(this.id!).path;\n } else {\n return super.previewPath();\n }\n }\n\n public getEditorTypeFor(fieldName:string):\"full\"|\"constrained\" {\n return fieldName === 'description' ? 'full' : 'constrained';\n }\n\n public isParentOf(otherWorkPackage:WorkPackageResource) {\n return otherWorkPackage.parent?.$links.self.$link.href === this.$links.self.$link.href;\n }\n\n /**\n * Invalidate a set of linked resources of this work package.\n * And inform the cache service about the work package update.\n *\n * Return a promise that returns the linked resources as properties.\n * Return a rejected promise, if the resource is not a property of the work package.\n */\n public updateLinkedResources(...resourceNames:string[]):Promise {\n const resources:{ [id:string]:Promise } = {};\n\n resourceNames.forEach(name => {\n const linked = this[name];\n resources[name] = linked ? linked.$update() : Promise.reject(undefined);\n });\n\n const promise = Promise.all(_.values(resources));\n promise.then(() => {\n this.wpCacheService.touch(this.id!);\n });\n\n return promise;\n }\n\n public $initialize(source:any) {\n super.$initialize(source);\n\n let attachments:any = this.attachments || {$source: {}, elements: []};\n this.attachments = new AttachmentCollectionResource(\n this.injector,\n // Attachments MAY be an array if we're building from a form\n _.get(attachments, '$source', attachments),\n false,\n this.halInitializer,\n 'HalResource'\n );\n }\n\n /**\n * Exclude the schema _link from the linkable Resources.\n */\n public $linkableKeys():string[] {\n return _.without(super.$linkableKeys(), 'schema');\n }\n\n /**\n * Return the associated state to this HAL resource, if any.\n */\n public get state():InputState {\n return this.states.workPackages.get(this.id!) as any;\n }\n\n /**\n * Update the state\n */\n public push(newValue:this):Promise {\n this.wpActivity.clear(newValue.id!);\n\n // If there is a parent, its view has to be updated as well\n if (newValue.parent) {\n this.apiV3Service.work_packages.id(newValue.parent).refresh();\n }\n\n return this.apiV3Service.work_packages.cache.updateWorkPackage(newValue as any);\n }\n}\n\nexport const WorkPackageResource = Attachable(WorkPackageBaseResource);\n\nexport interface WorkPackageResource extends WorkPackageBaseResource, WorkPackageResourceLinks, WorkPackageResourceEmbedded {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n AfterViewInit,\n Component,\n ViewEncapsulation,\n Output,\n EventEmitter,\n ChangeDetectorRef,\n} from '@angular/core';\nimport {WorkPackageAutocompleterComponent} from \"core-app/modules/common/autocomplete/wp-autocompleter.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\n\nexport type TimeEntryWorkPackageAutocompleterMode = 'all'|'recent';\n\n@Component({\n templateUrl: './te-work-package-autocompleter.component.html',\n styleUrls: ['./te-work-package-autocompleter.component.sass'],\n selector: 'te-work-package-autocompleter',\n encapsulation: ViewEncapsulation.None\n})\nexport class TimeEntryWorkPackageAutocompleterComponent extends WorkPackageAutocompleterComponent implements AfterViewInit {\n @Output() modeSwitch = new EventEmitter();\n\n constructor(readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly currentProject:CurrentProjectService,\n readonly pathHelper:PathHelperService) {\n super(I18n, cdRef, currentProject, pathHelper);\n\n this.text['all'] = this.I18n.t('js.label_all');\n this.text['recent'] = this.I18n.t('js.label_recent');\n }\n\n public loading:boolean = false;\n public mode:TimeEntryWorkPackageAutocompleterMode = 'all';\n\n public setMode(value:TimeEntryWorkPackageAutocompleterMode) {\n if (value !== this.mode) {\n this.modeSwitch.emit(value);\n }\n this.mode = value;\n }\n}\n","\n \n
    \n \n
    \n
    \n \n : {{search}}\n \n \n
    {{ item.name }}
    \n
    \n
    \n","import {concat, Observable, of, Subject} from \"rxjs\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {\n catchError,\n debounceTime,\n distinctUntilChanged, filter, share, shareReplay,\n switchMap,\n takeUntil,\n tap\n} from \"rxjs/operators\";\nimport {RequestSwitchmapHandler} from \"core-app/helpers/rxjs/request-switchmap\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\n\nexport type RequestErrorHandler = (error:unknown) => void;\n\nexport function errorNotificationHandler(service:HalResourceNotificationService):RequestErrorHandler {\n return (error:unknown) => service.handleRawError(error);\n}\n\nexport class DebouncedRequestSwitchmap {\n\n /** Input request state */\n public input$ = new Subject();\n\n /** Output results observable */\n public output$:Observable;\n\n /** Loading flag */\n public loading$ = new Subject();\n\n /** Whether results were returned */\n public lastResult:R[] = [];\n\n /** Last requested value */\n public lastRequestedValue:T|undefined;\n\n /**\n * @param handler switch map handler function to output a response observable\n * @param debounceTime {number} Time to debounce in ms.\n * @param preFilterNull {boolean} Whether to exclude null and undefined searches\n * @param emptyValue {R} The empty fall back value before first response or on errors\n */\n constructor(readonly requestHandler:RequestSwitchmapHandler,\n readonly errorHandler:RequestErrorHandler,\n readonly preFilterNull:boolean = false,\n readonly debounceMs = 250) {\n\n /** Output switchmap observable */\n this.output$ = concat(\n of([]),\n this.input$.pipe(\n filter(val => !preFilterNull || (val !== undefined && val !== null)),\n distinctUntilChanged(),\n debounceTime(debounceMs),\n tap((val:T) => {\n this.lastRequestedValue = val;\n this.lastResult = [];\n this.loading$.next(true);\n }),\n switchMap(term =>\n this.requestHandler(term)\n .pipe(\n catchError((error) => {\n this.errorHandler(error);\n return of([]);\n }),\n tap((results) => {\n this.loading$.next(false);\n this.lastResult = results;\n })\n )\n ),\n shareReplay(1)\n )\n );\n }\n\n /**\n * Append a new request for the given request value and pass\n * that to the switchmap handler\n * @param newValue\n */\n public request(newValue:T) {\n this.input$.next(newValue);\n }\n\n /**\n * Returns whether the last results returned anything\n */\n public get hasResults() {\n return this.lastResult.length > 0;\n }\n\n /**\n * Observe the switched response\n */\n public observe(until:Observable) {\n return this\n .output$\n .pipe(\n takeUntil(until)\n );\n }\n}\n","import {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {Constructor} from \"@angular/cdk/table\";\n\n/**\n * Simple resource collection to construct paths for RESTful resources.\n * Base class for APIV3 and BCF API helpers\n */\nexport class SimpleResourceCollection {\n // Base path\n public readonly path:string;\n\n constructor(protected basePath:string, readonly segment:string, protected resource?:Constructor) {\n this.path = `${this.basePath}/${segment}`;\n }\n\n public id(id:string|number):T {\n return new (this.resource || SimpleResource)(this.path, id) as T;\n }\n\n /**\n * Returns either the collection itself, or the resource\n * located by the ID when present.\n *\n * TypeScript will reduce available endpoints to anything available\n * in this collection AND the resource.\n *\n * @param id\n */\n public withOptionalId(id?:string|number):this|T {\n if (_.isNil(id)) {\n return this;\n } else {\n return this.id(id);\n }\n }\n\n public toString():string {\n return this.path;\n }\n\n public toPath():string {\n return this.path;\n }\n}\n\n/**\n * Singular RESTful resource object identified by a base path and ID\n */\nexport class SimpleResource {\n public readonly path:string;\n\n constructor(readonly basePath:string, readonly segment:string|number) {\n let separator = segment.toString().startsWith('?') ? '' : '/';\n this.path = `${this.basePath}${separator}${segment}`;\n }\n\n public toString() {\n return this.path;\n }\n\n public toPath():string {\n return this.path;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, Input, OnInit} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {States} from 'core-components/states.service';\nimport {filter} from 'rxjs/operators';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport const attachmentsSelector = 'attachments';\n\n@Component({\n selector: attachmentsSelector,\n templateUrl: './attachments.html'\n})\nexport class AttachmentsComponent extends UntilDestroyedMixin implements OnInit {\n @Input('resource') public resource:HalResource;\n\n public $element:JQuery;\n public allowUploading:boolean;\n public destroyImmediately:boolean;\n public text:any;\n\n constructor(protected elementRef:ElementRef,\n protected I18n:I18nService,\n protected states:States,\n protected halResourceService:HalResourceService) {\n super();\n\n this.text = {\n attachments: this.I18n.t('js.label_attachments'),\n };\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n if (!this.resource) {\n // Parse the resource if any exists\n const source = this.$element.data('resource');\n this.resource = this.halResourceService.createHalResource(source, true);\n }\n\n this.allowUploading = this.$element.data('allow-uploading');\n\n if (this.$element.data('destroy-immediately') !== undefined) {\n this.destroyImmediately = this.$element.data('destroy-immediately');\n } else {\n this.destroyImmediately = true;\n }\n\n this.setupResourceUpdateListener();\n }\n\n public setupResourceUpdateListener() {\n this.states.forResource(this.resource)!.changes$()\n .pipe(\n this.untilDestroyed(),\n filter(newResource => !!newResource)\n )\n .subscribe((newResource:HalResource) => {\n this.resource = newResource || this.resource;\n });\n }\n\n // Only show attachment list when allow uploading is set\n // or when at least one attachment exists\n public showAttachments() {\n return this.allowUploading || _.get(this.resource, 'attachments.count', 0) > 0;\n }\n}\n","
    \n \n {{ text.attachments }}\n \n
    \n \n \n \n \n
    \n
    \n\n","// @ts-ignore\nimport {utils} from \"@xeokit/xeokit-sdk/src/viewer/scene/utils\";\nimport {PathHelperService} from \"../../../common/path-helper/path-helper.service\";\nimport {IFCGonDefinition} from \"../pages/viewer/ifc-models-data.service\";\n\n/**\n * Default server client which loads content via HTTP from the file system.\n */\nexport class XeokitServer {\n private ifcModels:IFCGonDefinition;\n /**\n *\n * @param config\n * @param.config.pathHelper instance of PathHelperService.\n */\n constructor(private pathHelper:PathHelperService) {\n this.ifcModels = window.gon.ifc_models;\n }\n\n /**\n * Gets the manifest of all projects.\n * @param done\n * @param error\n */\n getProjects(done:Function, _error:Function) {\n done({ projects: this.ifcModels.projects });\n }\n\n /**\n * Gets a manifest for a project.\n * @param projectId\n * @param done\n * @param error\n */\n getProject(projectData:any, done:Function, _error:Function) {\n var manifestData = {\n id: projectData[0].id,\n name: projectData[0].name,\n models: this.ifcModels.models,\n viewerContent: {\n modelsLoaded: this.ifcModels.shown_models\n },\n viewerConfigs: {\n saoEnabled: true // Needs to be enabled by default if we want to use it selectively on the available models.\n }\n };\n\n done(manifestData);\n }\n\n /**\n * Gets metadata for a model within a project.\n * @param projectId\n * @param modelId\n * @param done\n * @param error\n */\n getMetadata(_projectId:string, modelId:number, done:Function, error:Function) {\n const attachmentId = this.ifcModels.metadata_attachment_ids[modelId];\n console.log(`Loading model metadata for: ${attachmentId}`);\n utils.loadJSON(this.pathHelper.attachmentContentPath(attachmentId), done, error);\n }\n\n /**\n * Gets geometry for a model within a project.\n * @param projectId\n * @param modelId\n * @param done\n * @param error\n */\n getGeometry(projectId:string, modelId:number, done:Function, error:Function) {\n const attachmentId = this.ifcModels.xkt_attachment_ids[modelId];\n console.log(`Loading model geometry for: ${attachmentId}`);\n utils.loadArraybuffer(this.pathHelper.attachmentContentPath(attachmentId), done, error);\n }\n}\n","import {Injectable, Inject, Injector} from '@angular/core';\nimport {XeokitServer} from \"core-app/modules/bim/ifc_models/xeokit/xeokit-server\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {ViewerBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service\";\nimport {BehaviorSubject, Observable, Subject} from \"rxjs\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {BcfApiService} from \"core-app/modules/bim/bcf/api/bcf-api.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {ViewpointsService} from \"core-app/modules/bim/bcf/helper/viewpoints.service\";\nimport {of} from 'rxjs';\n\n\nexport interface XeokitElements {\n canvasElement:HTMLElement;\n explorerElement:HTMLElement;\n toolbarElement:HTMLElement;\n navCubeCanvasElement:HTMLElement;\n busyModelBackdropElement:HTMLElement;\n}\n\nexport interface BCFCreationOptions {\n spacesVisible?:boolean;\n spaceBoundariesVisible?:boolean;\n openingsVisible?:boolean;\n}\n\nexport interface BCFLoadOptions {\n rayCast?:boolean;\n immediate?:boolean;\n duration?:number;\n}\n\n@Injectable()\nexport class IFCViewerService extends ViewerBridgeService {\n public shouldShowViewer = true;\n public viewerVisible$ = new BehaviorSubject(false);\n private _viewer:any;\n\n @InjectField() pathHelper:PathHelperService;\n @InjectField() bcfApi:BcfApiService;\n @InjectField() viewpointsService:ViewpointsService;\n\n constructor(readonly injector:Injector) {\n super(injector);\n }\n\n public newViewer(elements:XeokitElements, projects:any[]) {\n import('@xeokit/xeokit-bim-viewer/dist/main').then((XeokitViewerModule:any) => {\n let server = new XeokitServer(this.pathHelper);\n let viewerUI = new XeokitViewerModule.BIMViewer(server, elements);\n\n viewerUI.on(\"queryPicked\", (event:any) => {\n alert(`IFC Name = \"${event.objectName}\"\\nIFC class = \"${event.objectType}\"\\nIFC GUID = ${event.objectId}`);\n });\n\n viewerUI.on(\"modelLoaded\", () => this.viewerVisible$.next(true));\n\n viewerUI.loadProject(projects[0][\"id\"]);\n\n this.viewer = viewerUI;\n });\n }\n\n public destroy() {\n this.viewerVisible$.complete();\n\n if (!this.viewer) {\n return;\n }\n\n this.viewer.destroy();\n this.viewer = undefined;\n }\n\n public get viewer() {\n return this._viewer;\n }\n\n public set viewer(viewer:any) {\n this._viewer = viewer;\n }\n\n public setKeyboardEnabled(val:boolean) {\n this.viewer.setKeyboardEnabled(val);\n }\n\n public getViewpoint$():Observable {\n const viewpoint = this.viewer.saveBCFViewpoint({ spacesVisible: true });\n\n // The backend rejects viewpoints with bitmaps\n delete viewpoint.bitmaps;\n\n return of(viewpoint);\n }\n\n public showViewpoint(workPackage:WorkPackageResource, index:number) {\n // Avoid reload the app when there is a place to show the viewer\n // ('bim.partitioned.split')\n if (this.routeWithViewer) {\n if (this.viewer) {\n this.viewpointsService\n .getViewPoint$(workPackage, index)\n .subscribe(viewpoint => this.viewer.loadBCFViewpoint(viewpoint, {}));\n }\n } else {\n // Reload the whole app to get the correct menus and GON data\n // and redirect to a route with a place to show viewer\n // ('bim.partitioned.split')\n window.location.href = this.pathHelper.bimDetailsPath(\n workPackage.project.idFromLink,\n workPackage.id!,\n index\n );\n }\n }\n\n public viewerVisible():boolean {\n return !!this.viewer;\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport * as moment from 'moment-timezone';\nimport {Moment} from 'moment';\n\n@Injectable({ providedIn: 'root' })\nexport class TimezoneService {\n constructor(readonly ConfigurationService:ConfigurationService,\n readonly I18n:I18nService) {\n this.setupLocale();\n }\n\n public setupLocale() {\n moment.locale(I18n.locale);\n }\n\n /**\n * Takes a utc date time string and turns it into\n * a local date time moment object.\n */\n public parseDatetime(datetime:string, format?:string):Moment {\n var d = moment.utc(datetime, format);\n\n if (this.ConfigurationService.isTimezoneSet()) {\n d.local();\n d.tz(this.ConfigurationService.timezone());\n }\n\n return d;\n }\n\n public parseDate(date:Date|string, format?:string) {\n return moment(date, format);\n }\n\n /**\n * Parses a string that is considered to be a local date and\n * turns it into a utc date time moment object.\n * 'Local' might mean the browsers default time zone or the one configured\n * in the Configuration Service.\n *\n * @param {String} date\n * @param {String} format\n * @returns {Moment}\n */\n public parseLocalDateTime(date:string, format?:string) {\n var result;\n format = format || this.getTimeFormat();\n\n if (this.ConfigurationService.isTimezoneSet()) {\n result = moment.tz(date, format!, this.ConfigurationService.timezone());\n } else {\n result = moment(date, format);\n }\n result.utc();\n\n return result;\n }\n\n /**\n * Parses the specified datetime and applies the user's configured timezone, if any.\n *\n * This will effectfully transform the [server] provided datetime object to the user's configured local timezone.\n *\n * @param {String} datetime in 'YYYY-MM-DDTHH:mm:ssZ' format\n * @returns {Moment}\n */\n public parseISODatetime(datetime:string) {\n return this.parseDatetime(datetime, 'YYYY-MM-DDTHH:mm:ssZ');\n }\n\n public parseISODate(date:string) {\n return this.parseDate(date, 'YYYY-MM-DD');\n }\n\n public formattedDate(date:string) {\n var d = this.parseDate(date);\n return d.format(this.getDateFormat());\n }\n\n /**\n * Return whether the date is in the past\n * @param dateString\n */\n public inThePast(dateString:string):boolean {\n return this.daysFromToday(dateString) <= -1;\n }\n\n /**\n * Returns the number of days from today the given dateString is apart.\n * Negative means the date lies in the past.\n * @param dateString\n */\n public daysFromToday(dateString:string):number {\n const date = this.parseDate(dateString);\n const today = moment().startOf('day');\n\n return date.diff(today, 'days');\n }\n\n public formattedTime(datetimeString:string) {\n return this.parseDatetime(datetimeString).format(this.getTimeFormat());\n }\n\n public formattedDatetime(datetimeString:string) {\n var c = this.formattedDatetimeComponents(datetimeString);\n return c[0] + ' ' + c[1];\n }\n\n public formattedDatetimeComponents(datetimeString:string) {\n var d = this.parseDatetime(datetimeString);\n return [\n d.format(this.getDateFormat()),\n d.format(this.getTimeFormat())\n ];\n }\n\n public toHours(durationString:string) {\n return Number(moment.duration(durationString).asHours().toFixed(2));\n }\n\n public formattedDuration(durationString:string) {\n return this.I18n.t('js.units.hour', { count: this.toHours(durationString) });\n }\n\n public formattedISODate(date:any) {\n return this.parseDate(date).format('YYYY-MM-DD');\n }\n\n public formattedISODateTime(datetime:any) {\n return datetime.format();\n }\n\n public isValidISODate(date:any) {\n return this.isValid(date, 'YYYY-MM-DD');\n }\n\n public isValidISODateTime(dateTime:string) {\n return this.isValid(dateTime, 'YYYY-MM-DDTHH:mm:ssZ');\n }\n\n public isValid(date:string, dateFormat:string) {\n var format = dateFormat || this.getDateFormat();\n return moment(date, [format], true).isValid();\n }\n\n public getDateFormat() {\n return this.ConfigurationService.dateFormatPresent() ? this.ConfigurationService.dateFormat() : 'L';\n }\n\n public getTimeFormat() {\n return this.ConfigurationService.timeFormatPresent() ? this.ConfigurationService.timeFormat() : 'LT';\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';\nimport {\n CKEditorSetupService,\n ICKEditorContext,\n ICKEditorInstance\n} from \"core-app/modules/common/ckeditor/ckeditor-setup.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\n\ndeclare module 'codemirror';\n\nconst manualModeLocalStorageKey = 'op-ckeditor-uses-manual-mode';\n\n@Component({\n selector: 'op-ckeditor',\n templateUrl: './op-ckeditor.html',\n styleUrls: ['./op-ckeditor.sass']\n})\nexport class OpCkeditorComponent implements OnInit {\n @Input() ckEditorType:'full'|'constrained' = 'full';\n @Input() context:ICKEditorContext;\n @Input('content') _content:string;\n\n // Output notification once ready\n @Output() onInitialized = new EventEmitter();\n\n // Output notification at max once/s for data changes\n @Output() onContentChange = new EventEmitter();\n\n // Output notification when editor cannot be initialized\n @Output() onInitializationFailed = new EventEmitter();\n\n // View container of the replacement used to initialize CKEditor5\n @ViewChild('opCkeditorReplacementContainer', { static: true }) opCkeditorReplacementContainer:ElementRef;\n @ViewChild('codeMirrorPane') codeMirrorPane:ElementRef;\n\n // CKEditor instance once initialized\n public ckEditorInstance:ICKEditorInstance;\n public error:string|null = null;\n public allowManualMode = false;\n public manualMode = false;\n\n public text = {\n errorTitle: this.I18n.t('js.editor.error_initialization_failed')\n };\n\n // Codemirror instance, initialized lazily when running source mode\n public codeMirrorInstance:undefined|any;\n\n // Debounce change listener for both CKE and codemirror\n // to read back changes as they happen\n private debouncedEmitter = _.debounce(\n () => {\n this.getTransformedContent(false)\n .then(val => {\n this.onContentChange.emit(val);\n });\n },\n 1000,\n { leading: true }\n );\n\n private $element:JQuery;\n\n constructor(private readonly elementRef:ElementRef,\n private readonly Notifications:NotificationsService,\n private readonly I18n:I18nService,\n private readonly configurationService:ConfigurationService,\n private readonly ckEditorSetup:CKEditorSetupService) {\n }\n\n /**\n * Get the current live data from CKEditor. This may raise in cases\n * the data cannot be loaded (MS Edge!)\n */\n public getRawData() {\n if (this.manualMode) {\n return this._content = this.codeMirrorInstance!.getValue();\n } else {\n return this._content = this.ckEditorInstance!.getData({ trim: false });\n }\n }\n\n /**\n * Get a promise with the transformed content, will wrap errors in the promise.\n * @param notificationOnError\n */\n public getTransformedContent(notificationOnError = true):Promise {\n if (!this.initialized) {\n throw \"Tried to access CKEditor instance before initialization.\";\n }\n\n return new Promise((resolve, reject) => {\n try {\n resolve(this.getRawData());\n } catch (e) {\n console.error(`Failed to save CKEditor content: ${e}.`);\n let error = this.I18n.t(\n 'js.editor.error_saving_failed',\n { error: e || this.I18n.t('js.error.internal') }\n );\n\n if (notificationOnError) {\n this.Notifications.addError(error);\n }\n\n reject(error);\n }\n });\n }\n\n public set content(newVal:string) {\n if (!this.initialized) {\n throw \"Tried to access CKEditor instance before initialization.\";\n }\n\n this._content = newVal;\n this.ckEditorInstance!.setData(newVal);\n }\n\n /**\n * Return the current content. This may be outdated a tiny bit.\n */\n public get content() {\n return this._content;\n }\n\n public get initialized():boolean {\n return this.ckEditorInstance !== undefined;\n }\n\n ngOnInit() {\n try {\n this.initializeEditor();\n } catch (error) {\n // We will run into this error if, among others, the browser does not fully support\n // CKEditor's requirements on ES6.\n\n console.error(`Failed to setup CKEditor instance: ${error}`);\n this.error = error;\n this.onInitializationFailed.emit(error);\n }\n }\n\n private initializeEditor() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n const editorPromise = this.ckEditorSetup\n .create(\n this.ckEditorType,\n this.opCkeditorReplacementContainer.nativeElement,\n this.context,\n this.content\n )\n .catch((error:string) => {\n throw(error);\n })\n .then((editor:ICKEditorInstance) => {\n this.ckEditorInstance = editor;\n\n // Save changes while in wysiwyg mode\n editor.model.document.on('change', this.debouncedEmitter);\n\n // Switch mode\n editor.on('op:source-code-enabled', () => this.enableManualMode());\n editor.on('op:source-code-disabled', () => this.disableManualMode());\n\n this.onInitialized.emit(editor);\n return editor;\n });\n\n this.$element.data('editor', editorPromise);\n }\n\n\n /**\n * Disable the manual mode, kill the codeMirror instance and switch back to CKEditor\n */\n private disableManualMode() {\n const current = this.getRawData();\n\n // Apply content to ckeditor\n this.ckEditorInstance.setData(current);\n this.codeMirrorInstance = null;\n this.manualMode = false;\n }\n\n /**\n * Enable manual mode, get data from WYSIWYG and show CodeMirror instance.\n */\n private enableManualMode() {\n const current = this.getRawData();\n const cmMode = 'gfm';\n\n Promise\n .all([\n import('codemirror'),\n import(/* webpackChunkName: \"codemirror-mode\" */ `codemirror/mode/${cmMode}/${cmMode}.js`)\n ])\n .then((imported:any[]) => {\n const CodeMirror = imported[0].default;\n this.codeMirrorInstance = CodeMirror(\n this.$element.find('.ck-editor__source')[0],\n {\n lineNumbers: true,\n smartIndent: true,\n value: current,\n mode: ''\n }\n );\n\n this.codeMirrorInstance.on('change', this.debouncedEmitter);\n setTimeout(() => this.codeMirrorInstance.refresh(), 100);\n this.manualMode = true;\n });\n }\n}\n","\n
    \n
    \n

    \n \n
    \n \n

    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {IAutocompleteItem} from 'core-components/wp-query-select/wp-query-select-dropdown.component';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {Injectable} from '@angular/core';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {StateService} from \"@uirouter/core\";\nimport {CurrentUserService} from \"core-components/user/current-user.service\";\n\n@Injectable()\nexport class WorkPackageStaticQueriesService {\n constructor(private readonly I18n:I18nService,\n private readonly $state:StateService,\n private readonly CurrentProject:CurrentProjectService,\n private readonly PathHelper:PathHelperService,\n private readonly CurrentUserService:CurrentUserService) {\n }\n\n public text = {\n assignee: this.I18n.t('js.work_packages.properties.assignee'),\n author: this.I18n.t('js.work_packages.properties.author'),\n created_at: this.I18n.t('js.work_packages.properties.createdAt'),\n updated_at: this.I18n.t('js.work_packages.properties.updatedAt'),\n status: this.I18n.t('js.work_packages.properties.status'),\n work_packages: this.I18n.t('js.label_work_package_plural'),\n gantt: this.I18n.t('js.timelines.gantt_chart'),\n latest_activity: this.I18n.t('js.work_packages.default_queries.latest_activity'),\n created_by_me: this.I18n.t('js.work_packages.default_queries.created_by_me'),\n assigned_to_me: this.I18n.t('js.work_packages.default_queries.assigned_to_me'),\n recently_created: this.I18n.t('js.work_packages.default_queries.recently_created'),\n all_open: this.I18n.t('js.work_packages.default_queries.all_open'),\n summary: this.I18n.t('js.work_packages.default_queries.summary'),\n };\n\n // Create all static queries manually\n // The query_props configure default values of column names, sorting and applied filters\n // All queries are sorted by their update or creation time (so the latest is always the first)\n public get all():IAutocompleteItem[] {\n let items = [\n {\n identifier: 'all_open',\n label: this.text.all_open,\n query_props: null\n },\n {\n identifier: 'latest_activity',\n label: this.text.latest_activity,\n query_props: '{\"c\":[\"id\",\"subject\",\"type\",\"status\",\"assignee\",\"updatedAt\"],\"hi\":false,\"g\":\"\",\"t\":\"updatedAt:desc\",\"f\":[{\"n\":\"status\",\"o\":\"o\",\"v\":[]}]}'\n },\n {\n identifier: 'gantt',\n label: this.text.gantt,\n query_props: `{\"c\":[\"id\",\"type\",\"subject\",\"status\",\"startDate\",\"dueDate\"],\"tv\":true,\"tzl\":\"auto\",\"tll\":\"{\\\\\"left\\\\\":\\\\\"startDate\\\\\",\\\\\"right\\\\\":\\\\\"dueDate\\\\\",\\\\\"farRight\\\\\":\\\\\"subject\\\\\"}\",\"hi\":true,\"g\":\"\",\"t\":\"startDate:asc\",\"f\":[{\"n\":\"status\",\"o\":\"o\",\"v\":[]}]}`\n },\n {\n identifier: 'recently_created',\n label: this.text.recently_created,\n query_props: '{\"c\":[\"id\",\"subject\",\"type\",\"status\",\"assignee\",\"createdAt\"],\"hi\":false,\"g\":\"\",\"t\":\"createdAt:desc\",\"f\":[{\"n\":\"status\",\"o\":\"o\",\"v\":[]}]}'\n }\n ] as IAutocompleteItem[];\n\n const projectIdentifier = this.CurrentProject.identifier;\n if (projectIdentifier) {\n items.push({\n identifier: 'summary',\n label: this.text.summary,\n static_link: this.PathHelper.projectWorkPackagesPath(projectIdentifier) + '/report'\n });\n }\n\n if (this.CurrentUserService.isLoggedIn) {\n items = items.concat([\n {\n identifier: 'created_by_me',\n label: this.text.created_by_me,\n query_props: '{\"c\":[\"id\",\"subject\",\"type\",\"status\",\"assignee\",\"updatedAt\"],\"hi\":false,\"g\":\"\",\"t\":\"updatedAt:desc,id:asc\",\"f\":[{\"n\":\"status\",\"o\":\"o\",\"v\":[]},{\"n\":\"author\",\"o\":\"=\",\"v\":[\"me\"]}]}'\n },\n {\n identifier: 'assigned_to_me',\n label: this.text.assigned_to_me,\n query_props: '{\"c\":[\"id\",\"subject\",\"type\",\"status\",\"author\",\"updatedAt\"],\"hi\":false,\"g\":\"\",\"t\":\"updatedAt:desc,id:asc\",\"f\":[{\"n\":\"status\",\"o\":\"o\",\"v\":[]},{\"n\":\"assigneeOrGroup\",\"o\":\"=\",\"v\":[\"me\"]}]}'\n }\n ]);\n }\n\n return items;\n }\n\n public getStaticName(query:QueryResource) {\n if (this.$state.params.query_props) {\n let queryProps = JSON.parse(this.$state.params.query_props);\n delete queryProps.pp;\n delete queryProps.pa;\n let queryPropsString = JSON.stringify(queryProps);\n\n const matched = _.find(this.all, item =>\n item.query_props && item.query_props === queryPropsString\n );\n\n if (matched) {\n return matched.label;\n }\n }\n\n // Try to detect the all open filter\n if (query.filters.length === 1 && // Only one filter\n query.filters[0].id === 'status' && // that is status\n query.filters[0].operator.id === 'o') { // and is open\n return this.text.all_open;\n }\n\n // Otherwise, fall back to work packages\n return this.text.work_packages;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from '@angular/core';\nimport {HttpClient, HttpErrorResponse, HttpParams} from '@angular/common/http';\nimport {catchError, map} from 'rxjs/operators';\nimport {Observable, throwError} from 'rxjs';\nimport {HalResource, HalResourceClass} from 'core-app/modules/hal/resources/hal-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {HalLink, HalLinkInterface} from 'core-app/modules/hal/hal-link/hal-link';\nimport {URLParamsEncoder} from 'core-app/modules/hal/services/url-params-encoder';\nimport {ErrorResource} from \"core-app/modules/hal/resources/error-resource\";\nimport * as Pako from 'pako';\nimport {\n HTTPClientHeaders,\n HTTPClientOptions,\n HTTPClientParamMap,\n HTTPSupportedMethods\n} from \"core-app/modules/hal/http/http.interfaces\";\nimport {whenDebugging} from \"core-app/helpers/debug_output\";\nimport {initializeHalProperties} from \"../helpers/hal-resource-builder\";\n\nexport interface HalResourceFactoryConfigInterface {\n cls?:any;\n attrTypes?:{ [attrName:string]:string };\n}\n\n\n@Injectable({ providedIn: 'root' })\nexport class HalResourceService {\n\n /**\n * List of all known hal resources, extendable.\n */\n private config:{ [typeName:string]:HalResourceFactoryConfigInterface } = {};\n\n constructor(readonly injector:Injector,\n readonly http:HttpClient) {\n }\n\n /**\n * Perform a HTTP request and return a HalResource promise.\n */\n public request(method:HTTPSupportedMethods, href:string, data?:any, headers:HTTPClientHeaders = {}):Observable {\n\n // HttpClient requires us to create HttpParams instead of passing data for get\n // so forward to that method instead.\n if (method === 'get') {\n return this.get(href, data, headers);\n }\n\n const config:HTTPClientOptions = {\n body: data || {},\n headers: headers,\n withCredentials: true,\n responseType: 'json'\n };\n\n return this._request(method, href, config);\n }\n\n private _request(method:HTTPSupportedMethods, href:string, config:HTTPClientOptions):Observable {\n return this.http.request(method, href, config)\n .pipe(\n map((response:any) => this.createHalResource(response)),\n catchError((error:HttpErrorResponse) => {\n whenDebugging(() => console.error(`Failed to ${method} ${href}: ${error.name}`));\n const resource = this.createHalResource(error.error);\n resource.httpError = error;\n return throwError(resource);\n })\n ) as any;\n }\n\n /**\n * Perform a GET request and return a resource promise.\n *\n * @param href\n * @param params\n * @param headers\n * @returns {Promise}\n */\n public get(href:string, params?:HTTPClientParamMap, headers?:HTTPClientHeaders):Observable {\n const config:HTTPClientOptions = {\n headers: headers,\n params: new HttpParams({ encoder: new URLParamsEncoder(), fromObject: params }),\n withCredentials: true,\n responseType: 'json'\n };\n\n return this._request('get', href, config);\n }\n\n /**\n * Return all potential pages to the request, when the elements returned from API is smaller\n * than the expected.\n *\n * @param href\n * @param expected The expected number of elements\n * @param params\n * @param headers\n * @return {Promise}\n */\n public async getAllPaginated(href:string, expected:number, params:any = {}, headers:HTTPClientHeaders = {}) {\n // Total number retrieved\n let retrieved = 0;\n // Current offset page\n let page = 1;\n // Accumulated results\n const allResults:T = [] as any;\n // If possible, request all at once.\n params.pageSize = expected;\n\n while (retrieved < expected) {\n params.offset = page;\n\n const promise = this.request('get', href, this.toEprops(params), headers).toPromise();\n const results = await promise;\n\n if (results.count === 0) {\n throw 'No more results for this query, but expected more.';\n }\n\n allResults.push(results);\n\n retrieved += results.count;\n page += 1;\n }\n\n return allResults;\n }\n\n /**\n * Perform a PUT request and return a resource promise.\n * @param href\n * @param data\n * @param headers\n * @returns {Promise}\n */\n public put(href:string, data?:any, headers?:HTTPClientHeaders):Observable {\n return this.request('put', href, data, headers);\n }\n\n /**\n * Perform a POST request and return a resource promise.\n *\n * @param href\n * @param data\n * @param headers\n * @returns {Promise}\n */\n public post(href:string, data?:any, headers?:HTTPClientHeaders):Observable {\n return this.request('post', href, data, headers);\n }\n\n /**\n * Perform a PATCH request and return a resource promise.\n *\n * @param href\n * @param data\n * @param headers\n * @returns {Promise}\n */\n public patch(href:string, data?:any, headers?:HTTPClientHeaders):Observable {\n return this.request('patch', href, data, headers);\n }\n\n /**\n * Perform a DELETE request and return a resource promise\n *\n * @param href\n * @param data\n * @param headers\n * @returns {Promise}\n */\n public delete(href:string, data?:any, headers?:HTTPClientHeaders):Observable {\n return this.request('delete', href, data, headers);\n }\n\n /**\n * Register a HalResource for use with the API.\n * @param {HalResourceStatic} resource\n */\n public registerResource(key:string, entry:HalResourceFactoryConfigInterface) {\n this.config[key] = entry;\n }\n\n /**\n * Get the default class.\n * Initially, it's HalResource.\n *\n * @returns {HalResource}\n */\n public get defaultClass():HalResourceClass {\n let defaultCls:HalResourceClass = HalResource;\n return defaultCls;\n }\n\n /**\n * Create a HalResource from a source object.\n * If the APIv3 _type attribute is defined and the type is configured,\n * the respective class will be used for instantiation.\n *\n *\n * @param source\n * @returns {HalResource}\n */\n public createHalResource(source:any, loaded:boolean = true):T {\n if (_.isNil(source)) {\n source = HalResource.getEmptyResource();\n }\n\n const type = source._type || 'HalResource';\n return this.createHalResourceOfType(type, source, loaded);\n }\n\n public createHalResourceOfType(type:string, source:any, loaded:boolean = false) {\n const resourceClass:HalResourceClass = this.getResourceClassOfType(type);\n const initializer = (halResource:T) => initializeHalProperties(this, halResource);\n let resource = new resourceClass(this.injector, source, loaded, initializer, type);\n\n return resource;\n }\n\n /**\n * Create a resource class of the given class\n * @param resourceClass\n * @param source\n * @param loaded\n */\n public createHalResourceOfClass(resourceClass:HalResourceClass, source:any, loaded:boolean = false) {\n const initializer = (halResource:T) => initializeHalProperties(this, halResource);\n const type = source._type || 'HalResource';\n let resource = new resourceClass(this.injector, source, loaded, initializer, type);\n\n return resource;\n }\n\n /**\n * Create a linked HalResource from the given link.\n *\n * @param {HalLinkInterface} link\n * @returns {HalResource}\n */\n public fromLink(link:HalLinkInterface) {\n const resource = HalResource.getEmptyResource(HalLink.fromObject(this, link));\n return this.createHalResource(resource, false);\n }\n\n /**\n * Create an empty HAL resource with only the self link set.\n * @param href Self link of the HAL resource\n */\n public fromSelfLink(href:string|null) {\n const source = { _links: { self: { href: href } } };\n return this.createHalResource(source);\n }\n\n /**\n * Get a linked resource from its HalLink with the correct type.\n */\n public createLinkedResource(halResource:T, linkName:string, link:HalLinkInterface) {\n const source = HalResource.getEmptyResource();\n const fromType = halResource.$halType;\n const toType = this.getResourceClassOfAttribute(fromType, linkName) || 'HalResource';\n\n source._links.self = link;\n\n return this.createHalResourceOfType(toType, source, false);\n }\n\n /**\n * Get the configured resource class of a type.\n *\n * @param type\n * @returns {HalResource}\n */\n protected getResourceClassOfType(type:string):HalResourceClass {\n const config = this.config[type];\n return (config && config.cls) ? config.cls : this.defaultClass;\n }\n\n /**\n * Get the hal type for an attribute\n *\n * @param type\n * @param attribute\n * @returns {any}\n */\n protected getResourceClassOfAttribute(type:string, attribute:string):string|null {\n const typeConfig = this.config[type];\n const types = (typeConfig && typeConfig.attrTypes) || {};\n return types[attribute];\n }\n\n protected toEprops(params:{}):{} {\n let deflated = Pako.deflate(JSON.stringify(params), { to: 'string' });\n let compressed = btoa(deflated);\n\n return { eprops: compressed };\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageCreateComponent} from 'core-components/wp-new/wp-create.component';\nimport {ChangeDetectionStrategy, Component} from '@angular/core';\n\n@Component({\n selector: 'wp-new-full-view',\n host: { 'class': 'work-packages-page--ui-view' },\n templateUrl: './wp-new-full-view.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageNewFullViewComponent extends WorkPackageCreateComponent {\n public successState:string = 'work-packages.show';\n}\n","\n \n
    \n
    \n \n
    \n
      \n
    • \n \n
    • \n
    • \n \n
    • \n
    \n
    \n\n \n \n \n \n
    \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Subject} from 'rxjs';\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport abstract class EditFieldHandler extends UntilDestroyedMixin {\n /**\n * Whether the handler belongs to a larger edit mode form\n * e.g., WP-create\n */\n abstract get inEditMode():boolean;\n\n /** Whether the field is being saved */\n abstract get inFlight():boolean;\n\n /**\n * Return a unique ID for this edit field\n */\n htmlId:string;\n\n /**\n * The name of the attribute\n */\n fieldName:string;\n\n /**\n * Activation handler firing upon user requesting activation.\n */\n $onUserActivate:Subject;\n\n /**\n * Accessibility label for the field\n */\n fieldLabel:string;\n\n /**\n * Error messages on the field, if any.\n */\n public errorMessageOnLabel():string|undefined {\n return undefined;\n }\n\n /**\n * On destroy observable\n */\n public onDestroy = new Subject();\n\n // OnSubmit callbacks that may register from fields\n protected _onSubmitHandlers:Array<() => Promise> = [];\n\n // OnPreSubmit callbacks that may register from fields\n protected _onBeforeSubmitHandlers:Array<() => void> = [];\n\n /**\n * Call field submission callback handlers\n */\n public onSubmit():Promise {\n return Promise.all(this._onSubmitHandlers.map((cb) => cb()));\n }\n\n public registerOnSubmit(callback:() => Promise) {\n this._onSubmitHandlers.push(callback);\n }\n\n /**\n * Call field before-submission callback handlers\n */\n public onBeforeSubmit():any {\n return this._onBeforeSubmitHandlers.map((cb) => cb());\n }\n\n public registerOnBeforeSubmit(callback:() => void) {\n this._onBeforeSubmitHandlers.push(callback);\n }\n\n /**\n * Stop event propagation\n */\n public abstract stopPropagation(evt:JQuery.TriggeredEvent):boolean;\n\n /**\n * Focus on the active field.\n * Optionally, try to set the click position to the given offset if the field is an input element.\n */\n public abstract focus(setClickOffset?:number):void;\n\n /**\n * Handle a user submitting the field (e.g, ng-change)\n */\n public abstract handleUserSubmit():Promise;\n\n /**\n * Handle users pressing enter inside an edit mode.\n * Outside an edit mode, the regular save event is captured by handleUserSubmit (submit event).\n * In an edit mode, we can't derive from a submit event wheteher the user pressed enter\n * (and on what field he did that).\n */\n public abstract handleUserKeydown(event:JQuery.TriggeredEvent, onlyCancel?:boolean):void;\n\n /**\n * Cancel edit\n */\n public abstract handleUserCancel():void;\n\n /**\n * Cancel any pending changes\n */\n public abstract reset():void;\n\n /**\n * Close the field, resetting it with its display value.\n */\n public abstract deactivate(focus:boolean):void;\n\n /**\n * Returns whether the field has been changed\n */\n public abstract isChanged():boolean;\n\n /**\n * Handle focus loss\n */\n public abstract onFocusOut():void;\n\n public abstract setErrors(newErrors:string[]):void;\n\n public previewContext(resource:HalResource):string|undefined {\n return undefined;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Directive, EventEmitter, HostListener, Input, Output} from '@angular/core';\nimport {LinkHandling} from 'core-app/modules/common/link-handling/link-handling';\n\n@Directive({\n selector: '[accessibleClick]',\n})\nexport class AccessibleClickDirective {\n @Input('accessibleClickStopEvent') stopEventPropagation:boolean = true;\n @Input('accessibleClickSkipModifiers') skipEventModifiers:boolean = false;\n @Output('accessibleClick') onClick = new EventEmitter();\n\n @HostListener('click', ['$event'])\n @HostListener('keydown', ['$event'])\n public handleClick(event:MouseEvent|KeyboardEvent) {\n if (this.isMatchingEvent(event) && !this.skipOnModifier(event)) {\n if (this.stopEventPropagation) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n this.onClick.emit(event);\n }\n }\n\n /**\n * Whether the given event is handled by this directive\n * @param event\n * @private\n */\n private isMatchingEvent(event:MouseEvent|KeyboardEvent) {\n return event.type === 'click' ||\n (event instanceof KeyboardEvent && (event.key === 'Enter' || event.key === ' '));\n }\n\n /**\n * Whether to skip the click event with modifiers pressed\n * according to the input being set.\n *\n * @param event\n * @private\n */\n private skipOnModifier(event:MouseEvent|KeyboardEvent) {\n return this.skipEventModifiers && event instanceof MouseEvent && LinkHandling.isClickedWithModifier(event);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\n\nexport const DEFAULT_PAGINATION_OPTIONS = {\n maxVisiblePageOptions: 6,\n optionsTruncationSize: 1\n};\n\nexport interface IPaginationOptions {\n perPage:number;\n perPageOptions:number[];\n maxVisiblePageOptions:number;\n optionsTruncationSize:number;\n}\n\nexport interface PaginationObject {\n pageSize:number;\n offset:number;\n}\n\n\n@Injectable()\nexport class PaginationService {\n private paginationOptions:IPaginationOptions;\n\n constructor(private configuration:ConfigurationService) {\n this.loadPaginationOptions();\n }\n\n public getCachedPerPage(initialPageOptions:number[]):number {\n const value = this.localStoragePerPage;\n const initialLength = initialPageOptions?.length || 0;\n\n if (value !== null && value > 0 && (initialLength === 0 || initialPageOptions?.indexOf(value) !== -1)) {\n return value;\n }\n\n if (initialLength > 0) {\n return initialPageOptions[0];\n }\n\n return 20;\n }\n\n private get localStoragePerPage() {\n const value = window.OpenProject.guardedLocalStorage('pagination.perPage') as string;\n\n if (value !== undefined) {\n return parseInt(value, 10);\n } else {\n return null;\n }\n }\n\n public getPaginationOptions() {\n return this.paginationOptions;\n }\n\n public get isPerPageKnown() {\n return !!(this.localStoragePerPage || this.paginationOptions);\n }\n\n public getPerPage() {\n return this.localStoragePerPage || this.paginationOptions.perPage;\n }\n\n public getMaxVisiblePageOptions() {\n return _.get(this.paginationOptions, 'maxVisiblePageOptions', DEFAULT_PAGINATION_OPTIONS.maxVisiblePageOptions);\n }\n\n public getOptionsTruncationSize() {\n return _.get(this.paginationOptions, 'optionsTruncationSize', DEFAULT_PAGINATION_OPTIONS.optionsTruncationSize);\n }\n\n public setPerPage(perPage:number) {\n window.OpenProject.guardedLocalStorage('pagination.perPage', perPage.toString());\n this.paginationOptions.perPage = perPage;\n }\n\n public getPerPageOptions() {\n return this.paginationOptions.perPageOptions;\n }\n\n public setPerPageOptions(perPageOptions:number[]) {\n this.paginationOptions.perPageOptions = perPageOptions;\n }\n\n public loadPaginationOptions() {\n return this.configuration.initialized.then(() => {\n this.paginationOptions = {\n perPage: this.getCachedPerPage(this.configuration.perPageOptions),\n perPageOptions: this.configuration.perPageOptions,\n maxVisiblePageOptions: DEFAULT_PAGINATION_OPTIONS.maxVisiblePageOptions,\n optionsTruncationSize: DEFAULT_PAGINATION_OPTIONS.optionsTruncationSize\n };\n\n return this.paginationOptions;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {input} from \"reactivestates\";\nimport {Observable} from \"rxjs\";\nimport {takeUntil} from \"rxjs/operators\";\n\n@Injectable()\nexport class WorkPackageFiltersService {\n private readonly state = input(false);\n\n public get visible() {\n return this.state.getValueOr(false);\n }\n\n public set visible(val:boolean) {\n this.state.putValue(val);\n }\n\n public observeUntil(unsubscribe:Observable) {\n return this.state.values$().pipe(takeUntil(unsubscribe));\n }\n\n public toggleVisibility() {\n this.state.doModify((current) => !current);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {QueryFormResource} from 'core-app/modules/hal/resources/query-form-resource';\nimport {QuerySortByResource} from 'core-app/modules/hal/resources/query-sort-by-resource';\nimport {QueryGroupByResource} from 'core-app/modules/hal/resources/query-group-by-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {QueryFilterInstanceSchemaResource} from 'core-app/modules/hal/resources/query-filter-instance-schema-resource';\nimport {QueryColumn} from '../wp-query/query-column';\nimport {Injectable} from '@angular/core';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\n\n@Injectable()\nexport class WorkPackagesListInvalidQueryService {\n constructor(protected halResourceService:HalResourceService) {\n }\n\n public restoreQuery(query:QueryResource, form:QueryFormResource) {\n this.restoreFilters(query, form.payload, form.schema);\n this.restoreColumns(query, form.payload, form.schema);\n this.restoreSortBy(query, form.payload, form.schema);\n this.restoreGroupBy(query, form.payload, form.schema);\n this.restoreOtherProperties(query, form.payload);\n }\n\n private restoreFilters(query:QueryResource, payload:QueryResource, querySchema:SchemaResource) {\n let filters = _.map((payload.filters), filter => {\n let filterInstanceSchema = _.find(querySchema.filtersSchemas.elements, (schema:QueryFilterInstanceSchemaResource) => {\n return (schema.filter.allowedValues as QueryFilterResource[])[0].$href === filter.filter.$href;\n });\n\n if (!filterInstanceSchema) {\n return null;\n }\n\n let recreatedFilter = filterInstanceSchema.getFilter();\n\n let operator = _.find(filterInstanceSchema.operator.allowedValues, operator => {\n return operator.$href === filter.operator.$href;\n });\n\n if (operator) {\n recreatedFilter.operator = operator;\n }\n\n recreatedFilter.values.length = 0;\n _.each(filter.values, value => recreatedFilter.values.push(value));\n\n return recreatedFilter;\n });\n\n filters = _.compact(filters);\n\n // clear filters while keeping reference\n query.filters.length = 0;\n _.each(filters, filter => query.filters.push(filter));\n }\n\n private restoreColumns(query:QueryResource, stubQuery:QueryResource, schema:SchemaResource) {\n let columns = _.map(stubQuery.columns, column => {\n return _.find((schema.columns.allowedValues as QueryColumn[]), candidate => {\n return candidate.$href === column.$href;\n });\n });\n\n columns = _.compact(columns);\n\n query.columns.length = 0;\n _.each(columns, column => query.columns.push(column!));\n }\n\n private restoreSortBy(query:QueryResource, stubQuery:QueryResource, schema:SchemaResource) {\n let sortBys = _.map((stubQuery.sortBy), sortBy => {\n return _.find((schema.sortBy.allowedValues as QuerySortByResource[]), candidate => {\n return candidate.$href === sortBy.$href;\n })!;\n });\n\n sortBys = _.compact(sortBys);\n\n query.sortBy.length = 0;\n _.each(sortBys, sortBy => query.sortBy.push(sortBy));\n }\n\n private restoreGroupBy(query:QueryResource, stubQuery:QueryResource, schema:SchemaResource) {\n let groupBy = _.find((schema.groupBy.allowedValues as QueryGroupByResource[]), candidate => {\n return stubQuery.groupBy && stubQuery.groupBy.$href === candidate.$href;\n }) as any;\n\n query.groupBy = groupBy;\n }\n\n private restoreOtherProperties(query:QueryResource, stubQuery:QueryResource) {\n _.without(Object.keys(stubQuery.$source), '_links', 'filters').forEach((property:any) => {\n query[property] = stubQuery[property];\n });\n\n _.without(Object.keys(stubQuery.$source._links), 'columns', 'groupBy', 'sortBy').forEach((property:any) => {\n query[property] = stubQuery[property];\n });\n }\n}\n","/**\n * Return an HTML element with the given icon classes\n * and aria-hidden=true set.\n */\nexport function opIconElement(...classes:string[]) {\n let icon = document.createElement('i');\n icon.setAttribute('aria-hidden', 'true');\n icon.classList.add(...classes);\n\n return icon;\n}\n","import {Injector, Injectable} from '@angular/core';\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {Observable} from \"rxjs\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {StateService} from \"@uirouter/core\";\n\n\n@Injectable()\nexport abstract class ViewerBridgeService {\n @InjectField() state:StateService;\n\n /**\n * Determine whether a viewer should be shown,\n * wether 'bim.partitioned.split' state/route should be activated\n */\n abstract shouldShowViewer:boolean;\n\n /**\n * Check if we are on a router state where there is a place\n * where the viewer could be shown\n */\n get routeWithViewer():boolean {\n return this.state.includes('bim.partitioned.split');\n }\n\n constructor(readonly injector:Injector) {}\n /**\n * Get a viewpoint from the viewer\n */\n abstract getViewpoint$():Observable;\n\n /**\n * Show the given viewpoint JSON in the viewer\n * @param viewpoint\n */\n abstract showViewpoint(workPackage:WorkPackageResource, index:number):void;\n\n /**\n * Determine whether a viewer is present to ensure we can show viewpoints\n */\n abstract viewerVisible():boolean;\n\n /**\n * Fires when viewer becomes visible.\n */\n abstract viewerVisible$:Observable;\n}\n","
    \n \n\n
    \n
      \n
    • \n\n
    • \n\n \n \n \n\n {{ perPageOption }}\n
    • \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {PaginationService} from 'core-components/table-pagination/pagination-service';\nimport {PaginationInstance} from 'core-components/table-pagination/pagination-instance';\nimport {IPaginationOptions} from './pagination-service';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n Input,\n OnInit,\n Output\n} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Component({\n selector: '[tablePagination]',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './table-pagination.component.html'\n})\nexport class TablePaginationComponent extends UntilDestroyedMixin implements OnInit {\n @Input() totalEntries:string;\n @Input() hideForSinglePageResults:boolean = false;\n @Input() showPerPage:boolean = true;\n @Input() showPageSelections:boolean = true;\n @Input() infoText?:string;\n @Output() updateResults = new EventEmitter();\n\n public pagination:PaginationInstance;\n public text = {\n label_previous: this.I18n.t('js.pagination.pages.previous'),\n label_next: this.I18n.t('js.pagination.pages.next'),\n per_page: this.I18n.t('js.label_per_page'),\n no_other_page: this.I18n.t('js.pagination.no_other_page')\n };\n\n public currentRange:string = '';\n public pageNumbers:number[] = [];\n public postPageNumbers:number[] = [];\n public prePageNumbers:number[] = [];\n public perPageOptions:number[] = [];\n\n constructor(protected paginationService:PaginationService,\n protected cdRef:ChangeDetectorRef,\n protected I18n:I18nService) {\n super();\n }\n\n ngOnInit():void {\n this.paginationService\n .loadPaginationOptions()\n .then((paginationOptions:IPaginationOptions) => {\n this.perPageOptions = paginationOptions.perPageOptions;\n this.pagination = new PaginationInstance(1, parseInt(this.totalEntries), paginationOptions.perPage);\n this.cdRef.detectChanges();\n });\n }\n\n public update() {\n this.updateCurrentRangeLabel();\n this.updatePageNumbers();\n this.cdRef.detectChanges();\n }\n\n public selectPerPage(perPage:number) {\n this.pagination.perPage = perPage;\n this.paginationService.setPerPage(perPage);\n this.showPage(1);\n }\n\n public showPage(page:number) {\n this.pagination.page = page;\n\n this.updateCurrentRangeLabel();\n this.updatePageNumbers();\n\n this.onUpdatedPage();\n this.cdRef.detectChanges();\n }\n\n public onUpdatedPage() {\n this.updateResults.emit(this.pagination);\n }\n\n public get isVisible() {\n return !this.hideForSinglePageResults || (this.pagination.total > this.pagination.perPage);\n }\n\n /**\n * @name updateCurrentRange\n *\n * @description Defines a string containing page bound information inside the directive scope\n */\n public updateCurrentRangeLabel() {\n if (this.pagination.total) {\n let totalItems = this.pagination.total;\n let lowerBound = this.pagination.getLowerPageBound();\n let upperBound = this.pagination.getUpperPageBound(this.pagination.total);\n\n this.currentRange = '(' + lowerBound + ' - ' + upperBound + '/' + totalItems + ')';\n } else {\n this.currentRange = '(0 - 0/0)';\n }\n }\n\n /**\n * @name updatePageNumbers\n *\n * @description Defines a list of all pages in numerical order inside the scope\n */\n public updatePageNumbers() {\n if (!this.showPageSelections) {\n this.pageNumbers = [];\n this.postPageNumbers = [];\n return;\n }\n\n var maxVisible = this.paginationService.getMaxVisiblePageOptions();\n var truncSize = this.paginationService.getOptionsTruncationSize();\n\n var pageNumbers = [];\n\n const perPage = this.pagination.perPage;\n const currentPage = this.pagination.page;\n if (perPage) {\n for (var i = 1; i <= Math.ceil(this.pagination.total / perPage); i++) {\n pageNumbers.push(i);\n }\n\n // This avoids a truncation when there are not enough elements to truncate for the first elements\n var startingDiff = currentPage - 2 * truncSize;\n if (0 <= startingDiff && startingDiff <= 1) {\n this.postPageNumbers = this.truncatePageNums(pageNumbers, pageNumbers.length >= maxVisible + (truncSize * 2), maxVisible + truncSize, pageNumbers.length, 0);\n } else {\n this.prePageNumbers = this.truncatePageNums(pageNumbers, currentPage >= maxVisible, 0, Math.min(currentPage - Math.ceil(maxVisible / 2), pageNumbers.length - maxVisible), truncSize);\n this.postPageNumbers = this.truncatePageNums(pageNumbers, pageNumbers.length >= maxVisible + (truncSize * 2), maxVisible, pageNumbers.length, 0);\n }\n }\n\n this.pageNumbers = pageNumbers;\n }\n\n public showPerPageOptions() {\n return this.showPerPage &&\n this.perPageOptions.length > 0 &&\n this.pagination.total > this.perPageOptions[0];\n }\n\n private truncatePageNums(pageNumbers:any, perform:any, disectFrom:any, disectLength:any, truncateFrom:any) {\n if (perform) {\n var truncationSize = this.paginationService.getOptionsTruncationSize();\n var truncatedNums = pageNumbers.splice(disectFrom, disectLength);\n if (truncatedNums.length >= truncationSize * 2) {\n truncatedNums.splice(truncateFrom, truncatedNums.length - truncationSize);\n }\n return truncatedNums;\n } else {\n return [];\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {TablePaginationComponent} from 'core-components/table-pagination/table-pagination.component';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {IPaginationOptions, PaginationService} from 'core-components/table-pagination/pagination-service';\nimport {WorkPackageViewPaginationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service\";\nimport {WorkPackageViewPagination} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-pagination\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {combineLatest} from 'rxjs';\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\n\n@Component({\n templateUrl: '../../table-pagination/table-pagination.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-table-pagination'\n})\nexport class WorkPackageTablePaginationComponent extends TablePaginationComponent implements OnInit, OnDestroy {\n\n constructor(protected paginationService:PaginationService,\n protected cdRef:ChangeDetectorRef,\n protected wpTablePagination:WorkPackageViewPaginationService,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpTableSortBy:WorkPackageViewSortByService,\n readonly I18n:I18nService) {\n super(paginationService, cdRef, I18n);\n\n }\n\n ngOnInit() {\n this.paginationService\n .loadPaginationOptions()\n .then((paginationOptions:IPaginationOptions) => {\n this.perPageOptions = paginationOptions.perPageOptions;\n this.cdRef.detectChanges();\n });\n\n this.wpTablePagination\n .live$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wpPagination:WorkPackageViewPagination) => {\n this.pagination = wpPagination.current;\n this.update();\n });\n\n // hide/show pagination options depending on the sort mode\n combineLatest([\n this.querySpace.query.values$(),\n this.wpTableSortBy.live$()\n ]).pipe(\n this.untilDestroyed()\n ).subscribe(([query, sort]) => {\n this.showPerPage = this.showPageSelections = !this.isManualSortingMode;\n this.infoText = this.paginationInfoText(query.results);\n\n this.update();\n });\n }\n\n public selectPerPage(perPage:number) {\n this.paginationService.setPerPage(perPage);\n this.wpTablePagination.updateFromObject({ page: 1, perPage: perPage });\n }\n\n public showPage(pageNumber:number) {\n this.wpTablePagination.updateFromObject({ page: pageNumber });\n }\n\n private get isManualSortingMode() {\n return this.wpTableSortBy.isManualSortingMode;\n }\n\n public paginationInfoText(work_packages:WorkPackageCollectionResource) {\n if (this.isManualSortingMode && (work_packages.count < work_packages.total)) {\n return I18n.t('js.work_packages.limited_results',\n { count: work_packages.count });\n } else {\n return undefined;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\n\nexport class ActivityEntryInfo {\n\n constructor(public timezoneService:TimezoneService,\n public isReversed:boolean,\n public activities:any[],\n public activity:any,\n public index:number) {\n }\n\n public number(forceReverse:boolean = false) {\n return this.orderedIndex(this.index, forceReverse);\n }\n\n public get date() {\n return this.activityDate(this.activity);\n }\n\n public get dateOfPrevious():any {\n if (this.index > 0) {\n return this.activityDate(this.activities[this.index - 1]);\n }\n }\n\n public get href() {\n return this.activity.href;\n }\n\n public get identifier() {\n return `${this.href}-${this.version}`;\n }\n\n public get version() {\n return this.activity.version;\n }\n\n public get isNextDate() {\n return this.date !== this.dateOfPrevious;\n }\n\n public isInitial(forceReverse:boolean = false) {\n var activityNo = this.number(forceReverse);\n\n if (this.activity._type.indexOf('Activity') !== 0) {\n return false;\n }\n\n if (activityNo === 1) {\n return true;\n }\n\n while (--activityNo > 0) {\n var idx = this.orderedIndex(activityNo, forceReverse) - 1;\n var activity = this.activities[idx];\n if (!_.isNil(activity) && activity._type.indexOf('Activity') === 0) {\n return false;\n }\n }\n\n return true;\n }\n\n protected activityDate(activity:any) {\n // Force long date regardless of current date settings for headers\n return moment(activity.createdAt).format('LL');\n }\n\n protected orderedIndex(activityNo:number, forceReverse:boolean = false) {\n if (forceReverse || this.isReversed) {\n return this.activities.length - activityNo;\n }\n\n return activityNo + 1;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ActivityEntryInfo} from './activity-entry-info';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {Injectable} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {WorkPackageLinkedResourceCache} from 'core-components/wp-single-view-tabs/wp-linked-resource-cache.service';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\n\n@Injectable()\nexport class WorkPackagesActivityService extends WorkPackageLinkedResourceCache {\n\n constructor(public ConfigurationService:ConfigurationService,\n readonly timezoneService:TimezoneService) {\n super();\n }\n\n public get order() {\n return this.isReversed ? 'desc' : 'asc';\n }\n\n public get isReversed() {\n return this.ConfigurationService.commentsSortedInDescendingOrder();\n }\n\n /**\n * Aggregate user and revision activities for the given work package resource.\n * Resolves both promises and returns a sorted list of activities\n * whose order depends on the 'commentsSortedInDescendingOrder' property.\n */\n protected load(workPackage:WorkPackageResource):Promise {\n var aggregated:any[] = [], promises:Promise[] = [];\n\n var add = function (data:any) {\n aggregated.push(data.elements);\n };\n\n promises.push(workPackage.activities.$update().then(add));\n\n if (workPackage.revisions) {\n promises.push(workPackage.revisions.$update().then(add));\n }\n return Promise.all(promises).then(() => {\n return this.sortedActivityList(aggregated);\n });\n }\n\n protected sortedActivityList(activities:HalResource[], attr:string = 'createdAt'):HalResource[] {\n let sorted = _.sortBy(_.flatten(activities), attr);\n\n if (this.isReversed) {\n return sorted.reverse();\n } else {\n return sorted;\n }\n }\n\n public info(activities:HalResource[], activity:HalResource, index:number) {\n return new ActivityEntryInfo(this.timezoneService, this.isReversed, activities, activity, index);\n }\n}\n","import {Injectable, Injector} from '@angular/core';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {BcfApiService} from \"core-app/modules/bim/bcf/api/bcf-api.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {BcfViewpointPaths} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths\";\nimport {ViewerBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service\";\nimport {switchMap, map, tap} from 'rxjs/operators';\nimport {of, forkJoin, Observable} from 'rxjs';\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {BcfTopicResource} from \"core-app/modules/bim/bcf/api/topics/bcf-topic.resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Injectable()\nexport class ViewpointsService {\n topicUUID:string|number;\n\n @InjectField() bcfApi:BcfApiService;\n @InjectField() viewerBridge:ViewerBridgeService;\n @InjectField() apiV3Service:APIV3Service;\n\n constructor(readonly injector:Injector) {}\n\n public getViewPointResource(workPackage:WorkPackageResource, index:number):BcfViewpointPaths {\n const viewpointHref = workPackage.bcfViewpoints[index].href;\n\n return this.bcfApi.parse(viewpointHref);\n }\n\n public getViewPoint$(workPackage:WorkPackageResource, index:number):Observable {\n const viewpointResource = this.getViewPointResource(workPackage, index);\n\n return viewpointResource.get();\n }\n\n public deleteViewPoint$(workPackage:WorkPackageResource, index:number):Observable {\n const viewpointResource = this.getViewPointResource(workPackage, index);\n\n return viewpointResource\n .delete()\n .pipe(\n // Update the work package to reload the viewpoints\n tap(() => this.apiV3Service.work_packages.id(workPackage).requireAndStream(true))\n );\n }\n\n public saveViewpoint$(workPackage:WorkPackageResource, viewpoint?:BcfViewpointInterface):Observable {\n const wpProjectId = workPackage.project.idFromLink;\n const topicUUID$ = this.setBcfTopic$(workPackage);\n // Default to the current viewer's viewpoint\n const viewpoint$ = viewpoint ?\n of(viewpoint) :\n this.viewerBridge!.getViewpoint$();\n\n return forkJoin({\n topicUUID: topicUUID$,\n viewpoint: viewpoint$,\n })\n .pipe(\n switchMap(results => {\n return this.bcfApi\n .projects.id(wpProjectId)\n .topics.id(results.topicUUID as (string | number))\n .viewpoints\n .post(results.viewpoint);\n }\n ),\n // Update the work package to reload the viewpoints\n tap((results) =>\n this.apiV3Service.work_packages.id(workPackage).requireAndStream(true))\n );\n }\n\n public setBcfTopic$(workPackage:WorkPackageResource) {\n if (this.topicUUID) {\n return of(this.topicUUID);\n } else {\n const topicHref = workPackage.bcfTopic?.href;\n const topicUUID$ = topicHref ?\n of(this.bcfApi.parse(topicHref)!.id) :\n this.createBcfTopic$(workPackage);\n\n return topicUUID$.pipe(map(topicUUID => this.topicUUID = topicUUID));\n }\n }\n\n private createBcfTopic$(workPackage:WorkPackageResource):Observable {\n const wpProjectId = workPackage.project.idFromLink;\n const wpPayload = workPackage.convertBCF.payload;\n\n return this.bcfApi\n .projects.id(wpProjectId)\n .topics\n .post(wpPayload)\n .pipe(\n map((resource:BcfTopicResource) => {\n this.topicUUID = resource.guid;\n return this.topicUUID;\n })\n );\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, Output} from '@angular/core';\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {CreateAutocompleterComponent} from \"core-app/modules/common/autocomplete/create-autocompleter.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './create-autocompleter.component.html',\n selector: 'version-autocompleter'\n})\nexport class VersionAutocompleterComponent extends CreateAutocompleterComponent implements AfterViewInit {\n @Output() public onCreate = new EventEmitter();\n\n constructor(readonly I18n:I18nService,\n readonly currentProject:CurrentProjectService,\n readonly cdRef:ChangeDetectorRef,\n readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly halNotification:HalResourceNotificationService) {\n super(I18n, cdRef, currentProject, pathHelper);\n }\n\n ngAfterViewInit() {\n super.ngAfterViewInit();\n\n this.canCreateNewActionElements().then((val) => {\n if (val) {\n this.createAllowed = (input:string) => this.createNewVersion(input);\n this.cdRef.detectChanges();\n }\n });\n }\n\n /**\n * Checks for correct permissions\n * (whether the current project is in the list of allowed values in the version create form)\n * @returns {Promise}\n */\n public canCreateNewActionElements():Promise {\n if (!this.currentProject.id) {\n return Promise.resolve(false);\n }\n\n return this\n .apiV3Service\n .versions\n .available_projects\n .exists(this.currentProject.id!)\n .toPromise()\n .catch(() => false);\n }\n\n protected createNewVersion(name:string) {\n this\n .apiV3Service\n .versions\n .post(this.getVersionPayload(name))\n .subscribe(\n version => this.onCreate.emit(version),\n error => {\n this.closeSelect();\n this.halNotification.handleRawError(error);\n });\n }\n\n private getVersionPayload(name:string) {\n let payload:any = {};\n payload['name'] = name;\n payload['_links'] = {\n definingProject: {\n href: this.apiV3Service.projects.id(this.currentProject.id!).path\n }\n };\n\n return payload;\n }\n}\n","// Separated from render passes to avoid cyclic dependencies\nexport const rowGroupClassName = 'wp-table--group-header';\nexport const collapsedRowClass = '-collapsed';\n","import {Constructor} from \"@angular/cdk/table\";\nimport {SimpleResource, SimpleResourceCollection} from \"core-app/modules/apiv3/paths/path-resources\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Observable} from \"rxjs\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class APIv3ResourcePath extends SimpleResource {\n readonly injector = this.apiRoot.injector;\n @InjectField() halResourceService:HalResourceService;\n\n constructor(protected apiRoot:APIV3Service,\n readonly basePath:string,\n readonly id:string|number,\n protected parent?:APIv3ResourcePath|APIv3ResourceCollection) {\n super(basePath, id);\n }\n\n\n /**\n * Build a singular resource from the current segment\n *\n * @param segment Additional segment to add to the current path\n */\n protected subResource(segment:string, cls:Constructor = APIv3GettableResource as any):R {\n return new cls(this.apiRoot, this.path, segment, this);\n }\n}\n\n\nexport class APIv3GettableResource extends APIv3ResourcePath {\n /**\n * Perform a request to the HalResourceService with the current path\n */\n public get():Observable {\n return this\n .halResourceService\n .get(this.path) as any;\n }\n}\n\nexport class APIv3ResourceCollection> extends SimpleResourceCollection {\n readonly injector = this.apiRoot.injector;\n @InjectField() halResourceService:HalResourceService;\n\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string,\n segment:string,\n protected resource?:Constructor) {\n super(basePath, segment, resource);\n }\n\n /**\n * Returns an instance of T for the given singular resource ID.\n *\n * @param id Identifier of the resource, may be a string or number, or a HalResource with id property.\n */\n public id(input:string|number|{ id:string|null }):T {\n let id:string;\n if (typeof input === 'string' || typeof input === 'number') {\n id = input.toString();\n } else {\n id = input.id!;\n }\n\n return new (this.resource || APIv3GettableResource)(this.apiRoot, this.path, id, this) as T;\n }\n\n\n public withOptionalId(id?:string|number|null):this|T {\n if (_.isNil(id)) {\n return this;\n } else {\n return this.id(id);\n }\n }\n\n /**\n * Returns the path string to the requested endpoint.\n */\n public toString():string {\n return this.path;\n }\n\n /**\n * Returns the path string to the requested endpoint.\n */\n public toPath():string {\n return this.path;\n }\n\n /**\n * Returns a new resource with the path extended with a URL query\n * to match the filters.\n *\n * @param filters filter object to filter with\n * @param params additional URL params to append\n */\n public filtered>(filters:ApiV3FilterBuilder, params:{ [key:string]:string } = {}, resourceClass?:Constructor):R {\n return this.subResource('?' + filters.toParams(params), resourceClass) as R;\n }\n\n /**\n * Build a singular resource from the current segment\n *\n * @param segment Additional segment to add to the current path\n */\n protected subResource>(segment:string, cls:Constructor = APIv3GettableResource as any):R {\n return new cls(this.apiRoot, this.path, segment, this);\n }\n}","import {ApplicationRef, ComponentFactoryResolver, Injectable, Injector} from '@angular/core';\nimport {ComponentPortal, DomPortalOutlet, PortalInjector} from '@angular/cdk/portal';\nimport {TransitionService} from '@uirouter/core';\nimport {FocusHelperService} from 'core-app/modules/common/focus/focus-helper';\nimport {\n ExternalQueryConfigurationComponent,\n QueryConfigurationLocals\n} from \"core-components/wp-table/external-configuration/external-query-configuration.component\";\nimport {OpQueryConfigurationLocalsToken} from \"core-components/wp-table/external-configuration/external-query-configuration.constants\";\n\nexport type Class = { new(...args:any[]):any; };\n\n@Injectable()\nexport class ExternalQueryConfigurationService {\n\n // Hold a reference to the DOM node we're using as a host\n private _portalHostElement:HTMLElement;\n // And a reference to the actual portal host interface on top of the element\n private _bodyPortalHost:DomPortalOutlet;\n\n constructor(private componentFactoryResolver:ComponentFactoryResolver,\n readonly FocusHelper:FocusHelperService,\n private appRef:ApplicationRef,\n private $transitions:TransitionService,\n private injector:Injector) {\n }\n\n /**\n * Create a portal host element to contain the table configuration components.\n */\n private get bodyPortalHost() {\n if (!this._portalHostElement) {\n const hostElement = this._portalHostElement = document.createElement('div');\n hostElement.classList.add('op-external-query-configuration--container');\n document.body.appendChild(hostElement);\n\n this._bodyPortalHost = new DomPortalOutlet(\n hostElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n }\n\n return this._bodyPortalHost;\n }\n\n /**\n * Open a Modal reference and append it to the portal\n */\n public show(data:Partial) {\n this.detach();\n\n // Create a portal for the given component class and render it\n const portal = new ComponentPortal(\n this.externalQueryConfigurationComponent(),\n null,\n this.injectorFor(data)\n );\n this.bodyPortalHost.attach(portal);\n this._portalHostElement.style.display = 'block';\n }\n\n /**\n * Closes currently open modal window\n */\n public detach() {\n // Detach any component currently in the portal\n if (this.bodyPortalHost.hasAttached()) {\n this.bodyPortalHost.detach();\n this._portalHostElement.style.display = 'none';\n }\n }\n\n /**\n * Create an augmented injector that is equal to this service's injector + the additional data\n * passed into +show+.\n * This allows callers to pass data into the newly created modal.\n *\n */\n private injectorFor(data:any) {\n const injectorTokens = new WeakMap();\n // Pass the service because otherwise we're getting a cyclic dependency between the portal\n // host service and the bound portal\n data.service = this;\n\n injectorTokens.set(OpQueryConfigurationLocalsToken, data);\n\n return new PortalInjector(this.injector, injectorTokens);\n }\n\n externalQueryConfigurationComponent():Class {\n return ExternalQueryConfigurationComponent;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\n\n@Component({\n templateUrl: './text-edit-field.component.html'\n})\nexport class TextEditFieldComponent extends EditFieldComponent {\n // ToDo: Work package specific\n public shouldFocus = this.name === 'subject';\n}\n","\n","// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Component} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\n\n@Component({\n template: `\n \n `\n})\nexport class IntegerEditFieldComponent extends EditFieldComponent {\n public locale = I18n.locale;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport * as moment from 'moment';\nimport {Component} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n@Component({\n template: `\n \n `\n})\nexport class DurationEditFieldComponent extends EditFieldComponent {\n @InjectField() TimezoneService:TimezoneService;\n\n public parser(value:any, input:any) {\n // Managing decimal separators in a multi-language app is a complex topic:\n // https://www.ctrl.blog/entry/html5-input-number-localization.html\n // Depending on the locale of the OS, the browser or the app itself,\n // a decimal separator could be considered valid or invalid.\n // When a decimal operator is considered invalid (e.g: 1. in Chrome with\n // 'en' locale), the input emits null as a value and its state is marked\n // not valid, but the value remains in the input. Adding a value after the\n // 'invalid' separator (e.g: 1.2) emits a valid value.\n // In order to allow both decimal separator (period and comma) in any\n // context, we check the validity of the input and, if it's not valid, we\n // default to the previous value, emulating the way the browsers work with\n // valid separators (e.g: introducing 1. would set 1 as a value).\n if (value == null && !input.validity.valid) {\n value = this.value || 0;\n }\n\n return moment.duration(value, 'hours');\n }\n\n public formatter(value:any) {\n return Number(moment.duration(value).asHours().toFixed(2));\n }\n\n protected parseValue(val:moment.Moment | null) {\n if (val === null) {\n return val;\n }\n\n let parsedValue;\n if (val.isValid()) {\n parsedValue = val.toISOString();\n } else {\n parsedValue = null;\n }\n\n return parsedValue;\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\n\ninterface SelectAutocompleterAssignment {\n attribute:string;\n component:string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class SelectAutocompleterRegisterService {\n private _fields:SelectAutocompleterAssignment[] = [];\n\n public register(component:any, attribute:string) {\n this._fields.push({ attribute: attribute, component: component, });\n }\n\n public getAutocompleterOfAttribute(attribute:string) {\n let assignment = _.find(this._fields, field => field.attribute === attribute);\n return assignment ? assignment.component : undefined;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, InjectFlags, OnInit} from \"@angular/core\";\nimport {HalResourceSortingService} from \"core-app/modules/hal/services/hal-resource-sorting.service\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {EditFieldComponent} from \"../edit-field.component\";\nimport {CreateAutocompleterComponent} from \"core-app/modules/common/autocomplete/create-autocompleter.component\";\nimport {SelectAutocompleterRegisterService} from \"app/modules/fields/edit/field-types/select-autocompleter-register.service\";\nimport {from} from 'rxjs';\nimport {map, tap} from 'rxjs/operators';\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {StateService} from \"@uirouter/core\";\n\nexport interface ValueOption {\n name:string;\n $href:string|null;\n}\n\n@Component({\n templateUrl: './select-edit-field.component.html'\n})\nexport class SelectEditFieldComponent extends EditFieldComponent implements OnInit {\n @InjectField() selectAutocompleterRegister:SelectAutocompleterRegisterService;\n @InjectField() halNotification:HalResourceNotificationService;\n @InjectField() halSorting:HalResourceSortingService;\n @InjectField() $state:StateService;\n @InjectField(EditFormComponent, null, InjectFlags.Optional) editFormComponent:EditFormComponent;\n\n public availableOptions:any[];\n public valueOptions:ValueOption[];\n protected valuesLoaded = false;\n\n public text:{ [key:string]:string };\n\n public appendTo:any = null;\n private hiddenOverflowContainer = '.__hidden_overflow_container';\n\n /** Remember the values loading promise which changes as soon as the changeset is updated\n * (e.g., project or type is changed).\n */\n private valuesLoadingPromise:Promise;\n\n protected _autocompleterComponent:CreateAutocompleterComponent;\n\n public referenceOutputs:{ [key:string]:Function } = {\n onCreate: (newElement:HalResource) => this.onCreate(newElement),\n onChange: (value:HalResource) => this.onChange(value),\n onKeydown: (event:JQuery.TriggeredEvent) => this.handler.handleUserKeydown(event, true),\n onOpen: () => this.onOpen(),\n onClose: () => this.onClose(),\n onAfterViewInit: (component:CreateAutocompleterComponent) => this._autocompleterComponent = component\n };\n\n protected initialize() {\n this.text = {\n requiredPlaceholder: this.I18n.t('js.placeholders.selection'),\n placeholder: this.I18n.t('js.placeholders.default')\n };\n\n this.valuesLoadingPromise = this.change.getForm().then(() => {\n return this.initialValueLoading();\n });\n }\n\n protected initialValueLoading() {\n this.valuesLoaded = false;\n return this.loadValues().toPromise();\n }\n\n public autocompleterComponent() {\n let type = this.schema.type;\n return this.selectAutocompleterRegister.getAutocompleterOfAttribute(type) || CreateAutocompleterComponent;\n }\n\n public ngOnInit() {\n super.ngOnInit();\n this.appendTo = this.overflowingSelector;\n\n this.handler\n .$onUserActivate\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.valuesLoadingPromise.then(() => {\n this._autocompleterComponent.openDirectly = true;\n });\n });\n\n this._syncUrlParamsOnChangeIfNeeded(this.handler.fieldName, this.editFormComponent?.editMode);\n }\n\n public get selectedOption() {\n const href = this.value ? this.value.$href : null;\n return _.find(this.valueOptions, o => o.$href === href)!;\n }\n\n public set selectedOption(val:ValueOption) {\n let option = _.find(this.availableOptions, o => o.$href === val.$href);\n\n // Special case 'null' value, which angular\n // only understands in ng-options as an empty string.\n if (option && option.$href === '') {\n option.$href = null;\n }\n\n this.value = option;\n }\n\n private setValues(availableValues:HalResource[]) {\n this.availableOptions = this.sortValues(availableValues);\n this.addEmptyOption();\n this.valueOptions = this.availableOptions.map(el => this.mapAllowedValue(el));\n }\n\n protected loadValues(query?:string) {\n let allowedValues = this.schema.allowedValues;\n\n if (Array.isArray(allowedValues)) {\n this.setValues(allowedValues);\n this.valuesLoaded = true;\n } else if (allowedValues && !this.valuesLoaded) {\n return this.loadValuesFromBackend(query);\n } else {\n this.setValues([]);\n }\n\n return from(Promise.resolve(this.valueOptions));\n }\n\n protected loadValuesFromBackend(query?:string) {\n return from(\n this.loadAllowedValues(query)\n ).pipe(\n tap(collection => {\n // if it is an unpaginated collection or if we get all possible entries when fetching with a blank\n // query, we do not need to load the values again;\n if (collection.count === undefined || collection.total === undefined || (!query && collection.total === collection.count)) {\n this.valuesLoaded = true;\n }\n }),\n map(collection => {\n if (collection.count === undefined || collection.total === undefined || (!query && collection.total === collection.count) || !this.value) {\n return collection.elements;\n } else {\n return collection.elements.concat([this.value]);\n }\n }),\n tap(elements => this.setValues(elements)),\n map(() => this.valueOptions)\n );\n }\n\n protected loadAllowedValues(query?:string):Promise {\n // Cache the search without any params\n if (!query) {\n const cacheKey = this.schema.allowedValues.$link.href;\n return this.change.cacheValue(cacheKey, this.fetchAllowedValueQuery.bind(this));\n }\n\n return this.fetchAllowedValueQuery(query);\n }\n\n protected fetchAllowedValueQuery(query?:string) {\n return this.schema.allowedValues.$link.$fetch(this.allowedValuesFilter(query)) as Promise;\n }\n\n private addValue(val:HalResource) {\n this.availableOptions.push(val);\n this.valueOptions.push({ name: val.name, $href: val.$href });\n }\n\n public get currentValueInvalid():boolean {\n return !!(\n (this.value && !_.some(this.availableOptions, (option:HalResource) => (option.$href === this.value.$href)))\n ||\n (!this.value && this.schema.required)\n );\n }\n\n public onCreate(newElement:HalResource) {\n this.addValue(newElement);\n this.selectedOption = { name: newElement.name, $href: newElement.$href };\n this.handler.handleUserSubmit();\n }\n\n public onOpen() {\n jQuery(this.hiddenOverflowContainer).one('scroll', () => {\n this._autocompleterComponent.closeSelect();\n });\n }\n\n public onClose() {\n // Nothing to do\n }\n\n public onChange(value:HalResource|undefined) {\n if (value !== undefined) {\n this.selectedOption = { name: value.name, $href: value.$href };\n this.handler.handleUserSubmit();\n return;\n }\n\n const emptyOption = this.getEmptyOption();\n\n if (emptyOption) {\n this.selectedOption = emptyOption;\n this.handler.handleUserSubmit();\n }\n }\n\n private addEmptyOption() {\n // Empty options are not available for required fields\n if (this.isRequired()) {\n return;\n }\n\n // Since we use the original schema values, avoid adding\n // the option if one is returned / exists already.\n const emptyOption = this.getEmptyOption();\n if (emptyOption === undefined) {\n this.availableOptions.unshift({\n name: this.text.placeholder,\n $href: ''\n });\n }\n }\n\n protected isRequired() {\n return this.schema.required;\n }\n\n protected sortValues(availableValues:HalResource[]) {\n return this.halSorting.sort(availableValues);\n }\n\n protected mapAllowedValue(value:HalResource):ValueOption {\n return { name: value.name, $href: value.$href };\n }\n\n // Subclasses shall be able to override the filters with which the\n // allowed values are reduced in the backend.\n protected allowedValuesFilter(query?:string) {\n return {};\n }\n\n private getEmptyOption():ValueOption|undefined {\n return _.find(this.availableOptions, el => el.name === this.text.placeholder);\n }\n\n private _syncUrlParamsOnChangeIfNeeded(fieldName:string, editMode:boolean) {\n // Work package type changes need to be synced with the type url param\n // in order to keep the form changes (changeset) between route/state changes\n if (fieldName === 'type' && editMode) {\n this.handler.registerOnBeforeSubmit(() => {\n const newType = this.value?.$source?.id;\n\n if (newType) {\n this.$state.go('.', { type: newType }, { notify: false });\n }\n });\n }\n }\n}\n","\n\n","\n\n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {Component, OnInit, ViewChild} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {ValueOption} from \"core-app/modules/fields/edit/field-types/select-edit-field.component\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n@Component({\n templateUrl: './multi-select-edit-field.component.html'\n})\nexport class MultiSelectEditFieldComponent extends EditFieldComponent implements OnInit {\n @ViewChild(NgSelectComponent, { static: true }) public ngSelectComponent:NgSelectComponent;\n @InjectField() I18n!:I18nService;\n\n public availableOptions:any[] = [];\n public valueOptions:ValueOption[];\n public text = {\n requiredPlaceholder: this.I18n.t('js.placeholders.selection'),\n placeholder: this.I18n.t('js.placeholders.default'),\n save: this.I18n.t('js.inplace.button_save', { attribute: this.schema.name }),\n cancel: this.I18n.t('js.inplace.button_cancel', { attribute: this.schema.name }),\n };\n\n public appendTo:any = null;\n private hiddenOverflowContainer = '.__hidden_overflow_container';\n\n public currentValueInvalid:boolean = false;\n private nullOption:ValueOption;\n private _selectedOption:ValueOption[];\n\n /** Since we need to wait for values to be loaded, remember if the user activated this field*/\n private requestFocus = false;\n\n ngOnInit() {\n this.nullOption = { name: this.text.placeholder, $href: null };\n\n this.handler\n .$onUserActivate\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.requestFocus = this.availableOptions.length === 0;\n\n // If we already have all values loaded, open now.\n if (!this.requestFocus) {\n this.openAutocompleteSelectField();\n }\n });\n\n super.ngOnInit();\n this.appendTo = this.overflowingSelector;\n }\n\n public get value() {\n const val = this.resource[this.name];\n return val ? val[0] : val;\n }\n\n /**\n * Map the selected hal resource(s) to the value options so that ngOptions will track them.\n * We cannot pass the HalResources themselves as angular will copy them on every digest due to trackBy\n * @returns {any}\n */\n public buildSelectedOption() {\n const value:HalResource[] = this.resource[this.name];\n return value ? _.castArray(value).map(val => this.findValueOption(val)) : [];\n }\n\n public get selectedOption() {\n return this._selectedOption;\n }\n\n /**\n * Map the ValueOption to the actual HalResource option\n * @param val\n */\n public set selectedOption(val:ValueOption[]) {\n this._selectedOption = val;\n let mapper = (val:ValueOption) => {\n let option = _.find(this.availableOptions, o => o.$href === val.$href) || this.nullOption;\n\n // Special case 'null' value, which angular\n // only understands in ng-options as an empty string.\n if (option && option.$href === '') {\n option.$href = null;\n }\n\n return option;\n };\n\n this.resource[this.name] = _.castArray(val).map(el => mapper(el));\n }\n\n public onOpen() {\n jQuery(this.hiddenOverflowContainer).one('scroll', () => {\n this.ngSelectComponent.close();\n });\n }\n\n public onClose() {\n // Nothing to do\n }\n\n public repositionDropdown() {\n if (this.ngSelectComponent && this.ngSelectComponent.dropdownPanel) {\n setTimeout(() => this.ngSelectComponent.dropdownPanel.adjustPosition(), 0);\n }\n }\n\n private openAutocompleteSelectField() {\n // The timeout takes care that the opening is added to the end of the current call stack.\n // Thus we can be sure that the autocompleter is rendered and ready to be opened.\n let that = this;\n window.setTimeout(function () {\n that.ngSelectComponent.open();\n }, 0);\n }\n\n private findValueOption(option?:HalResource):ValueOption {\n let result;\n\n if (option) {\n result = _.find(this.valueOptions, (valueOption) => valueOption.$href === option.$href)!;\n }\n\n return result || this.nullOption;\n }\n\n private setValues(availableValues:any[], sortValuesByName:boolean = false) {\n if (sortValuesByName) {\n availableValues.sort(function (a:any, b:any) {\n let nameA = a.name.toLowerCase();\n let nameB = b.name.toLowerCase();\n return nameA < nameB ? -1 : nameA > nameB ? 1 : 0;\n });\n }\n\n this.availableOptions = availableValues || [];\n this.valueOptions = this.availableOptions.map(el => {\n return { name: el.name, $href: el.$href };\n });\n this._selectedOption = this.buildSelectedOption();\n this.checkCurrentValueValidity();\n\n if (this.availableOptions.length > 0 && this.requestFocus) {\n this.openAutocompleteSelectField();\n this.requestFocus = false;\n }\n }\n\n protected initialize() {\n super.initialize();\n this.loadValues();\n }\n\n private loadValues() {\n let allowedValues = this.schema.allowedValues;\n if (Array.isArray(allowedValues)) {\n this.setValues(allowedValues);\n } else if (this.schema.allowedValues) {\n return this.schema.allowedValues.$load().then((values:CollectionResource) => {\n // The select options of the project shall be sorted\n if (values.count > 0 && (values.elements[0] as any)._type === 'Project') {\n this.setValues(values.elements, true);\n } else {\n this.setValues(values.elements);\n }\n });\n } else {\n this.setValues([]);\n }\n return Promise.resolve();\n }\n\n private checkCurrentValueValidity() {\n if (this.value) {\n this.currentValueInvalid = !!(\n // (If value AND)\n // MultiSelect AND there is no value which href is not in the options hrefs\n (!_.some(this.value, (value:HalResource) => {\n return _.some(this.availableOptions, (option) => (option.$href === value.$href))\n }))\n );\n } else {\n // If no value but required\n this.currentValueInvalid = !!this.schema.required;\n }\n }\n}\n","// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Component} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\n\n@Component({\n template: `\n \n `\n})\nexport class FloatEditFieldComponent extends EditFieldComponent {\n public locale = I18n.locale;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\n\n\n@Component({\n template: `\n \n `\n})\nexport class BooleanEditFieldComponent extends EditFieldComponent {\n public updateValue(newValue:boolean) {\n this.value = newValue;\n this.handler.handleUserSubmit();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from \"@angular/core\";\nimport {SelectEditFieldComponent, ValueOption} from './select-edit-field.component';\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {DebouncedRequestSwitchmap, errorNotificationHandler} from \"core-app/helpers/rxjs/debounced-input-switchmap\";\nimport { take } from 'rxjs/operators';\n\n@Component({\n templateUrl: './work-package-edit-field.component.html'\n})\nexport class WorkPackageEditFieldComponent extends SelectEditFieldComponent {\n /** Keep a switchmap for search term and loading state */\n public requests = new DebouncedRequestSwitchmap(\n (searchTerm:string) => this.loadValues(searchTerm),\n errorNotificationHandler(this.halNotification)\n );\n\n protected initialValueLoading() {\n this.valuesLoaded = false;\n\n // Using this hack with the empty value to have the values loaded initially\n // while avoiding loading it multiple times.\n return new Promise((resolve) => {\n this.requests.output$.pipe(take(1)).subscribe(options => {\n resolve(options);\n });\n\n this.requests.input$.next('');\n });\n }\n\n public get typeahead() {\n if (this.valuesLoaded) {\n return false;\n } else {\n return this.requests.input$;\n }\n }\n\n protected allowedValuesFilter(query?:string):{} {\n let filterParams = super.allowedValuesFilter(query);\n\n if (query) {\n let filters:ApiV3FilterBuilder = new ApiV3FilterBuilder();\n\n filters.add('subjectOrId', '**', [query]);\n\n filterParams = { filters: filters.toJson() };\n }\n\n return filterParams;\n }\n\n protected mapAllowedValue(value:WorkPackageResource|ValueOption):ValueOption {\n if ((value as WorkPackageResource).id) {\n\n let prefix = (value as WorkPackageResource).type ? `${(value as WorkPackageResource).type.name} ` : '';\n let suffix = (value as WorkPackageResource).subject || value.name;\n\n return {\n name: `${prefix}#${ (value as WorkPackageResource).id } ${suffix}`,\n $href: value.$href\n };\n } else {\n return value;\n }\n }\n}\n","\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, OnInit} from \"@angular/core\";\nimport * as moment from \"moment\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\n\n@Component({\n template: `\n \n \n `\n})\nexport class DateEditFieldComponent extends EditFieldComponent implements OnInit {\n @InjectField() readonly timezoneService:TimezoneService;\n @InjectField() opModalService:OpModalService;\n\n ngOnInit() {\n super.ngOnInit();\n }\n\n public onValueSelected(data:string) {\n this.value = this.parser(data);\n this.handler.handleUserSubmit();\n }\n\n public onCancel() {\n this.handler.handleUserCancel();\n }\n\n public parser(data:any) {\n if (moment(data, 'YYYY-MM-DD', true).isValid()) {\n return data;\n } else {\n return null;\n }\n }\n\n public formatter(data:any) {\n if (moment(data, 'YYYY-MM-DD', true).isValid()) {\n var d = this.timezoneService.parseDate(data);\n return this.timezoneService.formattedISODate(d);\n } else {\n return null;\n }\n }\n}\n","// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Component, OnInit, ViewChild, ChangeDetectionStrategy} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {OpCkeditorComponent} from \"core-app/modules/common/ckeditor/op-ckeditor.component\";\nimport {ICKEditorContext, ICKEditorInstance} from \"core-app/modules/common/ckeditor/ckeditor-setup.service\";\n\nexport const formattableFieldTemplate = `\n
    \n
    \n \n \n
    \n \n \n
    \n`;\n\n@Component({\n template: formattableFieldTemplate,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class FormattableEditFieldComponent extends EditFieldComponent implements OnInit {\n public readonly field = this;\n\n // Detect when inner component could not be initalized\n public initializationError = false;\n\n @ViewChild(OpCkeditorComponent, { static: true }) editor:OpCkeditorComponent;\n\n // Values used in template\n public isPreview:boolean = false;\n public previewHtml:string = '';\n public text:any = {};\n\n public editorType = this.resource.getEditorTypeFor(this.field.name);\n\n ngOnInit() {\n super.ngOnInit();\n\n this.handler.registerOnSubmit(() => this.getCurrentValue());\n this.text = {\n attachmentLabel: this.I18n.t('js.label_formattable_attachment_hint'),\n save: this.I18n.t('js.inplace.button_save', {attribute: this.schema.name}),\n cancel: this.I18n.t('js.inplace.button_cancel', {attribute: this.schema.name})\n };\n }\n\n public onCkeditorSetup(editor:ICKEditorInstance) {\n if (!this.resource.isNew) {\n setTimeout(() => editor.editing.view.focus());\n }\n }\n\n public getCurrentValue():Promise {\n return this.editor\n .getTransformedContent()\n .then((val) => {\n this.rawValue = val;\n });\n }\n\n public onContentChange(value:string) {\n // Have the guard clause to avoid the text being set\n // in the changeset when no actual change has taken place.\n if (this.rawValue !== value) {\n this.rawValue = value;\n }\n }\n\n public handleUserSubmit() {\n this.getCurrentValue()\n .then(() => {\n this.handler.handleUserSubmit();\n });\n\n return false;\n }\n\n public get ckEditorContext():ICKEditorContext {\n return {\n resource: this.change.pristineResource,\n macros: 'none' as 'none',\n previewContext: this.previewContext,\n options: { rtl: this.schema.options && this.schema.options.rtl }\n };\n }\n\n private get previewContext() {\n return this.handler.previewContext(this.resource);\n }\n\n public reset() {\n if (this.editor && this.editor.initialized) {\n this.editor.content = this.rawValue;\n\n this.cdRef.markForCheck();\n }\n }\n\n public get rawValue() {\n if (this.value && this.value.raw) {\n return this.value.raw;\n } else {\n return '';\n }\n }\n\n public set rawValue(val:string) {\n this.value = { raw: val };\n }\n\n public isEmpty():boolean {\n return !(this.value && this.value.raw);\n }\n\n protected initialize() {\n if (this.resource.isNew && this.editor) {\n // Reset CKEditor when reloading after type/form changes\n this.reset();\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {Component, OnInit} from \"@angular/core\";\nimport {\n FormattableEditFieldComponent,\n formattableFieldTemplate\n} from \"core-app/modules/fields/edit/field-types/formattable-edit-field.component\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n@Component({\n template: formattableFieldTemplate\n})\nexport class WorkPackageCommentFieldComponent extends FormattableEditFieldComponent implements OnInit {\n public isBusy:boolean = false;\n public name = 'comment';\n\n @InjectField() public ConfigurationService:ConfigurationService;\n\n public get required() {\n return true;\n }\n\n ngOnInit() {\n super.ngOnInit();\n this.rawValue = this.rawValue || '';\n }\n}\n","import {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\nexport function projectStatusCodeCssClass(code:string|null|undefined):string {\n code = ensureDefaultCode(code);\n\n return '-' + code.replace(' ', '-');\n}\n\nexport function projectStatusI18n(code:string|null|undefined, I18n:I18nService):string {\n code = ensureDefaultCode(code);\n\n return I18n.t('js.grid.widgets.project_status.' + code.replace(' ', '_'));\n}\n\nfunction ensureDefaultCode(code:string|null|undefined):string {\n return code ? code : 'not set';\n}","\n \n \n {{item.name}}\n \n \n \n {{item.name}}\n \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {Component, OnInit, ViewChild} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {projectStatusCodeCssClass, projectStatusI18n} from \"core-app/modules/fields/helpers/project-status-helper\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n@Component({\n templateUrl: './project-status-edit-field.component.html',\n styleUrls: ['./project-status-edit-field.component.sass']\n})\nexport class ProjectStatusEditFieldComponent extends EditFieldComponent implements OnInit {\n @ViewChild(NgSelectComponent, {static: true}) public ngSelectComponent:NgSelectComponent;\n @InjectField() I18n!:I18nService;\n\n private _availableStatusCodes:string[] = ['not set', 'off track', 'at risk', 'on track'];\n public currentStatusCode:string = 'not set';\n\n public availableStatuses:any[] = this._availableStatusCodes.map((code:string):any => {\n return {\n code: code,\n name: projectStatusI18n(code, this.I18n),\n colorClass: projectStatusCodeCssClass(code)\n };\n });\n\n public hiddenOverflowContainer = '#content-wrapper';\n public appendToContainer = 'body';\n\n ngOnInit() {\n this.currentStatusCode = this.resource['status'] === null ? 'not set' : this.resource['status'];\n\n // The timeout takes care that the opening is added to the end of the current call stack.\n // Thus we can be sure that the select box is rendered and ready to be opened.\n let that = this;\n window.setTimeout(function () {\n that.ngSelectComponent.open();\n }, 0);\n }\n\n public onChange() {\n this.resource['status'] = this.currentStatusCode === 'not set' ? null : this.currentStatusCode;\n this.handler.handleUserSubmit();\n }\n\n public onOpen() {\n // Force reposition as a workaround for BUG\n // https://github.com/ng-select/ng-select/issues/1259\n setTimeout(() => {\n const component = (this.ngSelectComponent) as any;\n if (component && component.dropdownPanel) {\n component.dropdownPanel._updatePosition();\n }\n\n jQuery(this.hiddenOverflowContainer).one('scroll.autocompleteContainer', () => {\n this.ngSelectComponent.close();\n });\n }, 25);\n }\n\n public onClose() {\n jQuery(this.hiddenOverflowContainer).off('scroll.autocompleteContainer');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from \"@angular/core\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\n\n@Component({\n templateUrl: './text-edit-field.component.html'\n})\nexport class PlainFormattableEditFieldComponent extends EditFieldComponent {\n // only exists because the template is reused and the property is required there.\n public shouldFocus = false;\n\n public get value() {\n if (!this.schema) {\n return '';\n }\n const element = this.resource[this.name];\n\n return element && element.raw || '';\n }\n\n public set value(newValue:string) {\n this.resource[this.name] = { raw: newValue };\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from \"@angular/core\";\nimport {WorkPackageEditFieldComponent} from \"core-app/modules/fields/edit/field-types/work-package-edit-field.component\";\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {\n TimeEntryWorkPackageAutocompleterComponent,\n TimeEntryWorkPackageAutocompleterMode\n} from \"core-app/modules/common/autocomplete/te-work-package-autocompleter.component\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nconst RECENT_TIME_ENTRIES_MAGIC_NUMBER = 30;\n\n@Component({\n templateUrl: './work-package-edit-field.component.html'\n})\nexport class TimeEntryWorkPackageEditFieldComponent extends WorkPackageEditFieldComponent {\n @InjectField() apiV3Service:APIV3Service;\n\n private recentWorkPackageIds:string[];\n\n protected initialize() {\n super.initialize();\n\n // For reasons beyond me, the referenceOutputs variable is not defined at first when editing\n // existing values.\n if (this.referenceOutputs) {\n this.referenceOutputs['modeSwitch'] = (mode:TimeEntryWorkPackageAutocompleterMode) => {\n this.valuesLoaded = false;\n let lastValue = this.requests.lastRequestedValue!;\n\n // Hack to provide a new value to \"reset\" the input.\n // Only the second input is actually processed as the input is debounced.\n this.requests.input$.next('_/&\"()____');\n this.requests.input$.next(lastValue);\n };\n }\n }\n\n public autocompleterComponent() {\n return TimeEntryWorkPackageAutocompleterComponent;\n }\n\n // Although the schema states the work packages to not be required,\n // as time entries can also be assigned to a project, we want to only assign\n // time entries to work packages and thus require a value.\n // The back end will have to be changed in due time but not as long as there is still a rails based\n // time entry view in the application.\n protected isRequired() {\n return true;\n }\n\n // We fetch the last RECENT_TIME_ENTRIES_MAGIC_NUMBER time entries by that user. We then use it to fetch the work packages\n // associated with the time entries so that we have the most recent work packages the user logged time on.\n // As a worst case, the user logged RECENT_TIME_ENTRIES_MAGIC_NUMBER times on one work package so we can not guarantee to actually have\n // a fixed number returned.\n protected loadAllowedValues(query?:string) {\n if (!this.recentWorkPackageIds) {\n return this\n .apiV3Service\n .time_entries\n .list({ filters: [['user_id', '=', ['me']]], sortBy: [[\"updated_at\", \"desc\"]], pageSize: RECENT_TIME_ENTRIES_MAGIC_NUMBER })\n .toPromise()\n .then(collection => {\n this.recentWorkPackageIds = collection\n .elements\n .map((timeEntry) => timeEntry.workPackage.idFromLink)\n .filter((v, i, a) => a.indexOf(v) === i);\n\n return this.fetchAllowedValueQuery(query);\n });\n } else {\n return this.fetchAllowedValueQuery(query);\n }\n }\n\n protected allowedValuesFilter(query?:string):{} {\n let filters:ApiV3FilterBuilder = new ApiV3FilterBuilder();\n\n if ((this._autocompleterComponent as TimeEntryWorkPackageAutocompleterComponent).mode === 'recent') {\n filters.add('id', '=', this.recentWorkPackageIds);\n }\n\n if (query) {\n filters.add('subjectOrId', '**', [query]);\n }\n\n return { filters: filters.toJson() };\n }\n\n protected sortValues(availableValues:HalResource[]) {\n if ((this._autocompleterComponent as TimeEntryWorkPackageAutocompleterComponent).mode === 'recent') {\n return this.sortValuesByRecentIds(availableValues);\n } else {\n return super.sortValues(availableValues);\n }\n }\n\n protected sortValuesByRecentIds(availableValues:HalResource[]) {\n return availableValues\n .sort((a, b) => {\n return this.recentWorkPackageIds.indexOf(a.id!) - this.recentWorkPackageIds.indexOf(b.id!);\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {DateKeys} from \"core-components/datepicker/datepicker.modal\";\nimport {DatePicker} from \"core-app/modules/common/op-date-picker/datepicker\";\nimport {DateOption} from \"flatpickr/dist/types/options\";\n\n@Injectable({ providedIn: 'root' })\nexport class DatePickerModalHelper {\n public currentlyActivatedDateField:DateKeys;\n\n /**\n * Map the date to the internal format,\n * setting to null if it's empty.\n * @param key\n */\n public mappedDate(date:string):string|null {\n return date === '' ? null : date;\n }\n\n public parseDate(date:Date|string):Date|'' {\n if (date instanceof Date) {\n return new Date(date.setHours(0,0,0,0));\n } else if (date === '') {\n return '';\n } else {\n return new Date(new Date(date).setHours(0,0,0,0));\n }\n }\n\n public validDate(date:Date|string) {\n return (date instanceof Date) ||\n (date === '') ||\n !!new Date(date).valueOf();\n }\n\n public sortDates(dates:Date[]):Date[] {\n return dates.sort(function(a:Date, b:Date) {\n return a.getTime() - b.getTime();\n });\n }\n\n public areDatesEqual(firstDate:Date|string, secondDate:Date|string) {\n let parsedDate1 = this.parseDate(firstDate);\n let parsedDate2 = this.parseDate(secondDate);\n\n if ((typeof(parsedDate1) === 'string') || (typeof(parsedDate2) === 'string')) {\n return false;\n } else {\n return parsedDate1.getTime() === parsedDate2.getTime();\n }\n }\n\n public setCurrentActivatedField(val:DateKeys) {\n this.currentlyActivatedDateField = val;\n }\n\n public toggleCurrentActivatedField(dates:{ [key in DateKeys]:string }, datePicker:DatePicker) {\n this.currentlyActivatedDateField = this.currentlyActivatedDateField === 'start' ? 'end' : 'start';\n this.setDatepickerRestrictions(dates, datePicker);\n }\n\n public isStateOfCurrentActivatedField(val:DateKeys):boolean {\n return this.currentlyActivatedDateField === val;\n }\n\n public setDates(dates:DateOption|DateOption[], datePicker:DatePicker, enforceDate?:Date) {\n let currentMonth = datePicker.datepickerInstance.currentMonth;\n let currentYear = datePicker.datepickerInstance.currentYear;\n datePicker.setDates(dates);\n\n if (enforceDate) {\n datePicker.datepickerInstance.currentMonth = enforceDate.getMonth();\n datePicker.datepickerInstance.currentYear = enforceDate.getFullYear();\n } else {\n // Keep currently active month and avoid jump because of two-month layout\n datePicker.datepickerInstance.currentMonth = currentMonth;\n datePicker.datepickerInstance.currentYear = currentYear;\n }\n\n datePicker.datepickerInstance.redraw();\n }\n\n public setDatepickerRestrictions(dates:{ [key in DateKeys]:string }, datePicker:DatePicker) {\n if (!dates.start && !dates.end) {\n return;\n }\n\n let disableFunction:Function = (date:Date) => {\n return false;\n };\n\n if (this.isStateOfCurrentActivatedField('start') && dates.end) {\n disableFunction = (date:Date) => {\n return date.getTime() > new Date(dates.end).setHours(0,0,0,0);\n };\n } else if (this.isStateOfCurrentActivatedField('end') && dates.start) {\n disableFunction = (date:Date) => {\n return date.getTime() < new Date(dates.start).setHours(0,0,0,0);\n };\n }\n\n datePicker.datepickerInstance.set('disable', [disableFunction]);\n }\n\n public setRangeClasses(dates:{ [key in DateKeys]:string }) {\n if (!dates.start || !dates.end || (dates.start === dates.end)) {\n return;\n }\n\n var monthContainer = document.getElementsByClassName('dayContainer');\n // For each container of the two-month layout, set the highlighting classes\n for (let i = 0; i < monthContainer.length; i++) {\n this.highlightRangeInSingleMonth(monthContainer[i], dates);\n }\n }\n\n private highlightRangeInSingleMonth(container:Element, dates:{ [key in DateKeys]:string }) {\n var selectedElements = jQuery(container).find('.flatpickr-day.selected');\n if (selectedElements.length === 2) {\n // Both dates are in the same month\n selectedElements[0].classList.add('startRange');\n selectedElements[1].classList.add('endRange');\n\n this.selectRangeFromUntil(selectedElements[0], selectedElements[1]);\n } else if (selectedElements.length === 1) {\n // Only one date is in this month\n if (this.datepickerShowsDate(dates.start, selectedElements[0])) {\n selectedElements[0].classList.add('startRange');\n this.selectRangeFromUntil(selectedElements[0], '');\n } else if (this.datepickerShowsDate(dates.end, selectedElements[0])) {\n let firstDay = jQuery(container).find('.flatpickr-day')[0];\n\n selectedElements[0].classList.add('endRange');\n firstDay.classList.add('inRange');\n\n this.selectRangeFromUntil(firstDay, selectedElements[0]);\n }\n } else if (this.datepickerIsInDateRange(container, dates)) {\n // No date is in this month, but the month is completely between start and end date\n jQuery(container).find('.flatpickr-day').addClass('inRange');\n }\n }\n\n private datepickerShowsDate(date:string, selectedElement:Element):boolean {\n return new Date(selectedElement.getAttribute('aria-label')!).toDateString() === new Date(date).toDateString();\n }\n\n private datepickerIsInDateRange(container:Element, dates:{ [key in DateKeys]:string }):boolean {\n var firstDayOfMonthElement = jQuery(container).find('.flatpickr-day:not(.hidden)')[0];\n var firstDayOfMonth = new Date(firstDayOfMonthElement.getAttribute('aria-label')!);\n\n return firstDayOfMonth <= new Date(dates.end) &&\n firstDayOfMonth >= new Date(dates.start);\n }\n\n private selectRangeFromUntil(from:Element, until:string|Element) {\n jQuery(from).nextUntil(until).addClass('inRange');\n }\n}\n","
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n \n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n\n \n
    \n \n
    \n
    \n \n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n

    \n
    \n \n

    \n
    \n
    \n
    \n
    \n \n \n \n\n
    \n \n \n
    \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n Inject,\n Injector, ViewChild,\n ViewEncapsulation\n} from \"@angular/core\";\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {DatePicker} from \"core-app/modules/common/op-date-picker/datepicker\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {DatePickerModalHelper} from \"core-components/datepicker/datepicker.modal.helper\";\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\n\nexport type DateKeys = 'date'|'start'|'end';\n\n@Component({\n templateUrl: './datepicker.modal.html',\n styleUrls: ['./datepicker.modal.sass', './datepicker_mobile.modal.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None\n})\nexport class DatePickerModal extends OpModalComponent implements AfterViewInit {\n @InjectField() I18n!:I18nService;\n @InjectField() timezoneService:TimezoneService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() datepickerHelper:DatePickerModalHelper;\n @InjectField() browserDetector:BrowserDetector;\n\n @ViewChild('modalContainer') modalContainer:ElementRef;\n\n text = {\n save: this.I18n.t('js.button_save'),\n cancel: this.I18n.t('js.button_cancel'),\n clear: this.I18n.t('js.work_packages.button_clear'),\n manualScheduling: this.I18n.t('js.scheduling.manual'),\n date: this.I18n.t('js.work_packages.properties.date'),\n startDate: this.I18n.t('js.work_packages.properties.startDate'),\n endDate: this.I18n.t('js.work_packages.properties.dueDate'),\n placeholder: this.I18n.t('js.placeholders.default'),\n today: this.I18n.t('js.label_today'),\n isParent: this.I18n.t('js.work_packages.scheduling.is_parent'),\n isSwitchedFromManualToAutomatic: this.I18n.t('js.work_packages.scheduling.is_switched_from_manual_to_automatic')\n };\n public onDataUpdated = new EventEmitter();\n\n public singleDate = false;\n\n public scheduleManually = false;\n\n public htmlId:string = '';\n\n public dates:{ [key in DateKeys]:string } = {\n date: '',\n start: '',\n end: ''\n };\n\n private changeset:ResourceChangeset;\n\n private datePickerInstance:DatePicker;\n\n constructor(readonly injector:Injector,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef,\n readonly configurationService:ConfigurationService) {\n super(locals, cdRef, elementRef);\n this.changeset = locals.changeset;\n this.htmlId = `wp-datepicker-${locals.fieldName}`;\n\n this.singleDate = this.changeset.isWritable('date');\n this.scheduleManually = this.changeset.value('scheduleManually');\n\n if (this.singleDate) {\n this.dates.date = this.changeset.value('date');\n this.datepickerHelper.setCurrentActivatedField('date');\n } else {\n this.dates.start = this.changeset.value('startDate');\n this.dates.end = this.changeset.value('dueDate');\n this.datepickerHelper.setCurrentActivatedField(this.initialActivatedField());\n }\n }\n\n ngAfterViewInit():void {\n if (this.isSchedulable) {\n this.showDateSelection();\n }\n\n this.onDataChange();\n }\n\n changeSchedulingMode() {\n this.scheduleManually = !this.scheduleManually;\n this.cdRef.detectChanges();\n\n if (this.scheduleManually) {\n this.showDateSelection();\n } else if (this.isParent) {\n this.removeDateSelection();\n }\n }\n\n save():void {\n if (!this.isSavable) {\n return;\n }\n\n // Apply the changed scheduling mode if any\n this.changeset.setValue('scheduleManually', this.scheduleManually);\n\n // Apply the dates if they could be changed\n if (this.isSchedulable) {\n if (this.singleDate) {\n this.changeset.setValue('date', this.datepickerHelper.mappedDate(this.dates.date));\n } else {\n this.changeset.setValue('startDate', this.datepickerHelper.mappedDate(this.dates.start));\n this.changeset.setValue('dueDate', this.datepickerHelper.mappedDate(this.dates.end));\n }\n }\n\n this.closeMe();\n }\n\n cancel():void {\n this.closeMe();\n }\n\n clear(key:DateKeys):void {\n this.dates[key] = '';\n this.enforceManualChangesToDatepicker();\n }\n\n updateDate(key:DateKeys, val:string) {\n // Expected minimal format YYYY-M-D => 8 characters OR empty\n if (val.length >= 8 || val.length === 0) {\n this.dates[key] = val;\n if (this.datepickerHelper.validDate(val) && this.datePickerInstance) {\n this.enforceManualChangesToDatepicker(false);\n }\n }\n }\n\n setToday(key:DateKeys) {\n let today = this.datepickerHelper.parseDate(new Date());\n this.dates[key] = this.timezoneService.formattedISODate(today);\n\n (today instanceof Date) ? this.enforceManualChangesToDatepicker(true, today) : this.enforceManualChangesToDatepicker();\n }\n\n reposition(element:JQuery, target:JQuery) {\n element.position({\n my: 'left top',\n at: 'left bottom',\n of: target,\n collision: 'flipfit'\n });\n }\n\n setCurrentActivatedField(key:DateKeys) {\n this.datepickerHelper.setCurrentActivatedField(key);\n this.datepickerHelper.setDatepickerRestrictions(this.dates, this.datePickerInstance);\n this.datepickerHelper.setRangeClasses(this.dates);\n }\n\n showTodayLink(key:DateKeys):boolean {\n if (!this.isSchedulable) {\n return false;\n }\n\n if (key === 'start') {\n return this.datepickerHelper.parseDate(new Date()) <= this.datepickerHelper.parseDate(this.dates.end);\n } else {\n return this.datepickerHelper.parseDate(new Date()) >= this.datepickerHelper.parseDate(this.dates.start);\n }\n }\n\n /**\n * Returns whether the user can alter the dates of the work package.\n * The work package is always schedulable if the work package scheduled manually.\n * But it might also be altered in automatic scheduling mode if it does not have children and if there was\n * no switch from manual to automatic scheduling.\n * The later is necessary as we cannot correctly calculate the resulting dates in the frontend.\n */\n get isSchedulable():boolean {\n return this.scheduleManually || (!this.isParent && !this.isSwitchedFromManualToAutomatic);\n }\n\n get isSavable():boolean {\n return this.isSchedulable || this.isSwitchedFromManualToAutomatic;\n }\n\n /**\n * Determines whether the work package is a parent. It does so\n * by checking the children links.\n */\n get isParent():boolean {\n return this.changeset.projectedResource.$links.children && this.changeset.projectedResource.$links.children.length > 0;\n }\n\n get isSwitchedFromManualToAutomatic():boolean {\n return !this.scheduleManually && this.changeset.value('scheduleManually');\n }\n\n private showDateSelection() {\n this.initializeDatepicker();\n this.datepickerHelper.setDatepickerRestrictions(this.dates, this.datePickerInstance);\n this.datepickerHelper.setRangeClasses(this.dates);\n }\n\n private removeDateSelection() {\n this.datePickerInstance.destroy();\n }\n\n private initializeDatepicker() {\n this.datePickerInstance?.destroy();\n this.datePickerInstance = new DatePicker(\n '#flatpickr-input',\n this.singleDate ? this.dates.date : [this.dates.start, this.dates.end],\n {\n mode: this.singleDate ? 'single' : 'multiple',\n showMonths: this.browserDetector.isMobile ? 1 : 2,\n inline: true,\n onChange: (dates:Date[]) => {\n this.handleDatePickerChange(dates);\n\n this.onDataChange();\n },\n onMonthChange: () => { this.datepickerHelper.setRangeClasses(this.dates); },\n onYearChange: () => { this.datepickerHelper.setRangeClasses(this.dates); },\n },\n undefined,\n this.configurationService\n );\n }\n\n private enforceManualChangesToDatepicker(toggleField:boolean = true, enforceDate?:Date) {\n if (this.singleDate) {\n let date = this.datepickerHelper.parseDate(this.dates.date);\n this.datepickerHelper.setDates(date, this.datePickerInstance, enforceDate);\n } else {\n let dates = [this.datepickerHelper.parseDate(this.dates.start), this.datepickerHelper.parseDate(this.dates.end)];\n this.datepickerHelper.setDates(dates, this.datePickerInstance, enforceDate);\n\n this.setRangeClassesAndToggleActiveField(toggleField);\n }\n }\n\n private handleDatePickerChange(dates:Date[]) {\n switch (dates.length) {\n case 0: {\n // In case we removed the only value by clicking on a already selected date within the datepicker:\n if (this.dates.start || this.dates.end) {\n this.setDateAndToggleActiveField(this.dates.start || this.dates.end);\n }\n\n break;\n }\n case 1: {\n if (this.singleDate) {\n this.dates.date = this.timezoneService.formattedISODate(dates[0]);\n } else {\n // In case we removed a value by clicking on a already selected date within the datepicker:\n if (this.dates.start && this.dates.end) {\n // Both dates are the same, so it is correct to only highlight one date\n if (this.dates.start === this.dates.end) {\n return;\n }\n\n // I wanted to set the new start date to the preselected endDate OR\n // I wanted to set the new end date to the preselected startDate\n if ((this.datepickerHelper.isStateOfCurrentActivatedField('start') && this.datepickerHelper.areDatesEqual(this.dates.start, dates[0])) ||\n (this.datepickerHelper.isStateOfCurrentActivatedField('end') && this.datepickerHelper.areDatesEqual(this.dates.end, dates[0]))) {\n\n let otherDateIndex:DateKeys = this.datepickerHelper.isStateOfCurrentActivatedField('start') ? 'end' : 'start';\n this.setDateAndToggleActiveField(this.dates[otherDateIndex]);\n } else {\n // I clicked on the already set start or end date (and thus removed it):\n // We restore both values\n this.enforceManualChangesToDatepicker(true);\n }\n } else {\n // It is the first value we set (either start or end date)\n this.setDateAndToggleActiveField(this.timezoneService.formattedISODate(dates[0]), false);\n }\n }\n\n break;\n }\n case 2: {\n if ((!this.dates.end && this.datepickerHelper.isStateOfCurrentActivatedField('start')) ||\n (!this.dates.start && this.datepickerHelper.isStateOfCurrentActivatedField('end'))) {\n // If we change a start date when no end date is set, we keep only the newly clicked value and not both\n this.overwriteDatePickerWithNewDates([dates[1]]);\n } else {\n // Sort dates so that the start date is always first\n if (dates[0] > dates[1]) {\n dates = this.datepickerHelper.sortDates(dates);\n this.datepickerHelper.setDates(dates, this.datePickerInstance);\n }\n\n let index = this.datepickerHelper.isStateOfCurrentActivatedField('start') ? 0 : 1;\n this.dates[this.datepickerHelper.currentlyActivatedDateField] = this.timezoneService.formattedISODate(dates[index]);\n\n this.setRangeClassesAndToggleActiveField();\n }\n\n break;\n }\n default: {\n // Reset the date picker with the two new values\n if (this.datepickerHelper.isStateOfCurrentActivatedField('start')) {\n this.overwriteDatePickerWithNewDates([dates[2], dates[1]]);\n } else {\n this.overwriteDatePickerWithNewDates([dates[0], dates[2]]);\n }\n\n break;\n }\n }\n\n this.cdRef.detectChanges();\n }\n\n private overwriteDatePickerWithNewDates(dates:Date[]) {\n this.datepickerHelper.setDates(dates, this.datePickerInstance);\n this.handleDatePickerChange(dates);\n }\n\n private setDateAndToggleActiveField(newDate:string, forceDatePickerUpdate:boolean = true) {\n this.dates[this.datepickerHelper.currentlyActivatedDateField] = newDate;\n if (forceDatePickerUpdate) {\n this.datepickerHelper.setDates([this.datepickerHelper.parseDate(newDate)], this.datePickerInstance);\n }\n this.datepickerHelper.toggleCurrentActivatedField(this.dates, this.datePickerInstance);\n }\n\n private setRangeClassesAndToggleActiveField(toggleField:boolean = true) {\n if (toggleField) {\n this.datepickerHelper.toggleCurrentActivatedField(this.dates, this.datePickerInstance);\n }\n this.datepickerHelper.setRangeClasses(this.dates);\n }\n\n private onDataChange() {\n let date = this.dates.date || '';\n let start = this.dates.start || '';\n let end = this.dates.end || '';\n\n let output = this.singleDate ? date : start + ' - ' + end;\n this.onDataUpdated.emit(output);\n }\n\n private initialActivatedField():DateKeys {\n return this.locals.fieldName === 'dueDate' || (this.dates.start && !this.dates.end) ? 'end' : 'start';\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, OnDestroy, OnInit} from \"@angular/core\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {DatePickerModal} from \"core-components/datepicker/datepicker.modal\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {take} from \"rxjs/operators\";\nimport {DateEditFieldComponent} from \"core-app/modules/fields/edit/field-types/date-edit-field.component\";\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\n\n@Component({\n template: `\n \n `\n})\nexport class CombinedDateEditFieldComponent extends DateEditFieldComponent implements OnInit, OnDestroy {\n @InjectField() readonly timezoneService:TimezoneService;\n @InjectField() opModalService:OpModalService;\n\n dates:string = '';\n text_no_start_date = this.I18n.t('js.label_no_start_date');\n text_no_due_date = this.I18n.t('js.label_no_due_date');\n\n private modal:OpModalComponent;\n\n ngOnInit() {\n super.ngOnInit();\n\n this.handler\n .$onUserActivate\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.showDatePickerModal();\n });\n }\n\n ngOnDestroy() {\n super.ngOnDestroy();\n this.modal?.closeMe();\n }\n\n public handleClick() {\n this.showDatePickerModal();\n }\n\n private showDatePickerModal():void {\n const modal = this.modal = this\n .opModalService\n .show(DatePickerModal, this.injector, { changeset: this.change, fieldName: this.name });\n\n setTimeout(() => {\n const modalElement = jQuery(modal.elementRef.nativeElement).find('.datepicker-modal');\n const field = jQuery(this.elementRef.nativeElement);\n modal.reposition(modalElement, field);\n });\n\n modal\n .onDataUpdated\n .subscribe((dates:string) => {\n this.dates = dates;\n this.cdRef.detectChanges();\n });\n\n modal\n .closingEvent\n .pipe(take(1))\n .subscribe(() => {\n this.handler.handleUserSubmit();\n });\n }\n\n // Overwrite super in order to set the inital dates.\n protected initialize() {\n super.initialize();\n\n // this breaks the preceived abstraction of the edit fields. But the date picker\n // is already highly specific to start and due Date.\n this.dates = `${this.currentStartDate} - ${this.currentDueDate}`;\n }\n\n protected get currentStartDate():string {\n return this.resource.startDate || this.text_no_start_date;\n }\n\n protected get currentDueDate():string {\n return this.resource.dueDate || this.text_no_due_date;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class TextDisplayField extends DisplayField {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class FloatDisplayField extends DisplayField {\n\n public get valueString():string {\n if (this.value == null) {\n return '';\n }\n\n return this.value.toLocaleString(\n this.I18n.locale,\n { useGrouping: true, maximumFractionDigits: 20 }\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class IntegerDisplayField extends DisplayField {\n public get value() {\n return parseInt(this.resource[this.name]);\n }\n\n public isEmpty():boolean {\n return isNaN(this.value);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class ResourceDisplayField extends DisplayField {\n public get value() {\n if (this.schema) {\n return this.attribute && this.attribute.name;\n }\n else {\n return null;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {ExpressionService} from \"../../../../../../common/expression.service\";\nimport {ApplicationRef} from \"@angular/core\";\nimport {DynamicBootstrapper} from \"core-app/globals/dynamic-bootstrapper\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class FormattableDisplayField extends DisplayField {\n\n @InjectField() readonly appRef:ApplicationRef;\n\n public render(element:HTMLElement, displayText:string, options:any = {}):void {\n let div = document.createElement('div');\n\n div.classList.add(\n 'read-value--html',\n 'highlight',\n 'op-uc-container',\n 'op-uc-container_reduced-headings',\n '-multiline',\n );\n if (options.rtl) {\n div.classList.add('-rtl');\n }\n\n div.innerHTML = displayText;\n\n element.innerHTML = '';\n element.appendChild(div);\n\n // Allow embeddable rendered content\n DynamicBootstrapper.bootstrapOptionalEmbeddable(this.appRef, div);\n }\n\n public get isFormattable():boolean {\n return true;\n }\n\n public get value() {\n if (!this.schema) {\n return null;\n }\n const element = this.resource[this.name];\n if (!(element && element.html)) {\n return '';\n }\n\n return this.unescape(element.html);\n }\n\n // Escape the given HTML string from the backend, which contains escaped Angular expressions.\n // Since formattable fields are only binded to but never evaluated, we can safely remove these expressions.\n protected unescape(html:string) {\n if (html) {\n return ExpressionService.unescape(html);\n } else {\n return '';\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nexport class ExpressionService {\n\n // This is what returned by rails-angular-xss when it discovers double open curly braces\n // See https://github.com/opf/rails-angular-xss for more information.\n public static get UNESCAPED_EXPRESSION() {\n return '{{';\n }\n\n public static get ESCAPED_EXPRESSION() {\n return '{{ \\\\$root\\\\.DOUBLE_LEFT_CURLY_BRACE }}';\n }\n\n public static escape(input:string) {\n return input.replace(new RegExp(this.UNESCAPED_EXPRESSION, 'g'), this.ESCAPED_EXPRESSION);\n }\n\n public static unescape(input:string) {\n return input.replace(new RegExp(this.ESCAPED_EXPRESSION, 'g'), this.UNESCAPED_EXPRESSION);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class DurationDisplayField extends DisplayField {\n @InjectField() timezoneService:TimezoneService;\n\n private derivedText = this.I18n.t('js.label_value_derived_from_children');\n\n public get valueString() {\n return this.timezoneService.formattedDuration(this.value);\n }\n\n /**\n * Duration fields may have an additional derived value\n */\n public get derivedPropertyName() {\n return \"derived\" + this.name.charAt(0).toUpperCase() + this.name.slice(1);\n }\n\n public get derivedValue():string|null {\n return this.resource[this.derivedPropertyName];\n }\n\n public get derivedValueString():string {\n const value = this.derivedValue;\n\n if (value) {\n return this.timezoneService.formattedDuration(value);\n } else {\n return this.placeholder;\n }\n }\n\n public render(element:HTMLElement, displayText:string):void {\n if (this.isEmpty()) {\n element.textContent = this.placeholder;\n return;\n }\n\n element.classList.add('split-time-field');\n let value = this.value;\n let actual:number = (value && this.timezoneService.toHours(value)) || 0;\n\n if (actual !== 0) {\n this.renderActual(element, displayText);\n }\n\n let derived = this.derivedValue;\n if (derived && this.timezoneService.toHours(derived) !== 0) {\n this.renderDerived(element, this.derivedValueString, actual !== 0);\n }\n }\n\n public renderActual(element:HTMLElement, displayText:string):void {\n const span = document.createElement('span');\n\n span.textContent = displayText;\n span.title = this.valueString;\n span.classList.add('-actual-value');\n\n element.appendChild(span);\n }\n\n public renderDerived(element:HTMLElement, displayText:string, actualPresent:boolean):void {\n const span = document.createElement('span');\n\n span.setAttribute('title', this.texts.empty);\n span.textContent = '(' + (actualPresent ? '+' : '') + displayText + ')';\n span.title = `${this.derivedValueString} ${this.derivedText}`;\n span.classList.add('-derived-value');\n\n if (actualPresent) {\n span.classList.add('-with-actual-value');\n }\n\n element.appendChild(span);\n }\n\n public get title():string|null {\n return null; // we want to render separate titles ourselves\n }\n\n public isEmpty():boolean {\n const value = this.value;\n const derived = this.derivedValue;\n\n const valueEmpty = !value || this.timezoneService.toHours(value) === 0;\n const derivedEmpty = !derived || this.timezoneService.toHours(derived) === 0;\n\n\n return valueEmpty && derivedEmpty;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class DateTimeDisplayField extends DisplayField {\n @InjectField() timezoneService:TimezoneService;\n\n public get valueString() {\n if (this.value) {\n return this.timezoneService.formattedDatetime(this.value);\n }\n\n return '';\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class BooleanDisplayField extends DisplayField {\n\n public get valueString() {\n return this.translatedValue();\n }\n\n public get placeholder() {\n return this.translatedValue();\n }\n\n public translatedValue() {\n if (this.value) {\n return this.I18n.t('js.general_text_yes');\n } else {\n return this.I18n.t('js.general_text_no');\n }\n }\n\n public isEmpty():boolean {\n // We treat an empty value the same as if the user had set\n // the value to false;\n return false;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class WorkPackageDisplayField extends DisplayField {\n\n public text = {\n none: this.I18n.t('js.filter.noneElement')\n };\n\n public get value() {\n return this.resource[this.name];\n }\n\n public get title() {\n if (this.isEmpty()) {\n return this.text.none;\n } else {\n return this.value.name;\n }\n }\n\n public get wpId() {\n if (this.isEmpty()) {\n return null;\n }\n\n if (this.value.$loaded) {\n return this.value.id;\n }\n\n // Read WP ID from href\n return this.value.href.match(/(\\d+)$/)[0];\n }\n\n public get valueString() {\n // cannot display the type name easily here as it may not be loaded\n return `#${ this.wpId } ${ this.title }`;\n }\n\n public isEmpty():boolean {\n return !this.value;\n }\n\n public get unknownAttribute():boolean {\n return false;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport { DurationDisplayField } from './duration-display-field.module';\nimport { PathHelperService } from 'core-app/modules/common/path-helper/path-helper.service';\nimport { ProjectResource } from \"core-app/modules/hal/resources/project-resource\";\nimport { InjectField } from \"core-app/helpers/angular/inject-field.decorator\";\nimport * as URI from 'urijs';\nimport { TimeEntryCreateService } from 'core-app/modules/time_entries/create/create.service';\nimport { WorkPackageResource } from \"core-app/modules/hal/resources/work-package-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class WorkPackageSpentTimeDisplayField extends DurationDisplayField {\n public text = {\n linkTitle: this.I18n.t('js.work_packages.message_view_spent_time'),\n logTime: this.I18n.t('js.button_log_time')\n };\n\n @InjectField() PathHelper:PathHelperService;\n @InjectField(TimeEntryCreateService, null) timeEntryCreateService:TimeEntryCreateService;\n @InjectField() apiV3Service:APIV3Service;\n\n public render(element:HTMLElement, displayText:string):void {\n if (!this.value) {\n return;\n }\n\n const link = document.createElement('a');\n link.textContent = displayText;\n link.setAttribute('title', this.text.linkTitle);\n link.setAttribute('class', 'time-logging--value');\n\n if (this.resource.project) {\n const wpID = this.resource.id.toString();\n this\n .apiV3Service\n .projects\n .id(this.resource.project)\n .get()\n .subscribe((project:ProjectResource) => {\n // Link to the cost report having the work package filter preselected. No grouping.\n const href = URI(this.PathHelper.projectTimeEntriesPath(project.identifier))\n .search(`fields[]=WorkPackageId&operators[WorkPackageId]=%3D&values[WorkPackageId]=${wpID}&set_filter=1`)\n .toString();\n\n link.href = href;\n });\n }\n\n element.innerHTML = '';\n element.appendChild(link);\n\n this.appendTimelogLink(element);\n }\n\n private appendTimelogLink(element:HTMLElement) {\n if (this.timeEntryCreateService && this.resource.logTime) {\n const timelogElement = document.createElement('a');\n timelogElement.setAttribute('class', 'icon icon-time');\n timelogElement.setAttribute('href', '');\n timelogElement.setAttribute('title', this.text.logTime);\n\n element.appendChild(timelogElement);\n\n timelogElement.addEventListener('click', this.showTimelogWidget.bind(this, this.resource));\n }\n }\n\n private showTimelogWidget(wp:WorkPackageResource) {\n this.timeEntryCreateService\n .create(moment(new Date()), wp, false)\n .catch(() => {\n // do nothing, the user closed without changes\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class IdDisplayField extends DisplayField {\n public text = {\n linkTitle: this.I18n.t('js.work_packages.message_successful_show_in_fullscreen')\n };\n\n public get value() {\n if (this.resource.isNew) {\n return null;\n }\n else {\n return this.resource[this.name];\n }\n }\n\n public render(element:HTMLElement, displayText:string):void {\n if (!this.value) {\n return;\n }\n element.textContent = displayText;\n }\n\n public isEmpty():boolean {\n return false;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {HighlightableDisplayField} from \"core-app/modules/fields/display/field-types/highlightable-display-field.module\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\n\nexport class HighlightedResourceDisplayField extends HighlightableDisplayField {\n\n public render(element:HTMLElement, displayText:string):void {\n super.render(element, displayText);\n\n if (this.shouldHighlight) {\n this.addHighlight(element);\n }\n }\n\n public get value() {\n if (this.schema) {\n return this.attribute && this.attribute.name;\n }\n else {\n return null;\n }\n }\n\n private addHighlight(element:HTMLElement):void {\n if (this.attribute instanceof HalResource) {\n const hlClass = Highlighting.inlineClass(this.name, this.attribute.id!);\n element.classList.add(hlClass);\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HighlightedResourceDisplayField} from \"core-app/modules/fields/display/field-types/highlighted-resource-display-field.module\";\n\nexport class TypeDisplayField extends HighlightedResourceDisplayField {\n // Type will always be highlighted\n public get shouldHighlight() {\n return true;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {UserAvatarRendererService} from \"core-components/user/user-avatar/user-avatar-renderer.service\";\n\nexport class UserDisplayField extends DisplayField {\n @InjectField() avatarRenderer:UserAvatarRendererService;\n\n public get value() {\n if (this.schema) {\n return this.attribute && this.attribute.name;\n } else {\n return null;\n }\n }\n\n public render(element:HTMLElement, displayText:string):void {\n if (this.placeholder === displayText) {\n this.renderEmpty(element);\n } else {\n this.avatarRenderer.render(\n element,\n this.attribute,\n );\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ResourcesDisplayField} from \"./resources-display-field.module\";\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {UserAvatarRendererService} from \"core-components/user/user-avatar/user-avatar-renderer.service\";\nimport {cssClassCustomOption} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class MultipleUserFieldModule extends ResourcesDisplayField {\n @InjectField() avatarRenderer:UserAvatarRendererService;\n\n public render(element:HTMLElement, displayText:string):void {\n const names = this.value;\n element.innerHTML = '';\n element.setAttribute('title', names.join(', '));\n\n if (names.length === 0) {\n this.renderEmpty(element);\n } else {\n this.renderValues(this.attribute, element);\n }\n }\n\n /**\n * Renders at most the first two values, followed by a badge indicating\n * the total count.\n */\n protected renderValues(values:UserResource[], element:HTMLElement) {\n const content = document.createDocumentFragment();\n const divContainer = document.createElement('div');\n divContainer.classList.add(cssClassCustomOption);\n content.appendChild(divContainer);\n\n this.renderAbridgedValues(divContainer, values);\n\n if (values.length > 2) {\n const dots = document.createElement('span');\n dots.innerHTML = '... ';\n divContainer.appendChild(dots);\n\n const badge = this.optionDiv(values.length.toString(), 'badge', '-secondary');\n content.appendChild(badge);\n }\n\n element.appendChild(content);\n\n }\n\n public renderAbridgedValues(element:HTMLElement, values:UserResource[]) {\n const valueForDisplay = _.take(values, 2);\n this.avatarRenderer.renderMultiple(element, valueForDisplay);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {KeepTabService} from 'core-components/wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {StateService} from '@uirouter/core';\nimport {UiStateLinkBuilder} from \"core-components/wp-fast-table/builders/ui-state-link-builder\";\nimport {IdDisplayField} from \"core-app/modules/fields/display/field-types/id-display-field.module\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class WorkPackageIdDisplayField extends IdDisplayField {\n @InjectField() $state!:StateService;\n @InjectField() keepTab!:KeepTabService;\n \n private uiStateBuilder:UiStateLinkBuilder = new UiStateLinkBuilder(this.$state, this.keepTab);\n\n public render(element:HTMLElement, displayText:string):void {\n if (!this.value) {\n return;\n }\n let link = this.uiStateBuilder.linkToShow(\n this.value,\n displayText,\n this.value\n );\n\n element.appendChild(link);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {projectStatusCodeCssClass, projectStatusI18n} from \"core-app/modules/fields/helpers/project-status-helper\";\n\n\nexport class ProjectStatusDisplayField extends DisplayField {\n public render(element:HTMLElement, displayText:string):void {\n const code = this.value;\n\n const bulb = document.createElement('span');\n bulb.classList.add('project-status--bulb', projectStatusCodeCssClass(code));\n\n const name = document.createElement('span');\n name.classList.add('project-status--name', projectStatusCodeCssClass(code));\n name.textContent = projectStatusI18n(code, this.I18n);\n\n element.innerHTML = '';\n element.appendChild(bulb);\n element.appendChild(name);\n\n if (this.writable) {\n const pulldown = document.createElement('span');\n pulldown.classList.add('project-status--pulldown-icon', 'icon', 'icon-pulldown');\n\n element.appendChild(pulldown);\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class PlainFormattableDisplayField extends DisplayField {\n public get value() {\n if (!this.schema) {\n return null;\n }\n const element = this.resource[this.name];\n\n return element && element.raw || '';\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {StateService} from '@uirouter/core';\nimport {KeepTabService} from 'core-components/wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {UiStateLinkBuilder} from \"core-components/wp-fast-table/builders/ui-state-link-builder\";\nimport {WorkPackageDisplayField} from \"core-app/modules/fields/display/field-types/work-package-display-field.module\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class LinkedWorkPackageDisplayField extends WorkPackageDisplayField {\n\n public text = {\n linkTitle: this.I18n.t('js.work_packages.message_successful_show_in_fullscreen'),\n none: this.I18n.t('js.filter.noneElement')\n };\n\n @InjectField() $state!:StateService;\n @InjectField() keepTab!:KeepTabService;\n\n private uiStateBuilder:UiStateLinkBuilder = new UiStateLinkBuilder(this.$state, this.keepTab);\n\n public render(element:HTMLElement, displayText:string):void {\n if (this.isEmpty()) {\n element.innerText = this.placeholder;\n return;\n }\n\n let link = this.uiStateBuilder.linkToShow(\n this.wpId,\n this.text.linkTitle,\n this.valueString\n );\n\n let title = document.createElement('span');\n title.textContent = ' ' + _.truncate(this.title, {length: 40});\n\n element.innerHTML = '';\n element.appendChild(link);\n element.appendChild(title);\n }\n\n public get writable():boolean {\n return false;\n }\n\n public get valueString() {\n return '#' + this.wpId;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APP_INITIALIZER, NgModule} from '@angular/core';\nimport {EditFieldService} from \"core-app/modules/fields/edit/edit-field.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {initializeCoreEditFields} from \"core-app/modules/fields/edit/edit-field.initializer\";\nimport {initializeCoreDisplayFields} from \"core-app/modules/fields/display/display-field.initializer\";\nimport {BooleanEditFieldComponent} from \"core-app/modules/fields/edit/field-types/boolean-edit-field.component\";\nimport {DateEditFieldComponent} from \"core-app/modules/fields/edit/field-types/date-edit-field.component\";\nimport {DurationEditFieldComponent} from \"core-app/modules/fields/edit/field-types/duration-edit-field.component\";\nimport {FloatEditFieldComponent} from \"core-app/modules/fields/edit/field-types/float-edit-field.component\";\nimport {IntegerEditFieldComponent} from \"core-app/modules/fields/edit/field-types/integer-edit-field.component\";\nimport {MultiSelectEditFieldComponent} from \"core-app/modules/fields/edit/field-types/multi-select-edit-field.component\";\nimport {SelectEditFieldComponent} from \"core-app/modules/fields/edit/field-types/select-edit-field.component\";\nimport {FormattableEditFieldComponent} from \"core-app/modules/fields/edit/field-types/formattable-edit-field.component\";\nimport {TextEditFieldComponent} from \"core-app/modules/fields/edit/field-types/text-edit-field.component\";\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {EditFormPortalComponent} from \"core-app/modules/fields/edit/editing-portal/edit-form-portal.component\";\nimport {EditFieldControlsComponent,} from \"core-app/modules/fields/edit/field-controls/edit-field-controls.component\";\nimport {OpenprojectAccessibilityModule} from \"core-app/modules/a11y/openproject-a11y.module\";\nimport {OpenprojectEditorModule} from 'core-app/modules/editor/openproject-editor.module';\nimport {SelectAutocompleterRegisterService} from \"core-app/modules/fields/edit/field-types/select-autocompleter-register.service\";\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {WorkPackageEditFieldComponent} from \"core-app/modules/fields/edit/field-types/work-package-edit-field.component\";\nimport {EditableAttributeFieldComponent} from \"core-app/modules/fields/edit/field/editable-attribute-field.component\";\nimport {ProjectStatusEditFieldComponent} from \"core-app/modules/fields/edit/field-types/project-status-edit-field.component\";\nimport {PlainFormattableEditFieldComponent} from \"core-app/modules/fields/edit/field-types/plain-formattable-edit-field.component\";\nimport {TimeEntryWorkPackageEditFieldComponent} from \"core-app/modules/fields/edit/field-types/te-work-package-edit-field.component\";\nimport {AttributeValueMacroComponent} from \"core-app/modules/fields/macros/attribute-value-macro.component\";\nimport {AttributeLabelMacroComponent} from \"core-app/modules/fields/macros/attribute-label-macro.component\";\nimport {AttributeHelpTextComponent} from \"core-app/modules/fields/help-texts/attribute-help-text.component\";\nimport {AttributeHelpTextModal} from \"core-app/modules/fields/help-texts/attribute-help-text.modal\";\nimport {OpenprojectAttachmentsModule} from \"core-app/modules/attachments/openproject-attachments.module\";\nimport {WorkPackageQuickinfoMacroComponent} from \"core-app/modules/fields/macros/work-package-quickinfo-macro.component\";\nimport {DisplayFieldComponent} from \"core-app/modules/fields/display/display-field.component\";\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n OpenprojectAttachmentsModule,\n OpenprojectAccessibilityModule,\n OpenprojectEditorModule,\n ],\n exports: [\n EditFieldControlsComponent,\n EditFormPortalComponent,\n EditFormComponent,\n EditableAttributeFieldComponent,\n AttributeHelpTextComponent,\n ],\n providers: [\n {\n provide: APP_INITIALIZER,\n useFactory: initializeCoreEditFields,\n deps: [EditFieldService, SelectAutocompleterRegisterService],\n multi: true\n },\n {\n provide: APP_INITIALIZER,\n useFactory: initializeCoreDisplayFields,\n deps: [DisplayFieldService],\n multi: true\n },\n ],\n declarations: [\n EditFormPortalComponent,\n BooleanEditFieldComponent,\n DateEditFieldComponent,\n DurationEditFieldComponent,\n FloatEditFieldComponent,\n IntegerEditFieldComponent,\n FormattableEditFieldComponent,\n PlainFormattableEditFieldComponent,\n MultiSelectEditFieldComponent,\n SelectEditFieldComponent,\n TextEditFieldComponent,\n EditFieldControlsComponent,\n WorkPackageEditFieldComponent,\n TimeEntryWorkPackageEditFieldComponent,\n EditFormComponent,\n DisplayFieldComponent,\n EditableAttributeFieldComponent,\n ProjectStatusEditFieldComponent,\n AttributeValueMacroComponent,\n AttributeLabelMacroComponent,\n\n // Help texts\n AttributeHelpTextComponent,\n AttributeHelpTextModal,\n WorkPackageQuickinfoMacroComponent,\n ]\n})\nexport class OpenprojectFieldsModule {\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {EditFieldService} from \"core-app/modules/fields/edit/edit-field.service\";\nimport {TextEditFieldComponent} from \"core-app/modules/fields/edit/field-types/text-edit-field.component\";\nimport {IntegerEditFieldComponent} from \"core-app/modules/fields/edit/field-types/integer-edit-field.component\";\nimport {DurationEditFieldComponent} from \"core-app/modules/fields/edit/field-types/duration-edit-field.component\";\nimport {SelectEditFieldComponent} from \"core-app/modules/fields/edit/field-types/select-edit-field.component\";\nimport {MultiSelectEditFieldComponent} from \"core-app/modules/fields/edit/field-types/multi-select-edit-field.component\";\nimport {FloatEditFieldComponent} from \"core-app/modules/fields/edit/field-types/float-edit-field.component\";\nimport {BooleanEditFieldComponent} from \"core-app/modules/fields/edit/field-types/boolean-edit-field.component\";\nimport {WorkPackageEditFieldComponent} from \"core-app/modules/fields/edit/field-types/work-package-edit-field.component\";\nimport {DateEditFieldComponent} from \"core-app/modules/fields/edit/field-types/date-edit-field.component\";\nimport {FormattableEditFieldComponent} from \"core-app/modules/fields/edit/field-types/formattable-edit-field.component\";\nimport {WorkPackageCommentFieldComponent} from \"core-components/work-packages/work-package-comment/wp-comment-field.component\";\nimport {SelectAutocompleterRegisterService} from \"core-app/modules/fields/edit/field-types/select-autocompleter-register.service\";\nimport {VersionAutocompleterComponent} from \"core-app/modules/common/autocomplete/version-autocompleter.component\";\nimport {ProjectStatusEditFieldComponent} from \"core-app/modules/fields/edit/field-types/project-status-edit-field.component\";\nimport {PlainFormattableEditFieldComponent} from \"core-app/modules/fields/edit/field-types/plain-formattable-edit-field.component\";\nimport {WorkPackageAutocompleterComponent} from \"core-app/modules/common/autocomplete/wp-autocompleter.component\";\nimport {TimeEntryWorkPackageEditFieldComponent} from \"core-app/modules/fields/edit/field-types/te-work-package-edit-field.component\";\nimport {CombinedDateEditFieldComponent} from \"core-app/modules/fields/edit/field-types/combined-date-edit-field.component\";\n\n\nexport function initializeCoreEditFields(editFieldService:EditFieldService, selectAutocompleterRegisterService:SelectAutocompleterRegisterService) {\n return () => {\n editFieldService.defaultFieldType = 'text';\n editFieldService\n .addFieldType(TextEditFieldComponent, 'text', ['String'])\n .addFieldType(IntegerEditFieldComponent, 'integer', ['Integer'])\n .addFieldType(DurationEditFieldComponent, 'duration', ['Duration'])\n .addFieldType(SelectEditFieldComponent, 'select', ['Priority',\n 'Status',\n 'Type',\n 'User',\n 'Version',\n 'TimeEntriesActivity',\n 'Category',\n 'CustomOption',\n 'Project'])\n .addFieldType(MultiSelectEditFieldComponent, 'multi-select', [\n '[]CustomOption',\n '[]User'\n ])\n .addFieldType(FloatEditFieldComponent, 'float', ['Float'])\n .addFieldType(WorkPackageEditFieldComponent, 'workPackage', ['WorkPackage'])\n .addFieldType(BooleanEditFieldComponent, 'boolean', ['Boolean'])\n .addFieldType(DateEditFieldComponent, 'date', ['Date'])\n .addFieldType(FormattableEditFieldComponent, 'wiki-textarea', ['Formattable'])\n .addFieldType(ProjectStatusEditFieldComponent, 'project_status', ['ProjectStatus'])\n .addFieldType(WorkPackageCommentFieldComponent, '_comment', ['comment']);\n\n editFieldService\n .addSpecificFieldType('WorkPackage', CombinedDateEditFieldComponent,\n 'date',\n ['combinedDate', 'startDate', 'dueDate', 'date'])\n .addSpecificFieldType('TimeEntry', PlainFormattableEditFieldComponent, 'comment', ['comment'])\n .addSpecificFieldType('TimeEntry', TimeEntryWorkPackageEditFieldComponent, 'workPackage', ['WorkPackage']);\n\n selectAutocompleterRegisterService.register(VersionAutocompleterComponent, 'Version');\n selectAutocompleterRegisterService.register(WorkPackageAutocompleterComponent, 'WorkPackage');\n };\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {TextDisplayField} from \"core-app/modules/fields/display/field-types/text-display-field.module\";\nimport {FloatDisplayField} from \"core-app/modules/fields/display/field-types/float-display-field.module\";\nimport {IntegerDisplayField} from \"core-app/modules/fields/display/field-types/integer-display-field.module\";\nimport {ResourceDisplayField} from \"core-app/modules/fields/display/field-types/resource-display-field.module\";\nimport {ResourcesDisplayField} from \"core-app/modules/fields/display/field-types/resources-display-field.module\";\nimport {FormattableDisplayField} from \"core-app/modules/fields/display/field-types/formattable-display-field.module\";\nimport {DurationDisplayField} from \"core-app/modules/fields/display/field-types/duration-display-field.module\";\nimport {DateDisplayField} from \"core-app/modules/fields/display/field-types/date-display-field.module\";\nimport {DateTimeDisplayField} from \"core-app/modules/fields/display/field-types/datetime-display-field.module\";\nimport {BooleanDisplayField} from \"core-app/modules/fields/display/field-types/boolean-display-field.module\";\nimport {ProgressDisplayField} from \"core-app/modules/fields/display/field-types/progress-display-field.module\";\nimport {WorkPackageDisplayField} from \"core-app/modules/fields/display/field-types/work-package-display-field.module\";\nimport {WorkPackageSpentTimeDisplayField} from \"core-app/modules/fields/display/field-types/wp-spent-time-display-field.module\";\nimport {IdDisplayField} from \"core-app/modules/fields/display/field-types/id-display-field.module\";\nimport {HighlightedResourceDisplayField} from \"core-app/modules/fields/display/field-types/highlighted-resource-display-field.module\";\nimport {TypeDisplayField} from \"core-app/modules/fields/display/field-types/type-display-field.module\";\nimport {UserDisplayField} from \"core-app/modules/fields/display/field-types/user-display-field.module\";\nimport {MultipleUserFieldModule} from \"core-app/modules/fields/display/field-types/multiple-user-display-field.module\";\nimport {WorkPackageIdDisplayField} from \"core-app/modules/fields/display/field-types/wp-id-display-field.module\";\nimport {ProjectStatusDisplayField} from \"core-app/modules/fields/display/field-types/project-status-display-field.module\";\nimport {PlainFormattableDisplayField} from \"core-app/modules/fields/display/field-types/plain-formattable-display-field.module\";\nimport {LinkedWorkPackageDisplayField} from \"core-app/modules/fields/display/field-types/linked-work-package-display-field.module\";\nimport {CombinedDateDisplayField} from \"core-app/modules/fields/display/field-types/combined-date-display.field\";\n\nexport function initializeCoreDisplayFields(displayFieldService:DisplayFieldService) {\n return () => {\n displayFieldService.defaultFieldType = 'text';\n displayFieldService\n .addFieldType(TextDisplayField, 'text', ['String'])\n .addFieldType(FloatDisplayField, 'float', ['Float'])\n .addFieldType(IntegerDisplayField, 'integer', ['Integer'])\n .addFieldType(HighlightedResourceDisplayField, 'highlight', [\n 'Status',\n 'Priority'\n ])\n .addFieldType(TypeDisplayField, 'type', ['Type'])\n .addFieldType(ResourceDisplayField, 'resource', [\n 'Project',\n 'TimeEntriesActivity',\n 'Version',\n 'Category',\n 'CustomOption'])\n .addFieldType(ResourcesDisplayField, 'resources', ['[]CustomOption'])\n .addFieldType(MultipleUserFieldModule, 'users', ['[]User'])\n .addFieldType(FormattableDisplayField, 'formattable', ['Formattable'])\n .addFieldType(DurationDisplayField, 'duration', ['Duration'])\n .addFieldType(DateDisplayField, 'date', ['Date'])\n .addFieldType(DateTimeDisplayField, 'datetime', ['DateTime'])\n .addFieldType(BooleanDisplayField, 'boolean', ['Boolean'])\n .addFieldType(ProgressDisplayField, 'progress', ['percentageDone'])\n .addFieldType(LinkedWorkPackageDisplayField, 'work_package', ['WorkPackage'])\n .addFieldType(IdDisplayField, 'id', ['id'])\n .addFieldType(ProjectStatusDisplayField, 'project_status', ['ProjectStatus'])\n .addFieldType(UserDisplayField, 'user', ['User']);\n\n displayFieldService\n .addSpecificFieldType('WorkPackage', WorkPackageIdDisplayField, 'id', ['id'])\n .addSpecificFieldType('WorkPackage', WorkPackageSpentTimeDisplayField, 'spentTime', ['spentTime'])\n .addSpecificFieldType('WorkPackage', CombinedDateDisplayField, 'combinedDate', ['combinedDate'])\n .addSpecificFieldType('TimeEntry', PlainFormattableDisplayField, 'comment', ['comment'])\n .addSpecificFieldType('TimeEntry', WorkPackageDisplayField, 'work_package', ['workPackage']);\n };\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, Directive, ElementRef, Input} from \"@angular/core\";\nimport {FocusHelperService} from \"core-app/modules/common/focus/focus-helper\";\n\n@Directive({\n selector: '[focus]'\n})\nexport class FocusDirective implements AfterViewInit {\n @Input('focus') condition:boolean;\n @Input('focusPriority') priority?:number = 0;\n\n constructor(readonly FocusHelper:FocusHelperService,\n readonly elementRef:ElementRef) {\n }\n\n ngAfterViewInit() {\n this.updateFocus();\n }\n\n private updateFocus() {\n if (this.condition) {\n const element = jQuery(this.elementRef.nativeElement);\n this.FocusHelper.focusElement(element, this.priority);\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class SchemaDependencyResource extends HalResource {\n\n public dependencies:any;\n\n public forValue(value:string):any {\n return this.dependencies[value];\n }\n}\n","import {contextColumnIcon, OpTableAction} from 'core-components/wp-table/table-actions/table-action';\nimport {opIconElement} from 'core-app/helpers/op-icon-builder';\n\nimport {KeepTabService} from 'core-components/wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {UiStateLinkBuilder} from 'core-components/wp-fast-table/builders/ui-state-link-builder';\nimport {StateService} from \"@uirouter/core\";\n\nexport const detailsLinkClassName = 'wp-table--details-link';\n\nexport class OpDetailsTableAction extends OpTableAction {\n\n public readonly identifier = 'open-details-action';\n private uiStatebuilder = new UiStateLinkBuilder(this.injector.get(StateService), this.injector.get(KeepTabService));\n private text = {\n button: this.I18n.t('js.button_open_details')\n }\n\n public buildElement() {\n // Append details button\n let detailsLink = this.uiStatebuilder.linkToDetails(\n this.workPackage.id!,\n this.text.button,\n ''\n );\n\n detailsLink.classList.add(detailsLinkClassName, contextColumnIcon, 'hidden-for-mobile');\n detailsLink.appendChild(opIconElement('icon', 'icon-info2'));\n\n return detailsLink;\n }\n}\n","import {\n contextColumnIcon,\n contextMenuLinkClassName,\n OpTableAction\n} from 'core-components/wp-table/table-actions/table-action';\nimport {opIconElement} from 'core-app/helpers/op-icon-builder';\n\nexport class OpContextMenuTableAction extends OpTableAction {\n\n public readonly identifier = 'open-context-menu-action';\n\n private text = {\n linkTitle: this.I18n.t('js.label_open_context_menu')\n };\n\n public buildElement() {\n let contextMenu = document.createElement('a');\n contextMenu.href = '#';\n contextMenu.classList.add(contextMenuLinkClassName, contextColumnIcon);\n contextMenu.title = this.text.linkTitle;\n contextMenu.appendChild(opIconElement('icon', 'icon-show-more-horizontal'));\n\n return contextMenu;\n }\n}\n","import {Injectable, Injector} from '@angular/core';\nimport {\n OpTableActionFactory,\n} from 'core-components/wp-table/table-actions/table-action';\nimport {OpDetailsTableAction} from 'core-components/wp-table/table-actions/actions/details-table-action';\nimport {OpContextMenuTableAction} from 'core-components/wp-table/table-actions/actions/context-menu-table-action';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\n@Injectable()\nexport class OpTableActionsService {\n\n constructor(private readonly injector:Injector) {\n }\n\n /**\n * Actions currently registered\n */\n private actions:OpTableActionFactory[] = [\n (injector, workPackage) => new OpDetailsTableAction(injector, workPackage),\n (injector, workPackage) => new OpContextMenuTableAction(injector, workPackage),\n ];\n\n /**\n * Replace the actions with a different set\n */\n public setActions(...actions:OpTableActionFactory[]) {\n this.actions = actions;\n }\n\n /**\n * Render actions for the given work package.\n * @param {WorkPackageResource} workPackage\n */\n public render(workPackage:WorkPackageResource):HTMLElement[] {\n let built = this.actions.map((factory) => factory(this.injector, workPackage).buildElement());\n return _.compact(built);\n }\n}\n","\n//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\n\n@Injectable()\nexport class FirstRouteService {\n public name:string;\n public params:any;\n\n constructor() {}\n\n public get isEmpty() {\n return !this.name;\n }\n\n public setIfFirst(stateName:string|undefined, params:any) {\n if (!this.isEmpty || !stateName) {\n return;\n }\n\n this.name = stateName;\n this.params = params;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AbstractWorkPackageButtonComponent} from 'core-components/wp-buttons/wp-buttons.module';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core';\nimport {WorkPackageFiltersService} from 'core-components/filters/wp-filters/wp-filters.service';\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\n@Component({\n selector: 'wp-filter-button',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './wp-filter-button.html'\n})\nexport class WorkPackageFilterButtonComponent extends AbstractWorkPackageButtonComponent implements OnInit {\n public count:number;\n public initialized:boolean = false;\n\n public buttonId:string = 'work-packages-filter-toggle-button';\n public iconClass:string = 'icon-filter';\n\n constructor(readonly I18n:I18nService,\n protected cdRef:ChangeDetectorRef,\n protected wpFiltersService:WorkPackageFiltersService,\n protected wpTableFilters:WorkPackageViewFiltersService) {\n super(I18n);\n }\n\n ngOnInit():void {\n this.setupObserver();\n }\n\n public get labelKey():string {\n return 'js.button_filter';\n }\n\n public get textKey():string {\n return 'js.toolbar.filter';\n }\n\n public get label():string {\n return this.prefix + this.text.label;\n }\n\n public get filterCount():number {\n return this.count;\n }\n\n public performAction(event:Event) {\n this.toggleVisibility();\n }\n\n public toggleVisibility() {\n this.wpFiltersService.toggleVisibility();\n }\n\n private setupObserver() {\n this.wpTableFilters\n .live$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.count = this.wpTableFilters.currentlyVisibleFilters.length;\n this.initialized = true;\n this.cdRef.detectChanges();\n });\n\n this.wpFiltersService\n .observeUntil(componentDestroyed(this))\n .subscribe(() => {\n this.isActive = this.wpFiltersService.visible;\n this.cdRef.detectChanges();\n });\n }\n}\n","\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {QuerySortByResource} from 'core-app/modules/hal/resources/query-sort-by-resource';\nimport {HalLink} from 'core-app/modules/hal/hal-link/hal-link';\nimport {Injectable} from '@angular/core';\nimport {PaginationService} from 'core-components/table-pagination/pagination-service';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {ApiV3Filter, FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\n\n@Injectable({ providedIn: 'root' })\nexport class UrlParamsHelperService {\n\n public constructor(public paginationService:PaginationService) {\n }\n\n // copied more or less from angular buildUrl\n public buildQueryString(params:any) {\n if (!params) {\n return undefined;\n }\n\n let parts:string[] = [];\n _.each(params, (value, key) => {\n if (!value) return;\n if (!Array.isArray(value)) value = [value];\n\n _.each(value, (v) => {\n if (v !== null && typeof v === 'object') {\n v = JSON.stringify(v);\n }\n parts.push(encodeURIComponent(key) + '=' +\n encodeURIComponent(v));\n });\n });\n\n return parts.join('&');\n }\n\n public encodeQueryJsonParams(query:QueryResource, additional:any = {}) {\n let paramsData:any = {};\n\n paramsData = this.encodeColumns(paramsData, query);\n paramsData = this.encodeSums(paramsData, query);\n paramsData = this.encodeTimelineVisible(paramsData, query);\n paramsData = this.encodeHighlightingMode(paramsData, query);\n paramsData = this.encodeHighlightedAttributes(paramsData, query);\n paramsData.hi = !!query.showHierarchies;\n paramsData.g = _.get(query.groupBy, 'id', '');\n paramsData = this.encodeSortBy(paramsData, query);\n paramsData = this.encodeFilters(paramsData, query.filters);\n paramsData.pa = additional.page;\n paramsData.pp = additional.perPage;\n paramsData.dr = query.displayRepresentation;\n\n return JSON.stringify(paramsData);\n }\n\n private encodeColumns(paramsData:any, query:QueryResource) {\n paramsData.c = query.columns.map(function (column) {\n return column.id!;\n });\n\n return paramsData;\n }\n\n private encodeSums(paramsData:any, query:QueryResource) {\n if (!!query.sums) {\n paramsData.s = query.sums;\n }\n return paramsData;\n }\n\n private encodeHighlightingMode(paramsData:any, query:QueryResource) {\n if (query.highlightingMode && (query.persisted || query.highlightingMode !== 'inline')) {\n paramsData.hl = query.highlightingMode;\n }\n return paramsData;\n }\n\n private encodeHighlightedAttributes(paramsData:any, query:QueryResource) {\n if (query.highlightingMode === 'inline') {\n if (Array.isArray(query.highlightedAttributes) && query.highlightedAttributes.length > 0) {\n paramsData.hla = query.highlightedAttributes.map(el => el.id);\n }\n }\n return paramsData;\n }\n\n private encodeSortBy(paramsData:any, query:QueryResource) {\n if (query.sortBy) {\n paramsData.t = query\n .sortBy\n .map(function (sort:QuerySortByResource) {\n return sort.id!.replace('-', ':')\n })\n .join();\n }\n return paramsData;\n }\n\n public encodeFilters(paramsData:any, filters:QueryFilterInstanceResource[]) {\n if (filters && filters.length > 0) {\n paramsData.f = filters\n .map((filter:any) => {\n var id = filter.id;\n\n var operator = filter.operator.id;\n\n return {\n n: id,\n o: operator,\n v: _.map(filter.values, (v) => this.queryFilterValueToParam(v))\n };\n });\n } else {\n paramsData.f = [];\n }\n return paramsData;\n }\n\n private encodeTimelineVisible(paramsData:any, query:QueryResource) {\n if (!!query.timelineVisible) {\n paramsData.tv = query.timelineVisible;\n\n if (!_.isEmpty(query.timelineLabels)) {\n paramsData.tll = JSON.stringify(query.timelineLabels);\n }\n\n paramsData.tzl = query.timelineZoomLevel;\n } else {\n paramsData.tv = false;\n }\n return paramsData;\n }\n\n\n public buildV3GetQueryFromJsonParams(updateJson:string|null) {\n var queryData:any = {\n pageSize: this.paginationService.getPerPage()\n };\n\n if (!updateJson) {\n return queryData;\n }\n\n var properties = JSON.parse(updateJson);\n\n if (properties.c) {\n queryData[\"columns[]\"] = properties.c.map((column:any) => column);\n }\n if (!!properties.s) {\n queryData.showSums = properties.s;\n }\n\n queryData.timelineVisible = properties.tv;\n\n if (!!properties.tv) {\n if (!!properties.tll) {\n queryData.timelineLabels = properties.tll;\n }\n\n if (properties.tzl) {\n queryData.timelineZoomLevel = properties.tzl;\n }\n }\n\n if (properties.dr) {\n queryData.displayRepresentation = properties.dr;\n }\n\n if (properties.hl) {\n queryData.highlightingMode = properties.hl;\n }\n\n if (properties.hla) {\n queryData[\"highlightedAttributes[]\"] = properties.hla.map((column:any) => column);\n }\n\n if (properties.hi === false || properties.hi === true) {\n queryData.showHierarchies = properties.hi;\n }\n\n queryData.groupBy = _.get(properties, 'g', '');\n\n // Filters\n if (properties.f) {\n var filters = properties.f.map(function (urlFilter:any) {\n var attributes = {\n operator: decodeURIComponent(urlFilter.o)\n }\n if (urlFilter.v) {\n // the array check is only there for backwards compatibility reasons.\n // Nowadays, it will always be an array;\n var vs = Array.isArray(urlFilter.v) ? urlFilter.v : [urlFilter.v];\n _.extend(attributes, { values: vs });\n }\n const filterData:any = {};\n filterData[urlFilter.n] = attributes;\n\n return filterData;\n });\n\n queryData.filters = JSON.stringify(filters);\n }\n\n // Sortation\n if (properties.t) {\n queryData.sortBy = JSON.stringify(properties.t.split(',').map((sort:any) => sort.split(':')));\n }\n\n // Pagination\n if (properties.pa) {\n queryData.offset = properties.pa;\n }\n if (properties.pp) {\n queryData.pageSize = properties.pp;\n }\n\n return queryData;\n }\n\n public buildV3GetQueryFromQueryResource(query:QueryResource, additionalParams:any = {}, contextual:any = {}) {\n var queryData:any = {};\n\n queryData[\"columns[]\"] = this.buildV3GetColumnsFromQueryResource(query);\n queryData.showSums = query.sums;\n queryData.timelineVisible = !!query.timelineVisible;\n\n if (!!query.timelineVisible) {\n queryData.timelineZoomLevel = query.timelineZoomLevel;\n queryData.timelineLabels = JSON.stringify(query.timelineLabels);\n }\n\n if (query.highlightingMode) {\n queryData.highlightingMode = query.highlightingMode;\n }\n\n if (query.highlightedAttributes && query.highlightingMode === 'inline') {\n queryData['highlightedAttributes[]'] = query.highlightedAttributes.map(el => el.href);\n }\n\n if (query.displayRepresentation) {\n queryData.displayRepresentation = query.displayRepresentation;\n }\n\n queryData.showHierarchies = !!query.showHierarchies;\n queryData.groupBy = _.get(query.groupBy, 'id', '');\n\n // Filters\n queryData.filters = this.buildV3GetFiltersAsJson(query.filters, contextual);\n\n // Sortation\n queryData.sortBy = this.buildV3GetSortByFromQuery(query);\n\n return _.extend(additionalParams, queryData);\n }\n\n public queryFilterValueToParam(value:any) {\n if (typeof(value) === 'boolean') {\n return value ? 't' : 'f';\n }\n\n if (!value) {\n return '';\n } else if (value.id) {\n return value.id.toString();\n } else if (value.$href) {\n return value.$href.split('/').pop().toString();\n } else {\n return value.toString();\n }\n }\n\n private buildV3GetColumnsFromQueryResource(query:QueryResource) {\n if (query.columns) {\n return query.columns.map((column:any) => column.id || column.idFromLink);\n } else if (query._links.columns) {\n return query._links.columns.map((column:HalLink) => {\n let id = column.href!;\n\n return this.idFromHref(id);\n });\n }\n }\n\n public buildV3GetFilters(filters:QueryFilterInstanceResource[], replacements = {}):ApiV3Filter[] {\n let newFilters = filters.map((filter:QueryFilterInstanceResource) => {\n let id = this.buildV3GetFilterIdFromFilter(filter);\n let operator = this.buildV3GetOperatorIdFromFilter(filter);\n let values = this.buildV3GetValuesFromFilter(filter).map(value => {\n _.each(replacements, (val:string, key:string) => {\n value = value.replace(`{${key}}`, val);\n });\n\n return value;\n });\n\n const filterHash:ApiV3Filter = {};\n filterHash[id] = { operator: operator as FilterOperator, values: values };\n\n return filterHash;\n });\n\n return newFilters;\n }\n\n public buildV3GetFiltersAsJson(filter:QueryFilterInstanceResource[], contextual = {}) {\n return JSON.stringify(this.buildV3GetFilters(filter, contextual));\n }\n\n public buildV3GetFilterIdFromFilter(filter:QueryFilterInstanceResource) {\n let href = filter.filter ? filter.filter.$href : filter._links.filter.href;\n\n return this.idFromHref(href);\n }\n\n private buildV3GetOperatorIdFromFilter(filter:QueryFilterInstanceResource) {\n if (filter.operator) {\n return filter.operator.id || filter.operator.idFromLink;\n } else {\n let href = filter._links.operator.href;\n\n return this.idFromHref(href);\n }\n }\n\n private buildV3GetValuesFromFilter(filter:QueryFilterInstanceResource) {\n if (filter.values) {\n return _.map(filter.values, (v:any) => this.queryFilterValueToParam(v));\n } else {\n return _.map(filter._links.values, (v:any) => this.idFromHref(v.href));\n }\n\n }\n\n private buildV3GetSortByFromQuery(query:QueryResource) {\n let sortBys = query.sortBy ? query.sortBy : query._links.sortBy;\n let sortByIds = sortBys.map((sort:QuerySortByResource) => {\n if (sort.id) {\n return sort.id;\n } else {\n let href = sort.href!;\n\n let id = this.idFromHref(href);\n\n return id;\n }\n });\n\n return JSON.stringify(sortByIds.map((id:string) => id.split('-')));\n }\n\n private idFromHref(href:string) {\n let id = href.substring(href.lastIndexOf('/') + 1, href.length);\n\n return decodeURIComponent(id);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from '@angular/core';\nimport {StateService, Transition} from \"@uirouter/core\";\nimport {KeepTabService} from \"core-components/wp-single-view-tabs/keep-tab/keep-tab.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\ninterface BackRouteOptions {\n name:string;\n params:{};\n parent:string;\n baseRoute:string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class BackRoutingService {\n @InjectField() private $state:StateService;\n @InjectField() private keepTab:KeepTabService;\n\n private _backRoute:BackRouteOptions;\n\n constructor(readonly injector:Injector) {\n }\n\n private goToOtherState(route:string, params:{}):Promise {\n return this.$state.go(route, params);\n }\n\n private goBackToDetailsState(preferListOverSplit:boolean, baseRoute:string):void {\n if (preferListOverSplit) {\n this.goToOtherState(baseRoute, this.backRoute.params);\n } else {\n this.goToOtherState(baseRoute + this.keepTab.currentDetailsSubState, this.backRoute.params);\n }\n }\n\n private goBackNotToDetailsState():void {\n if (this.backRoute.parent) {\n this.goToOtherState(this.backRoute.name, this.backRoute.params).then(() => { this.$state.reload(); });\n }\n else {\n this.goToOtherState(this.backRoute.name, this.backRoute.params);\n }\n }\n\n private goBackToPreviousState(preferListOverSplit:boolean, baseRoute:string):void {\n if (this.keepTab.isDetailsState(this.backRoute.parent)) {\n this.goBackToDetailsState(preferListOverSplit, baseRoute);\n } else {\n this.goBackNotToDetailsState();\n }\n }\n\n public goBack(preferListOverSplit:boolean = false) {\n // Default: back to list\n // When coming from a deep link or a create form\n const baseRoute = this.backRoute?.baseRoute || this.$state.current.data.baseRoute || 'work-packages.partitioned.list';\n // if we are in the first state\n if (!this.backRoute && baseRoute.includes('show')) { this.$state.reload(); }\n else {\n if (!this.backRoute || this.backRoute.name.includes('new')) {\n this.$state.go(baseRoute, this.$state.params);\n } else {\n this.goBackToPreviousState(preferListOverSplit, baseRoute);\n }\n }\n }\n\n public goToBaseState() {\n const baseRoute = this.$state.current.data.baseRoute || 'work-packages.partitioned.list';\n this.$state.go(baseRoute, this.$state.params);\n }\n\n public sync(transition:Transition) {\n const fromState = transition.from();\n const toState = transition.to();\n\n // Set backRoute to know where we came from\n if (fromState.name &&\n fromState.data &&\n toState.data &&\n fromState.data.parent !== toState.data.parent) {\n const paramsFromCopy = { ...transition.params('from') };\n this.backRoute = { name: fromState.name,\n params: paramsFromCopy,\n parent: fromState.data.parent,\n baseRoute: fromState.data.baseRoute };\n }\n }\n\n public set backRoute(route:BackRouteOptions) {\n this._backRoute = route;\n }\n\n public get backRoute():BackRouteOptions {\n return this._backRoute;\n }\n}\n","import {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {Injector} from \"@angular/core\";\n\nexport class TableDragActionService {\n\n /**\n * Initialize an action service in the given isolated query space\n * @param querySpace The isolated query space for this table\n * @param injector The hierarchical injector for this table\n */\n constructor(readonly querySpace:IsolatedQuerySpace,\n readonly injector:Injector) {\n }\n\n /**\n * Determine whether the service applies for the given\n * query spaces.\n */\n public get applies():boolean {\n return true;\n }\n\n /**\n * Perform a post-order update\n */\n public onNewOrder(newOrder:string[]):void {\n }\n\n /**\n * Returns whether the given work package is movable\n */\n public canPickup(workPackage:WorkPackageResource):boolean {\n return true;\n }\n\n /**\n * Perform the respective action for the drop that just happened\n *\n * @param workPackage\n * @param target\n * @param source\n * @param sibling\n */\n public handleDrop(workPackage:WorkPackageResource, el:HTMLElement):Promise {\n return Promise.resolve(undefined);\n }\n\n /**\n * Manipulate the shadow element\n * @param shadowElement\n * @param backToDefault: Shall the modifications be made undone\n */\n public changeShadowElement(shadowElement:HTMLElement, backToDefault:boolean = false) {\n if (backToDefault) {\n shadowElement.classList.remove('-dragged');\n } else {\n shadowElement.classList.add('-dragged');\n }\n return true;\n }\n}\n","import {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageRelationsHierarchyService} from \"core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service\";\nimport {\n hierarchyGroupClass,\n hierarchyRootClass\n} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\nimport {relationRowClass, isInsideCollapsedGroup} from \"core-components/wp-fast-table/helpers/wp-table-row-helpers\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class HierarchyDragActionService extends TableDragActionService {\n\n @InjectField() private wpTableHierarchies:WorkPackageViewHierarchiesService;\n @InjectField() private relationHierarchyService:WorkPackageRelationsHierarchyService;\n @InjectField() private apiV3Service:APIV3Service;\n\n public get applies() {\n return this.wpTableHierarchies.isEnabled;\n }\n\n /**\n * Returns whether the given work package is movable\n */\n public canPickup(workPackage:WorkPackageResource):boolean {\n return !!workPackage.changeParent;\n }\n\n public handleDrop(workPackage:WorkPackageResource, el:HTMLElement):Promise {\n return this.determineParent(el).then((parentId:string|null) => {\n return this.relationHierarchyService.changeParent(workPackage, parentId);\n });\n }\n\n /**\n * Find an applicable parent element from the hierarchy information in the table.\n * @param el\n */\n private determineParent(el:Element):Promise {\n let previous = el.previousElementSibling;\n let next = el.nextElementSibling;\n let parent = null;\n\n if (previous !== null && this.droppedIntoGroup(el, previous, next)) {\n // If the previous element is a relation row,\n // skip it until we find the real previous sibling\n const isRelationRow = previous.className.indexOf(relationRowClass()) >= 0;\n\n if (isRelationRow) {\n let relationRoot = this.findRelationRowRoot(previous);\n if (relationRoot == null) {\n return Promise.resolve(null);\n }\n previous = relationRoot;\n }\n\n let previousWpId = (previous as HTMLElement).dataset.workPackageId!;\n\n if (this.isHiearchyRoot(previous, previousWpId)) {\n const droppedIntoCollapsedGroup = isInsideCollapsedGroup(next);\n\n if (droppedIntoCollapsedGroup) {\n return this.determineParent(previous);\n }\n // If the sibling is a hierarchy root, return that sibling as new parent.\n parent = previousWpId;\n } else {\n // If the sibling is no hierarchy root, return it's parent.\n // Thus, the dropped element will get the same hierarchy level as the sibling\n parent = this.loadParentOfWP(previousWpId);\n }\n }\n\n return Promise.resolve(parent);\n }\n\n private findRelationRowRoot(el:Element):Element|null {\n let previous = el.previousElementSibling;\n while (previous !== null) {\n if (previous.className.indexOf(relationRowClass()) < 0) {\n return previous;\n }\n previous = previous.previousElementSibling;\n }\n\n return null;\n }\n\n private droppedIntoGroup(element:Element, previous:Element, next:Element | null):boolean {\n const inGroup = previous.className.indexOf(hierarchyGroupClass('')) >= 0;\n const isRoot = previous.className.indexOf(hierarchyRootClass('')) >= 0;\n let skipDroppedIntoGroup;\n\n if (inGroup || isRoot) {\n const elementGroups = Array.from(element.classList).filter(listClass => listClass.includes('__hierarchy-group-')) || [];\n const previousGroups = Array.from(previous.classList).filter(listClass => listClass.includes('__hierarchy-group-')) || [];\n const nextGroups = next && Array.from(next.classList).filter(listClass => listClass.includes('__hierarchy-group-')) || [];\n const previousWpId = (previous as HTMLElement).dataset.workPackageId!;\n const isLastElementOfGroup = !nextGroups.some(nextGroup => previousGroups.includes(nextGroup)) && !nextGroups.includes(hierarchyGroupClass(previousWpId));\n const elementAlreadyBelongsToGroup = elementGroups.some(elementGroup => previousGroups.includes(elementGroup)) ||\n elementGroups.includes(hierarchyGroupClass(previousWpId));\n\n skipDroppedIntoGroup = isLastElementOfGroup && !elementAlreadyBelongsToGroup;\n }\n\n return !skipDroppedIntoGroup && inGroup || isRoot;\n }\n\n private isHiearchyRoot(previous:Element, previousWpId:string):boolean {\n return previous.classList.contains(hierarchyRootClass(previousWpId));\n }\n\n private loadParentOfWP(wpId:string):Promise {\n return this\n .apiV3Service\n .work_packages\n .id(wpId)\n .get()\n .toPromise()\n .then((wp:WorkPackageResource) => {\n return Promise.resolve(wp.parent?.id || null);\n });\n }\n}\n","import {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {rowGroupClassName} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants\";\nimport {locatePredecessorBySelector} from \"core-components/wp-fast-table/helpers/wp-table-row-helpers\";\nimport {groupIdentifier} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-rows-helpers\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\nexport class GroupByDragActionService extends TableDragActionService {\n\n @InjectField() wpTableGroupBy:WorkPackageViewGroupByService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() halEvents:HalEventsService;\n @InjectField() halNotification:HalResourceNotificationService;\n @InjectField() schemaCache:SchemaCacheService;\n\n public get applies() {\n return this.wpTableGroupBy.isEnabled;\n }\n\n /**\n * Returns whether the given work package is movable\n */\n public canPickup(workPackage:WorkPackageResource):boolean {\n const attribute = this.groupedAttribute;\n return attribute !== null && this.schemaCache.of(workPackage).isAttributeEditable(attribute);\n }\n\n public handleDrop(workPackage:WorkPackageResource, el:HTMLElement):Promise {\n const changeset = this.halEditing.changeFor(workPackage);\n const groupedValue = this.getValueForGroup(el);\n\n changeset.projectedResource[this.groupedAttribute!] = groupedValue;\n return this.halEditing\n .save(changeset)\n .then((saved) => this.halEvents.push(saved.resource, {eventType: 'updated'}))\n .catch(e => this.halNotification.handleRawError(e, workPackage));\n }\n\n private getValueForGroup(el:HTMLElement):unknown|null {\n const groupHeader = locatePredecessorBySelector(el, `.${rowGroupClassName}`)!;\n const match = this.groups.find(group => groupIdentifier(group) === groupHeader.dataset.groupIdentifier);\n\n if (!match) {\n return null;\n }\n\n if (match._links && match._links.valueLink) {\n const links = match._links.valueLink;\n\n // Unwrap single links to properly use them\n return links.length === 1 ? links[0] : links;\n } else {\n return match.value;\n }\n }\n\n /**\n * Get the attribute we're grouping by\n */\n private get groupedAttribute():string|null {\n const current = this.wpTableGroupBy.current;\n return current ? current.id : null;\n }\n\n /**\n * Returns the reference to the last table.groups state value\n */\n public get groups() {\n return this.querySpace.groups.value || [];\n }\n}\n","import {Injectable, Injector} from \"@angular/core\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {HierarchyDragActionService} from \"core-components/wp-table/drag-and-drop/actions/hierarchy-drag-action.service\";\nimport {GroupByDragActionService} from \"core-components/wp-table/drag-and-drop/actions/group-by-drag-action.service\";\n\ninterface ITableDragActionService {\n new(querySpace:IsolatedQuerySpace, injector:Injector):TableDragActionService;\n}\n\n@Injectable()\nexport class TableDragActionsRegistryService {\n\n private register:ITableDragActionService[] = [\n HierarchyDragActionService,\n GroupByDragActionService,\n ];\n\n public add(service:ITableDragActionService) {\n this.register.push(service);\n }\n\n public get(injector:Injector):TableDragActionService {\n const querySpace = injector.get(IsolatedQuerySpace);\n\n const match = this.register\n .map(cls => new cls(querySpace, injector))\n .find(instance => instance.applies);\n\n return match || new TableDragActionService(querySpace, injector);\n }\n}\n","export namespace ImageHelpers {\n\n /**\n * Returns an absolute asset path from the assets/images/ folder\n *\n * e.g., to access:\n * frontend/src/assets/images/board_creation_modal/assignees.svg\n *\n * use\n * imagePath('board_creation_modal/assignees.svg')\n *\n *\n * @param image Path to the image starting from frontend/src/assets/images\n */\n export function imagePath(image:string) {\n return __webpack_public_path__ + 'assets/images/' + image;\n }\n}\n","import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {\n DisplayFieldRenderer,\n editFieldContainerClass\n} from \"core-app/modules/fields/display/display-field-renderer\";\nimport {Injector} from '@angular/core';\nimport {QueryColumn} from \"core-components/wp-query/query-column\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nexport const tdClassName = 'wp-table--cell-td';\nexport const editCellContainer = 'wp-table--cell-container';\n\nexport class CellBuilder {\n\n @InjectField(SchemaCacheService) schemaCache:SchemaCacheService;\n\n public fieldRenderer = new DisplayFieldRenderer(this.injector, 'table');\n\n constructor(public injector:Injector) {\n }\n\n public build(workPackage:WorkPackageResource, column:QueryColumn) {\n const td = document.createElement('td');\n const attribute = column.id;\n td.classList.add(tdClassName, attribute);\n\n if (attribute === 'subject') {\n td.classList.add('-max');\n }\n\n const schema = this.schemaCache.of(workPackage).ofProperty(attribute);\n if (schema && schema.type === 'User') {\n td.classList.add('-contains-avatar');\n }\n\n const container = document.createElement('span');\n container.classList.add(editCellContainer, editFieldContainerClass, attribute);\n const displayElement = this.fieldRenderer.render(workPackage, attribute, null);\n\n container.appendChild(displayElement);\n td.appendChild(container);\n\n return td;\n }\n\n public refresh(container:HTMLElement, workPackage:WorkPackageResource, attribute:string) {\n const displayElement = this.fieldRenderer.render(workPackage, attribute, null);\n\n container.innerHTML = '';\n container.appendChild(displayElement);\n }\n}\n","import {environment} from '../../environments/environment';\n\n/**\n * Execute the callback when DEBUG is defined\n * through webpack.\n */\nexport function whenDebugging(cb:Function) {\n if (!environment.production) {\n cb();\n }\n}\n\n/**\n * Log with console.log when DEBUG is defined\n * through webpack.\n */\nexport function debugLog(message:string, ...args:any[]) {\n whenDebugging(() => console.log(`[DEBUG] ${message}`, ...args));\n}\n\nexport function timeOutput(msg:string, cb:() => void):any {\n if (!environment.production) {\n var t0 = performance.now();\n\n var results = cb();\n\n var t1 = performance.now();\n console.log(`%c${msg} completed in ${(t1 - t0)} milliseconds.`, 'color:#00A093;');\n\n return results;\n } else {\n return cb();\n }\n}\n\nexport function asyncTimeOutput(msg:string, promise:Promise):any {\n if (!environment.production) {\n var t0 = performance.now();\n\n return promise.then(() => {\n var t1 = performance.now();\n console.log(`%c${msg} completed in ${(t1 - t0)} milliseconds.`, 'color:#00A093;');\n });\n } else {\n return promise;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from '@angular/core';\nimport {INotification} from 'core-app/modules/common/notifications/notifications.service';\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageNotificationService extends HalResourceNotificationService {\n\n constructor(readonly injector:Injector,\n readonly apiV3Service:APIV3Service) {\n super(injector);\n }\n\n public showSave(resource:WorkPackageResource, isCreate:boolean = false) {\n let message:any = {\n message: this.I18n.t('js.notice_successful_' + (isCreate ? 'create' : 'update')),\n };\n\n this.addWorkPackageFullscreenLink(message, resource as any);\n\n this.NotificationsService.addSuccess(message);\n }\n\n protected showCustomError(errorResource:any, resource:WorkPackageResource):boolean {\n if (errorResource.errorIdentifier === 'urn:openproject-org:api:v3:errors:UpdateConflict') {\n this.NotificationsService.addError({\n message: errorResource.message,\n type: 'error',\n link: {\n text: this.I18n.t('js.hal.error.update_conflict_refresh'),\n target: () => this.apiV3Service.work_packages.id(resource).refresh()\n }\n });\n\n return true;\n }\n\n return super.showCustomError(errorResource, resource);\n }\n\n private addWorkPackageFullscreenLink(message:INotification, resource:WorkPackageResource) {\n // Don't show the 'Show in full screen' link if we're there already\n if (!this.$state.includes('work-packages.show')) {\n message.link = {\n target: () => this.$state.go('work-packages.show.activity', {workPackageId: resource.id}),\n text: this.I18n.t('js.work_packages.message_successful_show_in_fullscreen')\n };\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport const QUERY_SORT_BY_ASC = \"urn:openproject-org:api:v3:queries:directions:asc\"\nexport const QUERY_SORT_BY_DESC = \"urn:openproject-org:api:v3:queries:directions:desc\"\n\nexport interface QuerySortByResourceEmbedded {\n column:QueryColumn;\n direction:QuerySortByDirection;\n}\n\nexport class QuerySortByResource extends HalResource {\n public $embedded:QuerySortByResourceEmbedded;\n public column:QueryColumn;\n public direction:QuerySortByDirection;\n}\n\n/**\n * A direction for sorting\n */\nexport class QuerySortByDirection extends HalResource {\n public get id():string {\n return this.$href!.split('/').pop()!;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {WorkPackageRelationsHierarchyService} from 'core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service';\nimport {take} from 'rxjs/operators';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-relations-hierarchy',\n templateUrl: './wp-relations-hierarchy.template.html'\n})\nexport class WorkPackageRelationsHierarchyComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public relationType:string;\n\n public showEditForm:boolean = false;\n public workPackagePath:string;\n public canHaveChildren:boolean;\n public canModifyHierarchy:boolean;\n public canAddRelation:boolean;\n\n public childrenQueryProps:any;\n\n constructor(protected wpRelationsHierarchyService:WorkPackageRelationsHierarchyService,\n protected apiV3Service:APIV3Service,\n protected PathHelper:PathHelperService,\n readonly I18n:I18nService) {\n super();\n }\n\n public text = {\n parentHeadline: this.I18n.t('js.relations_hierarchy.parent_headline'),\n childrenHeadline: this.I18n.t('js.relations_hierarchy.children_headline'),\n };\n\n ngOnInit() {\n this.workPackagePath = this.PathHelper.workPackagePath(this.workPackage.id!);\n this.canModifyHierarchy = !!this.workPackage.changeParent;\n this.canAddRelation = !!this.workPackage.addRelation;\n\n this.childrenQueryProps = {\n filters: JSON.stringify([{ parent: { operator: '=', values: [this.workPackage.id] } }]),\n 'columns[]': ['id', 'type', 'subject', 'status'],\n showHierarchies: false\n };\n\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n\n let parentId = this.workPackage.parent?.id?.toString();\n\n if (parentId) {\n this\n .apiV3Service\n .work_packages\n .id(parentId)\n .get()\n .pipe(\n take(1)\n )\n .subscribe((parent:WorkPackageResource) => {\n this.workPackage.parent = parent;\n });\n }\n });\n }\n}\n","
    \n
    \n
    \n

    \n

    \n
    \n
    \n \n \n \n \n
    \n","
    \n
    \n\n
    \n \n\n\n \n \n \n \n
    \n \n
    \n
    \n\n
    \n \n \n
    \n\n
    \n \n \n \n
    \n\n
    \n \n \n \n \n \n \n
    \n
    \n\n
    \n
    \n
    \n
    \n \n \n \n
    \n
    \n
    \n","import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageRelationsService} from '../wp-relations.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {ChangeDetectorRef, Component, ElementRef, Input, OnInit, ViewChild} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Component({\n selector: 'wp-relation-row',\n templateUrl: './wp-relation-row.template.html'\n})\nexport class WorkPackageRelationRowComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public relatedWorkPackage:WorkPackageResource;\n @Input() public groupByWorkPackageType:boolean;\n\n @ViewChild('relationDescriptionTextarea') readonly relationDescriptionTextarea:ElementRef;\n\n public relationType:string;\n public showRelationInfo:boolean = false;\n public showEditForm:boolean = false;\n public availableRelationTypes:{ label:string, name:string }[];\n public selectedRelationType:{ name:string };\n\n public userInputs = {\n newRelationText: '',\n showDescriptionEditForm: false,\n showRelationTypesForm: false,\n showRelationInfo: false,\n };\n\n // Create a quasi-field object\n public fieldController = {\n handler: {\n active: true,\n },\n required: false\n };\n\n public relation:RelationResource;\n public text = {\n cancel: this.I18n.t('js.button_cancel'),\n save: this.I18n.t('js.button_save'),\n removeButton: this.I18n.t('js.relation_buttons.remove'),\n description_label: this.I18n.t('js.relation_buttons.update_description'),\n toggleDescription: this.I18n.t('js.relation_buttons.toggle_description'),\n updateRelation: this.I18n.t('js.relation_buttons.update_relation'),\n placeholder: {\n description: this.I18n.t('js.placeholders.relation_description')\n }\n };\n\n constructor(protected apiV3Service:APIV3Service,\n protected notificationService:WorkPackageNotificationService,\n protected wpRelations:WorkPackageRelationsService,\n protected halEvents:HalEventsService,\n protected I18n:I18nService,\n protected cdRef:ChangeDetectorRef,\n protected PathHelper:PathHelperService) {\n super();\n }\n\n ngOnInit() {\n this.relation = this.relatedWorkPackage.relatedBy as RelationResource;\n\n this.userInputs.newRelationText = this.relation.description || '';\n this.availableRelationTypes = RelationResource.LOCALIZED_RELATION_TYPES(false);\n this.selectedRelationType = _.find(this.availableRelationTypes,\n { 'name': this.relation.normalizedType(this.workPackage) })!;\n\n this\n .apiV3Service\n .work_packages\n .id(this.relatedWorkPackage)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n ).subscribe((wp) => {\n this.relatedWorkPackage = wp;\n });\n }\n\n /**\n * Return the normalized relation type for the work package we're viewing.\n * That is, normalize `precedes` where the work package is the `to` link.\n */\n public get normalizedRelationType() {\n var type = this.relation.normalizedType(this.workPackage);\n return this.I18n.t('js.relation_labels.' + type);\n }\n\n public get relationReady() {\n return this.relatedWorkPackage && this.relatedWorkPackage.$loaded;\n }\n\n public startDescriptionEdit() {\n this.userInputs.showDescriptionEditForm = true;\n setTimeout(() => {\n const textarea = jQuery(this.relationDescriptionTextarea.nativeElement);\n const textlen = (textarea.val() as string).length;\n // Focus and set cursor to end\n textarea.focus();\n\n textarea.prop('selectionStart', textlen);\n textarea.prop('selectionEnd', textlen);\n });\n }\n\n public handleDescriptionKey($event:JQuery.TriggeredEvent) {\n if ($event.which === 27) {\n this.cancelDescriptionEdit();\n }\n }\n\n public cancelDescriptionEdit() {\n this.userInputs.showDescriptionEditForm = false;\n this.userInputs.newRelationText = this.relation.description || '';\n }\n\n public saveDescription() {\n this.wpRelations.updateRelation(\n this.relation,\n { description: this.userInputs.newRelationText })\n .then((savedRelation:RelationResource) => {\n this.relation = savedRelation;\n this.relatedWorkPackage.relatedBy = savedRelation;\n this.userInputs.showDescriptionEditForm = false;\n this.notificationService.showSave(this.relatedWorkPackage);\n this.cdRef.detectChanges();\n });\n }\n\n public get showDescriptionInfo() {\n return this.userInputs.showRelationInfo || this.relation.description;\n }\n\n public activateRelationTypeEdit() {\n if (this.groupByWorkPackageType) {\n this.userInputs.showRelationTypesForm = true;\n }\n }\n\n public cancelRelationTypeEditOnEscape(evt:JQuery.TriggeredEvent) {\n this.userInputs.showRelationTypesForm = false;\n }\n\n public saveRelationType() {\n this.wpRelations.updateRelationType(\n this.workPackage,\n this.relatedWorkPackage,\n this.relation,\n this.selectedRelationType.name)\n .then((savedRelation:RelationResource) => {\n this.notificationService.showSave(this.relatedWorkPackage);\n this.relatedWorkPackage.relatedBy = savedRelation;\n this.relation = savedRelation;\n\n this.userInputs.showRelationTypesForm = false;\n this.cdRef.detectChanges();\n })\n .catch((error:any) => this.notificationService.handleRawError(error, this.workPackage));\n }\n\n public toggleUserDescriptionForm() {\n this.userInputs.showDescriptionEditForm = !this.userInputs.showDescriptionEditForm;\n }\n\n public removeRelation() {\n this.wpRelations.removeRelation(this.relation)\n .then(() => {\n this.halEvents.push(this.workPackage, {\n eventType: 'association',\n relatedWorkPackage: null,\n relationType: this.relation.normalizedType(this.workPackage)\n });\n\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(this.relatedWorkPackage);\n\n this.notificationService.showSave(this.relatedWorkPackage);\n })\n .catch((err:any) => this.notificationService.handleRawError(err,\n this.relatedWorkPackage));\n }\n}\n","
    \n
    \n
    \n

    \n

    \n
    \n
    \n \n \n \n
    \n
    \n\n
    \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Component, ElementRef, EventEmitter, Input, Output, ViewChild} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n\n\n@Component({\n selector: 'wp-relations-group',\n templateUrl: './wp-relations-group.template.html'\n})\nexport class WorkPackageRelationsGroupComponent {\n @Input() public relatedWorkPackages:WorkPackageResource[];\n @Input() public workPackage:WorkPackageResource;\n @Input() public header:string;\n @Input() public firstGroup:boolean;\n @Input() public groupByWorkPackageType:boolean;\n\n @Output() public onToggleGroupBy = new EventEmitter();\n\n @ViewChild('wpRelationGroupByToggler') readonly toggleElement:ElementRef;\n\n public text = {\n groupByType: this.I18n.t('js.relation_buttons.group_by_wp_type'),\n groupByRelation: this.I18n.t('js.relation_buttons.group_by_relation_type')\n };\n\n constructor(\n readonly I18n:I18nService) {\n }\n\n public get togglerText() {\n if (this.groupByWorkPackageType) {\n return this.text.groupByRelation;\n } else {\n return this.text.groupByType;\n }\n }\n\n public toggleButton() {\n this.onToggleGroupBy.emit();\n\n setTimeout(() => {\n this.toggleElement.nativeElement.focus();\n }, 20);\n }\n}\n","
    \n
    \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n \n \n \n
    \n
    \n
    \n
    \n\n\n\n\n","import {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageRelationsService} from '../wp-relations.service';\nimport {Component, Input} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Component({\n selector: 'wp-relations-create',\n templateUrl: './wp-relation-create.template.html'\n})\nexport class WorkPackageRelationsCreateComponent {\n @Input() readonly workPackage:WorkPackageResource;\n\n public showRelationsCreateForm:boolean = false;\n public selectedRelationType:string = RelationResource.DEFAULT();\n public selectedWpId:string;\n public relationTypes = RelationResource.LOCALIZED_RELATION_TYPES(false);\n\n public isDisabled = false;\n\n public text = {\n abort: this.I18n.t('js.relation_buttons.abort'),\n relationType: this.I18n.t('js.relation_buttons.relation_type'),\n addNewRelation: this.I18n.t('js.relation_buttons.add_new_relation')\n };\n\n constructor(readonly I18n:I18nService,\n protected wpRelations:WorkPackageRelationsService,\n protected notificationService:WorkPackageNotificationService,\n protected halEvents:HalEventsService) {\n }\n\n\n public createRelation() {\n\n if (!this.selectedRelationType || !this.selectedWpId) {\n return;\n }\n\n this.isDisabled = true;\n this.createCommonRelation()\n .catch(() => this.isDisabled = false)\n .then(() => this.isDisabled = false);\n }\n\n public onSelected(workPackage?:WorkPackageResource) {\n if (workPackage) {\n this.selectedWpId = workPackage.id!;\n this.createCommonRelation();\n }\n }\n\n protected createCommonRelation() {\n return this.wpRelations.addCommonRelation(this.workPackage.id!,\n this.selectedRelationType,\n this.selectedWpId)\n .then(relation => {\n this.halEvents.push(this.workPackage, {\n eventType: 'association',\n relatedWorkPackage: relation.id!,\n relationType: this.selectedRelationType\n });\n this.notificationService.showSave(this.workPackage);\n this.toggleRelationsCreateForm();\n })\n .catch(err => {\n this.notificationService.handleRawError(err, this.workPackage);\n this.toggleRelationsCreateForm();\n });\n }\n\n public toggleRelationsCreateForm() {\n this.showRelationsCreateForm = !this.showRelationsCreateForm;\n // Reset value\n this.selectedWpId = '';\n }\n}\n","
    \n\n
    \n
    \n
    \n

    \n

    \n
    \n
    \n
    \n\n\n
    \n \n
    \n \n \n\n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\nimport {Observable, zip} from 'rxjs';\nimport {take, takeUntil} from 'rxjs/operators';\nimport {RelatedWorkPackagesGroup} from './wp-relations.interfaces';\nimport {RelationsStateValue, WorkPackageRelationsService} from './wp-relations.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Component({\n selector: 'wp-relations',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './wp-relations.template.html'\n})\nexport class WorkPackageRelationsComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n public relationGroups:RelatedWorkPackagesGroup = {};\n public relationGroupKeys:string[] = [];\n public relationsPresent:boolean = false;\n public canAddRelation:boolean;\n\n // By default, group by relation type\n public groupByWorkPackageType = false;\n\n public text = {\n relations_header: this.I18n.t('js.work_packages.tabs.relations')\n };\n public currentRelations:WorkPackageResource[] = [];\n\n constructor(private I18n:I18nService,\n private wpRelations:WorkPackageRelationsService,\n private cdRef:ChangeDetectorRef,\n private apiV3Service:APIV3Service) {\n super();\n }\n\n ngOnInit() {\n this.canAddRelation = !!this.workPackage.addRelation;\n\n this.wpRelations\n .state(this.workPackage.id!)\n .values$()\n .pipe(\n takeUntil(componentDestroyed(this))\n )\n .subscribe((relations:RelationsStateValue) => {\n this.loadedRelations(relations);\n });\n\n this.wpRelations.require(this.workPackage.id!);\n\n // Listen for changes to this WP.\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .requireAndStream()\n .pipe(\n takeUntil(componentDestroyed(this))\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n });\n }\n\n private getRelatedWorkPackages(workPackageIds:string[]):Observable {\n let observablesToGetZipped:Observable[] = workPackageIds.map(wpId =>\n this\n .apiV3Service\n .work_packages\n .id(wpId)\n .get()\n );\n\n return zip(...observablesToGetZipped);\n }\n\n protected getRelatedWorkPackageId(relation:RelationResource):string {\n const involved = relation.ids;\n return (relation.to.href === this.workPackage.href) ? involved.from : involved.to;\n }\n\n public toggleGroupBy() {\n this.groupByWorkPackageType = !this.groupByWorkPackageType;\n this.buildRelationGroups();\n }\n\n protected buildRelationGroups() {\n if (_.isNil(this.currentRelations)) {\n return;\n }\n\n this.relationGroups = _.groupBy(this.currentRelations,\n (wp:WorkPackageResource) => {\n if (this.groupByWorkPackageType) {\n return wp.type.name;\n } else {\n var normalizedType = (wp.relatedBy as RelationResource).normalizedType(this.workPackage);\n return this.I18n.t('js.relation_labels.' + normalizedType);\n }\n });\n this.relationGroupKeys = _.keys(this.relationGroups);\n this.relationsPresent = _.size(this.relationGroups) > 0;\n this.cdRef.detectChanges();\n }\n\n protected loadedRelations(stateValues:RelationsStateValue):void {\n var relatedWpIds:string[] = [];\n var relations:{ [wpId:string]:any } = [];\n\n if (_.size(stateValues) === 0) {\n this.currentRelations = [];\n return this.buildRelationGroups();\n }\n\n _.each(stateValues, (relation:RelationResource) => {\n const relatedWpId = this.getRelatedWorkPackageId(relation);\n relatedWpIds.push(relatedWpId);\n relations[relatedWpId] = relation;\n });\n\n this.getRelatedWorkPackages(relatedWpIds)\n .pipe(\n take(1)\n )\n .subscribe((relatedWorkPackages:WorkPackageResource[]) => {\n this.currentRelations = relatedWorkPackages.map((wp:WorkPackageResource) => {\n wp.relatedBy = relations[wp.id!];\n return wp;\n });\n\n this.buildRelationGroups();\n });\n }\n}\n","
    \n
    \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Transition} from '@uirouter/core';\nimport {Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './relations-tab.html',\n selector: 'wp-relations-tab',\n})\nexport class WorkPackageRelationsTabComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackageId?:string;\n public workPackage:WorkPackageResource;\n\n public constructor(readonly I18n:I18nService,\n readonly $transition:Transition,\n readonly apiV3Service:APIV3Service) {\n super();\n }\n\n ngOnInit() {\n const wpId = this.workPackageId || this.$transition.params('to').workPackageId;\n this\n .apiV3Service\n .work_packages\n .id(wpId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp) => {\n this.workPackageId = wp.id!;\n this.workPackage = wp;\n });\n }\n\n}\n","import {Injector} from \"@angular/core\";\nimport {\n WorkPackageAction,\n WorkPackageContextMenuHelperService\n} from \"core-components/wp-table/context-menu-helper/wp-context-menu-helper.service\";\nimport {States} from \"core-components/states.service\";\nimport {WorkPackageRelationsHierarchyService} from \"core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {LinkHandling} from \"core-app/modules/common/link-handling/link-handling\";\nimport {OpContextMenuHandler} from \"core-components/op-context-menu/op-context-menu-handler\";\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {OpContextMenuItem, OpContextMenuLocalsMap} from \"core-components/op-context-menu/op-context-menu.types\";\nimport {PERMITTED_CONTEXT_MENU_ACTIONS} from \"core-components/op-context-menu/wp-context-menu/wp-static-context-menu-actions\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {WpDestroyModal} from \"core-components/modals/wp-destroy-modal/wp-destroy.modal\";\nimport {StateService} from \"@uirouter/core\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {TimeEntryCreateService} from \"core-app/modules/time_entries/create/create.service\";\nimport {splitViewRoute} from \"core-app/modules/work_packages/routing/split-view-routes.helper\";\n\nexport class WorkPackageViewContextMenu extends OpContextMenuHandler {\n\n @InjectField() protected states!:States;\n @InjectField() protected wpRelationsHierarchyService:WorkPackageRelationsHierarchyService;\n @InjectField() protected opModalService:OpModalService;\n @InjectField() protected $state!:StateService;\n @InjectField() protected wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() protected WorkPackageContextMenuHelper!:WorkPackageContextMenuHelperService;\n @InjectField() protected timeEntryCreateService:TimeEntryCreateService;\n\n protected workPackage = this.states.workPackages.get(this.workPackageId).value!;\n protected selectedWorkPackages = this.getSelectedWorkPackages();\n protected permittedActions = this.WorkPackageContextMenuHelper.getPermittedActions(\n this.selectedWorkPackages,\n PERMITTED_CONTEXT_MENU_ACTIONS,\n this.allowSplitScreenActions\n );\n\n // Get the base route for the current route to ensure we always link correctly\n protected baseRoute = this.$state.current.data.baseRoute || this.$state.current.name;\n\n protected items = this.buildItems();\n\n constructor(public injector:Injector,\n protected workPackageId:string,\n protected $element:JQuery,\n protected additionalPositionArgs:any = {},\n protected allowSplitScreenActions:boolean = true) {\n super(injector.get(OPContextMenuService));\n }\n\n public get locals():OpContextMenuLocalsMap {\n return { contextMenuId: 'work-package-context-menu', items: this.items };\n }\n\n public positionArgs(evt:JQuery.TriggeredEvent) {\n let position = super.positionArgs(evt);\n _.assign(position, this.additionalPositionArgs);\n\n return position;\n }\n\n public triggerContextMenuAction(action:WorkPackageAction) {\n const link = action.link;\n\n switch (action.key) {\n case 'delete':\n this.deleteSelectedWorkPackages();\n break;\n\n case 'edit':\n this.editSelectedWorkPackages(link!);\n break;\n\n case 'copy':\n this.copySelectedWorkPackages(link!);\n break;\n\n case 'relation-new-child':\n this.wpRelationsHierarchyService.addNewChildWp(this.baseRoute, this.workPackage);\n break;\n\n case 'log_time':\n this.logTimeForSelectedWorkPackage();\n break;\n\n default:\n window.location.href = link!;\n break;\n }\n }\n\n private deleteSelectedWorkPackages() {\n let selected = this.getSelectedWorkPackages();\n this.opModalService.show(WpDestroyModal, this.injector, { workPackages: selected });\n }\n\n private editSelectedWorkPackages(link:any) {\n let selected = this.getSelectedWorkPackages();\n\n if (selected.length > 1) {\n window.location.href = link;\n return;\n }\n }\n\n private copySelectedWorkPackages(link:any) {\n let selected = this.getSelectedWorkPackages();\n\n if (selected.length > 1) {\n window.location.href = link;\n return;\n }\n\n let params = {\n copiedFromWorkPackageId: selected[0].id\n };\n\n this.$state.go(this.baseRoute + '.copy', params);\n }\n\n private logTimeForSelectedWorkPackage() {\n this.timeEntryCreateService\n .create(moment(new Date()), this.workPackage)\n .catch(() => {\n // do nothing, the user closed without changes\n });\n }\n\n private getSelectedWorkPackages() {\n let selectedWorkPackages = this.wpTableSelection.getSelectedWorkPackages();\n\n if (selectedWorkPackages.length === 0) {\n return [this.workPackage];\n }\n\n if (selectedWorkPackages.indexOf(this.workPackage) === -1) {\n selectedWorkPackages.push(this.workPackage);\n }\n\n return selectedWorkPackages;\n }\n\n protected buildItems():OpContextMenuItem[] {\n let items = this.permittedActions.map((action:WorkPackageAction) => {\n return {\n class: undefined as string|undefined,\n disabled: false,\n linkText: action.text,\n href: action.href,\n icon: action.icon != null ? action.icon : `icon-${action.key}`,\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (action.href && LinkHandling.isClickedWithModifier($event)) {\n return false;\n }\n\n this.triggerContextMenuAction(action);\n return true;\n }\n };\n });\n\n\n if (!this.workPackage.isNew) {\n items.unshift({\n disabled: false,\n icon: 'icon-view-fullscreen',\n class: 'openFullScreenView',\n href: this.$state.href('work-packages.show', { workPackageId: this.workPackageId }),\n linkText: I18n.t('js.button_open_fullscreen'),\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (LinkHandling.isClickedWithModifier($event)) {\n return false;\n }\n\n this.$state.go(\n 'work-packages.show',\n { workPackageId: this.workPackageId }\n );\n return true;\n }\n });\n\n if (this.allowSplitScreenActions) {\n items.unshift({\n disabled: false,\n icon: 'icon-view-split',\n class: 'detailsViewMenuItem',\n href: this.$state.href(\n splitViewRoute(this.$state) + '.overview',\n { workPackageId: this.workPackageId }),\n linkText: I18n.t('js.button_open_details'),\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (LinkHandling.isClickedWithModifier($event)) {\n return false;\n }\n\n this.$state.go(\n splitViewRoute(this.$state) + '.overview',\n { workPackageId: this.workPackageId }\n );\n return true;\n }\n });\n }\n }\n\n return items;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AbstractWorkPackageButtonComponent} from '../wp-buttons.module';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\n\nimport * as sfimport from \"screenfull\";\nimport {Screenfull} from \"screenfull\";\n\nconst screenfull:Screenfull = sfimport as any;\nexport const zenModeComponentSelector = 'zen-mode-toggle-button';\n\n@Component({\n templateUrl: '../wp-button.template.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: zenModeComponentSelector,\n})\nexport class ZenModeButtonComponent extends AbstractWorkPackageButtonComponent {\n public buttonId:string = 'work-packages-zen-mode-toggle-button';\n public buttonClass:string = 'toolbar-icon';\n public iconClass:string = 'icon-zen-mode';\n\n static inZenMode:boolean = false;\n\n private activateLabel:string;\n private deactivateLabel:string;\n\n constructor(readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef) {\n super(I18n);\n\n this.activateLabel = I18n.t('js.zen_mode.button_activate');\n this.deactivateLabel = I18n.t('js.zen_mode.button_deactivate');\n let self = this;\n\n\n if (screenfull.enabled) {\n screenfull.onchange(function() {\n // This event might get triggered several times for once leaving\n // fullscreen mode.\n if (!screenfull.isFullscreen) {\n self.deactivateZenMode();\n }\n });\n }\n }\n\n public get label():string {\n if (this.isActive) {\n return this.deactivateLabel;\n } else {\n return this.activateLabel;\n }\n }\n\n public isToggle():boolean {\n return true;\n }\n\n private deactivateZenMode():void {\n this.isActive = ZenModeButtonComponent.inZenMode = false;\n jQuery('body').removeClass('zen-mode');\n this.disabled = false;\n if (screenfull.enabled && screenfull.isFullscreen) {\n screenfull.exit();\n }\n this.cdRef.detectChanges();\n }\n\n private activateZenMode() {\n this.isActive = ZenModeButtonComponent.inZenMode = true;\n jQuery('body').addClass('zen-mode');\n if (screenfull.enabled) {\n screenfull.request();\n }\n this.cdRef.detectChanges();\n }\n\n public performAction(evt:Event):false {\n if (ZenModeButtonComponent.inZenMode) {\n this.deactivateZenMode();\n } else {\n this.activateZenMode();\n }\n\n evt.preventDefault();\n return false;\n }\n}\n","\n","import \"reflect-metadata\";\nimport {InjectFlags, Injector} from \"@angular/core\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\n\nexport interface InjectableClass {\n injector:Injector;\n}\n\nexport function InjectField(token?:any, defaultValue:any = null, flags?:InjectFlags) {\n return (target:InjectableClass, property:string) => {\n if (delete (target as any)[property]) {\n Object.defineProperty(target, property, {\n get: function(this:InjectableClass) {\n if (token) {\n return this.injector.get(token, defaultValue, flags);\n } else {\n const type = Reflect.getMetadata('design:type', target, property);\n return this.injector.get(type, defaultValue, flags);\n }\n },\n set: function(this:InjectableClass, _val:any) {\n debugLog(\"Trying to set InjectField property \" + property);\n }\n });\n }\n };\n};","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectorRef, Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {OpTitleService} from 'core-components/html/op-title.service';\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {States} from \"core-components/states.service\";\nimport {KeepTabService} from \"core-components/wp-single-view-tabs/keep-tab/keep-tab.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {catchError, subscribeOn} from \"rxjs/operators\";\n\nexport class WorkPackageSingleViewBase extends UntilDestroyedMixin {\n\n @InjectField() states:States;\n @InjectField() I18n!:I18nService;\n @InjectField() keepTab:KeepTabService;\n @InjectField() PathHelper:PathHelperService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() wpTableFocus:WorkPackageViewFocusService;\n @InjectField() notificationService:WorkPackageNotificationService;\n @InjectField() authorisationService:AuthorisationService;\n @InjectField() cdRef:ChangeDetectorRef;\n @InjectField() readonly titleService:OpTitleService;\n @InjectField() readonly apiV3Service:APIV3Service;\n\n // Static texts\n public text:any = {};\n\n // Work package resource to be loaded from the cache\n public workPackage:WorkPackageResource;\n public projectIdentifier:string;\n\n public focusAnchorLabel:string;\n public showStaticPagePath:string;\n\n constructor(public injector:Injector, protected workPackageId:string) {\n super();\n this.initializeTexts();\n }\n\n /**\n * Observe changes of work package and re-run initialization.\n * Needs to be run explicitly by descendants.\n */\n protected observeWorkPackage() {\n /** Require the work package once to ensure we're displaying errors */\n this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.init();\n this.cdRef.detectChanges();\n },\n (error) => this.notificationService.handleRawError(error)\n );\n }\n\n /**\n * Provide static translations\n */\n protected initializeTexts() {\n this.text.tabs = {};\n ['overview', 'activity', 'relations', 'watchers'].forEach(tab => {\n this.text.tabs[tab] = this.I18n.t('js.work_packages.tabs.' + tab);\n });\n }\n\n /**\n * Initialize controller after workPackage resource has been loaded.\n */\n protected init() {\n // Set elements\n this\n .apiV3Service\n .projects\n .id(this.workPackage.project)\n .requireAndStream()\n .subscribe(() => {\n this.projectIdentifier = this.workPackage.project.identifier;\n this.cdRef.detectChanges();\n });\n\n // Set authorisation data\n this.authorisationService.initModelAuth('work_package', this.workPackage.$links);\n\n // Push the current title\n this.titleService.setFirstPart(this.workPackage.subjectWithType(20));\n\n // Preselect this work package for future list operations\n this.showStaticPagePath = this.PathHelper.workPackagePath(this.workPackageId);\n\n // Listen to tab changes to update the tab label\n this.keepTab.observable\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((tabs:any) => {\n this.updateFocusAnchorLabel(tabs.active);\n });\n }\n\n /**\n * Recompute the current tab focus label\n */\n public updateFocusAnchorLabel(tabName:string):string {\n const tabLabel = this.I18n.t('js.label_work_package_details_you_are_here', {\n tab: this.I18n.t('js.work_packages.tabs.' + tabName),\n type: this.workPackage.type.name,\n subject: this.workPackage.subject\n });\n\n return this.focusAnchorLabel = tabLabel;\n }\n\n public canViewWorkPackageWatchers() {\n return !!(this.workPackage && this.workPackage.watchers);\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {Board} from \"core-app/modules/boards/board/board\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {ApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class BoardListsService {\n\n private v3 = this.pathHelper.api.v3;\n\n constructor(private readonly CurrentProject:CurrentProjectService,\n private readonly pathHelper:PathHelperService,\n private readonly apiV3Service:APIV3Service,\n private readonly halResourceService:HalResourceService,\n private readonly notifications:NotificationsService,\n private readonly I18n:I18nService) {\n\n }\n\n private create(params:Object, filters:ApiV3Filter[]):Promise {\n let filterJson = JSON.stringify(filters);\n\n return this\n .apiV3Service\n .queries\n .form\n .loadWithParams(\n {\n pageSize: 0,\n filters: filterJson\n },\n undefined,\n this.CurrentProject.identifier,\n this.buildQueryRequest(params),\n )\n .toPromise()\n .then(([form, query]) => {\n // When the permission to create public queries is missing, throw an error.\n // Otherwise private queries would be created.\n if (form.schema['public'].writable) {\n return this\n .apiV3Service\n .queries\n .post(query, form)\n .toPromise();\n } else {\n throw new Error(this.I18n.t('js.boards.error_permission_missing'));\n }\n });\n }\n\n /**\n * Add a free query to the board\n */\n public addFreeQuery(board:Board, queryParams:Object) {\n const filter = this.freeBoardQueryFilter();\n return this.addQuery(board, queryParams, [filter]);\n }\n\n /**\n * Add an empty query to the board\n * @param board\n * @param query\n */\n public async addQuery(board:Board, queryParams:Object, filters:ApiV3Filter[]):Promise {\n const count = board.queries.length;\n try {\n const query = await this.create(queryParams, filters);\n\n let source = {\n _type: 'GridWidget',\n identifier: 'work_package_query',\n startRow: 1,\n endRow: 2,\n startColumn: count + 1,\n endColumn: count + 2,\n options: {\n queryId: query.id,\n filters: filters,\n }\n };\n\n let resource = this.halResourceService.createHalResourceOfClass(GridWidgetResource, source);\n board.addQuery(resource);\n } catch (e) {\n this.notifications.addError(e);\n console.error(e);\n }\n return board;\n }\n\n private buildQueryRequest(params:Object) {\n return {\n hidden: true,\n public: true,\n \"_links\": {\n \"sortBy\": [\n { \"href\": this.v3.apiV3Base + \"/queries/sort_bys/manualSorting-asc\" },\n { \"href\": this.v3.apiV3Base + \"/queries/sort_bys/id-asc\" },\n ]\n },\n ...params\n };\n }\n\n private freeBoardQueryFilter():ApiV3Filter {\n return { manualSort: { operator: 'ow', values: [] } };\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class CurrentProjectService {\n private current:{ id:string, identifier:string, name:string };\n\n constructor(private PathHelper:PathHelperService,\n private apiV3Service:APIV3Service) {\n this.detect();\n }\n\n public get inProjectContext():boolean {\n return this.current !== undefined;\n }\n\n public get path():string|null {\n if (this.current) {\n return this.PathHelper.projectPath(this.current.identifier);\n }\n\n return null;\n }\n\n public get apiv3Path():string|null {\n if (this.current) {\n return this.apiV3Service.projects.id(this.current.id).toString();\n }\n\n return null;\n }\n\n public get id():string|null {\n return this.getCurrent('id');\n }\n\n public get name():string|null {\n return this.getCurrent('name');\n }\n\n public get identifier():string|null {\n return this.getCurrent('identifier');\n }\n\n private getCurrent(key:'id'|'identifier'|'name') {\n if (this.current && this.current[key]) {\n return this.current[key].toString();\n }\n\n return null;\n }\n\n /**\n * Detect the current project from its meta tag.\n */\n public detect() {\n const element:HTMLMetaElement|null = document.querySelector('meta[name=current_project]');\n if (element) {\n this.current = {\n id: element.dataset.projectId!,\n name: element.dataset.projectName!,\n identifier: element.dataset.projectIdentifier!\n };\n }\n }\n}\n","import {\n contextColumnIcon,\n OpTableAction,\n OpTableActionFactory,\n} from 'core-components/wp-table/table-actions/table-action';\nimport {opIconElement} from 'core-app/helpers/op-icon-builder';\nimport {Injector} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\nexport class OpUnlinkTableAction extends OpTableAction {\n\n constructor(public injector:Injector,\n public workPackage:WorkPackageResource,\n public readonly identifier:string,\n private title:string,\n readonly applicable:(workPackage:WorkPackageResource) => boolean,\n readonly onClick:(workPackage:WorkPackageResource) => void) {\n super(injector, workPackage);\n\n }\n\n /**\n * Returns a factory for this action with the given title and identifier for reusing\n * remove actions.\n *\n * @param {string} identifier\n * @param {string} title\n */\n public static factoryFor(identifier:string,\n title:string,\n onClick:(workPackage:WorkPackageResource) => void,\n applicable:(workPackage:WorkPackageResource) => boolean = () => true):OpTableActionFactory {\n return (injector:Injector, workPackage:WorkPackageResource) => {\n return new OpUnlinkTableAction(injector,\n workPackage,\n identifier,\n title,\n applicable,\n onClick) as OpTableAction;\n };\n }\n\n public buildElement() {\n if (!this.applicable(this.workPackage)) {\n return null;\n }\n\n let element = document.createElement('a');\n element.title = this.title;\n element.href = '#';\n element.classList.add(contextColumnIcon, 'wp-table-action--unlink');\n element.dataset.workPackageId = this.workPackage.id!;\n element.appendChild(opIconElement('icon', 'icon-close'));\n jQuery(element).click((event) => {\n event.preventDefault();\n this.onClick(this.workPackage);\n });\n\n return element;\n }\n}\n","import {\n ApplicationRef,\n ChangeDetectorRef,\n Component,\n ComponentFactoryResolver,\n ElementRef,\n EventEmitter,\n Inject,\n InjectionToken,\n Injector,\n OnDestroy,\n OnInit,\n Optional,\n ViewChild\n} from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {WpTableConfigurationService} from 'core-components/wp-table/configuration-modal/wp-table-configuration.service';\nimport {\n ActiveTabInterface,\n TabComponent,\n TabInterface,\n TabPortalOutlet\n} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {WorkPackageStatesInitializationService} from 'core-components/wp-list/wp-states-initialization.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {QueryFormResource} from 'core-app/modules/hal/resources/query-form-resource';\nimport {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {ComponentType} from \"@angular/cdk/portal\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const WpTableConfigurationModalPrependToken = new InjectionToken>('WpTableConfigurationModalPrependComponent');\n\n@Component({\n templateUrl: './wp-table-configuration.modal.html'\n})\nexport class WpTableConfigurationModalComponent extends OpModalComponent implements OnInit, OnDestroy {\n\n /* Close on escape? */\n public closeOnEscape = false;\n\n /* Close on outside click */\n public closeOnOutsideClick = false;\n\n public $element:JQuery;\n\n public text = {\n title: this.I18n.t('js.work_packages.table_configuration.modal_title'),\n closePopup: this.I18n.t('js.close_popup_title'),\n\n columnsLabel: this.I18n.t('js.label_columns'),\n selectedColumns: this.I18n.t('js.description_selected_columns'),\n multiSelectLabel: this.I18n.t('js.work_packages.label_column_multiselect'),\n applyButton: this.I18n.t('js.modals.button_apply'),\n cancelButton: this.I18n.t('js.modals.button_cancel'),\n\n upsaleRelationColumns: this.I18n.t('js.modals.upsale_relation_columns'),\n upsaleRelationColumnsLink: this.I18n.t('js.modals.upsale_relation_columns_link')\n };\n\n public onDataUpdated = new EventEmitter();\n public selectedColumnMap:{ [id:string]:boolean } = {};\n\n // Get the view child we'll use as the portal host\n @ViewChild('tabContentOutlet', { static: true }) tabContentOutlet:ElementRef;\n // And a reference to the actual portal host interface\n public tabPortalHost:TabPortalOutlet;\n\n // Try to load an optional provided configuration service, and fall back to the default one\n private wpTableConfigurationService:WpTableConfigurationService =\n this.injector.get(WpTableConfigurationService, new WpTableConfigurationService(this.I18n));\n\n constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n @Optional() @Inject(WpTableConfigurationModalPrependToken) public prependModalComponent:ComponentType|null,\n readonly I18n:I18nService,\n readonly injector:Injector,\n readonly appRef:ApplicationRef,\n readonly componentFactoryResolver:ComponentFactoryResolver,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpStatesInitialization:WorkPackageStatesInitializationService,\n readonly apiV3Service:APIV3Service,\n readonly notificationService:WorkPackageNotificationService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly cdRef:ChangeDetectorRef,\n readonly ConfigurationService:ConfigurationService,\n readonly elementRef:ElementRef) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.tabPortalHost = new TabPortalOutlet(\n this.wpTableConfigurationService.tabs,\n this.tabContentOutlet.nativeElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n\n this.loadingIndicator.indicator('modal').promise = this.loadForm()\n .then(() => {\n const initialTab = this.locals['initialTab'] || this.availableTabs[0].name;\n this.switchTo(initialTab);\n });\n }\n\n ngOnDestroy() {\n this.onDataUpdated.complete();\n this.tabPortalHost.dispose();\n }\n\n public get availableTabs():TabInterface[] {\n return this.tabPortalHost.availableTabs;\n }\n\n public get currentTab():ActiveTabInterface|null {\n return this.tabPortalHost.currentTab;\n }\n\n public switchTo(name:string) {\n this.tabPortalHost.switchTo(name);\n }\n\n public saveChanges():void {\n this.tabPortalHost.activeComponents.forEach((component:TabComponent) => {\n component.onSave();\n });\n\n this.onDataUpdated.emit();\n this.service.close();\n }\n\n /**\n * Called when the user attempts to close the modal window.\n * The service will close this modal if this method returns true\n * @returns {boolean}\n */\n public onClose():boolean {\n this.afterFocusOn.focus();\n return true;\n }\n\n protected get afterFocusOn():JQuery {\n return this.$element;\n }\n\n protected loadForm() {\n const query = this.querySpace.query.value!;\n return this\n .apiV3Service\n .queries\n .form\n .load(query)\n .toPromise()\n .then(([form, _]) => {\n this.wpStatesInitialization.updateStatesFromForm(query, form);\n\n return form;\n })\n .catch((error) => this.notificationService.handleRawError(error));\n }\n}\n","
    \n
    \n
    \n

    \n\n \n \n
    \n \n
    \n\n \n \n \n\n
    \n \n
    \n\n
    \n
    \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {WorkPackageRelationsHierarchyService} from 'core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service';\nimport {OpUnlinkTableAction} from 'core-components/wp-table/table-actions/actions/unlink-table-action';\nimport {OpTableActionFactory} from 'core-components/wp-table/table-actions/table-action';\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WorkPackageRelationQueryBase} from \"core-components/wp-relations/embedded/wp-relation-query.base\";\nimport {WpChildrenInlineCreateService} from \"core-components/wp-relations/embedded/children/wp-children-inline-create.service\";\nimport {filter} from \"rxjs/operators\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {GroupDescriptor} from \"core-components/work-packages/wp-single-view/wp-single-view.component\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-children-query',\n templateUrl: '../wp-relation-query.html',\n providers: [\n { provide: WorkPackageInlineCreateService, useClass: WpChildrenInlineCreateService },\n ]\n})\nexport class WorkPackageChildrenQueryComponent extends WorkPackageRelationQueryBase implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public query:QueryResource;\n\n /** An optional group descriptor if we're rendering on the single view */\n @Input() public group?:GroupDescriptor;\n @Input() public addExistingChildEnabled:boolean = false;\n\n public tableActions:OpTableActionFactory[] = [\n OpUnlinkTableAction.factoryFor(\n 'remove-child-action',\n this.I18n.t('js.relation_buttons.remove_child'),\n (child:WorkPackageResource) => {\n this.embeddedTable.loadingIndicator = this.wpRelationsHierarchyService.removeChild(child);\n },\n (child:WorkPackageResource) => !!child.changeParent\n )\n ];\n\n constructor(protected wpRelationsHierarchyService:WorkPackageRelationsHierarchyService,\n protected PathHelper:PathHelperService,\n protected wpInlineCreate:WorkPackageInlineCreateService,\n protected halEvents:HalEventsService,\n protected apiV3Service:APIV3Service,\n protected queryUrlParamsHelper:UrlParamsHelperService,\n readonly I18n:I18nService) {\n super(queryUrlParamsHelper);\n }\n\n ngOnInit() {\n // Set reference target and reference class\n this.wpInlineCreate.referenceTarget = this.workPackage;\n\n // Set up the query props\n this.queryProps = this.buildQueryProps();\n\n // Fire event that children were added\n this.wpInlineCreate.newInlineWorkPackageCreated\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((toId:string) => {\n this.halEvents.push(this.workPackage, {\n eventType: 'association',\n relatedWorkPackage: toId,\n relationType: 'child'\n });\n });\n\n // Refresh table when work package is refreshed\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .observe()\n .pipe(\n filter(() => this.embeddedTable && this.embeddedTable.isInitialized),\n this.untilDestroyed()\n )\n .subscribe(() => this.refreshTable());\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewChild} from '@angular/core';\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {AddTagFn} from \"@ng-select/ng-select/lib/ng-select.component\";\nimport {Subject} from 'rxjs';\n\nexport interface CreateAutocompleterValueOption {\n name:string;\n $href:string|null;\n}\n\n@Component({\n templateUrl: './create-autocompleter.component.html',\n selector: 'create-autocompleter'\n})\nexport class CreateAutocompleterComponent implements AfterViewInit {\n @Input() public availableValues:CreateAutocompleterValueOption[];\n @Input() public appendTo:string;\n @Input() public model:any;\n @Input() public required:boolean = false;\n @Input() public disabled:boolean = false;\n @Input() public finishedLoading:boolean = false;\n @Input() public id:string = '';\n @Input() public classes:string = '';\n @Input() public typeahead?:Subject;\n @Input() public hideSelected:boolean = false;\n\n @Output() public onChange = new EventEmitter();\n @Output() public onKeydown = new EventEmitter();\n @Output() public onOpen = new EventEmitter();\n @Output() public onClose = new EventEmitter();\n @Output() public onAfterViewInit = new EventEmitter();\n\n\n @ViewChild('ngSelectComponent') public ngSelectComponent:NgSelectComponent;\n\n public text:{ [key:string]:string } = {\n add_new_action: this.I18n.t('js.label_create'),\n };\n\n public createAllowed:boolean|AddTagFn = false;\n\n private _openDirectly:boolean = false;\n\n constructor(readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly currentProject:CurrentProjectService,\n readonly pathHelper:PathHelperService) {\n }\n\n ngAfterViewInit() {\n this.onAfterViewInit.emit(this);\n }\n\n public openSelect() {\n if (this.ngSelectComponent) {\n this.ngSelectComponent.open();\n } else {\n // In case the autocompleter was not loaded,\n // do not reset the variable\n return;\n }\n\n this.openDirectly = false;\n }\n\n public closeSelect() {\n this.ngSelectComponent && this.ngSelectComponent.close();\n }\n\n public changeModel(element:HalResource) {\n this.onChange.emit(element);\n }\n\n public opened() {\n // Force reposition as a workaround for BUG\n // https://github.com/ng-select/ng-select/issues/1259\n setTimeout(() => {\n const component = this.ngSelectComponent as any;\n if (this.appendTo && component && component.dropdownPanel) {\n component.dropdownPanel._updatePosition();\n }\n }, 25);\n\n this.onOpen.emit();\n }\n\n public closed() {\n this.openDirectly = false;\n this.onClose.emit();\n }\n\n public keyPressed(event:JQuery.TriggeredEvent) {\n this.onKeydown.emit(event);\n }\n\n public get openDirectly() {\n return this._openDirectly;\n }\n\n public set openDirectly(val:boolean) {\n this._openDirectly = val;\n if (val) {\n this.openSelect();\n }\n }\n\n public focusInputField() {\n this.ngSelectComponent && this.ngSelectComponent.focus();\n }\n}\n","
    \n
    \n

    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n\n
    \n\n
    \n
    \n
    \n \n
    \n
    \n\n
    \n
    \n
    \n","\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {WorkPackageViewGroupByService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service';\nimport {QueryGroupByResource} from 'core-app/modules/hal/resources/query-group-by-resource';\nimport {WorkPackageViewHierarchiesService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service';\nimport {WorkPackageViewSumService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service';\nimport {Component, Injector} from \"@angular/core\";\n\n@Component({\n templateUrl: './display-settings-tab.component.html'\n})\nexport class WpTableConfigurationDisplaySettingsTab implements TabComponent {\n\n // Display mode\n public displayMode:'hierarchy'|'grouped'|'default' = 'default';\n\n // Grouping\n public currentGroup:QueryGroupByResource|null;\n public availableGroups:QueryGroupByResource[] = [];\n\n // Sums row display\n public displaySums:boolean = false;\n\n public text = {\n choose_mode: this.I18n.t('js.work_packages.table_configuration.choose_display_mode'),\n label_group_by: this.I18n.t('js.label_group_by'),\n title: this.I18n.t('js.label_group_by'),\n placeholder: this.I18n.t('js.placeholders.default'),\n please_select: this.I18n.t('js.placeholders.selection'),\n default: '— ' + this.I18n.t('js.work_packages.table_configuration.default'),\n display_sums: this.I18n.t('js.work_packages.query.display_sums'),\n display_sums_hint: '— ' + this.I18n.t('js.work_packages.table_configuration.display_sums_hint'),\n display_mode: {\n default: this.I18n.t('js.work_packages.table_configuration.default_mode'),\n grouped: this.I18n.t('js.work_packages.table_configuration.grouped_mode'),\n hierarchy: this.I18n.t('js.work_packages.table_configuration.hierarchy_mode'),\n hierarchy_hint: '— ' + this.I18n.t('js.work_packages.table_configuration.hierarchy_hint')\n }\n };\n\n constructor(readonly injector:Injector,\n readonly I18n:I18nService,\n readonly wpTableGroupBy:WorkPackageViewGroupByService,\n readonly wpTableHierarchies:WorkPackageViewHierarchiesService,\n readonly wpTableSums:WorkPackageViewSumService) {\n }\n\n public onSave() {\n // Update hierarchy state\n this.wpTableHierarchies.setEnabled(this.displayMode === 'hierarchy');\n\n // Update grouping state\n let group = this.displayMode === 'grouped' ? this.currentGroup : null;\n this.wpTableGroupBy.update(group);\n\n // Update sums state\n this.wpTableSums.setEnabled(this.displaySums);\n }\n\n public updateGroup(href:string) {\n this.displayMode = 'grouped';\n this.currentGroup = _.find(this.availableGroups, group => group.href === href) || null;\n }\n\n ngOnInit() {\n if (this.wpTableHierarchies.isEnabled) {\n this.displayMode = 'hierarchy';\n } else if (this.wpTableGroupBy.current) {\n this.displayMode = 'grouped';\n }\n\n this.displaySums = this.wpTableSums.current;\n\n this.wpTableGroupBy\n .onReady()\n .then(() => {\n this.availableGroups = _.sortBy(this.wpTableGroupBy.available, 'name');\n this.currentGroup = this.wpTableGroupBy.current;\n });\n }\n}\n","
    \n
    \n
    \n \n \n
    \n
    \n\n \n \n
    \n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n OnInit,\n Output,\n ViewChild\n} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {DragulaService, Group} from \"ng2-dragula\";\nimport {DomAutoscrollService} from \"core-app/modules/common/drag-and-drop/dom-autoscroll.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {merge} from \"rxjs\";\nimport {DomHelpers} from \"core-app/helpers/dom/set-window-cursor.helper\";\n\nexport interface DraggableOption {\n name:string;\n id:string;\n}\n\n@Component({\n selector: 'draggable-autocompleter',\n templateUrl: './draggable-autocomplete.component.html',\n styleUrls: ['./draggable-autocomplete.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DraggableAutocompleteComponent extends UntilDestroyedMixin implements OnInit, AfterViewInit {\n /** Options to show in the autocompleter */\n @Input() options:DraggableOption[];\n\n /** Should we focus the autocompleter ? */\n @Input() autofocus:boolean = true;\n\n /** Order list of selected items */\n @Input('selected') _selected:DraggableOption[] = [];\n\n /** Output when autocompleter changes values or items removed */\n @Output() onChange = new EventEmitter();\n\n /** List of items still available for selection */\n availableOptions:DraggableOption[] = [];\n\n private autoscroll:any;\n private columnsGroup:Group;\n\n @ViewChild('ngSelectComponent') public ngSelectComponent:NgSelectComponent;\n\n text = {\n placeholder: this.I18n.t('js.label_add_columns')\n };\n\n constructor(readonly I18n:I18nService,\n readonly dragula:DragulaService) {\n super();\n }\n\n ngOnInit():void {\n this.updateAvailableOptions();\n\n // Setup groups\n this.columnsGroup = this.dragula.createGroup('columns', {});\n\n // Set cursor when dragging\n this.dragula.drag('columns')\n .pipe(this.untilDestroyed())\n .subscribe(() => DomHelpers.setBodyCursor('move', 'important'));\n\n // Reset cursor when cancel or dropped\n merge(\n this.dragula.drop(\"columns\"),\n this.dragula.cancel(\"columns\")\n )\n .pipe(this.untilDestroyed())\n .subscribe(() => DomHelpers.setBodyCursor('auto'));\n\n // Setup autoscroll\n const that = this;\n this.autoscroll = new DomAutoscrollService(\n [\n document.getElementById('content-wrapper')!\n ],\n {\n margin: 25,\n maxSpeed: 10,\n scrollWhenOutside: true,\n autoScroll: function (this:any) {\n return this.down && that.columnsGroup.drake.dragging;\n }\n });\n }\n\n ngAfterViewInit():void {\n if (this.autofocus) {\n this.ngSelectComponent.focus();\n }\n }\n\n ngOnDestroy():void {\n super.ngOnDestroy();\n\n this.dragula.destroy('columns');\n }\n\n select(item:DraggableOption|undefined) {\n if (!item) {\n return;\n }\n\n this.selected = [...this.selected, item];\n\n // Remove selection\n this.ngSelectComponent.clearModel();\n }\n\n remove(item:DraggableOption) {\n this.selected = this.selected.filter(selected => selected.id !== item.id);\n }\n\n get selected() {\n return this._selected;\n }\n\n set selected(val:DraggableOption[]) {\n this._selected = val;\n this.updateAvailableOptions();\n\n this.onChange.emit(this.selected);\n }\n\n opened() {\n // Force reposition as a workaround for BUG\n // https://github.com/ng-select/ng-select/issues/1259\n setTimeout(() => {\n const component = this.ngSelectComponent as any;\n if (component && component.dropdownPanel) {\n component.dropdownPanel._updatePosition();\n }\n }, 25);\n }\n\n private updateAvailableOptions() {\n this.availableOptions = this.options\n .filter(item => !this.selected.find(selected => selected.id === item.id));\n }\n}\n","
    \n \n \n\n \n \n\n

    \n
    \n\n\n\n","import {Component, Injector, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service';\nimport {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {BannersService} from \"core-app/modules/common/enterprise/banners.service\";\nimport {DraggableOption} from \"core-app/modules/common/draggable-autocomplete/draggable-autocomplete.component\";\n\n@Component({\n templateUrl: './columns-tab.component.html'\n})\nexport class WpTableConfigurationColumnsTab implements TabComponent, OnInit {\n public availableColumnsOptions = this.wpTableColumns.all.map(c => this.column2Like(c));\n\n public availableColumns = this.wpTableColumns.all;\n public availableColumnsMap:{ [id:string]:QueryColumn } = _.keyBy(this.availableColumns, c => c.id);\n public selectedColumns:DraggableOption[] = this.wpTableColumns.getColumns().map(c => this.column2Like(c));\n\n public selectedColumnMap:{ [id:string]:boolean } = {};\n public eeShowBanners:boolean = false;\n public text = {\n\n columnsHelp: this.I18n.t('js.work_packages.table_configuration.columns_help_text'),\n columnsLabel: this.I18n.t('js.label_columns'),\n selectedColumns: this.I18n.t('js.description_selected_columns'),\n multiSelectLabel: this.I18n.t('js.work_packages.label_column_multiselect'),\n\n upsaleRelationColumns: this.I18n.t('js.work_packages.table_configuration.upsale.relation_columns'),\n upsaleCheckOutLink: this.I18n.t('js.work_packages.table_configuration.upsale.check_out_link')\n };\n\n constructor(readonly injector:Injector,\n readonly I18n:I18nService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly ConfigurationService:ConfigurationService,\n readonly bannerService:BannersService) {\n }\n\n public onSave() {\n this.wpTableColumns.setColumnsById(this.selectedColumns.map(c => c.id));\n }\n\n ngOnInit() {\n this.eeShowBanners = this.bannerService.eeShowBanners;\n this.selectedColumns.forEach((c:DraggableOption) => {\n this.selectedColumnMap[c.id] = true;\n });\n }\n\n private column2Like(c:QueryColumn):DraggableOption {\n return { id: c.id, name: c.name };\n }\n\n updateSelected(selected:DraggableOption[]) {\n this.selectedColumns = selected;\n }\n}\n","\n","import {Component, Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {WorkPackageFiltersService} from 'core-components/filters/wp-filters/wp-filters.service';\nimport {WorkPackageViewFiltersService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service';\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {BannersService} from \"core-app/modules/common/enterprise/banners.service\";\n\n@Component({\n templateUrl: './filters-tab.component.html',\n selector: 'wp-table-config-filters-tab'\n})\nexport class WpTableConfigurationFiltersTab implements TabComponent {\n\n public filters:QueryFilterInstanceResource[] = [];\n public eeShowBanners:boolean = false;\n\n public text = {\n columnsLabel: this.I18n.t('js.label_columns'),\n selectedColumns: this.I18n.t('js.description_selected_columns'),\n multiSelectLabel: this.I18n.t('js.work_packages.label_column_multiselect'),\n\n upsaleRelationColumns: this.I18n.t('js.modals.upsale_relation_columns'),\n upsaleRelationColumnsLink: this.I18n.t('js.modals.upsale_relation_columns_link')\n };\n\n constructor(readonly injector:Injector,\n readonly I18n:I18nService,\n readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly wpFiltersService:WorkPackageFiltersService,\n readonly bannerService:BannersService) {\n }\n\n ngOnInit() {\n this.eeShowBanners = this.bannerService.eeShowBanners;\n this.wpTableFilters\n .onReady()\n .then(() => this.filters = this.wpTableFilters.current);\n\n this.wpTableFilters.changes$().subscribe(filters => {\n this.filters = this.wpTableFilters.current;\n });\n }\n\n public onSave() {\n if (this.filters) {\n this.wpTableFilters.replaceIfComplete(this.filters);\n }\n }\n}\n","
    \n
    \n\n

    \n
    \n
    \n \n
    \n
    \n
    \n \n
    \n
    \n {{ text.sorting_mode.warning }}\n
    \n
    \n\n \n
    \n
    \n \n \n
    \n
    \n \n \n\n \n \n\n \n \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n","import {Component, Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {\n QUERY_SORT_BY_ASC,\n QUERY_SORT_BY_DESC,\n QuerySortByResource\n} from 'core-app/modules/hal/resources/query-sort-by-resource';\nimport {WorkPackageViewSortByService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service';\nimport {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\n\nexport class SortModalObject {\n constructor(public column:SortColumn,\n public direction:string) {\n }\n}\n\nexport interface SortColumn {\n name:string;\n href:string | null;\n}\n\nexport type SortingMode = 'automatic'|'manual';\n\n@Component({\n templateUrl: './sort-by-tab.component.html'\n})\nexport class WpTableConfigurationSortByTab implements TabComponent {\n\n public text = {\n title: this.I18n.t('js.label_sort_by'),\n placeholder: this.I18n.t('js.placeholders.default'),\n sort_criteria_1: this.I18n.t('js.filter.sorting.criteria.one'),\n sort_criteria_2: this.I18n.t('js.filter.sorting.criteria.two'),\n sort_criteria_3: this.I18n.t('js.filter.sorting.criteria.three'),\n sorting_mode: {\n description: this.I18n.t('js.work_packages.table_configuration.sorting_mode.description'),\n automatic: this.I18n.t('js.work_packages.table_configuration.sorting_mode.automatic'),\n manually: this.I18n.t('js.work_packages.table_configuration.sorting_mode.manually'),\n warning: this.I18n.t('js.work_packages.table_configuration.sorting_mode.warning'),\n },\n };\n\n readonly availableDirections = [\n {$href: QUERY_SORT_BY_ASC, name: this.I18n.t('js.label_ascending')},\n {$href: QUERY_SORT_BY_DESC, name: this.I18n.t('js.label_descending')}\n ];\n\n public availableColumns:SortColumn[] = [];\n public allColumns:SortColumn[] = [];\n public sortationObjects:SortModalObject[] = [];\n public emptyColumn:SortColumn = {name: this.text.placeholder, href: null};\n\n public sortingMode:SortingMode = 'automatic';\n public manualSortColumn:SortColumn;\n\n constructor(readonly injector:Injector,\n readonly I18n:I18nService,\n readonly wpTableSortBy:WorkPackageViewSortByService) {\n\n }\n\n public onSave() {\n let sortElements;\n if (this.sortingMode === 'automatic') {\n sortElements = this.sortationObjects.filter(object => object.column !== null);\n } else {\n sortElements = [ new SortModalObject(this.manualSortColumn, QUERY_SORT_BY_ASC) ];\n }\n\n sortElements = sortElements.map(object => this.getMatchingSort(object.column.href!, object.direction));\n this.wpTableSortBy.update(_.compact(sortElements));\n }\n\n ngOnInit() {\n this.wpTableSortBy\n .onReadyWithAvailable()\n .subscribe(() => {\n let allColumns:SortColumn[] = this.wpTableSortBy.available.filter(\n (sort:QuerySortByResource) => {\n return !sort.column.$href!.endsWith('/parent');\n }\n ).map(\n (sort:QuerySortByResource) => {\n return {name: sort.column.name, href: sort.column.$href};\n }\n );\n\n // For whatever reason, even though the UI doesnt implement it,\n // QuerySortByResources are doubled for each column (one for asc/desc direction)\n this.allColumns = _.uniqBy(allColumns, 'href');\n\n this.getManualSortingOption();\n\n _.each(this.wpTableSortBy.current, sort => {\n if (!sort.column.$href!.endsWith('/parent')) {\n this.sortationObjects.push(\n new SortModalObject({name: sort.column.name, href: sort.column.$href},\n sort.direction.$href!)\n );\n if (sort.column.href === this.manualSortColumn.href) {\n this.updateSortingMode('manual');\n }\n }\n });\n\n this.updateUsedColumns();\n this.fillUpSortElements();\n });\n }\n\n public updateSelection(sort:SortModalObject, selected:string | null) {\n sort.column = _.find(this.allColumns, (column) => column.href === selected) || this.emptyColumn;\n this.updateUsedColumns();\n }\n\n public updateUsedColumns() {\n let usedColumns = this.sortationObjects\n .filter(o => o.column !== null)\n .map((object:SortModalObject) => object.column);\n\n this.availableColumns = _.sortBy(_.differenceBy(this.allColumns, usedColumns, 'href'), 'name');\n }\n\n public updateSortingMode(mode:SortingMode) {\n this.sortingMode = mode;\n }\n\n private getMatchingSort(column:string, direction:string) {\n return _.find(this.wpTableSortBy.available, sort => {\n return sort.column.$href === column && sort.direction.$href === direction;\n });\n }\n\n private fillUpSortElements() {\n while (this.sortationObjects.length < 3) {\n this.sortationObjects.push(new SortModalObject(this.emptyColumn, QUERY_SORT_BY_ASC));\n }\n }\n\n private getManualSortingOption() {\n this.manualSortColumn = this.allColumns.find((e) => e.href!.endsWith('/manualSorting'))!;\n this.allColumns.splice(this.allColumns.indexOf(this.manualSortColumn), 1);\n }\n}\n","
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n

    \n
    \n \n
    \n \n \n

    \n\n
    \n
    \n
    \n\n \n \n \n
    \n
    \n
    \n
    \n\n
    \n \n \n

    \n
    \n
    \n \n {{ text.labels[key] }}\n \n
    \n
    \n \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n","import {Component, Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {WorkPackageViewTimelineService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service';\nimport {TimelineLabels, TimelineZoomLevel} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service';\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {zoomLevelOrder} from \"core-components/wp-table/timeline/wp-timeline\";\n\n@Component({\n templateUrl: './timelines-tab.component.html'\n})\nexport class WpTableConfigurationTimelinesTab implements TabComponent {\n\n public timelineVisible:boolean = false;\n public availableAttributes:{ id:string, name:string }[];\n\n public labels:TimelineLabels;\n public availableLabels:string[];\n\n public zoomLevel:TimelineZoomLevel;\n\n // Manualy build available zoom levels with zoom\n // because it is not part of the order.\n public availableZoomLevels:TimelineZoomLevel[] = ['auto', ...zoomLevelOrder];\n\n public text = {\n title: this.I18n.t('js.timelines.gantt_chart'),\n display_timelines: this.I18n.t('js.timelines.button_activate'),\n display_timelines_hint: this.I18n.t('js.work_packages.table_configuration.show_timeline_hint'),\n zoom: {\n level: this.I18n.t('js.tl_toolbar.zooms'),\n description: this.I18n.t('js.timelines.zoom.description'),\n days: this.I18n.t('js.timelines.zoom.days'),\n weeks: this.I18n.t('js.timelines.zoom.weeks'),\n months: this.I18n.t('js.timelines.zoom.months'),\n quarters: this.I18n.t('js.timelines.zoom.quarters'),\n years: this.I18n.t('js.timelines.zoom.years'),\n auto: this.I18n.t('js.timelines.zoom.auto')\n },\n labels: {\n title: this.I18n.t('js.timelines.labels.title'),\n description: this.I18n.t('js.timelines.labels.description'),\n bar: this.I18n.t('js.timelines.labels.bar'),\n none: this.I18n.t('js.timelines.filter.noneSelection'),\n left: this.I18n.t('js.timelines.labels.left'),\n right: this.I18n.t('js.timelines.labels.right'),\n farRight: this.I18n.t('js.timelines.labels.farRight')\n }\n };\n\n constructor(readonly injector:Injector,\n readonly I18n:I18nService,\n readonly wpTableTimeline:WorkPackageViewTimelineService,\n readonly wpTableColumns:WorkPackageViewColumnsService) {\n }\n\n public onSave() {\n this.wpTableTimeline.update({\n ...this.wpTableTimeline.current,\n visible: this.timelineVisible,\n labels: this.labels,\n zoomLevel: this.zoomLevel\n });\n }\n\n public updateLabels(key:keyof TimelineLabels, value:string|null) {\n if (value === '') {\n value = null;\n }\n\n this.labels[key] = value;\n }\n\n ngOnInit() {\n this.timelineVisible = this.wpTableTimeline.isVisible;\n\n // Current zoom level\n this.zoomLevel = this.wpTableTimeline.zoomLevel;\n\n // Current label models\n const labels = this.wpTableTimeline.labels;\n this.labels = _.clone(labels);\n this.availableLabels = Object.keys(this.labels);\n\n // Available labels\n const availableColumns = this.wpTableColumns\n .allPropertyColumns\n .sort((a:QueryColumn, b:QueryColumn) => a.name.localeCompare(b.name));\n\n this.availableAttributes = [{ id: '', name: this.text.labels.none }].concat(availableColumns);\n }\n}\n","
    \n \n \n
    \n

    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n\n
    \n \n\n
    \n
    \n \n \n
    \n
    \n
    \n\n
    \n \n
    \n
    \n
    \n","import {Component, Injector, ViewChild} from '@angular/core';\nimport {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {WorkPackageViewHighlightingService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HighlightingMode} from \"core-components/wp-fast-table/builders/highlighting/highlighting-mode.const\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {States} from \"core-app/components/states.service\";\nimport {BannersService} from \"core-app/modules/common/enterprise/banners.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\n\n@Component({\n templateUrl: './highlighting-tab.component.html'\n})\nexport class WpTableConfigurationHighlightingTab implements TabComponent {\n\n // Display mode\n public highlightingMode:HighlightingMode = 'inline';\n public entireRowMode:boolean = false;\n public lastEntireRowAttribute:HighlightingMode = 'status';\n public eeShowBanners:boolean = false;\n\n public availableInlineHighlightedAttributes:HalResource[] = [];\n public selectedAttributes:any[] = [];\n\n public availableRowHighlightedAttributes:{name:string; value:HighlightingMode}[] = [];\n\n @ViewChild('highlightedAttributesNgSelect') public highlightedAttributesNgSelect:NgSelectComponent;\n @ViewChild('rowHighlightNgSelect') public rowHighlightNgSelect:NgSelectComponent;\n\n public text = {\n title: this.I18n.t('js.work_packages.table_configuration.highlighting'),\n highlighting_mode: {\n description: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.description'),\n none: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.none'),\n inline: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.inline'),\n inline_all_attributes: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.inline_all'),\n status: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.status'),\n type: this.I18n.t('js.work_packages.properties.type'),\n priority: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.priority'),\n entire_row_by: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.entire_row_by'),\n },\n upsaleAttributeHighlighting: this.I18n.t('js.work_packages.table_configuration.upsale.attribute_highlighting'),\n upsaleCheckOutLink: this.I18n.t('js.work_packages.table_configuration.upsale.check_out_link')\n };\n\n constructor(readonly injector:Injector,\n readonly I18n:I18nService,\n readonly states:States,\n readonly querySpace:IsolatedQuerySpace,\n readonly Banners:BannersService,\n readonly wpTableHighlight:WorkPackageViewHighlightingService) {\n }\n\n ngOnInit() {\n this.availableInlineHighlightedAttributes = this.availableHighlightedAttributes;\n this.availableRowHighlightedAttributes = [\n {name: this.text.highlighting_mode.status, value: 'status'},\n {name: this.text.highlighting_mode.priority, value: 'priority'},\n ];\n\n this.setSelectedValues();\n\n this.eeShowBanners = this.Banners.eeShowBanners;\n this.updateMode(this.wpTableHighlight.current.mode);\n\n if (this.eeShowBanners) {\n this.updateMode('none');\n }\n }\n\n public onSave() {\n let mode = this.highlightingMode;\n this.wpTableHighlight.update({ mode: mode, selectedAttributes: this.selectedAttributes });\n }\n\n public updateMode(mode:HighlightingMode | 'entire-row') {\n if (mode === 'entire-row') {\n this.highlightingMode = this.lastEntireRowAttribute;\n } else {\n this.highlightingMode = mode;\n }\n\n if (['status', 'priority'].indexOf(this.highlightingMode) !== -1) {\n this.lastEntireRowAttribute = this.highlightingMode;\n this.entireRowMode = true;\n } else {\n this.entireRowMode = false;\n }\n }\n\n public updateHighlightingAttributes(model:HalResource[]) {\n this.selectedAttributes = model;\n }\n\n public disabledValue(value:boolean):string | null {\n return value ? 'disabled' : null;\n }\n\n public get availableHighlightedAttributes():HalResource[] {\n const schema = this.querySpace.queryForm.value!.schema;\n return schema.highlightedAttributes.allowedValues;\n }\n\n public onOpen(component:any) {\n setTimeout(() => {\n if (component.dropdownPanel) {\n component.dropdownPanel._updatePosition();\n }\n }, 25);\n }\n\n private setSelectedValues() {\n const currentValues = this.wpTableHighlight.current.selectedAttributes;\n\n if (currentValues) {\n this.selectedAttributes = currentValues;\n }\n }\n}\n","import {Injectable} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WpTableConfigurationDisplaySettingsTab} from 'core-components/wp-table/configuration-modal/tabs/display-settings-tab.component';\nimport {TabInterface} from \"core-components/wp-table/configuration-modal/tab-portal-outlet\";\nimport {WpTableConfigurationColumnsTab} from \"core-components/wp-table/configuration-modal/tabs/columns-tab.component\";\nimport {WpTableConfigurationFiltersTab} from \"core-components/wp-table/configuration-modal/tabs/filters-tab.component\";\nimport {WpTableConfigurationSortByTab} from \"core-components/wp-table/configuration-modal/tabs/sort-by-tab.component\";\nimport {WpTableConfigurationTimelinesTab} from \"core-components/wp-table/configuration-modal/tabs/timelines-tab.component\";\nimport {WpTableConfigurationHighlightingTab} from \"core-components/wp-table/configuration-modal/tabs/highlighting-tab.component\";\n\n@Injectable()\nexport class WpTableConfigurationService {\n\n protected _tabs:TabInterface[] = [\n {\n name: 'columns',\n title: this.I18n.t('js.label_columns'),\n componentClass: WpTableConfigurationColumnsTab,\n },\n {\n name: 'filters',\n title: this.I18n.t('js.work_packages.query.filters'),\n componentClass: WpTableConfigurationFiltersTab,\n },\n {\n name: 'sort-by',\n title: this.I18n.t('js.label_sort_by'),\n componentClass: WpTableConfigurationSortByTab,\n },\n {\n name: 'display-settings',\n title: this.I18n.t('js.work_packages.table_configuration.display_settings'),\n componentClass: WpTableConfigurationDisplaySettingsTab,\n },\n {\n name: 'highlighting',\n title: this.I18n.t('js.work_packages.table_configuration.highlighting'),\n componentClass: WpTableConfigurationHighlightingTab,\n },\n {\n name: 'timelines',\n title: this.I18n.t('js.timelines.gantt_chart'),\n componentClass: WpTableConfigurationTimelinesTab\n }\n ];\n\n constructor(readonly I18n:I18nService) {\n }\n\n public get tabs() {\n return this._tabs;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {BehaviorSubject} from 'rxjs';\nimport {auditTime} from 'rxjs/operators';\nimport {Directive, ElementRef, Input, OnInit} from \"@angular/core\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n// with courtesy of http://stackoverflow.com/a/29722694/3206935\n\n@Directive({\n selector: '[focus-within]'\n})\nexport class FocusWithinDirective extends UntilDestroyedMixin implements OnInit {\n @Input() public selector:string;\n\n constructor(readonly elementRef:ElementRef) {\n super();\n }\n\n\n ngOnInit() {\n let element = jQuery(this.elementRef.nativeElement);\n let focusedObservable = new BehaviorSubject(false);\n\n focusedObservable\n .pipe(\n this.untilDestroyed(),\n auditTime(50)\n )\n .subscribe(focused => {\n element.toggleClass('-focus', focused);\n });\n\n\n let focusListener = function () {\n focusedObservable.next(true);\n };\n element[0].addEventListener('focus', focusListener, true);\n\n let blurListener = function () {\n focusedObservable.next(false);\n };\n element[0].addEventListener('blur', blurListener, true);\n\n setTimeout(() => {\n element.addClass('focus-within--trigger');\n element.find(this.selector).addClass('focus-within--depending');\n }, 0);\n }\n}\n","import {Inject, Injectable, Injector, OnDestroy} from \"@angular/core\";\nimport {DOCUMENT} from \"@angular/common\";\nimport {DomAutoscrollService} from \"core-app/modules/common/drag-and-drop/dom-autoscroll.service\";\nimport {DragAndDropHelpers} from \"core-app/modules/common/drag-and-drop/drag-and-drop.helpers\";\n\nexport interface DragMember {\n dragContainer:HTMLElement;\n scrollContainers:HTMLElement[];\n /** Whether this element moves */\n moves:(element:HTMLElement, fromContainer:HTMLElement, handle:HTMLElement, sibling?:HTMLElement|null) => boolean;\n /** Move element in container */\n onMoved:(element:HTMLElement, target:any, source:HTMLElement, sibling:HTMLElement|null) => void;\n /** Add element to this container */\n onAdded:(element:HTMLElement, target:any, source:HTMLElement, sibling:HTMLElement|null) => Promise;\n /** Remove element from this container */\n onRemoved:(element:HTMLElement, target:any, source:HTMLElement, sibling:HTMLElement|null) => void;\n\n /** Move this container accepts elements */\n accepts?:(row:HTMLElement, container:any) => boolean;\n\n /** Callback when the element got cloned */\n onCloned?:(clone:HTMLElement, original:HTMLElement) => void;\n\n /** Callback when the shadow element got inserted into a container */\n onShadowInserted?:(row:HTMLElement) => void;\n\n /** Callback when the shadow element got inserted into a container */\n onCancel?:(element:HTMLElement) => void;\n}\n\n@Injectable()\nexport class DragAndDropService implements OnDestroy {\n\n public drake:dragula.Drake|null = null;\n\n public members:DragMember[] = [];\n\n private autoscroll:any;\n\n private escapeListener = (evt:KeyboardEvent) => {\n if (this.drake && evt.key === 'Escape') {\n this.drake.cancel(true);\n }\n };\n\n constructor(@Inject(DOCUMENT) private document:Document,\n readonly injector:Injector) {\n this.document.documentElement.addEventListener('keydown', this.escapeListener);\n }\n\n ngOnDestroy():void {\n this.document.documentElement.removeEventListener('keydown', this.escapeListener);\n this.autoscroll && this.autoscroll.destroy();\n this.drake && this.drake.destroy();\n }\n\n public remove(container:HTMLElement) {\n if (this.initialized) {\n _.remove(this.drake!.containers, (el) => el === container);\n _.remove(this.members, (el) => el.dragContainer === container);\n }\n }\n\n public member(container:HTMLElement):DragMember|undefined {\n return _.find(this.members, el => el.dragContainer === container);\n }\n\n public get initialized() {\n return this.drake !== null;\n }\n\n public register(member:DragMember) {\n this.members.push(member);\n const scrollContainers = member.scrollContainers;\n\n if (this.autoscroll) {\n this.autoscroll.add(scrollContainers);\n } else {\n this.setupAutoscroll(scrollContainers);\n }\n\n const dragContainer = member.dragContainer;\n if (this.drake === null) {\n this.initializeDrake([dragContainer]);\n } else {\n this.drake.containers.push(dragContainer);\n }\n }\n\n public addScrollContainer(el:Element) {\n if (this.autoscroll) {\n this.autoscroll.add(el);\n } else {\n this.setupAutoscroll([el]);\n }\n this.autoscroll.setOuterScrollContainer(el);\n }\n\n protected setupAutoscroll(containers:Element[]) {\n // Setup autoscroll\n this.autoscroll = new DomAutoscrollService(\n containers,\n {\n margin: 100,\n maxSpeed: 10,\n scrollWhenOutside: true,\n autoScroll: () => this.drake && this.drake.dragging\n });\n }\n\n /**\n * Retrieve a member from the container, if one exists.\n * @param container\n */\n protected getMember(container:Element):DragMember|undefined {\n return this.members.find(member => member.dragContainer === container);\n }\n\n protected initializeDrake(containers:Element[]) {\n this.drake = dragula(containers, {\n moves: (el:any, container:any, handle:any, sibling:any) => {\n const member = this.getMember(container);\n return member ? member.moves(el, container, handle, sibling) : false;\n },\n accepts: (el:any, container:any) => {\n const member = this.getMember(container);\n return (member && member.accepts) ? member.accepts(el, container) : true;\n },\n invalid: () => false,\n direction: 'vertical', // Y axis is considered when determining where an element would be dropped\n copy: false, // elements are moved by default, not copied\n revertOnSpill: true, // spilling will put the element back where it was dragged from, if this is true\n removeOnSpill: false, // spilling will `.remove` the element, if this is true\n mirrorContainer: document.body, // set the element that gets mirror elements appended\n ignoreInputTextSelection: true // allows users to select input text, see details below\n });\n\n this.drake.on('drag', (el:HTMLElement, source:HTMLElement) => {\n el.dataset.sourceIndex = DragAndDropHelpers.findIndex(el).toString();\n });\n\n this.drake.on('over', (el:HTMLElement, container:HTMLElement) => {\n const zone = container.closest('.drop-zone');\n if (zone) {\n zone.classList.add('-dragged-over');\n }\n });\n\n this.drake.on('out', (el:HTMLElement, container:HTMLElement) => {\n const zone = container.closest('.drop-zone');\n if (zone) {\n zone.classList.remove('-dragged-over');\n }\n });\n\n this.drake.on('cloned', (clone:HTMLElement, original:HTMLElement) => {\n const member = this.member(original.parentElement!);\n if (member && member.onCloned) {\n member.onCloned(clone, original);\n }\n });\n\n this.drake.on('drop', async (el:HTMLElement, target:HTMLElement, source:HTMLElement, sibling:HTMLElement) => {\n try {\n await this.handleDrop(el, target, source, sibling);\n } catch (e) {\n console.error(\"Failed to handle drop of %O, %O\", el, e);\n }\n });\n\n this.drake.on('shadow', (shadowElement:HTMLElement, container:HTMLElement) => {\n const member = this.member(container);\n if (member && member.onShadowInserted) {\n member.onShadowInserted(shadowElement);\n }\n });\n\n this.drake.on('cancel', (el:HTMLElement, container:HTMLElement, source:HTMLElement) => {\n const member = this.member(container);\n if (member && member.onCancel) {\n member.onCancel(el);\n }\n });\n }\n\n private async handleDrop(el:HTMLElement, target:HTMLElement, source:HTMLElement, sibling:HTMLElement|null) {\n const to = this.member(target);\n const from = this.member(source);\n\n if (!(to && from)) {\n return;\n }\n\n if (to === from) {\n return to.onMoved(el, target, source, sibling);\n }\n\n const result = await to.onAdded(el, target, source, sibling);\n\n if (result) {\n from.onRemoved(el, target, source, sibling);\n } else {\n // Restore element in from container\n DragAndDropHelpers.reinsert(el, el.dataset.sourceIndex || -1, source);\n }\n }\n}\n","import { NgModule } from '@angular/core';\nimport { DynamicBootstrapComponent } from './component/dynamic-bootstrap/dynamic-bootstrap.component';\n\n@NgModule({\n declarations: [DynamicBootstrapComponent],\n exports: [DynamicBootstrapComponent],\n})\nexport class DynamicBootstrapModule { }\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {FormsModule} from '@angular/forms';\nimport {Injector, NgModule} from '@angular/core';\n\nimport {AuthoringComponent} from 'core-app/modules/common/authoring/authoring.component';\nimport {OpDateTimeComponent} from 'core-app/modules/common/date/op-date-time.component';\nimport {OpIcon} from 'core-app/modules/common/icon/op-icon';\nimport {NotificationComponent} from 'core-app/modules/common/notifications/notification.component';\nimport {NotificationsContainerComponent} from 'core-app/modules/common/notifications/notifications-container.component';\nimport {UploadProgressComponent} from 'core-app/modules/common/notifications/upload-progress.component';\nimport {OpDatePickerComponent} from 'core-app/modules/common/op-date-picker/op-date-picker.component';\nimport {FocusWithinDirective} from 'core-app/modules/common/focus/focus-within.directive';\nimport {OpenprojectAccessibilityModule} from 'core-app/modules/a11y/openproject-a11y.module';\nimport {FocusDirective} from 'core-app/modules/common/focus/focus.directive';\nimport {HighlightColDirective} from 'core-app/modules/common/highlight-col/highlight-col.directive';\nimport {CopyToClipboardDirective} from 'core-app/modules/common/copy-to-clipboard/copy-to-clipboard.directive';\nimport {highlightColBootstrap} from './highlight-col/highlight-col.directive';\nimport {HookService} from '../plugins/hook-service';\nimport {ColorsAutocompleter} from 'core-app/modules/common/colors/colors-autocompleter.component';\nimport {ResizerComponent} from 'core-app/modules/common/resizer/resizer.component';\nimport {TablePaginationComponent} from 'core-components/table-pagination/table-pagination.component';\nimport {SortHeaderDirective} from 'core-components/wp-table/sort-header/sort-header.directive';\nimport {ZenModeButtonComponent} from 'core-components/wp-buttons/zen-mode-toggle-button/zen-mode-toggle-button.component';\nimport {OPContextMenuComponent} from 'core-components/op-context-menu/op-context-menu.component';\nimport {StateService, UIRouterModule} from '@uirouter/angular';\nimport {PortalModule} from '@angular/cdk/portal';\nimport {CommonModule} from '@angular/common';\nimport {CollapsibleSectionComponent} from 'core-app/modules/common/collapsible-section/collapsible-section.component';\nimport {NoResultsComponent} from 'core-app/modules/common/no-results/no-results.component';\nimport {DragDropModule} from '@angular/cdk/drag-drop';\nimport {UserAutocompleterComponent} from 'app/modules/common/autocomplete/user-autocompleter.component';\nimport {ScrollableTabsComponent} from 'core-app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component';\nimport {ContentTabsComponent} from 'core-app/modules/common/tabs/content-tabs/content-tabs.component';\nimport {EditableToolbarTitleComponent} from 'core-app/modules/common/editable-toolbar-title/editable-toolbar-title.component';\nimport {UserAvatarComponent} from 'core-components/user/user-avatar/user-avatar.component';\nimport {EnterpriseBannerComponent} from 'core-components/enterprise-banner/enterprise-banner.component';\nimport {EnterpriseBannerBootstrapComponent} from 'core-components/enterprise-banner/enterprise-banner-bootstrap.component';\nimport {DynamicModule} from 'ng-dynamic-component';\nimport {VersionAutocompleterComponent} from 'core-app/modules/common/autocomplete/version-autocompleter.component';\nimport {CreateAutocompleterComponent} from 'core-app/modules/common/autocomplete/create-autocompleter.component';\nimport {HomescreenNewFeaturesBlockComponent} from 'core-components/homescreen/blocks/new-features.component';\nimport {BoardVideoTeaserModalComponent} from 'core-app/modules/boards/board/board-video-teaser-modal/board-video-teaser-modal.component';\nimport {PersistentToggleComponent} from 'core-app/modules/common/persistent-toggle/persistent-toggle.component';\nimport {AutocompleteSelectDecorationComponent} from 'core-app/modules/common/autocomplete/autocomplete-select-decoration.component';\nimport {AddSectionDropdownComponent} from 'core-app/modules/common/hide-section/add-section-dropdown/add-section-dropdown.component';\nimport {HideSectionLinkComponent} from 'core-app/modules/common/hide-section/hide-section-link/hide-section-link.component';\nimport {RemoteFieldUpdaterComponent} from 'core-app/modules/common/remote-field-updater/remote-field-updater.component';\nimport {AutofocusDirective} from 'core-app/modules/common/autofocus/autofocus.directive';\nimport {ShowSectionDropdownComponent} from 'core-app/modules/common/hide-section/show-section-dropdown.component';\nimport {IconTriggeredContextMenuComponent} from 'core-components/op-context-menu/icon-triggered-context-menu/icon-triggered-context-menu.component';\nimport {NgSelectModule} from '@ng-select/ng-select';\nimport {NgOptionHighlightModule} from '@ng-select/ng-option-highlight';\nimport {CurrentProjectService} from 'core-components/projects/current-project.service';\nimport {CurrentUserService} from 'core-components/user/current-user.service';\nimport {WorkPackageAutocompleterComponent} from 'core-app/modules/common/autocomplete/wp-autocompleter.component';\nimport {TimeEntryWorkPackageAutocompleterComponent} from 'core-app/modules/common/autocomplete/te-work-package-autocompleter.component';\nimport {DraggableAutocompleteComponent} from 'core-app/modules/common/draggable-autocomplete/draggable-autocomplete.component';\nimport {DragulaModule} from 'ng2-dragula';\nimport {SlideToggleComponent} from 'core-app/modules/common/slide-toggle/slide-toggle.component';\nimport {DynamicBootstrapModule} from 'core-app/modules/common/dynamic-bootstrap/dynamic-bootstrap.module';\nimport {PrincipalRendererService} from \"core-app/modules/common/principal/principal-renderer.service\";\nimport {OpPrincipalComponent} from \"core-app/modules/common/principal/op-principal.component\";\n\nexport function bootstrapModule(injector:Injector) {\n // Ensure error reporter is run\n const currentProject = injector.get(CurrentProjectService);\n const currentUser = injector.get(CurrentUserService);\n const routerState = injector.get(StateService);\n\n window.ErrorReporter.addContext((scope) => {\n if (currentUser.isLoggedIn) {\n scope.setUser({ name: currentUser.name, id: currentUser.userId, email: currentUser.mail });\n }\n\n if (currentProject.inProjectContext) {\n scope.setTag('project', currentProject.identifier!);\n }\n\n scope.setExtra('router state', routerState.current.name);\n });\n\n const hookService = injector.get(HookService);\n hookService.register('openProjectAngularBootstrap', () => {\n return [\n highlightColBootstrap\n ];\n });\n}\n\n@NgModule({\n imports: [\n // UI router components (NOT routes!)\n UIRouterModule,\n // Angular browser + common module\n CommonModule,\n // Angular Forms\n FormsModule,\n // Angular CDK\n PortalModule,\n DragDropModule,\n DragulaModule,\n // Our own A11y module\n OpenprojectAccessibilityModule,\n NgSelectModule,\n NgOptionHighlightModule,\n\n DynamicModule.withComponents([\n VersionAutocompleterComponent,\n WorkPackageAutocompleterComponent,\n TimeEntryWorkPackageAutocompleterComponent,\n CreateAutocompleterComponent]),\n\n DynamicBootstrapModule,\n ],\n exports: [\n // Re-export all commonly used\n // modules to DRY\n UIRouterModule,\n CommonModule,\n FormsModule,\n PortalModule,\n DragDropModule,\n OpenprojectAccessibilityModule,\n NgSelectModule,\n NgOptionHighlightModule,\n DynamicBootstrapModule,\n\n OpDatePickerComponent,\n OpDateTimeComponent,\n OpIcon,\n AutofocusDirective,\n\n FocusWithinDirective,\n FocusDirective,\n AuthoringComponent,\n\n // Notifications\n NotificationsContainerComponent,\n NotificationComponent,\n UploadProgressComponent,\n OpDateTimeComponent,\n\n // Table highlight\n HighlightColDirective,\n\n ResizerComponent,\n\n TablePaginationComponent,\n SortHeaderDirective,\n\n ZenModeButtonComponent,\n\n OPContextMenuComponent,\n IconTriggeredContextMenuComponent,\n\n NoResultsComponent,\n\n UserAutocompleterComponent,\n\n ScrollableTabsComponent,\n\n EditableToolbarTitleComponent,\n\n // User Avatar\n UserAvatarComponent,\n\n // Enterprise Edition\n EnterpriseBannerComponent,\n\n DynamicModule,\n\n WorkPackageAutocompleterComponent,\n\n DraggableAutocompleteComponent,\n\n // filter\n\n SlideToggleComponent,\n OpPrincipalComponent,\n ],\n declarations: [\n OpDatePickerComponent,\n OpDateTimeComponent,\n OpIcon,\n AutofocusDirective,\n\n FocusWithinDirective,\n FocusDirective,\n AuthoringComponent,\n\n // Notifications\n NotificationsContainerComponent,\n NotificationComponent,\n UploadProgressComponent,\n OpDateTimeComponent,\n\n OPContextMenuComponent,\n IconTriggeredContextMenuComponent,\n\n // Table highlight\n HighlightColDirective,\n\n // Add functionality to rails rendered templates\n CopyToClipboardDirective,\n CollapsibleSectionComponent,\n\n CopyToClipboardDirective,\n ColorsAutocompleter,\n\n ResizerComponent,\n\n TablePaginationComponent,\n SortHeaderDirective,\n\n // Zen mode button\n ZenModeButtonComponent,\n\n NoResultsComponent,\n\n UserAutocompleterComponent,\n\n ScrollableTabsComponent,\n ContentTabsComponent,\n\n EditableToolbarTitleComponent,\n\n // User Avatar\n UserAvatarComponent,\n OpPrincipalComponent,\n\n PersistentToggleComponent,\n AutocompleteSelectDecorationComponent,\n HideSectionLinkComponent,\n ShowSectionDropdownComponent,\n AddSectionDropdownComponent,\n RemoteFieldUpdaterComponent,\n\n // Enterprise Edition\n EnterpriseBannerComponent,\n EnterpriseBannerBootstrapComponent,\n\n // Autocompleter\n CreateAutocompleterComponent,\n VersionAutocompleterComponent,\n WorkPackageAutocompleterComponent,\n TimeEntryWorkPackageAutocompleterComponent,\n DraggableAutocompleteComponent,\n\n HomescreenNewFeaturesBlockComponent,\n BoardVideoTeaserModalComponent,\n\n //filter\n SlideToggleComponent,\n ]\n})\nexport class OpenprojectCommonModule {\n constructor(injector:Injector) {\n bootstrapModule(injector);\n\n\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, Input} from \"@angular/core\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {UserAvatarRendererService} from \"core-components/user/user-avatar/user-avatar-renderer.service\";\n\nexport const userAvatarSelector = 'user-avatar';\n\n@Component({\n selector: userAvatarSelector,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: ''\n})\nexport class UserAvatarComponent implements AfterViewInit {\n /** If coming from angular, pass a user resource if available */\n @Input() public user?:UserResource;\n\n constructor(protected elementRef:ElementRef,\n protected avatarRenderer:UserAvatarRendererService,\n protected pathHelper:PathHelperService) {\n }\n\n public ngAfterViewInit() {\n const element = this.elementRef.nativeElement;\n let user = this.user || { name: element.dataset.userName!, id: element.dataset.userId };\n this.avatarRenderer.render(element, user, false, element.dataset.classList);\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\n\nexport class Apiv3GridForm extends APIv3FormResource {\n\n /**\n * We need to override the grid widget extraction\n * to pass the correct payload to the API.\n *\n * @param resource\n * @param schema\n */\n public static extractPayload(resource:HalResource|Object, schema:SchemaResource|null = null):Object {\n if (resource instanceof HalResource && schema) {\n let grid = resource as HalResource;\n let payload = HalPayloadHelper.extractPayloadFromSchema(grid, schema);\n\n // The widget only states the type of the widget resource but does not explain\n // the widget itself. We therefore have to do that by hand.\n if (payload.widgets) {\n payload.widgets = grid.widgets.map((widget:GridWidgetResource) => {\n return {\n id: widget.id,\n startRow: widget.startRow,\n endRow: widget.endRow,\n startColumn: widget.startColumn,\n endColumn: widget.endColumn,\n identifier: widget.identifier,\n options: widget.options\n };\n });\n }\n\n return payload;\n }\n\n return resource || {};\n }\n\n /**\n * Extract payload for the form from the request and optional schema.\n *\n * @param request\n * @param schema\n */\n public extractPayload(request:HalResource|Object, schema:SchemaResource|null = null) {\n return Apiv3GridForm.extractPayload(request, schema);\n }\n\n}\n","import {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {multiInput, MultiInputState, StatesGroup} from 'reactivestates';\nimport {Injectable} from \"@angular/core\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {Observable} from \"rxjs\";\nimport {map, take, tap} from \"rxjs/operators\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\n\nexport type RelationsStateValue = { [relationId:string]:RelationResource };\n\nexport class RelationStateGroup extends StatesGroup {\n name = 'WP-Relations';\n\n relations:MultiInputState = multiInput();\n\n constructor() {\n super();\n this.initializeMembers();\n }\n}\n\n@Injectable()\nexport class WorkPackageRelationsService extends StateCacheService {\n\n constructor(private PathHelper:PathHelperService,\n private apiV3Service:APIV3Service,\n private halResource:HalResourceService) {\n super(new RelationStateGroup().relations);\n }\n\n /**\n * Require the value to be loaded either when forced or the value is stale\n * according to the cache interval specified for this service.\n *\n * Returns a single promise to one loaded value\n *\n * @param id The state to require\n * @param force Load the value anyway.\n */\n public require(id:string, force:boolean = false):Promise {\n return this\n .requireAndStream(id, force)\n .pipe(\n take(1)\n )\n .toPromise();\n }\n\n /**\n * Require the value to be loaded either when forced or the value is stale\n * according to the cache interval specified for this service.\n *\n * Returns an observable to the values stream of the state.\n *\n * @param id The state to require\n * @param force Load the value anyway.\n */\n public requireAndStream(id:string, force:boolean = false):Observable {\n // Refresh when stale or being forced\n if (this.stale(id) || force) {\n this.clearAndLoad(\n id,\n this.load(id)\n );\n }\n\n return this.state(id).values$();\n }\n\n /**\n * Load a set of work package ids into the states, regardless of them being loaded\n * @param workPackageIds\n */\n protected load(id:string):Observable {\n return this\n .apiV3Service\n .work_packages\n .id(id)\n .relations\n .get()\n .pipe(\n map(collection => this.relationsStateValue(id, collection.elements))\n );\n }\n\n public requireAll(ids:string[]):Promise {\n return new Promise((resolve, reject) => {\n this\n .apiV3Service\n .relations\n .loadInvolved(ids)\n .toPromise()\n .then((elements:RelationResource[]) => {\n this.clearSome(...ids);\n this.accumulateRelationsFromInvolved(ids, elements);\n resolve();\n })\n .catch(reject);\n });\n }\n\n /**\n * Find a given relation by from, to and relation Type\n */\n public find(from:WorkPackageResource, to:WorkPackageResource, type:string):RelationResource|undefined {\n const relations:RelationsStateValue|undefined = this.state(from.id!).value;\n\n if (!relations) {\n return;\n }\n\n return _.find(relations, (relation:RelationResource) => {\n const denormalized = relation.denormalized(from);\n // Check that\n // 1. the denormalized relation points at \"to\"\n // 2. that the denormalized relation type matches.\n return denormalized.target.id === to.id &&\n denormalized.relationType === type;\n });\n }\n\n /**\n * Remove the given relation.\n */\n public removeRelation(relation:RelationResource) {\n return relation.delete().then(() => {\n this.removeFromStates(relation);\n });\n }\n\n /**\n * Update the given relation type, setting new values for from and to\n */\n public updateRelationType(from:WorkPackageResource, to:WorkPackageResource, relation:RelationResource, type:string) {\n const params = {\n _links: {\n from: { href: from.href },\n to: { href: to.href }\n },\n type: type\n };\n\n return this.updateRelation(relation, params);\n }\n\n public updateRelation(relation:RelationResource, params:{ [key:string]:any }) {\n return relation.updateImmediately(params)\n .then((savedRelation:RelationResource) => {\n this.insertIntoStates(savedRelation);\n return savedRelation;\n });\n }\n\n public addCommonRelation(fromId:string,\n relationType:string,\n relatedWpId:string) {\n const params = {\n _links: {\n from: { href: this.apiV3Service.work_packages.id(fromId).toString() },\n to: { href: this.apiV3Service.work_packages.id(relatedWpId).toString() }\n },\n type: relationType\n };\n\n const path = this.apiV3Service.work_packages.id(fromId).relations.toString();\n return this.halResource\n .post(path, params)\n .toPromise()\n .then((relation:RelationResource) => {\n this.insertIntoStates(relation);\n return relation;\n });\n }\n\n /**\n * Merges a single relation\n * @param relation\n */\n private insertIntoStates(relation:RelationResource) {\n _.values(relation.ids).forEach(wpId => {\n this.multiState.get(wpId).doModify((value:RelationsStateValue) => {\n value[relation.id!] = relation;\n return value;\n }, () => {\n let value:RelationsStateValue = {};\n value[relation.id!] = relation;\n return value;\n });\n });\n }\n\n /**\n * Remove the given relation from the from/to states\n * @param relation\n */\n private removeFromStates(relation:RelationResource) {\n _.values(relation.ids).forEach(wpId => {\n this.multiState.get(wpId).doModify((value:RelationsStateValue) => {\n delete value[relation.id!];\n return value;\n }, () => {\n return {};\n });\n });\n }\n\n /**\n * Given a set of complete relations for this work packge,\n * returns the RelationsStateValue\n *\n * @param wpId The wpId the relations belong to\n * @param relations The relation resource array.\n */\n private relationsStateValue(wpId:string, relations:RelationResource[]):RelationsStateValue {\n return _.keyBy(relations, r => r.id!);\n }\n\n /**\n *\n * We don't know how many values we're getting for a single work package\n * when we use the involved filter.\n *\n * We need to group relevant relations for work packages based on their to/from filter.\n */\n private accumulateRelationsFromInvolved(involved:string[], relations:RelationResource[]) {\n involved.forEach(wpId => {\n const relevant = relations.filter(r => r.isInvolved(wpId));\n const value = this.relationsStateValue(wpId, relevant);\n\n this.updateValue(wpId, value);\n });\n\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {Attachable} from \"core-app/modules/hal/resources/mixins/attachable-mixin\";\n\nexport interface GridResourceLinks {\n update(payload:unknown):Promise;\n updateImmediately(payload:unknown):Promise;\n delete():Promise;\n}\n\nexport class GridBaseResource extends HalResource {\n public widgets:GridWidgetResource[];\n public options:{[key:string]:unknown};\n public rowCount:number;\n public columnCount:number;\n\n public $initialize(source:any) {\n super.$initialize(source);\n\n this.widgets = this\n .widgets\n .map((widget:Object) => {\n let widgetResource = new GridWidgetResource( this.injector,\n widget,\n true,\n this.halInitializer,\n 'GridWidget'\n );\n\n widgetResource.grid = this;\n\n return widgetResource;\n });\n }\n\n readonly attachmentsBackend = true;\n\n public async updateAttachments():Promise {\n return this.attachments.$update().then(() => {\n this.states.forResource(this)!.putValue(this);\n return this.attachments;\n });\n }\n}\n\n\nexport const GridResource = Attachable(GridBaseResource);\n\nexport interface GridResource extends Partial, GridBaseResource {\n}\n","import {Component, EventEmitter, HostListener, Input, OnDestroy, Output} from \"@angular/core\";\nimport {DomHelpers} from \"core-app/helpers/dom/set-window-cursor.helper\";\n\n\nexport interface ResizeDelta {\n origin:any;\n\n // Absolute difference from start\n absolute:{\n x:number;\n y:number;\n };\n\n // Relative difference from last position\n relative:{\n x:number;\n y:number;\n };\n}\n\n@Component({\n selector: 'resizer',\n templateUrl: './resizer.component.html'\n})\nexport class ResizerComponent implements OnDestroy {\n private startX:number;\n private startY:number;\n private oldX:number;\n private oldY:number;\n private newX:number;\n private newY:number;\n private mouseMoveHandler:EventListener;\n private mouseUpHandler:EventListener;\n private resizing = false;\n\n @Output() end:EventEmitter = new EventEmitter();\n @Output() start:EventEmitter = new EventEmitter();\n @Output() move:EventEmitter = new EventEmitter();\n\n @Input() customHandler = false;\n @Input() cursorClass = 'nwse-resize';\n @Input() resizerClass = 'resizer';\n\n ngOnDestroy() {\n this.removeEventListener();\n }\n\n @HostListener('mousedown', ['$event'])\n @HostListener('touchstart', ['$event'])\n public startResize(event:any) {\n event.preventDefault();\n event.stopPropagation();\n\n // Only on left mouse click the resizing is started\n if (event.buttons === 1 || event.which === 1 || event.which === 0) {\n // Getting starting position\n this.oldX = this.startX = event.clientX || event.pageX || event.touches[0].clientX;\n this.oldY = this.startY = event.clientY || event.pageY || event.touches[0].clientY;\n\n this.newX = event.clientX || event.pageX || event.touches[0].clientX;\n this.newY = event.clientY || event.pageY || event.touches[0].clientY;\n\n this.resizing = true;\n\n this.setResizeCursor();\n this.bindEventListener(event);\n\n this.start.emit(this.buildDelta(event));\n }\n }\n\n private onMouseUp(event:any) {\n this.setAutoCursor();\n this.removeEventListener();\n\n this.end.emit(this.buildDelta(event));\n }\n\n private onMouseMove(event:any) {\n event.preventDefault();\n event.stopPropagation();\n\n this.oldX = this.newX;\n this.oldY = this.newY;\n\n this.newX = event.clientX || event.pageX || event.touches[0].clientX;\n this.newY = event.clientY || event.pageY || event.touches[0].clientX;\n\n this.move.emit(this.buildDelta(event));\n }\n\n // Necessary to encapsulate this to be able to remove the event listener later\n private bindEventListener(event:any) {\n this.mouseMoveHandler = this.onMouseMove.bind(this);\n this.mouseUpHandler = this.onMouseUp.bind(this);\n\n window.addEventListener('mousemove', this.mouseMoveHandler);\n window.addEventListener('touchmove', this.mouseMoveHandler);\n window.addEventListener('mouseup', this.mouseUpHandler);\n window.addEventListener('touchend', this.mouseUpHandler);\n }\n\n private removeEventListener() {\n window.removeEventListener('touchmove', this.mouseMoveHandler);\n window.removeEventListener('mousemove', this.mouseMoveHandler);\n window.removeEventListener('mouseup', this.mouseUpHandler);\n window.removeEventListener('touchend', this.mouseUpHandler);\n }\n\n private setResizeCursor() {\n DomHelpers.setBodyCursor(this.cursorClass, 'important');\n }\n\n private setAutoCursor() {\n DomHelpers.setBodyCursor('auto');\n }\n\n private buildDelta(event:any):ResizeDelta {\n return {\n origin: event,\n absolute: {\n x: this.newX - this.startX,\n y: this.newY - this.startY,\n },\n relative: {\n x: this.newX - this.oldX,\n y: this.newY - this.oldX,\n }\n };\n }\n}\n","
    \n
    \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\n\n@Injectable({ providedIn: 'root' })\nexport class CurrentUserService {\n public get isLoggedIn() {\n return this.userMeta.length > 0;\n }\n\n public get userId() {\n return this.userMeta.data('id');\n }\n\n public get href() {\n return `/api/v3/users/${this.userId}`;\n }\n\n public get name() {\n return this.userMeta.data('name');\n }\n\n public get mail() {\n return this.userMeta.data('mail');\n }\n\n public get language() {\n return I18n.locale || 'en';\n }\n\n private get userMeta():JQuery {\n return jQuery('meta[name=current_user]');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\n\nexport interface ISchemaProxy extends SchemaResource {\n ofProperty(property:string):IFieldSchema;\n isAttributeEditable(property:string):boolean;\n isEditable:boolean;\n}\n\nexport class SchemaProxy implements ProxyHandler {\n constructor(protected schema:SchemaResource,\n protected resource:HalResource) {\n }\n\n static create(schema:SchemaResource, resource:HalResource) {\n return new Proxy(\n schema,\n new this(schema, resource)\n ) as ISchemaProxy;\n }\n\n get(schema:SchemaResource, property:PropertyKey, receiver:any):any {\n switch (property) {\n case 'ofProperty': {\n return this.proxyMethod(this.ofProperty);\n }\n case 'isAttributeEditable': {\n return this.proxyMethod(this.isAttributeEditable);\n }\n case 'mappedName': {\n return this.proxyMethod(this.mappedName);\n }\n case 'isEditable': {\n return this.isEditable;\n }\n default: {\n return Reflect.get(schema, property, receiver);\n }\n }\n }\n\n /**\n * Returns the part of the schema relevant for the provided property.\n *\n * We use it to support the virtual attribute 'combinedDate' which is the combination of the three\n * attributes 'startDate', 'dueDate' and 'scheduleManually'. That combination exists only in the front end\n * and not on the native schema. As a property needs to be writable for us to allow the user editing,\n * we need to mark the writability positively if any of the combined properties are writable.\n *\n * @param property the schema part is desired for\n */\n public ofProperty(property:string):IFieldSchema|null {\n let propertySchema = this.schema[this.mappedName(property)];\n\n if (propertySchema) {\n return Object.assign({}, propertySchema, { writable: this.isEditable && propertySchema && propertySchema.writable });\n } else {\n return null;\n }\n }\n\n /**\n * Return whether the resource is editable with the user's permission\n * on the given resource package attribute.\n * In order to be editable, there needs to be an update link on the resource and the schema for\n * the attribute needs to indicate the writability.\n *\n * @param property\n */\n public isAttributeEditable(property:string):boolean {\n let propertySchema = this.ofProperty(property);\n\n return !!propertySchema && propertySchema.writable;\n }\n\n /**\n * Return whether the user in general has permission to edit the resource.\n * This check is required, but not sufficient to check all attribute restrictions.\n *\n * Use +isAttributeEditable(property)+ for this case.\n */\n public get isEditable() {\n return this.resource.isNew || !!this.resource.$links.update;\n }\n\n public mappedName(property:string):string {\n return property;\n }\n\n private proxyMethod(method:Function) {\n const self = this;\n\n // Returning a Proxy here so that the call is bound\n // to the SchemaProxy instance.\n return new Proxy(method, {\n apply: function (_, __, argumentsList) {\n return method.apply(self, [argumentsList[0]]);\n }\n });\n }\n}\n","
    \n
    \n\n \n\n
    \n
    \n \n \n
    \n \n\n \n \n \n\n \n \n \n \n
    \n
    \n
    \n\n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {WorkPackagesActivityService} from 'core-components/wp-single-view-tabs/activity-panel/wp-activity.service';\nimport {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\nimport {CommentService} from \"core-components/wp-activity/comment-service\";\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ElementRef,\n Injector,\n Input,\n OnDestroy,\n OnInit,\n TemplateRef,\n ViewChild\n} from \"@angular/core\";\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\n\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageCommentFieldHandler} from \"core-components/work-packages/work-package-comment/work-package-comment-field-handler\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'work-package-comment',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './work-package-comment.component.html'\n})\nexport class WorkPackageCommentComponent extends WorkPackageCommentFieldHandler implements OnInit, OnDestroy {\n @Input() public workPackage:WorkPackageResource;\n\n @ContentChild(TemplateRef) template:TemplateRef;\n @ViewChild('commentContainer') public commentContainer:ElementRef;\n\n public text = {\n editTitle: this.I18n.t('js.label_add_comment_title'),\n addComment: this.I18n.t('js.label_add_comment'),\n cancelTitle: this.I18n.t('js.label_cancel_comment'),\n placeholder: this.I18n.t('js.label_add_comment_title')\n };\n public fieldLabel:string = this.text.editTitle;\n\n public inFlight = false;\n public canAddComment:boolean;\n public showAbove:boolean;\n\n public htmlId = 'wp-comment-field';\n\n constructor(protected elementRef:ElementRef,\n protected injector:Injector,\n protected commentService:CommentService,\n protected wpLinkedActivities:WorkPackagesActivityService,\n protected ConfigurationService:ConfigurationService,\n protected loadingIndicator:LoadingIndicatorService,\n protected apiV3Service:APIV3Service,\n protected workPackageNotificationService:WorkPackageNotificationService,\n protected NotificationsService:NotificationsService,\n protected cdRef:ChangeDetectorRef,\n protected I18n:I18nService) {\n super(elementRef, injector);\n }\n\n public ngOnInit() {\n super.ngOnInit();\n\n this.canAddComment = !!this.workPackage.addComment;\n this.showAbove = this.ConfigurationService.commentsSortedInDescendingOrder();\n\n this.commentService.quoteEvents\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((quote:string) => {\n this.activate(quote);\n this.commentContainer.nativeElement.scrollIntoView();\n });\n }\n\n // Open the field when its closed and relay drag & drop events to it.\n public startDragOverActivation(event:JQuery.TriggeredEvent) {\n if (this.active) {\n return true;\n }\n\n this.activate();\n\n event.preventDefault();\n return false;\n }\n\n public activate(withText?:string) {\n super.activate(withText);\n\n if (!this.showAbove) {\n this.scrollToBottom();\n }\n\n this.cdRef.detectChanges();\n }\n\n public deactivate(focus:boolean) {\n focus && this.focus();\n this.active = false;\n this.cdRef.detectChanges();\n }\n\n public async handleUserSubmit() {\n if (this.inFlight || !this.rawComment) {\n return Promise.resolve();\n }\n\n this.inFlight = true;\n await this.onSubmit();\n let indicator = this.loadingIndicator.wpDetails;\n return indicator.promise = this.commentService.createComment(this.workPackage, this.commentValue)\n .then(() => {\n this.active = false;\n this.NotificationsService.addSuccess(this.I18n.t('js.work_packages.comment_added'));\n\n this.wpLinkedActivities.require(this.workPackage, true);\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage.id!)\n .refresh();\n\n this.inFlight = false;\n this.deactivate(true);\n })\n .catch((error:any) => {\n this.inFlight = false;\n if (error instanceof ErrorResource) {\n this.workPackageNotificationService.showError(error, this.workPackage);\n } else {\n this.NotificationsService.addError(this.I18n.t('js.work_packages.comment_send_failed'));\n }\n });\n }\n\n scrollToBottom():void {\n const scrollableContainer = jQuery(this.elementRef.nativeElement).scrollParent()[0];\n if (scrollableContainer) {\n setTimeout(() => {\n scrollableContainer.scrollTop = scrollableContainer.scrollHeight;\n }, 400);\n }\n }\n\n setErrors(newErrors:string[]):void {\n // interface\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {BcfPathHelperService} from \"core-app/modules/bim/bcf/helper/bcf-path-helper.service\";\n\nexport class BcfThumbnailDisplayField extends DisplayField {\n @InjectField() bcfPathHelper:BcfPathHelperService;\n\n public render(element:HTMLElement, displayText:string):void {\n const viewpoints = this.resource.bcfViewpoints;\n if (viewpoints && viewpoints.length > 0) {\n const viewpoint = viewpoints[0];\n element.innerHTML = `\n \n `;\n } else {\n element.innerHTML = '';\n }\n }\n}\n","import {Inject, Injectable} from '@angular/core';\nimport {DOCUMENT} from \"@angular/common\";\n\n@Injectable()\nexport class BcfDetectorService {\n constructor (@Inject(DOCUMENT) private documentElement:Document) {\n }\n\n /**\n * Detect whether the BCF module was activated,\n * resulting in a body class.\n */\n public get isBcfActivated() {\n return this.hasBodyClass('bcf-activated');\n }\n\n private hasBodyClass(name:string):boolean {\n return this.documentElement.body.classList.contains(name);\n }\n}\n","import {multiInput} from \"reactivestates\";\nimport {BcfExtensionResource} from \"core-app/modules/bim/bcf/api/extensions/bcf-extension.resource\";\nimport {BcfApiService} from \"core-app/modules/bim/bcf/api/bcf-api.service\";\nimport {Observable} from \"rxjs\";\nimport {map, take} from \"rxjs/operators\";\nimport {Injectable} from \"@angular/core\";\n\nexport type AllowedExtensionKey = keyof BcfExtensionResource;\n\n@Injectable({ providedIn: 'root' })\nexport class BcfAuthorizationService {\n\n // Poor mans caching to avoid repeatedly fetching from the backend.\n protected authorizationMap = multiInput();\n\n constructor(readonly bcfApi:BcfApiService) {\n }\n\n /**\n * Returns an observable boolean whether the given action\n * is authorized in the project by using the project extensions.\n *\n * Ensures the extension is loaded only once per project\n *\n * @param projectIdentifier Project identifier to check permission in\n * @param extension The extension key to check for\n * @param action The desired action\n */\n public authorized$(projectIdentifier:string, extension:AllowedExtensionKey, action:string):Observable {\n const state = this.authorizationMap.get(projectIdentifier);\n\n state.putFromPromiseIfPristine(() =>\n this.bcfApi\n .projects.id(projectIdentifier)\n .extensions\n .get()\n .toPromise()\n );\n\n return state\n .values$()\n .pipe(\n map(\n resource => resource[extension] && resource[extension].includes(action)\n )\n );\n }\n\n /**\n * One-time check to determine current allowed state.\n *\n * @param projectIdentifier Project identifier to check permission in\n * @param extension The extension key to check for\n * @param action The desired action\n */\n public isAllowedTo(projectIdentifier:string, extension:AllowedExtensionKey, action:string):Promise {\n return this\n .authorized$(projectIdentifier, extension, action)\n .pipe(\n take(1)\n )\n .toPromise()\n .catch(() => false);\n }\n}\n\n","\n
    \n
    \n
    \n

    \n
    \n
    \n\n
    0\">\n \n \n
    \n\n \n \n {{text.viewpoint}} \n \n
    \n
    ","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Input,\n OnDestroy,\n OnInit,\n ViewChild\n} from \"@angular/core\";\nimport {StateService} from \"@uirouter/core\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {NgxGalleryComponent, NgxGalleryOptions} from '@kolkov/ngx-gallery';\nimport {HalLink} from \"core-app/modules/hal/hal-link/hal-link\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ViewerBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {WorkPackageCreateService} from \"core-components/wp-new/wp-create.service\";\nimport {BcfAuthorizationService} from \"core-app/modules/bim/bcf/api/bcf-authorization.service\";\nimport {ViewpointsService} from \"core-app/modules/bim/bcf/helper/viewpoints.service\";\nimport {BcfViewpointItem} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint-item.interface\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Component({\n templateUrl: './bcf-wp-attribute-group.component.html',\n styleUrls: ['./bcf-wp-attribute-group.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [ViewpointsService]\n})\nexport class BcfWpAttributeGroupComponent extends UntilDestroyedMixin implements AfterViewInit, OnDestroy, OnInit {\n @Input() workPackage:WorkPackageResource;\n @ViewChild(NgxGalleryComponent) gallery:NgxGalleryComponent;\n\n text = {\n bcf: this.I18n.t('js.bcf.label_bcf'),\n viewpoint: this.I18n.t('js.bcf.viewpoint'),\n add_viewpoint: this.I18n.t('js.bcf.add_viewpoint'),\n show_viewpoint: this.I18n.t('js.bcf.show_viewpoint'),\n delete_viewpoint: this.I18n.t('js.bcf.delete_viewpoint'),\n text_are_you_sure: this.I18n.t('js.text_are_you_sure'),\n notice_successful_create: this.I18n.t('js.notice_successful_create'),\n notice_successful_delete: this.I18n.t('js.notice_successful_delete'),\n };\n\n galleryOptions:NgxGalleryOptions[] = [\n {\n width: '100%',\n height: '400px',\n\n // Show first thumbnail by default\n startIndex: 0,\n\n // Show only one image (\"thumbnail\")\n // and disable the large image slideshow\n image: false,\n thumbnailsColumns: 1,\n // Ensure thumbnails are ALWAYS shown\n thumbnailsAutoHide: false,\n // For BCFs all information shall be visible\n thumbnailSize: 'contain',\n imageAnimation: '',\n previewAnimation: false,\n previewCloseOnEsc: true,\n previewKeyboardNavigation: true,\n imageSize: 'contain',\n imageArrowsAutoHide: true,\n // thumbnailsArrowsAutoHide: true,\n thumbnailsMargin: 5,\n thumbnailMargin: 5,\n previewDownload: true,\n previewCloseOnClick: true,\n arrowPrevIcon: 'icon-arrow-left2',\n arrowNextIcon: 'icon-arrow-right2',\n closeIcon: 'icon-close',\n downloadIcon: 'icon-download',\n thumbnailActions: this.actions(),\n actions: this.actions(),\n },\n // max-width 800\n {\n breakpoint: 800,\n width: '100%',\n height: '400px',\n imagePercent: 80,\n thumbnailsPercent: 20,\n thumbnailsMargin: 5,\n thumbnailMargin: 5\n },\n // max-width 680\n {\n breakpoint: 680,\n height: '200px',\n thumbnailsColumns: 3,\n thumbnailsMargin: 5,\n thumbnailMargin: 5,\n }\n ];\n\n viewpoints:BcfViewpointItem[] = [];\n\n galleryImages:any[] = [];\n\n // Store whether viewing is allowed\n viewAllowed:boolean = false;\n // Store whether viewpoint creation is allowed\n createAllowed:boolean = false;\n // Currently, this is static. Need observable if this changes over time\n viewerVisible = false;\n projectId:string;\n\n constructor(readonly state:StateService,\n readonly bcfAuthorization:BcfAuthorizationService,\n readonly viewerBridge:ViewerBridgeService,\n readonly apiV3Service:APIV3Service,\n readonly wpCreate:WorkPackageCreateService,\n readonly notifications:NotificationsService,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService,\n readonly viewpointsService:ViewpointsService) {\n super();\n }\n\n ngAfterViewInit():void {\n // Observe changes on the work package to update the viewpoints\n this.observeChanges();\n }\n\n ngOnInit() {\n this.viewerBridge.viewerVisible$.subscribe((visible:boolean) => {\n if (visible) {\n this.viewerVisible = true;\n } else {\n this.viewerVisible = false;\n }\n this.cdRef.detectChanges();\n });\n }\n\n protected observeChanges() {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .requireAndStream()\n .pipe(this.untilDestroyed())\n .subscribe(async wp => {\n this.workPackage = wp;\n\n if (!this.projectId) {\n await this.initialize(this.workPackage);\n }\n\n if (wp.bcfViewpoints) {\n this.refreshViewpoints(wp.bcfViewpoints);\n }\n });\n }\n\n async initialize(workPackage:WorkPackageResource) {\n this.projectId = workPackage.project.idFromLink;\n this.viewAllowed = await this.bcfAuthorization.isAllowedTo(this.projectId, 'project_actions', 'viewTopic');\n this.createAllowed = await this.bcfAuthorization.isAllowedTo(this.projectId, 'topic_actions', 'createViewpoint');\n\n this.loadViewpointFromRoute(workPackage);\n this.cdRef.detectChanges();\n }\n\n refreshViewpoints(viewpoints:HalLink[]) {\n this.viewpoints = viewpoints.map((el:HalLink) => ({ href: el.href, snapshotURL: `${el.href}/snapshot` }));\n\n this.setViewpointsOnGallery(this.viewpoints);\n }\n\n protected showViewpoint(workPackage:WorkPackageResource, index:number) {\n this.viewerBridge.showViewpoint(workPackage, index);\n }\n\n protected deleteViewpoint(workPackage:WorkPackageResource, index:number) {\n if (!window.confirm(this.text.text_are_you_sure)) {\n return;\n }\n\n this.viewpointsService\n .deleteViewPoint$(workPackage, index)\n .subscribe(data => {\n this.notifications.addSuccess(this.text.notice_successful_delete);\n this.gallery.preview.close();\n });\n }\n\n public saveViewpoint(workPackage:WorkPackageResource) {\n this.viewpointsService\n .saveViewpoint$(workPackage)\n .subscribe(viewpoint => {\n this.notifications.addSuccess(this.text.notice_successful_create);\n this.showIndex = this.viewpoints.length;\n });\n }\n\n protected loadViewpointFromRoute(workPackage:WorkPackageResource) {\n if (typeof (this.state.params.viewpoint) === 'number') {\n const index = this.state.params.viewpoint;\n this.showViewpoint(workPackage, index);\n this.showIndex = index;\n this.selectViewpointInGallery();\n this.state.go('.', { ...this.state.params, viewpoint: undefined }, { reload: false });\n }\n }\n\n public shouldShowGroup() {\n return this.viewAllowed &&\n (this.viewpoints.length > 0 ||\n (this.createAllowed && this.viewerVisible));\n }\n\n // Gallery functionality\n protected actions() {\n return [\n {\n icon: 'icon-view-model',\n onClick: (evt:any, index:number) => {\n this.showViewpoint(this.workPackage, index);\n this.gallery.preview.close();\n },\n titleText: this.text.show_viewpoint\n },\n {\n icon: 'icon-delete',\n onClick: (evt:any, index:number) => this.deleteViewpoint(this.workPackage, index),\n titleText: this.text.delete_viewpoint\n }\n ];\n }\n\n public galleryPreviewOpen():void {\n jQuery('#top-menu').addClass('-no-z-index');\n }\n\n public galleryPreviewClose():void {\n jQuery('#top-menu').removeClass('-no-z-index');\n }\n\n public selectViewpointInGallery() {\n setTimeout(() => this.gallery?.show(this.showIndex), 250);\n }\n\n public onGalleryChanged(event:{ index:number }) {\n this.showIndex = event.index;\n }\n\n protected set showIndex(value:number) {\n const options = [...this.galleryOptions];\n options[0].startIndex = value;\n this.galleryOptions = options;\n }\n\n protected get showIndex():number {\n return this.galleryOptions[0].startIndex!;\n }\n\n protected setViewpointsOnGallery(viewpoints:BcfViewpointItem[]) {\n const length = viewpoints.length;\n\n this.setThumbnailProperties(length);\n\n if (this.showIndex < 0 || length < 1) {\n this.showIndex = 0;\n } else if (this.showIndex >= length) {\n this.showIndex = length - 1;\n }\n\n this.galleryImages = viewpoints.map(viewpoint => {\n return {\n small: viewpoint.snapshotURL,\n medium: viewpoint.snapshotURL,\n big: viewpoint.snapshotURL\n };\n });\n this.cdRef.detectChanges();\n }\n\n protected setThumbnailProperties(viewpointCount:number) {\n const options = [...this.galleryOptions];\n\n options[0].thumbnailsColumns = viewpointCount < 5 ? viewpointCount : 4;\n options[1].thumbnailsColumns = viewpointCount < 5 ? viewpointCount : 4;\n options[2].thumbnailsColumns = viewpointCount < 4 ? viewpointCount : 3;\n\n options[0].height = `${this.dynamicThumbnailHeight(viewpointCount)}px`;\n options[1].height = `${this.dynamicThumbnailHeight(viewpointCount)}px`;\n options[2].height = `${this.dynamicThumbnailHeight(viewpointCount)}px`;\n\n this.galleryOptions = options;\n }\n\n protected dynamicThumbnailHeight(viewpointCount:number):number {\n return Math.max(Math.round(300 / viewpointCount), 120);\n }\n}\n","import {ChangeDetectionStrategy, Component} from \"@angular/core\";\nimport {BcfWpAttributeGroupComponent} from \"core-app/modules/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component\";\nimport {take, switchMap} from \"rxjs/operators\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {forkJoin} from \"rxjs\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {BcfViewpointItem} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint-item.interface\";\n\n\n@Component({\n templateUrl: './bcf-wp-attribute-group.component.html',\n styleUrls: ['./bcf-wp-attribute-group.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BcfNewWpAttributeGroupComponent extends BcfWpAttributeGroupComponent {\n galleryViewpoints:BcfViewpointItem[] = [];\n\n ngAfterViewInit():void {\n if (this.viewerVisible) {\n super.ngAfterViewInit();\n\n // Save any leftover viewpoints when saving the work package\n if (this.workPackage.isNew) {\n this.observeCreation();\n }\n }\n }\n\n // Because this is a new WorkPackage, in order to save the\n // viewpoints on it we need to:\n // - Wait until the WorkPackage is created\n // - Create the BCFTopic on it to save the viewpoints\n private observeCreation() {\n this.wpCreate\n .onNewWorkPackage()\n .pipe(\n this.untilDestroyed(),\n take(1),\n switchMap((wp:WorkPackageResource) => this.viewpointsService.setBcfTopic$(wp), (wp) => wp),\n switchMap((wp:WorkPackageResource) => {\n this.workPackage = wp;\n const observables = this.galleryViewpoints\n .filter(viewPointItem => !viewPointItem.href && viewPointItem.viewpoint)\n .map(viewPointItem => this.viewpointsService.saveViewpoint$(this.workPackage, viewPointItem.viewpoint)); \n\n return forkJoin(observables);\n })\n )\n .subscribe((viewpoints: BcfViewpointInterface[]) => {\n this.showIndex = this.galleryViewpoints.length - 1;\n });\n }\n\n // Disable show viewpoint functionality\n showViewpoint(workPackage:WorkPackageResource, index:number) {\n return;\n }\n\n deleteViewpoint(workPackage:WorkPackageResource, index:number) {\n this.galleryViewpoints = this.galleryViewpoints.filter((_, i) => i !== index);\n\n this.setViewpointsOnGallery(this.galleryViewpoints);\n \n return;\n }\n\n saveViewpoint() {\n this.viewerBridge\n .getViewpoint$() \n .subscribe(viewpoint => { \n const newViewpoint = {\n snapshotURL: viewpoint.snapshot.snapshot_data,\n viewpoint: viewpoint\n };\n\n this.galleryViewpoints = [\n ...this.galleryViewpoints,\n newViewpoint\n ];\n\n this.setViewpointsOnGallery(this.galleryViewpoints);\n\n // Select the last created viewpoint and show it\n this.showIndex = this.galleryViewpoints.length - 1;\n this.selectViewpointInGallery();\n });\n }\n\n shouldShowGroup() {\n return this.createAllowed && this.viewerVisible;\n }\n protected actions() {\n // Show only delete button\n return super\n .actions()\n .filter(el => el.icon === 'icon-delete');\n }\n}\n","import {Injectable, Injector} from '@angular/core';\nimport {Observable, Subject, BehaviorSubject} from \"rxjs\";\nimport {distinctUntilChanged, filter, first, map, mapTo} from \"rxjs/operators\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {ViewerBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {ViewpointsService} from \"core-app/modules/bim/bcf/helper/viewpoints.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n\ndeclare global {\n interface Window {\n RevitBridge:any;\n }\n}\n\n@Injectable()\nexport class RevitBridgeService extends ViewerBridgeService {\n public shouldShowViewer = false;\n public viewerVisible$ = new BehaviorSubject(false);\n private revitMessageReceivedSource = new Subject<{ messageType:string, trackingId:string, messagePayload:any }>();\n private trackingIdNumber = 0;\n\n @InjectField() viewpointsService:ViewpointsService;\n\n revitMessageReceived$ = this.revitMessageReceivedSource.asObservable();\n\n constructor(readonly injector:Injector) {\n super(injector);\n\n if (window.RevitBridge) {\n this.hookUpRevitListener();\n } else {\n window.addEventListener('revit.plugin.ready', () => {\n this.hookUpRevitListener();\n }, { once: true });\n }\n }\n\n public viewerVisible() {\n return this.viewerVisible$.getValue();\n }\n\n public getViewpoint$():Observable {\n const trackingId = this.newTrackingId();\n\n this.sendMessageToRevit('ViewpointGenerationRequest', trackingId, '');\n\n return this.revitMessageReceived$\n .pipe(\n distinctUntilChanged(),\n filter(message => message.messageType === 'ViewpointData' && message.trackingId === trackingId),\n first()\n )\n .pipe(\n map((message) => {\n let viewpointJson = message.messagePayload;\n\n viewpointJson.snapshot = {\n snapshot_type: 'png',\n snapshot_data: viewpointJson.snapshot,\n };\n\n return viewpointJson;\n })\n );\n }\n\n public showViewpoint(workPackage:WorkPackageResource, index:number) {\n this.viewpointsService\n .getViewPoint$(workPackage, index)\n .subscribe((viewpoint:BcfViewpointInterface) => this.sendMessageToRevit('ShowViewpoint', this.newTrackingId(), JSON.stringify(viewpoint)));\n }\n\n sendMessageToRevit(messageType:string, trackingId:string, messagePayload?:any) {\n if (!this.viewerVisible()) {\n return;\n }\n\n const jsonPayload = messagePayload != null ? JSON.stringify(messagePayload) : null;\n window.RevitBridge.sendMessageToRevit(messageType, trackingId, jsonPayload);\n }\n\n private hookUpRevitListener() {\n window.RevitBridge.sendMessageToOpenProject = (messageString:string) => {\n const message = JSON.parse(messageString);\n const messageType = message.messageType;\n const trackingId = message.trackingId;\n const messagePayload = JSON.parse(message.messagePayload);\n\n this.revitMessageReceivedSource.next({\n messageType: messageType,\n trackingId: trackingId,\n messagePayload: messagePayload\n });\n };\n this.viewerVisible$.next(true);\n }\n\n newTrackingId():string {\n this.trackingIdNumber = this.trackingIdNumber + 1;\n return String(this.trackingIdNumber);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injector, NgModule} from '@angular/core';\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {NgxGalleryModule} from \"@kolkov/ngx-gallery\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {BcfThumbnailDisplayField} from \"core-app/modules/bim/bcf/fields/display/bcf-thumbnail-field.module\";\nimport {HTTP_INTERCEPTORS} from \"@angular/common/http\";\nimport {OpenProjectHeaderInterceptor} from \"core-app/modules/hal/http/openproject-header-interceptor\";\nimport {BcfDetectorService} from \"core-app/modules/bim/bcf/helper/bcf-detector.service\";\nimport {BcfPathHelperService} from \"core-app/modules/bim/bcf/helper/bcf-path-helper.service\";\nimport {ViewpointsService} from \"core-app/modules/bim/bcf/helper/viewpoints.service\";\nimport {BcfImportButtonComponent} from \"core-app/modules/bim/ifc_models/toolbar/import-export-bcf/bcf-import-button.component\";\nimport {BcfExportButtonComponent} from \"core-app/modules/bim/ifc_models/toolbar/import-export-bcf/bcf-export-button.component\";\nimport {IFCViewerService} from \"core-app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service\";\nimport {ViewerBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {BcfWpAttributeGroupComponent} from \"core-app/modules/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component\";\nimport {BcfNewWpAttributeGroupComponent} from \"core-app/modules/bim/bcf/bcf-wp-attribute-group/bcf-new-wp-attribute-group.component\";\nimport {RevitBridgeService} from \"core-app/modules/bim/revit_add_in/revit-bridge.service\";\n\n/**\n * Determines based on the current user agent whether\n * we're running in Revit or not.\n *\n * Depending on that, we use the IFC viewer service for showing/saving viewpoints.\n */\nexport const viewerBridgeServiceFactory = (injector:Injector) => {\n if (window.navigator.userAgent.search('Revit') > -1) {\n return new RevitBridgeService(injector);\n } else {\n return injector.get(IFCViewerService, new IFCViewerService(injector));\n }\n};\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n NgxGalleryModule,\n ],\n providers: [\n { provide: HTTP_INTERCEPTORS, useClass: OpenProjectHeaderInterceptor, multi: true },\n {\n provide: ViewerBridgeService,\n useFactory: viewerBridgeServiceFactory,\n deps: [Injector]\n },\n BcfDetectorService,\n BcfPathHelperService,\n ViewpointsService,\n ],\n declarations: [\n BcfWpAttributeGroupComponent,\n BcfNewWpAttributeGroupComponent,\n BcfImportButtonComponent,\n BcfExportButtonComponent,\n ],\n exports: [\n BcfImportButtonComponent,\n BcfExportButtonComponent,\n ]\n})\nexport class OpenprojectBcfModule {\n static bootstrapCalled = false;\n\n constructor(injector:Injector) {\n OpenprojectBcfModule.bootstrap(injector);\n }\n\n // The static property prevents running the function\n // multiple times. This happens e.g. when the module is included\n // into a plugin's module.\n public static bootstrap(injector:Injector):void {\n if (this.bootstrapCalled) {\n return;\n }\n\n this.bootstrapCalled = true;\n\n const displayFieldService = injector.get(DisplayFieldService);\n displayFieldService\n .addFieldType(BcfThumbnailDisplayField, 'bcfThumbnail', [\n 'BCF Thumbnail'\n ]);\n\n\n const hookService = injector.get(HookService);\n hookService.register('prependedAttributeGroups', (workPackage:WorkPackageResource) => {\n if (!window.OpenProject.isBimEdition) {\n return;\n }\n\n if (workPackage.isNew) {\n return BcfNewWpAttributeGroupComponent;\n } else {\n return BcfWpAttributeGroupComponent;\n }\n });\n }\n}\n\n","import {Injectable} from \"@angular/core\";\n\n/**\n * General components\n */\nexport interface GlobalI18n {\n t(translateId:string, parameters?:any):string;\n\n lookup(translateId:string):boolean|undefined;\n\n toNumber(num:number, options?:ToNumberOptions):string;\n\n toPercentage(num:number, options?:ToPercentageOptions):string;\n\n toCurrency(num:number, options?:ToCurrencyOptions):string;\n\n strftime(date:Date, format:string):string;\n\n toHumanSize(num:number, options?:ToHumanSizeOptions):string;\n\n locale:string;\n firstDayOfWeek:number;\n pluralization:any;\n}\n\ninterface ToNumberOptions {\n precision?:number;\n separator?:string;\n delimiter?:string;\n strip_insignificant_zeros?:boolean;\n}\n\ntype ToPercentageOptions = ToNumberOptions;\n\ninterface ToCurrencyOptions extends ToNumberOptions {\n format?:string;\n unit?:string;\n sign_first?:boolean;\n}\n\ninterface ToHumanSizeOptions extends ToNumberOptions {\n format?:string;\n}\n\n\n@Injectable({ providedIn: 'root' })\nexport class I18nService {\n private _i18n:GlobalI18n = (window as any).I18n;\n\n public get locale():string {\n return this._i18n.locale;\n }\n\n public t(translateId:string, parameters?:{ [key:string]:any }):string {\n return this._i18n.t(translateId, parameters);\n }\n\n public lookup(translateId:string):boolean|undefined {\n return this._i18n.lookup(translateId);\n }\n\n public toNumber = this._i18n.toNumber.bind(this._i18n);\n public toPercentage = this._i18n.toPercentage.bind(this._i18n);\n public toCurrency = this._i18n.toCurrency.bind(this._i18n);\n public strftime = this._i18n.strftime.bind(this._i18n);\n public toHumanSize = this._i18n.toHumanSize.bind(this._i18n);\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nexport class WorkPackageViewHierarchies {\n public isVisible:boolean = false;\n public last:string|null = null;\n public collapsed:{[workPackageId:string]:boolean} = {};\n\n constructor(visible:boolean) {\n this.isVisible = visible;\n }\n}\n","import {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {Injectable} from '@angular/core';\nimport {WorkPackageViewHierarchies} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-hierarchies\";\n\n@Injectable()\nexport class WorkPackageViewHierarchiesService extends WorkPackageQueryStateService {\n\n public valueFromQuery(query:QueryResource):WorkPackageViewHierarchies {\n const value = new WorkPackageViewHierarchies(query.showHierarchies);\n const current = this.current;\n\n // Take over current collapsed values\n // which are not yet saved\n if (current) {\n value.collapsed = current.collapsed;\n }\n\n return value;\n }\n\n public hasChanged(query:QueryResource) {\n return query.showHierarchies !== this.isEnabled;\n }\n\n public applyToQuery(query:QueryResource) {\n query.showHierarchies = this.isEnabled;\n\n // We need to visibly load the ancestors when the mode is activated.\n return this.isEnabled;\n }\n\n /**\n * Return whether the current hierarchy mode is active\n */\n public get isEnabled():boolean {\n return !!(this.current && this.current.isVisible);\n }\n\n public setEnabled(active:boolean = true) {\n const state = { ...this.current, isVisible: active, last: null };\n this.update(state);\n }\n\n /**\n * Toggle the hierarchy state\n */\n public toggleState():boolean {\n this.setEnabled(!this.isEnabled);\n return this.isEnabled;\n }\n\n /**\n * Return whether the given wp ID is collapsed.\n */\n public collapsed(wpId:string):boolean {\n return this.current.collapsed[wpId];\n }\n\n /**\n * Collapse the hierarchy for this work package\n */\n public collapse(wpId:string):void {\n this.setState(wpId, true);\n }\n\n /**\n * Expand the hierarchy for this work package\n */\n public expand(wpId:string):void {\n this.setState(wpId, false);\n }\n\n /**\n * Toggle the hierarchy state\n */\n public toggle(wpId:string):void {\n this.setState(wpId, !this.collapsed(wpId));\n }\n\n /**\n * Set the collapse/expand state of the given work package id.\n */\n private setState(wpId:string, isCollapsed:boolean):void {\n const state = { ...this.current, last: wpId };\n state.collapsed[wpId] = isCollapsed;\n this.update(state);\n }\n\n /**\n * Get current selection state.\n */\n public get current():WorkPackageViewHierarchies {\n const state = this.lastUpdatedState.value;\n\n if (state === undefined) {\n return this.initialState;\n }\n\n if (!state.collapsed) {\n state.collapsed = {};\n }\n\n return state;\n }\n\n private get initialState():WorkPackageViewHierarchies {\n return new WorkPackageViewHierarchies(false);\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\n\n/**\n * The service is intended to store all the updates caused to a query by a user.\n * It is e.g. used to not update the board list when the current user moved a card within a list/query.\n */\n\n\n@Injectable()\nexport class CausedUpdatesService {\n /** contains all the updates to the query caused by modifications of the user */\n private causedUpdates:string[] = [];\n\n public includes(query:QueryResource) {\n return this.causedUpdates.includes(this.cacheValue(query));\n }\n\n public add(query:QueryResource) {\n if (this.causedUpdates.length > 100) {\n this.causedUpdates.splice(0, 90);\n }\n\n this.causedUpdates.push(this.cacheValue(query));\n }\n\n private cacheValue(query:QueryResource) {\n return query.updatedAt + query.$href;\n }\n}\n","import {Component, Input} from \"@angular/core\";\nimport {enterpriseEditionUrl} from \"core-app/globals/constants.const\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n selector: 'enterprise-banner',\n styleUrls: ['./enterprise-banner.component.sass'],\n template: `\n
    \n
    \n

    \n

    \n \n
    \n
    \n `\n})\nexport class EnterpriseBannerComponent {\n @Input() public leftMargin:boolean = false;\n @Input() public textMessage:string;\n @Input() public linkMessage:string;\n @Input() public opReferrer:string;\n\n public text:any = {\n enterpriseFeature: this.I18n.t('js.upsale.ee_only'),\n };\n\n constructor(protected I18n:I18nService) {\n }\n\n public eeLink() {\n if (this.opReferrer) {\n return enterpriseEditionUrl + '&op_referrer=' + this.opReferrer;\n } else {\n return enterpriseEditionUrl;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport interface ButtonControllerText {\n activate:string;\n deactivate:string;\n label:string;\n buttonText:string;\n}\n\nexport abstract class AbstractWorkPackageButtonComponent extends UntilDestroyedMixin {\n public disabled:boolean;\n public buttonId:string;\n public iconClass:string;\n\n public accessKey:number;\n public isActive:boolean = false;\n\n protected text:ButtonControllerText;\n\n constructor(public I18n:I18nService) {\n super();\n\n this.text = {\n activate: this.I18n.t('js.label_activate'),\n deactivate: this.I18n.t('js.label_deactivate'),\n label: this.labelKey ? this.I18n.t(this.labelKey) : '',\n buttonText: this.textKey ? this.I18n.t(this.textKey) : ''\n };\n }\n\n public get label():string {\n return this.text.label;\n }\n\n public get buttonText():string {\n return this.text.buttonText;\n }\n\n public get labelKey():string {\n return '';\n }\n\n public get textKey():string {\n return '';\n }\n\n protected get activationPrefix():string {\n return !this.isActive ? this.text.activate + ' ' : '';\n }\n\n protected get deactivationPrefix():string {\n return this.isActive ? this.text.deactivate + ' ' : '';\n }\n\n protected get prefix():string {\n return this.activationPrefix || this.deactivationPrefix;\n }\n\n public isToggle():boolean {\n return false;\n }\n\n public abstract performAction(event:Event):void;\n}\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n \n \n
    \n\n
    \n \n\n \n\n \n
    \n
    \n
    \n","import {Component, ChangeDetectionStrategy} from \"@angular/core\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport { TimeEntryBaseModal } from '../shared/modal/base.modal';\n\n@Component({\n templateUrl: '../shared/modal/base.modal.html',\n styleUrls: ['../shared/modal/base.modal.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class TimeEntryCreateModal extends TimeEntryBaseModal {\n public createdEntry:TimeEntryResource;\n\n public get deleteAllowed() {\n return false;\n }\n\n public setModifiedEntry($event:{savedResource:HalResource, isInital:boolean}) {\n this.createdEntry = $event.savedResource as TimeEntryResource;\n this.reloadWorkPackageAndClose();\n }\n\n public get saveText() {\n return this.i18n.t('js.label_create');\n }\n}\n","import { Injectable, Injector } from \"@angular/core\";\nimport { OpModalService } from \"app/components/op-modals/op-modal.service\";\nimport { HalResourceService } from \"app/modules/hal/services/hal-resource.service\";\nimport { I18nService } from \"core-app/modules/common/i18n/i18n.service\";\nimport { TimeEntryResource } from 'core-app/modules/hal/resources/time-entry-resource';\nimport { take } from 'rxjs/operators';\nimport { FormResource } from \"core-app/modules/hal/resources/form-resource\";\nimport { ResourceChangeset } from \"core-app/modules/fields/changeset/resource-changeset\";\nimport { HalResourceEditingService } from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport { Moment } from 'moment';\nimport { TimeEntryCreateModal } from \"core-app/modules/time_entries/create/create.modal\";\nimport { WorkPackageResource } from 'core-app/modules/hal/resources/work-package-resource';\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class TimeEntryCreateService {\n\n constructor(readonly opModalService:OpModalService,\n readonly injector:Injector,\n readonly halResource:HalResourceService,\n readonly apiV3Service:APIV3Service,\n readonly schemaCache:SchemaCacheService,\n protected halEditing:HalResourceEditingService,\n readonly i18n:I18nService) {\n }\n\n public create(date:Moment, wp?:WorkPackageResource, showWorkPackageField:boolean = true) {\n return new Promise<{ entry:TimeEntryResource, action:'create' }>((resolve, reject) => {\n this\n .createNewTimeEntry(date, wp)\n .then(changeset => {\n const modal = this.opModalService.show(TimeEntryCreateModal, this.injector, { changeset: changeset, showWorkPackageField: showWorkPackageField });\n\n modal\n .closingEvent\n .pipe(take(1))\n .subscribe(() => {\n if (modal.createdEntry) {\n resolve({ entry: modal.createdEntry, action: 'create' });\n } else {\n reject();\n }\n });\n });\n });\n }\n\n public createNewTimeEntry(date:Moment, wp?:WorkPackageResource) {\n let payload:any = {\n spentOn: date.format('YYYY-MM-DD')\n };\n\n if (wp) {\n payload['_links'] = {\n workPackage: {\n href: wp.href\n }\n };\n }\n\n return this\n .apiV3Service\n .time_entries\n .form\n .post(payload)\n .toPromise()\n .then(form => {\n return this.fromCreateForm(form);\n });\n }\n\n public fromCreateForm(form:FormResource):ResourceChangeset {\n let entry = this.initializeNewResource(form);\n\n return this.halEditing.edit>(entry, form);\n }\n\n private initializeNewResource(form:FormResource) {\n let entry = this.halResource.createHalResourceOfType('TimeEntry', form.payload.$plain());\n\n entry.$links['schema'] = { href: 'new' };\n\n entry['_type'] = 'TimeEntry';\n entry['id'] = 'new';\n entry['hours'] = 'PT1H';\n\n // Set update link to form\n entry['update'] = entry.$links['update'] = form.$links.self;\n // Use POST /work_packages for saving link\n entry['updateImmediately'] = entry.$links['updateImmediately'] = (payload:{}) => {\n return this\n .apiV3Service\n .time_entries\n .post(payload)\n .toPromise();\n };\n\n entry.state.putValue(entry);\n // We need to provide the schema to the cache so that it is available in the html form to e.g. determine\n // the editability.\n // It would be better if the edit field could simply rely on the changeset if it exists.\n this.schemaCache.update(entry, form.schema);\n\n return entry;\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\n\nimport {OpenprojectCommonModule} from 'core-app/modules/common/openproject-common.module';\nimport {AttachmentsComponent} from \"core-app/modules/attachments/attachments.component\";\nimport {AttachmentListComponent} from \"core-app/modules/attachments/attachment-list/attachment-list.component\";\nimport {AttachmentListItemComponent} from \"core-app/modules/attachments/attachment-list/attachment-list-item.component\";\nimport {AttachmentsUploadComponent} from \"core-app/modules/attachments/attachments-upload/attachments-upload.component\";\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n ],\n declarations: [\n AttachmentsComponent,\n AttachmentListComponent,\n AttachmentListItemComponent,\n AttachmentsUploadComponent,\n ],\n exports: [\n AttachmentsUploadComponent,\n AttachmentListComponent,\n AttachmentsComponent,\n ]\n})\nexport class OpenprojectAttachmentsModule {\n}\n\n","import {Injector} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {SingleRowBuilder} from \"core-components/wp-fast-table/builders/rows/single-row-builder\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {States} from \"core-components/states.service\";\nimport {\n collapsedGroupClass,\n hierarchyGroupClass,\n hierarchyRootClass\n} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport const indicatorCollapsedClass = '-hierarchy-collapsed';\nexport const hierarchyCellClassName = 'wp-table--hierarchy-span';\nexport const additionalHierarchyRowClassName = 'wp-table--hierarchy-aditional-row';\nexport const hierarchyIndentation = 20;\nexport const hierarchyBaseIndentation = 25;\n\nexport class SingleHierarchyRowBuilder extends SingleRowBuilder {\n // Injected\n @InjectField() public wpTableHierarchies:WorkPackageViewHierarchiesService;\n @InjectField() public states:States;\n\n // Retain a map of hierarchy elements present in the table\n // with at least a visible child\n public parentsWithVisibleChildren:{ [id:string]:boolean };\n\n public text:{\n leaf:(level:number) => string;\n expanded:(level:number) => string;\n collapsed:(level:number) => string;\n };\n\n constructor(public readonly injector:Injector,\n protected workPackageTable:WorkPackageTable) {\n\n super(injector, workPackageTable);\n\n this.text = {\n leaf: (level:number) => this.I18n.t('js.work_packages.hierarchy.leaf', {level: level}),\n expanded: (level:number) => this.I18n.t('js.work_packages.hierarchy.children_expanded',\n {level: level}),\n collapsed: (level:number) => this.I18n.t('js.work_packages.hierarchy.children_collapsed',\n {level: level}),\n };\n }\n\n /**\n * Refresh a single row after structural changes.\n * Remembers and re-adds the hierarchy indicator if neccessary.\n */\n public refreshRow(workPackage:WorkPackageResource, jRow:JQuery):JQuery {\n // Remove any old hierarchy\n const newRow = super.refreshRow(workPackage, jRow);\n newRow.find(`.wp-table--hierarchy-span`).remove();\n this.appendHierarchyIndicator(workPackage, newRow);\n\n return newRow;\n }\n\n /**\n * Build the columns on the given empty row\n */\n public buildEmpty(workPackage:WorkPackageResource):[HTMLTableRowElement, boolean] {\n let [element, _] = super.buildEmpty(workPackage);\n let [classes, hidden] = this.ancestorRowData(workPackage);\n element.classList.add(...classes);\n\n this.appendHierarchyIndicator(workPackage, jQuery(element));\n return [element, hidden];\n }\n\n /**\n * Returns a set of\n * @param workPackage\n */\n public ancestorRowData(workPackage:WorkPackageResource):[string[], boolean] {\n const state = this.wpTableHierarchies.current;\n const rowClasses:string[] = [];\n let hidden = false;\n\n if (this.parentsWithVisibleChildren[workPackage.id!]) {\n rowClasses.push(hierarchyRootClass(workPackage.id!));\n }\n\n if (_.isArray(workPackage.ancestors)) {\n workPackage.ancestors.forEach((ancestor) => {\n rowClasses.push(hierarchyGroupClass(ancestor.id!));\n\n if (state.collapsed[ancestor.id!]) {\n hidden = true;\n rowClasses.push(collapsedGroupClass(ancestor.id!));\n }\n\n });\n }\n\n return [rowClasses, hidden];\n }\n\n /**\n * Append an additional ancestor row that is not yet loaded\n */\n public buildAncestorRow(ancestor:WorkPackageResource,\n ancestorGroups:string[],\n index:number):[HTMLTableRowElement, boolean] {\n\n const workPackage = this.states.workPackages.get(ancestor.id!).value!;\n const [tr, hidden] = this.buildEmpty(workPackage);\n tr.classList.add(additionalHierarchyRowClassName);\n return [tr, hidden];\n }\n\n /**\n * Append to the row of hierarchy level a hierarchy indicator.\n * @param workPackage\n * @param jRow jQuery row element\n * @param level Indentation level\n */\n private appendHierarchyIndicator(workPackage:WorkPackageResource, jRow:JQuery, level?:number):void {\n const hierarchyLevel = level === undefined || null ? workPackage.ancestors.length : level;\n const hierarchyElement = this.buildHierarchyIndicator(workPackage, jRow, hierarchyLevel);\n\n jRow.find('td.subject')\n .addClass('-with-hierarchy')\n .prepend(hierarchyElement);\n\n // Assure that the content is still visible when the hierarchy indentation is very large\n jRow.find('td.subject').css('minWidth', 125 + (hierarchyIndentation * hierarchyLevel) + 'px');\n jRow.find('td.subject .wp-table--cell-container')\n .css('width', 'calc(100% - ' + hierarchyBaseIndentation + 'px - ' + (hierarchyIndentation * hierarchyLevel) + 'px)');\n }\n\n /**\n * Build the hierarchy indicator at the given indentation level.\n */\n private buildHierarchyIndicator(workPackage:WorkPackageResource, jRow:JQuery|null, level:number):HTMLElement {\n const hierarchyIndicator = document.createElement('span');\n const collapsed = this.wpTableHierarchies.collapsed(workPackage.id!);\n const indicatorWidth = hierarchyBaseIndentation + (hierarchyIndentation * level) + 'px';\n hierarchyIndicator.classList.add(hierarchyCellClassName);\n hierarchyIndicator.style.width = indicatorWidth;\n hierarchyIndicator.dataset.indentation = indicatorWidth;\n\n if (this.parentsWithVisibleChildren[workPackage.id!]) {\n const className = collapsed ? indicatorCollapsedClass : '';\n hierarchyIndicator.innerHTML = `\n \n \n ${this.text.expanded(\n level)}\n ${this.text.collapsed(\n level)}\n \n `;\n } else {\n hierarchyIndicator.innerHTML = `\n \n ${this.text.leaf(level)}\n \n `;\n }\n\n return hierarchyIndicator;\n }\n\n}\n","import { ElementRef, Inject, ChangeDetectorRef, ViewChild, Directive, Injector } from \"@angular/core\";\nimport {OpModalComponent} from \"app/components/op-modals/op-modal.component\";\nimport {OpModalLocalsToken} from \"app/components/op-modals/op-modal.service\";\nimport {OpModalLocalsMap} from \"app/components/op-modals/op-modal.types\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {TimeEntryFormComponent} from \"core-app/modules/time_entries/form/form.component\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport { InjectField } from 'core-app/helpers/angular/inject-field.decorator';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Directive()\nexport abstract class TimeEntryBaseModal extends OpModalComponent {\n @ViewChild('editForm', { static: true }) editForm:TimeEntryFormComponent;\n\n public text:{ [key:string]:string } = {\n title: this.i18n.t('js.time_entry.title'),\n cancel: this.i18n.t('js.button_cancel'),\n close: this.i18n.t('js.button_close'),\n delete: this.i18n.t('js.button_delete'),\n areYouSure: this.i18n.t('js.text_are_you_sure'),\n };\n\n public closeOnEscape = false;\n public closeOnOutsideClick = false;\n public formInFlight:boolean;\n\n @InjectField() apiV3Service:APIV3Service;\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) readonly locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly i18n:I18nService,\n readonly injector:Injector) {\n super(locals, cdRef, elementRef);\n }\n\n public abstract setModifiedEntry($event:{savedResource:HalResource, isInital:boolean}):void;\n\n public get changeset() {\n return this.locals.changeset;\n }\n\n public get entry() {\n return this.changeset.projectedResource;\n }\n\n public get showWorkPackageField() {\n return this.locals.showWorkPackageField !== undefined ? this.locals.showWorkPackageField : true;\n }\n\n public saveEntry() {\n this.formInFlight = true;\n\n this.editForm.save()\n .then(() => this.reloadWorkPackageAndClose())\n .catch(() => {\n this.formInFlight = false;\n this.cdRef.detectChanges();\n });\n }\n\n public get saveText() {\n return this.i18n.t('js.button_save');\n }\n\n public get saveAllowed() {\n return true;\n }\n\n public get deleteAllowed() {\n return true;\n }\n\n protected reloadWorkPackageAndClose() {\n // reload workPackage\n if (this.entry.workPackage) {\n this\n .apiV3Service\n .work_packages\n .id(this.entry.workPackage)\n .refresh();\n }\n this.service.close();\n this.formInFlight = false;\n this.cdRef.detectChanges();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {InputState} from 'reactivestates';\n\nexport class UserResource extends HalResource {\n\n // Properties\n public login:string;\n public firstName:string;\n public lastName:string;\n public email:string;\n public avatar:string;\n public status:string;\n\n // Links\n public lock:HalResource;\n public unlock:HalResource;\n public delete:HalResource;\n public showUser:HalResource;\n\n public static get active_user_statuses() {\n return ['active', 'registered'];\n }\n\n public get state():InputState {\n return this.states.users.get(this.href as string) as any;\n }\n\n public get showUserPath() {\n return this.showUser ? this.showUser.$link.href : null;\n }\n\n public get isActive() {\n return UserResource.active_user_statuses.indexOf(this.status) >= 0;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit} from '@angular/core';\nimport {Transition} from '@uirouter/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageWatchersService} from 'core-components/wp-single-view-tabs/watchers-tab/wp-watchers.service';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './watchers-tab.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-watchers-tab',\n})\nexport class WorkPackageWatchersTabComponent extends UntilDestroyedMixin implements OnInit {\n public workPackageId:string;\n public workPackage:WorkPackageResource;\n public trackByHref = AngularTrackingHelpers.trackByHref;\n\n public error = false;\n public noResults:boolean = false;\n public allowedToView = false;\n public allowedToAdd = false;\n public allowedToRemove = false;\n public availableWatchersPath:string;\n private $element:JQuery;\n\n public watching:any[] = [];\n public text = {\n loading: this.I18n.t('js.watchers.label_loading'),\n loadingError: this.I18n.t('js.watchers.label_error_loading'),\n autocomplete: {\n placeholder: this.I18n.t('js.watchers.typeahead_placeholder')\n }\n };\n\n public constructor(readonly I18n:I18nService,\n readonly elementRef:ElementRef,\n readonly wpWatchersService:WorkPackageWatchersService,\n readonly $transition:Transition,\n readonly notificationService:WorkPackageNotificationService,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly cdRef:ChangeDetectorRef,\n readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service) {\n super();\n }\n\n public ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.workPackageId = this.$transition.params('to').workPackageId;\n this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.loadCurrentWatchers();\n });\n\n this.availableWatchersPath = this.apiV3Service.work_packages.id(this.workPackageId).available_watchers.path;\n }\n\n public loadCurrentWatchers() {\n this.error = false;\n this.allowedToView = !!this.workPackage.watchers;\n this.allowedToAdd = !!this.workPackage.addWatcher;\n this.allowedToRemove = !!this.workPackage.removeWatcher;\n\n if (!this.allowedToView) {\n this.error = true;\n return;\n }\n\n this.wpWatchersService.require(this.workPackage)\n .then((watchers:HalResource[]) => {\n this.watching = watchers;\n this.cdRef.detectChanges();\n })\n .catch((error:any) => {\n this.notificationService.showError(error, this.workPackage);\n });\n }\n\n public set loadingPromise(promise:Promise) {\n this.loadingIndicator.wpDetails.promise = promise;\n }\n\n\n public addWatcher(user:any) {\n this.loadingPromise = this.workPackage.addWatcher.$link.$fetch({ user: { href: user.href } })\n .then(() => {\n // Forcefully reload the resource to update the watch/unwatch links\n // should the current user have been added\n this.wpWatchersService.require(this.workPackage, true);\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .refresh();\n\n this.cdRef.detectChanges();\n })\n .catch((error:any) => this.notificationService.showError(error, this.workPackage));\n }\n\n public removeWatcher(watcher:any) {\n this.workPackage.removeWatcher.$link.$prepare({ user_id: watcher.id })()\n .then(() => {\n _.remove(this.watching, (other:HalResource) => {\n return other.href === watcher.href;\n });\n\n // Forcefully reload the resource to update the watch/unwatch links\n // should the current user have been removed\n this.wpWatchersService.require(this.workPackage, true);\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .refresh();\n this.cdRef.detectChanges();\n })\n .catch((error:any) => this.notificationService.showError(error, this.workPackage));\n }\n}\n","
    \n
    \n
    \n

    \n
    \n
    \n
    \n
    \n\n \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectorRef, Directive, Injector, OnInit, ViewChild} from '@angular/core';\nimport {StateService, Transition} from '@uirouter/core';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {States} from '../states.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {RootResource} from 'core-app/modules/hal/resources/root-resource';\nimport {WorkPackageCreateService} from './wp-create.service';\nimport {takeWhile} from 'rxjs/operators';\nimport {OpTitleService} from 'core-components/html/op-title.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {WorkPackageViewFocusService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service\";\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport * as URI from 'urijs';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {splitViewRoute} from \"core-app/modules/work_packages/routing/split-view-routes.helper\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {HalSource, HalSourceLinks} from \"core-app/modules/hal/resources/hal-resource\";\n\n@Directive()\nexport class WorkPackageCreateComponent extends UntilDestroyedMixin implements OnInit {\n public successState:string = splitViewRoute(this.$state);\n public cancelState:string = this.$state.current.data.baseRoute;\n public newWorkPackage:WorkPackageResource;\n public parentWorkPackage:WorkPackageResource;\n public change:WorkPackageChangeset;\n\n /** Are we in the copying substates ? */\n public copying = false;\n\n public stateParams = this.$transition.params('to');\n public text = {\n button_settings: this.I18n.t('js.button_settings')\n };\n\n @ViewChild(EditFormComponent, { static: false }) protected editForm:EditFormComponent;\n\n /** Explicitly remember destroy state in this abstract base */\n protected destroyed = false;\n\n constructor(public readonly injector:Injector,\n protected readonly $transition:Transition,\n protected readonly $state:StateService,\n protected readonly I18n:I18nService,\n protected readonly titleService:OpTitleService,\n protected readonly notificationService:WorkPackageNotificationService,\n protected readonly states:States,\n protected readonly wpCreate:WorkPackageCreateService,\n protected readonly wpViewFocus:WorkPackageViewFocusService,\n protected readonly wpTableFilters:WorkPackageViewFiltersService,\n protected readonly pathHelper:PathHelperService,\n protected readonly apiV3Service:APIV3Service,\n protected readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n public ngOnInit() {\n this.closeEditFormWhenNewWorkPackageSaved();\n\n this.showForm();\n }\n\n public ngOnDestroy() {\n super.ngOnDestroy();\n }\n\n public switchToFullscreen() {\n this.$state.go('work-packages.new', this.$state.params);\n }\n\n public onSaved(params:{ savedResource:WorkPackageResource, isInitial:boolean }) {\n let { savedResource, isInitial } = params;\n\n this.editForm?.cancel(false);\n\n if (this.successState) {\n this.$state.go(this.successState, { workPackageId: savedResource.id })\n .then(() => {\n this.wpViewFocus.updateFocus(savedResource.id!);\n this.notificationService.showSave(savedResource, isInitial);\n });\n }\n }\n\n protected showForm() {\n this\n .createdWorkPackage()\n .then((changeset:WorkPackageChangeset) => {\n this.change = changeset;\n this.newWorkPackage = changeset.pristineResource;\n this.cdRef.detectChanges();\n\n this.setTitle();\n\n if (this.stateParams['parent_id']) {\n changeset.setValue(\n 'parent',\n { href: this.apiV3Service.work_packages.id(this.stateParams['parent_id']).path }\n );\n }\n\n // Load the parent simply to display the type name :-/\n if (this.stateParams['parent_id']) {\n this\n .apiV3Service\n .work_packages\n .id(this.stateParams['parent_id'])\n .get()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(parent => {\n this.parentWorkPackage = parent;\n this.cdRef.detectChanges();\n });\n }\n })\n .catch((error:any) => {\n if (error.errorIdentifier === 'urn:openproject-org:api:v3:errors:MissingPermission') {\n this.apiV3Service.root.get().subscribe((root:RootResource) => {\n if (!root.user) {\n // Not logged in\n let url = URI(this.pathHelper.loginPath());\n url.search({ back_url: url });\n window.location.href = url.toString();\n }\n });\n this.notificationService.handleRawError(error);\n }\n });\n }\n\n protected setTitle() {\n this.titleService.setFirstPart(this.I18n.t('js.work_packages.create.title'));\n }\n\n public cancelAndBackToList() {\n this.wpCreate.cancelCreation();\n this.$state.go(this.cancelState, this.$state.params);\n }\n\n protected createdWorkPackage() {\n let defaults:HalSource = {\n _links: {}\n };\n\n const type = this.stateParams.type ? parseInt(this.stateParams.type) : undefined;\n const parent = this.stateParams.parent_id ? parseInt(this.stateParams.parent_id) : undefined;\n const project = this.stateParams.projectPath;\n\n if (type) {\n defaults._links['type'] = { href: this.apiV3Service.types.id(type).path };\n }\n if (parent) {\n defaults._links['parent'] = { href: this.apiV3Service.work_packages.id(parent).path };\n }\n\n return this.wpCreate.createOrContinueWorkPackage(project, type, defaults);\n }\n\n private closeEditFormWhenNewWorkPackageSaved() {\n this.wpCreate\n .onNewWorkPackage()\n .pipe(\n takeWhile(() => !this.componentDestroyed)\n )\n .subscribe((wp:WorkPackageResource) => {\n this.onSaved({ savedResource: wp, isInitial: true });\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ConfirmDialogModal} from \"core-components/modals/confirm-dialog/confirm-dialog.modal\";\nimport {Component, ElementRef, OnInit, ViewChild} from \"@angular/core\";\n\n@Component({\n templateUrl: './password-confirmation.modal.html'\n})\nexport class PasswordConfirmationModal extends ConfirmDialogModal implements OnInit {\n\n public password_confirmation:string|null = null;\n\n @ViewChild('passwordConfirmationField', { static: true }) passwordConfirmationField:ElementRef;\n\n public ngOnInit() {\n super.ngOnInit();\n\n this.text.title = I18n.t('js.password_confirmation.title');\n this.text.field_description = I18n.t('js.password_confirmation.field_description');\n this.text.confirm_button = I18n.t('js.button_confirm');\n this.text.password = I18n.t('js.label_password');\n\n this.closeOnEscape = false;\n this.closeOnOutsideClick = false;\n this.showClose = false;\n }\n\n public confirmAndClose(evt:JQuery.TriggeredEvent) {\n if (this.passwordValuePresent()) {\n super.confirmAndClose(evt);\n }\n }\n\n public onOpen(modalElement:JQuery) {\n super.onOpen(modalElement);\n this.passwordConfirmationField.nativeElement.focus();\n }\n\n public passwordValuePresent() {\n return this.password_confirmation !== null && this.password_confirmation.length > 0;\n }\n}\n","
    \n
    \n
    \n

    \n
    \n\n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectorRef, Component, ElementRef, Inject, OnDestroy, OnInit} from \"@angular/core\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n templateUrl: './dynamic-content.modal.html'\n})\nexport class DynamicContentModal extends OpModalComponent implements OnInit, OnDestroy {\n // override superclass\n // Allowing outside clicks to close the modal leads to the user involuntarily closing\n // the modal when removing error messages or clicking on labels e.g. in the registration modal.\n public closeOnOutsideClick:boolean = false;\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n\n super(locals, cdRef, elementRef);\n }\n\n\n ngOnInit() {\n super.ngOnInit();\n\n // Append the dynamic body\n this.$element\n .find('.dynamic-content-modal--wrapper')\n .addClass(this.locals.modalClassName)\n .append(this.locals.modalBody);\n\n // Register click listeners\n jQuery(document.body)\n .on('click.opdynamicmodal',\n '.dynamic-content-modal--close-button',\n (evt:JQuery.TriggeredEvent) => {\n this.closeMe(evt);\n });\n }\n\n ngOnDestroy() {\n jQuery(document.body).off('click.opdynamicmodal');\n super.ngOnDestroy();\n }\n\n}\n","
    \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, SecurityContext} from \"@angular/core\";\nimport {DomSanitizer, SafeHtml} from \"@angular/platform-browser\";\n\n@Injectable({ providedIn: 'root' })\nexport class HTMLSanitizeService {\n public constructor(readonly sanitizer:DomSanitizer) { }\n\n public sanitize(string:string):SafeHtml {\n return this.sanitizer.sanitize(SecurityContext.HTML, string) || '';\n }\n}\n","import {ApplicationRef, Injector, NgZone} from \"@angular/core\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {ConfirmDialogService} from \"core-components/modals/confirm-dialog/confirm-dialog.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ExternalQueryConfigurationService} from \"core-components/wp-table/external-configuration/external-query-configuration.service\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {PasswordConfirmationModal} from \"../../components/modals/request-for-confirmation/password-confirmation.modal\";\nimport {OpModalService} from \"../../components/op-modals/op-modal.service\";\nimport {DynamicContentModal} from \"../../components/modals/modal-wrapper/dynamic-content.modal\";\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {EditFieldService} from \"core-app/modules/fields/edit/edit-field.service\";\nimport {OpenProjectFileUploadService} from \"core-components/api/op-file-upload/op-file-upload.service\";\nimport {EditorMacrosService} from \"core-components/modals/editor/editor-macros.service\";\nimport {HTMLSanitizeService} from \"../common/html-sanitize/html-sanitize.service\";\nimport {PathHelperService} from \"../common/path-helper/path-helper.service\";\nimport {DynamicBootstrapper} from \"core-app/globals/dynamic-bootstrapper\";\nimport {States} from 'core-components/states.service';\nimport {CKEditorPreviewService} from \"core-app/modules/common/ckeditor/ckeditor-preview.service\";\nimport {ExternalRelationQueryConfigurationService} from \"core-components/wp-table/external-configuration/external-relation-query-configuration.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\n\n/**\n * Plugin context bridge for plugins outside the CLI compiler context\n * in order to access services and parts of the core application\n */\nexport class OpenProjectPluginContext {\n\n private _knownHookNames = [\n 'workPackageTableContextMenu',\n 'workPackageSingleContextMenu',\n 'workPackageNewInitialization'\n ];\n\n // Common services referencable by index\n public readonly services = {\n confirmDialog: this.injector.get(ConfirmDialogService),\n externalQueryConfiguration: this.injector.get(ExternalQueryConfigurationService),\n externalRelationQueryConfiguration: this.injector.get(ExternalRelationQueryConfigurationService),\n halResource: this.injector.get(HalResourceService),\n hooks: this.injector.get(HookService),\n i18n: this.injector.get(I18nService),\n notifications: this.injector.get(NotificationsService),\n opModalService: this.injector.get(OpModalService),\n opFileUpload: this.injector.get(OpenProjectFileUploadService),\n displayField: this.injector.get(DisplayFieldService),\n editField: this.injector.get(EditFieldService),\n macros: this.injector.get(EditorMacrosService),\n htmlSanitizeService: this.injector.get(HTMLSanitizeService),\n ckEditorPreview: this.injector.get(CKEditorPreviewService),\n pathHelperService: this.injector.get(PathHelperService),\n states: this.injector.get(States),\n apiV3Service: this.injector.get(APIV3Service),\n configurationService: this.injector.get(ConfigurationService)\n };\n\n // Random collection of classes needed outside of angular\n public readonly classes = {\n modals: {\n passwordConfirmation: PasswordConfirmationModal,\n dynamicContent: DynamicContentModal,\n },\n HalResource: HalResource,\n DisplayField: DisplayField\n };\n\n // Hooks\n public readonly hooks:{ [hook:string]:(callback:Function) => void } = {};\n\n // Angular zone reference\n @InjectField() public readonly zone:NgZone;\n\n // Angular2 global injector reference\n constructor(public readonly injector:Injector) {\n this\n ._knownHookNames\n .forEach((hook:string) => {\n this.hooks[hook] = (callback:Function) => this.services.hooks.register(hook, callback);\n });\n }\n\n /**\n * Run the given callback in the angular zone,\n * resulting in triggered change detection that would otherwise not occur.\n *\n * @param cb\n */\n public runInZone(cb:() => void) {\n this.zone.run(cb);\n }\n\n /**\n * Bootstrap a dynamically embeddable component\n * @param element\n */\n public bootstrap(element:HTMLElement) {\n DynamicBootstrapper.bootstrapOptionalEmbeddable(\n this.injector.get(ApplicationRef),\n element\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++ Ng1FieldControlsWrapper,\n\n\nimport {Injector, NgModule} from \"@angular/core\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {OpenProjectPluginContext} from \"core-app/modules/plugins/plugin-context\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\n\n\n@NgModule({\n providers: [\n HookService,\n ],\n})\nexport class OpenprojectPluginsModule {\n constructor(injector:Injector) {\n debugLog(\"Registering OpenProject plugin context\");\n const pluginContext = new OpenProjectPluginContext(injector);\n window.OpenProject.pluginContext.putValue(pluginContext);\n }\n}\n\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {Attachable} from 'core-app/modules/hal/resources/mixins/attachable-mixin';\n\nexport interface BudgetResourceLinks {\n addAttachment(attachment:HalResource):Promise;\n}\n\nclass BudgetBaseResource extends HalResource {\n public $links:BudgetResourceLinks;\n}\n\nexport const BudgetResource = Attachable(BudgetBaseResource);\n\nexport interface BudgetResource extends BudgetBaseResource, BudgetResourceLinks {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\n\n@Injectable()\nexport class CostSubformAugmentService {\n\n constructor() {\n jQuery('costs-subform').each((i, match) => {\n let el = jQuery(match);\n\n const container = el.find('.subform-container');\n\n const templateEl = el.find('.subform-row-template');\n templateEl.detach();\n const template = templateEl[0].outerHTML;\n let rowIndex = parseInt(el.attr('item-count')!);\n\n el.on('click', '.delete-row-button,.delete-budget-item', (evt:any) => {\n jQuery(evt.target).closest('.subform-row').remove();\n return false;\n });\n\n // Add new row handler\n el.find('.add-row-button,.wp-inline-create--add-link').click((evt:any) => {\n evt.preventDefault();\n let row = jQuery(template.replace(/INDEX/g, rowIndex.toString()));\n row.show();\n row.removeClass('subform-row-template');\n row.find('input.costs-date-picker').prop('required', true);\n row.find('input[id^=\"cost_type_new_rate_attributes\"]').prop('required', true);\n\n container.append(row);\n rowIndex += 1;\n\n container.find('.subform-row:last-child input:first').focus();\n\n return false;\n });\n });\n }\n}\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nexport class PlannedCostsFormAugment {\n\n public obj:JQuery;\n public objId:string;\n public objName:string;\n public placeholder:string;\n\n static listen() {\n jQuery(document).on('click', '.costs--edit-planned-costs-btn', (evt) => {\n const form = jQuery(evt.target as any).closest('cost-unit-subform') as JQuery;\n new PlannedCostsFormAugment(form);\n });\n }\n\n constructor(public $element:JQuery) {\n this.objId = this.$element.attr('obj-id')!;\n this.objName = this.$element.attr('obj-name')!;\n this.obj = jQuery(`#${this.objId}_costs`) as any;\n this.placeholder = this.$element.data('placeholder');\n\n this.makeEditable();\n }\n\n public makeEditable() {\n this.edit_and_focus();\n }\n\n private edit_and_focus() {\n this.edit();\n\n jQuery('#' + this.objId + '_costs_edit').trigger('focus');\n jQuery('#' + this.objId + '_costs_edit').trigger('select');\n }\n\n private getCurrency() {\n return jQuery('#' + this.objId + '_currency').val();\n }\n\n private getValue() {\n return jQuery('#' + this.objId + '_cost_value').val();\n }\n\n private edit() {\n this.obj.hide();\n\n let id = this.obj[0].id;\n let currency = this.getCurrency();\n let value = this.getValue();\n let name = this.objName;\n let placeholder = this.placeholder;\n\n let template = `\n
    \n
    \n
    \n
    \n
    \n \n
    \n
    ${currency}
    \n
    \n
    \n
    \n `;\n\n jQuery(template).insertAfter(this.obj);\n\n let that = this;\n jQuery('#' + id + '_cancel').on('click', function () {\n jQuery('#' + id + '_section').remove();\n that.obj.show();\n return false;\n });\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {HttpClient} from '@angular/common/http';\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\n\n@Injectable()\nexport class CostBudgetSubformAugmentService {\n\n constructor(private halNotification:HalResourceNotificationService,\n private http:HttpClient) {\n }\n\n listen() {\n jQuery('costs-budget-subform').each((i, match) => {\n let el = jQuery(match);\n\n const container = el.find('.budget-item-container');\n const templateEl = el.find('.budget-row-template');\n templateEl.detach();\n const template = templateEl[0].outerHTML;\n let rowIndex = parseInt(el.attr('item-count') as string);\n\n // Refresh row on changes\n el.on('change', '.budget-item-value', (evt) => {\n let row = jQuery(evt.target).closest('.cost_entry');\n this.refreshRow(el, row.attr('id') as string);\n });\n\n el.on('click', '.delete-budget-item', (evt) => {\n evt.preventDefault();\n jQuery(evt.target).closest('.cost_entry').remove();\n return false;\n });\n\n // Add new row handler\n el.find('.budget-add-row').click((evt) => {\n evt.preventDefault();\n let row = jQuery(template.replace(/INDEX/g, rowIndex.toString()));\n row.show();\n row.removeClass('budget-row-template');\n container.append(row);\n rowIndex += 1;\n return false;\n });\n });\n }\n\n /**\n * Refreshes the given row after updating values\n */\n public refreshRow(el:JQuery, row_identifier:string) {\n let row = el.find('#' + row_identifier);\n let request = this.buildRefreshRequest(row, row_identifier);\n\n this.http\n .post(\n el.attr('update-url')!,\n request,\n {\n headers: { 'Accept': 'application/json' },\n withCredentials: true\n })\n .subscribe(\n (data:any) => {\n _.each(data, (val:string, selector:string) => {\n let element = document.getElementById(selector) as HTMLElement|HTMLInputElement|undefined;\n if (element instanceof HTMLInputElement) {\n element.value = val;\n } else if (element) {\n element.textContent = val;\n }\n });\n },\n (error:any) => this.halNotification.handleRawError(error)\n );\n }\n\n /**\n * Returns the params for the update request\n */\n private buildRefreshRequest(row:JQuery, row_identifier:string) {\n let request:any = {\n element_id: row_identifier,\n fixed_date: jQuery('#budget_fixed_date').val()\n };\n\n // Augment common values with specific values for this type\n row.find('.budget-item-value').each((_i:number, el:any) => {\n let field = jQuery(el);\n request[field.data('requestKey')] = field.val() || '0';\n });\n\n return request;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n\nimport {Injector, NgModule} from '@angular/core';\nimport {OpenProjectPluginContext} from 'core-app/modules/plugins/plugin-context';\nimport {BudgetResource} from './hal/resources/budget-resource';\nimport {multiInput} from 'reactivestates';\nimport {CostSubformAugmentService} from \"./augment/cost-subform.augment.service\";\nimport {PlannedCostsFormAugment} from \"core-app/modules/plugins/linked/budgets/augment/planned-costs-form\";\nimport {CostBudgetSubformAugmentService} from \"core-app/modules/plugins/linked/budgets/augment/cost-budget-subform.augment.service\";\n\nexport function initializeCostsPlugin(injector:Injector) {\n window.OpenProject.getPluginContext().then((pluginContext:OpenProjectPluginContext) => {\n pluginContext.services.editField.extendFieldType('select', ['Budget']);\n\n let displayFieldService = pluginContext.services.displayField;\n displayFieldService.extendFieldType('resource', ['Budget']);\n\n let halResourceService = pluginContext.services.halResource;\n halResourceService.registerResource('Budget', {cls: BudgetResource});\n\n let states = pluginContext.services.states;\n states.add('budgets', multiInput());\n\n // Augment previous cost-subforms\n new CostSubformAugmentService();\n PlannedCostsFormAugment.listen();\n\n const budgetSubform = injector.get(CostBudgetSubformAugmentService);\n budgetSubform.listen();\n });\n}\n\n\n@NgModule({\n providers: [\n CostBudgetSubformAugmentService,\n ],\n})\nexport class PluginModule {\n constructor(injector:Injector) {\n initializeCostsPlugin(injector);\n }\n}\n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\ninterface ICostsByType {\n costObjectId:string;\n costType:{\n name:string;\n id:string;\n };\n staticPath:{\n href:string;\n };\n spentUnits:number;\n}\n\nexport class CostsByTypeDisplayField extends DisplayField {\n\n @InjectField() apiV3Service:APIV3Service;\n\n public apply(resource:any, schema:IFieldSchema) {\n super.apply(resource, schema);\n this.loadIfNecessary();\n }\n\n protected loadIfNecessary() {\n if (this.value && this.value.$loaded === false) {\n this.value.$load().then(() => {\n\n if (this.resource.$source._type === 'WorkPackage') {\n this\n .apiV3Service\n .work_packages\n .cache\n .touch(this.resource.id!);\n }\n });\n }\n }\n\n public get title() {\n return '';\n }\n\n public render(element:HTMLElement, displayText:string):void {\n if (this.isEmpty()) {\n element.textContent = this.placeholder;\n return;\n }\n\n this.value.elements.forEach((val:ICostsByType, i:number) => {\n if (this.resource.showCosts) {\n this.renderCostAsLink(val, element, i);\n } else {\n this.renderCostAsText(val, element, i);\n }\n });\n }\n\n public isEmpty():boolean {\n return !this.value ||\n !this.value.elements ||\n this.value.elements.length === 0;\n }\n\n\n /**\n * Render link to reporting\n */\n private renderCostAsLink(val:ICostsByType, element:HTMLElement, i:number) {\n const showCosts = this.resource.showCosts;\n const link = document.createElement('a') as HTMLAnchorElement;\n\n link.href = showCosts.href + '&unit=' + val.costType.id;\n link.setAttribute('target', '_blank');\n link.textContent = val.spentUnits + ' ' + val.costType.name;\n element.appendChild(link);\n\n this.addSeparator(element, i);\n }\n\n /**\n * Render text\n */\n private renderCostAsText(val:ICostsByType, element:HTMLElement, i:number) {\n const span = document.createElement('span');\n span.textContent = val.spentUnits + ' ' + val.costType.name;\n element.appendChild(span);\n this.addSeparator(element, i);\n }\n\n private addSeparator(element:HTMLElement, i:Number) {\n if (i < this.value.elements.length - 1) {\n const sep = document.createElement('span');\n sep.textContent = ', ';\n\n element.appendChild(sep);\n }\n }\n}\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class CurrencyDisplayField extends DisplayField {\n\n public isEmpty():boolean {\n return !this.value ||\n !parseFloat(this.value.match(/\\d+/g)[0]);\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n\nimport {Injector, NgModule} from '@angular/core';\nimport {OpenProjectPluginContext} from 'core-app/modules/plugins/plugin-context';\nimport {CostsByTypeDisplayField} from './wp-display/costs-by-type-display-field.module';\nimport {CurrencyDisplayField} from './wp-display/currency-display-field.module';\n\nexport function initializeCostsPlugin(injector:Injector) {\n window.OpenProject.getPluginContext().then((pluginContext:OpenProjectPluginContext) => {\n let displayFieldService = pluginContext.services.displayField;\n displayFieldService.addFieldType(CostsByTypeDisplayField, 'costs', ['costsByType']);\n displayFieldService.addFieldType(CurrencyDisplayField, 'currency', ['laborCosts', 'materialCosts', 'overallCosts']);\n\n pluginContext.hooks.workPackageSingleContextMenu(function (params:any) {\n return {\n key: 'log_costs',\n icon: 'icon-projects',\n indexBy: function (actions:any) {\n let index = _.findIndex(actions, {key: 'log_time'});\n return index !== -1 ? index + 1 : actions.length;\n },\n resource: 'workPackage',\n link: 'logCosts'\n };\n });\n\n pluginContext.hooks.workPackageTableContextMenu(function (params:any) {\n return {\n key: 'log_costs',\n icon: 'icon-projects',\n link: 'logCosts',\n indexBy: function (actions:any) {\n let index = _.findIndex(actions, {link: 'logTime'});\n return index !== -1 ? index + 1 : actions.length;\n },\n text: I18n.t('js.button_log_costs'),\n };\n });\n });\n}\n\n\n@NgModule({\n providers: [\n ],\n})\nexport class PluginModule {\n constructor(injector:Injector) {\n initializeCostsPlugin(injector);\n }\n}\n\n\n\n","import {UploadBlob} from \"core-components/api/op-file-upload/op-file-upload.service\";\n\nexport namespace ImageHelpers {\n\n /**\n * Resize a file input to the given max dimension, returning the data URL and a blob\n *\n * @param {maxSize} Max width or height\n * @param {File} Input file\n */\n export function resizeFile(maxSize:number, file:File):Promise<[string, UploadBlob]> {\n return new Promise((resolve, _) => {\n const reader = new FileReader();\n reader.onload = (readerEvent: any) => {\n const image = new Image();\n image.onload = () => resolve(resizeImage(maxSize, image));\n image.src = readerEvent.target.result;\n };\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Resize an image to the given max dimension, returning the data URL and a blob\n * Based on https://stackoverflow.com/a/39235724/420614\n *\n * @param {maxSize} Max width or height\n * @param {HTMLImageElement} Input image\n */\n export function resizeImage(maxSize:number, image:HTMLImageElement):[string, UploadBlob] {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d')!;\n\n let width = image.width;\n let height = image.height;\n\n if (width > height) {\n if (width > maxSize) {\n height *= maxSize / width;\n width = maxSize;\n }\n } else {\n if (height > maxSize) {\n width *= maxSize / height;\n height = maxSize;\n }\n }\n\n canvas.width = width;\n canvas.height = height;\n ctx.drawImage(image, 0, 0, width, height);\n let dataUrl = canvas.toDataURL('image/jpeg');\n return [dataUrl, dataURItoBlob(dataUrl)];\n }\n\n function dataURItoBlob(dataURI:string) {\n const bytes = dataURI.split(',')[0].indexOf('base64') >= 0 ?\n atob(dataURI.split(',')[1]) :\n unescape(dataURI.split(',')[1]);\n const mime = dataURI.split(',')[0].split(':')[1].split(';')[0];\n const max = bytes.length;\n const ia = new Uint8Array(max);\n for (var i = 0; i < max; i++) ia[i] = bytes.charCodeAt(i);\n return new Blob([ia], {type: mime});\n }\n}\n","
    \n \n
    \n \n
    \n
    \n \n
    \n \n
    \n
    \n
    \n
    \n \n \n
    \n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {Component, ElementRef, OnInit, ViewChild} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpenProjectFileUploadService} from \"core-components/api/op-file-upload/op-file-upload.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {UploadFile} from \"core-components/api/op-file-upload/op-file-upload.service\";\nimport {ImageHelpers} from \"core-app/helpers/images/resizer\";\n\n@Component({\n selector: 'avatar-upload-form',\n templateUrl: './avatar-upload-form.html'\n})\nexport class AvatarUploadFormComponent implements OnInit {\n // Form targets\n public form:any;\n public target:string;\n public method:string;\n\n // File\n public avatarFile:any;\n public avatarPreviewUrl:any;\n public busy:boolean = false;\n public fileInvalid = false;\n\n @ViewChild('avatarFilePicker', { static: true }) public avatarFilePicker:ElementRef;\n\n // Text\n public text = {\n label_choose_avatar: this.I18n.t('js.avatars.label_choose_avatar'),\n upload_instructions: this.I18n.t('js.avatars.text_upload_instructions'),\n error_too_large: this.I18n.t('js.avatars.error_image_too_large'),\n wrong_file_format: this.I18n.t('js.avatars.wrong_file_format'),\n button_update: this.I18n.t('js.button_update'),\n uploading: this.I18n.t('js.avatars.uploading_avatar'),\n preview: this.I18n.t('js.label_preview')\n };\n\n public constructor(protected I18n:I18nService,\n protected elementRef:ElementRef,\n protected notificationsService:NotificationsService,\n protected opFileUpload:OpenProjectFileUploadService) {\n }\n\n public ngOnInit() {\n const element = this.elementRef.nativeElement;\n this.target = element.getAttribute('target');\n this.method = element.getAttribute('method');\n }\n\n public onFilePickerChanged(_evt:Event) {\n const files:UploadFile[] = Array.from(this.avatarFilePicker.nativeElement.files);\n if (files.length === 0) {\n return;\n }\n\n const file = files[0];\n if (['image/jpeg', 'image/png', 'image/gif'].indexOf(file.type) === -1) {\n this.fileInvalid = true;\n return;\n }\n\n ImageHelpers.resizeFile(128, file).then(([dataURL, blob]) => {\n // Create resized file\n blob.name = file.name;\n this.avatarFile = blob;\n this.avatarPreviewUrl = dataURL;\n });\n }\n\n public uploadAvatar(evt:Event) {\n evt.preventDefault();\n this.busy = true;\n const upload = this.opFileUpload.uploadSingle(this.target, this.avatarFile, this.method, 'text');\n this.notificationsService.addAttachmentUpload(this.text.uploading, [upload]);\n\n upload[1].subscribe(\n (evt:any) => {\n switch (evt.type) {\n case 0: // Sent\n return;\n\n case 4:\n this.avatarFile.progress = 100;\n this.busy = false;\n window.location.reload();\n return;\n\n default:\n // Sent or unknown event\n return;\n }\n },\n (error:any) => {\n this.notificationsService.addError(error.error);\n this.busy = false;\n }\n );\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n\nimport {Injector, NgModule} from '@angular/core';\nimport {CommonModule} from \"@angular/common\";\nimport {AvatarUploadFormComponent} from \"./avatar-upload-form/avatar-upload-form.component\";\nimport {HookService} from \"../../hook-service\";\n\n@NgModule({\n imports: [\n CommonModule,\n ],\n declarations: [\n AvatarUploadFormComponent\n ]\n})\nexport class PluginModule {\n constructor(injector:Injector) {\n const hookService = injector.get(HookService);\n hookService.register('openProjectAngularBootstrap', () => {\n return [\n { selector: 'avatar-upload-form', cls: AvatarUploadFormComponent }\n ];\n });\n }\n}\n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n// This resource exists solely for the purpose of uploading attachments via the\n// WYSIWYIG editor.\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {Attachable} from 'core-app/modules/hal/resources/mixins/attachable-mixin';\n\nexport interface DocumentResourceLinks {\n addAttachment(attachment:HalResource):Promise;\n}\n\nclass DocumentBaseResource extends HalResource {\n public $links:DocumentResourceLinks;\n\n private attachmentsBackend = false;\n}\n\nexport const DocumentResource = Attachable(DocumentBaseResource);\n\nexport interface DocumentResource extends DocumentBaseResource {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {OpenProjectPluginContext} from \"core-app/modules/plugins/plugin-context\";\nimport {DocumentResource} from './hal/resources/document-resource';\nimport {multiInput} from 'reactivestates';\n\nexport function initializeDocumentPlugin() {\n window.OpenProject.getPluginContext()\n .then((pluginContext:OpenProjectPluginContext) => {\n let halResourceService = pluginContext.services.halResource;\n halResourceService.registerResource('Document', {cls: DocumentResource});\n\n let states = pluginContext.services.states;\n states.add('documents', multiInput());\n });\n}\n\n\n@NgModule()\nexport class PluginModule {\n constructor() {\n initializeDocumentPlugin();\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\n// This file is generated by Rails using the rake task\n// rake openproject:plugins:register_frontend\n\nimport {NgModule} from \"@angular/core\";\nimport {PluginModule as Budgets} from './linked/budgets/main';\nimport {PluginModule as Costs} from './linked/costs/main';\nimport {PluginModule as OpenprojectAvatars} from './linked/openproject-avatars/main';\nimport {PluginModule as OpenprojectDocuments} from './linked/openproject-documents/main';\n\n@NgModule({\n imports: [\n Budgets,\n Costs,\n OpenprojectAvatars,\n OpenprojectDocuments,\n ],\n})\nexport class LinkedPluginsModule { }\n\n\n\n","export class GridArea {\n private storedGuid:string;\n public startRow:number;\n public endRow:number;\n public startColumn:number;\n public endColumn:number;\n\n constructor(startRow:number, endRow:number, startColumn:number, endColumn:number) {\n this.startRow = startRow;\n this.endRow = endRow;\n this.startColumn = startColumn;\n this.endColumn = endColumn;\n }\n\n public get gridStartRow() {\n return this.startRow * 2;\n }\n\n public get gridEndRow() {\n return this.endRow * 2 - 1;\n }\n\n public get gridStartColumn() {\n return this.startColumn * 2;\n }\n\n public get gridEndColumn() {\n return this.endColumn * 2 - 1;\n }\n\n public get guid():string {\n if (!this.storedGuid) {\n this.storedGuid = this.newGuid();\n }\n\n return this.storedGuid;\n }\n\n private newGuid() {\n function s4() {\n return Math.floor((1 + Math.random()) * 0x10000)\n .toString(16)\n .substring(1);\n }\n return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();\n }\n}\n\n","import {GridWidgetResource} from \"app/modules/hal/resources/grid-widget-resource\";\nimport {GridArea} from \"app/modules/grids/areas/grid-area\";\n\nexport class GridWidgetArea extends GridArea {\n public widget:GridWidgetResource;\n\n constructor(widget:GridWidgetResource) {\n super(widget.startRow,\n widget.endRow,\n widget.startColumn,\n widget.endColumn);\n\n this.widget = widget;\n }\n\n public reset() {\n this.startRow = this.widget.startRow;\n this.endRow = this.widget.endRow;\n this.startColumn = this.widget.startColumn;\n this.endColumn = this.widget.endColumn;\n }\n\n public moveRight() {\n this.startColumn++;\n this.endColumn++;\n }\n\n public moveLeft() {\n this.startColumn--;\n this.endColumn--;\n }\n\n public growColumn() {\n this.endColumn++;\n }\n\n public overlaps(otherArea:GridWidgetArea) {\n return this.rowOverlaps(otherArea) &&\n this.columnOverlaps(otherArea);\n }\n\n public rowOverlaps(otherArea:GridWidgetArea) {\n return this.startRow < otherArea.endRow &&\n this.endRow >= otherArea.endRow ||\n this.startRow <= otherArea.startRow &&\n this.endRow > otherArea.startRow ||\n this.startRow > otherArea.startRow &&\n this.endRow < otherArea.endRow;\n }\n\n public columnOverlaps(otherArea:GridWidgetArea) {\n return this.startColumn < otherArea.endColumn &&\n this.endColumn >= otherArea.endColumn ||\n this.startColumn <= otherArea.startColumn &&\n this.endColumn > otherArea.startColumn ||\n this.startColumn > otherArea.startColumn &&\n this.endColumn < otherArea.endColumn;\n }\n\n public startColumnOverlaps(otherArea:GridWidgetArea) {\n return this.startColumn < otherArea.startColumn &&\n this.endColumn > otherArea.startColumn &&\n this.rowOverlaps(otherArea);\n }\n\n public get unchangedSize() {\n return this.startColumn === this.widget.startColumn &&\n this.endColumn === this.widget.endColumn &&\n this.startRow === this.widget.startRow &&\n this.endRow === this.widget.endRow;\n }\n\n public writeAreaChangeToWidget() {\n this.widget.startRow = this.startRow;\n this.widget.endRow = this.endRow;\n this.widget.startColumn = this.startColumn;\n this.widget.endColumn = this.endColumn;\n }\n\n public copyDimensionsTo(sink:GridWidgetArea) {\n sink.startRow = this.startRow;\n sink.startColumn = this.startColumn;\n sink.endRow = this.endRow;\n sink.endColumn = this.endColumn;\n }\n}\n","import {GridArea} from \"core-app/modules/grids/areas/grid-area\";\n\nexport class GridGap extends GridArea {\n private type:'row'|'column';\n\n constructor(startRow:number, endRow:number, startColumn:number, endColumn:number, type:'row'|'column') {\n super(startRow, endRow, startColumn, endColumn);\n\n this.type = type;\n }\n\n public get gridStartRow() {\n if (this.isRow) {\n return this.startRow * 2 - 1;\n } else {\n return this.startRow * 2;\n }\n }\n\n public get gridEndRow() {\n if (this.isRow) {\n return this.endRow * 2 - 2;\n } else {\n return this.endRow * 2 - 1;\n }\n }\n\n public get gridStartColumn() {\n if (this.isRow) {\n return this.startColumn * 2;\n } else {\n return this.startColumn * 2 - 1;\n }\n }\n\n public get gridEndColumn() {\n if (this.isRow) {\n return this.endColumn * 2 - 1;\n } else {\n return this.endColumn * 2 - 2;\n }\n }\n\n public get isRow() {\n return this.type === 'row';\n }\n\n public get isColumn() {\n return this.type === 'column';\n }\n}\n","import {Injectable} from '@angular/core';\nimport {GridWidgetArea} from \"app/modules/grids/areas/grid-widget-area\";\nimport {GridArea} from \"core-app/modules/grids/areas/grid-area\";\nimport {GridGap} from \"core-app/modules/grids/areas/grid-gap\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {WidgetChangeset} from \"core-app/modules/grids/widgets/widget-changeset\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport { BehaviorSubject } from 'rxjs';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3GridForm} from \"core-app/modules/apiv3/endpoints/grids/apiv3-grid-form\";\nimport {map} from \"rxjs/operators\";\n\n@Injectable()\nexport class GridAreaService {\n\n private resource:GridResource;\n public schema:SchemaResource;\n\n public numColumns:number = 0;\n public numRows:number = 0;\n public gridAreas:GridArea[];\n public gridGaps:GridArea[];\n public widgetAreas:GridWidgetArea[];\n public gridAreaIds:string[];\n public mousedOverArea:GridArea|null = null;\n public $mousedOverArea = new BehaviorSubject(this.mousedOverArea);\n public helpMode = false;\n\n constructor (private apiV3Service:APIV3Service,\n private notification:NotificationsService,\n private i18n:I18nService) { }\n\n public set gridResource(value:GridResource) {\n this.resource = value;\n this.fetchSchema();\n\n this.numRows = this.resource.rowCount;\n this.numColumns = this.resource.columnCount;\n\n this.buildAreas(true);\n }\n\n public get gridResource() {\n return this.resource;\n }\n\n public setMousedOverArea(area:GridArea|null) {\n this.mousedOverArea = area;\n\n this.$mousedOverArea.next(area);\n }\n\n public cleanupUnusedAreas() {\n // array containing Numbers from this.numRows to 1\n let unusedRows = _.range(this.numRows, 0, -1);\n\n this.widgetAreas.forEach(widget => {\n unusedRows = unusedRows.filter(item => item !== widget.startRow);\n });\n\n unusedRows.forEach(number => {\n if (this.numRows > 1) {\n this.removeRow(number);\n }\n });\n\n let unusedColumns = _.range(this.numColumns, 0, -1);\n\n this.widgetAreas.forEach(widget => {\n unusedColumns = unusedColumns.filter(item => item !== widget.startColumn);\n });\n\n unusedColumns.forEach(number => {\n if (this.numColumns > 1) {\n this.removeColumn(number);\n }\n });\n }\n\n public buildAreas(widgets = false) {\n this.gridAreas = this.buildGridAreas();\n this.gridGaps = this.buildGridGaps();\n this.gridAreaIds = this.buildGridAreaIds();\n if (widgets) {\n this.widgetAreas = this.buildGridWidgetAreas();\n }\n }\n\n public rebuildAndPersist() {\n this.persist();\n this.buildAreas(false);\n }\n\n public persist() {\n this.resource.rowCount = this.numRows = (this.widgetAreas.map(area => area.endRow).sort((a, b) => a - b).pop() || 2) - 1;\n this.resource.columnCount = this.numColumns;\n\n this.writeAreaChangesToWidgets();\n\n this.saveGrid(this.resource, this.schema);\n }\n\n public saveWidgetChangeset(changeset:WidgetChangeset) {\n let payload:any = Apiv3GridForm.extractPayload(this.resource, this.schema);\n\n let payloadWidget = payload.widgets.find((w:any) => w.id === changeset.pristineResource.id);\n Object.assign(payloadWidget, changeset.changes);\n\n // Adding the id so that the url can be deduced\n payload['id'] = this.resource.id;\n\n this.saveGrid(payload);\n }\n\n public isGap(area:GridArea) {\n return area instanceof GridGap;\n }\n\n public get isSingleCell() {\n return this.numRows === 1 && this.numColumns === 1 && this.widgetResources.length === 0;\n }\n\n public get inHelpMode() {\n return this.helpMode || this.isSingleCell;\n }\n\n public toggleHelpMode() {\n this.helpMode = !this.helpMode;\n }\n\n // This is a hacky way to have the placeholder in the viewport.\n // It is a noop for firefox and edge as both do not support scrollIntoViewIfNeeded.\n // But as scrollIntoView will always readjust the viewport, the result would be an unbearable flicker\n // which causes e.g. dragging to be impossible.\n public scrollPlaceholderIntoView() {\n let placeholder = jQuery('.grid--area.-placeholder');\n\n if ((placeholder[0] as any).scrollIntoViewIfNeeded) {\n setTimeout(() => (placeholder[0] as any).scrollIntoViewIfNeeded());\n }\n }\n\n private saveGrid(resource:GridWidgetResource|any, schema?:SchemaResource) {\n this\n .apiV3Service\n .grids\n .id(resource)\n .patch(resource, schema)\n .subscribe(updatedGrid => {\n this.assignAreasWidget(updatedGrid);\n this.notification.addSuccess(this.i18n.t('js.notice_successful_update'));\n });\n }\n\n private assignAreasWidget(newGrid:GridResource) {\n this.resource.widgets = newGrid.widgets;\n\n let takenIds = this.widgetAreas.map(a => a.widget.id);\n this.widgetAreas.forEach(area => {\n let newWidget:GridWidgetResource;\n\n // identify the right resource for the area. Typically that means fetching them by id.\n // But new areas have unpersisted resources at first. Unpersisted resources have no id.\n // In those cases, we find the one resource which is not claimed by any other area.\n if (area.widget.id) {\n newWidget = newGrid.widgets.find(widget => widget.id === area.widget.id)!;\n } else {\n newWidget = newGrid.widgets.find(widget => !takenIds.includes(widget.id) && widget.identifier === area.widget.identifier && widget.startRow === area.widget.startRow && widget.startColumn === area.widget.startColumn)!;\n }\n\n area.widget = newWidget!;\n });\n }\n\n private buildGridAreas() {\n let cells:GridArea[] = [];\n\n // the one extra row is added in case the user wants to drag a widget to the very bottom\n for (let row = 1; row <= this.numRows + 1; row++) {\n cells.push(...this.buildGridAreasRow(row));\n }\n\n return cells;\n }\n\n private buildGridGaps() {\n let cells:GridArea[] = [];\n\n // special case where we want no gaps\n if (this.isSingleCell) {\n return cells;\n }\n\n for (let row = 1; row <= this.numRows + 1; row++) {\n cells.push(...this.buildGridGapRow(row));\n }\n\n return cells;\n }\n\n private buildGridAreasRow(row:number) {\n let cells:GridArea[] = [];\n\n for (let column = 1; column <= this.numColumns; column++) {\n let cell = new GridArea(row,\n row + 1,\n column,\n column + 1);\n\n cells.push(cell);\n }\n\n return cells;\n }\n\n private buildGridGapRow(row:number) {\n let cells:GridGap[] = [];\n\n for (let column = 1; column <= this.numColumns; column++) {\n cells.push(new GridGap(row,\n row + 1,\n column,\n column + 1,\n 'row'));\n }\n\n if (row <= this.numRows) {\n for (let column = 1; column <= this.numColumns + 1; column++) {\n cells.push(new GridGap(row,\n row + 1,\n column,\n column + 1,\n 'column'));\n }\n }\n\n return cells;\n }\n\n private buildGridWidgetAreas() {\n return this.widgetResources.map((widget) => {\n return new GridWidgetArea(widget);\n });\n }\n\n // persist all changes to the areas caused by dragging/resizing\n // to the widget\n public writeAreaChangesToWidgets() {\n this.widgetAreas.forEach((area) => {\n area.writeAreaChangeToWidget();\n });\n }\n\n public addColumn(column:number, excludeRow:number) {\n this.numColumns++;\n\n let movedWidgets:GridWidgetArea[] = [];\n\n for (let row = 1; row <= this.numRows; row++) {\n if (row === excludeRow) {\n continue;\n }\n\n let widget = this\n .rowWidgets(row)\n .sort((a, b) => a.startColumn - b.startColumn)\n .find(widget => !(widget.startRow < excludeRow && widget.endRow > excludeRow) &&\n (widget.startColumn === column + 1 ||\n widget.endColumn === column + 1 ||\n widget.startColumn <= column && widget.endColumn > column));\n\n if (widget) {\n movedWidgets.push(widget);\n widget.endColumn++;\n }\n }\n\n this.moveSubsequentRowWidgets(this.widgetAreas.filter(widget => !movedWidgets.includes(widget)),\n column);\n }\n\n public addRow(row:number, excludeColumn:number) {\n this.numRows++;\n\n let movedWidgets:GridWidgetArea[] = [];\n\n for (let column = 1; column <= this.numColumns; column++) {\n if (column === excludeColumn) {\n continue;\n }\n\n let widget = this\n .columnWidgets(column)\n .sort((a, b) => a.startRow - b.startRow)\n .find(widget => !(widget.startColumn < excludeColumn && widget.endColumn > excludeColumn) &&\n (widget.startRow === row + 1 ||\n widget.endRow === row + 1 ||\n widget.startRow <= row && widget.endRow > row));\n\n if (widget) {\n movedWidgets.push(widget);\n widget.endRow++;\n }\n }\n\n this.moveSubsequentColumnWidgets(this.widgetAreas.filter(widget => !movedWidgets.includes(widget)),\n row);\n }\n\n public removeColumn(column:number) {\n this.numColumns--;\n\n //shrink widgets that span more than the removed column\n this.widgetAreas.forEach((widget) => {\n if (widget.startColumn <= column && widget.endColumn >= column + 1) {\n //shrink widgets that span more than the removed column\n widget.endColumn--;\n }\n });\n\n // move all widgets that are after the removed column\n // so that they appear to keep their place.\n this.widgetAreas.filter((widget) => {\n return widget.startColumn > column;\n }).forEach((widget) => {\n widget.startColumn--;\n widget.endColumn--;\n });\n }\n\n public removeRow(row:number) {\n this.numRows--;\n\n //shrink widgets that span more than the removed row\n this.widgetAreas.forEach((widget) => {\n if (widget.startRow <= row && widget.endRow >= row + 1) {\n //shrink widgets that span more than the removed row\n widget.endRow--;\n }\n });\n\n // move all widgets that are after the removed row\n // so that they appear to keep their place.\n this.widgetAreas.filter((widget) => {\n return widget.startRow > row;\n }).forEach((widget) => {\n widget.startRow--;\n widget.endRow--;\n });\n }\n\n public resetAreas(ignoredArea:GridWidgetArea|null = null) {\n this.widgetAreas.filter((area) => {\n return !ignoredArea || area.guid !== ignoredArea.guid;\n }).forEach(area => area.reset());\n\n this.numRows = this.resource.rowCount;\n this.numColumns = this.resource.columnCount;\n }\n\n public get isEditable() {\n return this.gridResource.updateImmediately !== undefined;\n }\n\n private buildGridAreaIds() {\n return this\n .gridAreas\n .filter(area => !this.isGap(area))\n .map((area) => area.guid);\n }\n\n private fetchSchema() {\n this\n .apiV3Service\n .grids\n .id(this.resource)\n .form\n .post({})\n .subscribe(form => this.schema = form.schema);\n }\n\n public removeWidget(removedWidget:GridWidgetResource) {\n let index = this.resource.widgets.findIndex((widget) => widget.id === removedWidget.id );\n this.resource.widgets.splice(index, 1);\n\n index = this.widgetAreas.findIndex((area) => area.widget.id === removedWidget.id);\n this.widgetAreas.splice(index, 1);\n this.cleanupUnusedAreas();\n\n this.rebuildAndPersist();\n }\n\n public get widgetResources() {\n return (this.resource && this.resource.widgets) || [];\n }\n\n private rowWidgets(row:number) {\n return this.widgetAreas.filter(widget => widget.startRow === row);\n }\n\n private moveSubsequentRowWidgets(rowWidgets:GridWidgetArea[], column:number) {\n rowWidgets.forEach(subsequentWidget => {\n if (subsequentWidget.startColumn > column) {\n subsequentWidget.startColumn++;\n subsequentWidget.endColumn++;\n }\n });\n }\n\n private columnWidgets(column:number) {\n return this.widgetAreas.filter(widget => widget.startColumn === column);\n }\n\n private moveSubsequentColumnWidgets(columnWidgets:GridWidgetArea[], row:number) {\n columnWidgets.forEach(subsequentWidget => {\n if (subsequentWidget.startRow > row) {\n subsequentWidget.startRow++;\n subsequentWidget.endRow++;\n }\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ChangeDetectionStrategy, Input, EventEmitter, Output} from '@angular/core';\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\n\n@Component({\n selector: 'widget-header',\n templateUrl: './header.component.html',\n styleUrls: ['./header.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WidgetHeaderComponent {\n @Input() name:string;\n @Input() editable:boolean = true;\n @Output() onRenamed = new EventEmitter();\n\n constructor(readonly layout:GridAreaService) {\n\n }\n\n public renamed(name:string) {\n this.onRenamed.emit(name);\n }\n\n public get isRenameable() {\n return this.editable && this.layout.isEditable;\n }\n}\n","

    \n\n \n\n \n \n\n \n

    \n","import {Injectable} from \"@angular/core\";\nimport {GridWidgetArea} from \"core-app/modules/grids/areas/grid-widget-area\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\n\n@Injectable()\nexport class GridRemoveWidgetService {\n\n constructor(readonly layout:GridAreaService) {\n }\n\n public area(area:GridWidgetArea) {\n this.widget(area.widget);\n }\n\n public widget(widget:GridWidgetResource) {\n this.layout.removeWidget(widget);\n }\n\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport { Input, Directive } from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {OpContextMenuItem} from \"core-components/op-context-menu/op-context-menu.types\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {GridRemoveWidgetService} from \"core-app/modules/grids/grid/remove-widget.service\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\n\n@Directive()\nexport abstract class WidgetAbstractMenuComponent {\n @Input() resource:GridWidgetResource;\n\n protected menuItemList:OpContextMenuItem[] = [this.removeItem];\n\n constructor(readonly i18n:I18nService,\n protected readonly remove:GridRemoveWidgetService,\n protected readonly layout:GridAreaService) {\n }\n\n public get menuItems() {\n return async () => {\n return this.menuItemList;\n };\n }\n\n protected get removeItem() {\n return {\n linkText: this.i18n.t('js.grid.remove'),\n onClick: () => {\n this.remove.widget(this.resource);\n return true;\n }\n };\n }\n\n public get hasMenu() {\n return this.layout.isEditable;\n }\n}\n","\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from '@angular/core';\nimport {WidgetAbstractMenuComponent} from \"core-app/modules/grids/widgets/menu/widget-abstract-menu.component\";\n\n@Component({\n selector: 'widget-menu',\n templateUrl: './widget-menu.component.html',\n styleUrls: ['./widget-menu.component.css']\n})\nexport class WidgetMenuComponent extends WidgetAbstractMenuComponent {\n}\n","\n
    \n \n \n
    \n\n","import {\n AfterViewInit,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Input,\n OnInit,\n SecurityContext,\n ViewChild\n} from \"@angular/core\";\nimport {FullCalendarComponent} from '@fullcalendar/angular';\nimport {States} from \"core-components/states.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport * as moment from \"moment\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {StateService} from \"@uirouter/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {DomSanitizer} from \"@angular/platform-browser\";\nimport {WorkPackagesListChecksumService} from \"core-components/wp-list/wp-list-checksum.service\";\nimport {OpTitleService} from \"core-components/html/op-title.service\";\nimport dayGridPlugin from '@fullcalendar/daygrid';\nimport {CalendarOptions, EventApi, EventInput} from '@fullcalendar/core';\nimport {Subject} from \"rxjs\";\nimport {take, debounceTime} from 'rxjs/operators';\nimport {ToolbarInput} from '@fullcalendar/common';\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\ninterface CalendarViewEvent {\n el:HTMLElement;\n event:EventApi;\n}\n\n@Component({\n templateUrl: './wp-calendar.template.html',\n styleUrls: ['./wp-calendar.sass'],\n selector: 'wp-calendar',\n})\nexport class WorkPackagesCalendarController extends UntilDestroyedMixin implements OnInit {\n private resizeObserver:ResizeObserver;\n private resizeSubject = new Subject();\n private ucCalendar:FullCalendarComponent;\n @ViewChild(FullCalendarComponent)\n set container(v:FullCalendarComponent|undefined) {\n // ViewChild reference may be undefined initially\n // due to ngIf\n if (!v) {\n return;\n }\n\n this.ucCalendar = v;\n\n // The full-calendar component's outputs do not seem to work\n // see: https://github.com/fullcalendar/fullcalendar-angular/issues/228#issuecomment-523505044\n // Therefore, setting the outputs via the underlying API\n this.ucCalendar.getApi().setOption('eventDidMount', (event:CalendarViewEvent) => {\n this.addTooltip(event);\n });\n this.ucCalendar.getApi().setOption('eventClick', (event:CalendarViewEvent) => {\n this.toWPFullView(event);\n });\n }\n @ViewChild('ucCalendar', { read: ElementRef })\n set ucCalendarElement(v:ElementRef|undefined) {\n if (!v) {\n return;\n }\n\n if (!this.resizeObserver) {\n this.resizeObserver = new ResizeObserver(() => this.resizeSubject.next());\n }\n\n this.resizeObserver.observe(v.nativeElement);\n }\n\n @Input() projectIdentifier:string;\n @Input() static:boolean = false;\n static MAX_DISPLAYED = 100;\n\n public tooManyResultsText:string|null;\n\n private alreadyLoaded = false;\n\n calendarOptions:CalendarOptions|undefined;\n\n constructor(readonly states:States,\n readonly $state:StateService,\n readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly wpListService:WorkPackagesListService,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpListChecksumService:WorkPackagesListChecksumService,\n readonly schemaCache:SchemaCacheService,\n readonly titleService:OpTitleService,\n private element:ElementRef,\n readonly i18n:I18nService,\n readonly notificationsService:NotificationsService,\n private sanitizer:DomSanitizer,\n private configuration:ConfigurationService) {\n super();\n }\n\n ngOnInit() {\n this.resizeSubject\n .pipe(debounceTime(50))\n .subscribe(() => {\n this.ucCalendar.getApi().updateSize();\n });\n\n // Clear any old subscribers\n this.querySpace.stopAllSubscriptions.next();\n\n this.setupWorkPackagesListener();\n this.initializeCalendar();\n }\n\n public calendarEventsFunction(fetchInfo:{ start:Date, end:Date, timeZone:string },\n successCallback:(events:EventInput[]) => void,\n failureCallback:(error:any) => void):void|PromiseLike {\n if (this.alreadyLoaded) {\n this.alreadyLoaded = false;\n let events = this.updateResults(this.querySpace.results.value!);\n successCallback(events);\n } else {\n this.querySpace.results.values$().pipe(\n take(1)\n ).subscribe((collection:WorkPackageCollectionResource) => {\n let events = this.updateResults((collection));\n successCallback(events);\n });\n }\n\n\n this.updateTimeframe(fetchInfo);\n }\n\n private initializeCalendar() {\n this.configuration.initialized\n .then(() => {\n this.calendarOptions = {\n editable: false,\n locale: this.i18n.locale,\n fixedWeekCount: false,\n firstDay: this.configuration.startOfWeek(),\n events: this.calendarEventsFunction.bind(this),\n plugins: [dayGridPlugin],\n initialView: (() => {\n if (this.static) {\n return 'dayGridWeek';\n } else {\n return undefined;\n }\n })(),\n height: this.calendarHeight(),\n headerToolbar: this.buildHeader()\n };\n });\n }\n\n public updateTimeframe(fetchInfo:{ start:Date, end:Date, timeZone:string }) {\n let filtersEmpty = this.wpTableFilters.isEmpty;\n\n if (filtersEmpty && this.querySpace.query.value) {\n // nothing to do\n return;\n }\n\n let startDate = moment(fetchInfo.start).format('YYYY-MM-DD');\n let endDate = moment(fetchInfo.end).format('YYYY-MM-DD');\n\n if (filtersEmpty) {\n let queryProps = this.defaultQueryProps(startDate, endDate);\n\n if (this.$state.params.query_props) {\n queryProps = decodeURIComponent(this.$state.params.query_props || '');\n }\n\n this.wpListService.fromQueryParams({ query_props: queryProps }, this.projectIdentifier).toPromise();\n } else {\n let params = this.$state.params;\n\n this.wpTableFilters.modify('datesInterval', (datesIntervalFilter) => {\n datesIntervalFilter.values[0] = startDate;\n datesIntervalFilter.values[1] = endDate;\n });\n }\n }\n\n public addTooltip(event:CalendarViewEvent) {\n jQuery(event.el).tooltip({\n content: this.tooltipContentString(event.event.extendedProps.workPackage),\n items: '.fc-event',\n close: function () {\n jQuery(\".ui-helper-hidden-accessible\").remove();\n },\n track: true\n });\n }\n\n public toWPFullView(event:CalendarViewEvent) {\n let workPackage = event.event.extendedProps.workPackage;\n\n if (event.el) {\n // do not display the tooltip on the wp show page\n this.removeTooltip(event.el);\n }\n\n // Ensure checksum is removed to allow queries to load\n this.wpListChecksumService.clear();\n\n // Ensure current calendar URL is pushed to history\n window.history.pushState({}, this.titleService.current, window.location.href);\n\n this.$state.go(\n 'work-packages.show',\n { workPackageId: workPackage.id },\n { inherit: false });\n }\n private get calendarElement() {\n return jQuery(this.element.nativeElement).find('.wp-calendar--container');\n }\n\n private calendarHeight():number {\n if (this.static) {\n let heightElement = jQuery(this.element.nativeElement);\n\n while (!heightElement.height() && heightElement.parent()) {\n heightElement = heightElement.parent();\n }\n\n let topOfCalendar = jQuery(this.element.nativeElement).position().top;\n let topOfHeightElement = heightElement.position().top;\n\n return heightElement.height()! - (topOfCalendar - topOfHeightElement);\n } else {\n // -12 for the bottom padding\n return jQuery(window).height()! - this.calendarElement.offset()!.top - 12;\n }\n }\n\n public buildHeader() {\n if (this.static) {\n return false;\n } else {\n return {\n right: 'dayGridMonth,dayGridWeek',\n center: 'title',\n left: 'prev,next today'\n };\n }\n }\n\n private setCalendarsDate() {\n const query = this.querySpace.query.value;\n if (!query) {\n return;\n }\n\n let datesIntervalFilter = _.find(query.filters || [], { 'id': 'datesInterval' }) as any;\n\n let calendarDate:any = null;\n let calendarUnit = 'dayGridMonth';\n\n if (datesIntervalFilter) {\n let lower = moment(datesIntervalFilter.values[0] as string);\n let upper = moment(datesIntervalFilter.values[1] as string);\n let diff = upper.diff(lower, 'days');\n\n calendarDate = lower.add(diff / 2, 'days');\n\n if (diff === 7) {\n calendarUnit = 'dayGridWeek';\n }\n }\n\n if (calendarDate) {\n this.ucCalendar.getApi().changeView(calendarUnit, calendarDate.toDate());\n } else {\n this.ucCalendar.getApi().changeView(calendarUnit);\n }\n }\n\n private setupWorkPackagesListener() {\n this.querySpace.results.values$().pipe(\n this.untilDestroyed()\n ).subscribe((collection:WorkPackageCollectionResource) => {\n this.alreadyLoaded = true;\n this.setCalendarsDate();\n\n this.ucCalendar.getApi().refetchEvents();\n });\n }\n\n private updateResults(collection:WorkPackageCollectionResource) {\n this.warnOnTooManyResults(collection);\n\n return this.mapToCalendarEvents(collection.elements);\n }\n\n private mapToCalendarEvents(workPackages:WorkPackageResource[]) {\n let events = workPackages.map((workPackage:WorkPackageResource) => {\n let startDate = this.eventDate(workPackage, 'start');\n let endDate = this.eventDate(workPackage, 'due');\n\n let exclusiveEnd = moment(endDate).add(1, 'days').format('YYYY-MM-DD');\n\n return {\n title: workPackage.subject,\n start: startDate,\n end: exclusiveEnd,\n allDay: true,\n className: `__hl_background_type_${workPackage.type.id}`,\n workPackage: workPackage\n };\n });\n\n return events;\n }\n\n private warnOnTooManyResults(collection:WorkPackageCollectionResource) {\n if (collection.count < collection.total) {\n this.tooManyResultsText = this.i18n.t('js.calendar.too_many',\n {\n count: collection.total,\n max: WorkPackagesCalendarController.MAX_DISPLAYED\n });\n } else {\n this.tooManyResultsText = null;\n }\n\n if (this.tooManyResultsText && !this.static) {\n this.notificationsService.addNotice(this.tooManyResultsText);\n }\n }\n\n private defaultQueryProps(startDate:string, endDate:string) {\n let props = {\n \"c\": [\"id\"],\n \"t\":\n \"id:asc\",\n \"f\": [{ \"n\": \"status\", \"o\": \"o\", \"v\": [] },\n { \"n\": \"datesInterval\", \"o\": \"<>d\", \"v\": [startDate, endDate] }],\n \"pp\": WorkPackagesCalendarController.MAX_DISPLAYED\n };\n\n return JSON.stringify(props);\n }\n\n private eventDate(workPackage:WorkPackageResource, type:'start'|'due') {\n if (this.schemaCache.of(workPackage).isMilestone) {\n return workPackage.date;\n } else {\n return workPackage[`${type}Date`];\n }\n }\n\n private tooltipContentString(workPackage:WorkPackageResource) {\n return `\n ${this.sanitizedValue(workPackage, 'type')} #${workPackage.id}: ${this.sanitizedValue(workPackage, 'subject', null)}\n
      \n
    • \n ${this.i18n.t('js.work_packages.properties.projectName')}:\n ${this.sanitizedValue(workPackage, 'project')}\n
    • \n
    • \n ${this.i18n.t('js.work_packages.properties.status')}:\n ${this.sanitizedValue(workPackage, 'status')}\n
    • \n
    • \n ${this.i18n.t('js.work_packages.properties.startDate')}:\n ${this.eventDate(workPackage, 'start')}\n
    • \n
    • \n ${this.i18n.t('js.work_packages.properties.dueDate')}:\n ${this.eventDate(workPackage, 'due')}\n
    • \n
    • \n ${this.i18n.t('js.work_packages.properties.assignee')}:\n ${this.sanitizedValue(workPackage, 'assignee')}\n
    • \n
    • \n ${this.i18n.t('js.work_packages.properties.priority')}:\n ${this.sanitizedValue(workPackage, 'priority')}\n
    • \n
    \n `;\n }\n\n private sanitizedValue(workPackage:WorkPackageResource, attribute:string, toStringMethod:string|null = 'name') {\n let value = workPackage[attribute];\n value = toStringMethod && value ? value[toStringMethod] : value;\n value = value || this.i18n.t('js.placeholders.default');\n\n return this.sanitizer.sanitize(SecurityContext.HTML, value);\n }\n\n private removeTooltip(element:HTMLElement) {\n // deactivate tooltip so that it is not displayed on the wp show page\n jQuery(element).tooltip({\n close: function () {\n jQuery(\".ui-helper-hidden-accessible\").remove();\n },\n disabled: true\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Injector} from '@angular/core';\nimport {AbstractWidgetComponent} from \"app/modules/grids/widgets/abstract-widget.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\n\n@Component({\n templateUrl: './wp-calendar.component.html',\n})\nexport class WidgetWpCalendarComponent extends AbstractWidgetComponent {\n constructor(protected readonly i18n:I18nService,\n protected readonly injector:Injector,\n protected readonly currentProject:CurrentProjectService) {\n super(i18n, injector);\n }\n\n public get projectIdentifier() {\n return this.currentProject.identifier;\n }\n}\n","\n\n \n \n\n\n\n \n\n","import { Injectable } from '@angular/core';\nimport {DisplayedDays} from \"core-app/modules/calendar/te-calendar/te-calendar.component\";\n\n@Injectable()\nexport class TimeEntriesCurrentUserConfigurationModalService {\n /*\n * Get the data of the days in the locale order\n * @param daysCheckedValues: Checked value of all days of the week, starting from Monday.\n * Moment's default weekday start is Sunday, so daysCheckedValues have a weekday offset of 1.\n * @param localeWeekDays: week days ordered by locale\n * @param localeOffset: locale offset regarding the default week start day (Sunday (0)).\n */\n\n getOrderedDaysData(\n daysCheckedValues:boolean[],\n localeWeekDays = moment.weekdays(true),\n localeOffset = moment.localeData().firstDayOfWeek(),\n ):IDayData[] {\n // The daysCheckedValues come with offset 1 (the week start day is Monday (1),\n // so the first element in the array is Monday). We have to subtract 1 to the\n // locale offset to match localeWeekDays with daysCheckedValues. For example:\n // localeWeekDays (with offset 0) = [SundayValue, MondayValue, TuesdayValue, WednesdayValue, ThursdayValue, FridayValue, SaturdayValue]\n // daysCheckedValues (with offset 1) = [MondayValue, TuesdayValue, WednesdayValue, ThursdayValue, FridayValue, SaturdayValue, SundayValue]\n // offsetToApply = -1, so we need to pass the last daysCheckedValues to the start of the array to match the localeWeekDays order\n // In order save the result, we will have to reorder it with offset 1 (getCheckedValuesInOriginalOrder)\n const offsetToApply = localeOffset - 1;\n const offsetCheckedValues = offsetToApply >= 0 ? daysCheckedValues.splice(0, offsetToApply) : daysCheckedValues.splice(offsetToApply);\n const orderedDaysCheckedValues = offsetToApply >= 0 ? [...daysCheckedValues, ...offsetCheckedValues] : [...offsetCheckedValues, ...daysCheckedValues];\n const weekDaysWithCheckedValue = orderedDaysCheckedValues\n .map(\n (dayCheckedValue, index) => ({\n weekDay: localeWeekDays[index],\n checked: dayCheckedValue,\n originalIndex: this.getOriginalIndex(offsetToApply, index, orderedDaysCheckedValues.length)\n })\n );\n\n return weekDaysWithCheckedValue;\n }\n\n getOriginalIndex(offsetToApply:number, currentIndex:number, arrayLength:number):number {\n let originalIndex = currentIndex + offsetToApply;\n\n if (originalIndex < 0 ) {\n originalIndex = arrayLength - 1;\n } else if (originalIndex >= arrayLength) {\n originalIndex = 0;\n }\n\n return originalIndex;\n }\n\n getCheckedValuesInOriginalOrder(days:IDayData[]) {\n const configuredDays = days\n .sort((a, b) => a.originalIndex < b.originalIndex ? -1 : 1)\n .map(localeDayData => localeDayData.checked);\n\n return this.validDays(configuredDays as DisplayedDays);\n }\n\n private validDays(days:DisplayedDays) {\n if (days.every((value) => !value)) {\n return Array.apply(null, Array(7)).map(() => true);\n } else {\n return days;\n }\n }\n}\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n \n \n \n \n \n \n
    \n\n
    \n
    \n \n \n
    \n
    \n
    \n","import {\n ApplicationRef,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Inject,\n Injector,\n OnInit,\n} from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {TimeEntriesCurrentUserConfigurationModalService} from \"core-app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-configuration-modal/services/time-entries-current-user-configuration-modal/time-entries-current-user-configuration-modal.service\";\n\n@Component({\n templateUrl: './time-entries-current-user-configuration.modal.html',\n providers: [TimeEntriesCurrentUserConfigurationModalService],\n})\nexport class TimeEntriesCurrentUserConfigurationModalComponent extends OpModalComponent implements OnInit {\n\n /* Close on escape? */\n public closeOnEscape = true;\n\n /* Close on outside click */\n public closeOnOutsideClick = true;\n\n public $element:JQuery;\n\n public text = {\n displayedDays: this.I18n.t('js.grid.widgets.time_entries_current_user.displayed_days'),\n closePopup: this.I18n.t('js.close_popup_title'),\n applyButton: this.I18n.t('js.modals.button_apply'),\n cancelButton: this.I18n.t('js.modals.button_cancel'),\n };\n\n public firstDayOfWeek:number;\n\n // Checked value of all days of the week, starting from Monday.\n public options:{ days:boolean[] };\n public daysOriginalCheckedValues:boolean[];\n public days:IDayData[];\n\n constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly I18n:I18nService,\n readonly injector:Injector,\n readonly appRef:ApplicationRef,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly notificationService:WorkPackageNotificationService,\n readonly cdRef:ChangeDetectorRef,\n readonly configuration:ConfigurationService,\n readonly elementRef:ElementRef,\n readonly timeEntriesCurrentUserConfigurationModalService:TimeEntriesCurrentUserConfigurationModalService) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n this.daysOriginalCheckedValues = this.locals.options.days || Array.from({ length: 7 }, () => true);\n this.days = this.timeEntriesCurrentUserConfigurationModalService.getOrderedDaysData(this.daysOriginalCheckedValues);\n }\n\n public saveChanges():void {\n const checkedValuesInOriginalOrder = this.timeEntriesCurrentUserConfigurationModalService.getCheckedValuesInOriginalOrder(this.days);\n\n this.options = { days: checkedValuesInOriginalOrder };\n this.service.close();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Output, EventEmitter, Injector} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {GridRemoveWidgetService} from \"core-app/modules/grids/grid/remove-widget.service\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\nimport {WidgetAbstractMenuComponent} from \"core-app/modules/grids/widgets/menu/widget-abstract-menu.component\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {TimeEntriesCurrentUserConfigurationModalComponent} from \"core-app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-configuration-modal/time-entries-current-user-configuration.modal\";\n\n@Component({\n selector: 'widget-time-entries-current-user-menu',\n templateUrl: '../../menu/widget-menu.component.html'\n})\nexport class WidgetTimeEntriesCurrentUserMenuComponent extends WidgetAbstractMenuComponent {\n @Output()\n onConfigured:EventEmitter = new EventEmitter();\n\n protected menuItemList = [\n this.removeItem,\n this.configureItem\n ];\n\n constructor(private readonly injector:Injector,\n private readonly opModalService:OpModalService,\n readonly i18n:I18nService,\n protected readonly remove:GridRemoveWidgetService,\n readonly layout:GridAreaService) {\n super(i18n,\n remove,\n layout);\n }\n\n protected get configureItem() {\n return {\n linkText: this.i18n.t('js.grid.configure'),\n onClick: () => {\n this.opModalService.show(TimeEntriesCurrentUserConfigurationModalComponent, this.injector, this.locals)\n .closingEvent.subscribe((modal:TimeEntriesCurrentUserConfigurationModalComponent) => {\n if (modal.options) {\n this.onConfigured.emit(modal.options);\n }\n });\n return true;\n }\n };\n }\n\n protected get locals() {\n return { options: this.resource.options };\n }\n}\n","import {Component, ChangeDetectionStrategy} from \"@angular/core\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {TimeEntryBaseModal} from \"core-app/modules/time_entries/shared/modal/base.modal\";\n\n@Component({\n templateUrl: '../shared/modal/base.modal.html',\n styleUrls: ['../shared/modal/base.modal.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class TimeEntryEditModal extends TimeEntryBaseModal {\n public modifiedEntry:TimeEntryResource;\n public destroyedEntry:TimeEntryResource;\n\n public setModifiedEntry($event:{savedResource:HalResource, isInital:boolean}) {\n this.modifiedEntry = $event.savedResource as TimeEntryResource;\n this.reloadWorkPackageAndClose();\n }\n\n public get saveAllowed() {\n return !!this.entry.update;\n }\n\n public get deleteAllowed() {\n return !!this.entry.delete;\n }\n\n public destroy() {\n if (!window.confirm(this.text.areYouSure)) {\n return;\n }\n\n this.destroyedEntry = this.entry;\n this.service.close();\n }\n}\n","import {Injectable, Injector} from \"@angular/core\";\nimport {OpModalService} from \"app/components/op-modals/op-modal.service\";\nimport {HalResourceService} from \"app/modules/hal/services/hal-resource.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport { TimeEntryResource } from 'core-app/modules/hal/resources/time-entry-resource';\nimport { TimeEntryEditModal } from './edit.modal';\nimport { take } from 'rxjs/operators';\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class TimeEntryEditService {\n\n constructor(readonly opModalService:OpModalService,\n readonly injector:Injector,\n readonly apiV3Service:APIV3Service,\n readonly halResource:HalResourceService,\n protected halEditing:HalResourceEditingService,\n readonly i18n:I18nService) {\n }\n\n public edit(entry:TimeEntryResource) {\n return new Promise<{entry:TimeEntryResource, action:'update'|'destroy'}>((resolve, reject) => {\n this\n .createChangeset(entry)\n .then(changeset => {\n const modal = this.opModalService.show(TimeEntryEditModal, this.injector, { changeset: changeset });\n\n modal\n .closingEvent\n .pipe(take(1))\n .subscribe(() => {\n if (modal.destroyedEntry) {\n modal.destroyedEntry.delete().then(() => {\n resolve({entry: modal.destroyedEntry, action: 'destroy'});\n });\n } else if (modal.modifiedEntry) {\n resolve({ entry: modal.modifiedEntry, action: 'update' });\n } else {\n reject();\n }\n });\n });\n });\n }\n\n public createChangeset(entry:TimeEntryResource) {\n return this\n .apiV3Service\n .time_entries\n .id(entry)\n .form\n .post(entry)\n .toPromise()\n .then(form => {\n return this.halEditing.edit>(entry, form);\n });\n }\n}\n","\n
    \n\n \n\n \n \n
    \n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n EventEmitter,\n Injector,\n Input,\n Output,\n SecurityContext,\n ViewChild,\n ViewEncapsulation\n} from \"@angular/core\";\nimport {FullCalendarComponent} from '@fullcalendar/angular';\nimport {States} from \"core-components/states.service\";\nimport * as moment from \"moment\";\nimport {Moment} from \"moment\";\nimport {StateService} from \"@uirouter/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {DomSanitizer} from \"@angular/platform-browser\";\nimport timeGrid from '@fullcalendar/timegrid';\nimport {CalendarOptions, Duration, EventApi, EventInput} from '@fullcalendar/core';\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\nimport {FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport interactionPlugin from '@fullcalendar/interaction';\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {TimeEntryEditService} from \"core-app/modules/time_entries/edit/edit.service\";\nimport {TimeEntryCreateService} from \"core-app/modules/time_entries/create/create.service\";\nimport {ColorsService} from \"core-app/modules/common/colors/colors.service\";\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {HalResourceNotificationService} from 'core-app/modules/hal/services/hal-resource-notification.service';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\ninterface CalendarViewEvent {\n el:HTMLElement;\n event:EventApi;\n}\n\ninterface CalendarMoveEvent {\n el:HTMLElement;\n event:EventApi;\n oldEvent:EventApi;\n delta:Duration;\n revert:() => void;\n}\n\n// An array of all the days that are displayed. The zero index represents Monday.\nexport type DisplayedDays = [boolean, boolean, boolean, boolean, boolean, boolean, boolean];\n\nconst TIME_ENTRY_CLASS_NAME = 'te-calendar--time-entry';\nconst DAY_SUM_CLASS_NAME = 'te-calendar--day-sum';\nconst ADD_ENTRY_CLASS_NAME = 'te-calendar--add-entry';\nconst ADD_ICON_CLASS_NAME = 'te-calendar--add-icon';\nconst ADD_ENTRY_PROHIBITED_CLASS_NAME = '-prohibited';\n\n@Component({\n templateUrl: './te-calendar.template.html',\n styleUrls: ['./te-calendar.component.sass'],\n selector: 'te-calendar',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n TimeEntryEditService,\n TimeEntryCreateService,\n HalResourceEditingService\n ]\n})\nexport class TimeEntryCalendarComponent implements AfterViewInit {\n @ViewChild(FullCalendarComponent) ucCalendar:FullCalendarComponent;\n @Input() projectIdentifier:string;\n @Input() static:boolean = false;\n\n @Input() set displayedDays(days:DisplayedDays) {\n this.setHiddenDays(days);\n }\n\n @Output() entries = new EventEmitter>();\n\n // Not used by the calendar but rather is the maximum/minimum of the graph.\n public minHour = 1;\n public maxHour = 12;\n public labelIntervalHours = 2;\n public scaleRatio = 1;\n\n public calendarEvents:Function;\n protected memoizedTimeEntries:{ start:Date, end:Date, entries:Promise> };\n public memoizedCreateAllowed:boolean = false;\n public hiddenDays:number[] = [];\n\n public text = {\n logTime: this.i18n.t('js.button_log_time')\n };\n\n calendarOptions:CalendarOptions = {\n editable: false,\n locale: this.i18n.locale,\n fixedWeekCount: false,\n headerToolbar: {\n right: '',\n center: 'title',\n left: 'prev,next today'\n },\n initialView: 'timeGridWeek',\n firstDay: this.configuration.startOfWeek(),\n hiddenDays: [],\n contentHeight: 605,\n slotEventOverlap: false,\n slotLabelInterval: `${this.labelIntervalHours}:00:00`,\n slotLabelFormat: (info:any) => ((this.maxHour - info.date.hour) / this.scaleRatio).toString(),\n allDaySlot: false,\n displayEventTime: false,\n slotMinTime: `${this.minHour - 1}:00:00`,\n slotMaxTime: `${this.maxHour}:00:00`,\n events: this.calendarEventsFunction.bind(this),\n eventOverlap: (stillEvent:any) => !stillEvent.classNames.includes(TIME_ENTRY_CLASS_NAME),\n plugins: [timeGrid, interactionPlugin]\n };\n\n constructor(readonly states:States,\n readonly apiV3Service:APIV3Service,\n readonly $state:StateService,\n private element:ElementRef,\n readonly i18n:I18nService,\n readonly injector:Injector,\n readonly notifications:HalResourceNotificationService,\n private sanitizer:DomSanitizer,\n private configuration:ConfigurationService,\n private timezone:TimezoneService,\n private timeEntryEdit:TimeEntryEditService,\n private timeEntryCreate:TimeEntryCreateService,\n private schemaCache:SchemaCacheService,\n private colors:ColorsService,\n private browserDetector:BrowserDetector) {\n }\n\n ngAfterViewInit() {\n // The full-calendar component's outputs do not seem to work\n // see: https://github.com/fullcalendar/fullcalendar-angular/issues/228#issuecomment-523505044\n // Therefore, setting the outputs via the underlying API\n this.ucCalendar.getApi().setOption('eventDidMount', (event:CalendarViewEvent) => {\n this.alterEventEntry(event);\n });\n this.ucCalendar.getApi().setOption('eventWillUnmount', (event:CalendarViewEvent) => {\n this.beforeEventRemove(event);\n });\n this.ucCalendar.getApi().setOption('eventClick', (event:CalendarViewEvent) => {\n this.dispatchEventClick(event);\n });\n this.ucCalendar.getApi().setOption('eventDrop', (event:CalendarMoveEvent) => {\n this.moveEvent(event);\n });\n }\n\n public calendarEventsFunction(fetchInfo:{ start:Date, end:Date },\n successCallback:(events:EventInput[]) => void,\n failureCallback:(error:unknown) => void):void|PromiseLike {\n\n this.fetchTimeEntries(fetchInfo.start, fetchInfo.end)\n .then((collection) => {\n this.entries.emit(collection);\n\n successCallback(this.buildEntries(collection.elements, fetchInfo));\n });\n }\n\n protected fetchTimeEntries(start:Date, end:Date) {\n if (!this.memoizedTimeEntries ||\n this.memoizedTimeEntries.start.getTime() !== start.getTime() ||\n this.memoizedTimeEntries.end.getTime() !== end.getTime()) {\n let promise = this\n .apiV3Service\n .time_entries\n .list({ filters: this.dmFilters(start, end), pageSize: 500 })\n .toPromise()\n .then(collection => {\n this.memoizedCreateAllowed = !!collection.createTimeEntry;\n\n return collection;\n });\n\n this.memoizedTimeEntries = { start: start, end: end, entries: promise };\n }\n\n return this.memoizedTimeEntries.entries;\n }\n\n private buildEntries(entries:TimeEntryResource[], fetchInfo:{ start:Date, end:Date }) {\n this.setRatio(entries);\n\n return this.buildTimeEntryEntries(entries)\n .concat(this.buildAuxEntries(entries, fetchInfo));\n }\n\n private setRatio(entries:TimeEntryResource[]) {\n let dateSums = this.calculateDateSums(entries);\n\n let maxHours = Math.max(...Object.values(dateSums), 0);\n\n let oldRatio = this.scaleRatio;\n\n if (maxHours > this.maxHour - this.minHour) {\n this.scaleRatio = this.smallerSuitableRatio((this.maxHour - this.minHour) / maxHours);\n } else {\n this.scaleRatio = 1;\n }\n\n if (oldRatio !== this.scaleRatio) {\n // This is a hack.\n // We already set the same function (different object) via angular.\n // But it will trigger repainting the calendar.\n // Weirdly, this.ucCalendar.getApi().rerender() does not.\n this.ucCalendar.getApi().setOption('slotLabelFormat', (info:any) => {\n let val = (this.maxHour - info.date.hour) / this.scaleRatio;\n return val.toString();\n });\n }\n }\n\n private buildTimeEntryEntries(entries:TimeEntryResource[]) {\n let hoursDistribution:{ [key:string]:Moment } = {};\n\n return entries.map((entry) => {\n let start:Moment;\n let end:Moment;\n let hours = this.timezone.toHours(entry.hours) * this.scaleRatio;\n\n if (hoursDistribution[entry.spentOn]) {\n start = hoursDistribution[entry.spentOn].clone().subtract(hours, 'h');\n end = hoursDistribution[entry.spentOn].clone();\n } else {\n start = moment(entry.spentOn).add(this.maxHour - hours, 'h');\n end = moment(entry.spentOn).add(this.maxHour, 'h');\n }\n\n hoursDistribution[entry.spentOn] = start;\n\n const color = this.colors.toHsl(this.entryName(entry));\n\n return this.timeEntry(entry, hours, start, end);\n }) as EventInput[];\n }\n\n private buildAuxEntries(entries:TimeEntryResource[], fetchInfo:{ start:Date, end:Date }) {\n let dateSums = this.calculateDateSums(entries);\n\n let calendarEntries:EventInput[] = [];\n\n for (let m = moment(fetchInfo.start); m.diff(fetchInfo.end, 'days') <= 0; m.add(1, 'days')) {\n let duration = dateSums[m.format('YYYY-MM-DD')] || 0;\n\n calendarEntries.push(this.sumEntry(m, duration));\n\n if (this.memoizedCreateAllowed) {\n calendarEntries.push(this.addEntry(m, duration));\n }\n }\n\n return calendarEntries;\n }\n\n private calculateDateSums(entries:TimeEntryResource[]) {\n let dateSums:{ [key:string]:number } = {};\n\n entries.forEach((entry) => {\n let hours = this.timezone.toHours(entry.hours);\n\n if (dateSums[entry.spentOn]) {\n dateSums[entry.spentOn] += hours;\n } else {\n dateSums[entry.spentOn] = hours;\n }\n });\n\n return dateSums;\n }\n\n protected timeEntry(entry:TimeEntryResource, hours:number, start:Moment, end:Moment) {\n const color = this.colors.toHsl(this.entryName(entry));\n\n let classNames = [TIME_ENTRY_CLASS_NAME];\n\n let span = end.diff(start, 'm');\n\n if (span < 40) {\n classNames.push('-no-fadeout');\n }\n\n return {\n title: span < 20 ? '' : this.entryName(entry),\n startEditable: !!entry.update,\n start: start.format(),\n end: end.format(),\n backgroundColor: color,\n borderColor: color,\n classNames: classNames,\n entry: entry\n };\n }\n\n protected sumEntry(date:Moment, duration:number) {\n return {\n start: date.clone().add(this.maxHour - Math.min(duration * this.scaleRatio, this.maxHour - 0.5) - 0.5, 'h').format(),\n end: date.clone().add(this.maxHour - Math.min(((duration + 0.05) * this.scaleRatio), this.maxHour - 0.5), 'h').format(),\n classNames: DAY_SUM_CLASS_NAME,\n rendering: 'background' as 'background',\n startEditable: false,\n sum: this.i18n.t('js.units.hour', { count: this.formatNumber(duration) })\n };\n }\n\n protected addEntry(date:Moment, duration:number) {\n let classNames = [ADD_ENTRY_CLASS_NAME];\n\n if (duration >= 24) {\n classNames.push(ADD_ENTRY_PROHIBITED_CLASS_NAME);\n }\n\n return {\n start: date.clone().format(),\n end: date.clone().add(this.maxHour - Math.min(duration * this.scaleRatio, this.maxHour - 1) - 0.5, 'h').format(),\n rendering: \"background\" as 'background',\n classNames: classNames\n };\n }\n\n protected dmFilters(start:Date, end:Date):Array<[string, FilterOperator, string[]]> {\n let startDate = moment(start).format('YYYY-MM-DD');\n let endDate = moment(end).subtract(1, 'd').format('YYYY-MM-DD');\n return [['spentOn', '<>d', [startDate, endDate]] as [string, FilterOperator, string[]],\n ['user_id', '=', ['me']] as [string, FilterOperator, [string]]];\n }\n\n private dispatchEventClick(event:CalendarViewEvent) {\n if (event.event.extendedProps.entry) {\n this.editEvent(event.event.extendedProps.entry);\n } else if (event.el.classList.contains(ADD_ENTRY_CLASS_NAME) && !event.el.classList.contains(ADD_ENTRY_PROHIBITED_CLASS_NAME)) {\n this.addEvent(moment(event.event.start!));\n }\n }\n\n private editEvent(entry:TimeEntryResource) {\n this\n .timeEntryEdit\n .edit(entry)\n .then(modificationAction => {\n this.updateEventSet(modificationAction.entry, modificationAction.action);\n })\n .catch(() => {\n // do nothing, the user closed without changes\n });\n }\n\n private moveEvent(event:CalendarMoveEvent) {\n let entry = event.event.extendedProps.entry;\n\n // Use end instead of start as when dragging, the event might be too long and would thus be start\n // on the day before by fullcalendar.\n entry.spentOn = moment(event.event.end!).format('YYYY-MM-DD');\n\n this\n .schemaCache\n .ensureLoaded(entry)\n .then(schema => {\n this\n .apiV3Service\n .time_entries\n .id(entry)\n .patch(entry, schema)\n .subscribe(\n event => this.updateEventSet(event, 'update'),\n e => {\n this.notifications.handleRawError(e);\n event.revert();\n }\n );\n });\n }\n\n public addEventToday() {\n this.addEvent(moment(new Date()));\n }\n\n private addEvent(date:Moment) {\n if (!this.memoizedCreateAllowed) {\n return;\n }\n\n this\n .timeEntryCreate\n .create(date)\n .then(modificationAction => {\n this.updateEventSet(modificationAction.entry, modificationAction.action);\n })\n .catch(() => {\n // do nothing, the user closed without changes\n });\n }\n\n private updateEventSet(event:TimeEntryResource, action:'update'|'destroy'|'create') {\n this.memoizedTimeEntries.entries.then(collection => {\n let foundIndex = collection.elements.findIndex(x => x.id === event.id);\n\n switch (action) {\n case 'update':\n collection.elements[foundIndex] = event;\n break;\n case 'destroy':\n collection.elements.splice(foundIndex, 1);\n break;\n case 'create':\n this\n .apiV3Service\n .time_entries\n .cache\n .updateFor(event);\n\n collection.elements.push(event);\n break;\n }\n\n this.ucCalendar.getApi().refetchEvents();\n });\n }\n\n private alterEventEntry(event:CalendarViewEvent) {\n this.appendAddIcon(event);\n this.appendSum(event);\n\n if (!event.event.extendedProps.entry) {\n return;\n }\n\n this.addTooltip(event);\n this.prependDuration(event);\n this.appendFadeout(event);\n }\n\n private appendAddIcon(event:CalendarViewEvent) {\n if (!event.el.classList.contains(ADD_ENTRY_CLASS_NAME)) {\n return;\n }\n\n let addIcon = document.createElement('div');\n addIcon.classList.add(ADD_ICON_CLASS_NAME);\n addIcon.innerText = '+';\n event.el.append(addIcon);\n }\n\n private appendSum(event:CalendarViewEvent) {\n if (event.event.extendedProps.sum) {\n event.el.innerHTML = event.event.extendedProps.sum;\n }\n }\n\n private addTooltip(event:CalendarViewEvent) {\n if (this.browserDetector.isMobile) {\n return;\n }\n\n jQuery(event.el).tooltip({\n content: this.tooltipContentString(event.event.extendedProps.entry),\n items: '.fc-event',\n close: function () {\n jQuery(\".ui-helper-hidden-accessible\").remove();\n },\n track: true\n });\n }\n\n private removeTooltip(event:CalendarViewEvent) {\n jQuery(event.el).tooltip('disable');\n }\n\n private prependDuration(event:CalendarViewEvent) {\n let timeEntry = event.event.extendedProps.entry;\n\n if (this.timezone.toHours(timeEntry.hours) < 0.5) {\n return;\n }\n\n let formattedDuration = this.timezone.formattedDuration(timeEntry.hours);\n\n jQuery(event.el)\n .find('.fc-event-title')\n .prepend(`
    ${formattedDuration}
    `);\n }\n\n /* Fade out event text to the bottom to avoid it being cut of weirdly.\n * Multiline ellipsis with an unknown height is not possible, hence we blur the text.\n * The gradient needs to take the background color of the element into account (hashed over the event\n * title) which is why the style is set in code.\n *\n * We do not print anything on short entries (< 0.5 hours),\n * which leads to the fc-short class not being applied by full calendar. For other short events, the css rules\n * need to deactivate the fc-fadeout.\n */\n private appendFadeout(event:CalendarViewEvent) {\n let timeEntry = event.event.extendedProps.entry;\n\n if (this.timezone.toHours(timeEntry.hours) < 0.5) {\n return;\n }\n\n let $element = jQuery(event.el);\n let fadeout = jQuery(`
    `);\n\n let hslaStart = this.colors.toHsla(this.entryName(timeEntry), 0);\n let hslaEnd = this.colors.toHsla(this.entryName(timeEntry), 100);\n\n fadeout.css('background', `-webkit-linear-gradient(${hslaStart} 0%, ${hslaEnd} 100%`);\n\n ['-moz-linear-gradient', '-o-linear-gradient', 'linear-gradient', '-ms-linear-gradient'].forEach((style => {\n fadeout.css('background-image', `${style}(${hslaStart} 0%, ${hslaEnd} 100%`);\n }));\n\n $element\n .append(fadeout);\n }\n\n private beforeEventRemove(event:CalendarViewEvent) {\n if (!event.event.extendedProps.entry) {\n return;\n }\n\n this.removeTooltip(event);\n }\n\n private entryName(entry:TimeEntryResource) {\n let name = entry.project.name;\n if (entry.workPackage) {\n name += ` - ${this.workPackageName(entry)}`;\n }\n\n return name || '-';\n }\n\n private workPackageName(entry:TimeEntryResource) {\n return `#${entry.workPackage.idFromLink}: ${entry.workPackage.name}`;\n }\n\n private tooltipContentString(entry:TimeEntryResource) {\n return `\n
      \n
    • \n ${this.i18n.t('js.time_entry.project')}:\n ${this.sanitizedValue(entry.project.name)}\n
    • \n
    • \n ${this.i18n.t('js.time_entry.work_package')}:\n ${entry.workPackage ? this.sanitizedValue(this.workPackageName(entry)) : this.i18n.t('js.placeholders.default')}\n
    • \n
    • \n ${this.i18n.t('js.time_entry.activity')}:\n ${this.sanitizedValue(entry.activity.name)}\n
    • \n
    • \n ${this.i18n.t('js.time_entry.hours')}:\n ${this.timezone.formattedDuration(entry.hours)}\n
    • \n
    • \n ${this.i18n.t('js.time_entry.comment')}:\n ${entry.comment.raw || this.i18n.t('js.placeholders.default')}\n
    • \n `;\n }\n\n private sanitizedValue(value:string) {\n return this.sanitizer.sanitize(SecurityContext.HTML, value);\n }\n\n protected formatNumber(value:number):string {\n return this.i18n.toNumber(value, { precision: 2 });\n }\n\n private smallerSuitableRatio(value:number):number {\n for (let divisor = this.labelIntervalHours + 1; divisor < 100; divisor++) {\n let candidate = this.labelIntervalHours / divisor;\n\n if (value >= candidate) {\n return candidate;\n }\n }\n\n return 1;\n }\n\n protected setHiddenDays(displayedDays:DisplayedDays) {\n let hiddenDays:number[] = Array\n .from(displayedDays, (value, index) => {\n if (!value) {\n return (index + 1) % 7;\n } else {\n return null;\n }\n })\n .filter((value) => value !== null) as number[];\n\n this.calendarOptions = { ...this.calendarOptions, hiddenDays };\n }\n}\n","import {Component, Injector, ChangeDetectionStrategy, ChangeDetectorRef} from \"@angular/core\";\nimport { TimeEntryResource } from 'core-app/modules/hal/resources/time-entry-resource';\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {DisplayedDays} from \"core-app/modules/calendar/te-calendar/te-calendar.component\";\n\n@Component({\n templateUrl: './time-entries-current-user.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WidgetTimeEntriesCurrentUserComponent extends AbstractWidgetComponent {\n public entries:TimeEntryResource[] = [];\n public displayedDays:DisplayedDays;\n\n constructor(protected readonly injector:Injector,\n readonly timezone:TimezoneService,\n readonly i18n:I18nService,\n readonly pathHelper:PathHelperService,\n protected readonly cdr:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n public ngOnInit() {\n this.displayedDays = this.resource.options.days as DisplayedDays;\n }\n\n public updateEntries(entries:CollectionResource) {\n this.entries = entries.elements;\n\n this.cdr.detectChanges();\n }\n\n public get total() {\n let duration = this.entries.reduce((current, entry) => {\n return current + this.timezone.toHours(entry.hours);\n }, 0);\n\n if (duration > 0) {\n return this.i18n.t('js.units.hour', { count: this.formatNumber(duration) });\n } else {\n return this.i18n.t('js.placeholders.default');\n }\n }\n\n public get isEditable() {\n return false;\n }\n\n public updateConfiguration(options:{ days:DisplayedDays }) {\n this.resourceChanged.emit(this.setChangesetOptions(options));\n // Need to copy to trigger change detection\n this.displayedDays = [...options.days] as DisplayedDays;\n }\n\n protected formatNumber(value:number):string {\n return this.i18n.toNumber(value, { precision: 2 });\n }\n}\n","\n\n \n \n\n\n\n\n\n
      \n

      Total:

      \n
      \n
      \n","import {Injectable} from \"@angular/core\";\nimport {WidgetRegistration} from \"app/modules/grids/grid/grid.component\";\nimport {HookService} from \"app/modules/plugins/hook-service\";\n\n@Injectable()\nexport class GridWidgetsService {\n constructor(private Hook:HookService) {}\n\n public get registered() {\n let registeredWidgets:WidgetRegistration[] = [];\n\n _.each(this.Hook.call('gridWidgets'), (registration:WidgetRegistration[]) => {\n registeredWidgets = registeredWidgets.concat(registration);\n });\n\n return registeredWidgets;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ViewChild} from '@angular/core';\nimport {WorkPackagesViewBase} from \"core-app/modules/work_packages/routing/wp-view-base/work-packages-view.base\";\nimport {WorkPackagesCalendarController} from \"core-app/modules/calendar/wp-calendar/wp-calendar.component\";\n\n@Component({\n templateUrl: './wp-calendar-entry.component.html'\n})\n\nexport class WorkPackagesCalendarEntryComponent extends WorkPackagesViewBase {\n @ViewChild(WorkPackagesCalendarController, { static: true }) calendarElement:WorkPackagesCalendarController;\n\n protected set loadingIndicator(promise:Promise) {\n this.loadingIndicatorService.indicator('calendar-entry').promise = promise;\n }\n\n public refresh(visibly:boolean, firstPage:boolean):Promise {\n return this.loadingIndicator =\n this.wpListService.loadCurrentQueryFromParams(this.projectIdentifier!);\n }\n}\n","
      \n
      \n
      \n
      \n

      \n {{ I18n.t('js.calendar.title') }}\n

      \n
      \n\n
        \n
      • \n \n \n
      • \n
      • \n \n \n
      • \n
      \n
      \n
      \n\n \n\n \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpenprojectCommonModule} from 'core-app/modules/common/openproject-common.module';\nimport {NgModule} from '@angular/core';\nimport {OpenprojectFieldsModule} from \"core-app/modules/fields/openproject-fields.module\";\nimport {TimeEntryCreateModal} from \"core-app/modules/time_entries/create/create.modal\";\nimport {TimeEntryEditModal} from \"core-app/modules/time_entries/edit/edit.modal\";\nimport {TimeEntryFormComponent} from \"core-app/modules/time_entries/form/form.component\";\nimport {TimeEntryEditService} from \"core-app/modules/time_entries/edit/edit.service\";\nimport {TriggerActionsEntryComponent} from \"core-app/modules/time_entries/edit/trigger-actions-entry.component\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\n\n@NgModule({\n imports: [\n // Commons\n OpenprojectCommonModule,\n\n // Editable fields e.g. for modals\n OpenprojectFieldsModule,\n ],\n providers: [\n TimeEntryEditService\n ],\n declarations: [\n TimeEntryEditModal,\n TimeEntryCreateModal,\n TimeEntryFormComponent,\n TriggerActionsEntryComponent\n ]\n})\nexport class OpenprojectTimeEntriesModule {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpenprojectCommonModule} from 'core-app/modules/common/openproject-common.module';\nimport {NgModule} from '@angular/core';\nimport {FullCalendarModule} from '@fullcalendar/angular';\nimport {WorkPackagesCalendarEntryComponent} from \"core-app/modules/calendar/wp-calendar-entry/wp-calendar-entry.component\";\nimport {WorkPackagesCalendarController} from \"core-app/modules/calendar/wp-calendar/wp-calendar.component\";\nimport {OpenprojectWorkPackagesModule} from \"core-app/modules/work_packages/openproject-work-packages.module\";\nimport {Ng2StateDeclaration, UIRouterModule} from \"@uirouter/angular\";\nimport {TimeEntryCalendarComponent} from \"core-app/modules/calendar/te-calendar/te-calendar.component\";\nimport {OpenprojectFieldsModule} from \"core-app/modules/fields/openproject-fields.module\";\nimport {OpenprojectTimeEntriesModule} from \"core-app/modules/time_entries/openproject-time-entries.module\";\n\nconst menuItemClass = 'calendar-menu-item';\n\nexport const CALENDAR_ROUTES:Ng2StateDeclaration[] = [\n {\n name: 'work-packages.calendar',\n url: '/calendar',\n component: WorkPackagesCalendarEntryComponent,\n reloadOnSearch: false,\n data: {\n bodyClasses: 'router--work-packages-calendar',\n menuItem: menuItemClass,\n parent: 'work-packages'\n }\n }\n];\n\n@NgModule({\n imports: [\n // Commons\n OpenprojectCommonModule,\n\n // Routes for /work_packages/calendar\n UIRouterModule.forChild({ states: CALENDAR_ROUTES }),\n\n // Work Package module\n OpenprojectWorkPackagesModule,\n\n // Time entry module\n OpenprojectTimeEntriesModule,\n\n // Editable fields e.g. for modals\n OpenprojectFieldsModule,\n\n // Calendar component\n FullCalendarModule,\n ],\n declarations: [\n // Work package calendars\n WorkPackagesCalendarEntryComponent,\n WorkPackagesCalendarController,\n TimeEntryCalendarComponent,\n ],\n exports: [\n WorkPackagesCalendarController,\n TimeEntryCalendarComponent,\n ]\n})\nexport class OpenprojectCalendarModule {\n}\n","\n\n \n \n\n\n
      \n \n \n \n

      \n \n \n

      \n

      \n \n

      \n\n
      \n
      \n
      \n
      \n","import {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {Component, OnInit, SecurityContext, ChangeDetectionStrategy, ChangeDetectorRef, Injector} from '@angular/core';\nimport {DocumentResource} from \"../../../../../../../modules/documents/frontend/module/hal/resources/document-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {DomSanitizer} from '@angular/platform-browser';\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './documents.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WidgetDocumentsComponent extends AbstractWidgetComponent implements OnInit {\n public text = {\n noResults: this.i18n.t('js.grid.widgets.documents.no_results'),\n };\n\n public entries:DocumentResource[] = [];\n private entriesLoaded = false;\n\n constructor(readonly halResource:HalResourceService,\n readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly i18n:I18nService,\n readonly timezone:TimezoneService,\n readonly domSanitizer:DomSanitizer,\n protected readonly injector:Injector,\n readonly currentProject:CurrentProjectService,\n readonly cdr:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.halResource\n .get(this.documentsUrl)\n .toPromise()\n .then((collection) => {\n this.entries = collection.elements as DocumentResource[];\n this.entriesLoaded = true;\n\n this.cdr.detectChanges();\n });\n }\n\n public get isEditable() {\n return false;\n }\n\n public documentPath(document:DocumentResource) {\n return `${this.pathHelper.appBasePath}/documents/${document.id}`;\n }\n\n public documentCreated(document:DocumentResource) {\n return this.timezone.formattedDatetime(document.createdAt);\n }\n\n public documentDescription(document:DocumentResource) {\n return this.domSanitizer.sanitize(SecurityContext.HTML, document.description.html);\n }\n\n public get noEntries() {\n return !this.entries.length && this.entriesLoaded;\n }\n\n public get documentsUrl() {\n let orders = JSON.stringify([['updated_at', 'desc']]);\n\n let url = this.apiV3Service.documents.toPath() + `?sortBy=${orders}&pageSize=10`;\n\n if (this.currentProject.id) {\n let filters = JSON.stringify([{project_id: { operator: '=', values: [this.currentProject.id.toString()]}}]);\n\n url = url + `&filters=${filters}`;\n }\n\n return url;\n }\n}\n","\n\n \n \n\n\n
      \n \n \n
        \n
      • \n
        \n \n \n
        \n \n :\n \n \n
        \n
        \n \n
        \n
        \n

        \n
        \n
        \n
      • \n
      \n
      ","import { AbstractWidgetComponent } from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport { ChangeDetectionStrategy, Component, Injector, OnInit, ChangeDetectorRef } from '@angular/core';\nimport { I18nService } from \"core-app/modules/common/i18n/i18n.service\";\nimport { PathHelperService } from \"core-app/modules/common/path-helper/path-helper.service\";\nimport { TimezoneService } from \"core-components/datetime/timezone.service\";\nimport { NewsResource } from \"core-app/modules/hal/resources/news-resource\";\nimport { CurrentProjectService } from \"core-components/projects/current-project.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3ListParameters} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\n\n@Component({\n templateUrl: './news.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WidgetNewsComponent extends AbstractWidgetComponent implements OnInit {\n public text = {\n at: this.i18n.t('js.grid.widgets.news.at'),\n noResults: this.i18n.t('js.grid.widgets.news.no_results'),\n addedBy: (news:NewsResource) => this.i18n.t('js.label_added_time_by',\n { author: this.newsAuthorName(news), age: this.newsCreated(news), authorLink: this.newsAuthorPath(news)})\n };\n\n public entries:NewsResource[] = [];\n private entriesLoaded = false;\n\n constructor(\n\n readonly pathHelper:PathHelperService,\n readonly i18n:I18nService,\n protected readonly injector:Injector,\n readonly timezone:TimezoneService,\n readonly currentProject:CurrentProjectService,\n readonly apiV3Service:APIV3Service,\n readonly cdr:ChangeDetectorRef\n ) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .news\n .list(this.newsDmParams)\n .subscribe(collection => this.setupNews(collection.elements));\n }\n\n public setupNews(news:any[]) {\n\n this.entries = news;\n this.entriesLoaded = true;\n this.cdr.detectChanges();\n }\n\n public get isEditable() {\n return false;\n }\n\n public newsPath(news:NewsResource) {\n\n return this.pathHelper.newsPath(news.id!);\n }\n\n public newsProjectPath(news:NewsResource) {\n return this.pathHelper.projectPath(news.project?.idFromLink);\n }\n\n public newsProjectName(news:NewsResource) {\n return news.project?.name;\n }\n\n public newsAuthorName(news:NewsResource) {\n return news.author?.name;\n }\n\n public newsAuthorPath(news:NewsResource) {\n return this.pathHelper.userPath(news.author?.id);\n\n }\n\n public newsCreated(news:NewsResource) {\n return this.timezone.formattedDatetime(news.createdAt);\n }\n\n public get noEntries() {\n return !this.entries.length && this.entriesLoaded;\n }\n\n private get newsDmParams() {\n let params:Apiv3ListParameters = {\n sortBy: [['created_at', 'desc']],\n pageSize: 3\n };\n\n if (this.currentProject.id) {\n params['filters'] = [['project_id', '=', [this.currentProject.id]]];\n }\n\n return params;\n }\n}\n","import {Injectable} from '@angular/core';\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {switchMap} from \"rxjs/operators\";\n\n@Injectable()\nexport class GridInitializationService {\n constructor(readonly apiV3Service:APIV3Service,\n readonly halResourceService:HalResourceService) {\n }\n\n // If a page with the current page exists (scoped to the current user by the backend)\n // that page will be used to initialized the grid.\n // If it does not exist, fetch the form and then create a new resource.\n // The created resource is then used to initialize the grid.\n public initialize(path:string) {\n return this\n .apiV3Service\n .grids\n .list({ filters: [['scope', '=', [path]]] })\n .toPromise()\n .then(collection => {\n if (collection.total === 0) {\n return this.myPageForm(path);\n } else {\n return (collection.elements[0] as GridResource);\n }\n });\n }\n\n private myPageForm(path:string):Promise {\n let payload = {\n '_links': {\n 'scope': {\n 'href': path\n }\n }\n };\n\n return this\n .apiV3Service\n .grids\n .form\n .post(payload)\n .pipe(\n switchMap(form => {\n let source = form.payload.$source;\n let resource = this.halResourceService.createHalResource(source) as GridResource;\n\n if (resource.widgets.length === 0) {\n resource.rowCount = 1;\n resource.columnCount = 1;\n }\n\n return this\n .apiV3Service\n .grids\n .post(resource, form.schema);\n })\n )\n .toPromise();\n }\n}\n","import {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {Component, ViewChild} from \"@angular/core\";\n\n@Component({\n templateUrl: './settings-tab.component.html'\n})\nexport class WpGraphConfigurationSettingsTab implements TabComponent {\n @ViewChild('tabInner', { static: true })\n tabInner:TabComponent;\n\n public onSave() {\n this.tabInner.onSave();\n }\n}\n","\n \n\n\n","import {Component, ViewChild} from '@angular/core';\nimport {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\n\n@Component({\n templateUrl: './filters-tab.component.html'\n})\nexport class WpGraphConfigurationFiltersTab implements TabComponent {\n @ViewChild('tabInner', { static: true })\n tabInner:TabComponent;\n\n public onSave() {\n this.tabInner.onSave();\n }\n}\n","\n \n\n","import {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {ChartType, ChartOptions} from 'chart.js';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\nexport interface WpGraphQueryParams {\n id?:string;\n props?:any;\n name?:string;\n}\n\nexport interface WpGraphConfiguration {\n queries:QueryResource[];\n queryParams:WpGraphQueryParams[];\n chartType:ChartType;\n chartOptions:ChartOptions;\n}\n\nexport class WpGraphConfiguration implements WpGraphConfiguration {\n public queries:QueryResource[] = [];\n\n constructor(public queryParams:WpGraphQueryParams[],\n public chartOptions:ChartOptions,\n public chartType:ChartType) {\n this.chartType = this.chartType || 'horizontalBar';\n }\n\n public static queryCreationParams(i18n:I18nService, is_public:boolean) {\n return {\n hidden: true,\n public: is_public,\n name: i18n.t('js.grid.widgets.work_packages_graph.title'),\n showHierarchies: false,\n _links: {\n groupBy: {\n href: \"/api/v3/queries/group_bys/status\"\n }\n }\n };\n }\n}\n","import {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WpGraphConfigurationSettingsTab} from \"core-app/modules/work-package-graphs/configuration-modal/tabs/settings-tab.component\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {TabInterface} from \"core-components/wp-table/configuration-modal/tab-portal-outlet\";\nimport {Injectable} from '@angular/core';\nimport {WpGraphConfigurationFiltersTab} from \"core-app/modules/work-package-graphs/configuration-modal/tabs/filters-tab.component\";\nimport {ChartType} from 'chart.js';\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {\n WpGraphConfiguration,\n WpGraphQueryParams\n} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WpGraphConfigurationService {\n\n private _configuration:WpGraphConfiguration;\n private _forms:{[id:string]:QueryFormResource} = {};\n private _formsPromise:Promise|null;\n\n constructor(readonly I18n:I18nService,\n readonly apiv3Service:APIV3Service,\n readonly notificationService:WorkPackageNotificationService,\n readonly currentProject:CurrentProjectService) {\n }\n\n public persistAndReload() {\n return new Promise((resolve, reject) => {\n this.persistChanges().then(() => {\n this.reloadQueries().then(() => resolve());\n });\n });\n }\n\n public persistChanges() {\n let promises = this.queries.map(query => {\n return this.saveQuery(query);\n });\n\n return Promise.all(promises);\n }\n\n public get datasets() {\n return this.queries.map(query => {\n return {\n groups: query.results.groups,\n queryProps: '',\n label: query.name\n };\n });\n }\n\n public reloadQueries() {\n this.configuration.queries.length = 0;\n\n return this.loadQueries();\n }\n\n public ensureQueryAndLoad() {\n if (this.queryParams.length === 0) {\n return this.createInitial()\n .then((query) => {\n this.queryParams.push({id: query.id!});\n\n return this.loadQueries();\n });\n } else {\n return this.loadQueries();\n }\n }\n\n private createInitial():Promise {\n return this\n .apiv3Service\n .queries\n .form\n .loadWithParams(\n {pageSize: 0},\n undefined,\n this.currentProject.identifier,\n WpGraphConfiguration.queryCreationParams(this.I18n, !!this.currentProject.identifier)\n )\n .toPromise()\n .then(([form, query]) => {\n return this\n .apiv3Service\n .queries\n .post(query, form)\n .toPromise();\n });\n }\n\n private loadQueries() {\n let queryPromises = this.queryParams.map(queryParam => {\n return this.loadQuery(queryParam);\n });\n\n return Promise.all(queryPromises);\n }\n\n private loadQuery(params:WpGraphQueryParams) {\n return this\n .apiv3Service\n .queries\n .find(\n Object.assign({pageSize: 0}, params.props),\n params.id,\n this.currentProject.identifier,\n )\n .toPromise()\n .then(query => {\n if (params.name) {\n query.name = params.name;\n }\n this.configuration.queries.push(query);\n });\n }\n\n private async saveQuery(query:QueryResource) {\n return this.formFor(query)\n .then(form => {\n return this\n .apiv3Service\n .queries\n .id(query)\n .patch(query, form)\n .toPromise();\n });\n }\n\n public get configuration() {\n return this._configuration;\n }\n\n public set configuration(config:WpGraphConfiguration) {\n this._configuration = config;\n this._formsPromise = null;\n }\n\n public async formFor(query:QueryResource) {\n return this\n .loadForms()\n .then(() => {\n return this._forms[query.id!];\n });\n }\n\n public get tabs() {\n let tabs:TabInterface[] = [\n {\n name: 'graph-settings',\n title: this.I18n.t('js.chart.tabs.graph_settings'),\n componentClass: WpGraphConfigurationSettingsTab,\n }\n ];\n\n let queryTabs = this.configuration.queries.map((query) => {\n return {\n name: query.id as string,\n title: this.I18n.t('js.work_packages.query.filters'),\n componentClass: WpGraphConfigurationFiltersTab\n };\n });\n\n return tabs.concat(queryTabs);\n }\n\n public loadForms() {\n if (!this._formsPromise) {\n let formPromises = this.configuration.queries.map((query) => {\n return this\n .apiv3Service\n .queries\n .form\n .load(query)\n .toPromise()\n .then(([form, _]) => {\n this._forms[query.id as string] = form;\n })\n .catch((error) => this.notificationService.handleRawError(error));\n });\n\n this._formsPromise = Promise.all(formPromises);\n }\n\n return this._formsPromise;\n }\n\n public get chartType() {\n return this._configuration.chartType;\n }\n\n public set chartType(type:ChartType) {\n this._configuration.chartType = type;\n }\n\n public get queries() {\n return this._configuration.queries;\n }\n\n public get chartOptions() {\n return this._configuration.chartOptions;\n }\n\n public get queryParams() {\n return this._configuration.queryParams;\n }\n}\n","import {\n ApplicationRef,\n ChangeDetectorRef,\n Component,\n ComponentFactoryResolver,\n ElementRef,\n Inject,\n InjectionToken,\n Injector,\n OnDestroy,\n OnInit,\n Optional,\n ViewChild\n} from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {\n ActiveTabInterface,\n TabComponent,\n TabInterface,\n TabPortalOutlet\n} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {ComponentType} from \"@angular/cdk/portal\";\nimport {WpGraphConfigurationService} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration.service\";\nimport {WpGraphConfiguration} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\nexport const WpTableConfigurationModalPrependToken = new InjectionToken>('WpTableConfigurationModalPrependComponent');\n\n@Component({\n templateUrl: '../../../components/wp-table/configuration-modal/wp-table-configuration.modal.html',\n})\nexport class WpGraphConfigurationModalComponent extends OpModalComponent implements OnInit, OnDestroy {\n\n /* Close on escape? */\n public closeOnEscape = false;\n\n /* Close on outside click */\n public closeOnOutsideClick = false;\n\n public $element:JQuery;\n\n public text = {\n title: this.I18n.t('js.chart.modal_title'),\n closePopup: this.I18n.t('js.close_popup_title'),\n\n applyButton: this.I18n.t('js.modals.button_apply'),\n cancelButton: this.I18n.t('js.modals.button_cancel'),\n };\n\n public configuration:WpGraphConfiguration;\n\n // Get the view child we'll use as the portal host\n @ViewChild('tabContentOutlet', { static: true }) tabContentOutlet:ElementRef;\n // And a reference to the actual portal host interface\n public tabPortalHost:TabPortalOutlet;\n\n constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n @Optional() @Inject(WpTableConfigurationModalPrependToken) public prependModalComponent:ComponentType|null,\n readonly I18n:I18nService,\n readonly injector:Injector,\n readonly appRef:ApplicationRef,\n readonly componentFactoryResolver:ComponentFactoryResolver,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly notificationService:WorkPackageNotificationService,\n readonly cdRef:ChangeDetectorRef,\n readonly ConfigurationService:ConfigurationService,\n readonly elementRef:ElementRef,\n readonly graphConfiguration:WpGraphConfigurationService) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.loadingIndicator.indicator('modal').promise = this.graphConfiguration.loadForms()\n .then(() => {\n this.tabPortalHost = new TabPortalOutlet(\n this.graphConfiguration.tabs,\n this.tabContentOutlet.nativeElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n\n const initialTab = this.locals['initialTab'] || this.availableTabs[0].name;\n this.switchTo(initialTab);\n });\n }\n\n ngOnDestroy() {\n this.tabPortalHost.dispose();\n }\n\n public get availableTabs():TabInterface[] {\n return this.tabPortalHost.availableTabs;\n }\n\n public get currentTab():ActiveTabInterface|null {\n return this.tabPortalHost.currentTab;\n }\n\n public switchTo(name:string) {\n this.tabPortalHost.switchTo(name);\n }\n\n public saveChanges():void {\n this.tabPortalHost.activeComponents.forEach((component:TabComponent) => {\n component.onSave();\n });\n\n this.configuration = this.graphConfiguration.configuration;\n\n this.service.close();\n }\n\n /**\n * Called when the user attempts to close the modal window.\n * The service will close this modal if this method returns true\n * @returns {boolean}\n */\n public onClose():boolean {\n this.afterFocusOn.focus();\n return true;\n }\n\n protected get afterFocusOn():JQuery {\n return this.$element;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport { Injector, EventEmitter, Output, Directive } from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {GridRemoveWidgetService} from \"core-app/modules/grids/grid/remove-widget.service\";\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {ComponentType} from '@angular/cdk/portal';\nimport {WidgetAbstractMenuComponent} from \"core-app/modules/grids/widgets/menu/widget-abstract-menu.component\";\nimport {WpGraphConfigurationModalComponent} from \"core-app/modules/work-package-graphs/configuration-modal/wp-graph-configuration.modal\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\n\n@Directive()\nexport abstract class WidgetWpSetMenuComponent extends WidgetAbstractMenuComponent {\n protected configurationComponent:ComponentType;\n\n @Output()\n onConfigured:EventEmitter = new EventEmitter();\n\n protected menuItemList = [\n this.removeItem,\n this.configureItem\n ];\n\n constructor(private readonly injector:Injector,\n private readonly opModalService:OpModalService,\n readonly i18n:I18nService,\n protected readonly remove:GridRemoveWidgetService,\n readonly layout:GridAreaService) {\n super(i18n,\n remove,\n layout);\n }\n\n protected get configureItem() {\n return {\n linkText: this.i18n.t('js.toolbar.settings.configure_view'),\n onClick: () => {\n this.opModalService.show(this.configurationComponent, this.injector, this.locals)\n .closingEvent.subscribe((modal:WpGraphConfigurationModalComponent) => {\n this.onConfigured.emit(modal.configuration);\n });\n return true;\n }\n };\n }\n\n protected get locals() {\n return {};\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from '@angular/core';\nimport {WpGraphConfigurationModalComponent} from \"core-app/modules/work-package-graphs/configuration-modal/wp-graph-configuration.modal\";\nimport {WidgetWpSetMenuComponent} from \"core-app/modules/grids/widgets/menu/wp-set-menu.component\";\n\n@Component({\n selector: 'widget-wp-graph-menu',\n templateUrl: '../menu/widget-menu.component.html'\n})\nexport class WidgetWpGraphMenuComponent extends WidgetWpSetMenuComponent {\n protected configurationComponent = WpGraphConfigurationModalComponent;\n}\n","
      \n \n \n \n \n
      \n\n","import {Component, Input, SimpleChanges} from '@angular/core';\nimport {WorkPackageTableConfiguration} from 'core-components/wp-table/wp-table-configuration';\nimport {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {ChartOptions, ChartType} from 'chart.js';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\nexport interface WorkPackageEmbeddedGraphDataset {\n label:string;\n queryProps:any;\n queryId?:number|string;\n groups?:GroupObject[];\n}\ninterface ChartDataSet {\n label:string;\n data:number[];\n}\n\n@Component({\n selector: 'wp-embedded-graph',\n templateUrl: './wp-embedded-graph.html',\n styleUrls: ['./wp-embedded-graph.component.sass'],\n})\nexport class WorkPackageEmbeddedGraphComponent {\n @Input() public datasets:WorkPackageEmbeddedGraphDataset[];\n @Input('chartOptions') public inputChartOptions:ChartOptions;\n @Input('chartType') chartType:ChartType = 'horizontalBar';\n\n public configuration:WorkPackageTableConfiguration;\n public error:string|null = null;\n\n public chartHeight = '100%';\n public chartLabels:string[] = [];\n public chartData:ChartDataSet[] = [];\n public chartOptions:ChartOptions;\n public initialized = false;\n\n public text = {\n noResults: this.i18n.t('js.work_packages.no_results.title'),\n };\n\n constructor(readonly i18n:I18nService) {}\n\n ngOnChanges(changes:SimpleChanges) {\n if (changes.datasets) {\n this.setChartOptions();\n this.updateChartData();\n\n\n if (!changes.datasets.firstChange) {\n this.initialized = true;\n }\n } else if (changes.chartType) {\n this.setChartOptions();\n }\n }\n\n private updateChartData() {\n let uniqLabels = _.uniq(this.datasets.reduce((array, dataset) => {\n let groups = (dataset.groups || []).map((group) => group.value) as any;\n return array.concat(groups);\n }, [])) as string[];\n\n let labelCountMaps = this.datasets.map((dataset) => {\n let countMap = (dataset.groups || []).reduce((hash, group) => {\n hash[group.value] = group.count;\n return hash;\n }, {} as any);\n\n return {\n label: dataset.label,\n data: uniqLabels.map((label) => { return countMap[label] || 0; })\n };\n });\n\n uniqLabels = uniqLabels.map((label) => {\n if (!label) {\n return this.i18n.t('js.placeholders.default');\n } else {\n return label;\n }\n });\n\n this.setHeight();\n\n // keep the array in order to update the labels\n this.chartLabels.length = 0;\n this.chartLabels.push(...uniqLabels);\n this.chartData.length = 0;\n this.chartData.push(...labelCountMaps);\n }\n\n protected setChartOptions() {\n let defaults = {\n responsive: true,\n maintainAspectRatio: false,\n legend: {\n // Only display legends if more than one dataset is provided.\n display: this.datasets.length > 1\n },\n plugins: {\n datalabels: {\n align: this.chartType === 'bar' ? 'top' : 'center',\n }\n }\n };\n\n let chartTypeDefaults:ChartOptions = {scales:{}};\n if (this.chartType === 'horizontalBar' || this.chartType === 'bar' ) {\n this.setChartAxesValues(chartTypeDefaults);\n }\n\n this.chartOptions = Object.assign({}, defaults, chartTypeDefaults, this.inputChartOptions);\n }\n\n public get hasDataToDisplay() {\n return this.chartData.length > 0 && this.chartData.some(set => set.data.length > 0);\n }\n\n private setHeight() {\n if (this.chartType === 'horizontalBar' && this.datasets && this.datasets[0]) {\n let labels:string[] = [];\n this.datasets.forEach(d => d.groups!.forEach(g => {\n if (!labels.includes(g.value)) {\n labels.push(g.value);\n }\n }));\n let height = labels.length * 40;\n\n if (this.datasets.length > 1) {\n // make some more room for the legend\n height += 40;\n }\n\n // some minimum height e.g. for the labels\n height += 40;\n\n this.chartHeight = `${height}px`;\n } else {\n this.chartHeight = '100%';\n }\n }\n\n // function to set ticks of axis\n private setChartAxesValues(chartOptions:ChartOptions) {\n\n let changeableValuesAxis = [{\n stacked: true,\n ticks: {\n callback: (value:number) => {\n if (Math.floor(value) === value) {\n return value;\n } else {\n return null;\n }\n }\n }\n }];\n\n let constantValuesAxis = [{\n stacked: true\n }];\n\n if (chartOptions.scales) {\n if (this.chartType === 'bar') {\n chartOptions.scales.yAxes = changeableValuesAxis;\n chartOptions.scales.xAxes = constantValuesAxis;\n } else if (this.chartType === 'horizontalBar') {\n chartOptions.scales.xAxes = changeableValuesAxis;\n chartOptions.scales.yAxes = constantValuesAxis;\n }\n }\n }\n}\n","import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, OnDestroy, OnInit} from '@angular/core';\nimport {WorkPackageEmbeddedGraphDataset} from \"core-app/modules/work-package-graphs/embedded/wp-embedded-graph.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {ChartOptions, ChartType} from 'chart.js';\nimport {WpGraphConfigurationService} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration.service\";\nimport {WpGraphConfiguration} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration\";\n\n@Component({\n selector: 'widget-wp-graph',\n templateUrl: './wp-graph.component.html',\n styleUrls: ['../wp-table/wp-table.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [WpGraphConfigurationService]\n})\nexport class WidgetWpGraphComponent extends AbstractWidgetComponent implements OnInit, OnDestroy {\n public datasets:WorkPackageEmbeddedGraphDataset[] = [];\n\n constructor(protected i18n:I18nService,\n protected injector:Injector,\n protected cdr:ChangeDetectorRef,\n protected readonly graphConfiguration:WpGraphConfigurationService) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.initializeConfiguration();\n this.loadQueriesInitially();\n }\n\n public set chartType(type:ChartType) {\n this.resource.options.chartType = type;\n }\n\n public updateGraph(config:any) {\n this.graphConfiguration.persistAndReload()\n .then(() => {\n this.repaint();\n\n if (this.resource.options.chartType !== this.graphConfiguration.chartType) {\n let changeset = this.setChangesetOptions({ chartType: this.graphConfiguration.chartType });\n\n this.resourceChanged.emit(changeset);\n }\n });\n }\n\n protected repaint() {\n this.datasets = this.graphConfiguration.datasets;\n this.cdr.detectChanges();\n }\n\n protected initializeConfiguration() {\n let ids = [];\n if (this.resource.options.queryId) {\n ids.push({ id: this.resource.options.queryId as string });\n }\n\n this.graphConfiguration.configuration = new WpGraphConfiguration(ids,\n this.resource.options.chartOptions as ChartOptions,\n this.resource.options.chartType as ChartType);\n }\n\n protected loadQueriesInitially() {\n this.graphConfiguration.ensureQueryAndLoad()\n .then(() => {\n if (!this.resource.options.queryId) {\n let changeset = this.setChangesetOptions({ queryId: this.graphConfiguration.queryParams[0].id });\n\n this.resourceChanged.emit(changeset);\n }\n this.repaint();\n });\n }\n\n public get chartOptions() {\n return this.graphConfiguration.chartOptions;\n }\n\n public get chartType() {\n return this.graphConfiguration.chartType;\n }\n}\n","\n\n \n \n\n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from '@angular/core';\nimport {WpTableConfigurationModalComponent} from \"core-components/wp-table/configuration-modal/wp-table-configuration.modal\";\nimport {WidgetWpSetMenuComponent} from \"core-app/modules/grids/widgets/menu/wp-set-menu.component\";\n\n@Component({\n selector: 'widget-wp-table-menu',\n templateUrl: '../menu/widget-menu.component.html',\n})\nexport class WidgetWpTableMenuComponent extends WidgetWpSetMenuComponent {\n protected configurationComponent = WpTableConfigurationModalComponent;\n}\n","\n \n \n\n\n\n\n","import {ChangeDetectionStrategy, Component, Injector} from '@angular/core';\nimport {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {WorkPackageTableConfiguration} from \"core-components/wp-table/wp-table-configuration\";\nimport {Observable} from 'rxjs';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {StateService} from '@uirouter/core';\nimport {finalize, publish, skip} from 'rxjs/operators';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'widget-wp-table',\n templateUrl: './wp-table.component.html',\n styleUrls: ['./wp-table.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WidgetWpTableComponent extends AbstractWidgetComponent {\n public queryId:string|null;\n private queryForm:QueryFormResource;\n public inFlight = false;\n public query$:Observable;\n\n public configuration:Partial = {\n actionsColumnEnabled: false,\n columnMenuEnabled: false,\n hierarchyToggleEnabled: true,\n contextMenuEnabled: false\n };\n\n constructor(protected i18n:I18nService,\n protected readonly injector:Injector,\n protected urlParamsHelper:UrlParamsHelperService,\n protected readonly state:StateService,\n protected readonly querySpace:IsolatedQuerySpace,\n protected readonly apiV3Service:APIV3Service) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n if (!this.resource.options.queryId) {\n this.createInitial()\n .then((query) => {\n let changeset = this.setChangesetOptions({ queryId: query.id });\n\n this.resourceChanged.emit(changeset);\n\n this.queryId = query.id;\n });\n } else {\n this.queryId = this.resource.options.queryId as string;\n }\n\n this.query$ = this\n .querySpace\n .query\n .values$();\n\n this.query$\n .pipe(\n // 2 because ... well it is a magic number and works\n skip(2),\n this.untilDestroyed()\n ).subscribe((query) => {\n this.ensureFormAndSaveQuery(query);\n });\n }\n\n public get widgetName() {\n return this.resource.options.name as string;\n }\n\n public static get identifier():string {\n return 'work_packages_table';\n }\n\n private ensureFormAndSaveQuery(query:QueryResource) {\n if (this.queryForm) {\n this.saveQuery(query, this.queryForm);\n } else {\n this\n .apiV3Service\n .queries\n .form\n .load(query)\n .subscribe(([form, _]) => {\n this.queryForm = form;\n this.saveQuery(query, form);\n });\n }\n }\n\n private saveQuery(query:QueryResource, form:QueryFormResource) {\n this.inFlight = true;\n\n this\n .apiV3Service\n .queries\n .id(query)\n .patch(query, this.queryForm)\n .subscribe(\n () => this.inFlight = false,\n () => this.inFlight = false,\n );\n }\n\n private createInitial():Promise {\n const projectIdentifier = this.state.params['projectPath'];\n let initializationProps = this.resource.options.queryProps;\n let queryProps = Object.assign({ pageSize: 0 }, initializationProps);\n\n return this\n .apiV3Service\n .queries\n .form\n .loadWithParams(\n queryProps,\n undefined,\n projectIdentifier,\n this.queryCreationParams()\n )\n .toPromise()\n .then(([form, query]) => {\n return this\n .apiV3Service\n .queries\n .post(query, form)\n .toPromise()\n .then((query) => {\n delete this.resource.options.queryProps;\n\n return query;\n });\n });\n }\n\n protected queryCreationParams() {\n // On the MyPage, the queries should be non public, on a project dashboard, they should be public.\n // This will not longer work, when global dashboards are implemented as the tables then need to\n // be public as well.\n const projectIdentifier = this.state.params['projectPath'];\n\n return {\n hidden: true,\n public: !!projectIdentifier\n };\n }\n}\n","import {Component} from '@angular/core';\nimport {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {WidgetChangeset} from \"core-app/modules/grids/widgets/widget-changeset\";\n\n@Component({\n templateUrl: './wp-table-qs.component.html',\n styleUrls: ['./wp-table-qs.component.sass'],\n})\nexport class WidgetWpTableQuerySpaceComponent extends AbstractWidgetComponent {\n public onResourceChanged(changeset:WidgetChangeset) {\n this.resourceChanged.emit(changeset);\n }\n}\n","\n \n\n","import {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageStatesInitializationService} from \"core-components/wp-list/wp-states-initialization.service\";\nimport {WpGraphConfigurationService} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration.service\";\n\nexport abstract class QuerySpacedTabComponent {\n constructor(readonly I18n:I18nService,\n readonly wpStatesInitialization:WorkPackageStatesInitializationService,\n readonly wpGraphConfiguration:WpGraphConfigurationService) {\n }\n\n protected initializeQuerySpace() {\n return this\n .wpGraphConfiguration\n .formFor(this.query)\n .then(form => {\n this.wpStatesInitialization.initialize(this.query, this.query.results);\n this.wpStatesInitialization.updateStatesFromForm(this.query, form);\n });\n }\n\n protected abstract get query():QueryResource;\n}\n","\n","import {Component} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {WorkPackageFiltersService} from 'core-components/filters/wp-filters/wp-filters.service';\nimport {WorkPackageViewFiltersService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service';\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {WpGraphConfigurationService} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration.service\";\nimport {WorkPackageStatesInitializationService} from \"core-components/wp-list/wp-states-initialization.service\";\nimport {QuerySpacedTabComponent} from \"core-app/modules/work-package-graphs/configuration-modal/tabs/abstract-query-spaced-tab.component\";\n\n@Component({\n selector: 'filters-tab-inner',\n templateUrl: './filters-tab-inner.component.html',\n})\nexport class WpGraphConfigurationFiltersTabInner extends QuerySpacedTabComponent implements TabComponent {\n public filters:QueryFilterInstanceResource[] = [];\n\n public text = {\n multiSelectLabel: this.I18n.t('js.work_packages.label_column_multiselect'),\n };\n\n constructor(readonly I18n:I18nService,\n readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly wpFiltersService:WorkPackageFiltersService,\n readonly wpStatesInitialization:WorkPackageStatesInitializationService,\n readonly wpGraphConfiguration:WpGraphConfigurationService) {\n super(I18n, wpStatesInitialization, wpGraphConfiguration);\n }\n\n ngOnInit() {\n this.initializeQuerySpace()\n .then(() => {\n this.wpTableFilters\n .onReady()\n .then(() => {\n this.filters = this.wpTableFilters.current;\n });\n });\n }\n\n public onSave() {\n if (this.filters) {\n this.wpTableFilters.replaceIfComplete(this.filters);\n this.wpTableFilters.applyToQuery(this.wpGraphConfiguration.queries[0]);\n }\n }\n\n protected get query() {\n return this.wpGraphConfiguration.queries[0];\n }\n}\n","
      \n
      \n
      \n \n
      \n
      \n \n
      \n
      \n
      \n\n
      \n \n
      \n
      \n \n
      \n
      \n
      \n
      \n
      \n","\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageViewGroupByService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service';\nimport {QueryGroupByResource} from 'core-app/modules/hal/resources/query-group-by-resource';\nimport {Component} from \"@angular/core\";\nimport {ChartType} from 'chart.js';\nimport {WpGraphConfigurationService} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration.service\";\nimport {WorkPackageStatesInitializationService} from \"core-components/wp-list/wp-states-initialization.service\";\nimport {TabComponent} from \"core-components/wp-table/configuration-modal/tab-portal-outlet\";\nimport {QuerySpacedTabComponent} from \"core-app/modules/work-package-graphs/configuration-modal/tabs/abstract-query-spaced-tab.component\";\n\ninterface OpChartType {\n identifier:ChartType;\n label:string;\n}\n\n@Component({\n selector: 'settings-tab-inner',\n templateUrl: './settings-tab-inner.component.html'\n})\nexport class WpGraphConfigurationSettingsTabInner extends QuerySpacedTabComponent implements TabComponent {\n // Grouping\n public availableGroups:QueryGroupByResource[] = [];\n public availableChartTypes:OpChartType[];\n public currentChartType:OpChartType;\n\n public text = {\n group_by: this.I18n.t('js.chart.axis_criteria'),\n chart_type: this.I18n.t('js.chart.type')\n };\n\n constructor(readonly I18n:I18nService,\n readonly wpTableGroupBy:WorkPackageViewGroupByService,\n readonly wpStatesInitialization:WorkPackageStatesInitializationService,\n readonly wpGraphConfiguration:WpGraphConfigurationService) {\n super(I18n, wpStatesInitialization, wpGraphConfiguration);\n }\n\n public onSave() {\n this.wpGraphConfiguration.chartType = this.currentChartType.identifier;\n this.wpGraphConfiguration.queries.forEach((query) => {\n this.wpTableGroupBy.applyToQuery(query);\n });\n }\n\n public get currentGroup() {\n return this.wpTableGroupBy.current!;\n }\n\n public set currentGroup(value:QueryGroupByResource) {\n this.wpTableGroupBy.update(value);\n }\n\n ngOnInit() {\n this\n .initializeQuerySpace()\n .then(() => {\n this.wpTableGroupBy\n .onReady()\n .then(() => {\n this.initializeAvailableGroups();\n this.initializeAvailableChartType();\n });\n });\n }\n\n private initializeAvailableGroups() {\n let available = this.wpTableGroupBy.available;\n // the object in current is not identical to one in available. We therefore\n // have to do this by hand to be able to just use ngModel later.\n let current = this.wpTableGroupBy.current;\n\n if (current) {\n available = available.filter(group => group.id !== current!.id);\n available = available.concat(current);\n }\n\n this.availableGroups = _.sortBy(available, 'name');\n }\n\n private initializeAvailableChartType() {\n this.availableChartTypes = _.sortBy([\n {identifier: 'horizontalBar' as ChartType, label: this.I18n.t('js.chart.types.horizontal_bar')},\n {identifier: 'bar' as ChartType, label: this.I18n.t('js.chart.types.bar')},\n {identifier: 'line' as ChartType, label: this.I18n.t('js.chart.types.line')},\n {identifier: 'pie' as ChartType, label: this.I18n.t('js.chart.types.pie')},\n {identifier: 'doughnut' as ChartType, label: this.I18n.t('js.chart.types.doughnut')},\n {identifier: 'radar' as ChartType, label: this.I18n.t('js.chart.types.radar')},\n {identifier: 'polarArea' as ChartType, label: this.I18n.t('js.chart.types.polar_area')}\n ], 'label');\n\n this.currentChartType = this.availableChartTypes.find(type => type.identifier === this.wpGraphConfiguration.configuration.chartType) || this.availableChartTypes[0];\n }\n\n protected get query() {\n return this.wpGraphConfiguration.queries[0];\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpenprojectCommonModule} from 'core-app/modules/common/openproject-common.module';\nimport {NgModule} from '@angular/core';\nimport {OpenprojectWorkPackagesModule} from \"core-app/modules/work_packages/openproject-work-packages.module\";\nimport {WpGraphConfigurationModalComponent} from \"core-app/modules/work-package-graphs/configuration-modal/wp-graph-configuration.modal\";\nimport {WpGraphConfigurationFiltersTab} from \"core-app/modules/work-package-graphs/configuration-modal/tabs/filters-tab.component\";\nimport {WpGraphConfigurationSettingsTab} from \"core-app/modules/work-package-graphs/configuration-modal/tabs/settings-tab.component\";\nimport {WpGraphConfigurationFiltersTabInner} from \"core-app/modules/work-package-graphs/configuration-modal/tabs/filters-tab-inner.component\";\nimport {WpGraphConfigurationSettingsTabInner} from \"core-app/modules/work-package-graphs/configuration-modal/tabs/settings-tab-inner.component\";\nimport {WorkPackageEmbeddedGraphComponent} from \"core-app/modules/work-package-graphs/embedded/wp-embedded-graph.component\";\nimport {WorkPackageOverviewGraphComponent} from \"core-app/modules/work-package-graphs/overview/wp-overview-graph.component\";\nimport {ChartsModule} from 'ng2-charts';\nimport * as ChartDataLabels from 'chartjs-plugin-datalabels';\n\n@NgModule({\n imports: [\n // Commons\n OpenprojectCommonModule,\n\n OpenprojectWorkPackagesModule,\n\n ChartsModule,\n ],\n declarations: [\n // Modals\n WpGraphConfigurationModalComponent,\n WpGraphConfigurationFiltersTab,\n WpGraphConfigurationFiltersTabInner,\n WpGraphConfigurationSettingsTab,\n WpGraphConfigurationSettingsTabInner,\n\n // Embedded graphs\n WorkPackageEmbeddedGraphComponent,\n // Work package graphs on version page\n WorkPackageOverviewGraphComponent,\n\n ],\n exports: [\n // Modals\n WpGraphConfigurationModalComponent,\n\n // Embedded graphs\n WorkPackageEmbeddedGraphComponent,\n WorkPackageOverviewGraphComponent\n ]\n})\nexport class OpenprojectWorkPackageGraphsModule {\n constructor() {\n // By this seemingly useless statement, the plugin is registered with Chart.\n // Simply importing it will have it removed probably by angular tree shaking\n // so it will not be active. The current default of the plugin is to be enabled\n // by default. This will be changed in the future:\n // https://github.com/chartjs/chartjs-plugin-datalabels/issues/42\n ChartDataLabels;\n }\n}\n","\n\n \n\n \n \n\n\n
      \n \n \n \n \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Injector} from '@angular/core';\nimport {AbstractWidgetComponent} from \"app/modules/grids/widgets/abstract-widget.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {Observable} from \"rxjs\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './project-description.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class WidgetProjectDescriptionComponent extends AbstractWidgetComponent implements OnInit {\n public project$:Observable;\n\n constructor(protected readonly i18n:I18nService,\n protected readonly injector:Injector,\n protected readonly apiV3Service:APIV3Service,\n protected readonly currentProject:CurrentProjectService,\n protected readonly cdRef:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.project$ = this\n .apiV3Service\n .projects\n .id(this.currentProject.id!)\n .get();\n\n this.cdRef.detectChanges();\n }\n\n public get isEditable() {\n return false;\n }\n}\n","\n\n
      \n
      \n
      \n
      \n\n\n\n\n\n\n","import {Component, ElementRef, Input, OnInit, ViewChild, ChangeDetectorRef, ChangeDetectionStrategy} from '@angular/core';\nimport {\n WorkPackageEmbeddedGraphComponent,\n WorkPackageEmbeddedGraphDataset\n} from \"core-app/modules/work-package-graphs/embedded/wp-embedded-graph.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ChartOptions} from 'chart.js';\nimport {WpGraphConfigurationService} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration.service\";\nimport {\n WpGraphConfiguration,\n WpGraphQueryParams\n} from \"core-app/modules/work-package-graphs/configuration/wp-graph-configuration\";\n\nexport const wpOverviewGraphSelector = 'wp-overview-graph';\n\n@Component({\n selector: wpOverviewGraphSelector,\n templateUrl: './wp-overview-graph.template.html',\n styleUrls: ['./wp-overview-graph.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n WpGraphConfigurationService\n ]\n})\n\nexport class WorkPackageOverviewGraphComponent implements OnInit {\n @Input() additionalFilter:any;\n @ViewChild('wpEmbeddedGraphMulti') private embeddedGraphMulti:WorkPackageEmbeddedGraphComponent;\n @ViewChild('wpEmbeddedGraphSingle') private embeddedGraphSingle:WorkPackageEmbeddedGraphComponent;\n @Input() groupBy:string = 'status';\n @Input() chartOptions:ChartOptions = { maintainAspectRatio: false };\n public datasets:WorkPackageEmbeddedGraphDataset[] = [];\n public displayModeSingle = true;\n public availableGroupBy:{label:string, key:string}[];\n public error:string|null = null;\n\n constructor(readonly elementRef:ElementRef,\n readonly I18n:I18nService,\n readonly graphConfigurationService:WpGraphConfigurationService,\n protected readonly cdr:ChangeDetectorRef) {\n\n this.availableGroupBy = [{label: I18n.t('js.work_packages.properties.category'), key: 'category'},\n {label: I18n.t('js.work_packages.properties.type'), key: 'type'},\n {label: I18n.t('js.work_packages.properties.status'), key: 'status'},\n {label: I18n.t('js.work_packages.properties.priority'), key: 'priority'},\n {label: I18n.t('js.work_packages.properties.author'), key: 'author'},\n {label: I18n.t('js.work_packages.properties.assignee'), key: 'assignee'}];\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement;\n this.additionalFilter = JSON.parse(element.getAttribute('additional-filter'));\n\n this.setQueryProps();\n }\n\n public setQueryProps() {\n this.datasets = [];\n\n let params = this.graphParams;\n\n this.graphConfigurationService.configuration = new WpGraphConfiguration(params, {}, 'horizontalBar');\n\n // 'finally' was not available yet so the code for the change detection is duplicated\n this\n .graphConfigurationService\n .reloadQueries()\n .then(() => {\n this.datasets = this.sortedDatasets(this.graphConfigurationService.datasets, params);\n\n this.cdr.detectChanges();\n })\n .catch(() => {\n this.error = this.I18n.t('js.chart.errors.could_not_load');\n\n this.cdr.detectChanges();\n });\n }\n\n public get graphParams() {\n let params = [];\n\n if (this.groupBy === 'status') {\n this.displayModeSingle = true;\n\n params.push({ name: this.I18n.t('js.label_all'), props: this.propsBoth });\n } else {\n this.displayModeSingle = false;\n\n params.push({ name: this.I18n.t('js.label_open_work_packages'), props: this.propsOpen });\n params.push({ name: this.I18n.t('js.label_closed_work_packages'), props: this.propsClosed });\n }\n\n return params;\n }\n\n public sortedDatasets(datasets:WorkPackageEmbeddedGraphDataset[], params:WpGraphQueryParams[]) {\n let sortingArray = params.map((x) => x.name );\n\n return datasets.slice().sort((a, b) => {\n return sortingArray.indexOf(a.label) - sortingArray.indexOf(b.label);\n });\n\n }\n\n public get propsBoth() {\n return this.baseProps();\n }\n\n public get propsOpen() {\n return this.baseProps({status: { operator: 'o', values: []}});\n }\n\n public get propsClosed() {\n return this.baseProps({status: { operator: 'c', values: []}});\n }\n\n private baseProps(filter?:any) {\n let filters = [{subprojectId: {operator: '*', values: []}}];\n\n if (filter) {\n filters.push(filter);\n }\n\n if (this.additionalFilter) {\n filters.push(this.additionalFilter);\n }\n\n return {\n 'columns[]': [],\n filters: JSON.stringify(filters),\n group_by: this.groupBy,\n pageSize: 0\n };\n }\n\n public get displaySingle() {\n return this.displayModeSingle;\n }\n\n public get displayMulti() {\n return !this.displayModeSingle;\n }\n\n private get currentGraph() {\n if (this.displaySingle) {\n return this.embeddedGraphSingle;\n } else {\n return this.embeddedGraphMulti;\n }\n\n }\n}\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ChangeDetectionStrategy} from '@angular/core';\nimport {AbstractWidgetComponent} from \"app/modules/grids/widgets/abstract-widget.component\";\n\n@Component({\n templateUrl: './wp-overview.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WidgetWpOverviewComponent extends AbstractWidgetComponent {\n}\n","\n\n \n \n\n\n\n\n","import {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {ElementRef, Injector, Injectable} from \"@angular/core\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {BehaviorSubject} from \"rxjs\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {UploadFile} from \"core-components/api/op-file-upload/op-file-upload.service\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\n\n@Injectable()\nexport class CustomTextEditFieldService extends EditFieldHandler {\n public fieldName = 'text';\n\n public valueChanged$:BehaviorSubject;\n\n public changeset:ResourceChangeset;\n public active:boolean;\n\n constructor(protected elementRef:ElementRef,\n protected injector:Injector,\n protected halResource:HalResourceService,\n protected schemaCache:SchemaCacheService) {\n super();\n }\n\n onFocusOut():void {\n // interface\n }\n\n public initialize(value:GridWidgetResource) {\n this.initializeChangeset(value);\n this.valueChanged$ = new BehaviorSubject(value.options['text'] as string);\n }\n\n public reinitialize(value:GridWidgetResource) {\n this.initializeChangeset(value);\n }\n\n /**\n * Handle saving the text\n */\n public handleUserSubmit():Promise {\n return this.update();\n }\n\n public reset(withText:string = '') {\n if (withText.length > 0) {\n withText += '\\n';\n }\n\n this.changeset.setValue(this.fieldName, { raw: withText });\n }\n\n public get schema():IFieldSchema {\n return {\n name: I18n.t('js.grid.widgets.custom_text.title'),\n writable: true,\n required: false,\n type: 'Formattable',\n hasDefault: false\n };\n }\n\n private async update() {\n return this\n .onSubmit()\n .then(() => {\n this.valueChanged$.next(this.rawText);\n this.deactivate();\n });\n }\n\n public get rawText() {\n return _.get(this.textValue, 'raw', '');\n }\n\n public get htmlText() {\n return _.get(this.textValue, 'html', '');\n }\n\n public get textValue() {\n return this.changeset.value(this.fieldName);\n }\n\n public handleUserCancel() {\n this.deactivate();\n }\n\n deactivate():void {\n this.changeset.clear();\n this.active = false;\n }\n\n activate() {\n this.active = true;\n }\n\n get inEditMode():boolean {\n return false;\n }\n\n get inFlight():boolean {\n return this.changeset.inFlight;\n }\n\n focus():void {\n const trigger = this.elementRef.nativeElement.querySelector('.inplace-editing--trigger-container');\n trigger && trigger.focus();\n }\n\n setErrors(newErrors:string[]):void {\n // interface\n }\n\n handleUserKeydown(event:JQuery.TriggeredEvent, onlyCancel?:boolean):void {\n // interface\n }\n\n isChanged():boolean {\n return !this.changeset.isEmpty();\n }\n\n stopPropagation(evt:JQuery.TriggeredEvent):boolean {\n return false;\n }\n\n /**\n * Mimiks having a HalResource for the sake of the Changeset.\n * @param value\n */\n private initializeChangeset(value:GridWidgetResource) {\n let schemaHref = 'customtext-schema';\n let resourceSource = {\n text: value.options.text,\n getEditorTypeFor: () => 'full',\n canAddAttachments: value.grid.canAddAttachments,\n uploadAttachments: (files:UploadFile[]) => value.grid.uploadAttachments(files),\n _links: {\n schema: {\n href: schemaHref\n }\n }\n };\n\n let resource = this.halResource.createHalResource(resourceSource, true);\n\n let schemaSource = {\n text: this.schema,\n _links: {\n self: { href: schemaHref }\n }\n };\n\n let schema = this.halResource.createHalResource(schemaSource, true) as SchemaResource;\n\n this.schemaCache.update(resource, schema);\n\n this.changeset = new ResourceChangeset(resource);\n }\n}\n","\n\n \n \n\n\n\n \n
      \n \n
      \n
      \n\n
      \n
      \n \n \n \n \n\n
      \n
      \n\n \n
      \n\n \n \n \n
      \n
      \n
      \n","import {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {\n ApplicationRef,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n OnChanges,\n OnDestroy,\n OnInit,\n SimpleChanges,\n ViewChild\n} from '@angular/core';\nimport {CustomTextEditFieldService} from \"core-app/modules/grids/widgets/custom-text/custom-text-edit-field.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {filter} from 'rxjs/operators';\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\nimport {DomSanitizer, SafeHtml} from '@angular/platform-browser';\nimport {DynamicBootstrapper} from \"core-app/globals/dynamic-bootstrapper\";\n\n@Component({\n templateUrl: './custom-text.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n CustomTextEditFieldService\n ]\n})\nexport class WidgetCustomTextComponent extends AbstractWidgetComponent implements OnInit, OnChanges, OnDestroy {\n protected currentRawText:string;\n public customText:SafeHtml;\n\n @ViewChild('displayContainer') readonly displayContainer:ElementRef;\n\n constructor(protected i18n:I18nService,\n protected injector:Injector,\n public handler:CustomTextEditFieldService,\n protected cdr:ChangeDetectorRef,\n protected sanitization:DomSanitizer,\n protected appRef:ApplicationRef,\n protected layout:GridAreaService) {\n super(i18n, injector);\n }\n\n ngOnInit():void {\n this.setupVariables(true);\n\n this\n .handler\n .valueChanged$\n .pipe(\n this.untilDestroyed(),\n filter(value => value !== this.resource.options['text'])\n ).subscribe(newText => {\n let changeset = this.setChangesetOptions({ text: { raw: newText } });\n this.resourceChanged.emit(changeset);\n });\n }\n\n ngOnChanges(changes:SimpleChanges):void {\n if (changes.resource.currentValue.options.text.raw !== this.currentRawText) {\n this.setupVariables();\n\n this.cdr.detectChanges();\n }\n }\n\n public activate(event:MouseEvent) {\n // Prevent opening the edit mode if a link was clicked\n if (this.clickedElementIsLinkWithinDisplayContainer(event)) {\n return;\n }\n\n // Load the attachments so that they are displayed in the list.\n // Once that is done, we can show the edit form.\n this.resource.grid.updateAttachments().then(() => {\n this.handler.activate();\n });\n }\n\n public get placeholderText() {\n return this.i18n.t('js.grid.widgets.work_packages_overview.placeholder');\n }\n\n public get inplaceEditClasses() {\n let classes = 'inplace-editing--container inline-edit--display-field -editable';\n\n if (this.textEmpty) {\n classes += ' -placeholder';\n }\n\n return classes;\n }\n\n public get schema() {\n return this.handler.schema;\n }\n\n public get changeset() {\n return this.handler.changeset;\n }\n\n public get active() {\n return this.handler.active;\n }\n\n public get textEmpty() {\n return !this.currentRawText.length;\n }\n\n public get isTextEditable() {\n return this.layout.isEditable;\n }\n\n private setupVariables(initial = false) {\n this.memorizeRawText();\n if (initial) {\n this.handler.initialize(this.resource);\n } else {\n this.handler.reinitialize(this.resource);\n }\n this.memorizeCustomText();\n }\n\n private memorizeRawText() {\n this.currentRawText = (this.resource.options.text as HalResource).raw;\n }\n\n private memorizeCustomText() {\n this.customText = this.sanitization.bypassSecurityTrustHtml(this.handler.htmlText);\n\n // Allow embeddable rendered content\n setTimeout(() => {\n DynamicBootstrapper.bootstrapOptionalEmbeddable(this.appRef, this.displayContainer.nativeElement);\n }, 100);\n }\n\n private clickedElementIsLinkWithinDisplayContainer(event:any) {\n return this.displayContainer.nativeElement.contains(event.target.closest('a,macro'));\n }\n}\n","\n\n \n \n\n\n
      \n \n
      \n \n
      \n {{ cf.label }}\n \n
      \n
      \n \n \n
      \n
      \n
      \n
      \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n OnInit,\n ViewChild\n} from '@angular/core';\nimport {AbstractWidgetComponent} from \"app/modules/grids/widgets/abstract-widget.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {Observable} from \"rxjs\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './project-details.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class WidgetProjectDetailsComponent extends AbstractWidgetComponent implements OnInit {\n @ViewChild('contentContainer', { static: true }) readonly contentContainer:ElementRef;\n\n public customFields:{key:string, label:string}[] = [];\n public project$:Observable;\n\n constructor(protected readonly i18n:I18nService,\n protected readonly injector:Injector,\n protected readonly apiV3Service:APIV3Service,\n protected readonly currentProject:CurrentProjectService,\n protected readonly cdRef:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.loadAndRender();\n this.project$ = this\n .apiV3Service\n .projects\n .id(this.currentProject.id!)\n .requireAndStream();\n }\n\n public get isEditable() {\n return false;\n }\n\n private loadAndRender() {\n Promise.all([\n this.loadProjectSchema()\n ])\n .then(([schema]) => {\n this.setCustomFields(schema);\n });\n }\n\n private loadProjectSchema() {\n return this\n .apiV3Service\n .projects\n .schema\n .get()\n .toPromise();\n }\n\n private setCustomFields(schema:SchemaResource) {\n Object.entries(schema).forEach(([key, keySchema]) => {\n if (key.match(/customField\\d+/)) {\n this.customFields.push({key: key, label: keySchema.name });\n }\n });\n\n this.cdRef.detectChanges();\n }\n}\n","import { ChangeDetectorRef, Injector, OnInit, Directive } from \"@angular/core\";\nimport {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {ConfirmDialogService} from \"core-components/modals/confirm-dialog/confirm-dialog.service\";\nimport {FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {TimeEntryEditService} from \"core-app/modules/time_entries/edit/edit.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Directive()\nexport abstract class WidgetTimeEntriesListComponent extends AbstractWidgetComponent implements OnInit {\n public text = {\n activity: this.i18n.t('js.time_entry.activity'),\n comment: this.i18n.t('js.time_entry.comment'),\n hour: this.i18n.t('js.time_entry.hours'),\n workPackage: this.i18n.t('js.label_work_package'),\n edit: this.i18n.t('js.button_edit'),\n delete: this.i18n.t('js.button_delete'),\n confirmDelete: {\n text: this.i18n.t('js.modals.destroy_time_entry.text'),\n title: this.i18n.t('js.modals.destroy_time_entry.title')\n },\n noResults: this.i18n.t('js.grid.widgets.time_entries_list.no_results'),\n };\n public entries:TimeEntryResource[] = [];\n private entriesLoaded = false;\n public rows:{ date:string, sum?:string, entry?:TimeEntryResource}[] = [];\n\n @InjectField() public readonly timeEntryEditService:TimeEntryEditService;\n @InjectField() public readonly apiV3Service:APIV3Service;\n\n constructor(readonly injector:Injector,\n readonly timezone:TimezoneService,\n readonly i18n:I18nService,\n readonly pathHelper:PathHelperService,\n readonly confirmDialog:ConfirmDialogService,\n protected readonly cdr:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .time_entries\n .list({ filters: this.dmFilters(), pageSize: 500 })\n .subscribe((collection) => {\n this.buildEntries(collection.elements);\n this.entriesLoaded = true;\n\n this.cdr.detectChanges();\n });\n }\n\n public get total() {\n let duration = this.entries.reduce((current, entry) => {\n return current + this.timezone.toHours(entry.hours);\n }, 0);\n\n return this.i18n.t('js.units.hour', { count: this.formatNumber(duration) });\n }\n\n public get anyEntries() {\n return !!this.entries.length;\n }\n\n public activityName(entry:TimeEntryResource) {\n return entry.activity.name;\n }\n\n public projectName(entry:TimeEntryResource) {\n return entry.project.name;\n }\n\n public workPackageName(entry:TimeEntryResource) {\n return `#${entry.workPackage.id}: ${entry.workPackage.name}`;\n }\n\n public workPackageId(entry:TimeEntryResource) {\n return entry.workPackage.id!;\n }\n\n public comment(entry:TimeEntryResource) {\n return entry.comment && entry.comment.raw;\n }\n\n public hours(entry:TimeEntryResource) {\n return this.formatNumber(this.timezone.toHours(entry.hours));\n }\n\n public workPackagePath(entry:TimeEntryResource) {\n return this.pathHelper.workPackagePath(entry.workPackage.idFromLink);\n }\n\n public get isEditable() {\n return false;\n }\n\n public editTimeEntry(entry:TimeEntryResource) {\n this\n .apiV3Service\n .time_entries\n .id(entry.id!)\n .get()\n .subscribe((loadedEntry) => {\n this.timeEntryEditService\n .edit(loadedEntry)\n .then((changedEntry) => {\n let oldEntryIndex:number = this.entries.findIndex(el => el.id === changedEntry.entry.id);\n let newEntries = this.entries;\n newEntries[oldEntryIndex] = changedEntry.entry;\n\n this.buildEntries(newEntries);\n })\n .catch(() => {\n // User canceled the modal\n });\n });\n }\n\n public deleteIfConfirmed(event:Event, entry:TimeEntryResource) {\n event.preventDefault();\n this.confirmDialog.confirm({\n text: this.text.confirmDelete,\n closeByEscape: true,\n showClose: true,\n closeByDocument: true,\n passedData:[\n '#' + entry.workPackage?.idFromLink + ' ' + entry.workPackage?.name,\n this.i18n.t(\n 'js.units.hour',\n { count: this.timezone.toHours(entry.hours) }) + ' (' + entry.activity?.name + ')'\n ],\n dangerHighlighting: true\n }).then(() => {\n entry.delete().then(() => {\n let newEntries = this.entries.filter((anEntry) => {\n return entry.id !== anEntry.id;\n });\n\n this.buildEntries(newEntries);\n });\n })\n .catch(() => {\n // nothing\n });\n }\n\n protected abstract dmFilters():Array<[string, FilterOperator, [string]]>;\n\n private buildEntries(entries:TimeEntryResource[]) {\n this.entries = entries;\n let sumsByDateSpent:{[key:string]:number} = {};\n\n entries.forEach((entry) => {\n let date = entry.spentOn;\n\n if (!sumsByDateSpent[date]) {\n sumsByDateSpent[date] = 0;\n }\n\n sumsByDateSpent[date] = sumsByDateSpent[date] + this.timezone.toHours(entry.hours);\n });\n\n let sortedEntries = entries.sort((a, b) => {\n return b.spentOn.localeCompare(a.spentOn);\n });\n\n this.rows = [];\n let currentDate:string|null = null;\n sortedEntries.forEach((entry) => {\n if (entry.spentOn !== currentDate) {\n currentDate = entry.spentOn;\n this.rows.push({date: this.timezone.formattedDate(currentDate!), sum: this.formatNumber(sumsByDateSpent[currentDate!])});\n }\n\n this.rows.push({date: currentDate!, entry: entry});\n });\n //entries\n }\n\n protected formatNumber(value:number):string {\n return this.i18n.toNumber(value, { precision: 2 });\n }\n\n public get noEntries() {\n return !this.entries.length && this.entriesLoaded;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nexport namespace PrincipalHelper {\n export type PrincipalType = 'user'|'placeholder_user'|'group';\n export type PrincipalPluralType = 'users'|'placeholder_users'|'groups';\n\n export function typeFromHref(href:string):PrincipalType|null {\n const match = href.match(/\\/(user|group|placeholder_user)s\\/\\d+$/);\n\n if (!match) {\n return null;\n }\n\n return match[1] as PrincipalType;\n }\n}\n\n","\n\n \n \n\n\n\n\n\n\n
      \n

      Total:

      \n
      \n\n
      \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
      \n
      \n
      \n \n
      \n
      \n
      \n
      \n
      \n \n
      \n
      \n
      \n
      \n
      \n \n
      \n
      \n
      \n
      \n
      \n \n
      \n
      \n
      \n \n \n \n {{projectName(item.entry)}} - \n \n \n \n \n \n \n \n \n \n \n \n \n
      \n
      \n
      \n","import {Component, OnInit, Injector, ChangeDetectorRef} from \"@angular/core\";\nimport {FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {WidgetTimeEntriesListComponent} from \"core-app/modules/grids/widgets/time-entries/list/time-entries-list.component\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {ConfirmDialogService} from \"core-components/modals/confirm-dialog/confirm-dialog.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\n\n@Component({\n templateUrl: '../list/time-entries-list.component.html',\n})\nexport class WidgetTimeEntriesProjectComponent extends WidgetTimeEntriesListComponent implements OnInit {\n constructor(readonly injector:Injector,\n readonly timezone:TimezoneService,\n readonly i18n:I18nService,\n readonly pathHelper:PathHelperService,\n readonly confirmDialog:ConfirmDialogService,\n protected readonly cdr:ChangeDetectorRef,\n protected readonly currentProject:CurrentProjectService) {\n super(injector, timezone, i18n, pathHelper, confirmDialog, cdr);\n }\n protected dmFilters():Array<[string, FilterOperator, [string]]> {\n return [['spentOn', '>t-', ['7']] as [string, FilterOperator, [string]],\n ['project_id', '=', [this.currentProject.id]] as [string, FilterOperator, [string]]];\n }\n}\n","\n\n \n \n\n\n
      \n \n \n \n \n \n , \n \n
      \n","import {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {Component, OnInit, ChangeDetectorRef, Injector, ChangeDetectionStrategy} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3ListParameters} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\n\n@Component({\n templateUrl: './subprojects.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WidgetSubprojectsComponent extends AbstractWidgetComponent implements OnInit {\n public text = {\n noResults: this.i18n.t('js.grid.widgets.subprojects.no_results'),\n };\n\n public projects:ProjectResource[];\n\n constructor(readonly halResource:HalResourceService,\n readonly pathHelper:PathHelperService,\n readonly i18n:I18nService,\n protected readonly injector:Injector,\n readonly timezone:TimezoneService,\n readonly apiV3Service:APIV3Service,\n readonly currentProject:CurrentProjectService,\n readonly cdr:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .projects\n .list(this.projectListParams)\n .subscribe((collection) => {\n this.projects = collection.elements as ProjectResource[];\n\n this.cdr.detectChanges();\n });\n }\n\n public get isEditable() {\n return false;\n }\n\n public projectPath(project:ProjectResource) {\n return this.pathHelper.projectPath(project.identifier);\n }\n\n public projectName(project:ProjectResource) {\n return project.name;\n }\n\n public get noEntries() {\n return this.projects && !this.projects.length;\n }\n\n private get projectListParams():Apiv3ListParameters {\n return { sortBy: [['name', 'asc']],\n filters: [['parent_id', '=', [this.currentProject.id!]]] };\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {ColorsService} from \"core-app/modules/common/colors/colors.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {PrincipalHelper} from \"core-app/modules/common/principal/principal-helper\";\nimport PrincipalType = PrincipalHelper.PrincipalType;\n\nexport interface PrincipalLike {\n id:string;\n name:string;\n href:string;\n}\nexport interface AvatarOptions {\n classes:string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class PrincipalRendererService {\n\n constructor(private pathHelper:PathHelperService,\n private apiV3Service:APIV3Service,\n private colors:ColorsService) {\n\n }\n\n renderMultiple(container:HTMLElement,\n users:PrincipalLike[],\n renderName:boolean = true,\n multiLine:boolean = false) {\n\n const span = document.createElement('span');\n\n\n for (let i = 0; i < users.length; i++) {\n const avatar = document.createElement('span');\n if (multiLine) {\n avatar.classList.add('user-avatar--multi-line');\n }\n\n this.render(avatar, users[i], renderName);\n\n if (!multiLine && i < users.length - 1) {\n const sep = document.createElement('span');\n sep.textContent = ', ';\n avatar.appendChild(sep);\n }\n\n span.appendChild(avatar);\n }\n\n container.appendChild(span);\n }\n\n render(container:HTMLElement,\n principal:PrincipalLike,\n name:boolean = true,\n avatar:false|AvatarOptions = { classes: 'avatar-medium' }):void {\n\n const type = PrincipalHelper.typeFromHref(principal.href)!;\n\n if (avatar) {\n const el = this.renderAvatar(principal, avatar, type);\n container.appendChild(el);\n }\n\n if (name) {\n const el = this.renderName(principal, type);\n container.appendChild(el);\n }\n }\n\n private renderAvatar(principal:PrincipalLike, avatar:AvatarOptions, type:PrincipalType) {\n const userInitials = this.getInitials(principal.name);\n const colorCode = this.colors.toHsl(principal.name);\n\n let fallback = document.createElement('div');\n fallback.className = avatar.classes;\n fallback.classList.add('avatar-default');\n fallback.textContent = userInitials;\n fallback.style.background = colorCode;\n\n // Image avatars are only supported for users\n if (type === 'user') {\n this.renderUserAvatar(principal, fallback, avatar);\n }\n\n return fallback;\n }\n\n private renderUserAvatar(principal:PrincipalLike, fallback:HTMLElement, avatar:AvatarOptions) {\n const image = new Image();\n image.className = avatar.classes;\n image.classList.add('avatar--fallback');\n image.src = this.apiV3Service.users.id(principal.id).avatar.toString();\n image.title = principal.name;\n image.alt = principal.name;\n image.onload = function () {\n fallback.replaceWith(image);\n (fallback as any) = undefined;\n };\n }\n\n private renderName(principal:PrincipalLike, type:PrincipalType) {\n const link = document.createElement('a');\n link.textContent = principal.name;\n link.href = this.principalURL(principal, type);\n link.target = '_blank';\n\n return link;\n }\n\n private principalURL(principal:PrincipalLike, type:PrincipalType) {\n switch (type) {\n case 'group':\n return this.pathHelper.groupPath(principal.id);\n case 'placeholder_user':\n return this.pathHelper.placeholderUserPath(principal.id);\n case 'user':\n return this.pathHelper.userPath(principal.id);\n }\n }\n\n private getInitials(name:string) {\n let characters = [...name];\n let lastSpace = name.lastIndexOf(' ');\n let first = characters[0]?.toUpperCase();\n let last = name[lastSpace + 1]?.toUpperCase();\n\n return [first, last].join(\"\");\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {PrincipalHelper} from \"core-app/modules/common/principal/principal-helper\";\nimport PrincipalPluralType = PrincipalHelper.PrincipalPluralType;\nimport {PrincipalLike, PrincipalRendererService} from \"core-app/modules/common/principal/principal-renderer.service\";\n\n@Component({\n template: '',\n selector: 'op-principal',\n host: {'class': 'op-principal'}\n})\nexport class OpPrincipalComponent implements OnInit {\n /** If coming from angular, pass a principal resource if available */\n @Input() principal:PrincipalLike;\n @Input() renderAvatar:boolean = true;\n @Input() renderName:boolean = true;\n @Input() avatarClasses:string = '';\n\n public constructor(readonly elementRef:ElementRef,\n readonly PathHelper:PathHelperService,\n readonly principalRenderer:PrincipalRendererService,\n readonly I18n:I18nService,\n readonly apiV3Service:APIV3Service,\n readonly timezoneService:TimezoneService) {\n\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement;\n\n if (!this.principal) {\n this.principal = this.principalFromDataset(element);\n this.renderAvatar = element.dataset.renderAvatar === 'true';\n this.renderName = element.dataset.renderName === 'true';\n this.avatarClasses = element.dataset.avatarClasses ?? '';\n }\n\n this.principalRenderer.render(\n element,\n this.principal,\n this.renderName,\n this.renderAvatar ? { classes: this.avatarClasses } : false\n );\n }\n\n private principalFromDataset(element:HTMLElement) {\n const id = element.dataset.principalId!;\n const type = element.dataset.principalType;\n const plural = type + 's' as PrincipalPluralType;\n const href = this.apiV3Service[plural].id(id).toString();\n\n return {\n id: id,\n name: element.dataset.principalName!,\n href: href\n }\n }\n}\n","\n\n \n \n\n\n
      \n \n \n
      \n \n
      \n {{usersByRole.role.name}}\n
      \n\n
      \n \n \n \n , \n \n
      \n
      \n
      \n
      \n {{moreMembersText}}\n
      \n
      \n\n\n","import {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {Component, OnInit, ChangeDetectorRef, Injector, ChangeDetectionStrategy} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {MembershipResource} from \"core-app/modules/hal/resources/membership-resource\";\nimport {RoleResource} from \"core-app/modules/hal/resources/role-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3ListParameters} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\n\nconst DISPLAYED_MEMBERS_LIMIT = 100;\n\n@Component({\n templateUrl: './members.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n styleUrls: ['./members.component.sass']\n})\nexport class WidgetMembersComponent extends AbstractWidgetComponent implements OnInit {\n public text = {\n add: this.i18n.t('js.grid.widgets.members.add'),\n noResults: this.i18n.t('js.grid.widgets.members.no_results'),\n viewAll: this.i18n.t('js.grid.widgets.members.view_all_members'),\n };\n\n public totalMembers:number;\n public entriesByRoles:{[roleId:string]:{role:RoleResource, users:UserResource[]}} = {};\n private entriesLoaded = false;\n public membersAddable:boolean = false;\n\n constructor(readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly i18n:I18nService,\n protected readonly injector:Injector,\n readonly currentProject:CurrentProjectService,\n readonly cdr:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .memberships\n .list(this.listMembersParams)\n .subscribe(collection => {\n this.partitionEntriesByRole(collection.elements);\n this.sortUsersByName();\n this.totalMembers = collection.total;\n\n this.entriesLoaded = true;\n this.cdr.detectChanges();\n });\n\n this.apiV3Service\n .memberships\n .available_projects\n .list(this.listAvailableProjectsParams)\n .subscribe(collection => {\n this.membersAddable = collection.total > 0;\n });\n }\n\n public get isEditable() {\n return false;\n }\n\n public get noMembers() {\n return this.entriesLoaded && !Object.keys(this.entriesByRoles).length;\n }\n\n public get moreMembers() {\n return this.entriesLoaded && this.totalMembers > DISPLAYED_MEMBERS_LIMIT;\n }\n\n public get moreMembersText() {\n return I18n.t(\n 'js.grid.widgets.members.too_many',\n { count: DISPLAYED_MEMBERS_LIMIT, total: this.totalMembers }\n );\n }\n\n public get projectMembershipsPath() {\n return this.pathHelper.projectMembershipsPath(this.currentProject.identifier!);\n }\n\n public get usersByRole() {\n return Object.values(this.entriesByRoles);\n }\n\n private partitionEntriesByRole(memberships:MembershipResource[]) {\n memberships.forEach(membership => {\n membership.roles.forEach((role) => {\n if (!this.entriesByRoles[role.id!]) {\n this.entriesByRoles[role.id!] = { role: role, users: [] };\n }\n\n this.entriesByRoles[role.id!].users.push(membership.principal);\n });\n });\n }\n\n private sortUsersByName() {\n Object.values(this.entriesByRoles).forEach(entry => {\n entry.users.sort((a, b) => {\n return a.name.localeCompare(b.name);\n });\n });\n }\n\n private get listMembersParams() {\n let params:Apiv3ListParameters = { sortBy: [['created_at', 'desc']], pageSize: DISPLAYED_MEMBERS_LIMIT };\n\n if (this.currentProject.id) {\n params['filters'] = [['project_id', '=', [this.currentProject.id]]];\n }\n\n return params;\n }\n\n private get listAvailableProjectsParams() {\n // It would make sense to set the pageSize but the backend for projects\n // returns an upaginated list which does not support that.\n let params:Apiv3ListParameters = {};\n\n if (this.currentProject.id) {\n params['filters'] = [['id', '=', [this.currentProject.id]]];\n }\n\n return params;\n }\n}\n","\n\n \n\n \n \n\n\n
      \n \n
      \n \n \n
      \n
      \n \n \n
      \n
      \n
      \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n OnInit,\n ViewChild\n} from '@angular/core';\nimport {AbstractWidgetComponent} from \"app/modules/grids/widgets/abstract-widget.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Observable} from \"rxjs\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './project-status.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n WorkPackageViewHighlightingService,\n IsolatedQuerySpace,\n HalResourceEditingService\n ]\n})\nexport class WidgetProjectStatusComponent extends AbstractWidgetComponent implements OnInit {\n\n @ViewChild('contentContainer', { static: true }) readonly contentContainer:ElementRef;\n\n public currentStatusCode:string = 'not set';\n public explanation:String = '';\n public project$:Observable;\n\n constructor(protected readonly i18n:I18nService,\n protected readonly injector:Injector,\n protected readonly apiV3Service:APIV3Service,\n protected readonly currentProject:CurrentProjectService,\n protected readonly cdRef:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.project$ = this\n .apiV3Service\n .projects\n .id(this.currentProject.id!)\n .get();\n\n this.cdRef.detectChanges();\n }\n\n public get isEditable() {\n return false;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injector, NgModule} from '@angular/core';\nimport {DynamicModule} from 'ng-dynamic-component';\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {BrowserModule} from '@angular/platform-browser';\nimport {FormsModule} from '@angular/forms';\nimport {DragDropModule} from '@angular/cdk/drag-drop';\nimport {OpenprojectWorkPackagesModule} from \"core-app/modules/work_packages/openproject-work-packages.module\";\nimport {WidgetWpCalendarComponent} from \"core-app/modules/grids/widgets/wp-calendar/wp-calendar.component.ts\";\nimport {WidgetTimeEntriesCurrentUserComponent} from \"core-app/modules/grids/widgets/time-entries/current-user/time-entries-current-user.component\";\nimport {GridWidgetsService} from \"core-app/modules/grids/widgets/widgets.service\";\nimport {GridComponent} from \"core-app/modules/grids/grid/grid.component\";\nimport {AddGridWidgetModal} from \"core-app/modules/grids/widgets/add/add.modal\";\nimport {OpenprojectCalendarModule} from \"core-app/modules/calendar/openproject-calendar.module\";\nimport {WidgetDocumentsComponent} from \"core-app/modules/grids/widgets/documents/documents.component\";\nimport {WidgetNewsComponent} from \"core-app/modules/grids/widgets/news/news.component\";\nimport {WidgetWpTableComponent} from \"core-app/modules/grids/widgets/wp-table/wp-table.component\";\nimport {WidgetMenuComponent} from \"core-app/modules/grids/widgets/menu/widget-menu.component\";\nimport {WidgetWpTableMenuComponent} from \"core-app/modules/grids/widgets/wp-table/wp-table-menu.component\";\nimport {GridInitializationService} from \"core-app/modules/grids/grid/initialization.service\";\nimport {WidgetWpGraphComponent} from \"core-app/modules/grids/widgets/wp-graph/wp-graph.component\";\nimport {WidgetWpGraphMenuComponent} from \"core-app/modules/grids/widgets/wp-graph/wp-graph-menu.component\";\nimport {WidgetWpTableQuerySpaceComponent} from \"core-app/modules/grids/widgets/wp-table/wp-table-qs.component\";\nimport {OpenprojectWorkPackageGraphsModule} from \"core-app/modules/work-package-graphs/openproject-work-package-graphs.module\";\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WidgetProjectDescriptionComponent} from \"core-app/modules/grids/widgets/project-description/project-description.component\";\nimport {WidgetHeaderComponent} from \"core-app/modules/grids/widgets/header/header.component\";\nimport {WidgetWpOverviewComponent} from \"core-app/modules/grids/widgets/wp-overview/wp-overview.component\";\nimport {WidgetCustomTextComponent} from \"core-app/modules/grids/widgets/custom-text/custom-text.component\";\nimport {OpenprojectFieldsModule} from \"core-app/modules/fields/openproject-fields.module\";\nimport {WidgetProjectDetailsComponent} from \"core-app/modules/grids/widgets/project-details/project-details.component\";\nimport {WidgetTimeEntriesProjectComponent} from \"core-app/modules/grids/widgets/time-entries/project/time-entries-project.component\";\nimport {WidgetSubprojectsComponent} from \"core-app/modules/grids/widgets/subprojects/subprojects.component\";\nimport {OpenprojectAttachmentsModule} from \"core-app/modules/attachments/openproject-attachments.module\";\nimport {WidgetMembersComponent} from \"core-app/modules/grids/widgets/members/members.component\";\nimport {WidgetProjectStatusComponent} from \"core-app/modules/grids/widgets/project-status/project-status.component\";\nimport {OpenprojectTimeEntriesModule} from \"core-app/modules/time_entries/openproject-time-entries.module\";\nimport {WidgetTimeEntriesCurrentUserMenuComponent} from \"core-app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-menu.component\";\nimport { TimeEntriesCurrentUserConfigurationModalComponent } from './widgets/time-entries/current-user/time-entries-current-user-configuration-modal/time-entries-current-user-configuration.modal';\n\n@NgModule({\n imports: [\n BrowserModule,\n FormsModule,\n DragDropModule,\n\n OpenprojectCommonModule,\n OpenprojectWorkPackagesModule,\n OpenprojectWorkPackageGraphsModule,\n OpenprojectCalendarModule,\n OpenprojectTimeEntriesModule,\n\n OpenprojectAttachmentsModule,\n\n DynamicModule.withComponents([\n WidgetCustomTextComponent,\n WidgetDocumentsComponent,\n WidgetMembersComponent,\n WidgetNewsComponent,\n WidgetWpTableQuerySpaceComponent,\n WidgetWpGraphComponent,\n WidgetWpCalendarComponent,\n WidgetWpOverviewComponent,\n WidgetProjectDescriptionComponent,\n WidgetProjectDetailsComponent,\n WidgetProjectStatusComponent,\n WidgetSubprojectsComponent,\n WidgetTimeEntriesCurrentUserComponent,\n WidgetTimeEntriesProjectComponent]),\n\n // Support for inline editig fields\n OpenprojectFieldsModule,\n\n ],\n providers: [\n GridWidgetsService,\n GridInitializationService,\n ],\n declarations: [\n GridComponent,\n\n // Widgets\n WidgetCustomTextComponent,\n WidgetDocumentsComponent,\n WidgetMembersComponent,\n WidgetNewsComponent,\n WidgetWpCalendarComponent,\n WidgetWpOverviewComponent,\n WidgetWpTableComponent,\n WidgetWpTableQuerySpaceComponent,\n WidgetWpGraphComponent,\n WidgetProjectDescriptionComponent,\n WidgetProjectDetailsComponent,\n WidgetProjectStatusComponent,\n WidgetSubprojectsComponent,\n WidgetTimeEntriesCurrentUserComponent,\n WidgetTimeEntriesProjectComponent,\n\n // Widget menus\n WidgetMenuComponent,\n WidgetWpTableMenuComponent,\n WidgetWpGraphMenuComponent,\n WidgetTimeEntriesCurrentUserMenuComponent,\n TimeEntriesCurrentUserConfigurationModalComponent,\n\n AddGridWidgetModal,\n\n WidgetHeaderComponent,\n ],\n exports: [\n GridComponent\n ]\n})\nexport class OpenprojectGridsModule {\n constructor(injector:Injector) {\n registerWidgets(injector);\n }\n}\n\nexport function registerWidgets(injector:Injector) {\n const hookService = injector.get(HookService);\n const i18n = injector.get(I18nService);\n\n hookService.register('gridWidgets', () => {\n\n let defaultColumns = [\"id\", \"project\", \"type\", \"subject\"];\n\n let assignedFilters = new ApiV3FilterBuilder();\n assignedFilters.add('assignee', '=', [\"me\"]);\n assignedFilters.add('status', 'o', []);\n\n let assignedProps = {\n \"columns[]\": defaultColumns,\n \"filters\": assignedFilters.toJson()\n };\n\n let accountableFilters = new ApiV3FilterBuilder();\n accountableFilters.add('responsible', '=', [\"me\"]);\n accountableFilters.add('status', 'o', []);\n\n let accountableProps = {\n \"columns[]\": defaultColumns,\n \"filters\": accountableFilters.toJson()\n };\n\n let createdFilters = new ApiV3FilterBuilder();\n createdFilters.add('author', '=', [\"me\"]);\n createdFilters.add('status', 'o', []);\n\n let createdProps = {\n \"columns[]\": defaultColumns,\n \"filters\": createdFilters.toJson()\n };\n\n let watchedFilters = new ApiV3FilterBuilder();\n watchedFilters.add('watcher', '=', [\"me\"]);\n watchedFilters.add('status', 'o', []);\n\n let watchedProps = {\n \"columns[]\": defaultColumns,\n \"filters\": watchedFilters.toJson()\n };\n\n return [\n {\n identifier: 'work_packages_assigned',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_assigned.title`),\n properties: {\n queryProps: assignedProps,\n name: i18n.t('js.grid.widgets.work_packages_assigned.title')\n }\n },\n {\n identifier: 'work_packages_accountable',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_accountable.title`),\n properties: {\n queryProps: accountableProps,\n name: i18n.t('js.grid.widgets.work_packages_accountable.title')\n }\n },\n {\n identifier: 'work_packages_created',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_created.title`),\n properties: {\n queryProps: createdProps,\n name: i18n.t('js.grid.widgets.work_packages_created.title')\n }\n },\n {\n identifier: 'work_packages_watched',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_watched.title`),\n properties: {\n queryProps: watchedProps,\n name: i18n.t('js.grid.widgets.work_packages_watched.title')\n }\n },\n {\n identifier: 'work_packages_table',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_table.title`),\n properties: {\n name: i18n.t('js.grid.widgets.work_packages_table.title')\n }\n },\n {\n identifier: 'work_packages_graph',\n component: WidgetWpGraphComponent,\n title: i18n.t(`js.grid.widgets.work_packages_graph.title`),\n properties: {\n name: i18n.t('js.grid.widgets.work_packages_graph.title')\n }\n },\n {\n identifier: 'work_packages_calendar',\n component: WidgetWpCalendarComponent,\n title: i18n.t(`js.grid.widgets.work_packages_calendar.title`),\n properties: {\n name: i18n.t('js.grid.widgets.work_packages_calendar.title')\n }\n },\n {\n identifier: 'work_packages_overview',\n component: WidgetWpOverviewComponent,\n title: i18n.t(`js.grid.widgets.work_packages_overview.title`),\n properties: {\n name: i18n.t('js.grid.widgets.work_packages_overview.title')\n }\n },\n {\n identifier: 'time_entries_current_user',\n component: WidgetTimeEntriesCurrentUserComponent,\n title: i18n.t(`js.grid.widgets.time_entries_current_user.title`),\n properties: {\n name: i18n.t('js.grid.widgets.time_entries_current_user.title'),\n days: [true, true, true, true, true, true, true]\n }\n },\n {\n identifier: 'time_entries_project',\n component: WidgetTimeEntriesProjectComponent,\n title: i18n.t(`js.grid.widgets.time_entries_list.title`),\n properties: {\n name: i18n.t('js.grid.widgets.time_entries_list.title'),\n }\n },\n {\n identifier: 'documents',\n component: WidgetDocumentsComponent,\n title: i18n.t(`js.grid.widgets.documents.title`),\n properties: {\n name: i18n.t('js.grid.widgets.documents.title')\n }\n },\n {\n identifier: 'members',\n component: WidgetMembersComponent,\n title: i18n.t(`js.grid.widgets.members.title`),\n properties: {\n name: i18n.t('js.grid.widgets.members.title')\n }\n },\n {\n identifier: 'news',\n component: WidgetNewsComponent,\n title: i18n.t(`js.grid.widgets.news.title`),\n properties: {\n name: i18n.t('js.grid.widgets.news.title')\n }\n },\n {\n identifier: 'project_description',\n component: WidgetProjectDescriptionComponent,\n title: i18n.t(`js.grid.widgets.project_description.title`),\n properties: {\n name: i18n.t('js.grid.widgets.project_description.title')\n }\n },\n {\n identifier: 'custom_text',\n component: WidgetCustomTextComponent,\n title: i18n.t(`js.grid.widgets.custom_text.title`),\n properties: {\n name: i18n.t('js.grid.widgets.custom_text.title'),\n text: {\n raw: ''\n }\n }\n },\n {\n identifier: 'project_details',\n component: WidgetProjectDetailsComponent,\n title: i18n.t(`js.grid.widgets.project_details.title`),\n properties: {\n name: i18n.t('js.grid.widgets.project_details.title')\n }\n },\n {\n identifier: 'project_status',\n component: WidgetProjectStatusComponent,\n title: i18n.t(`js.grid.widgets.project_status.title`),\n properties: {\n name: i18n.t('js.grid.widgets.project_status.title')\n }\n },\n {\n identifier: 'subprojects',\n component: WidgetSubprojectsComponent,\n title: i18n.t(`js.grid.widgets.subprojects.title`),\n properties: {\n name: i18n.t('js.grid.widgets.subprojects.title')\n }\n }\n ];\n });\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from \"@angular/core\";\n\nexport const appBaseSelector = 'openproject-base';\n\n@Component({\n selector: appBaseSelector,\n template: `\n
      \n \n
      \n `\n})\nexport class ApplicationBaseComponent {\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {StateDeclaration, StateService, Transition, TransitionService, UIRouter} from '@uirouter/core';\nimport {INotification, NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {Injector} from \"@angular/core\";\nimport {FirstRouteService} from \"core-app/modules/router/first-route-service\";\nimport {Ng2StateDeclaration, StatesModule} from \"@uirouter/angular\";\nimport {appBaseSelector, ApplicationBaseComponent} from \"core-app/modules/router/base/application-base.component\";\nimport {BackRoutingService} from \"core-app/modules/common/back-routing/back-routing.service\";\n\nexport const OPENPROJECT_ROUTES:Ng2StateDeclaration[] = [\n {\n name: 'root',\n url: '/{projects}/{projectPath}',\n component: ApplicationBaseComponent,\n abstract: true,\n params: {\n // value: null makes the parameter optional\n // squash: true avoids duplicate slashes when the parameter is not provided\n projectPath: { type: 'path', value: null, squash: true },\n projects: { type: 'path', value: null, squash: true },\n\n // Allow passing of flash messages after routes load\n flash_message: { dynamic: true, value: null, inherit: false }\n }\n },\n {\n name: 'boards.**',\n parent: 'root',\n url: '/boards',\n loadChildren: () => import('../boards/openproject-boards.module').then(m => m.OpenprojectBoardsModule)\n },\n {\n name: 'bim.**',\n parent: 'root',\n url: '/bcf',\n loadChildren: () => import('../bim/ifc_models/openproject-ifc-models.module').then(m => m.OpenprojectIFCModelsModule)\n },\n {\n name: 'backlogs.**',\n parent: 'root',\n url: '/backlogs',\n loadChildren: () => import('../backlogs/openproject-backlogs.module').then(m => m.OpenprojectBacklogsModule)\n },\n {\n name: 'backlogs_sprint.**',\n parent: 'root',\n url: '/sprints',\n loadChildren: () => import('../backlogs/openproject-backlogs.module').then(m => m.OpenprojectBacklogsModule)\n },\n {\n name: 'reporting.**',\n parent: 'root',\n url: '/cost_reports',\n loadChildren: () => import('../reporting/openproject-reporting.module').then(m => m.OpenprojectReportingModule)\n },\n {\n name: 'job-statuses.**',\n parent: 'root',\n url: '/job_statuses',\n loadChildren: () => import('../job-status/openproject-job-status.module').then(m => m.OpenProjectJobStatusModule)\n },\n];\n\n/**\n * Add or remove a body class. Helper for ui-router body classes functionality\n *\n * @param className\n * @param action\n */\nexport function bodyClass(className:string[]|string|null|undefined, action:'add'|'remove' = 'add') {\n if (className) {\n if (Array.isArray(className)) {\n className.forEach((cssClass:string) => {\n document.body.classList[action](cssClass);\n });\n } else {\n document.body.classList[action](className);\n }\n }\n}\n\nexport function updateMenuItem(menuItemClass:string|undefined, action:'add'|'remove' = 'add') {\n if (!menuItemClass) {\n return;\n }\n\n let menuItem = jQuery('#main-menu .' + menuItemClass)[0];\n\n if (!menuItem) {\n return;\n }\n\n // Update Class\n menuItem.classList[action]('selected');\n\n // Update accessibility label\n let menuItemTitle = (menuItem.getAttribute('title') || '').split(':').slice(-1)[0];\n if (action === 'add') {\n menuItemTitle = I18n.t('js.description_current_position') + menuItemTitle;\n }\n\n menuItem.setAttribute('title', menuItemTitle);\n}\n\nexport function uiRouterConfiguration(uiRouter:UIRouter, injector:Injector, module:StatesModule) {\n // Allow optional trailing slashes\n uiRouter.urlService.config.strictMode(false);\n\n // Register custom URL params type\n // to ensure query props are correctly set\n uiRouter.urlService.config.type(\n 'opQueryString',\n {\n encode: encodeURIComponent,\n decode: decodeURIComponent,\n raw: true,\n dynamic: true,\n is: (val:unknown) => typeof (val) === 'string',\n equals: (a:any, b:any) => _.isEqual(a, b),\n }\n );\n}\n\nexport function initializeUiRouterListeners(injector:Injector) {\n const $transitions:TransitionService = injector.get(TransitionService);\n const stateService = injector.get(StateService);\n const notificationsService:NotificationsService = injector.get(NotificationsService);\n const currentProject:CurrentProjectService = injector.get(CurrentProjectService);\n const firstRoute:FirstRouteService = injector.get(FirstRouteService);\n const backRoutingService:BackRoutingService = injector.get(BackRoutingService);\n\n // Check whether we are running within our complete app, or only within some other bootstrapped\n // component\n let wpBase = document.querySelector(appBaseSelector);\n\n // Uncomment to trace route changes\n // const uiRouter = injector.get(UIRouter);\n // uiRouter.trace.enable();\n\n // Apply classes from bodyClasses in each state definition\n // This was defined as onEnter, onExit functions in each state before\n // but since AOT doesn't allow anonymous functions, we can't re-use them now.\n // The transition will only return the target state on `transition.to()`,\n // however the second parameter has the currently (e.g., parent) entering state chain.\n $transitions.onEnter({}, function (transition:Transition, state:StateDeclaration) {\n // Add body class when entering this state\n bodyClass(_.get(state, 'data.bodyClasses'), 'add');\n if (transition.from().data && _.get(state, 'data.menuItem') !== transition.from().data.menuItem) {\n updateMenuItem(_.get(state, 'data.menuItem'), 'add');\n }\n\n // Reset scroll position, mostly relevant for mobile\n window.scrollTo(0, 0);\n });\n\n $transitions.onExit({}, function (transition:Transition, state:StateDeclaration) {\n // Remove body class when leaving this state\n bodyClass(_.get(state, 'data.bodyClasses'), 'remove');\n if (transition.to().data && _.get(state, 'data.menuItem') !== transition.to().data.menuItem) {\n updateMenuItem(_.get(state, 'data.menuItem'), 'remove');\n }\n });\n\n $transitions.onStart({}, function (transition:Transition) {\n const $state = transition.router.stateService;\n const toParams = transition.params('to');\n const fromState = transition.from();\n const toState = transition.to();\n\n // Remove start_onboarding_tour param if set\n if (toParams.start_onboarding_tour && toState.name !== 'work-packages.partitioned.list') {\n const paramsCopy = Object.assign({}, transition.params());\n paramsCopy.start_onboarding_tour = undefined;\n return $state.target(transition.to(), paramsCopy);\n }\n\n // Set backRoute to know where we came from\n backRoutingService.sync(transition);\n\n // Reset profiler, if we're actually profiling\n const profiler:any = (window as any).MiniProfiler;\n profiler && profiler.pageTransition();\n\n const projectIdentifier = toParams.projectPath || currentProject.identifier;\n if (!toParams.projects && projectIdentifier) {\n const newParams = _.clone(toParams);\n _.assign(newParams, { projectPath: projectIdentifier, projects: 'projects' });\n return $state.target(toState, newParams, { location: 'replace' });\n }\n\n // Abort the transition and move to the url instead\n // Only move to the URL if we're not coming from an initial URL load\n // (cases like /work_packages/invalid/activity which render a 403 without frontend,\n // but trigger the ui-router state)\n //\n // The FirstRoute service remembers the first angular route we went to\n // but for pages without any angular routes, this will stay empty.\n // So we also allow routes to happen after some delay\n if (wpBase === null) {\n\n // Get the current path and compare\n const path = window.location.pathname;\n const pathWithSearch = path + window.location.search;\n const target = stateService.href(toState, toParams);\n\n if (target && path !== target && pathWithSearch !== target) {\n window.location.href = target;\n return false;\n }\n }\n\n // Remove and add any body class definitions for entering\n // and exiting states.\n bodyClass(_.get(toState, 'data.bodyClasses'), 'add');\n\n // We need to distinguish between actions that should run on the initial page load\n // (ie. openining a new tab in the details view should focus on the element in the table)\n // so we need to know which route we visited initially\n firstRoute.setIfFirst(toState.name, toParams);\n\n // Clear all notifications when actually moving between states.\n if (transition.to().name !== transition.from().name) {\n notificationsService.clear();\n }\n\n // Add new notifications if passed to params\n if (toParams.flash_message) {\n notificationsService.add(toParams.flash_message as INotification);\n }\n\n return true;\n });\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injector, NgModule} from '@angular/core';\nimport {FirstRouteService} from \"core-app/modules/router/first-route-service\";\nimport {UIRouterModule} from \"@uirouter/angular\";\nimport {ApplicationBaseComponent} from \"core-app/modules/router/base/application-base.component\";\nimport {\n initializeUiRouterListeners,\n OPENPROJECT_ROUTES,\n uiRouterConfiguration\n} from \"core-app/modules/router/openproject.routes\";\n\n@NgModule({\n imports: [\n UIRouterModule.forRoot({\n states: OPENPROJECT_ROUTES,\n useHash: false,\n config: uiRouterConfiguration,\n } as any),\n ],\n providers: [\n FirstRouteService\n ],\n declarations: [\n ApplicationBaseComponent\n ]\n})\nexport class OpenprojectRouterModule {\n constructor(injector:Injector) {\n initializeUiRouterListeners(injector);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {WorkPackageCopyController} from 'core-components/wp-copy/wp-copy.controller';\n\n@Component({\n selector: 'wp-copy-full-view',\n host: { 'class': 'work-packages-page--ui-view' },\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: '../wp-new/wp-new-full-view.html'\n})\nexport class WorkPackageCopyFullViewComponent extends WorkPackageCopyController {\n public successState = 'work-packages.show';\n}\n\n","
      \n\n \n\n
      \n
      \n
      \n\n \n\n
      \n \n
      \n
      \n
        \n
      • \n \n \n
      • \n
      • \n \n \n
      • \n
      • \n \n \n
      • \n
      • \n \n
      • \n
      \n
      \n
      \n\n
      \n
      \n
      \n \n
      \n
      \n
      \n
      \n \n
      \n
        \n \n
      • \n \n
      • \n
      • \n \n \n
      • \n
      • \n \n \n
      • \n
      \n
      \n
      \n
      \n
      \n\n
      \n \n
      \n
      \n
      \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {StateService} from '@uirouter/core';\nimport {Component, Injector, OnInit} from '@angular/core';\nimport {WorkPackageViewSelectionService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service';\nimport {WorkPackageSingleViewBase} from \"core-app/modules/work_packages/routing/wp-view-base/work-package-single-view.base\";\nimport {of} from \"rxjs\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Component({\n templateUrl: './wp-full-view.html',\n selector: 'wp-full-view-entry',\n // Required class to support inner scrolling on page\n host: { 'class': 'work-packages-page--ui-view' },\n providers: [\n { provide: HalResourceNotificationService, useExisting: WorkPackageNotificationService }\n ]\n})\nexport class WorkPackagesFullViewComponent extends WorkPackageSingleViewBase implements OnInit {\n // Watcher properties\n public isWatched:boolean;\n public displayWatchButton:boolean;\n public watchers:any;\n\n stateName$ = of('work-packages.new');\n\n constructor(public injector:Injector,\n public wpTableSelection:WorkPackageViewSelectionService,\n readonly $state:StateService) {\n super(injector, $state.params['workPackageId']);\n }\n\n ngOnInit():void {\n this.observeWorkPackage();\n }\n\n protected initializeTexts() {\n super.initializeTexts();\n\n this.text.full_view = {\n button_more: this.I18n.t('js.button_more')\n };\n }\n\n protected init() {\n super.init();\n\n // Set Focused WP\n this.wpTableFocus.updateFocus(this.workPackage.id!);\n\n this.setWorkPackageScopeProperties(this.workPackage);\n }\n\n private setWorkPackageScopeProperties(wp:WorkPackageResource) {\n this.isWatched = wp.hasOwnProperty('unwatch');\n this.displayWatchButton = wp.hasOwnProperty('unwatch') || wp.hasOwnProperty('watch');\n\n // watchers\n if (wp.watchers) {\n this.watchers = (wp.watchers as any).elements;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {Directive, ElementRef} from \"@angular/core\";\nimport {OpContextMenuTrigger} from \"core-components/op-context-menu/handlers/op-context-menu-trigger.directive\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n WorkPackageViewDisplayRepresentationService,\n wpDisplayCardRepresentation,\n wpDisplayListRepresentation\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\n\n@Directive({\n selector: '[wpViewDropdown]'\n})\nexport class WorkPackageViewDropdownMenuDirective extends OpContextMenuTrigger {\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly I18n:I18nService,\n readonly wpDisplayRepresentationService:WorkPackageViewDisplayRepresentationService,\n readonly wpTableTimeline:WorkPackageViewTimelineService) {\n\n super(elementRef, opContextMenu);\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n this.buildItems();\n this.opContextMenu.show(this, evt);\n }\n\n public get locals() {\n return {\n items: this.items,\n contextMenuId: 'wp-view-context-menu'\n };\n }\n\n private buildItems() {\n this.items = [];\n\n if (this.wpDisplayRepresentationService.current !== wpDisplayCardRepresentation) {\n this.items.push(\n {\n // Card View\n linkText: this.I18n.t('js.views.card'),\n icon: 'icon-view-card',\n onClick: (evt:any) => {\n this.wpDisplayRepresentationService.setDisplayRepresentation(wpDisplayCardRepresentation);\n if (this.wpTableTimeline.isVisible) {\n // Necessary for the timeline buttons to disappear\n this.wpTableTimeline.toggle();\n }\n return true;\n }\n });\n }\n\n if (this.wpTableTimeline.isVisible || this.wpDisplayRepresentationService.current === wpDisplayCardRepresentation) {\n this.items.push(\n {\n // List View\n linkText: this.I18n.t('js.views.list'),\n icon: 'icon-view-list',\n onClick: (evt:any) => {\n this.wpDisplayRepresentationService.setDisplayRepresentation(wpDisplayListRepresentation);\n if (this.wpTableTimeline.isVisible) {\n this.wpTableTimeline.toggle();\n }\n return true;\n }\n });\n }\n\n if (!this.wpTableTimeline.isVisible || this.wpDisplayRepresentationService.current === wpDisplayCardRepresentation) {\n this.items.push(\n {\n // List View with enabled Gantt\n linkText: this.I18n.t('js.views.timeline'),\n icon: 'icon-view-timeline',\n onClick: (evt:any) => {\n if (!this.wpTableTimeline.isVisible) {\n this.wpTableTimeline.toggle();\n }\n this.wpDisplayRepresentationService.setDisplayRepresentation(wpDisplayListRepresentation);\n return true;\n }\n });\n }\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {\n WorkPackageViewDisplayRepresentationService,\n wpDisplayCardRepresentation,\n wpDisplayListRepresentation\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {combineLatest} from \"rxjs\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n\n@Component({\n template: `\n \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-view-toggle-button',\n})\nexport class WorkPackageViewToggleButton extends UntilDestroyedMixin implements OnInit {\n public view:string;\n\n public text:any = {\n card: this.I18n.t('js.views.card'),\n list: this.I18n.t('js.views.list'),\n timeline: this.I18n.t('js.views.timeline'),\n };\n\n constructor(readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly wpDisplayRepresentationService:WorkPackageViewDisplayRepresentationService,\n readonly wpTableTimeline:WorkPackageViewTimelineService) {\n super();\n }\n\n ngOnInit() {\n let statesCombined = combineLatest([\n this.wpDisplayRepresentationService.live$(),\n this.wpTableTimeline.live$(),\n ]);\n\n statesCombined.pipe(\n this.untilDestroyed()\n ).subscribe(([display, timelines]) => {\n this.detectView(display, timelines.visible);\n this.cdRef.detectChanges();\n });\n }\n\n public detectView(display:string|null, timelineVisible:boolean) {\n if (display === wpDisplayCardRepresentation) {\n this.view = wpDisplayCardRepresentation;\n return;\n }\n\n if (timelineVisible) {\n this.view = 'timeline';\n } else {\n this.view = wpDisplayListRepresentation;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {KeepTabService} from '../../wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {States} from '../../states.service';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {StateService, TransitionService} from '@uirouter/core';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy} from '@angular/core';\nimport {AbstractWorkPackageButtonComponent} from 'core-components/wp-buttons/wp-buttons.module';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n templateUrl: '../wp-button.template.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-details-view-button',\n})\nexport class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageButtonComponent implements OnDestroy {\n public projectIdentifier:string;\n public accessKey:number = 8;\n public activeState:string = 'work-packages.partitioned.list.details';\n public listState:string = 'work-packages.partitioned.list';\n public buttonId:string = 'work-packages-details-view-button';\n public buttonClass:string = 'toolbar-icon';\n public iconClass:string = 'icon-info2';\n\n public activateLabel:string;\n public deactivateLabel:string;\n\n private transitionListener:Function;\n\n constructor(\n readonly $state:StateService,\n readonly I18n:I18nService,\n readonly transitions:TransitionService,\n readonly cdRef:ChangeDetectorRef,\n public states:States,\n public wpTableFocus:WorkPackageViewFocusService,\n public keepTab:KeepTabService) {\n super(I18n);\n\n this.activateLabel = I18n.t('js.button_open_details');\n this.deactivateLabel = I18n.t('js.button_close_details');\n\n this.transitionListener = this.transitions.onSuccess({}, () => {\n this.isActive = this.$state.includes(this.activeState);\n this.cdRef.detectChanges();\n });\n }\n\n public ngOnDestroy() {\n super.ngOnDestroy();\n this.transitionListener();\n }\n\n public get label():string {\n if (this.isActive) {\n return this.deactivateLabel;\n } else {\n return this.activateLabel;\n }\n }\n\n public isToggle():boolean {\n return true;\n }\n\n public performAction(event:Event) {\n if (this.isActive) {\n this.openListView();\n } else {\n this.openDetailsView();\n }\n }\n\n public openListView() {\n var params = {\n projectPath: this.projectIdentifier\n };\n\n _.extend(params, this.$state.params);\n this.$state.go(this.listState, params);\n }\n\n public openDetailsView() {\n var params = {\n workPackageId: this.wpTableFocus.focusedWorkPackage,\n projectPath: this.projectIdentifier,\n };\n\n _.extend(params, this.$state.params);\n this.$state.go(this.keepTab.currentDetailsState, params);\n }\n}\n","
        \n\n
      • \n \n
      • \n\n
      • \n \n
      • \n\n
      • \n \n
      • \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AbstractWorkPackageButtonComponent, ButtonControllerText} from '../wp-buttons.module';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {TimelineZoomLevel} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\n\nexport interface TimelineButtonText extends ButtonControllerText {\n zoomOut:string;\n zoomIn:string;\n zoomAuto:string;\n}\n\n@Component({\n templateUrl: './wp-timeline-toggle-button.html',\n styleUrls: ['./wp-timeline-toggle-button.sass'],\n selector: 'wp-timeline-toggle-button',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageTimelineButtonComponent extends AbstractWorkPackageButtonComponent implements OnInit {\n public buttonId:string = 'work-packages-timeline-toggle-button';\n public iconClass:string = 'icon-view-timeline';\n\n private activateLabel:string;\n private deactivateLabel:string;\n\n public text:TimelineButtonText;\n\n public minZoomLevel:TimelineZoomLevel = 'days';\n public maxZoomLevel:TimelineZoomLevel = 'years';\n\n public isAutoZoom = false;\n\n public isMaxLevel:boolean = false;\n public isMinLevel:boolean = false;\n\n constructor(readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n public wpTableTimeline:WorkPackageViewTimelineService) {\n super(I18n);\n\n this.activateLabel = I18n.t('js.timelines.button_activate');\n this.deactivateLabel = I18n.t('js.timelines.button_deactivate');\n\n this.text.zoomIn = I18n.t('js.timelines.zoom.in');\n this.text.zoomOut = I18n.t('js.timelines.zoom.out');\n this.text.zoomAuto = I18n.t('js.timelines.zoom.auto');\n }\n\n ngOnInit():void {\n this.wpTableTimeline\n .live$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.isAutoZoom = this.wpTableTimeline.isAutoZoom();\n this.isActive = this.wpTableTimeline.isVisible;\n this.cdRef.detectChanges();\n });\n\n this.wpTableTimeline\n .appliedZoomLevel$\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((current) => {\n this.isMaxLevel = current === this.maxZoomLevel;\n this.isMinLevel = current === this.minZoomLevel;\n this.cdRef.detectChanges();\n });\n }\n\n public get label():string {\n if (this.isActive) {\n return this.deactivateLabel;\n } else {\n return this.activateLabel;\n }\n }\n\n public isToggle():boolean {\n return true;\n }\n\n public updateZoomWithDelta(delta:number) {\n this.wpTableTimeline.updateZoomWithDelta(delta);\n }\n\n public performAction(event:Event) {\n this.toggleTimeline();\n }\n\n public toggleTimeline() {\n this.wpTableTimeline.toggle();\n }\n\n public enableAutoZoom() {\n this.wpTableTimeline.enableAutozoom();\n }\n\n public getAutoZoomToggleClass():string {\n return this.isAutoZoom ? '-disabled' : '';\n }\n}\n","import {States} from '../../states.service';\nimport {AuthorisationService} from 'core-app/modules/common/model-auth/model-auth.service';\nimport {Component, EventEmitter, Input, Output} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\n\nexport interface QuerySharingChange {\n isStarred:boolean;\n isPublic:boolean;\n}\n\n@Component({\n selector: 'query-sharing-form',\n templateUrl: './query-sharing-form.html'\n})\nexport class QuerySharingForm {\n @Input() public isSave:boolean;\n @Input() public isStarred:boolean;\n @Input() public isPublic:boolean;\n @Output() public onChange = new EventEmitter();\n\n public text = {\n showInMenu: this.I18n.t('js.label_star_query'),\n visibleForOthers: this.I18n.t('js.label_public_query'),\n\n showInMenuText: this.I18n.t('js.work_packages.query.star_text'),\n visibleForOthersText: this.I18n.t('js.work_packages.query.public_text')\n };\n\n constructor(readonly states:States,\n readonly querySpace:IsolatedQuerySpace,\n readonly authorisationService:AuthorisationService,\n readonly I18n:I18nService) {\n }\n\n public get canStar() {\n return this.isSave ||\n this.authorisationService.can('query', 'star') ||\n this.authorisationService.can('query', 'unstar');\n }\n\n public get canPublish() {\n const form = this.querySpace.queryForm.value!;\n\n return this.authorisationService.can('query', 'updateImmediately')\n && form.schema.public.writable;\n }\n\n public updateStarred(val:boolean) {\n this.isStarred = val;\n this.changed();\n }\n\n public updatePublic(val:boolean) {\n this.isPublic = val;\n this.changed();\n }\n\n public changed() {\n this.onChange.emit({ isStarred: !!this.isStarred, isPublic: !!this.isPublic });\n }\n}\n","
      \n
      \n \n
      \n
      \n
      \n\n
      \n
      \n \n
      \n
      \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {States} from '../../states.service';\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {ChangeDetectorRef, Component, ElementRef, Inject, ViewChild} from \"@angular/core\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {QuerySharingChange} from \"core-components/modals/share-modal/query-sharing-form.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\n\n@Component({\n templateUrl: './save-query.modal.html'\n})\nexport class SaveQueryModal extends OpModalComponent {\n public queryName:string = '';\n public isStarred = false;\n public isPublic = false;\n public isBusy = false;\n\n @ViewChild('queryNameField', { static: true }) queryNameField:ElementRef;\n\n public text = {\n title: this.I18n.t('js.modals.form_submit.title'),\n text: this.I18n.t('js.modals.form_submit.text'),\n save_as: this.I18n.t('js.label_save_as'),\n label_name: this.I18n.t('js.modals.label_name'),\n label_visibility_settings: this.I18n.t('js.label_visibility_settings'),\n button_save: this.I18n.t('js.modals.button_save'),\n button_cancel: this.I18n.t('js.button_cancel'),\n close_popup: this.I18n.t('js.close_popup_title')\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly I18n:I18nService,\n readonly states:States,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpListService:WorkPackagesListService,\n readonly halNotification:HalResourceNotificationService,\n readonly cdRef:ChangeDetectorRef,\n readonly notificationsService:NotificationsService) {\n super(locals, cdRef, elementRef);\n }\n\n public setValues(change:QuerySharingChange) {\n this.isStarred = change.isStarred;\n this.isPublic = change.isPublic;\n }\n\n public onOpen() {\n this.queryNameField.nativeElement.focus();\n }\n\n public get afterFocusOn() {\n return jQuery('#work-packages-settings-button');\n }\n\n public saveQueryAs($event:JQuery.TriggeredEvent) {\n if (this.isBusy || !this.queryName) {\n return;\n }\n\n this.isBusy = true;\n const query = this.querySpace.query.value!;\n query.public = this.isPublic;\n\n this.wpListService\n .create(query, this.queryName)\n .then((savedQuery:QueryResource):Promise => {\n if (this.isStarred && !savedQuery.starred) {\n return this.wpListService.toggleStarred(savedQuery).then(() => this.closeMe($event));\n }\n\n this.closeMe($event);\n return Promise.resolve(true);\n })\n .catch((error:any) => this.halNotification.handleRawError(error))\n .then(() => this.isBusy = false); // Same as .finally()\n }\n}\n","
      \n
      \n
      \n

      \n\n \n \n \n \n
      \n\n
      \n
      \n \n
      \n
      \n \n
      \n
      \n
      \n\n
      \n

      \n \n \n
      \n\n
      \n \n \n
      \n
      \n
      \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackagesListService} from '../../wp-list/wp-list.service';\nimport {States} from '../../states.service';\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {ChangeDetectorRef, Component, ElementRef, Inject, OnInit} from \"@angular/core\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {QuerySharingChange} from \"core-components/modals/share-modal/query-sharing-form.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\n\n@Component({\n templateUrl: './query-sharing.modal.html'\n})\nexport class QuerySharingModal extends OpModalComponent implements OnInit {\n public query:QueryResource;\n public isStarred = false;\n public isPublic = false;\n public isBusy = false;\n\n public text = {\n title: this.I18n.t('js.modals.form_submit.title'),\n text: this.I18n.t('js.modals.form_submit.text'),\n save_as: this.I18n.t('js.label_save_as'),\n label_name: this.I18n.t('js.modals.label_name'),\n label_visibility_settings: this.I18n.t('js.label_visibility_settings'),\n button_save: this.I18n.t('js.modals.button_save'),\n button_cancel: this.I18n.t('js.button_cancel'),\n close_popup: this.I18n.t('js.close_popup_title')\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly I18n:I18nService,\n readonly states:States,\n readonly querySpace:IsolatedQuerySpace,\n readonly cdRef:ChangeDetectorRef,\n readonly wpListService:WorkPackagesListService,\n readonly halNotification:HalResourceNotificationService,\n readonly notificationsService:NotificationsService) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n super.ngOnInit();\n\n this.query = this.querySpace.query.value!;\n\n this.isStarred = this.query.starred;\n this.isPublic = this.query.public;\n }\n\n\n public setValues(change:QuerySharingChange) {\n this.isStarred = change.isStarred;\n this.isPublic = change.isPublic;\n }\n\n public get afterFocusOn() {\n return jQuery('#work-packages-settings-button');\n }\n\n public saveQuery($event:JQuery.TriggeredEvent) {\n if (this.isBusy) {\n return;\n }\n\n this.isBusy = true;\n let promises = [];\n\n if (this.query.public !== this.isPublic) {\n this.query.public = this.isPublic;\n\n promises.push(this.wpListService.save(this.query));\n }\n\n if (this.query.starred !== this.isStarred) {\n promises.push(this.wpListService.toggleStarred(this.query));\n }\n\n Promise\n .all(promises)\n .then(() => {\n this.closeMe($event);\n this.isBusy = false;\n })\n .catch(() => {\n this.notificationsService.addError(this.I18n.t('js.errors.query_saving'));\n this.isBusy = false;\n });\n }\n}\n","
      \n
      \n
      \n

      \n\n \n \n \n \n
      \n\n \n \n\n
      \n \n \n
      \n
      \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Directive, ElementRef, Injector, Input} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {AuthorisationService} from 'core-app/modules/common/model-auth/model-auth.service';\nimport {OpContextMenuTrigger} from 'core-components/op-context-menu/handlers/op-context-menu-trigger.directive';\nimport {OPContextMenuService} from 'core-components/op-context-menu/op-context-menu.service';\nimport {States} from 'core-components/states.service';\nimport {WorkPackagesListService} from 'core-components/wp-list/wp-list.service';\nimport {QueryFormResource} from 'core-app/modules/hal/resources/query-form-resource';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {WpTableExportModal} from \"core-components/modals/export-modal/wp-table-export.modal\";\nimport {SaveQueryModal} from \"core-components/modals/save-modal/save-query.modal\";\nimport {QuerySharingModal} from \"core-components/modals/share-modal/query-sharing.modal\";\nimport {WpTableConfigurationModalComponent} from 'core-components/wp-table/configuration-modal/wp-table-configuration.modal';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {\n selectableTitleIdentifier,\n triggerEditingEvent\n} from \"core-app/modules/common/editable-toolbar-title/editable-toolbar-title.component\";\n\n@Directive({\n selector: '[opSettingsContextMenu]'\n})\nexport class OpSettingsMenuDirective extends OpContextMenuTrigger {\n @Input('opSettingsContextMenu-query') public query:QueryResource;\n private form:QueryFormResource;\n private loadingPromise:PromiseLike;\n private focusAfterClose = true;\n\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly opModalService:OpModalService,\n readonly wpListService:WorkPackagesListService,\n readonly authorisationService:AuthorisationService,\n readonly states:States,\n readonly injector:Injector,\n readonly querySpace:IsolatedQuerySpace,\n readonly I18n:I18nService) {\n\n super(elementRef, opContextMenu);\n }\n\n ngAfterViewInit():void {\n super.ngAfterViewInit();\n\n this.querySpace.query.values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(queryUpdate => {\n this.query = queryUpdate;\n });\n\n this.loadingPromise = this.querySpace.queryForm.valuesPromise();\n\n this.querySpace.queryForm.values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(formUpdate => {\n this.form = formUpdate;\n });\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n this.loadingPromise.then(() => {\n this.buildItems();\n this.opContextMenu.show(this, evt);\n });\n }\n\n public get locals() {\n return {\n contextMenuId: 'settingsDropdown',\n items: this.items\n };\n }\n\n /**\n * Positioning args for jquery-ui position.\n *\n * @param {Event} openerEvent\n */\n public positionArgs(evt:JQuery.TriggeredEvent) {\n let additionalPositionArgs = {\n my: 'right top',\n at: 'right bottom'\n };\n\n let position = super.positionArgs(evt);\n _.assign(position, additionalPositionArgs);\n\n return position;\n }\n\n public onClose() {\n if (this.focusAfterClose) {\n this.afterFocusOn.focus();\n }\n }\n\n private allowQueryAction(event:JQuery.TriggeredEvent, action:any) {\n return this.allowAction(event, 'query', action);\n }\n\n private allowWorkPackageAction(event:JQuery.TriggeredEvent, action:any) {\n return this.allowAction(event, 'work_packages', action);\n }\n\n private allowFormAction(event:JQuery.TriggeredEvent, action:string) {\n if (this.form.$links[action]) {\n return true;\n } else {\n event.stopPropagation();\n return false;\n }\n }\n\n private allowAction(event:JQuery.TriggeredEvent, modelName:string, action:any) {\n if (this.authorisationService.can(modelName, action)) {\n return true;\n } else {\n event.stopPropagation();\n return false;\n }\n }\n\n private buildItems() {\n this.items = [\n {\n // Configuration modal\n disabled: false,\n linkText: this.I18n.t('js.toolbar.settings.configure_view'),\n icon: 'icon-settings',\n onClick: ($event:JQuery.TriggeredEvent) => {\n this.opContextMenu.close();\n this.opModalService.show(WpTableConfigurationModalComponent, this.injector);\n\n return true;\n }\n },\n {\n // Insert columns\n linkText: this.I18n.t('js.work_packages.query.insert_columns'),\n icon: 'icon-columns',\n class: 'hidden-for-mobile',\n onClick: () => {\n this.opModalService.show(\n WpTableConfigurationModalComponent,\n this.injector,\n { initialTab: 'columns' }\n );\n return true;\n }\n },\n {\n // Sort by\n linkText: this.I18n.t('js.toolbar.settings.sort_by'),\n icon: 'icon-sort-by',\n onClick: () => {\n this.opModalService.show(\n WpTableConfigurationModalComponent,\n this.injector,\n { initialTab: 'sort-by' }\n );\n return true;\n }\n },\n {\n // Group by\n linkText: this.I18n.t('js.toolbar.settings.group_by'),\n icon: 'icon-group-by',\n class: 'hidden-for-mobile',\n onClick: () => {\n this.opModalService.show(\n WpTableConfigurationModalComponent,\n this.injector,\n { initialTab: 'display-settings' }\n );\n return true;\n }\n },\n {\n // Rename query shortcut\n disabled: !this.query.id || this.authorisationService.cannot('query', 'updateImmediately'),\n linkText: this.I18n.t('js.toolbar.settings.page_settings'),\n icon: 'icon-edit',\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (this.allowQueryAction($event, 'update')) {\n this.focusAfterClose = false;\n jQuery(`${selectableTitleIdentifier}`).trigger(triggerEditingEvent);\n }\n\n return true;\n }\n },\n {\n // Query save modal\n disabled: this.authorisationService.cannot('query', 'updateImmediately'),\n linkText: this.I18n.t('js.toolbar.settings.save'),\n icon: 'icon-save',\n onClick: ($event:JQuery.TriggeredEvent) => {\n const query = this.query;\n if (!query.persisted && this.allowQueryAction($event, 'updateImmediately')) {\n this.opModalService.show(SaveQueryModal, this.injector);\n } else if (query.id && this.allowQueryAction($event, 'updateImmediately')) {\n this.wpListService.save(query);\n }\n\n return true;\n }\n },\n {\n // Query save as modal\n disabled: this.form ? !this.form.$links.create_new : this.authorisationService.cannot('query', 'updateImmediately'),\n linkText: this.I18n.t('js.toolbar.settings.save_as'),\n icon: 'icon-save',\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (this.allowFormAction($event, 'create_new')) {\n this.opModalService.show(SaveQueryModal, this.injector);\n }\n\n return true;\n }\n },\n {\n // Delete query\n disabled: this.authorisationService.cannot('query', 'delete'),\n linkText: this.I18n.t('js.toolbar.settings.delete'),\n icon: 'icon-delete',\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (this.allowQueryAction($event, 'delete') &&\n window.confirm(this.I18n.t('js.text_query_destroy_confirmation'))) {\n this.wpListService.delete();\n }\n\n return true;\n }\n },\n {\n // Export query\n disabled: this.authorisationService.cannot('work_packages', 'representations'),\n linkText: this.I18n.t('js.toolbar.settings.export'),\n icon: 'icon-export',\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (this.allowWorkPackageAction($event, 'representations')) {\n this.opModalService.show(WpTableExportModal, this.injector);\n }\n\n return true;\n }\n },\n {\n // Sharing modal\n disabled: this.authorisationService.cannot('query', 'unstar') && this.authorisationService.cannot('query', 'star'),\n linkText: this.I18n.t('js.toolbar.settings.visibility_settings'),\n icon: 'icon-watched',\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (this.allowQueryAction($event, 'unstar') || this.allowQueryAction($event, 'star')) {\n this.opModalService.show(QuerySharingModal, this.injector);\n }\n\n return true;\n }\n },\n {\n divider: true,\n hidden: !(this.query.results.customFields && this.form.configureForm)\n },\n {\n // Settings modal\n hidden: !this.query.results.customFields,\n href: this.query.results.customFields && this.query.results.customFields.href,\n linkText: this.query.results.customFields && this.query.results.customFields.name,\n icon: 'icon-custom-fields',\n onClick: () => false\n }\n ];\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n templateUrl: './wp-settings-button.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WorkPackageSettingsButtonComponent {\n public text = {\n 'button_settings': this.I18n.t('js.button_settings')\n };\n\n constructor(readonly I18n:I18nService) {\n }\n}\n","\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {Directive, ElementRef} from \"@angular/core\";\nimport {OpContextMenuTrigger} from \"core-components/op-context-menu/handlers/op-context-menu-trigger.directive\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n WorkPackageViewDisplayRepresentationService,\n wpDisplayCardRepresentation,\n wpDisplayListRepresentation\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageViewCollapsedGroupsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service\";\n\n@Directive({\n selector: '[wpGroupToggleDropdown]'\n})\nexport class WorkPackageGroupToggleDropdownMenuDirective extends OpContextMenuTrigger {\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly I18n:I18nService,\n readonly wpViewCollapsedGroups:WorkPackageViewCollapsedGroupsService) {\n super(elementRef, opContextMenu);\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n this.buildItems();\n this.opContextMenu.show(this, evt);\n }\n\n public get locals() {\n return {\n items: this.items,\n contextMenuId: 'wp-group-fold-context-menu'\n };\n }\n\n private buildItems() {\n this.items = [\n {\n disabled: this.wpViewCollapsedGroups.allGroupsAreCollapsed,\n linkText: this.I18n.t('js.button_collapse_all'),\n icon: 'icon-minus2',\n onClick: (evt:JQuery.TriggeredEvent) => {\n this.wpViewCollapsedGroups.setAllGroupsCollapseStateTo(true);\n\n return true;\n }\n },\n {\n disabled: this.wpViewCollapsedGroups.allGroupsAreExpanded,\n linkText: this.I18n.t('js.button_expand_all'),\n icon: 'icon-plus',\n onClick: (evt:JQuery.TriggeredEvent) => {\n this.wpViewCollapsedGroups.setAllGroupsCollapseStateTo(false);\n\n return true;\n }\n }\n ];\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n template: `\n \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-fold-toggle-view-button'\n})\nexport class WorkPackageFoldToggleButtonComponent {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component, OnInit} from \"@angular/core\";\nimport {take} from \"rxjs/operators\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {QueryParamListenerService} from \"core-components/wp-query/query-param-listener.service\";\nimport {\n PartitionedQuerySpacePageComponent,\n ToolbarButtonComponentDefinition\n} from \"core-app/modules/work_packages/routing/partitioned-query-space-page/partitioned-query-space-page.component\";\nimport {WorkPackageCreateButtonComponent} from \"core-components/wp-buttons/wp-create-button/wp-create-button.component\";\nimport {WorkPackageFilterButtonComponent} from \"core-components/wp-buttons/wp-filter-button/wp-filter-button.component\";\nimport {WorkPackageViewToggleButton} from \"core-components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component\";\nimport {WorkPackageDetailsViewButtonComponent} from \"core-components/wp-buttons/wp-details-view-button/wp-details-view-button.component\";\nimport {WorkPackageTimelineButtonComponent} from \"core-components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.component\";\nimport {ZenModeButtonComponent} from \"core-components/wp-buttons/zen-mode-toggle-button/zen-mode-toggle-button.component\";\nimport {WorkPackageSettingsButtonComponent} from \"core-components/wp-buttons/wp-settings-button/wp-settings-button.component\";\nimport {of} from \"rxjs\";\nimport {WorkPackageFoldToggleButtonComponent} from \"core-components/wp-buttons/wp-fold-toggle-button/wp-fold-toggle-button.component\";\n\n@Component({\n selector: 'wp-view-page',\n templateUrl: '/app/modules/work_packages/routing/partitioned-query-space-page/partitioned-query-space-page.component.html',\n styleUrls: [\n // Absolute paths do not work for styleURLs :-(\n '../partitioned-query-space-page/partitioned-query-space-page.component.sass'\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n /** We need to provide the wpNotification service here to get correct save notifications for WP resources */\n { provide: HalResourceNotificationService, useClass: WorkPackageNotificationService },\n QueryParamListenerService\n ]\n})\nexport class WorkPackageViewPageComponent extends PartitionedQuerySpacePageComponent implements OnInit {\n toolbarButtonComponents:ToolbarButtonComponentDefinition[] = [\n {\n component: WorkPackageCreateButtonComponent,\n inputs: {\n stateName$: of(\"work-packages.partitioned.list.new\"),\n allowed: ['work_packages.createWorkPackage']\n }\n },\n {\n component: WorkPackageFilterButtonComponent\n },\n {\n component: WorkPackageViewToggleButton,\n containerClasses: 'hidden-for-mobile'\n },\n {\n component: WorkPackageFoldToggleButtonComponent,\n show: () => {\n return !!(this.currentQuery && this.currentQuery.groupBy);\n }\n },\n {\n component: WorkPackageDetailsViewButtonComponent,\n containerClasses: 'hidden-for-mobile'\n },\n {\n component: WorkPackageTimelineButtonComponent,\n containerClasses: 'hidden-for-mobile -no-spacing'\n },\n {\n component: ZenModeButtonComponent,\n containerClasses: 'hidden-for-mobile'\n },\n {\n component: WorkPackageSettingsButtonComponent\n }\n ];\n\n ngOnInit() {\n super.ngOnInit();\n this.text.button_settings = this.I18n.t('js.button_settings');\n }\n\n protected additionalLoadingTime():Promise {\n if (this.wpTableTimeline.isVisible) {\n return this.querySpace.timelineRendered.pipe(take(1)).toPromise();\n } else {\n return this.querySpace.tableRendered.valuesPromise() as Promise;\n }\n }\n\n protected shouldUpdateHtmlTitle():boolean {\n return this.$state.current.name === 'work-packages.partitioned.list';\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageActivityTabComponent} from 'core-components/wp-single-view-tabs/activity-panel/activity-tab.component';\nimport {WorkPackageRelationsTabComponent} from 'core-components/wp-single-view-tabs/relations-tab/relations-tab.component';\nimport {WorkPackageWatchersTabComponent} from 'core-components/wp-single-view-tabs/watchers-tab/watchers-tab.component';\nimport {WorkPackageNewFullViewComponent} from 'core-components/wp-new/wp-new-full-view.component';\nimport {WorkPackageCopyFullViewComponent} from 'core-components/wp-copy/wp-copy-full-view.component';\nimport {WorkPackagesFullViewComponent} from \"core-app/modules/work_packages/routing/wp-full-view/wp-full-view.component\";\nimport {WorkPackageSplitViewComponent} from \"core-app/modules/work_packages/routing/wp-split-view/wp-split-view.component\";\nimport {Ng2StateDeclaration} from \"@uirouter/angular\";\nimport {WorkPackagesBaseComponent} from \"core-app/modules/work_packages/routing/wp-base/wp--base.component\";\nimport {WorkPackageListViewComponent} from \"core-app/modules/work_packages/routing/wp-list-view/wp-list-view.component\";\nimport {WorkPackageViewPageComponent} from \"core-app/modules/work_packages/routing/wp-view-page/wp-view-page.component\";\nimport {makeSplitViewRoutes} from \"core-app/modules/work_packages/routing/split-view-routes.template\";\n\nexport const menuItemClass = 'work-packages-menu-item';\n\nexport const WORK_PACKAGES_ROUTES:Ng2StateDeclaration[] = [\n {\n name: 'work-packages',\n parent: 'root',\n component: WorkPackagesBaseComponent,\n url: '/work_packages?query_id&query_props&start_onboarding_tour',\n redirectTo: 'work-packages.partitioned.list',\n data: {\n bodyClasses: 'router--work-packages-base',\n menuItem: menuItemClass\n },\n params: {\n query_id: { type: 'query', dynamic: true },\n // Use custom encoder/decoder that ensures validity of URL string\n query_props: { type: 'opQueryString' },\n // Optional initial tour param\n start_onboarding_tour: { type: 'query', squash: true, value: undefined },\n }\n },\n {\n name: 'work-packages.new',\n url: '/new?type&parent_id',\n component: WorkPackageNewFullViewComponent,\n reloadOnSearch: false,\n data: {\n baseRoute: 'work-packages',\n allowMovingInEditMode: true,\n bodyClasses: 'router--work-packages-full-create',\n menuItem: menuItemClass\n },\n },\n {\n name: 'work-packages.copy',\n url: '/{copiedFromWorkPackageId:[0-9]+}/copy',\n component: WorkPackageCopyFullViewComponent,\n reloadOnSearch: false,\n data: {\n baseRoute: 'work-packages',\n allowMovingInEditMode: true,\n bodyClasses: 'router--work-packages-full-create',\n menuItem: menuItemClass\n },\n },\n {\n name: 'work-packages.show',\n url: '/{workPackageId:[0-9]+}',\n // Redirect to 'activity' by default.\n redirectTo: 'work-packages.show.activity',\n component: WorkPackagesFullViewComponent,\n data: {\n baseRoute: 'work-packages',\n bodyClasses: 'router--work-packages-full-view',\n newRoute: 'work-packages.new',\n menuItem: menuItemClass\n }\n },\n {\n name: 'work-packages.show.activity',\n url: '/activity',\n component: WorkPackageActivityTabComponent,\n data: {\n parent: 'work-packages.show',\n menuItem: menuItemClass\n }\n },\n {\n name: 'work-packages.show.activity.details',\n url: '/activity/details/#{activity_no:\\d+}',\n component: WorkPackageActivityTabComponent,\n data: {\n parent: 'work-packages.show',\n menuItem: menuItemClass\n }\n },\n {\n name: 'work-packages.show.relations',\n url: '/relations',\n component: WorkPackageRelationsTabComponent,\n data: {\n parent: 'work-packages.show',\n menuItem: menuItemClass\n }\n },\n {\n name: 'work-packages.show.watchers',\n url: '/watchers',\n component: WorkPackageWatchersTabComponent,\n data: {\n parent: 'work-packages.show',\n menuItem: menuItemClass\n }\n },\n {\n name: 'work-packages.partitioned',\n component: WorkPackageViewPageComponent,\n url: '',\n data: {\n // This has to be empty to avoid inheriting the parent bodyClasses\n bodyClasses: ''\n }\n },\n {\n name: 'work-packages.partitioned.list',\n url: '',\n reloadOnSearch: false,\n views: {\n 'content-left': { component: WorkPackageListViewComponent }\n },\n data: {\n bodyClasses: 'router--work-packages-partitioned-split-view',\n menuItem: menuItemClass,\n partition: '-left-only'\n }\n },\n ...makeSplitViewRoutes(\n 'work-packages.partitioned.list',\n menuItemClass,\n WorkPackageSplitViewComponent\n )\n // Avoid lazy-loading the routes for now\n // {\n // name: 'work-packages.calendar.**',\n // url: '/calendar',\n // loadChildren: '../calendar/openproject-calendar.module#OpenprojectCalendarModule'\n // },\n];\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {UIRouterModule} from \"@uirouter/angular\";\nimport {WORK_PACKAGES_ROUTES} from \"core-app/modules/work_packages/routing/work-packages-routes\";\nimport {OpenprojectWorkPackagesModule} from \"core-app/modules/work_packages/openproject-work-packages.module\";\n\n/**\n * Separate module for work package routes because WP modules\n * are required by other lazy-loaded modules such as calendar.\n *\n * And we must not re-import a module with route definitions.\n */\n\n@NgModule({\n imports: [\n // Import the actual WP modules\n OpenprojectWorkPackagesModule,\n\n // Routes for /work_packages\n UIRouterModule.forChild({ states: WORK_PACKAGES_ROUTES }),\n ]\n})\nexport class OpenprojectWorkPackageRoutesModule {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {BehaviorSubject} from 'rxjs';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {Injector} from \"@angular/core\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\n\n@Injectable()\nexport class GlobalSearchService {\n private _searchTerm = new BehaviorSubject('');\n public searchTerm$ = this._searchTerm.asObservable();\n\n // Default selected tab is Work Packages\n private _currentTab = new BehaviorSubject('work_packages');\n public currentTab$ = this._currentTab.asObservable();\n\n // Default project scope is \"this project and all subprojets\"\n private _projectScope = new BehaviorSubject('');\n public projectScope$ = this._projectScope.asObservable();\n\n private _tabs = new BehaviorSubject([]);\n public tabs$ = this._tabs.asObservable();\n\n // Sometimes we need to be able to hide the search results altogether, i.e. while expecting a full page reload.\n private _resultsHidden = new BehaviorSubject(false);\n public resultsHidden$ = this._resultsHidden.asObservable();\n\n constructor(protected I18n:I18nService,\n protected injector:Injector,\n protected PathHelper:PathHelperService,\n protected currentProjectService:CurrentProjectService) {\n this.initialize();\n }\n\n private initialize():void {\n let initialData = this.loadGonData();\n if (initialData) {\n if (initialData.available_search_types) {\n this._tabs.next(initialData.available_search_types);\n }\n if (initialData.search_term) {\n this._searchTerm.next(initialData.search_term);\n }\n if (initialData.current_tab) {\n this._currentTab.next(initialData.current_tab);\n }\n\n if (initialData.project_scope) {\n this._projectScope.next(initialData.project_scope);\n } else if (!this.currentProjectService.path) {\n this._projectScope.next('all');\n }\n }\n }\n\n private loadGonData():{available_search_types:string[],\n search_term:string,\n project_scope:string,\n current_tab:string}|null {\n try {\n return (window as any).gon.global_search;\n } catch (e) {\n return null;\n }\n }\n\n public submitSearch():void {\n window.location.href = this.searchPath();\n }\n\n public searchPath() {\n let searchPath:string = this.PathHelper.staticBase;\n if (this.currentProjectService.path && this.projectScope !== 'all') {\n searchPath = this.currentProjectService.path;\n }\n searchPath = searchPath + `/search?${this.searchQueryParams()}`;\n return searchPath;\n }\n\n public set searchTerm(searchTerm:string) {\n this._searchTerm.next(searchTerm);\n }\n\n public get searchTerm():string {\n return this._searchTerm.value;\n }\n\n public get tabs():string {\n return this._tabs.value;\n }\n\n public get currentTab():string {\n return this._currentTab.value;\n }\n\n public set currentTab(tab:string) {\n this._currentTab.next(tab);\n }\n\n public get projectScope():string {\n return this._projectScope.value;\n }\n\n public set projectScope(value:string) {\n this._projectScope.next(value);\n }\n\n public get resultsHidden():boolean {\n return this._resultsHidden.value;\n }\n\n public set resultsHidden(value:boolean) {\n this._resultsHidden.next(value);\n }\n\n private searchQueryParams():string {\n let params:string;\n\n params = `q=${encodeURIComponent(this.searchTerm)}`;\n\n if (this.currentTab.length > 0 && this.currentTab !== 'all') {\n params = `${params}&${this.currentTab}=1`;\n }\n if (this.projectScope.length > 0) {\n params = `${params}&scope=${this.projectScope}`;\n }\n\n return params;\n }\n\n public isAfterSearch():boolean {\n return (jQuery('body.controller-search').length > 0);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {OpenprojectWorkPackagesModule} from \"core-app/modules/work_packages/openproject-work-packages.module\";\nimport {GlobalSearchInputComponent} from \"core-app/modules/global_search/input/global-search-input.component\";\nimport {GlobalSearchWorkPackagesComponent} from \"core-app/modules/global_search/global-search-work-packages.component\";\nimport {GlobalSearchTabsComponent} from \"core-app/modules/global_search/tabs/global-search-tabs.component\";\nimport {GlobalSearchTitleComponent} from \"core-app/modules/global_search/title/global-search-title.component\";\nimport {GlobalSearchService} from \"core-app/modules/global_search/services/global-search.service\";\nimport {GlobalSearchWorkPackagesEntryComponent} from \"core-app/modules/global_search/global-search-work-packages-entry.component\";\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n OpenprojectWorkPackagesModule\n ],\n providers: [\n GlobalSearchService,\n ],\n declarations: [\n GlobalSearchInputComponent,\n GlobalSearchWorkPackagesEntryComponent,\n GlobalSearchWorkPackagesComponent,\n GlobalSearchTabsComponent,\n GlobalSearchTitleComponent,\n ]\n})\nexport class OpenprojectGlobalSearchModule { }\n\n","import {BehaviorSubject} from \"rxjs\";\nimport {filter, take} from \"rxjs/operators\";\nimport {Injectable} from \"@angular/core\";\n\n@Injectable({ providedIn: 'root' })\nexport class MainMenuNavigationService {\n\n public navigationEvents$ = new BehaviorSubject('');\n\n public onActivate(...names:string[]) {\n return this\n .navigationEvents$\n .pipe(\n filter(evt => names.indexOf(evt) !== -1),\n take(1)\n );\n }\n\n private recreateToggler() {\n let that = this;\n // rejigger the main-menu sub-menu functionality.\n jQuery(\"#main-menu .toggler\").remove(); // remove the togglers so they're inserted properly later.\n\n var toggler = jQuery('')\n .on('click', function() {\n let target = jQuery(this);\n if (target.hasClass('toggler')) {\n\n // TODO: Instead of hiding the sidebar move sidebar's contents to submenus and cache it.\n jQuery('#sidebar').toggleClass('-hidden', true);\n\n jQuery(\".menu_root li\").removeClass('open')\n jQuery(\".menu_root\").removeClass('open').addClass('closed');\n\n let targetLi = target.closest('li')\n targetLi\n .addClass('open')\n .find('li > a:first, .tree-menu--title:first').first().focus();\n\n console.log(\"Activating \" + targetLi.data('name'));\n that.navigationEvents$.next(targetLi.data('name'));\n }\n return false;\n });\n toggler.attr('title', I18n.t('js.project_menu_details'));\n\n return toggler;\n }\n\n private wrapMainItem() {\n var mainItems = jQuery('#main-menu li > a').not('ul ul a');\n\n mainItems.wrap((index:number) => {\n var item = mainItems[index];\n var elementId = item.id;\n\n var wrapperElement = jQuery('
      ')\n\n // inherit element id\n if (elementId) {\n wrapperElement.attr('id', elementId + '-wrapper')\n }\n\n return wrapperElement;\n });\n }\n\n register() {\n\n // Wrap main item\n this.wrapMainItem();\n\n // Scroll to the active item\n const selected = jQuery('.main-item-wrapper a.selected');\n if (selected.length > 0) {\n selected[0].scrollIntoView();\n }\n\n\n // Recreate toggler\n const toggler = this.recreateToggler();\n\n // Emit first active\n let active = jQuery('#main-menu .menu_root > li.open').data('name');\n let activeRoot = jQuery('#main-menu .menu_root.open > li').data('name');\n if (active || activeRoot) {\n this.navigationEvents$.next(active || activeRoot);\n }\n\n jQuery('#main-menu li:has(ul) .main-item-wrapper > a').not('ul ul a')\n // 1. unbind the current click functions\n .unbind('click')\n // 2. wrap each in a span that we'll use for the new click element\n .wrapInner('')\n // 3. reinsert the so that it sits outside of the above\n .after(toggler);\n\n function navigateUp(this:any, event:any) {\n event.preventDefault();\n var target = jQuery(this);\n jQuery(target).parents('li').first().removeClass('open');\n jQuery(\".menu_root\").removeClass('closed').addClass('open');\n\n target.parents('li').first().find('.toggler').first().focus();\n\n // TODO: Instead of hiding the sidebar move sidebar's contents to submenus and cache it.\n jQuery('#sidebar').toggleClass('-hidden', false);\n }\n\n jQuery('#main-menu ul.main-menu--children').each(function(_i, child) {\n var title = jQuery(child).parents('li').find('.main-item-wrapper .menu-item--title').contents()[0].textContent;\n var parentURL = jQuery(child).parents('li').find('.main-item-wrapper > a').attr('href');\n var header = jQuery('
      ');\n var upLink = jQuery('');\n var parentLink = jQuery('' + title + '');\n upLink.attr('title', I18n.t('js.label_up'));\n upLink.on('click', navigateUp);\n header.append(upLink);\n header.append(parentLink);\n jQuery(child).before(header);\n });\n\n if (jQuery('.menu_root').hasClass('closed')) {\n // TODO: Instead of hiding the sidebar move sidebar's contents to submenus and cache it.\n jQuery('#sidebar').toggleClass('-hidden', true);\n }\n }\n\n}\n","import {ConfirmDialogService} from 'core-components/modals/confirm-dialog/confirm-dialog.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {BannersService} from 'core-app/modules/common/enterprise/banners.service';\nimport { Inject, Injectable } from '@angular/core';\nimport {DOCUMENT} from '@angular/common';\n\n@Injectable()\nexport class TypeBannerService extends BannersService {\n\n constructor(@Inject(DOCUMENT) protected documentElement:Document,\n private confirmDialog:ConfirmDialogService,\n private I18n:I18nService) {\n super(documentElement);\n }\n\n showEEOnlyHint():void {\n this.confirmDialog.confirm({\n text: {\n title: this.I18n.t('js.types.attribute_groups.upgrade_to_ee'),\n text: this.I18n.t('js.types.attribute_groups.upgrade_to_ee_text'),\n button_continue: this.I18n.t('js.types.attribute_groups.more_information'),\n button_cancel: this.I18n.t('js.types.attribute_groups.nevermind')\n }\n }).then(() => {\n window.location.href = 'https://www.openproject.org/enterprise-edition/?utm_source=unknown&utm_medium=community-edition&utm_campaign=form-configuration';\n });\n }\n}\n\n","
      \n
      \n \n
      \n
      \n\n
      \n
      \n
      \n \n \n \n \n \n \n
      \n
      \n
      \n
      \n
      \n \n &ngsp;\n \n
      \n
      \n
      \n \n \n {{ inactive_attribute.translation }}\n \n \n \n
      \n
      \n
      \n
      \n
      \n","import {AfterViewInit, Component, ElementRef, OnInit} from '@angular/core';\nimport {TypeBannerService} from 'core-app/modules/admin/types/type-banner.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {ExternalRelationQueryConfigurationService} from 'core-components/wp-table/external-configuration/external-relation-query-configuration.service';\nimport {DomAutoscrollService} from 'core-app/modules/common/drag-and-drop/dom-autoscroll.service';\nimport {DragulaService, DrakeWithModels} from 'ng2-dragula';\nimport {ConfirmDialogService} from 'core-components/modals/confirm-dialog/confirm-dialog.service';\nimport {Drake} from 'dragula';\nimport {GonService} from \"core-app/modules/common/gon/gon.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {install_menu_logic} from \"core-app/globals/global-listeners/action-menu\";\n\nexport type TypeGroupType = 'attribute'|'query';\n\nexport interface TypeFormAttribute {\n key:string;\n translation:string;\n is_cf:boolean;\n}\n\nexport interface TypeGroup {\n /** original internal key, if any */\n key:string|null|undefined;\n /** Localized / given name */\n name:string;\n attributes:TypeFormAttribute[];\n query?:any;\n type:TypeGroupType;\n}\n\nexport const adminTypeFormConfigurationSelector = 'admin-type-form-configuration';\nexport const emptyTypeGroup = '__empty';\n\n@Component({\n selector: adminTypeFormConfigurationSelector,\n templateUrl: './type-form-configuration.html',\n providers: [\n TypeBannerService,\n ]\n})\nexport class TypeFormConfigurationComponent extends UntilDestroyedMixin implements OnInit, AfterViewInit {\n\n public text = {\n drag_to_activate: this.I18n.t('js.admin.type_form.drag_to_activate'),\n reset: this.I18n.t('js.admin.type_form.reset_to_defaults'),\n label_group: this.I18n.t('js.label_group'),\n new_group: this.I18n.t('js.admin.type_form.new_group'),\n label_inactive: this.I18n.t('js.admin.type_form.inactive'),\n custom_field: this.I18n.t('js.admin.type_form.custom_field'),\n add_group: this.I18n.t('js.admin.type_form.add_group'),\n add_table: this.I18n.t('js.admin.type_form.add_table'),\n };\n\n private autoscroll:any;\n private element:HTMLElement;\n private form:JQuery;\n private submit:JQuery;\n\n public groups:TypeGroup[] = [];\n public inactives:TypeFormAttribute[] = [];\n\n private attributeDrake:DrakeWithModels;\n private groupsDrake:DrakeWithModels;\n\n private no_filter_query:string;\n\n constructor(private elementRef:ElementRef,\n private I18n:I18nService,\n private Gon:GonService,\n private dragula:DragulaService,\n private confirmDialog:ConfirmDialogService,\n private notificationsService:NotificationsService,\n private externalRelationQuery:ExternalRelationQueryConfigurationService) {\n super();\n }\n\n ngOnInit():void {\n // Hook on form submit\n this.element = this.elementRef.nativeElement;\n this.no_filter_query = this.element.dataset.noFilterQuery!;\n this.form = jQuery(this.element).closest('form');\n this.submit = this.form.find('.form-configuration--save');\n\n // In the following we are triggering the form submit ourselves to work around\n // a firefox shortcoming. But to avoid double submits which are sometimes not canceled fast\n // enough, we need to memoize whether we have already submitted.\n let submitted = false;\n\n this.form.on('submit', (event) => {\n submitted = true;\n });\n\n // Capture mousedown on button because firefox breaks blur on click\n this.submit.on('mousedown', (event) => {\n setTimeout(() => {\n if (!submitted) {\n this.form.trigger('submit');\n }\n }, 50);\n return true;\n });\n\n // Capture regular form submit\n this.form.on('submit.typeformupdater', () => {\n this.updateHiddenFields();\n return true;\n });\n\n // Setup groups\n this.groupsDrake = this\n .dragula\n .createGroup('groups', {\n moves: (el, source, handle:HTMLElement) => handle.classList.contains('group-handle')\n })\n .drake;\n\n // Setup attributes\n this.attributeDrake = this\n .dragula\n .createGroup('attributes', {\n moves: (el, source, handle:HTMLElement) => handle.classList.contains('attribute-handle')\n })\n .drake;\n\n // Get attribute id\n this.groups = JSON\n .parse(this.element.dataset.activeGroups!)\n .filter((group:TypeGroup) => group?.key !== emptyTypeGroup);\n this.inactives = JSON.parse(this.element.dataset.inactiveAttributes!);\n\n // Setup autoscroll\n const that = this;\n this.autoscroll = new DomAutoscrollService(\n [\n document.getElementById('content-wrapper')!\n ],\n {\n margin: 25,\n maxSpeed: 10,\n scrollWhenOutside: true,\n autoScroll: function (this:any) {\n const groups = that.groupsDrake && that.groupsDrake.dragging;\n const attributes = that.attributeDrake && that.attributeDrake.dragging;\n\n return groups || attributes;\n }\n });\n }\n\n ngAfterViewInit() {\n const menu = jQuery(this.elementRef.nativeElement).find('.toolbar-items');\n install_menu_logic(menu);\n }\n\n public deactivateAttribute(attribute:TypeFormAttribute) {\n this.updateInactives(this.inactives.concat(attribute));\n }\n\n public addGroupAndOpenQuery():void {\n let newGroup = this.createGroup('query');\n this.editQuery(newGroup);\n }\n\n public editQuery(group:TypeGroup) {\n // Disable display mode and timeline for now since we don't want users to enable it\n const disabledTabs = {\n 'display-settings': I18n.t('js.work_packages.table_configuration.embedded_tab_disabled'),\n 'timelines': I18n.t('js.work_packages.table_configuration.embedded_tab_disabled')\n };\n\n this.externalRelationQuery.show({\n currentQuery: JSON.parse(group.query),\n callback: (queryProps:any) => group.query = JSON.stringify(queryProps),\n disabledTabs\n });\n }\n\n public deleteGroup(group:TypeGroup) {\n if (group.type === 'attribute') {\n this.updateInactives(this.inactives.concat(group.attributes));\n }\n\n this.groups = this.groups.filter(el => el !== group);\n\n return group;\n }\n\n public createGroup(type:TypeGroupType, groupName:string = '') {\n let group:TypeGroup = {\n type: type,\n name: '',\n key: null,\n query: this.no_filter_query,\n attributes: [],\n };\n\n this.groups.unshift(group);\n return group;\n }\n\n public resetToDefault($event:Event):boolean {\n this.confirmDialog\n .confirm({\n text: {\n title: this.I18n.t('js.types.attribute_groups.reset_title'),\n text: this.I18n.t('js.types.attribute_groups.confirm_reset'),\n button_continue: this.I18n.t('js.label_reset')\n }\n })\n .then(() => {\n this.form.find('input#type_attribute_groups').val(JSON.stringify([]));\n\n // Disable our form handler that updates the attribute groups\n this.form.off('submit.typeformupdater');\n this.form.trigger('submit');\n });\n\n $event.preventDefault();\n return false;\n }\n\n private updateInactives(newValue:TypeFormAttribute[]) {\n this.inactives = [...newValue].sort((a, b) => a.translation.localeCompare(b.translation));\n }\n\n // We maintain an empty group\n // that gets hidden in the frontend in case the user\n // decides to remove all groups\n // This was necessary since the \"default\" is actually an empty array of groups\n private get emptyGroup():TypeGroup {\n return { type: 'attribute', key: emptyTypeGroup, name: 'empty', attributes: [] };\n }\n\n private updateHiddenFields() {\n const hiddenField = this.form.find('.admin-type-form--hidden-field');\n if (this.groups.length === 0) {\n // Ensure we're adding an empty group if deliberately removing\n // all values.\n hiddenField.val(JSON.stringify([this.emptyGroup]));\n } else {\n hiddenField.val(JSON.stringify(this.groups));\n }\n }\n}\n\n","
      \n
      \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n Input,\n OnInit,\n Output\n} from '@angular/core';\nimport {TypeBannerService} from 'core-app/modules/admin/types/type-banner.service';\n\n@Component({\n selector: 'group-edit-in-place',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './group-edit-in-place.html'\n})\nexport class GroupEditInPlaceComponent implements OnInit {\n @Input() public placeholder:string = '';\n @Input() public name:string;\n\n @Output() public onValueChange = new EventEmitter();\n\n public editing = false;\n\n public editedName:string;\n\n constructor(private bannerService:TypeBannerService,\n protected readonly cdRef:ChangeDetectorRef) {\n }\n\n ngOnInit():void {\n this.editedName = this.name;\n\n if (!this.name || this.name.length === 0) {\n // Group name is empty so open in editing mode straight away.\n this.startEditing();\n }\n }\n\n startEditing() {\n this.bannerService.conditional(\n () => this.bannerService.showEEOnlyHint(),\n () => {\n this.editing = true;\n }\n );\n }\n\n saveEdition(event:FocusEvent) {\n this.leaveEditingMode();\n this.name = this.editedName.trim();\n\n this.cdRef.detectChanges();\n\n if (this.name !== '') {\n this.onValueChange.emit(this.name);\n }\n\n // Ensure form is not submitted.\n event.preventDefault();\n event.stopPropagation();\n return false;\n }\n\n reset() {\n this.editing = false;\n this.editedName = this.name;\n }\n\n leaveEditingMode() {\n // Only leave Editing mode if name not empty.\n if (this.editedName != null && this.editedName.trim().length > 0) {\n this.editing = false;\n }\n }\n}\n","
      \n
      \n \n \n \n \n
      \n
      \n
      \n \n \n {{ attribute.translation }}\n \n \n \n \n
      \n
      \n
      \n","import {ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output} from '@angular/core';\nimport {TypeFormAttribute, TypeGroup} from \"core-app/modules/admin/types/type-form-configuration.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n selector: 'type-form-attribute-group',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './attribute-group.component.html'\n})\nexport class TypeFormAttributeGroupComponent {\n @Input() public group:TypeGroup;\n\n @Output() public deleteGroup = new EventEmitter();\n @Output() public removeAttribute = new EventEmitter();\n\n text = {\n custom_field: this.I18n.t('js.admin.type_form.custom_field')\n };\n\n constructor(private I18n:I18nService,\n private cdRef:ChangeDetectorRef) {\n }\n\n rename(newValue:string) {\n this.group.name = newValue;\n delete this.group.key;\n this.cdRef.detectChanges();\n }\n\n removeFromGroup(attribute:TypeFormAttribute) {\n this.group.attributes = this.group.attributes.filter(a => a !== attribute);\n this.removeAttribute.emit(attribute);\n }\n}\n","import {ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n selector: 'type-form-query-group',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './query-group.component.html'\n})\nexport class TypeFormQueryGroupComponent {\n\n text = {\n edit_query: this.I18n.t('js.admin.type_form.edit_query')\n };\n\n @Input() public group:any;\n @Output() public editQuery = new EventEmitter();\n @Output() public deleteGroup = new EventEmitter();\n\n constructor(private I18n:I18nService,\n private cdRef:ChangeDetectorRef) {\n }\n\n rename(newValue:string) {\n this.group.name = newValue;\n this.cdRef.detectChanges();\n }\n}\n","
      \n
      \n \n \n \n \n
      \n
      \n \n \n {{ text.edit_query }}\n \n
      \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {TypeFormConfigurationComponent} from 'core-app/modules/admin/types/type-form-configuration.component';\nimport {GroupEditInPlaceComponent} from 'core-app/modules/admin/types/group-edit-in-place.component';\nimport {TypeFormAttributeGroupComponent} from 'core-app/modules/admin/types/attribute-group.component';\nimport {DragulaModule} from 'ng2-dragula';\nimport {TypeFormQueryGroupComponent} from \"core-app/modules/admin/types/query-group.component\";\nimport {OpenprojectAccessibilityModule} from \"core-app/modules/a11y/openproject-a11y.module\";\nimport {EditableQueryPropsComponent} from \"core-app/modules/admin/editable-query-props/editable-query-props.component\";\n\n@NgModule({\n imports: [\n DragulaModule.forRoot(),\n OpenprojectCommonModule,\n OpenprojectAccessibilityModule\n ],\n providers: [\n ],\n declarations: [\n TypeFormAttributeGroupComponent,\n TypeFormQueryGroupComponent,\n TypeFormConfigurationComponent,\n GroupEditInPlaceComponent,\n EditableQueryPropsComponent,\n ]\n})\nexport class OpenprojectAdminModule { }\n","
      \n
      \n
      \n \n \n \n \n

      \n
      \n\n
      \n
      \n
      \n\n \n \n
      \n
      \n
      \n","import {Component, ElementRef, Inject, ChangeDetectorRef} from \"@angular/core\";\nimport {OpModalComponent} from \"app/components/op-modals/op-modal.component\";\nimport {WidgetRegistration} from \"app/modules/grids/grid/grid.component\";\nimport {OpModalLocalsToken} from \"app/components/op-modals/op-modal.service\";\nimport {OpModalLocalsMap} from \"app/components/op-modals/op-modal.types\";\nimport {GridWidgetsService} from \"app/modules/grids/widgets/widgets.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {BannersService} from \"core-app/modules/common/enterprise/banners.service\";\n\n@Component({\n templateUrl: './add.modal.html'\n})\nexport class AddGridWidgetModal extends OpModalComponent {\n\n text = {\n title: this.i18n.t('js.grid.add_widget'),\n close_popup: this.i18n.t('js.button_close'),\n upsale_link: this.i18n.t('js.grid.upsale.link'),\n upsale_text: this.i18n.t('js.grid.upsale.text')\n };\n\n public chosenWidget:WidgetRegistration;\n public eeShowBanners = false;\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) readonly locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly widgetsService:GridWidgetsService,\n readonly i18n:I18nService,\n readonly bannerService:BannersService) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n super.ngOnInit();\n this.eeShowBanners = this.bannerService.eeShowBanners;\n }\n\n public get selectable() {\n return this.eligibleWidgets.sort((a, b) => {\n return a.title.localeCompare(b.title);\n });\n }\n\n public select($event:any, widget:WidgetRegistration) {\n this.chosenWidget = widget;\n this.closeMe($event);\n }\n\n public trackWidgetBy(widget:WidgetRegistration) {\n return widget.identifier;\n }\n\n private get eligibleWidgets() {\n let schemaWidgetIdentifiers = this.locals.schema.widgets.allowedValues.map((widget:any) => {\n return widget.identifier;\n });\n\n return this.widgetsService.registered.filter((widget) => {\n return schemaWidgetIdentifiers.includes(widget.identifier);\n });\n }\n}\n","import {Injectable} from '@angular/core';\nimport {GridWidgetArea} from \"app/modules/grids/areas/grid-widget-area\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\n\n\n@Injectable()\nexport class GridMoveService {\n constructor(private layout:GridAreaService) {}\n\n public down(movedArea:GridWidgetArea|null, ignoreArea:GridWidgetArea) {\n let movedAreas:GridWidgetArea[] = [];\n let remainingAreas:GridWidgetArea[] = this.layout.widgetAreas.slice(0);\n\n if (ignoreArea) {\n remainingAreas = remainingAreas.filter((area) => {\n return area.guid !== ignoreArea.guid;\n });\n }\n\n remainingAreas.sort((a, b) => {\n return b.startRow - a.startRow;\n });\n\n while (movedArea !== null) {\n movedAreas.push(movedArea!);\n\n remainingAreas = remainingAreas.filter((area) => {\n return area.guid !== movedArea!.guid;\n });\n\n movedArea = this.moveOneDown(movedAreas, remainingAreas);\n }\n }\n\n private moveOneDown(anchorAreas:GridWidgetArea[], movableAreas:GridWidgetArea[]) {\n let moveSpecification = this.firstAreaToMove(anchorAreas, movableAreas);\n\n if (moveSpecification) {\n let toMoveArea = moveSpecification[0] as GridWidgetArea;\n let anchorArea = moveSpecification[1] as GridWidgetArea;\n\n let areaHeight = toMoveArea.widget.height;\n\n toMoveArea.startRow = anchorArea.endRow;\n toMoveArea.endRow = toMoveArea.startRow + areaHeight;\n\n if (this.layout.numRows < toMoveArea.endRow - 1) {\n this.layout.numRows = toMoveArea.endRow - 1;\n }\n\n return toMoveArea;\n } else {\n return null;\n }\n }\n\n // Return first area that needs to move as it overlaps another area.\n // There are two groups of areas here. The first (anchorAreas) is considered stable\n // and as such not fit for being moved. This happens e.g. when the user explicitly\n // moved a widget or if the area has already been moved in a previous run of this method.\n // The second group (movableAreas) consists of all areas that are movable.\n // Once an area out of the second group has been identified that overlaps an area of the first\n // group, the appropriate reference area for later moving is selected out of the group of all\n // unmovable areas. The reference area is the bottommost area within the unmovable areas which's\n // column values (start/end) include the to move area's start column value and which's end row is larger\n // than the area overlapping the area to move. Unmovable areas which's column values do not include the\n // start column are to the left or right of the area to move and can thus be ignored.\n private firstAreaToMove(anchorAreas:GridWidgetArea[], movableAreas:GridWidgetArea[]) {\n let overlappingArea:GridWidgetArea|null = null;\n let toMoveArea:GridWidgetArea|null = null;\n\n movableAreas.forEach((movableArea) => {\n anchorAreas.forEach((anchorArea) => {\n if (anchorArea.overlaps(movableArea)) {\n overlappingArea = anchorArea;\n toMoveArea = movableArea;\n return;\n }\n });\n\n if (toMoveArea) {\n return;\n }\n });\n\n if (toMoveArea !== null) {\n let referenceArea = overlappingArea!;\n\n anchorAreas.forEach((anchorArea) => {\n if (anchorArea.endRow > referenceArea.endRow && toMoveArea!.columnOverlaps(anchorArea)) {\n referenceArea = anchorArea;\n }\n });\n\n return [toMoveArea, referenceArea];\n } else {\n return null;\n }\n }\n}\n","import {Injectable, OnDestroy} from '@angular/core';\nimport {GridWidgetArea} from \"core-app/modules/grids/areas/grid-widget-area\";\nimport {GridArea} from \"core-app/modules/grids/areas/grid-area\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\nimport {GridMoveService} from \"core-app/modules/grids/grid/move.service\";\nimport { Subscription } from 'rxjs';\nimport { filter, distinctUntilChanged, throttleTime } from 'rxjs/operators';\n\n@Injectable()\nexport class GridDragAndDropService implements OnDestroy {\n public draggedArea:GridWidgetArea|null;\n public placeholderArea:GridWidgetArea|null;\n public draggedHeight:number|null;\n private mousedOverAreaObserver:Subscription;\n\n constructor(readonly layout:GridAreaService,\n readonly move:GridMoveService) {\n // ngOnInit is not called on services\n this.setupMousedOverAreaSubscription();\n }\n\n ngOnDestroy():void {\n this.mousedOverAreaObserver.unsubscribe();\n }\n\n private setupMousedOverAreaSubscription() {\n this.mousedOverAreaObserver = this\n .layout\n .$mousedOverArea\n .pipe(\n // avoid flickering of widgets as the grid gets resized by the placeholder movement\n throttleTime(10),\n distinctUntilChanged(),\n filter((area) => this.currentlyDragging && !!area && !this.layout.isGap(area) && (this.placeholderArea!.startRow !== area.startRow || this.placeholderArea!.startColumn !== area.startColumn)),\n ).subscribe(area => {\n this.updateArea(area!);\n\n this.layout.scrollPlaceholderIntoView();\n });\n }\n\n private updateArea(area:GridArea) {\n this.layout.resetAreas(this.draggedArea);\n this.moveAreasOnDragging(area);\n }\n\n private moveAreasOnDragging(dropArea:GridArea) {\n if (!this.placeholderArea) {\n return;\n }\n let widgetArea = this.draggedArea!;\n\n // Set the draggedArea's startRow/startColumn properties\n // to the drop zone ones.\n // The dragged Area should keep it's height and width normally but will\n // shrink if the area would otherwise end outside the grid.\n // we cannot use the widget's original area as moving it while dragging confuses cdkDrag\n this.copyPositionButRestrict(dropArea, this.placeholderArea);\n\n this.move.down(this.placeholderArea, widgetArea);\n }\n\n public get currentlyDragging() {\n return !!this.draggedArea;\n }\n\n public isDropOnlyArea(area:GridArea) {\n return !this.currentlyDragging && area.endRow === this.layout.numRows + 2;\n }\n\n public isDragged(area:GridWidgetArea) {\n return this.currentlyDragging && this.draggedArea!.guid === area.guid;\n }\n\n public isPassive(area:GridWidgetArea) {\n return this.currentlyDragging && !this.isDragged(area);\n }\n\n public get isDraggable() {\n return this.layout.isEditable;\n }\n\n public start(area:GridWidgetArea) {\n this.placeholderArea = new GridWidgetArea(area.widget);\n // TODO find an angular way to do this that ideally does not require passing the element from the grid component\n this.draggedHeight = (document as any).getElementById(area.guid).offsetHeight - 2; // border width * 2\n this.draggedArea = area;\n }\n\n public abort() {\n document.dispatchEvent(new Event('mouseup'));\n this.draggedArea = null;\n this.placeholderArea = null;\n this.layout.resetAreas();\n }\n\n public drop() {\n if (!this.draggedArea) {\n return;\n }\n\n this.placeholderArea!.copyDimensionsTo(this.draggedArea!)\n\n if (!this.draggedArea!.unchangedSize) {\n this.layout.writeAreaChangesToWidgets();\n this.layout.cleanupUnusedAreas();\n this.layout.rebuildAndPersist();\n }\n\n this.draggedArea = null;\n this.placeholderArea = null;\n }\n\n private copyPositionButRestrict(source:GridArea, sink:GridWidgetArea) {\n sink.startRow = source.startRow;\n\n // The first condition is aimed at the case when the user drags an element to the very last row\n // which is not reflected by the numRows.\n if (source.startRow === this.layout.numRows + 1) {\n sink.endRow = this.layout.numRows + 2;\n } else if (source.startRow + sink.widget.height > this.layout.numRows + 1) {\n sink.endRow = this.layout.numRows + 1;\n } else {\n sink.endRow = source.startRow + sink.widget.height;\n }\n\n sink.startColumn = source.startColumn;\n if (source.startColumn + sink.widget.width > this.layout.numColumns + 1) {\n sink.endColumn = this.layout.numColumns + 1;\n } else {\n sink.endColumn = source.startColumn + sink.widget.width;\n }\n }\n\n}\n","import {Injectable} from '@angular/core';\nimport {GridWidgetArea} from \"core-app/modules/grids/areas/grid-widget-area\";\nimport {GridArea} from \"core-app/modules/grids/areas/grid-area\";\nimport {ResizeDelta} from \"core-app/modules/common/resizer/resizer.component\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\nimport {GridMoveService} from \"core-app/modules/grids/grid/move.service\";\nimport {GridDragAndDropService} from \"core-app/modules/grids/grid/drag-and-drop.service\";\n\n@Injectable()\nexport class GridResizeService {\n private resizedArea:GridWidgetArea|null;\n private targetIds:string[];\n\n constructor(readonly layout:GridAreaService,\n readonly move:GridMoveService,\n readonly drag:GridDragAndDropService) { }\n\n public end(area:GridWidgetArea) {\n if (!this.resizedArea) {\n return;\n }\n\n this.resizedArea = null;\n\n // user aborted resizing\n if (area.unchangedSize) {\n return;\n }\n\n this.layout.writeAreaChangesToWidgets();\n this.layout.cleanupUnusedAreas();\n\n this.layout.rebuildAndPersist();\n }\n\n public abort() {\n if (this.resizedArea) {\n this.layout.resetAreas();\n this.resizedArea = null;\n }\n }\n\n public start(resizedArea:GridWidgetArea) {\n this.resizedArea = resizedArea;\n\n let resizeTargets = this.layout.gridAreas.filter((area) => {\n // All areas on the same row which are after the current column are valid targets.\n let sameRow = area.startRow === this.resizedArea!.startRow &&\n area.startColumn >= this.resizedArea!.startColumn;\n\n // Areas that are on higher (number, they are printed below) rows\n // are allowed as long as there is guaranteed to always be one widget\n // before or after the resized to area.\n let higherRow = area.startRow > this.resizedArea!.startRow &&\n area.startColumn >= this.resizedArea!.startColumn &&\n this.layout.widgetAreas.some((fixedArea) => {\n return fixedArea.startRow === area.startRow &&\n // before\n (fixedArea.endColumn <= this.resizedArea!.startColumn ||\n // after\n fixedArea.startColumn >= area.endColumn);\n });\n return sameRow || higherRow;\n });\n\n this.targetIds = resizeTargets\n .map(area => area.guid);\n }\n\n public moving(deltas:ResizeDelta) {\n if (!this.resizedArea ||\n !this.layout.mousedOverArea ||\n !this.targetIds.includes(this.layout.mousedOverArea.guid)) {\n return;\n }\n\n this.layout.resetAreas();\n\n this.resizedArea.endRow = this.layout.mousedOverArea.endRow;\n this.resizedArea.endColumn = this.layout.mousedOverArea.endColumn;\n\n this.move.down(this.resizedArea, this.resizedArea);\n }\n\n public isTarget(area:GridArea) {\n let areaId = area.guid;\n\n return this.resizedArea && this.targetIds.includes(areaId);\n }\n\n public isResized(area:GridWidgetArea) {\n return this.resizedArea && this.resizedArea.guid === area.guid;\n }\n\n public isPassive(area:GridWidgetArea) {\n return this.currentlyResizing && !this.isResized(area);\n }\n\n public get currentlyResizing() {\n return !!this.resizedArea;\n }\n\n public get isResizable() {\n return !this.drag.currentlyDragging && this.isAllowed;\n }\n\n private get isAllowed() {\n return this.layout.gridResource.updateImmediately;\n }\n}\n","import {Injectable, Injector} from \"@angular/core\";\nimport {OpModalService} from \"app/components/op-modals/op-modal.service\";\nimport {AddGridWidgetModal} from \"app/modules/grids/widgets/add/add.modal\";\nimport {GridWidgetResource} from \"app/modules/hal/resources/grid-widget-resource\";\nimport {GridArea} from \"app/modules/grids/areas/grid-area\";\nimport {HalResourceService} from \"app/modules/hal/services/hal-resource.service\";\nimport {GridWidgetArea} from \"core-app/modules/grids/areas/grid-widget-area\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\nimport {GridDragAndDropService} from \"core-app/modules/grids/grid/drag-and-drop.service\";\nimport {GridResizeService} from \"core-app/modules/grids/grid/resize.service\";\nimport {GridMoveService} from \"core-app/modules/grids/grid/move.service\";\nimport {GridGap} from \"core-app/modules/grids/areas/grid-gap\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Injectable()\nexport class GridAddWidgetService {\n\n text = { add: this.i18n.t('js.grid.add_widget') };\n\n constructor(readonly opModalService:OpModalService,\n readonly injector:Injector,\n readonly halResource:HalResourceService,\n readonly layout:GridAreaService,\n readonly drag:GridDragAndDropService,\n readonly move:GridMoveService,\n readonly resize:GridResizeService,\n readonly i18n:I18nService) {\n }\n\n public isAddable(area:GridArea) {\n return !this.drag.currentlyDragging &&\n !this.resize.currentlyResizing &&\n (this.layout.mousedOverArea === area || this.layout.isSingleCell || this.layout.inHelpMode) &&\n this.isAllowed;\n }\n\n public widget(area:GridArea) {\n this\n .select(area)\n .then((widgetResource) => {\n\n if (this.layout.isGap(area)) {\n this.addLine(area as GridGap);\n }\n\n let newArea = new GridWidgetArea(widgetResource);\n\n this.setMaxWidth(newArea);\n\n this.persist(newArea);\n })\n .catch(() => {\n // user didn't select a widget\n });\n }\n\n public get addText() {\n return this.text.add;\n }\n\n private select(area:GridArea) {\n return new Promise((resolve, reject) => {\n const modal = this.opModalService.show(AddGridWidgetModal, this.injector, { schema: this.layout.schema });\n modal.closingEvent.subscribe((modal:AddGridWidgetModal) => {\n let registered = modal.chosenWidget;\n\n if (!registered) {\n reject();\n return;\n }\n\n let source = {\n _type: 'GridWidget',\n identifier: registered.identifier,\n startRow: area.startRow,\n endRow: area.endRow,\n startColumn: area.startColumn,\n endColumn: area.endColumn,\n options: registered.properties || {}\n };\n\n let resource = this.halResource.createHalResource(source) as GridWidgetResource;\n\n resource.grid = this.layout.gridResource;\n\n resolve(resource);\n });\n });\n }\n\n private addLine(area:GridGap) {\n if (area.isRow) {\n // - 1 to have it added before\n this.layout.addRow(area.startRow - 1, area.startColumn);\n } else if (area.isColumn) {\n // - 1 to have it added before\n this.layout.addColumn(area.startColumn - 1, area.startRow);\n }\n }\n\n // try to set it to a layout with a height of 1 and as wide as possible\n // but shrink if that is outside the grid or overlaps any other widget\n private setMaxWidth(area:GridWidgetArea) {\n area.endColumn = this.layout.numColumns + 1;\n\n this.layout.widgetAreas.forEach((existingArea) => {\n if (area.startColumnOverlaps(existingArea)) {\n area.endColumn = existingArea.startColumn;\n }\n });\n }\n\n private persist(area:GridWidgetArea) {\n area.writeAreaChangeToWidget();\n this.layout.widgetAreas.push(area);\n this.layout.widgetResources.push(area.widget);\n this.layout.rebuildAndPersist();\n }\n\n public get isAllowed() {\n return this.layout.gridResource && this.layout.gridResource.updateImmediately;\n }\n}\n","import { ChangeDetectorRef, OnDestroy, OnInit, Renderer2, Directive } from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {Title} from '@angular/platform-browser';\nimport {GridInitializationService} from \"core-app/modules/grids/grid/initialization.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {GridAddWidgetService} from \"core-app/modules/grids/grid/add-widget.service\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\n\n@Directive()\nexport abstract class GridPageComponent implements OnInit, OnDestroy {\n public text = { title: this.i18n.t(`js.${this.i18nNamespace()}.label`),\n html_title: this.i18n.t(`js.${this.i18nNamespace()}.label`) };\n\n constructor(readonly gridInitialization:GridInitializationService,\n // not used in the base class but will be used throughout the subclasses\n readonly pathHelper:PathHelperService,\n readonly currentProject:CurrentProjectService,\n readonly i18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly title:Title,\n readonly addWidget:GridAddWidgetService,\n readonly renderer:Renderer2,\n readonly areas:GridAreaService) {}\n\n public grid:GridResource;\n\n ngOnInit() {\n this.renderer.addClass(document.body, 'widget-grid-layout');\n this\n .gridInitialization\n .initialize(this.gridScopePath())\n .then((grid) => {\n this.grid = grid;\n this.cdRef.detectChanges();\n });\n\n this.setHtmlTitle();\n }\n\n ngOnDestroy():void {\n this.renderer.removeClass(document.body, 'widget-grid-layout');\n }\n\n private setHtmlTitle() {\n this.title.setTitle(this.text.html_title);\n }\n\n protected abstract i18nNamespace():string;\n\n protected abstract gridScopePath():string;\n}\n","
      \n\n \n
      \n
      \n\n \n\n \n \n
      \n \n
      \n \n \n
      \n
      \n
      \n\n \n
      \n
      \n
      \n
      \n\n
      \n
      \n
      \n
      \n\n \n
      \n
      \n
      \n
      \n
      \n","import {Component,\n ComponentRef,\n OnDestroy,\n OnInit,\n Input,\n HostListener} from \"@angular/core\";\nimport {GridResource} from \"app/modules/hal/resources/grid-resource\";\nimport {DomSanitizer} from \"@angular/platform-browser\";\nimport {GridWidgetsService} from \"app/modules/grids/widgets/widgets.service\";\nimport {AbstractWidgetComponent} from \"app/modules/grids/widgets/abstract-widget.component\";\nimport {GridArea} from \"app/modules/grids/areas/grid-area\";\nimport {GridMoveService} from \"app/modules/grids/grid/move.service\";\nimport {GridDragAndDropService} from \"core-app/modules/grids/grid/drag-and-drop.service\";\nimport {GridResizeService} from \"core-app/modules/grids/grid/resize.service\";\nimport {GridAreaService} from \"core-app/modules/grids/grid/area.service\";\nimport {GridAddWidgetService} from \"core-app/modules/grids/grid/add-widget.service\";\nimport {GridRemoveWidgetService} from \"core-app/modules/grids/grid/remove-widget.service\";\nimport {WidgetWpGraphComponent} from \"core-app/modules/grids/widgets/wp-graph/wp-graph.component\";\nimport {GridWidgetArea} from \"core-app/modules/grids/areas/grid-widget-area\";\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\n\nexport interface WidgetRegistration {\n identifier:string;\n title:string;\n component:{ new (...args:any[]):AbstractWidgetComponent };\n properties?:any;\n}\n\nexport const GRID_PROVIDERS = [\n GridAreaService,\n GridMoveService,\n GridDragAndDropService,\n GridResizeService,\n GridAddWidgetService,\n GridRemoveWidgetService\n];\n\n@Component({\n templateUrl: './grid.component.html',\n selector: 'grid'\n})\nexport class GridComponent implements OnDestroy, OnInit {\n public uiWidgets:ComponentRef[] = [];\n public GRID_AREA_HEIGHT = 'auto';\n public GRID_GAP_DIMENSION = '20px';\n\n public component = WidgetWpGraphComponent;\n\n @Input() grid:GridResource;\n\n constructor(private sanitization:DomSanitizer,\n private widgetsService:GridWidgetsService,\n public drag:GridDragAndDropService,\n public resize:GridResizeService,\n public layout:GridAreaService,\n public add:GridAddWidgetService,\n public remove:GridRemoveWidgetService,\n readonly browserDetector:BrowserDetector) {\n }\n\n ngOnInit() {\n this.layout.gridResource = this.grid;\n }\n\n ngOnDestroy() {\n this.uiWidgets.forEach((widget) => widget.destroy());\n }\n\n @HostListener('window:keyup', ['$event'])\n handleKeyboardEvent(event:KeyboardEvent) {\n if (event.key !== 'Escape') {\n return;\n } else if (this.drag.currentlyDragging) {\n this.drag.abort();\n } else if (this.resize.currentlyResizing) {\n this.resize.abort();\n }\n }\n\n public widgetComponent(area:GridWidgetArea) {\n let widget = area.widget;\n\n if (!widget) {\n return null;\n }\n\n let registration = this.widgetsService.registered.find((reg) => reg.identifier === widget.identifier);\n\n if (!registration) {\n // debugLog(`No widget registered with identifier ${widget.identifier}`);\n\n return null;\n } else {\n return registration.component;\n }\n }\n\n public widgetComponentInput(area:GridWidgetArea) {\n return { resource: area.widget };\n }\n\n public widgetComponentOutput(area:GridWidgetArea) {\n return { resourceChanged: this.layout.saveWidgetChangeset.bind(this.layout) };\n }\n\n public get gridColumnStyle() {\n return this.gridStyle(this.layout.numColumns,\n `calc((100% - ${this.GRID_GAP_DIMENSION} * ${this.layout.numColumns + 1}) / ${this.layout.numColumns})`);\n }\n\n public get gridRowStyle() {\n return this.gridStyle(this.layout.numRows,\n this.GRID_AREA_HEIGHT);\n }\n\n public identifyGridArea(index:number, area:GridArea) {\n return area.guid;\n }\n\n public get isHeadersDisplayed() {\n return this.layout.isEditable;\n }\n\n public get isMobileDevice() {\n return this.browserDetector.isMobile;\n }\n\n private gridStyle(amount:number, itemStyle:string) {\n let style = '';\n for (let i = 0; i < amount; i++) {\n style += `${this.GRID_GAP_DIMENSION} ${itemStyle} `;\n }\n\n style += `${this.GRID_GAP_DIMENSION}`;\n\n return this.sanitization.bypassSecurityTrustStyle(style);\n }\n}\n","
      \n
      \n
      \n

      \n
      \n\n
        \n
      • \n \n
      • \n
      • \n \n
      • \n
      \n
      \n
      \n\n\n","import {Component} from '@angular/core';\nimport {GridPageComponent} from \"core-app/modules/grids/grid/page/grid-page.component\";\nimport {GRID_PROVIDERS} from \"core-app/modules/grids/grid/grid.component\";\n\n@Component({\n selector: 'dashboard',\n templateUrl: '../../grids/grid/page/grid-page.component.html',\n styleUrls: ['../../grids/grid/page/grid-page.component.sass'],\n providers: GRID_PROVIDERS\n})\nexport class DashboardComponent extends GridPageComponent {\n protected i18nNamespace():string {\n return 'dashboards';\n }\n\n protected gridScopePath():string {\n return this.pathHelper.projectDashboardsPath(this.currentProject.identifier!);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {Ng2StateDeclaration, UIRouter, UIRouterModule} from \"@uirouter/angular\";\nimport {DashboardComponent} from \"core-app/modules/dashboards/dashboard/dashboard.component\";\nimport {OpenprojectGridsModule} from \"core-app/modules/grids/openproject-grids.module\";\n\nconst menuItemClass = 'dashboards-menu-item';\n\nexport const DASHBOARDS_ROUTES:Ng2StateDeclaration[] = [\n {\n name: 'dashboards',\n parent: 'root',\n // The trailing slash is important\n // cf., https://community.openproject.com/wp/29754\n url: '/dashboards/',\n data: {\n bodyClasses: ['router--dashboards-view-base', 'widget-grid-layout'],\n menuItem: menuItemClass\n },\n component: DashboardComponent\n }\n];\n\nexport function uiRouterDashboardsConfiguration(uiRouter:UIRouter) {\n // Ensure boards/ are being redirected correctly\n // cf., https://community.openproject.com/wp/29754\n uiRouter.urlService.rules\n .when(\n new RegExp(\"^/projects/(.*)/dashboards$\"),\n match => `/projects/${match[1]}/dashboards/`\n );\n}\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n\n OpenprojectGridsModule,\n\n // Routes for /dashboards\n UIRouterModule.forChild({\n states: DASHBOARDS_ROUTES,\n config: uiRouterDashboardsConfiguration\n }),\n ],\n providers: [\n ],\n declarations: [\n DashboardComponent\n ]\n})\nexport class OpenprojectDashboardsModule {\n}\n\n","
      \n \n \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Inject, OnInit} from \"@angular/core\";\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {OpModalLocalsToken, OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {StateService} from \"@uirouter/core\";\n\n@Component({\n templateUrl: './wp-preview.modal.html',\n styleUrls: ['./wp-preview.modal.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WpPreviewModal extends OpModalComponent implements OnInit {\n public workPackage:WorkPackageResource;\n\n public text = {\n created_by: this.i18n.t('js.label_created_by'),\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) readonly locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly i18n:I18nService,\n readonly apiV3Service:APIV3Service,\n readonly opModalService:OpModalService,\n readonly $state:StateService) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n super.ngOnInit();\n const workPackageLink = this.locals.workPackageLink;\n const workPackageId = HalResource.idFromLink(workPackageLink);\n\n this\n .apiV3Service\n .work_packages\n .id(workPackageId)\n .requireAndStream()\n .subscribe((workPackage:WorkPackageResource) => {\n this.workPackage = workPackage;\n this.cdRef.detectChanges();\n\n const modal = jQuery(this.elementRef.nativeElement).find('.preview-modal--container');\n this.reposition(modal, this.locals.event.target);\n });\n }\n\n public reposition(element:JQuery, target:JQuery) {\n element.position({\n my: 'right top',\n at: 'right bottom',\n of: target,\n collision: 'flipfit'\n });\n }\n\n public openStateLink(event:{ workPackageId:string; requestedState:string }) {\n const params = { workPackageId: event.workPackageId };\n\n this.$state.go(event.requestedState, params);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {Injectable, Injector} from \"@angular/core\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {WpPreviewModal} from \"core-components/modals/preview-modal/wp-preview-modal/wp-preview.modal\";\n\n@Injectable({ providedIn: 'root' })\nexport class PreviewTriggerService {\n private previewModal:WpPreviewModal;\n private modalElement:HTMLElement;\n\n constructor(readonly opModalService:OpModalService,\n readonly injector:Injector) {\n }\n\n setupListener() {\n jQuery(document.body).on('mouseenter', '.preview-trigger', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const el = jQuery(e.target);\n const href = el.attr('href');\n\n if (!href) {\n return;\n }\n\n this.previewModal = this.opModalService.show(WpPreviewModal, this.injector, { workPackageLink: href, event: e });\n this.modalElement = this.previewModal.elementRef.nativeElement;\n this.previewModal.reposition(jQuery(this.modalElement), el);\n\n jQuery(this.modalElement).addClass('-no-width -no-height');\n });\n\n jQuery(document.body).on('mouseleave', '.preview-trigger', (e:JQuery.MouseLeaveEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (this.isMouseOverPreview(e)) {\n jQuery(this.modalElement).on('mouseleave', () => {\n this.opModalService.close();\n });\n } else {\n this.opModalService.close();\n }\n });\n }\n\n private isMouseOverPreview(e:JQuery.MouseLeaveEvent) {\n if (!this.modalElement) {\n return false;\n }\n\n const previewElement = jQuery(this.modalElement.children[0]);\n if (previewElement && previewElement.offset()) {\n let horizontalHover = e.pageX >= Math.floor(previewElement.offset()!.left) &&\n e.pageX < previewElement.offset()!.left + previewElement.width()!;\n let verticalHover = e.pageY >= Math.floor(previewElement.offset()!.top) &&\n e.pageY < previewElement.offset()!.top + previewElement.height()!;\n return horizontalHover && verticalHover;\n }\n return false;\n }\n\n}\n","import {Component} from '@angular/core';\nimport {GridPageComponent} from \"core-app/modules/grids/grid/page/grid-page.component\";\nimport {GRID_PROVIDERS} from \"core-app/modules/grids/grid/grid.component\";\n\n@Component({\n selector: 'overview',\n templateUrl: '../grids/grid/page/grid-page.component.html',\n styleUrls: ['../grids/grid/page/grid-page.component.sass'],\n providers: GRID_PROVIDERS\n})\nexport class OverviewComponent extends GridPageComponent {\n protected i18nNamespace():string {\n return 'overviews';\n }\n\n protected gridScopePath():string {\n return this.pathHelper.projectPath(this.currentProject.identifier!);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {Ng2StateDeclaration, UIRouter, UIRouterModule} from \"@uirouter/angular\";\nimport {OpenprojectGridsModule} from \"core-app/modules/grids/openproject-grids.module\";\nimport {OverviewComponent} from \"core-app/modules/overview/overview.component\";\n\nconst menuItemClass = 'overview-menu-item';\n\nexport const OVERVIEW_ROUTES:Ng2StateDeclaration[] = [\n {\n name: 'overview',\n parent: 'root',\n // The trailing slash is important\n // cf., https://community.openproject.com/wp/29754\n url: '/',\n data: {\n menuItem: menuItemClass\n },\n component: OverviewComponent\n }\n];\n\nexport function uiRouterOverviewConfiguration(uiRouter:UIRouter) {\n // Ensure projects/:project_id/ are being redirected correctly\n // cf., https://community.openproject.com/wp/29754\n uiRouter.urlService.rules\n .when(\n new RegExp(\"^/projects(?!/new$)/([^/]+)$\"),\n match => `/projects/${match[1]}/`\n );\n}\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n\n OpenprojectGridsModule,\n\n UIRouterModule.forChild({\n states: OVERVIEW_ROUTES,\n config: uiRouterOverviewConfiguration\n }),\n ],\n providers: [\n ],\n declarations: [\n OverviewComponent\n ]\n})\nexport class OpenprojectOverviewModule {\n}\n\n","import {Component} from \"@angular/core\";\nimport {GRID_PROVIDERS} from \"core-app/modules/grids/grid/grid.component\";\nimport {GridPageComponent} from \"core-app/modules/grids/grid/page/grid-page.component\";\n\n@Component({\n templateUrl: '../grids/grid/page/grid-page.component.html',\n styleUrls: ['../grids/grid/page/grid-page.component.sass'],\n providers: GRID_PROVIDERS\n})\nexport class MyPageComponent extends GridPageComponent {\n protected i18nNamespace():string {\n return 'my_page';\n }\n\n protected gridScopePath():string {\n return this.pathHelper.myPagePath();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {Ng2StateDeclaration, UIRouterModule} from \"@uirouter/angular\";\nimport {OpenprojectGridsModule} from \"core-app/modules/grids/openproject-grids.module\";\nimport {MyPageComponent} from \"core-app/modules/my-page/my-page.component\";\n\nexport const MY_PAGE_ROUTES:Ng2StateDeclaration[] = [\n {\n name: 'my_page',\n url: '/my/page',\n component: MyPageComponent,\n data: {\n bodyClasses: ['router--work-packages-my-page', 'widget-grid-layout'],\n parent: 'work-packages'\n }\n },\n];\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n\n OpenprojectGridsModule,\n\n // Routes for my_page\n UIRouterModule.forChild({ states: MY_PAGE_ROUTES }),\n ],\n declarations: [\n MyPageComponent\n ]\n})\nexport class OpenprojectMyPageModule {\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {PathHelperService} from \"../common/path-helper/path-helper.service\";\nimport {CurrentProjectService} from \"../../components/projects/current-project.service\";\nimport {FocusHelperService} from \"../common/focus/focus-helper\";\n\nconst accessKeys = {\n preview: 1,\n newWorkPackage: 2,\n edit: 3,\n quickSearch: 4,\n projectSearch: 5,\n help: 6,\n moreMenu: 7,\n details: 8\n};\n\n// this could be extracted into a separate component if it grows\nconst accessibleListSelector = 'table.keyboard-accessible-list';\nconst accessibleRowSelector = 'table.keyboard-accessible-list tbody tr';\n\n\n@Injectable({\n providedIn: 'root'\n})\nexport class KeyboardShortcutService {\n\n // maybe move it to a .constant\n private shortcuts:any = {\n '?': () => this.showHelpModal(),\n 'g m': this.globalAction('myPagePath'),\n 'g o': this.projectScoped('projectPath'),\n 'g w p': this.projectScoped('projectWorkPackagesPath'),\n 'g w i': this.projectScoped('projectWikiPath'),\n 'g a': this.projectScoped('projectActivityPath'),\n 'g c': this.projectScoped('projectCalendarPath'),\n 'g n': this.projectScoped('projectNewsPath'),\n 'n w p': this.projectScoped('projectWorkPackageNewPath'),\n\n 'g e': this.accessKey('edit'),\n 'g p': this.accessKey('preview'),\n 'd w p': this.accessKey('details'),\n 'm': this.accessKey('moreMenu'),\n 'p': this.accessKey('projectSearch'),\n 's': this.accessKey('quickSearch'),\n 'k': () => this.focusPrevItem(),\n 'j': () => this.focusNextItem()\n };\n\n\n constructor(private readonly PathHelper:PathHelperService,\n private readonly FocusHelper:FocusHelperService,\n private readonly currentProject:CurrentProjectService) {\n this.register();\n }\n\n /**\n * Register the keyboard shortcuts.\n */\n public register() {\n _.each(this.shortcuts, (action:() => void, key:string) => Mousetrap.bind(key, action));\n }\n\n public accessKey(keyName:'preview'|'newWorkPackage'|'edit'|'quickSearch'|'projectSearch'|'help'|'moreMenu'|'details') {\n var key = accessKeys[keyName];\n return () => {\n var elem = jQuery('[accesskey=' + key + ']:first');\n if (elem.is('input') || elem.attr('id') === 'global-search-input') {\n // timeout with delay so that the key is not\n // triggered on the input\n setTimeout(() => this.FocusHelper.focus(elem), 200);\n } else if (elem.is('[href]')) {\n this.clickLink(elem[0]);\n } else {\n elem[0].click();\n }\n };\n }\n\n public globalAction(action:keyof PathHelperService) {\n return () => {\n var url = (this.PathHelper[action] as any)();\n window.location.href = url;\n };\n }\n\n public projectScoped(action:keyof PathHelperService) {\n return () => {\n var projectIdentifier = this.currentProject.identifier;\n if (projectIdentifier) {\n var url = (this.PathHelper[action] as any)(projectIdentifier);\n window.location.href = url;\n }\n };\n }\n\n clickLink(link:any) {\n var cancelled = false;\n\n if (!!document.createEvent) {\n var event = new MouseEvent('click', {\n view: window,\n bubbles: true,\n cancelable: true\n });\n cancelled = !link.dispatchEvent(event);\n } else if (link.fireEvent) {\n cancelled = !link.fireEvent('onclick');\n }\n\n if (!cancelled) {\n window.location.href = link.href;\n }\n }\n\n showHelpModal() {\n window.open(this.PathHelper.keyboardShortcutsHelpPath());\n }\n\n findListInPage() {\n const domLists = jQuery(accessibleListSelector);\n const focusElements:any = [];\n domLists.find('tbody tr').each(function (index, tr) {\n var firstLink = jQuery(tr).find(':visible:tabbable')[0];\n if (firstLink !== undefined) {\n focusElements.push(firstLink);\n }\n });\n return focusElements;\n }\n\n focusItemOffset(offset:number) {\n const list = this.findListInPage();\n let index;\n\n if (list === null) {\n return;\n }\n\n index = list.indexOf(\n jQuery(document.activeElement!)\n .closest(accessibleRowSelector)\n .find(':visible:tabbable')[0]\n );\n\n const target = jQuery(list[(index + offset + list.length) % list.length]);\n target.focus();\n\n }\n\n focusNextItem() {\n this.focusItemOffset(1);\n }\n\n focusPrevItem() {\n this.focusItemOffset(-1);\n }\n}\n\n","import {Component, ElementRef, Input, OnInit} from '@angular/core';\n\nexport const wpTableEntrySelector = 'wp-embedded-table-entry';\n\n@Component({\n selector: wpTableEntrySelector,\n template: `\n \n \n \n \n `\n})\nexport class WorkPackageEmbeddedTableEntryComponent implements OnInit {\n @Input() public queryProps:any;\n @Input() public configuration:any;\n @Input() public initialLoadingIndicator:boolean = true;\n\n constructor(readonly elementRef:ElementRef) {\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement;\n\n if (element.getAttribute('query-props')) {\n this.getInputsFromData(element);\n }\n }\n\n private getInputsFromData(element:HTMLElement) {\n this.queryProps = JSON.parse(element.getAttribute('query-props')!);\n this.configuration = JSON.parse(element.getAttribute('configuration')!);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++ Ng1FieldControlsWrapper,\n\nimport {Component, ElementRef} from \"@angular/core\";\nimport {WorkPackageTableConfigurationObject} from \"core-components/wp-table/wp-table-configuration\";\n\nexport const wpEmbeddedTableMacroSelector = 'macro.embedded-table';\n\n@Component({\n selector: wpEmbeddedTableMacroSelector,\n template: `\n \n \n `\n})\nexport class EmbeddedTablesMacroComponent {\n // noinspection JSUnusedGlobalSymbols\n public queryProps:any;\n public configuration:WorkPackageTableConfigurationObject = {\n actionsColumnEnabled: false,\n columnMenuEnabled: false,\n contextMenuEnabled: false\n };\n\n constructor(readonly elementRef:ElementRef) {\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement;\n this.queryProps = JSON.parse(element.dataset.queryProps);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, OnInit} from '@angular/core';\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\nexport const colorsAutocompleterSelector = 'colors-autocompleter';\n\n@Component({\n template: `\n \n \n {{item.name}}\n \n \n {{item.name}}\n \n \n `,\n selector: colorsAutocompleterSelector\n})\nexport class ColorsAutocompleter implements OnInit {\n public options:any[];\n public selectedOption:any;\n private highlightTextInline:boolean = false;\n private updateInputField:HTMLInputElement|undefined;\n private selectedColorId:string;\n\n constructor(protected elementRef:ElementRef,\n protected readonly I18n:I18nService) {\n }\n\n ngOnInit() {\n this.setColorOptions();\n\n this.updateInputField = document.getElementsByName(this.elementRef.nativeElement.dataset.updateInput)[0] as HTMLInputElement|undefined;\n this.highlightTextInline = JSON.parse(this.elementRef.nativeElement.dataset.highlightTextInline);\n }\n\n public onModelChange(color:any) {\n if (color && this.updateInputField) {\n this.updateInputField.value = color.value;\n }\n }\n\n private setColorOptions() {\n this.options = JSON.parse(this.elementRef.nativeElement.dataset.colors);\n this.options.unshift({name: this.I18n.t('js.label_no_color'), value: ''});\n\n this.selectedOption = this.options.find((item) => item.selected === true);\n\n if (this.selectedOption) {\n this.selectedOption = this.selectedOption.value;\n } else {\n // Differentiate between \"No color\" and a color that is now not selectable any more\n this.selectedColorId = this.elementRef.nativeElement.dataset.selectedColor;\n this.selectedOption = this.selectedColorId ? this.selectedColorId : '';\n }\n }\n\n private highlightColor(item:any) {\n if (item.value === '') { return; }\n\n let highlightingClass;\n if (this.highlightTextInline) {\n highlightingClass = '__hl_inline_type_ ';\n } else {\n highlightingClass = '__hl_inline_ ';\n }\n return highlightingClass + Highlighting.colorClass(this.highlightTextInline, item.value);\n }\n\n}\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, Renderer2} from '@angular/core';\nimport {FocusHelperService} from 'app/modules/common/focus/focus-helper';\nimport {I18nService} from 'app/modules/common/i18n/i18n.service';\nimport {HalResourceService} from \"app/modules/hal/services/hal-resource.service\";\nimport {GlobalSearchService} from \"core-app/modules/global_search/services/global-search.service\";\nimport {WorkPackageFiltersService} from \"app/components/filters/wp-filters/wp-filters.service\";\nimport {UrlParamsHelperService} from \"app/components/wp-query/url-params-helper\";\nimport {WorkPackageTableConfigurationObject} from \"core-components/wp-table/wp-table-configuration\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {debounceTime, distinctUntilChanged, skip} from \"rxjs/operators\";\nimport {combineLatest} from \"rxjs\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport const globalSearchWorkPackagesSelector = 'global-search-work-packages';\n\n@Component({\n selector: globalSearchWorkPackagesSelector,\n template: `\n \n \n `\n})\n\nexport class GlobalSearchWorkPackagesComponent extends UntilDestroyedMixin implements OnInit, OnDestroy, AfterViewInit {\n public queryProps:{ [key:string]:any };\n public resultsHidden = false;\n\n public tableConfiguration:WorkPackageTableConfigurationObject = {\n actionsColumnEnabled: false,\n columnMenuEnabled: true,\n contextMenuEnabled: false,\n inlineCreateEnabled: false,\n withFilters: true,\n showFilterButton: true,\n filterButtonText: this.I18n.t('js.button_advanced_filter')\n };\n\n constructor(readonly FocusHelper:FocusHelperService,\n readonly elementRef:ElementRef,\n readonly renderer:Renderer2,\n readonly I18n:I18nService,\n readonly halResourceService:HalResourceService,\n readonly globalSearchService:GlobalSearchService,\n readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpFilters:WorkPackageFiltersService,\n readonly cdRef:ChangeDetectorRef,\n private UrlParamsHelper:UrlParamsHelperService) {\n super();\n }\n\n ngAfterViewInit() {\n combineLatest([\n this.globalSearchService.searchTerm$,\n this.globalSearchService.projectScope$\n ])\n .pipe(\n skip(1),\n distinctUntilChanged(),\n debounceTime(10),\n this.untilDestroyed()\n )\n .subscribe(([newSearchTerm, newProjectScope]) => {\n this.wpFilters.visible = false;\n this.setQueryProps();\n });\n\n this.globalSearchService\n .resultsHidden$\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((resultsHidden:boolean) => this.resultsHidden = resultsHidden);\n }\n\n ngOnInit():void {\n this.setQueryProps();\n }\n\n private setQueryProps():void {\n let filters:any[] = [];\n let columns = ['id', 'project', 'subject', 'type', 'status', 'updatedAt'];\n\n if (this.globalSearchService.searchTerm.length > 0) {\n filters.push({\n search: {\n operator: '**',\n values: [this.globalSearchService.searchTerm]\n }\n });\n }\n\n if (this.globalSearchService.projectScope === 'current_project') {\n filters.push({\n subprojectId: {\n operator: '!*',\n values: []\n }\n });\n columns = ['id', 'subject', 'type', 'status', 'updatedAt'];\n }\n\n if (this.globalSearchService.projectScope === '') {\n filters.push({\n subprojectId: {\n operator: '*',\n values: []\n }\n });\n }\n\n this.queryProps = {\n 'columns[]': columns,\n filters: JSON.stringify(filters),\n sortBy: JSON.stringify([['updatedAt', 'desc']]),\n showHierarchies: false\n };\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {DomSanitizer} from \"@angular/platform-browser\";\nimport {BcfRestApi} from \"core-app/modules/bim/bcf/bcf-constants.const\";\nimport {ImageHelpers} from \"core-app/helpers/images/path-helper\";\nimport imagePath = ImageHelpers.imagePath;\n\nexport const homescreenNewFeaturesBlockSelector = 'homescreen-new-features-block';\n\n@Component({\n template: `\n

      \n {{ text.descriptionNewFeatures }}\n

      \n
      \n

      \n \n \n
      \n\n {{ text.learnAbout }}\n `,\n selector: homescreenNewFeaturesBlockSelector,\n styleUrls: ['./new-features.component.sass'],\n})\n\n\n/**\n * Component for the homescreen block to promote new features.\n * When updating this for the next release, be sure to cleanup stuff is not needed any more:\n * Locals (js-en.yml), Styles (new-features.component.sass), HTML (above), TS (below)\n */\nexport class HomescreenNewFeaturesBlockComponent {\n public isStandardEdition:boolean;\n new_features_image = ImageHelpers.imagePath('new_features.png');\n public text = {\n newFeatures: this.i18n.t('js.label_new_features'),\n descriptionNewFeatures: this.i18n.t('js.homescreen.blocks.new_features.text_new_features'),\n learnAbout: this.i18n.t('js.homescreen.blocks.new_features.learn_about'),\n };\n\n constructor(\n readonly i18n:I18nService,\n readonly domSanitizer:DomSanitizer\n ) {\n this.isStandardEdition = window.OpenProject.isStandardEdition;\n }\n\n public get teaserWebsiteUrl() {\n let url = this.translated('learn_about_link');\n return this.domSanitizer.bypassSecurityTrustResourceUrl(url);\n }\n\n public get currentNewFeatureHtml():string {\n return this.translated('current_new_feature_html');\n }\n\n private translated(key:string):string {\n return this.i18n.t(this.i18nBase + this.i18nPrefix + '.' + key, { list_styling_class: 'widget-box--arrow-links', bcf_api_link: BcfRestApi});\n }\n\n private i18nBase:string = 'js.homescreen.blocks.new_features.';\n\n private get i18nPrefix():string {\n return this.isStandardEdition ? \"standard\" : \"bim\";\n }\n}\n","export const BcfRestApi = \"https://github.com/opf/openproject/blob/dev/docs/api/bcf/bcf-rest-api.md\";\n","
      \n \n \n \n \n \n \n \n \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ApplicationRef, ChangeDetectorRef, Component, ElementRef, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\n\n\nexport const customDateActionAdminSelector = 'custom-date-action-admin';\n\n@Component({\n selector: customDateActionAdminSelector,\n templateUrl: './custom-date-action-admin.html'\n})\nexport class CustomDateActionAdminComponent implements OnInit {\n public valueVisible = false;\n public fieldName:string;\n public fieldValue:string;\n public visibleValue:string;\n public selectedOperator:any;\n\n private onKey = 'on';\n private currentKey = 'current';\n private currentFieldValue = '%CURRENT_DATE%';\n\n public operators = [\n {key: this.onKey, label: this.I18n.t('js.custom_actions.date.specific')},\n {key: this.currentKey, label: this.I18n.t('js.custom_actions.date.current_date')}\n ];\n\n constructor(private elementRef:ElementRef,\n private cdRef:ChangeDetectorRef,\n public appRef:ApplicationRef,\n private I18n:I18nService) {\n }\n\n // cannot use $onInit as it would be called before the operators gets filled\n public ngOnInit() {\n const element = this.elementRef.nativeElement as HTMLElement;\n this.fieldName = element.dataset.fieldName!;\n this.fieldValue = element.dataset.fieldValue!;\n\n if (this.fieldValue === this.currentFieldValue) {\n this.selectedOperator = this.operators[1];\n } else {\n this.selectedOperator = this.operators[0];\n this.visibleValue = this.fieldValue;\n }\n\n this.toggleValueVisibility();\n }\n\n public toggleValueVisibility() {\n this.valueVisible = this.selectedOperator.key === this.onKey;\n if (this.fieldValue === this.currentFieldValue) {\n this.fieldValue = '';\n }\n\n this.updateDbValue();\n }\n\n private updateDbValue() {\n if (this.selectedOperator.key === this.currentKey) {\n this.fieldValue = this.currentFieldValue;\n }\n }\n\n public get fieldId() {\n // replace all square brackets by underscore\n // to match the label's for value\n return this.fieldName\n .replace(/\\[|\\]/g, '_')\n .replace('__', '_')\n .replace(/_$/, '');\n }\n\n updateField(val:string) {\n this.fieldValue = val;\n this.cdRef.detectChanges();\n }\n}\n\n\n","
      \n
        \n
      • \n \n \n
      • \n
      \n
      \n","import {Component, OnInit} from \"@angular/core\";\nimport {Observable} from \"rxjs\";\nimport {BoardService} from \"core-app/modules/boards/board/board.service\";\nimport {Board} from \"core-app/modules/boards/board/board\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {MainMenuNavigationService} from \"core-components/main-menu/main-menu-navigation.service\";\nimport {map} from \"rxjs/operators\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const boardsMenuSelector = 'boards-menu';\n\n@Component({\n selector: boardsMenuSelector,\n templateUrl: './boards-menu.component.html'\n})\n\nexport class BoardsMenuComponent extends UntilDestroyedMixin implements OnInit {\n trackById = AngularTrackingHelpers.compareByAttribute('id');\n\n currentProjectIdentifier = this.currentProject.identifier;\n\n selectedBoardId:string;\n\n public boards$:Observable = this\n .apiV3Service\n .boards\n .observeAll()\n .pipe(\n map((boards:Board[]) => {\n return boards.sort(function (a, b) {\n if (a.name < b.name) {\n return -1;\n }\n if (a.name > b.name) {\n return 1;\n }\n return 0;\n });\n })\n );\n\n constructor(private readonly boardService:BoardService,\n private readonly apiV3Service:APIV3Service,\n private readonly currentProject:CurrentProjectService,\n private readonly mainMenuService:MainMenuNavigationService) {\n super();\n }\n\n ngOnInit() {\n // When activating the boards submenu,\n // either initially or through click on the toggle, load the results\n this.mainMenuService\n .onActivate('board_view')\n .subscribe(() => {\n this.focusBackArrow();\n this.boardService.loadAllBoards();\n });\n\n this\n .boardService\n .currentBoard$\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((id:string|null) => {\n this.selectedBoardId = id ? id : '';\n });\n }\n\n private focusBackArrow() {\n let buttonArrowLeft = jQuery('*[data-name=\"board_view\"] .main-menu--arrow-left-to-project');\n buttonArrowLeft.focus();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component} from '@angular/core';\n\nexport const globalSearchWorkPackagesSelectorEntry = 'global-search-work-packages-entry';\n\n/**\n * An entry component to be rendered by Rails which opens an isolated query space\n * for the work package search embedded table.\n */\n@Component({\n selector: globalSearchWorkPackagesSelectorEntry,\n template: `\n \n \n \n `\n})\nexport class GlobalSearchWorkPackagesEntryComponent {\n}\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';\nimport {UploadFile, UploadHttpEvent, UploadInProgress} from \"core-components/api/op-file-upload/op-file-upload.service\";\nimport {HttpErrorResponse, HttpEventType, HttpProgressEvent} from \"@angular/common/http\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Component({\n selector: 'notifications-upload-progress',\n template: `\n
    • \n \n \n

      0%

      \n \n \n \n \n
    • \n `\n})\nexport class UploadProgressComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public upload:UploadInProgress;\n @Output() public onError = new EventEmitter();\n @Output() public onSuccess = new EventEmitter();\n\n @ViewChild('progressBar')\n progressBar:ElementRef;\n @ViewChild('progressPercentage')\n progressPercentage:ElementRef;\n\n public file:UploadFile;\n public error:boolean = false;\n public completed = false;\n\n set value(value:number) {\n this.progressBar.nativeElement.value = value;\n this.progressPercentage.nativeElement.innerText = `${value}%`;\n\n if (value === 100) {\n this.progressBar.nativeElement.style.display = 'none';\n }\n }\n\n constructor(protected readonly I18n:I18nService) {\n super();\n }\n\n ngOnInit() {\n this.file = this.upload[0];\n const observable = this.upload[1];\n\n observable\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(\n (evt:UploadHttpEvent) => {\n switch (evt.type) {\n case HttpEventType.Sent:\n this.value = 5;\n return debugLog(`Uploading file \"${this.file.name}\" of size ${this.file.size}.`);\n\n case HttpEventType.UploadProgress:\n return this.updateProgress(evt);\n\n case HttpEventType.Response:\n debugLog(`File ${this.fileName} was fully uploaded.`);\n this.value = 100;\n this.completed = true;\n return this.onSuccess.emit();\n\n default:\n // Sent or unknown event\n return;\n }\n },\n (error:HttpErrorResponse) => this.handleError(error)\n );\n }\n\n public get fileName():string|undefined {\n return this.file && this.file.name;\n }\n\n private updateProgress(evt:HttpProgressEvent) {\n if (evt.total) {\n this.value = Math.round(evt.loaded / evt.total * 100);\n } else {\n this.value = 10;\n }\n }\n\n private handleError(error:HttpErrorResponse) {\n this.error = true;\n this.onError.emit(error);\n }\n}\n\n","
      \n
      \n

      \n \n \n \n \n

      \n
      \n
      \n
      \n \n \n \n \n \n \n \n
      \n
      \n
        0\">\n \n \n
      \n
      \n
      \n
      \n
      \n
        \n
      • \n
      \n
      \n
      \n
      \n \n \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {\n INotification,\n NotificationsService,\n NotificationType\n} from 'core-app/modules/common/notifications/notifications.service';\n\n@Component({\n templateUrl: './notification.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'notification'\n})\nexport class NotificationComponent implements OnInit {\n @Input() public notification:INotification;\n\n public text = {\n close_popup: this.I18n.t('js.close_popup_title'),\n };\n\n public type:NotificationType;\n public uploadCount = 0;\n public show = false;\n\n constructor(readonly I18n:I18nService,\n readonly notificationsService:NotificationsService) {\n }\n\n ngOnInit() {\n this.type = this.notification.type;\n }\n\n public get data() {\n return this.notification.data;\n }\n\n public canBeHidden() {\n return this.data && this.data.length > 5;\n }\n\n public removable() {\n return this.notification.type !== 'upload';\n }\n\n public remove() {\n this.notificationsService.remove(this.notification);\n }\n\n /**\n * Execute the link callback from content.link.target\n * and close this notification.\n */\n public executeTarget() {\n if (this.notification.link) {\n this.notification.link.target();\n this.remove();\n }\n }\n\n public onUploadError(message:string) {\n this.remove();\n }\n\n public onUploadSuccess() {\n this.uploadCount += 1;\n }\n\n public get uploadText() {\n return this.I18n.t('js.label_upload_counter',\n { done: this.uploadCount, count: this.data.length});\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core';\nimport {INotification, NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport const notificationsContainerSelector = 'notifications-container';\n\n@Component({\n template: `\n
      \n
      \n \n
      \n
      \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: notificationsContainerSelector\n})\nexport class NotificationsContainerComponent extends UntilDestroyedMixin implements OnInit {\n\n public stack:INotification[] = [];\n\n constructor(readonly notificationsService:NotificationsService,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit():void {\n this.notificationsService\n .current\n .values$('Subscribing to changes in the notification stack')\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(stack => {\n this.stack = stack;\n this.cdRef.detectChanges();\n });\n }\n}\n\n\n","\n
      \n \n \n
      \n\n \n \n \n \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, OnInit, ViewChild} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {States} from 'core-components/states.service';\nimport {filter, takeUntil} from 'rxjs/operators';\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ICKEditorContext, ICKEditorInstance} from \"core-app/modules/common/ckeditor/ckeditor-setup.service\";\nimport {OpCkeditorComponent} from \"core-app/modules/common/ckeditor/op-ckeditor.component\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n\nexport const ckeditorAugmentedTextareaSelector = 'ckeditor-augmented-textarea';\n\n@Component({\n selector: ckeditorAugmentedTextareaSelector,\n templateUrl: './ckeditor-augmented-textarea.html'\n})\nexport class CkeditorAugmentedTextareaComponent extends UntilDestroyedMixin implements OnInit {\n public textareaSelector:string;\n public previewContext:string;\n\n // Which template to include\n public $element:JQuery;\n public formElement:JQuery;\n public wrappedTextArea:JQuery;\n public $attachmentsElement:JQuery;\n\n // Remember if the user changed\n public changed:boolean = false;\n public inFlight:boolean = false;\n\n public initialContent:string;\n public resource?:HalResource;\n public context:ICKEditorContext;\n public macros:boolean;\n public editorType:string;\n\n // Reference to the actual ckeditor instance component\n @ViewChild(OpCkeditorComponent, { static: true }) private ckEditorInstance:OpCkeditorComponent;\n\n private attachments:HalResource[];\n private isEditing = false;\n\n constructor(protected elementRef:ElementRef,\n protected pathHelper:PathHelperService,\n protected halResourceService:HalResourceService,\n protected Notifications:NotificationsService,\n protected I18n:I18nService,\n protected states:States,\n protected ConfigurationService:ConfigurationService) {\n super();\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n // Parse the attribute explicitly since this is likely a bootstrapped element\n this.textareaSelector = this.$element.attr('textarea-selector')!;\n this.previewContext = this.$element.attr('preview-context')!;\n this.macros = this.$element.attr('macros') !== 'false';\n this.editorType = this.$element.attr('editor-type') || 'full';\n\n // Parse the resource if any exists\n const source = this.$element.data('resource');\n this.resource = source ? this.halResourceService.createHalResource(source, true) : undefined;\n\n this.formElement = this.$element.closest('form');\n this.wrappedTextArea = this.formElement.find(this.textareaSelector);\n this.wrappedTextArea\n .removeAttr('required')\n .hide();\n this.initialContent = this.wrappedTextArea.val() as string;\n\n this.$attachmentsElement = this.formElement.find('#attachments_fields');\n this.context = { resource: this.resource, previewContext: this.previewContext };\n if (!this.macros) {\n this.context['macros'] = 'none';\n }\n }\n\n ngOnDestroy() {\n super.ngOnDestroy();\n this.formElement.off('submit.ckeditor');\n }\n\n public markEdited() {\n window.OpenProject.pageWasEdited = true;\n }\n\n public setup(editor:ICKEditorInstance) {\n // Have a hacky way to access the editor from outside of angular.\n // This is e.g. employed to set the text from outside to reuse the same editor for different languages.\n this.$element.data('editor', editor);\n\n if (this.resource && this.resource.attachments) {\n this.setupAttachmentAddedCallback(editor);\n this.setupAttachmentRemovalSignal(editor);\n }\n\n // Listen for form submission to set textarea content\n this.formElement.on('submit.ckeditor change.ckeditor', () => {\n try {\n this.wrappedTextArea.val(this.ckEditorInstance.getRawData());\n } catch (e) {\n console.error(`Failed to save CKEditor body to textarea: ${e}.`);\n this.Notifications.addError(e || this.I18n.t('js.error.internal'));\n\n // Avoid submission of the form\n return false;\n }\n\n this.addUploadedAttachmentsToForm();\n\n // Continue with submission\n return true;\n });\n\n this.setLabel();\n\n return editor;\n }\n\n private setupAttachmentAddedCallback(editor:ICKEditorInstance) {\n editor.model.on('op:attachment-added', () => {\n this.states.forResource(this.resource!)!.putValue(this.resource!);\n });\n }\n\n private setupAttachmentRemovalSignal(editor:ICKEditorInstance) {\n this.attachments = _.clone(this.resource!.attachments.elements);\n\n this.states.forResource(this.resource!)!.changes$()\n .pipe(\n takeUntil(componentDestroyed(this)),\n filter(resource => !!resource)\n ).subscribe(resource => {\n let missingAttachments = _.differenceBy(this.attachments,\n resource!.attachments.elements,\n (attachment:HalResource) => attachment.id);\n\n let removedUrls = missingAttachments.map(attachment => attachment.downloadLocation.$href);\n\n if (removedUrls.length) {\n editor.model.fire('op:attachment-removed', removedUrls);\n }\n\n this.attachments = _.clone(resource!.attachments.elements);\n });\n }\n\n private setLabel() {\n let textareaId = this.textareaSelector.substring(1);\n let label = jQuery(`label[for=${textareaId}]`);\n\n let ckContent = this.$element.find('.ck-content');\n\n ckContent.attr('aria-label', null);\n ckContent.attr('aria-labelledby', textareaId);\n\n label.click(() => {\n ckContent.focus();\n });\n }\n\n private addUploadedAttachmentsToForm() {\n if (!this.resource || !this.resource.attachments || this.resource.id) {\n return;\n }\n\n const takenIds = this.$attachmentsElement.find('input[type=\\'file\\']').map((index, input) => {\n let match = (input.getAttribute('name') || '').match(/attachments\\[(\\d+)\\]\\[(?:file|id)\\]/);\n\n if (match) {\n return parseInt(match[1]);\n } else {\n return 0;\n }\n });\n\n const maxValue:number = takenIds.toArray().sort().pop() || 0;\n\n let addedAttachments = this.resource.attachments.elements || [];\n\n jQuery.each(addedAttachments, (index:number, attachment:HalResource) => {\n this.$attachmentsElement.append(``);\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, OnInit} from \"@angular/core\";\n\nexport const persistentToggleSelector = 'persistent-toggle';\n\n@Component({\n selector: persistentToggleSelector,\n template: ''\n})\nexport class PersistentToggleComponent implements OnInit {\n\n /** Unique identifier of the toggle */\n private identifier:string;\n\n /** Is hidden */\n private isHidden:boolean = false;\n\n /** Element reference */\n private $element:JQuery;\n private $targetNotification:JQuery;\n\n constructor(private elementRef:ElementRef) {\n }\n\n ngOnInit():void {\n this.$element = jQuery(this.elementRef.nativeElement);\n this.$targetNotification = this.getTargetNotification();\n\n this.identifier = this.$element.data('identifier');\n this.isHidden = window.OpenProject.guardedLocalStorage(this.identifier) === 'true';\n\n // Set initial state\n this.$targetNotification.prop('hidden', !!this.isHidden);\n\n // Register click handler\n this.$element\n .parent()\n .find('.persistent-toggle--click-handler')\n .on('click', () => this.toggle(!this.isHidden));\n\n // Register target notification close icon\n this.$targetNotification\n .find('.notification-box--close')\n .on('click', () => this.toggle(true));\n\n }\n\n private getTargetNotification() {\n return this.$element\n .parent()\n .find('.persistent-toggle--notification');\n }\n\n private toggle(isNowHidden:boolean) {\n this.isHidden = isNowHidden;\n window.OpenProject.guardedLocalStorage(this.identifier, (!!isNowHidden).toString());\n\n if (isNowHidden) {\n this.$targetNotification.slideUp(400, () => {\n // Set hidden only after animation completed\n this.$targetNotification.prop('hidden', true);\n });\n } else {\n this.$targetNotification.slideDown(400);\n this.$targetNotification.prop('hidden', false);\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {GonService} from \"core-app/modules/common/gon/gon.service\";\nimport {Injectable} from \"@angular/core\";\nimport {input} from \"reactivestates\";\n\nexport interface HideSectionDefinition {\n key:string;\n label:string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class HideSectionService {\n public displayed = input();\n public all:HideSectionDefinition[] = [];\n\n constructor(Gon:GonService) {\n const sections:any = Gon.get('hideSections');\n this.all = sections.all;\n this.displayed.putValue(sections.active.map((el:HideSectionDefinition) => {\n this.toggleVisibility(el.key, true);\n return el.key;\n }));\n\n this.removeHiddenOnSubmit();\n }\n\n section(key:string):HTMLElement|null {\n return document.querySelector(`section.hide-section[data-section-name=\"${key}\"]`);\n }\n\n hide(key:string) {\n this.displayed.doModify(displayed => displayed.filter(el => el !== key));\n this.toggleVisibility(key, false);\n }\n\n show(key:string) {\n this.displayed.doModify(displayed => [...displayed, key]);\n this.toggleVisibility(key, true);\n }\n\n private toggleVisibility(key:string, visible:boolean) {\n const section = this.section(key);\n\n if (section) {\n section.hidden = !visible;\n }\n }\n\n private removeHiddenOnSubmit() {\n jQuery(document.body)\n .on('submit', 'form', function(evt:any) {\n const form = jQuery(this);\n const sections = form.find('section.hide-section:hidden');\n\n if (form.data('hideSectionRemoved') || sections.length === 0) {\n return true;\n }\n\n form.data('hideSectionRemoved', true);\n sections.remove();\n form.trigger('submit');\n evt.preventDefault();\n return false;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, OnInit} from \"@angular/core\";\nimport {HideSectionService} from \"core-app/modules/common/hide-section/hide-section.service\";\n\nexport const hideSectionLinkSelector = 'hide-section-link';\n\n@Component({\n selector: hideSectionLinkSelector,\n templateUrl: './hide-section-link.component.html',\n})\nexport class HideSectionLinkComponent implements OnInit {\n displayed:boolean = true;\n\n public sectionName:string;\n\n constructor(protected elementRef:ElementRef,\n protected hideSectionService:HideSectionService) {}\n\n ngOnInit():void {\n this.sectionName = this.elementRef.nativeElement.dataset.sectionName;\n }\n\n hideSection() {\n this.hideSectionService.hide(this.sectionName);\n return false;\n }\n}\n","\n \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HideSectionService} from \"./hide-section.service\";\nimport {Component, ElementRef, OnInit} from \"@angular/core\";\n\nexport const showSectionDropdownSelector = 'show-section-dropdown';\n\n@Component({\n selector: showSectionDropdownSelector,\n template: ''\n})\nexport class ShowSectionDropdownComponent implements OnInit {\n public optValue:string; // value of option for which hide-section should be visible\n public hideSecWithName:string; // section-name of hide-section\n\n constructor(private HideSectionService:HideSectionService,\n private elementRef:ElementRef) {\n }\n\n ngOnInit() {\n const element = jQuery(this.elementRef.nativeElement);\n this.optValue = element.data('optValue');\n this.hideSecWithName = element.data('hideSecWithName');\n\n const target = jQuery(this.elementRef.nativeElement).prev();\n target.on('change', event => {\n let selectedOption = jQuery(\"option:selected\", event.target);\n\n if (selectedOption.val() !== this.optValue) {\n this.HideSectionService.hide(this.hideSecWithName);\n } else {\n this.HideSectionService.show(this.hideSecWithName);\n }\n });\n }\n}\n\n\n","\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {Component, ElementRef, OnInit, ViewChild} from \"@angular/core\";\nimport {HideSectionDefinition, HideSectionService} from \"core-app/modules/common/hide-section/hide-section.service\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport const addSectionDropdownSelector = 'add-section-dropdown';\n\n@Component({\n selector: addSectionDropdownSelector,\n templateUrl: './add-section-dropdown.component.html'\n})\nexport class AddSectionDropdownComponent extends UntilDestroyedMixin implements OnInit {\n @ViewChild('fallbackOption', { static: true }) private option:ElementRef;\n\n trackByKey = AngularTrackingHelpers.trackByProperty('key');\n\n selectable:HideSectionDefinition[] = [];\n active:string[] = [];\n\n public htmlId:string;\n public placeholder = this.I18n.t('js.placeholders.selection');\n\n constructor(protected hideSectionService:HideSectionService,\n protected elementRef:ElementRef,\n protected I18n:I18nService) {\n super();\n }\n\n ngOnInit():void {\n this.htmlId = this.elementRef.nativeElement.dataset.htmlId;\n\n this.hideSectionService\n .displayed\n .values$()\n .pipe(\n this.untilDestroyed()\n ).subscribe(displayed => {\n this.selectable = this.hideSectionService.all\n .filter(el => displayed.indexOf(el.key) === -1)\n .sort((a, b) => a.label.localeCompare(b.label));\n\n (this.option.nativeElement as HTMLOptionElement).selected = true;\n });\n }\n\n show(value:string) {\n this.hideSectionService.show(value);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, OnInit, ViewChild} from '@angular/core';\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\n\ntype SelectItem = { label:string, value:string, selected?:boolean };\n\nexport const autocompleteSelectDecorationSelector = 'autocomplete-select-decoration';\n\n@Component({\n template: `\n \n \n {{ item.label }}\n \n \n `,\n selector: autocompleteSelectDecorationSelector\n})\nexport class AutocompleteSelectDecorationComponent implements OnInit {\n @ViewChild(NgSelectComponent) public ngSelectComponent:NgSelectComponent;\n\n public options:SelectItem[];\n\n /** Whether we're a multiselect */\n public multiselect:boolean = false;\n\n /** Get the selected options */\n public selected:SelectItem|SelectItem[];\n\n /** The input name we're syncing selections to */\n private syncInputFieldName:string;\n\n /** The input id used for label */\n public labelForId:string;\n\n constructor(protected elementRef:ElementRef) {\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement;\n\n // Set options\n this.multiselect = element.dataset.multiselect === 'true';\n this.labelForId = element.dataset.inputId!;\n\n // Get the sync target\n this.syncInputFieldName = element.dataset.inputName;\n // Add Rails multiple identifier if multiselect\n if (this.multiselect) {\n this.syncInputFieldName += '[]';\n }\n\n // Prepare and build the options\n // Expected array of objects with id, name, select\n const data:SelectItem[] = JSON.parse(element.dataset.options);\n\n // Set initial selection\n this.setInitialSelection(data);\n\n if (!this.multiselect) {\n this.selected = (this.selected as SelectItem[])[0];\n }\n\n this.options = data;\n\n // Unhide the parent\n element.parentElement.hidden = false;\n }\n\n setInitialSelection(data:SelectItem[]) {\n this.updateSelection(data.filter(element => element.selected));\n }\n\n updateSelection(items:SelectItem|SelectItem[]) {\n this.selected = items;\n items = _.castArray(items) as SelectItem[];\n\n this.removeCurrentSyncedFields();\n items.forEach((el:SelectItem) => {\n this.createSyncedField(el.value);\n });\n }\n\n createSyncedField(value:string) {\n const element = jQuery(this.elementRef.nativeElement);\n element\n .parent()\n .append(``);\n }\n\n removeCurrentSyncedFields() {\n const element = jQuery(this.elementRef.nativeElement);\n element\n .parent()\n .find(`input[name=\"${this.syncInputFieldName}\"]`)\n .remove();\n }\n}\n","
      \n
        \n
      • \n \n
      • \n
      \n
      \n \n
      \n
      \n \n
      \n
      \n","import {AfterViewInit, Component, ElementRef, ViewChild} from \"@angular/core\";\n\nexport interface Tab {\n id:string;\n name:string;\n path?:string;\n}\n\n@Component({\n templateUrl: 'scrollable-tabs.component.html'\n})\n\nexport class ScrollableTabsComponent implements AfterViewInit {\n @ViewChild('scrollContainer', { static: true }) scrollContainer:ElementRef;\n @ViewChild('scrollPane', { static: true }) scrollPane:ElementRef;\n @ViewChild('scrollRightBtn', { static: true }) scrollRightBtn:ElementRef;\n @ViewChild('scrollLeftBtn', { static: true }) scrollLeftBtn:ElementRef;\n\n public currentTabId:string = '';\n public tabs:Tab[] = [];\n public classes:string[] = ['scrollable-tabs'];\n public hideLeftButton:boolean = true;\n public hideRightButton:boolean = true;\n\n private container:Element;\n private pane:Element;\n\n ngAfterViewInit() {\n this.container = this.scrollContainer.nativeElement;\n this.pane = this.scrollPane.nativeElement;\n\n this.determineScrollButtonVisibility();\n this.scrollIntoVisibleArea(this.currentTabId);\n }\n\n public clickTab(tab:string) {\n this.currentTabId = tab;\n }\n\n public onScroll(event:any) {\n this.determineScrollButtonVisibility();\n }\n\n private determineScrollButtonVisibility() {\n this.hideLeftButton = (this.pane.scrollLeft <= 0);\n this.hideRightButton = (this.pane.scrollWidth - this.pane.scrollLeft <= this.container.clientWidth);\n }\n\n public scrollRight() {\n this.pane.scrollLeft += this.container.clientWidth;\n }\n\n public scrollLeft() {\n this.pane.scrollLeft -= this.container.clientWidth;\n }\n\n private scrollIntoVisibleArea(tabId:string) {\n const tab:JQuery = jQuery(this.pane).find(`[tab-id=${tabId}]`);\n const position:JQueryCoordinates = tab.position();\n\n const tabRightBorderAt:number = position.left + Number(tab.outerWidth());\n\n if (this.pane.scrollLeft + this.container.clientWidth < tabRightBorderAt) {\n this.pane.scrollLeft = tabRightBorderAt - this.container.clientWidth + 40; // 40px to not overlap by buttons\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n Component,\n ElementRef,\n ChangeDetectionStrategy\n} from '@angular/core';\nimport {GonService} from \"core-app/modules/common/gon/gon.service\";\nimport {StateService} from '@uirouter/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ScrollableTabsComponent} from \"core-app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component\";\n\n\nexport const contentTabsSelector = 'content-tabs';\n\ninterface GonTab {\n name:string;\n partial:string;\n path:string;\n label:string;\n}\n\n@Component({\n selector: 'content-tabs',\n templateUrl: '/app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\n\nexport class ContentTabsComponent extends ScrollableTabsComponent {\n public gonTabs:GonTab[];\n public currentTab:GonTab;\n\n public classes:string[] = ['content--tabs', 'scrollable-tabs'];\n\n constructor(readonly elementRef:ElementRef,\n readonly $state:StateService,\n readonly gon:GonService,\n readonly I18n:I18nService) {\n super();\n\n this.gonTabs = JSON.parse((this.gon.get('contentTabs') as any).tabs);\n this.currentTab = JSON.parse((this.gon.get('contentTabs') as any).selected);\n\n // parse tabs from backend and map them to scrollable tabs structure\n this.tabs = this.gonTabs.map((tab:GonTab) => {\n return {\n id: tab.name,\n name: this.I18n.t('js.' + tab.label, { defaultValue: tab.label }),\n path: tab.path\n };\n });\n\n // highlight current tab\n this.currentTabId = this.currentTab.name;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {Component, ElementRef, OnInit} from \"@angular/core\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\nexport const copyToClipboardSelector = 'copy-to-clipboard';\n\n@Component({\n template: '',\n selector: copyToClipboardSelector\n})\nexport class CopyToClipboardDirective implements OnInit {\n public clickTarget:string;\n public clipboardTarget:string;\n private target:JQuery;\n\n constructor(readonly NotificationsService:NotificationsService,\n readonly elementRef:ElementRef,\n readonly I18n:I18nService,\n readonly ConfigurationService:ConfigurationService) {\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement;\n // Get inputs as attributes since this is a bootstrapped directive\n this.clickTarget = element.getAttribute('click-target');\n this.clipboardTarget = element.getAttribute('clipboard-target');\n\n jQuery(this.clickTarget).on('click', (evt:JQuery.TriggeredEvent) => this.onClick(evt));\n\n element.classList.add('copy-to-clipboard');\n this.target = jQuery(this.clipboardTarget ? this.clipboardTarget : element);\n }\n\n addNotification(type:'addSuccess'|'addError', message:string) {\n let notification = this.NotificationsService[type](message);\n\n // Remove the notification some time later\n setTimeout(() => this.NotificationsService.remove(notification), 5000);\n }\n\n onClick($event:JQuery.TriggeredEvent) {\n var supported = (document.queryCommandSupported && document.queryCommandSupported('copy'));\n $event.preventDefault();\n\n // At least select the input for the user\n // even when clipboard API not supported\n this.target.select().focus();\n\n if (supported) {\n try {\n // Copy it to the clipboard\n if (document.execCommand('copy')) {\n this.addNotification('addSuccess', this.I18n.t('js.clipboard.copied_successful'));\n return;\n }\n } catch (e) {\n console.log(\n 'Your browser seems to support the clipboard API, but copying failed: ' + e\n );\n }\n }\n\n this.addNotification('addError', this.I18n.t('js.clipboard.browser_error'));\n }\n}\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ConfirmDialogService} from './../confirm-dialog/confirm-dialog.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {Component, ElementRef, OnInit} from \"@angular/core\";\n\nexport const confirmFormSubmitSelector = 'confirm-form-submit';\n\n@Component({\n template: '',\n selector: confirmFormSubmitSelector\n})\nexport class ConfirmFormSubmitController implements OnInit {\n\n // Allow original form submission after dialog was closed\n public confirmed = false;\n public text = {\n title: this.I18n.t('js.modals.form_submit.title'),\n text: this.I18n.t('js.modals.form_submit.text')\n };\n\n private $element:JQuery;\n private $form:JQuery;\n\n constructor(readonly element:ElementRef,\n readonly confirmDialog:ConfirmDialogService,\n readonly I18n:I18nService) {\n }\n\n ngOnInit() {\n this.$element = jQuery(this.element.nativeElement);\n\n if (this.$element.is('form')) {\n this.$form = this.$element;\n } else {\n this.$form = this.$element.closest('form');\n }\n\n this.$form.on('submit', (evt) => {\n if (!this.confirmed) {\n evt.preventDefault();\n this.openConfirmationDialog();\n return false;\n }\n\n return true;\n });\n }\n\n public openConfirmationDialog() {\n this.confirmDialog.confirm({\n text: this.text,\n closeByEscape: true,\n showClose: true,\n closeByDocument: true,\n }).then(() => {\n this.confirmed = true;\n this.$form.trigger('submit');\n })\n .catch(() => this.confirmed = false);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectorRef, Component, ElementRef, OnInit} from '@angular/core';\nimport {distinctUntilChanged} from 'rxjs/operators';\nimport {ResizeDelta} from \"core-app/modules/common/resizer/resizer.component\";\nimport {MainMenuToggleService} from \"core-components/main-menu/main-menu-toggle.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport const mainMenuResizerSelector = 'main-menu-resizer';\n\n@Component({\n selector: mainMenuResizerSelector,\n template: `\n \n
      \n \n\n \n
      \n
      \n `\n})\n\nexport class MainMenuResizerComponent extends UntilDestroyedMixin implements OnInit {\n public toggleTitle:string;\n private resizeEvent:string;\n private localStorageKey:string;\n\n private elementWidth:number;\n private mainMenu = jQuery('#main-menu')[0];\n\n public moving:boolean = false;\n\n constructor(readonly toggleService:MainMenuToggleService,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef) {\n super();\n }\n\n ngOnInit() {\n this.toggleService.titleData$\n .pipe(\n distinctUntilChanged(),\n this.untilDestroyed()\n )\n .subscribe(setToggleTitle => {\n this.toggleTitle = setToggleTitle;\n this.cdRef.detectChanges();\n });\n\n this.resizeEvent = \"main-menu-resize\";\n this.localStorageKey = \"openProject-mainMenuWidth\";\n }\n\n public resizeStart() {\n this.elementWidth = this.mainMenu.clientWidth;\n }\n\n public resizeMove(deltas:ResizeDelta) {\n this.toggleService.saveWidth(this.elementWidth + deltas.absolute.x);\n }\n\n public resizeEnd() {\n const event = new Event(this.resizeEvent);\n window.dispatchEvent(event);\n }\n}\n","
      \n \n \n \n \n \n
      \n
      \n
      \n {{currentValue}} \n {{item.text}} ↵ \n
      \n
      \n
      \n \n \n \n \n \n
      \n
      \n \n \n \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostListener,\n OnDestroy,\n OnInit,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport {ContainHelpers} from 'core-app/modules/common/focus/contain-helpers';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {GlobalSearchService} from \"core-app/modules/global_search/services/global-search.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {Observable, of} from \"rxjs\";\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {DebouncedRequestSwitchmap, errorNotificationHandler} from \"core-app/helpers/rxjs/debounced-input-switchmap\";\nimport {LinkHandling} from \"core-app/modules/common/link-handling/link-handling\";\nimport {filter, map, take, tap} from \"rxjs/operators\";\nimport {APIV3Service} from \"../../apiv3/api-v3.service\";\nimport { HalResource } from 'core-app/modules/hal/resources/hal-resource';\n\nexport const globalSearchSelector = 'global-search-input';\n\ninterface SearchResultItem {\n id:string;\n subject:string;\n status:string;\n statusId:string;\n $href:string;\n project:string;\n author:HalResource;\n}\n\ninterface SearchOptionItem {\n projectScope:string;\n text:string;\n}\n\n@Component({\n selector: globalSearchSelector,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './global-search-input.component.html',\n styleUrls: ['./global-search-input.component.sass', \"./global-search-input-mobile.component.sass\"],\n // Necessary because of ng-select\n encapsulation: ViewEncapsulation.None\n})\nexport class GlobalSearchInputComponent implements OnInit, OnDestroy {\n @ViewChild('btn', { static: true }) btn:ElementRef;\n @ViewChild(NgSelectComponent, { static: true }) public ngSelectComponent:NgSelectComponent;\n\n public expanded:boolean = false;\n public markable = false;\n\n /** Keep a switchmap for search term and loading state */\n public requests = new DebouncedRequestSwitchmap(\n (searchTerm:string) => this.autocompleteWorkPackages(searchTerm).pipe(\n tap(() => {\n setTimeout(() => this.setMarkedOption(), 50);\n })\n ),\n errorNotificationHandler(this.halNotification)\n );\n\n /** Remember the current value */\n public currentValue:string = '';\n\n /** Remember the item that best matches the query.\n * That way, it will be highlighted (as we manually mark the selected item) and we can handle enter.\n * */\n public selectedItem:SearchResultItem|SearchOptionItem|null;\n\n private unregisterGlobalListener:Function|undefined;\n\n public text:{ [key:string]:string } = {\n all_projects: this.I18n.t('js.global_search.all_projects'),\n current_project: this.I18n.t('js.global_search.current_project'),\n current_project_and_all_descendants: this.I18n.t('js.global_search.current_project_and_all_descendants'),\n search: this.I18n.t('js.global_search.search'),\n search_dots: this.I18n.t('js.global_search.search') + ' ...',\n close_search: this.I18n.t('js.global_search.close_search')\n };\n\n constructor(readonly elementRef:ElementRef,\n readonly I18n:I18nService,\n readonly apiV3Service:APIV3Service,\n readonly PathHelperService:PathHelperService,\n readonly halResourceService:HalResourceService,\n readonly globalSearchService:GlobalSearchService,\n readonly currentProjectService:CurrentProjectService,\n readonly deviceService:DeviceService,\n readonly cdRef:ChangeDetectorRef,\n readonly halNotification:HalResourceNotificationService) {\n }\n\n ngOnInit() {\n // check searchterm on init, expand / collapse search bar and set correct classes\n this.ngSelectComponent.searchTerm = this.currentValue = this.globalSearchService.searchTerm;\n this.expanded = (this.ngSelectComponent.searchTerm.length > 0);\n this.toggleTopMenuClass();\n }\n\n ngOnDestroy() {\n this.unregister();\n }\n\n // detect if click is outside or inside the element\n @HostListener('click', ['$event'])\n public handleClick(event:JQuery.TriggeredEvent):void {\n event.stopPropagation();\n event.preventDefault();\n\n // handle click on search button\n if (ContainHelpers.insideOrSelf(this.btn.nativeElement, event.target)) {\n if (this.deviceService.isMobile) {\n this.toggleMobileSearch();\n // open ng-select menu on default\n jQuery('.ng-input input').focus();\n } else if (this.ngSelectComponent.searchTerm.length === 0) {\n this.ngSelectComponent.focus();\n } else {\n this.submitNonEmptySearch();\n }\n }\n }\n\n // open or close mobile search\n public toggleMobileSearch() {\n this.expanded = !this.expanded;\n this.toggleTopMenuClass();\n }\n\n public redirectToWp(id:string, event:MouseEvent) {\n event.stopImmediatePropagation();\n if (LinkHandling.isClickedWithModifier(event)) {\n return true;\n }\n\n window.location.href = this.wpPath(id);\n event.preventDefault();\n return false;\n }\n\n public wpPath(id:string) {\n return this.PathHelperService.workPackagePath(id);\n }\n\n public search($event:any) {\n this.currentValue = this.ngSelectComponent.searchTerm;\n this.openCloseMenu($event.term);\n }\n\n // close menu when input field is empty\n public openCloseMenu(searchedTerm:string) {\n this.ngSelectComponent.isOpen = (searchedTerm.trim().length > 0);\n }\n\n public onFocus() {\n this.expanded = true;\n this.toggleTopMenuClass();\n this.openCloseMenu(this.currentValue);\n }\n\n public onFocusOut() {\n if (!this.deviceService.isMobile) {\n this.expanded = (this.ngSelectComponent.searchTerm.length > 0);\n this.ngSelectComponent.isOpen = false;\n this.toggleTopMenuClass();\n }\n }\n\n public clearSearch() {\n this.currentValue = this.ngSelectComponent.searchTerm = '';\n this.openCloseMenu(this.currentValue);\n }\n\n // If Enter key is pressed before result list is loaded, wait for the results to come\n // in and then decide what to do. If a direct hit is present, follow that. Otherwise,\n // go to the search in the current scope.\n public onEnterBeforeResultsLoaded() {\n this.requests.loading$.pipe(\n filter(value => value === false),\n take(1)\n )\n .subscribe(() => {\n if (this.selectedItem) {\n this.followSelectedItem();\n } else {\n this.searchInScope(this.currentScope);\n }\n });\n }\n\n public statusHighlighting(statusId:string) {\n return Highlighting.inlineClass('status', statusId);\n }\n\n private get isDirectHit() {\n return this.selectedItem && this.selectedItem.hasOwnProperty('id');\n }\n\n public followItem(item:SearchResultItem|SearchOptionItem) {\n if (item.hasOwnProperty('id')) {\n window.location.href = this.wpPath((item as SearchResultItem).id);\n } else {\n // update embedded table and title when new search is submitted\n this.globalSearchService.searchTerm = this.currentValue;\n this.searchInScope((item as SearchOptionItem).projectScope);\n }\n }\n\n public followSelectedItem() {\n if (this.selectedItem) {\n this.followItem(this.selectedItem);\n }\n }\n\n // return all project scope items and all items which contain the search term\n public customSearchFn(term:string, item:any):boolean {\n return item.id === undefined || item.subject.toLowerCase().indexOf(term.toLowerCase()) !== -1;\n }\n\n private autocompleteWorkPackages(query:string):Observable<(SearchResultItem|SearchOptionItem)[]> {\n if (!query) {\n return of([]);\n }\n\n // Reset the currently selected item.\n // We do not follow the typical goal of an autocompleter of \"setting a value\" here.\n this.selectedItem = null;\n // Hide highlighting of ng-option\n this.markable = false;\n\n\n let hashFreeQuery = this.queryWithoutHash(query);\n\n return this\n .fetchSearchResults(hashFreeQuery, hashFreeQuery !== query)\n .get()\n .pipe(\n map((collection) => {\n return this.searchResultsToOptions(collection.elements, hashFreeQuery);\n })\n );\n }\n\n // Remove ID marker # when searching for #\n private queryWithoutHash(query:string) {\n if (query.match(/^#(\\d+)/)) {\n return query.substr(1);\n } else {\n return query;\n }\n }\n\n private fetchSearchResults(query:string, idOnly:boolean) {\n return this\n .apiV3Service\n .work_packages\n .filterBySubjectOrId(query, idOnly);\n }\n\n private searchResultsToOptions(results:WorkPackageResource[], query:string) {\n let searchItems = results.map((wp) => {\n let item = {\n id: wp.id!,\n subject: wp.subject,\n status: wp.status.name,\n statusId: wp.status.idFromLink,\n $href: wp.$href,\n project: wp.project.name,\n author: wp.author\n } as SearchResultItem;\n\n // If we have a direct hit, we choose it to be the selected element.\n if (query === wp.id!.toString()) {\n this.selectedItem = item;\n }\n\n return item;\n });\n\n let searchOptions = this.detailedSearchOptions();\n\n if (!this.selectedItem) {\n this.selectedItem = searchOptions[0];\n }\n\n return (searchOptions as (SearchResultItem|SearchOptionItem)[]).concat(searchItems);\n }\n\n // set the possible 'search in scope' options for the current project path\n private detailedSearchOptions() {\n let searchOptions = [];\n // add all options when searching within a project\n // otherwise search in 'all projects'\n if (this.currentProjectService.path) {\n searchOptions.push('current_project_and_all_descendants');\n searchOptions.push('current_project');\n }\n if (this.globalSearchService.projectScope === 'current_project') {\n searchOptions.reverse();\n }\n searchOptions.push('all_projects');\n\n return searchOptions.map((suggestion:string) => {\n return { projectScope: suggestion, text: this.text[suggestion] };\n });\n }\n\n /*\n * Set the marked ng-option within ng-select and apply the class to highlight marked options.\n *\n * ng-select differentiates between the selected and the marked option. The selected optinon is the option\n * that is binded via ng-model. The marked option is the one that the user is currently selecting (via mouse or keyboard up/down).\n * When hitting enter, the marked option is taken to be the new selected option. Ng-select will retain the index of the marked\n * option between individual searches. The selected option has no influence on the marked option. This is problematic\n * in our use case as the user might have:\n * * the mouse hovering (deliberately or not) over the search options which will mark that option.\n * * marked an option for a previous search but might then have decided to add/remove additional characters to the search.\n *\n * In both cases, whenever the user presses enter then, ng-select assigns the marked option to the ng-model.\n *\n * Our goal however is to either:\n * * mark the direct hit (id matches) if it available\n * * mark the first item if there is no direct hit\n *\n * And we need to update the marked option after every search.\n *\n * There is no way of doing this via the interface provided in the template. There is only [markFirst] and it neither allows us\n * to mark a direct hit, nor does it reset after a search. We handle this then by selecting the desired element once the\n * search results are back. We then set the marked option to be the selected option.\n *\n * In order to avoid flickering, a -markable modifyer class is unset/set before/after searching. This will unset the background until we\n * have marked the element we wish to.\n */\n private setMarkedOption() {\n this.markable = true;\n this.ngSelectComponent.itemsList.markItem(this.ngSelectComponent.itemsList.selectedItems[0]);\n\n this.cdRef.detectChanges();\n }\n\n private searchInScope(scope:string) {\n switch (scope) {\n case 'all_projects': {\n let forcePageLoad = false;\n if (this.globalSearchService.projectScope !== 'all') {\n forcePageLoad = true;\n this.globalSearchService.resultsHidden = true;\n }\n this.globalSearchService.projectScope = 'all';\n this.submitNonEmptySearch(forcePageLoad);\n break;\n }\n case 'current_project': {\n this.globalSearchService.projectScope = 'current_project';\n this.submitNonEmptySearch();\n break;\n }\n case 'current_project_and_all_descendants': {\n this.globalSearchService.projectScope = '';\n this.submitNonEmptySearch();\n break;\n }\n }\n }\n\n public submitNonEmptySearch(forcePageLoad:boolean = false) {\n this.globalSearchService.searchTerm = this.currentValue;\n if (this.currentValue.length > 0) {\n this.ngSelectComponent.close();\n // Work package results can update without page reload.\n if (!forcePageLoad &&\n this.globalSearchService.isAfterSearch() &&\n this.globalSearchService.currentTab === 'work_packages') {\n window.history\n .replaceState({},\n `${I18n.t('global_search.search')}: ${this.ngSelectComponent.searchTerm}`,\n this.globalSearchService.searchPath());\n\n return;\n }\n this.globalSearchService.submitSearch();\n }\n }\n\n public blur() {\n this.ngSelectComponent.searchTerm = '';\n (document.activeElement).blur();\n }\n\n private get currentScope():string {\n let serviceScope = this.globalSearchService.projectScope;\n return (serviceScope === '') ? 'current_project_and_all_descendants' : serviceScope;\n }\n\n private unregister() {\n if (this.unregisterGlobalListener) {\n this.unregisterGlobalListener();\n this.unregisterGlobalListener = undefined;\n }\n }\n\n private toggleTopMenuClass() {\n jQuery('#top-menu').toggleClass('-global-search-expanded', this.expanded);\n }\n}\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {Component, ElementRef, OnInit, ViewChild} from \"@angular/core\";\n\nexport const collapsibleSectionAugmentSelector = 'collapsible-section-augment';\n\n@Component({\n selector: collapsibleSectionAugmentSelector,\n templateUrl: './collapsible-section.html'\n})\nexport class CollapsibleSectionComponent implements OnInit {\n public expanded:boolean = false;\n public sectionTitle:string;\n\n @ViewChild('sectionBody', { static: true }) public sectionBody:ElementRef;\n\n constructor(public elementRef:ElementRef) {\n }\n\n ngOnInit():void {\n const element:HTMLElement = this.elementRef.nativeElement;\n\n this.sectionTitle = element.getAttribute('section-title')!;\n if (element.getAttribute('initially-expanded') === 'true') {\n this.expanded = true;\n }\n\n const target:HTMLElement = element.nextElementSibling as HTMLElement;\n this.sectionBody.nativeElement.appendChild(target);\n target.removeAttribute('hidden');\n }\n\n public toggle() {\n this.expanded = !this.expanded;\n }\n}\n","
      \n\n \n \n \n
      \n \n
      \n
      \n","import {Component, ElementRef, OnInit} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\nexport const enterpriseBannerSelector = 'enterprise-banner-bootstrap';\n\n@Component({\n selector: enterpriseBannerSelector,\n template: `\n \n \n `\n})\nexport class EnterpriseBannerBootstrapComponent implements OnInit {\n public textMessage:string;\n public linkMessage:string;\n public referrer:string;\n\n constructor(protected elementRef:ElementRef,\n protected i18n:I18nService) {\n }\n\n ngOnInit() {\n let $element = jQuery(this.elementRef.nativeElement);\n\n this.textMessage = $element.attr('text-message')!;\n this.linkMessage = $element.attr('link-message') || this.i18n.t('js.work_packages.table_configuration.upsale.check_out_link');\n this.referrer = $element.attr('referrer')!;\n }\n}\n","import * as Fuse from 'fuse.js';\n\nexport interface IAutocompleteItem {\n label:string;\n render:'match' | 'disabled';\n object:T;\n}\n\nexport abstract class ILazyAutocompleterBridge {\n // Current page the autocompleter is on\n public currentPage:number;\n\n // Input autocomplete element\n public input:any;\n\n // Fuzzy instance for the results\n public fuseInstance:any;\n\n public constructor(public widgetName:string) {\n LazyLoadedAutocompleter.register(widgetName, this);\n }\n\n /**\n * Return the maximum number of items to render in this page.\n * Note that for this value, the container must be setup that a scrollbar exists.\n * @returns {number}\n */\n public abstract get maxItemsPerPage():number;\n\n /**\n * Handler function for when an active item was selected through the autocompleter\n * @param {T} item\n */\n public abstract onItemSelected(item:T):void;\n\n /**\n * Handler function for when no results were matched through the search term.\n * @param {JQueryUI.AutocompleteEvent} event\n * @param {JQueryUI.AutocompleteUIParams} ui\n */\n public abstract onNoResultsFound(event:JQueryUI.AutocompleteEvent, ui:any):void;\n\n /**\n * Customize the rendering of an inner item element.\n *\n * @param {IAutocompleteItem} item\n * @param {JQuery} div\n */\n public renderItem(item:IAutocompleteItem, div:JQuery):void {\n div.text(item.label);\n }\n\n /**\n * Returns the elements matched by the fuzzy search\n */\n private fuzzySearch(items:IAutocompleteItem[], term:string) {\n if (term === '') {\n return items;\n } else if (term.length >= 3) {\n const literalMatches = this.literalSearch(items, term);\n\n if (literalMatches.length > 0) {\n return literalMatches as any;\n }\n }\n\n return this.fuseInstance.search(term);\n }\n\n /**\n * Filters the given list of items so that only items whose label contains\n * the exact search term (case insensitive).\n *\n * @param items Items to be searched\n * @param term Search term\n * @return The subset of the given items matching the search term.\n */\n private literalSearch(items:IAutocompleteItem[], term:string) {\n const results:IAutocompleteItem[] = [];\n const str:string = term.toLowerCase();\n\n items.forEach(e => {\n if (e.label.toLowerCase().indexOf(str) !== -1) {\n results.push(e);\n }\n });\n\n return results;\n }\n\n /**\n * Allows to augment the set of matched items (e.g., to add hierarchy).\n * @param {IAutocompleteItem[]} items\n * @param {IAutocompleteItem[]} matched\n * @returns {IAutocompleteItem[]}\n */\n protected augmentedResultSet(items:IAutocompleteItem[], matched:IAutocompleteItem[]) {\n // By default, set all to match\n const results:IAutocompleteItem[] = [];\n\n matched.forEach(el => {\n results.push({\n label: el.label,\n object: el.object,\n render: 'match'\n } as IAutocompleteItem);\n });\n\n return results;\n }\n\n public setup(input:JQuery, items:IAutocompleteItem[]) {\n this.currentPage = 0;\n this.input = input;\n this.input[this.widgetName].call(this.input, this.setupParams(items));\n const options = {\n shouldSort: true,\n tokenize: false,\n threshold: 0.2,\n location: 0,\n distance: 10000, // allow the term to appear anywhere\n maxPatternLength: 16,\n minMatchCharLength: 2,\n keys: ['label'] as any\n };\n\n this.fuseInstance = new Fuse(items, options);\n }\n\n protected setupParams(autocompleteValues:IAutocompleteItem[]) {\n const ctrl = this;\n\n return {\n delay: 50,\n source: function (request:any, response:any) {\n const fuzzyResults = ctrl.fuzzySearch(autocompleteValues, request.term);\n response(ctrl.augmentedResultSet(autocompleteValues, fuzzyResults));\n },\n select: (ul:any, selected:{ item:IAutocompleteItem }) => {\n if (selected.item.render === 'match') {\n ctrl.onItemSelected(selected.item.object);\n }\n },\n create: () => ctrl.input.focus(),\n response: (event:JQueryUI.AutocompleteEvent, ui:JQueryUI.AutocompleteUIParams) => {\n ctrl.onNoResultsFound(event, ui);\n },\n autoFocus: true,\n minLength: 0\n };\n }\n}\n\nexport namespace LazyLoadedAutocompleter {\n\n /**\n * Returns whether the scrollbar is at a place where we should display additional elements\n * @param ul\n */\n function isScrollbarBottom(container:JQuery) {\n var height = container.outerHeight()!;\n var scrollHeight = container[0].scrollHeight;\n var scrollTop = container.scrollTop()!;\n return scrollTop >= (scrollHeight - height);\n }\n\n export function register(name:string, ctrl:ILazyAutocompleterBridge) {\n jQuery.widget(`custom.${name}`, jQuery.ui.autocomplete, {\n _create: function (this:any) {\n ctrl.currentPage = 0;\n this._super();\n this.widget().menu('option', 'items', '> .ui-matched-item');\n this._search('');\n },\n\n _renderMenu: function (this:any, ul:HTMLElement, items:IAutocompleteItem[]) {\n //remove scroll event to prevent attaching multiple scroll events to one container element\n jQuery(ul).unbind('scroll');\n\n this._renderLazyMenu(ul, items);\n },\n\n // Rener the menu for the current page\n _renderMenuPage(this:any, ul:JQuery, items:IAutocompleteItem[], page:number|null = null) {\n let widget = this;\n let rendered:number = items.length;\n let pageElements = items;\n let max = ctrl.maxItemsPerPage;\n if (page !== null) {\n pageElements = items.slice(page * max, (page * max) + max);\n rendered = Math.min(items.length, (page * max) + max);\n }\n\n // Insert elements of this page\n jQuery.each(pageElements, function (index, item) {\n widget._renderItemData(ul, item);\n });\n\n // Ensure scrollbar is shown when more results exist\n ul.css('height', 'auto');\n if (rendered < items.length) {\n const maxHeight = document.body.offsetHeight * 0.55;\n const shownHeight = rendered * 32;\n\n if (shownHeight < maxHeight) {\n ul.css('height', shownHeight - 50);\n }\n }\n },\n\n /**\n * Return the number of (lazy) pages for the curent set of results\n * @param {IAutocompleteItem[]} items\n * @returns {number}\n */\n _pages(items:IAutocompleteItem[]):number {\n return Math.ceil(items.length / ctrl.maxItemsPerPage);\n },\n\n _repositionMenu: function (this:any, container:JQuery) {\n const widget = this;\n const menu = widget.menu;\n\n menu.refresh();\n\n // Call ui's own resize\n widget._resizeMenu();\n\n container.position(jQuery.extend({of: widget.element}, widget.options.position));\n if (widget.options.autoFocus) {\n menu.next(new jQuery.Event('mouseover'));\n }\n },\n\n _resizeMenu: function (this:any) {\n var ul = this.menu.element;\n ul.outerWidth(this.element.outerWidth());\n },\n\n _renderItem: function (this:any, ul:JQuery, item:IAutocompleteItem) {\n const term = this.element.val();\n const disabled = item.render === 'disabled';\n const div = jQuery('
      ').addClass('ui-menu-item-wrapper');\n\n ctrl.renderItem(item, div);\n\n const element = jQuery('
    • ')\n .toggleClass('ui-state-disabled', disabled)\n .toggleClass('ui-matched-item', !disabled)\n .append(div)\n .appendTo(ul);\n\n if (term !== '') {\n (element as any).mark(term, {className: 'ui-autocomplete-match'});\n }\n\n return element;\n },\n\n _renderLazyMenu: function (this:any, ul:Element, items:IAutocompleteItem[]) {\n const widget = this;\n const container = jQuery(ul) as JQuery;\n const pages = this._pages(items);\n\n if (pages <= 1) {\n return widget._renderMenuPage(ul, items);\n }\n\n widget._renderMenuPage(ul, items, 0);\n\n container.scroll(function () {\n if (isScrollbarBottom(container)) {\n if (++ctrl.currentPage >= pages) {\n return;\n }\n\n // Render the current menu page\n widget._renderMenuPage(ul, items, ctrl.currentPage);\n\n // Refresh the menu\n widget._repositionMenu(ul);\n }\n });\n }\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {\n IAutocompleteItem,\n ILazyAutocompleterBridge\n} from 'core-app/modules/common/autocomplete/lazyloaded/lazyloaded-autocompleter';\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {LinkHandling} from 'core-app/modules/common/link-handling/link-handling';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HttpClient} from \"@angular/common/http\";\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit} from \"@angular/core\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\n\nexport interface IProjectMenuEntry {\n id:number;\n name:string;\n identifier:string;\n parents:IProjectMenuEntry[];\n level:number;\n}\n\nexport type ProjectAutocompleteItem = IAutocompleteItem;\n\nexport const projectMenuAutocompleteSelector = 'project-menu-autocomplete';\n\n@Component({\n templateUrl: './project-menu-autocomplete.template.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: projectMenuAutocompleteSelector\n})\nexport class ProjectMenuAutocompleteComponent extends ILazyAutocompleterBridge implements OnInit {\n public text:any;\n\n // The project dropdown menu\n public dropdownMenu:JQuery;\n // The project filter input\n public input:JQuery;\n // No results element\n public noResults:JQuery;\n\n // The result set for the instance, loaded only once\n public results:null|IProjectMenuEntry[] = null;\n\n private loaded = false;\n private $element:JQuery;\n\n\n constructor(protected PathHelper:PathHelperService,\n protected elementRef:ElementRef,\n protected http:HttpClient,\n protected cdRef:ChangeDetectorRef,\n protected I18n:I18nService,\n protected currentProject:CurrentProjectService) {\n super('projectMenuAutocomplete');\n\n this.text = {\n label: I18n.t('js.projects.autocompleter.label'),\n no_results: I18n.t('js.notice_no_principals_found'),\n loading: I18n.t('js.ajax.loading')\n };\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n this.dropdownMenu = this.$element.parents('li.drop-down');\n this.input = this.$element.find('.project-menu-autocomplete--input');\n this.noResults = this.$element.find('.project-menu-autocomplete--no-results');\n\n this.dropdownMenu.on('opened', () => this.open());\n this.dropdownMenu.on('closed', () => this.close());\n }\n\n public close() {\n try {\n (this.input as any).projectMenuAutocomplete('destroy');\n } catch (e) {\n console.warn(\"Failed to destroy autocomplete: %O\", e);\n }\n this.$element.find('.project-search-results').css('visibility', 'hidden');\n }\n\n public open() {\n this.$element.find('.project-search-results').css('visibility', 'visible');\n this.loadProjects().then((results:IProjectMenuEntry[]) => {\n let autocompleteValues = _.map(results, project => {\n return { label: project.name, render: 'match', object: project } as ProjectAutocompleteItem;\n });\n\n this.setup(this.input, autocompleteValues);\n this.addInputHandlers();\n this.addClickHandler();\n this.loaded = true;\n this.cdRef.detectChanges();\n\n this.scrollCurrentProjectIntoView();\n });\n }\n\n // Items per page to show before using lazy load\n // Please note that the max-height of the container is relevant here.\n public get maxItemsPerPage() {\n return 250;\n }\n\n onItemSelected(project:IProjectMenuEntry):void {\n window.location.href = this.projectLink(project.identifier);\n }\n\n onNoResultsFound(event:JQueryUI.AutocompleteEvent, ui:any):void {\n // Show the noResults span if we don't have any matches\n this.noResults.toggle(ui.content.length === 0);\n }\n\n public renderItem(item:ProjectAutocompleteItem, div:JQuery):void {\n const link = jQuery('')\n .attr('href', this.projectLink(item.object.identifier))\n .text(item.label)\n .appendTo(div);\n\n // When in hierarchy, indent\n if (item.object.level > 0) {\n link\n .text(`» ${item.label}`)\n .css('padding-left', (4 + item.object.level * 16) + 'px');\n }\n\n // Highlight selected project\n if (item.object.identifier === this.currentProject.identifier) {\n div.addClass('selected');\n }\n }\n\n public projectLink(identifier:string) {\n const currentMenuItem = jQuery('meta[name=\"current_menu_item\"]').attr('content');\n let url = this.PathHelper.projectPath(identifier);\n\n if (currentMenuItem) {\n url += '?jump=' + encodeURIComponent(currentMenuItem);\n }\n\n return url;\n }\n\n public get loadingText():string {\n if (this.loaded) {\n return '';\n } else {\n return this.text.loading;\n }\n }\n\n private loadProjects() {\n if (this.results !== null) {\n return Promise.resolve(this.results);\n }\n\n const url = this.PathHelper.projectLevelListPath();\n return this.http\n .get(url)\n .toPromise()\n .then((result:{ projects:any }) => {\n return this.results = this.augmentWithParents(result.projects);\n });\n }\n\n /**\n * Augment the level_list with the set of parents that belong to this project\n */\n public augmentWithParents(projects:IProjectMenuEntry[]) {\n const parents:IProjectMenuEntry[] = [];\n let currentLevel = -1;\n\n return projects.map((project) => {\n while (currentLevel >= project.level) {\n parents.pop();\n currentLevel--;\n }\n\n parents.push(project);\n currentLevel = project.level;\n project.parents = parents.slice(0, -1); // make sure to pass a clone\n\n return project;\n });\n }\n\n /**\n * Determines from the set of matched results, the elements we should render\n * (ie. including the parents of the elements)\n */\n protected augmentedResultSet(items:ProjectAutocompleteItem[], matched:ProjectAutocompleteItem[]) {\n const matches = matched.map(el => el.object.identifier);\n const matchedParents = _.flatten(matched.map(el => el.object.parents));\n\n const results:ProjectAutocompleteItem[] = [];\n\n items.forEach(el => {\n const identifier = el.object.identifier;\n let renderType:'disabled'|'match';\n\n if (matches.indexOf(identifier) >= 0) {\n renderType = 'match';\n } else if (_.find(matchedParents, e => e.identifier === identifier)) {\n renderType = 'disabled';\n } else {\n return;\n }\n\n results.push({\n label: el.label,\n object: el.object,\n render: renderType\n });\n });\n\n return results;\n }\n\n /**\n * Avoid closing the results when the input has lost focus.\n */\n protected addInputHandlers() {\n this.input.off('blur');\n\n this.input.keydown((evt:JQuery.TriggeredEvent) => {\n if (evt.which === keyCodes.ESCAPE) {\n this.input.val('');\n (this.input as any)[this.widgetName].call(this.input, 'search', '');\n return false;\n }\n\n return true;\n });\n }\n\n /**\n * When clicking an item with meta keys,\n * avoid its propagation.\n *\n */\n protected addClickHandler() {\n var touchMoved:boolean = false;\n this.$element\n .find('.project-menu-autocomplete--results')\n .on('click', '.ui-menu-item a', (evt:JQuery.TriggeredEvent) => {\n if (LinkHandling.isClickedWithModifier(evt)) {\n evt.stopImmediatePropagation();\n }\n\n return true;\n })\n\n // On iOS the click event doesn't get fired. So we need to listen to touch events and discard them if they they\n // are the beginning of some scrolling.\n .on('touchend', '.ui-menu-item a', function (evt:JQuery.TriggeredEvent) {\n if (!touchMoved) {\n window.location.href = (evt.target as HTMLAnchorElement).href;\n }\n }).on('touchmove', '.ui-menu-item a', function () {\n touchMoved = true;\n }).on('touchstart', '.ui-menu-item a', function () {\n touchMoved = false;\n });\n }\n\n protected setupParams(autocompleteValues:ProjectAutocompleteItem[]) {\n const params:any = super.setupParams(autocompleteValues);\n\n // Append to top-menu\n params.appendTo = '.project-menu-autocomplete--wrapper';\n params.classes = {\n 'ui-autocomplete': '-inplace project-menu-autocomplete--results'\n };\n params.position = {\n of: '.project-menu-autocomplete--input-container'\n }\n\n return params;\n }\n\n private scrollCurrentProjectIntoView() {\n let currentProject:HTMLElement|null = document.querySelector('.ui-menu-item-wrapper.selected');\n\n // It can happen that no project is selected yet initially.\n if (!currentProject) {\n return;\n }\n\n let currentProjectHeight = currentProject.offsetHeight;\n let scrollableContainer = document.getElementsByClassName('project-menu-autocomplete--results')[0];\n\n // Scroll current project to top of the list and\n // substract half the container width again to center it vertically\n let scrollValue = currentProject.offsetTop -\n (scrollableContainer as HTMLElement).offsetHeight / 2 +\n currentProjectHeight / 2;\n\n // The top visible project shall be seen completely.\n // Otherwise there will be a scrolling effect when the user hovers over the project.\n scrollableContainer.scrollTop = (scrollValue % currentProjectHeight === 0) ?\n scrollValue :\n scrollValue - (scrollValue % currentProjectHeight);\n }\n}\n\n","
      \n
      \n
      \n \n \n \n
      \n \n
      \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, OnInit} from '@angular/core';\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {HttpClient} from '@angular/common/http';\n\nexport const remoteFieldUpdaterSelector = 'remote-field-updater';\n\n@Component({\n selector: remoteFieldUpdaterSelector,\n template: ''\n})\nexport class RemoteFieldUpdaterComponent implements OnInit {\n\n constructor(private elementRef:ElementRef,\n private http:HttpClient) {\n }\n\n private url:string;\n private htmlMode:boolean;\n\n private inputs:JQuery;\n private target:JQuery;\n\n ngOnInit():void {\n const $element = jQuery(this.elementRef.nativeElement);\n const $form = $element.parent();\n this.inputs = $form.find('.remote-field--input');\n this.target = $form.find('.remote-field--target');\n\n this.url = $element.data('url');\n this.htmlMode = $element.data('mode') === 'html';\n\n this.inputs.on('keyup change', _.debounce((event:JQuery.TriggeredEvent) => {\n // This prevents an update of the result list when\n // tabbing to the result list (9),\n // pressing enter (13)\n // tabbing back with shift (16) and\n // special cases where the tab code is not correctly recognized (undefined).\n // Thus the focus is kept on the first element of the result list.\n let keyCodesArray = [keyCodes.TAB, keyCodes.ENTER, keyCodes.SHIFT];\n if (event.type === 'change' || (event.which && keyCodesArray.indexOf(event.which) === -1)) {\n this.updater();\n }\n }, 500));\n }\n\n private request(params:any) {\n const headers:any = {};\n\n // In HTML mode, expect html response\n if (this.htmlMode) {\n headers['Accept'] = 'text/html';\n } else {\n headers['Accept'] = 'application/json';\n }\n\n return this.http\n .get(\n this.url,\n {\n params: params,\n headers: headers,\n responseType: (this.htmlMode ? 'text' : 'json') as any,\n withCredentials: true\n }\n );\n }\n\n private updater() {\n let params:any = {};\n\n // Gather request keys\n this.inputs.each((i, el:HTMLInputElement) => {\n params[el.dataset.remoteFieldKey!] = el.value;\n });\n\n this\n .request(params)\n .subscribe((response:any) => {\n if (this.htmlMode) {\n // Replace the given target\n this.target.html(response);\n } else {\n _.each(response, (val:string, selector:string) => {\n let element = document.getElementById(selector) as HTMLElement|HTMLInputElement;\n\n if (element instanceof HTMLInputElement) {\n element.value = val;\n } else if (element) {\n element.textContent = val;\n }\n });\n }\n });\n }\n}\n\n","
      \n
      \n
      \n \n \n \n
      \n
      \n

      \n
      \n
      \n
      \n
      \n
      \n
      \n
      \n
      \n
      \n
      \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {States} from '../states.service';\nimport {StateService, TransitionService} from '@uirouter/core';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild} from \"@angular/core\";\nimport {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {WorkPackageStaticQueriesService} from 'core-components/wp-query-select/wp-static-queries.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {LinkHandling} from \"core-app/modules/common/link-handling/link-handling\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {MainMenuToggleService} from \"core-components/main-menu/main-menu-toggle.service\";\nimport {MainMenuNavigationService} from \"core-components/main-menu/main-menu-navigation.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport type QueryCategory = 'starred'|'public'|'private'|'default';\n\nexport interface IAutocompleteItem {\n // Some optional identifier\n identifier?:string;\n // Internal id for selecting items\n auto_id?:number;\n // The autocomplete item may be a static link (e.g., summary page)\n static_link?:string;\n // Label for the current locale\n label:string;\n // May be tied to a persisted query\n query?:QueryResource;\n // Or a loose map of query_props\n query_props?:any;\n // And is tied to a category\n category?:QueryCategory;\n}\n\ninterface IQueryAutocompleteJQuery extends JQuery {\n querycomplete(...args:any[]):void;\n}\n\nexport const wpQuerySelectSelector = 'wp-query-select';\n\n@Component({\n selector: wpQuerySelectSelector,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './wp-query-select.template.html',\n})\nexport class WorkPackageQuerySelectDropdownComponent extends UntilDestroyedMixin implements OnInit {\n @ViewChild('wpQueryMenuSearchInput', { static: true }) _wpQueryMenuSearchInput:ElementRef;\n @ViewChild('queryResultsContainer', { static: true }) _queryResultsContainerElement:ElementRef;\n\n public loading = false;\n public noResults = false;\n\n public text = {\n search: this.I18n.t('js.toolbar.search_query_label'),\n label: this.I18n.t('js.toolbar.search_query_label'),\n scope_default: this.I18n.t('js.label_default_queries'),\n scope_starred: this.I18n.t('js.label_starred_queries'),\n scope_global: this.I18n.t('js.label_global_queries'),\n scope_private: this.I18n.t('js.label_custom_queries'),\n no_results: this.I18n.t('js.work_packages.query.text_no_results'),\n };\n private unregisterTransitionListener:Function;\n\n private projectIdentifier:string|null;\n\n private hiddenCategories:any = [];\n\n private reportsBodySelector = '.controller-work_packages\\\\/reports';\n\n private queryResultsContainer:JQuery;\n private buttonArrowLeft:JQuery;\n\n private searchInput:IQueryAutocompleteJQuery;\n\n private initialized = false;\n\n\n constructor(readonly ref:ChangeDetectorRef,\n readonly element:ElementRef,\n readonly apiV3Service:APIV3Service,\n readonly $state:StateService,\n readonly $transitions:TransitionService,\n readonly I18n:I18nService,\n readonly states:States,\n readonly CurrentProject:CurrentProjectService,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly pathHelper:PathHelperService,\n readonly wpStaticQueries:WorkPackageStaticQueriesService,\n readonly mainMenuService:MainMenuNavigationService,\n readonly toggleService:MainMenuToggleService,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n public ngOnInit() {\n this.queryResultsContainer = jQuery(this._queryResultsContainerElement.nativeElement);\n this.projectIdentifier = this.element.nativeElement.getAttribute('data-project-identifier');\n\n // When activating the work packages submenu,\n // either initially or through click on the toggle, load the results\n this.mainMenuService\n .onActivate('work_packages', 'work_packages_query_select')\n .subscribe(() => this.initializeAutocomplete());\n\n // Register click handler on results\n this.addClickHandler();\n this.cdRef.detach();\n }\n\n ngOnDestroy() {\n super.ngOnDestroy();\n this.unregisterTransitionListener();\n }\n\n private initializeAutocomplete() {\n if (this.initialized) {\n return;\n }\n\n this.searchInput = jQuery(this._wpQueryMenuSearchInput.nativeElement) as any;\n this.buttonArrowLeft = jQuery('.main-menu--arrow-left-to-project', jQuery('#main-menu-work-packages-wrapper').parent()) as any;\n this.initialized = true;\n this.buttonArrowLeft.focus();\n this.setupAutoCompletion(this.searchInput);\n this.updateMenuOnChanges();\n this.loadQueries();\n }\n\n private transformQueries(collection:CollectionResource) {\n let loadedQueries:IAutocompleteItem[] = collection.elements\n .map(query => {\n return { label: query.name, query: query, query_props: null };\n });\n\n // Add to the loaded set of queries the fixed set of queries for the current project context\n const combinedQueries = loadedQueries.concat(this.wpStaticQueries.all);\n return this.sortQueries(combinedQueries);\n }\n\n // Filter the collection by categories, add the correct categories to every item of the filtered array\n // Sort every category array alphabetically, except the default queries\n private sortQueries(items:IAutocompleteItem[]):IAutocompleteItem[] {\n // Concat all categories in the right order\n let categorized:{ [category:string]:IAutocompleteItem[] } = {\n // Starred / favored\n starred: [],\n // default\n default: [],\n // public\n public: [],\n // private\n private: []\n };\n\n let auto_id = 0;\n items.forEach((item):any => {\n item.auto_id = auto_id++;\n\n if (!item.query) {\n item.category = 'default';\n return categorized.default.push(item);\n }\n\n if (item.query.starred) {\n item.category = 'starred';\n return categorized.starred.push(item);\n }\n\n if (!item.query.starred && item.query.public) {\n item.category = 'public';\n return categorized.public.push(item);\n }\n\n if (!(item.query.starred || item.query.public)) {\n item.category = 'private';\n return categorized.private.push(item);\n }\n });\n\n return _.flatten(\n [categorized.starred, categorized.default, categorized.public, categorized.private]\n .map(items => this.sortByLabel(items))\n );\n }\n\n // Sort a given array of items by the value of their label attribute\n private sortByLabel(items:IAutocompleteItem[]):IAutocompleteItem[] {\n return items.sort((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase()));\n }\n\n private loadQueries() {\n return this.loadingPromise = this\n .apiV3Service\n .queries\n .filterNonHidden(this.CurrentProject.identifier)\n .toPromise()\n .then(collection => {\n\n // Update the complete collection\n this.searchInput.querycomplete(\"option\", { source: this.transformQueries(collection) });\n\n // To visibly show the changes, we need to search again\n this.searchInput.querycomplete(\"search\", this.searchInput.val());\n\n // To search an empty string would expand all categories again every time\n // Remember all previously hidden categories and set them again after updating the menu\n _.each(this.hiddenCategories, category => {\n let thisCategory:string = jQuery(category).attr(\"category\")!;\n this.expandCollapseCategory(thisCategory);\n });\n\n // Update view\n this.ref.detectChanges();\n });\n }\n\n private set loadingPromise(promise:Promise) {\n this.loading = true;\n promise\n .then(() => {\n this.loading = false;\n this.cdRef.detectChanges();\n })\n .catch(() => {\n this.loading = false;\n this.cdRef.detectChanges();\n });\n }\n\n private setupAutoCompletion(input:IQueryAutocompleteJQuery) {\n this.defineJQueryQueryComplete();\n\n input.querycomplete({\n delay: 100,\n // The values are added later by the listener also covering\n // the changes to queries (updateMenuOnChanges()).\n source: [],\n select: (ul:any, selected:{ item:IAutocompleteItem }) => {\n return false; // Don't show title of selected query in the input field\n },\n response: (event:any, ui:any) => {\n // Show the noResults span if we don't have any matches\n this.noResults = (ui.content.length === 0);\n },\n close: (event:any, ui:any) => {\n const autocompleteUi = this.queryResultsContainer.find('ul.ui-autocomplete');\n if (!autocompleteUi.is(\":visible\") && !this.noResults) {\n autocompleteUi.show();\n }\n },\n focus: (_event:JQuery.TriggeredEvent, ui:{ item:IAutocompleteItem }) => {\n let sourceEvent:any|null = _event;\n\n while (sourceEvent && sourceEvent.originalEvent) {\n sourceEvent = sourceEvent.originalEvent as any;\n }\n\n // Focus the given item, but only when we're using the keyboard.\n // With the mouse, hover shall suffice to avoid weird focus/hover combinations\n // e.g., https://community.openproject.com/wp/28197\n if (sourceEvent && sourceEvent.type === 'keydown') {\n this.queryResultsContainer\n .find(`#collapsible-menu-item-${ui.item.auto_id} .collapsible-menu--item-link`)\n .focus();\n }\n\n return false;\n },\n appendTo: '.collapsible-menu--results-container',\n classes: {\n 'ui-autocomplete': 'collapsible-menu--search-ul -inplace',\n 'ui-menu-divider': 'collapsible-menu--category-icon'\n },\n autoFocus: false, // Don't automatically select first entry since we 'open' the autocomplete on page load\n minLength: 0\n });\n }\n\n private defineJQueryQueryComplete() {\n let thisComponent = this;\n\n jQuery.widget('custom.querycomplete', jQuery.ui.autocomplete, {\n _create: function (this:any) {\n this._super();\n this.widget().menu('option', 'items', '.collapsible-menu--item');\n this._search('');\n },\n _renderItem: function (this:{}, ul:any, item:IAutocompleteItem) {\n const link = jQuery('
      ')\n .addClass('collapsible-menu--item-link')\n .attr('href', thisComponent.buildQueryItemUrl(item))\n .text(item.label);\n\n const li = jQuery('
    • ')\n .addClass(`ui-menu-item collapsible-menu--item`)\n .attr('id', `collapsible-menu-item-${item.auto_id}`)\n .attr('data-category', item.category || '')\n .data('ui-autocomplete-item', item) // Focus method of autocompleter needs this data for accessibility - if not set, it will throw errors\n .append(link)\n .appendTo(ul);\n\n thisComponent.setInitialHighlighting(li, item);\n\n return li;\n },\n _renderMenu: function (this:any, ul:any, items:IAutocompleteItem[]) {\n let currentCategory:QueryCategory;\n\n _.each(items, option => {\n // Check if item has same category as previous item and if not insert a new category label in the list\n if (option.category !== currentCategory) {\n currentCategory = option.category!;\n let label = thisComponent.labelFunction(currentCategory);\n\n ul.append(``);\n jQuery('
    • ')\n .addClass('ui-autocomplete--category collapsible-menu--category-toggle ellipsis')\n .attr('title', label)\n .attr('data-category', currentCategory)\n .text(label)\n .appendTo(ul);\n }\n this._renderItemData(ul, option);\n });\n\n\n // Scroll to selected element if search is empty\n if (thisComponent.searchInput.val() === '') {\n let selected = thisComponent.queryResultsContainer.find('.collapsible-menu--item.selected');\n if (selected.length > 0) {\n setTimeout(() => selected[0].scrollIntoView({ behavior: 'auto', block: 'center' }), 20);\n }\n }\n }\n });\n }\n\n // Set class 'selected' on initial rendering of the menu\n // Case 1: Wp menu is opened from somewhere else in the project -> Compare query params with url params and highlight selected\n // Case 2: Click on menu item 'Work Packages' (query 'All open' is opened on default) -> highlight 'All open'\n private setInitialHighlighting(currentLi:JQuery, item:IAutocompleteItem) {\n const params = this.getQueryParams(item);\n const currentId = this.$state.params.query_id;\n const currentProps = this.$state.params.query_props;\n let onWorkPackagesPage:boolean = this.$state.includes('work-packages');\n let onWorkPackagesReportPage:boolean = jQuery('body').hasClass('controller-work_packages/reports');\n\n // When the current ID is selected\n const currentIdSelected = params.query_id && (currentId || '').toString() === params.query_id.toString();\n\n // Case1: Static query props\n const matchesStaticQueryProps = !item.query && item.query_props && item.query_props === currentProps;\n\n // Case2: We're on the All open menu item\n const allOpen = onWorkPackagesPage && !currentId && !currentProps && item.identifier === 'all_open';\n\n // Case3: We're on the static summary page\n const onSummary = onWorkPackagesReportPage && item.identifier === 'summary';\n\n if (currentIdSelected || matchesStaticQueryProps || allOpen || onSummary) {\n currentLi.addClass('selected');\n }\n }\n\n private labelFunction(category:QueryCategory):string {\n switch (category) {\n case 'starred':\n return this.text.scope_starred;\n case 'public':\n return this.text.scope_global;\n case 'private':\n return this.text.scope_private;\n case 'default':\n return this.text.scope_default;\n default:\n return '';\n }\n }\n\n // Listens on all changes of queries (via an observable in the service), e.g. delete, create, rename, toggle starred\n // Update collection in autocompleter\n // Search again for the current value in input field to update the menu without loosing the current search results\n private updateMenuOnChanges() {\n this.states.changes.queries\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => this.loadQueries());\n }\n\n private expandCollapseCategory(category:string) {\n jQuery(`[data-category=\"${category}\"]`)\n // Don't hide the categories themselves (Regression #28584)\n .not('.ui-autocomplete--category')\n .toggleClass('-hidden');\n jQuery(`.collapsible-menu--category-icon[data-category=\"${category}\"]`).toggleClass('-collapsed');\n }\n\n // On click of a menu item, load requested query\n private loadQuery(item:IAutocompleteItem) {\n const params = this.getQueryParams(item);\n const opts = { reload: true };\n\n this.$state.go(\n 'work-packages.partitioned.list',\n params,\n opts\n );\n\n this.toggleService.closeWhenOnMobile();\n }\n\n private getQueryParams(item:IAutocompleteItem) {\n let val:{ query_id:string|null, query_props:string|null, projects?:string, projectPath?:string } = {\n query_id: item.query ? _.toString(item.query.id) : null,\n query_props: item.query ? null : item.query_props,\n };\n\n if (this.projectIdentifier) {\n val.projects = 'projects';\n val.projectPath = this.projectIdentifier;\n }\n\n return val;\n }\n\n private buildQueryItemUrl(item:IAutocompleteItem):string {\n // Static item (such as summary)\n if (item.static_link) {\n return item.static_link;\n }\n\n const params = this.getQueryParams(item);\n return this.$state.href('work-packages.partitioned.list', params);\n }\n\n private highlightSelected(item:IAutocompleteItem) {\n this.highlightBySelector(`#collapsible-menu-item-${item.auto_id}`);\n }\n\n private highlightBySelector(selector:string) {\n // Remove old selection\n this.queryResultsContainer.find(\".ui-menu-item\").removeClass('selected');\n //Find selected element in DOM and highlight it\n this.queryResultsContainer.find(selector).addClass('selected');\n }\n\n /**\n * When clicking an item with meta keys,\n * avoid its propagation.\n *\n */\n private addClickHandler() {\n this.queryResultsContainer\n .on('click keydown', '.ui-menu-item a', (evt:JQuery.TriggeredEvent) => {\n if (evt.type === 'keydown' && evt.which !== keyCodes.ENTER) {\n return true;\n }\n\n // Find the item from the clicked element\n const target = jQuery(evt.target);\n const item:IAutocompleteItem = target\n .closest('.collapsible-menu--item')\n .data('ui-autocomplete-item');\n\n // Either the link is clicked with a modifier, then always cancel any propagation\n const clickedWithModifier = evt.type === 'click' && LinkHandling.isClickedWithModifier(evt);\n\n // Or the item is only a static link, then cancel propagation\n const isStatic = !!item.static_link;\n\n if (clickedWithModifier || isStatic) {\n evt.stopImmediatePropagation();\n\n if (evt.type === 'keydown') {\n window.location.href = target.attr('href')!;\n }\n } else {\n // If neither clicked with modifier nor static\n // Then prevent the default link handling and load the query\n evt.preventDefault();\n this.loadQuery(item);\n this.highlightSelected(item);\n return false;\n }\n\n return true;\n })\n .on('click keydown', '.collapsible-menu--category-toggle', (evt:JQuery.TriggeredEvent) => {\n if (evt.type === 'keydown' && evt.which !== keyCodes.ENTER) {\n return true;\n }\n\n const target = jQuery(evt.target);\n const clickedCategory = target.data('category');\n\n if (clickedCategory) {\n this.expandCollapseCategory(clickedCategory);\n }\n\n // Remember all hidden catagories\n this.hiddenCategories = this.queryResultsContainer.find(\".ui-autocomplete--category.hidden\");\n\n evt.preventDefault();\n return false;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\nimport {ChangeDetectorRef, Component, ElementRef, Injector, Input, OnDestroy} from '@angular/core';\nimport {distinctUntilChanged} from 'rxjs/operators';\nimport {combineLatest} from 'rxjs';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {GlobalSearchService} from \"core-app/modules/global_search/services/global-search.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport const globalSearchTitleSelector = 'global-search-title';\n\n@Component({\n selector: 'global-search-title',\n templateUrl: './global-search-title.component.html'\n})\nexport class GlobalSearchTitleComponent extends UntilDestroyedMixin implements OnDestroy {\n @Input() public searchTerm:string;\n @Input() public project:string;\n @Input() public projectScope:string;\n @Input() public searchTitle:string;\n\n @InjectField() private currentProjectService:CurrentProjectService;\n\n public text:{ [key:string]:string } = {\n all_projects: this.I18n.t('js.global_search.title.all_projects'),\n project_and_subprojects: this.I18n.t('js.global_search.title.project_and_subprojects'),\n search_for: this.I18n.t('js.global_search.title.search_for'),\n in: this.I18n.t('js.label_in')\n };\n\n constructor(readonly elementRef:ElementRef,\n readonly cdRef:ChangeDetectorRef,\n readonly globalSearchService:GlobalSearchService,\n readonly I18n:I18nService,\n readonly injector:Injector) {\n super();\n }\n\n ngOnInit() {\n // Listen on changes of search input value and project scope\n combineLatest([\n this.globalSearchService.searchTerm$,\n this.globalSearchService.projectScope$\n ])\n .pipe(\n distinctUntilChanged(),\n this.untilDestroyed()\n )\n .subscribe(([newSearchTerm, newProjectScope]) => {\n this.searchTerm = newSearchTerm;\n this.project = this.projectText(newProjectScope);\n this.searchTitle = `${this.text.search_for} ${this.searchTerm} ${this.project === '' ? '' : this.text.in} ${this.project}`;\n\n this.cdRef.detectChanges();\n });\n }\n\n private projectText(scope:string):string {\n let currentProjectName = this.currentProjectService.name ? this.currentProjectService.name : '';\n\n switch (scope) {\n case 'all':\n return this.text.all_projects;\n break;\n case 'current_project':\n return currentProjectName;\n break;\n case '':\n return currentProjectName + ' ' + this.text.project_and_subprojects;\n break;\n default:\n return '';\n }\n }\n}\n","
      \n
      \n
      \n

      \n {{ text.search_for }}\n \"{{ searchTerm }}\"\n {{ project === '' ? '' : text.in }}\n {{ project }}\n

      \n
        \n
        \n
        \n
        \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, OnDestroy} from '@angular/core';\nimport {GlobalSearchService} from \"core-app/modules/global_search/services/global-search.service\";\nimport {Subscription} from \"rxjs\";\nimport {ScrollableTabsComponent} from \"core-app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component\";\n\nexport const globalSearchTabsSelector = 'global-search-tabs';\n\n@Component({\n selector: globalSearchTabsSelector,\n templateUrl: '/app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component.html'\n})\n\nexport class GlobalSearchTabsComponent extends ScrollableTabsComponent implements OnDestroy {\n private currentTabSub:Subscription;\n private tabsSub:Subscription;\n\n public classes:string[] = ['global-search--tabs', 'scrollable-tabs'];\n\n constructor(readonly globalSearchService:GlobalSearchService) {\n super();\n }\n\n ngOnInit() {\n this.currentTabSub = this.globalSearchService\n .currentTab$\n .subscribe((currentTab) => {\n this.currentTabId = currentTab;\n });\n\n this.tabsSub = this.globalSearchService\n .tabs$\n .subscribe((tabs) => {\n this.tabs = tabs;\n this.tabs.map((tab) => tab.path = '#');\n });\n }\n\n public clickTab(tab:string) {\n super.clickTab(tab);\n\n this.globalSearchService.currentTab = tab;\n this.globalSearchService.submitSearch();\n }\n\n ngOnDestroy():void {\n this.currentTabSub.unsubscribe();\n this.tabsSub.unsubscribe();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, OnInit} from '@angular/core';\nimport {MainMenuToggleService} from './main-menu-toggle.service';\nimport {distinctUntilChanged} from 'rxjs/operators';\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {DeviceService} from \"app/modules/common/browser/device.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport const mainMenuToggleSelector = 'main-menu-toggle';\n\n@Component({\n selector: mainMenuToggleSelector,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n
        \n \n \n \n
        \n `\n})\n\nexport class MainMenuToggleComponent extends UntilDestroyedMixin implements OnInit {\n toggleTitle:string = \"\";\n @InjectField() currentProject:CurrentProjectService;\n\n constructor(readonly toggleService:MainMenuToggleService,\n readonly cdRef:ChangeDetectorRef,\n readonly deviceService:DeviceService,\n readonly injector:Injector) {\n super();\n }\n\n ngOnInit() {\n this.toggleService.initializeMenu();\n\n this.toggleService.titleData$\n .pipe(\n distinctUntilChanged(),\n this.untilDestroyed()\n )\n .subscribe(setToggleTitle => {\n this.toggleTitle = setToggleTitle;\n this.cdRef.detectChanges();\n });\n }\n}\n\n","import {UserAutocompleterComponent} from \"core-app/modules/common/autocomplete/user-autocompleter.component\";\nimport {Observable} from \"rxjs\";\nimport {map} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {HttpClient, HttpParams} from \"@angular/common/http\";\nimport {Component} from \"@angular/core\";\nimport {URLParamsEncoder} from \"core-app/modules/hal/services/url-params-encoder\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\n\nexport const membersAutocompleterSelector = 'members-autocompleter';\n\n@Component({\n templateUrl: '/app/modules/common/autocomplete/user-autocompleter.component.html',\n selector: membersAutocompleterSelector\n})\nexport class MembersAutocompleterComponent extends UserAutocompleterComponent {\n @InjectField() http:HttpClient;\n @InjectField() pathHelper:PathHelperService;\n\n protected getAvailableUsers(url:string, searchTerm:any):Observable<{ [key:string]:string|null }[]> {\n return this.http\n .get(url,\n {\n params: new HttpParams({ encoder: new URLParamsEncoder(), fromObject: { q: searchTerm } }),\n responseType: 'json',\n headers: { 'Content-Type': 'application/json; charset=utf-8' }\n },\n )\n .pipe(\n map((res:any) => {\n return res.results.items.map((el:any) => {\n const href = /^\\d+$/.test(el.id.toString()) ? this.pathHelper.userPath(el.id) : null;\n return { name: el.name, id: el.id, href: href };\n });\n })\n );\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HttpClient, HttpErrorResponse, HttpHeaders} from \"@angular/common/http\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {FormGroup} from \"@angular/forms\";\nimport {input} from \"reactivestates\";\n\nexport interface EnterpriseTrialData {\n id?:string;\n company:string;\n first_name:string;\n last_name:string;\n email:string;\n domain:string;\n general_consent?:boolean;\n newsletter_consent?:boolean;\n}\n\n@Injectable()\nexport class EnterpriseTrialService {\n // user data needs to be sync in ee-active-trial.component.ts\n userData$ = input();\n\n public readonly baseUrlAugur:string;\n public readonly tokenVersion:string;\n\n public trialLink:string;\n public resendLink:string;\n\n public modalOpen = false;\n public confirmed:boolean;\n public cancelled = false;\n public status:'mailSubmitted'|'startTrial'|undefined;\n public error:HttpErrorResponse|undefined;\n public emailInvalid:boolean = false;\n public text = {\n invalid_email: this.I18n.t('js.admin.enterprise.trial.form.invalid_email'),\n taken_email: this.I18n.t('js.admin.enterprise.trial.form.taken_email'),\n taken_domain: this.I18n.t('js.admin.enterprise.trial.form.taken_domain'),\n };\n\n constructor(readonly I18n:I18nService,\n protected http:HttpClient,\n readonly pathHelper:PathHelperService,\n protected notificationsService:NotificationsService) {\n let gon = (window as any).gon;\n this.baseUrlAugur = gon.augur_url;\n this.tokenVersion = gon.token_version;\n\n if ((window as any).gon.ee_trial_key) {\n this.setMailSubmittedStatus();\n }\n }\n\n // send POST request with form object\n // receive an enterprise trial link to access a token\n public sendForm(form:FormGroup) {\n const request = { ...form.value, token_version: this.tokenVersion};\n this.http.post(this.baseUrlAugur + '/public/v1/trials', request)\n .toPromise()\n .then((enterpriseTrial:any) => {\n this.userData$.putValue(form.value);\n this.cancelled = false;\n\n this.trialLink = enterpriseTrial._links.self.href;\n this.saveTrialKey(this.trialLink);\n\n this.retryConfirmation();\n })\n .catch((error:HttpErrorResponse) => {\n // mail is invalid or user already created a trial\n if (error.status === 422 || error.status === 400) {\n this.error = error;\n } else {\n this.notificationsService.addWarning(error.error.description || I18n.t('js.error.internal'));\n }\n });\n }\n\n // get a token from the trial link if user confirmed mail\n public getToken() {\n // 2) GET /public/v1/trials/:id\n this.http\n .get(this.trialLink)\n .toPromise()\n .then(async (res:any) => {\n // show confirmed status and enable continue btn\n this.confirmed = true;\n\n // returns token if mail was confirmed\n // -> if token is new (token_retrieved: false) save token in backend\n if (!res.token_retrieved) {\n await this.saveToken(res.token);\n }\n })\n .catch((error:HttpErrorResponse) => {\n // returns error 422 while waiting of confirmation\n if (error.status === 422 && error.error.identifier === 'waiting_for_email_verification') {\n // get resend button link\n this.resendLink = error.error._links.resend.href;\n // save a key for the requested trial\n if (!this.status || this.cancelled) { // only do it once\n this.saveTrialKey(this.resendLink);\n }\n // open next modal window -> status waiting\n this.setMailSubmittedStatus();\n this.confirmed = false;\n } else if (_.get(error, 'error._type') === 'Error') {\n this.notificationsService.addError(error.error.message);\n } else {\n this.notificationsService.addError(error.error || I18n.t('js.error.internal'));\n }\n });\n }\n\n // save a part of the resend link in db\n // which allows to remember if a user has already requested a trial token\n // and to ask for the corresponding user data saved in Augur\n private saveTrialKey(resendlink:string) {\n // extract token from resend link\n let trialKey = resendlink.split('/')[6];\n return this.http.post(\n this.pathHelper.appBasePath + '/admin/enterprise/save_trial_key',\n { trial_key: trialKey },\n { withCredentials: true }\n )\n .toPromise()\n .catch((e:any) => {\n this.notificationsService.addError(e.error.message || e.message || e);\n });\n }\n\n // save received token in controller\n private saveToken(token:string) {\n return this.http.post(\n this.pathHelper.appBasePath + '/admin/enterprise',\n { enterprise_token: { encoded_token: token } },\n { withCredentials: true }\n )\n .toPromise()\n .then(() => {\n // load page if mail was confirmed and modal window is not open\n if (!this.modalOpen) {\n setTimeout(() => { // display confirmed status before reloading\n window.location.reload();\n }, 500);\n }\n })\n .catch((error:HttpErrorResponse) => {\n // Delete the trial key as the token could not be saved and thus something is wrong with the token.\n // Without this deletion, we run into an endless loop of an confirmed mail, but no saved token.\n this.http\n .delete(\n this.pathHelper.api.v3.apiV3Base + '/admin/enterprise/delete_trial_key',\n { withCredentials: true }\n )\n .toPromise();\n\n this.notificationsService.addError(error.error.description || I18n.t('js.error.internal'));\n });\n }\n\n // retry request while waiting for mail confirmation\n public retryConfirmation(delay:number = 5000, retries:number = 60) {\n if (this.cancelled || this.confirmed) {\n return;\n } else if (retries === 0) {\n this.cancelled = true;\n } else {\n this.getToken();\n setTimeout(() => {\n this.retryConfirmation(delay, retries - 1);\n }, delay);\n }\n }\n\n public setStartTrialStatus() {\n this.status = 'startTrial';\n }\n\n public setMailSubmittedStatus() {\n this.status = 'mailSubmitted';\n }\n\n public get trialStarted():boolean {\n return this.status === 'startTrial';\n }\n\n public get mailSubmitted():boolean {\n return this.status === 'mailSubmitted';\n }\n\n public get domainTaken():boolean {\n return this.error ? this.error.error.identifier === 'domain_taken' : false;\n }\n\n public get emailTaken():boolean {\n return this.error ? this.error.error.identifier === 'user_already_created_trial' : false;\n }\n\n public get emailError():boolean {\n if (this.emailInvalid) {\n return true;\n } else if (this.error) {\n return this.emailTaken;\n } else {\n return false;\n }\n }\n\n public get errorMsg() {\n let error:string = '';\n if (this.emailInvalid) {\n error = this.text.invalid_email;\n } else if (this.domainTaken) {\n error = this.text.taken_domain;\n } else if (this.emailTaken) {\n error = this.text.taken_email;\n }\n\n return error;\n }\n}\n","export namespace I18nHelpers {\n\n export interface LocalizedLinkMap {\n [key:string]:string;\n\n en:string;\n }\n\n /**\n * Return the matching link for the current locale\n *\n * @param map A hash of locale => URL to use\n */\n export function localizeLink(map:LocalizedLinkMap) {\n const locale = I18n.locale;\n\n return map[locale] || map.en;\n }\n}\n","
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        {{ eeTrialService.errorMsg }}
        \n
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        {{ eeTrialService.errorMsg }}
        \n
        \n
        \n
        \n \n
        \n
        \n
        \n
        \n \n
        \n
        \n
        ","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef} from \"@angular/core\";\nimport {FormBuilder, Validators} from \"@angular/forms\";\nimport {I18nService} from \"app/modules/common/i18n/i18n.service\";\nimport {EnterpriseTrialData, EnterpriseTrialService} from \"core-components/enterprise/enterprise-trial.service\";\nimport {CurrentUserService} from \"core-components/user/current-user.service\";\nimport {I18nHelpers} from \"core-app/helpers/i18n/localized-link\";\n\nconst newsletterURL = 'https://www.openproject.com/newsletter/';\n\n@Component({\n selector: 'enterprise-trial-form',\n templateUrl: './ee-trial-form.component.html',\n styleUrls: ['./ee-trial-form.component.sass']\n})\nexport class EETrialFormComponent {\n // Retain used values\n userData:Partial = this.eeTrialService.userData$.getValueOr({});\n\n trialForm = this.formBuilder.group({\n company: [this.userData.company, Validators.required],\n first_name: [this.userData.first_name, Validators.required],\n last_name: [this.userData.last_name, Validators.required],\n email: ['', [Validators.required, Validators.email]],\n domain: [this.userData.domain || window.location.host, Validators.required],\n general_consent: [null, Validators.required],\n newsletter_consent: null,\n language: this.currentUserService.language\n });\n\n public text = {\n general_consent: this.I18n.t('js.admin.enterprise.trial.form.general_consent', {\n link_terms: I18nHelpers.localizeLink({\n en: 'https://www.openproject.com/terms-of-service/',\n de: 'https://www.openproject.org/de/nutzungsbedingungen/',\n }),\n link_privacy: I18nHelpers.localizeLink({\n en: 'https://www.openproject.org/data-privacy-and-security/',\n de: 'https://www.openproject.org/de/datenschutz/'\n })\n }),\n label_test_ee: this.I18n.t('js.admin.enterprise.trial.form.test_ee'),\n label_company: this.I18n.t('js.admin.enterprise.trial.form.label_company'),\n label_first_name: this.I18n.t('js.admin.enterprise.trial.form.label_first_name'),\n label_last_name: this.I18n.t('js.admin.enterprise.trial.form.label_last_name'),\n label_email: this.I18n.t('js.admin.enterprise.trial.form.label_email'),\n label_domain: this.I18n.t('js.admin.enterprise.trial.form.label_domain'),\n privacy_policy: this.I18n.t('js.admin.enterprise.trial.form.privacy_policy'),\n receive_newsletter: this.I18n.t('js.admin.enterprise.trial.form.receive_newsletter', { link: newsletterURL }),\n terms_of_service: this.I18n.t('js.admin.enterprise.trial.form.terms_of_service')\n };\n\n constructor(readonly elementRef:ElementRef,\n readonly I18n:I18nService,\n private formBuilder:FormBuilder,\n readonly currentUserService:CurrentUserService,\n public eeTrialService:EnterpriseTrialService) {\n\n }\n\n // checks if mail is valid after input field was edited by the user\n // displays message for user\n public checkMailField() {\n if (this.trialForm.value.email !== '' && this.trialForm.controls.email.errors) {\n this.eeTrialService.emailInvalid = true;\n } else {\n this.eeTrialService.emailInvalid = false;\n this.eeTrialService.error = undefined;\n }\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {I18nService} from \"app/modules/common/i18n/i18n.service\";\n\nexport class EEActiveTrialBase extends UntilDestroyedMixin {\n public text = {\n label_email: this.I18n.t('js.admin.enterprise.trial.form.label_email'),\n label_expires_at: this.I18n.t('js.admin.enterprise.trial.form.label_expires_at'),\n label_maximum_users: this.I18n.t('js.admin.enterprise.trial.form.label_maximum_users'),\n label_company: this.I18n.t('js.admin.enterprise.trial.form.label_company'),\n label_domain: this.I18n.t('js.admin.enterprise.trial.form.label_domain'),\n label_starts_at: this.I18n.t('js.admin.enterprise.trial.form.label_starts_at'),\n label_subscriber: this.I18n.t('js.admin.enterprise.trial.form.label_subscriber')\n };\n\n constructor(readonly I18n:I18nService) {\n super();\n }\n}\n","
        \n
        \n
        \n
        \n
        \n
        \n \n
        \n
        \n
        \n
        \n
        \n \n
        \n
        \n
        \n
        \n
        \n \n
        \n
        \n
        \n
        \n
        \n \n
        \n
        \n
        \n
        \n
        \n \n
        \n
        \n
        \n
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        \n \n
        \n
        \n
        \n
        \n
        ","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectorRef, Component, ElementRef, OnInit} from \"@angular/core\";\nimport {distinctUntilChanged} from \"rxjs/operators\";\nimport {I18nService} from \"app/modules/common/i18n/i18n.service\";\nimport {EnterpriseTrialService} from \"app/components/enterprise/enterprise-trial.service\";\nimport {HttpClient, HttpErrorResponse} from \"@angular/common/http\";\nimport {EEActiveTrialBase} from \"core-components/enterprise/enterprise-active-trial/ee-active-trial.base\";\nimport {GonService} from \"core-app/modules/common/gon/gon.service\";\n\n@Component({\n selector: 'enterprise-active-trial',\n templateUrl: './ee-active-trial.component.html',\n styleUrls: ['./ee-active-trial.component.sass']\n})\nexport class EEActiveTrialComponent extends EEActiveTrialBase implements OnInit {\n public subscriber:string;\n public email:string;\n public company:string;\n public domain:string;\n public userCount:string;\n public startsAt:string;\n public expiresAt:string;\n\n constructor(readonly elementRef:ElementRef,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService,\n readonly http:HttpClient,\n readonly Gon:GonService,\n public eeTrialService:EnterpriseTrialService) {\n super(I18n);\n }\n\n ngOnInit() {\n if (!this.subscriber) {\n this.eeTrialService.userData$\n .values$()\n .pipe(\n distinctUntilChanged(),\n this.untilDestroyed()\n )\n .subscribe(userForm => {\n this.formatUserData(userForm);\n this.cdRef.detectChanges();\n });\n\n this.initialize();\n }\n }\n\n private initialize():void {\n let eeTrialKey = this.Gon.get('ee_trial_key') as any;\n\n if (eeTrialKey && !this.eeTrialService.userData$.hasValue()) {\n // after reload: get data from Augur using the trial key saved in gon\n this.eeTrialService.trialLink = this.eeTrialService.baseUrlAugur + '/public/v1/trials/' + eeTrialKey.value;\n this.getUserDataFromAugur();\n }\n }\n\n // use the trial key saved in the db\n // to get the user data from Augur\n private getUserDataFromAugur() {\n this.http\n .get(this.eeTrialService.trialLink + '/details')\n .toPromise()\n .then((userForm:any) => {\n this.eeTrialService.userData$.putValue(userForm);\n this.eeTrialService.retryConfirmation();\n })\n .catch((error:HttpErrorResponse) => {\n // Check whether the mail has been confirmed by now\n this.eeTrialService.getToken();\n });\n }\n\n private formatUserData(userForm:any) {\n this.subscriber = userForm.first_name + ' ' + userForm.last_name;\n this.email = userForm.email;\n this.company = userForm.company;\n this.domain = userForm.domain;\n }\n\n}\n","\n\n

        {{ text.confirmation_info(created, email) }}

        \n

        \n {{ text.status_label }} \n \n {{ text.status_waiting }}\n\n {{ text.resend }}\n

        {{ text.session_timeout }}

        \n \n\n \n {{ text.status_confirmed }}\n \n

        \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef, OnInit} from \"@angular/core\";\nimport {I18nService} from \"app/modules/common/i18n/i18n.service\";\nimport {EnterpriseTrialService} from \"app/components/enterprise/enterprise-trial.service\";\nimport {HttpClient} from \"@angular/common/http\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {distinctUntilChanged} from \"rxjs/operators\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\n\n@Component({\n selector: 'enterprise-trial-waiting',\n templateUrl: './ee-trial-waiting.component.html',\n styleUrls: ['./ee-trial-waiting.component.sass']\n})\nexport class EETrialWaitingComponent implements OnInit {\n created = this.timezoneService.formattedDate(new Date().toString());\n email:string = '';\n\n public text = {\n confirmation_info: (date:string, email:string) => this.I18n.t('js.admin.enterprise.trial.confirmation_info',{\n date: date,\n email: email\n }),\n resend: this.I18n.t('js.admin.enterprise.trial.resend_link'),\n resend_success: this.I18n.t('js.admin.enterprise.trial.resend_success'),\n resend_warning: this.I18n.t('js.admin.enterprise.trial.resend_warning'),\n session_timeout: this.I18n.t('js.admin.enterprise.trial.session_timeout'),\n status_confirmed: this.I18n.t('js.admin.enterprise.trial.status_confirmed'),\n status_label: this.I18n.t('js.admin.enterprise.trial.status_label'),\n status_waiting: this.I18n.t('js.admin.enterprise.trial.status_waiting')\n };\n\n constructor(readonly elementRef:ElementRef,\n readonly I18n:I18nService,\n protected http:HttpClient,\n protected notificationsService:NotificationsService,\n public eeTrialService:EnterpriseTrialService,\n readonly timezoneService:TimezoneService) {\n }\n\n ngOnInit() {\n let eeTrialKey = (window as any).gon.ee_trial_key;\n if (eeTrialKey) {\n let savedDateStr = eeTrialKey.created.split(' ')[0];\n this.created = this.timezoneService.formattedDate(savedDateStr);\n }\n\n this.eeTrialService.userData$\n .values$()\n .pipe(\n distinctUntilChanged(),\n )\n .subscribe(userForm => {\n this.email = userForm.email;\n });\n }\n\n // resend mail if resend link has been clicked\n public resendMail() {\n this.eeTrialService.cancelled = false;\n this.http.post(this.eeTrialService.resendLink, {})\n .toPromise()\n .then(() => {\n this.notificationsService.addSuccess(this.text.resend_success);\n this.eeTrialService.retryConfirmation();\n })\n .catch(() => {\n if (this.eeTrialService.trialLink) {\n // Check whether the mail has been confirmed by now\n this.eeTrialService.getToken();\n } else {\n this.notificationsService.addError(this.text.resend_warning);\n }\n });\n }\n}\n\n","
        \n
        \n
        \n

        \n \n \n \n \n
        \n\n
        \n \n
        \n \n
        \n \n
        \n \n
        \n \n
        \n
        \n
        \n {{ text.quick_overview }}\n
        \n
        \n \n
        \n
        \n
        \n
        \n\n
        \n
        \n \n \n
        \n \n \n \n \n
        \n\n
        \n
        ","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {AfterViewInit, ChangeDetectorRef, Component, ElementRef, Inject, Input, ViewChild} from \"@angular/core\";\nimport {DomSanitizer, SafeResourceUrl} from \"@angular/platform-browser\";\nimport {FormControl, FormGroup} from \"@angular/forms\";\nimport {OpModalComponent} from \"app/components/op-modals/op-modal.component\";\nimport {OpModalLocalsToken} from \"app/components/op-modals/op-modal.service\";\nimport {OpModalLocalsMap} from \"app/components/op-modals/op-modal.types\";\nimport {I18nService} from \"app/modules/common/i18n/i18n.service\";\nimport {EETrialFormComponent} from \"core-components/enterprise/enterprise-modal/enterprise-trial-form/ee-trial-form.component\";\nimport {EnterpriseTrialService} from \"core-components/enterprise/enterprise-trial.service\";\n\nexport const eeOnboardingVideoURL = 'https://www.youtube.com/embed/zLMSydhFSkw?autoplay=1';\n\n@Component({\n selector: 'enterprise-trial-modal',\n templateUrl: './enterprise-trial.modal.html',\n styleUrls: ['./enterprise-trial.modal.sass']\n})\nexport class EnterpriseTrialModal extends OpModalComponent implements AfterViewInit {\n @ViewChild(EETrialFormComponent, { static: false }) formComponent:EETrialFormComponent;\n @Input() public opReferrer:string;\n\n public trialForm:FormGroup;\n\n // modal configuration\n public showClose = true;\n public closeOnEscape = false;\n public closeOnOutsideClick = false;\n\n public trustedEEVideoURL:SafeResourceUrl;\n public text = {\n button_submit: this.I18n.t('js.modals.button_submit'),\n button_cancel: this.I18n.t('js.modals.button_cancel'),\n button_continue: this.I18n.t('js.button_continue'),\n close_popup: this.I18n.t('js.close_popup_title'),\n heading_confirmation: this.I18n.t('js.admin.enterprise.trial.confirmation'),\n heading_next_steps: this.I18n.t('js.admin.enterprise.trial.next_steps'),\n heading_test_ee: this.I18n.t('js.admin.enterprise.trial.test_ee'),\n quick_overview: this.I18n.t('js.admin.enterprise.trial.quick_overview')\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService,\n readonly domSanitizer:DomSanitizer,\n public eeTrialService:EnterpriseTrialService) {\n super(locals, cdRef, elementRef);\n this.trustedEEVideoURL = this.trustedURL(eeOnboardingVideoURL);\n }\n\n ngAfterViewInit() {\n this.trialForm = this.formComponent.trialForm;\n }\n\n // checks if form is valid and submits it\n public onSubmit() {\n if (this.trialForm.valid) {\n this.trialForm.addControl('_type', new FormControl('enterprise-trial'));\n this.eeTrialService.sendForm(this.trialForm);\n }\n }\n\n public startEnterpriseTrial() {\n // open onboarding modal screen\n this.eeTrialService.setStartTrialStatus();\n }\n\n public headerText() {\n if (this.eeTrialService.mailSubmitted) {\n return this.text.heading_confirmation;\n } else if (this.eeTrialService.trialStarted) {\n return this.text.heading_next_steps;\n } else {\n return this.text.heading_test_ee;\n }\n }\n\n public closeModal(event:any) {\n this.closeMe(event);\n // refresh page to show enterprise trial\n if (this.eeTrialService.trialStarted || this.eeTrialService.confirmed) {\n window.location.reload();\n }\n this.eeTrialService.modalOpen = false;\n }\n\n public trustedURL(url:string) {\n return this.domSanitizer.bypassSecurityTrustResourceUrl(url);\n }\n\n public openWindow():number {\n if (!this.eeTrialService.status || this.eeTrialService.cancelled) {\n return 1;\n } else if (this.eeTrialService.mailSubmitted && !this.eeTrialService.cancelled) {\n return 2;\n } else {\n return 3;\n }\n }\n}\n\n","
        \n

        {{ text.enterprise_edition }}

        \n

        {{ text.confidence }}

        \n

        \n {{ text.become_hero }}
        \n {{ text.you_contribute }}\n

        \n \n
        \n\n\n \n

        {{ text.email_not_received }}\n {{ text.try_another_email }}\n

        \n
        \n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Injector} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {EnterpriseTrialModal} from \"core-components/enterprise/enterprise-modal/enterprise-trial.modal\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {EnterpriseTrialService} from \"core-components/enterprise/enterprise-trial.service\";\n\nexport const enterpriseBaseSelector = 'enterprise-base';\n\n@Component({\n selector: enterpriseBaseSelector,\n templateUrl: './enterprise-base.component.html',\n styleUrls: ['./enterprise-base.component.sass']\n})\nexport class EnterpriseBaseComponent {\n public text = {\n button_trial: this.I18n.t('js.admin.enterprise.upsale.button_start_trial'),\n button_book: this.I18n.t('js.admin.enterprise.upsale.button_book_now'),\n link_quote: this.I18n.t('js.admin.enterprise.upsale.link_quote'),\n become_hero: this.I18n.t('js.admin.enterprise.upsale.become_hero'),\n you_contribute: this.I18n.t('js.admin.enterprise.upsale.you_contribute'),\n email_not_received: this.I18n.t('js.admin.enterprise.trial.email_not_received'),\n enterprise_edition: this.I18n.t('js.admin.enterprise.upsale.text'),\n confidence: this.I18n.t('js.admin.enterprise.upsale.confidence'),\n try_another_email: this.I18n.t('js.admin.enterprise.trial.try_another_email')\n };\n\n constructor(protected I18n:I18nService,\n protected opModalService:OpModalService,\n readonly injector:Injector,\n public eeTrialService:EnterpriseTrialService) {\n }\n\n public openTrialModal() {\n // cancel request and open first modal window\n this.eeTrialService.cancelled = true;\n this.eeTrialService.modalOpen = true;\n this.opModalService.show(EnterpriseTrialModal, this.injector);\n }\n\n public get noTrialRequested() {\n return this.eeTrialService.status === undefined;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, ElementRef} from \"@angular/core\";\nimport {I18nService} from \"app/modules/common/i18n/i18n.service\";\nimport {EEActiveTrialBase} from \"core-components/enterprise/enterprise-active-trial/ee-active-trial.base\";\n\nexport const enterpriseActiveSavedTrialSelector = 'enterprise-active-saved-trial';\n\n@Component({\n selector: enterpriseActiveSavedTrialSelector,\n templateUrl: './ee-active-trial.component.html',\n styleUrls: ['./ee-active-trial.component.sass']\n})\nexport class EEActiveSavedTrialComponent extends EEActiveTrialBase {\n public subscriber = this.elementRef.nativeElement.dataset['subscriber'];\n public email = this.elementRef.nativeElement.dataset['email'];\n public company = this.elementRef.nativeElement.dataset['company'];\n public domain = this.elementRef.nativeElement.dataset['domain'];\n public userCount = this.elementRef.nativeElement.dataset['userCount'];\n public startsAt = this.elementRef.nativeElement.dataset['startsAt'];\n public expiresAt = this.elementRef.nativeElement.dataset['expiresAt'];\n\n constructor(readonly elementRef:ElementRef,\n readonly I18n:I18nService) {\n super(I18n);\n }\n}\n","import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Injector, OnInit} from \"@angular/core\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {TimeEntryEditService} from \"core-app/modules/time_entries/edit/edit.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\n\nexport const triggerActionsEntryComponentSelector = 'time-entry--trigger-actions-entry';\n\n@Component({\n selector: triggerActionsEntryComponentSelector,\n template: `\n \n \n \n \n \n \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService,\n TimeEntryEditService\n ]\n})\nexport class TriggerActionsEntryComponent {\n @InjectField() readonly timeEntryEditService:TimeEntryEditService;\n @InjectField() readonly apiv3Service:APIV3Service;\n @InjectField() readonly notificationsService:NotificationsService;\n @InjectField() readonly elementRef:ElementRef;\n @InjectField() i18n!:I18nService;\n @InjectField() readonly cdRef:ChangeDetectorRef;\n\n public text = {\n edit: this.i18n.t('js.button_edit'),\n delete: this.i18n.t('js.button_delete'),\n error: this.i18n.t('js.error.internal'),\n areYouSure: this.i18n.t('js.text_are_you_sure')\n };\n\n constructor(readonly injector:Injector) {\n }\n\n editTimeEntry() {\n this.loadEntry()\n .then(entry => {\n this.timeEntryEditService\n .edit(entry)\n .then(() => {\n window.location.reload();\n })\n .catch(() => {\n // User canceled the modal\n });\n });\n }\n\n deleteTimeEntry() {\n if (!window.confirm(this.text.areYouSure)) {\n return;\n }\n\n this.loadEntry()\n .then(entry => {\n this\n .apiv3Service\n .time_entries\n .id(entry)\n .delete()\n .subscribe(\n () => window.location.reload(),\n error => this.notificationsService.addError(error || this.text.error)\n );\n });\n }\n\n protected loadEntry():Promise {\n let timeEntryId = this.elementRef.nativeElement.dataset['entry'];\n\n return this\n .apiv3Service\n .time_entries\n .id(timeEntryId)\n .get()\n .toPromise();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++ Ng1FieldControlsWrapper,\n\nimport {Injectable} from \"@angular/core\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {NEVER, Observable, throwError} from \"rxjs\";\nimport {map, take, tap} from \"rxjs/operators\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {multiInput} from \"reactivestates\";\nimport {TransitionService} from \"@uirouter/core\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\n\nexport type SupportedAttributeModels = 'project'|'workPackage';\n\n@Injectable({ providedIn: \"root\" })\nexport class AttributeModelLoaderService {\n\n text = {\n not_found: this.I18n.t('js.editor.macro.attribute_reference.not_found')\n };\n\n // Cache the required model/id values because\n // we may need to expensively filter for them\n private cache$ = multiInput();\n\n constructor(readonly apiV3Service:APIV3Service,\n readonly transitions:TransitionService,\n readonly currentProject:CurrentProjectService,\n readonly I18n:I18nService) {\n\n // Clear cached values whenever leaving the page\n transitions.onStart({}, () => {\n this.cache$.clear();\n return true;\n });\n }\n\n /**\n * Require a given model with an id reference to be loaded.\n * This might be a singular resource identified by an actual integer ID or\n * another (e.g., work package subject) reference.\n *\n * @param model\n * @param id\n */\n require(model:SupportedAttributeModels, id:string):Promise {\n const identifier = `${model}-${id}`;\n const state = this.cache$.get(identifier);\n\n if (state.isPristine()) {\n const promise = this.load(model, id).toPromise();\n state.clearAndPutFromPromise(promise);\n\n return promise;\n }\n\n return state\n .values$()\n .pipe(\n take(1),\n tap(val => console.log(\"VAL \" + val), err => console.error('ERR ' + err))\n )\n .toPromise();\n }\n\n private load(model:SupportedAttributeModels, id?:string|undefined|null):Observable {\n switch (model) {\n case 'workPackage':\n return this.loadWorkPackage(id);\n case 'project':\n return this.loadProject(id);\n default:\n return NEVER;\n }\n }\n\n private loadProject(id:string|undefined|null) {\n id = id || this.currentProject.id;\n\n if (!id) {\n return throwError(this.text.not_found);\n }\n\n return this\n .apiV3Service\n .projects\n .id(id)\n .get()\n .pipe(\n take(1)\n );\n }\n\n private loadWorkPackage(id?:string|undefined|null) {\n if (!id) {\n return throwError(this.text.not_found);\n }\n\n // Return global reference to the subject\n if (/^[1-9]\\d*$/.test(id)) {\n return this\n .apiV3Service\n .work_packages\n .id(id)\n .get()\n .pipe(\n take(1)\n );\n }\n\n // Otherwise, look for subject IN the current project (if we're in project context)\n return this\n .apiV3Service\n .withOptionalProject(this.currentProject.id)\n .work_packages\n .filterBySubjectOrId(id, false, { pageSize: '1' })\n .get()\n .pipe(\n take(1),\n map(collection => collection.elements[0] || null)\n );\n }\n}\n","import {ChangeDetectionStrategy, Component, ElementRef, Injector, Input, OnInit, ViewChild} from '@angular/core';\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {Constructor} from \"@angular/cdk/table\";\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\n@Component({\n selector: 'display-field',\n template: '',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DisplayFieldComponent implements OnInit {\n @Input() resource:HalResource;\n @Input() fieldName:string;\n @Input() displayClass?:Constructor;\n\n @Input() containerType:'table'|'single-view'|'timeline' = 'table';\n @Input() displayFieldOptions:{[key:string]:unknown} = {};\n\n @ViewChild('displayFieldContainer') container:ElementRef;\n\n constructor(private injector:Injector,\n private displayFieldService:DisplayFieldService,\n private schemaCache:SchemaCacheService) {\n }\n\n ngOnInit() {\n this.schemaCache\n .ensureLoaded(this.resource)\n .then(schema => {\n this.render(schema[this.fieldName]);\n });\n }\n\n render(fieldSchema:IFieldSchema) {\n const field = this.getDisplayFieldInstance(fieldSchema);\n\n const container = this.container.nativeElement;\n container.hidden = false;\n\n // Default the field to a placeholder when rendering\n if (field.isEmpty()) {\n container.textContent = '-';\n } else {\n field.render(container, field.valueString);\n }\n }\n\n private getDisplayFieldInstance(fieldSchema:IFieldSchema) {\n if (this.displayClass) {\n let instance = new this.displayClass(this.fieldName, this.displayFieldContext);\n instance.apply(this.resource, fieldSchema);\n return instance;\n }\n\n return this.displayFieldService.getField(\n this.resource,\n this.fieldName,\n fieldSchema,\n this.displayFieldContext\n );\n }\n\n private get displayFieldContext() {\n return { injector: this.injector, container: this.containerType, options: this.displayFieldOptions }\n }\n}\n","\n \n \n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++ Ng1FieldControlsWrapper,\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostBinding,\n Injector,\n ViewChild\n} from \"@angular/core\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {NEVER, Observable} from \"rxjs\";\nimport {filter, map, take, tap} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n AttributeModelLoaderService,\n SupportedAttributeModels\n} from \"core-app/modules/fields/macros/attribute-model-loader.service\";\n\nexport const attributeValueMacro = 'macro.macro--attribute-value';\n\n@Component({\n selector: attributeValueMacro,\n templateUrl: './attribute-value-macro.html',\n styleUrls: ['./attribute-macro.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class AttributeValueMacroComponent {\n @ViewChild('displayContainer') private displayContainer:ElementRef;\n\n // Whether the value could not be loaded\n error:string|null = null;\n\n text = {\n help: this.I18n.t('js.editor.macro.attribute_reference.macro_help_tooltip'),\n placeholder: this.I18n.t('js.placeholders.default'),\n not_found: this.I18n.t('js.editor.macro.attribute_reference.not_found'),\n invalid_attribute: (attr:string) =>\n this.I18n.t('js.editor.macro.attribute_reference.invalid_attribute', { name: attr }),\n };\n\n @HostBinding('title') hostTitle = this.text.help;\n\n resource:HalResource;\n fieldName:string;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly resourceLoader:AttributeModelLoaderService,\n readonly schemaCache:SchemaCacheService,\n readonly displayField:DisplayFieldService,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef) {\n\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement as HTMLElement;\n const model:SupportedAttributeModels = element.dataset.model as any;\n const id:string = element.dataset.id!;\n const attributeName:string = element.dataset.attribute!;\n\n this.loadAndRender(model, id, attributeName);\n }\n\n private async loadAndRender(model:SupportedAttributeModels, id:string, attributeName:string) {\n let resource:HalResource|null;\n\n try {\n resource = await this.resourceLoader.require(model, id);\n } catch (e) {\n console.error(\"Failed to render macro \" + e);\n return this.markError(this.text.not_found);\n }\n\n if (!resource) {\n this.markError(this.text.not_found);\n return;\n }\n\n const schema = await this.schemaCache.ensureLoaded(resource);\n const attribute = schema.attributeFromLocalizedName(attributeName) || attributeName;\n const fieldSchema = schema[attribute] as IFieldSchema|undefined;\n\n if (fieldSchema) {\n this.resource = resource;\n this.fieldName = attribute;\n } else {\n this.markError(this.text.invalid_attribute(attributeName));\n }\n\n this.cdRef.detectChanges();\n }\n\n markError(message:string) {\n this.error = this.I18n.t('js.editor.macro.error', { message: message });\n this.cdRef.detectChanges();\n }\n}\n","export namespace StringHelpers {\n\n /**\n * Capitalize\n * @param value\n */\n export function capitalize(value:string):string {\n return value.charAt(0).toUpperCase() + value.slice(1);\n }\n}","\n \n \n \n\n\n\n \n \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++ Ng1FieldControlsWrapper,\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostBinding,\n Injector,\n ViewChild\n} from \"@angular/core\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {NEVER, Observable} from \"rxjs\";\nimport {filter, map, take, tap} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n AttributeModelLoaderService,\n SupportedAttributeModels\n} from \"core-app/modules/fields/macros/attribute-model-loader.service\";\nimport {StringHelpers} from \"core-app/helpers/string-helpers\";\n\nexport const attributeLabelMacro = 'macro.macro--attribute-label';\n\n@Component({\n selector: attributeLabelMacro,\n templateUrl: './attribute-label-macro.html',\n styleUrls: ['./attribute-macro.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class AttributeLabelMacroComponent {\n\n // Whether the value could not be loaded\n error:string|null = null;\n\n text = {\n help: this.I18n.t('js.editor.macro.attribute_reference.macro_help_tooltip'),\n not_found: this.I18n.t('js.editor.macro.attribute_reference.not_found'),\n invalid_attribute: (attr:string) =>\n this.I18n.t('js.editor.macro.attribute_reference.invalid_attribute', { name: attr }),\n };\n\n @HostBinding('title') hostTitle = this.text.help;\n\n // The loaded resource, required for help text\n resource:HalResource|null = null;\n // The scope to load for attribute help text\n attributeScope:string;\n // The attribute name, normalized from schema\n attribute:string;\n // The label to render\n label:string;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly resourceLoader:AttributeModelLoaderService,\n readonly schemaCache:SchemaCacheService,\n readonly displayField:DisplayFieldService,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef) {\n\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement as HTMLElement;\n const model:SupportedAttributeModels = element.dataset.model as any;\n const id:string = element.dataset.id!;\n const attributeName:string = element.dataset.attribute!;\n this.attributeScope = StringHelpers.capitalize(model);\n\n this.loadResourceAttribute(model, id, attributeName);\n }\n\n private async loadResourceAttribute(model:SupportedAttributeModels, id:string, attributeName:string) {\n let resource:HalResource|null;\n\n try {\n this.resource = resource = await this.resourceLoader.require(model, id);\n } catch (e) {\n console.error(\"Failed to render macro \" + e);\n return this.markError(this.text.not_found);\n }\n\n if (!resource) {\n this.markError(this.text.not_found);\n return;\n }\n\n const schema = await this.schemaCache.ensureLoaded(resource);\n this.attribute = schema.attributeFromLocalizedName(attributeName) || attributeName;\n this.label = schema[this.attribute]?.name;\n\n if (!this.label) {\n this.markError(this.text.invalid_attribute(attributeName));\n }\n\n this.cdRef.detectChanges();\n }\n\n markError(message:string) {\n this.error = this.I18n.t('js.editor.macro.error', { message: message });\n this.cdRef.detectChanges();\n }\n}\n","\n \n \n \n \n \n #{{workPackage.id}}:\n \n \n \n \n (\n \n \n )\n \n\n\n \n \n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++ Ng1FieldControlsWrapper,\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, HostBinding, Injector} from \"@angular/core\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {tap} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {DateDisplayField} from \"core-app/modules/fields/display/field-types/date-display-field.module\";\nimport {CombinedDateDisplayField} from \"core-app/modules/fields/display/field-types/combined-date-display.field\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\n\nexport const quickInfoMacroSelector = 'macro.macro--wp-quickinfo';\n\n@Component({\n selector: quickInfoMacroSelector,\n templateUrl: './work-package-quickinfo-macro.html',\n styleUrls: ['./work-package-quickinfo-macro.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class WorkPackageQuickinfoMacroComponent {\n // Whether the value could not be loaded\n error:string|null = null;\n\n text = {\n not_found: this.I18n.t('js.editor.macro.attribute_reference.not_found'),\n help: this.I18n.t('js.editor.macro.attribute_reference.macro_help_tooltip')\n };\n\n @HostBinding('title') hostTitle = this.text.help;\n\n /** Work package to be shown */\n workPackage$:Observable;\n dateDisplayField = CombinedDateDisplayField;\n workPackageLink:string;\n detailed:boolean = false;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly apiV3Service:APIV3Service,\n readonly schemaCache:SchemaCacheService,\n readonly displayField:DisplayFieldService,\n readonly pathHelper:PathHelperService,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef) {\n\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement as HTMLElement;\n const id:string = element.dataset.id!;\n this.detailed = element.dataset.detailed === 'true';\n this.workPackageLink = this.pathHelper.workPackagePath(id);\n\n this.workPackage$ = this\n .apiV3Service\n .work_packages\n .id(id)\n .get()\n .pipe(\n tap({ error: (e) => this.markError(this.text.not_found) })\n );\n }\n\n markError(message:string) {\n console.error(\"Failed to render macro \" + message);\n this.error = this.I18n.t('js.editor.macro.error', { message: message });\n this.cdRef.detectChanges();\n }\n}\n","import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ExternalQueryConfigurationService} from \"core-components/wp-table/external-configuration/external-query-configuration.service\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\n\nexport const editableQueryPropsSelector = 'editable-query-props';\n\n@Component({\n selector: editableQueryPropsSelector,\n templateUrl: './editable-query-props.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class EditableQueryPropsComponent implements OnInit {\n id:string|null;\n name:string|null;\n urlParams:boolean = false;\n\n queryProps:string;\n\n text = {\n edit_query: this.I18n.t('js.admin.type_form.edit_query')\n };\n\n constructor(private elementRef:ElementRef,\n private I18n:I18nService,\n private cdRef:ChangeDetectorRef,\n private urlParamsHelper:UrlParamsHelperService,\n private externalQuery:ExternalQueryConfigurationService) {\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement;\n this.id = element.dataset.id;\n this.name = element.dataset.name;\n this.urlParams = element.dataset.urlParams === 'true';\n\n this.queryProps = element.dataset.query;\n }\n\n public editQuery() {\n let queryProps:any = this.queryProps;\n\n if (!this.urlParams) {\n try {\n queryProps = JSON.parse(this.queryProps);\n } catch (e) {\n console.error(`Failed to parse query props from ${this.queryProps}: ${e}`);\n queryProps = {};\n }\n }\n\n this.externalQuery.show({\n currentQuery: queryProps,\n urlParams: this.urlParams,\n callback: (queryProps:any) => {\n this.queryProps = this.urlParams ? queryProps : JSON.stringify(queryProps);\n this.cdRef.detectChanges();\n }\n });\n }\n}","\n\n","import {OptionalBootstrapDefinition} from \"core-app/globals/dynamic-bootstrapper\";\nimport {appBaseSelector, ApplicationBaseComponent} from \"core-app/modules/router/base/application-base.component\";\nimport {\n EmbeddedTablesMacroComponent,\n wpEmbeddedTableMacroSelector\n} from \"core-components/wp-table/embedded/embedded-tables-macro.component\";\nimport {\n ColorsAutocompleter,\n colorsAutocompleterSelector\n} from \"core-app/modules/common/colors/colors-autocompleter.component\";\nimport {\n ZenModeButtonComponent,\n zenModeComponentSelector\n} from \"core-components/wp-buttons/zen-mode-toggle-button/zen-mode-toggle-button.component\";\nimport {AttachmentsComponent, attachmentsSelector} from \"core-app/modules/attachments/attachments.component\";\nimport {\n UserAutocompleterComponent,\n usersAutocompleterSelector\n} from \"core-app/modules/common/autocomplete/user-autocompleter.component\";\nimport {\n GlobalSearchWorkPackagesComponent,\n globalSearchWorkPackagesSelector\n} from \"core-app/modules/global_search/global-search-work-packages.component\";\nimport {\n HomescreenNewFeaturesBlockComponent,\n homescreenNewFeaturesBlockSelector\n} from \"core-components/homescreen/blocks/new-features.component\";\nimport {\n CustomDateActionAdminComponent,\n customDateActionAdminSelector\n} from \"core-components/wp-custom-actions/date-action/custom-date-action-admin.component\";\nimport {BoardsMenuComponent, boardsMenuSelector} from \"core-app/modules/boards/boards-sidebar/boards-menu.component\";\nimport {\n GlobalSearchWorkPackagesEntryComponent,\n globalSearchWorkPackagesSelectorEntry\n} from \"core-app/modules/global_search/global-search-work-packages-entry.component\";\nimport {\n NotificationsContainerComponent,\n notificationsContainerSelector\n} from \"core-app/modules/common/notifications/notifications-container.component\";\nimport {\n adminTypeFormConfigurationSelector,\n TypeFormConfigurationComponent\n} from \"core-app/modules/admin/types/type-form-configuration.component\";\nimport {\n CkeditorAugmentedTextareaComponent,\n ckeditorAugmentedTextareaSelector\n} from \"core-app/ckeditor/ckeditor-augmented-textarea.component\";\nimport {\n PersistentToggleComponent,\n persistentToggleSelector\n} from \"core-app/modules/common/persistent-toggle/persistent-toggle.component\";\nimport {UserAvatarComponent, userAvatarSelector} from \"core-components/user/user-avatar/user-avatar.component\";\nimport {\n HideSectionLinkComponent,\n hideSectionLinkSelector\n} from \"core-app/modules/common/hide-section/hide-section-link/hide-section-link.component\";\nimport {\n ShowSectionDropdownComponent,\n showSectionDropdownSelector\n} from \"core-app/modules/common/hide-section/show-section-dropdown.component\";\nimport {\n AddSectionDropdownComponent,\n addSectionDropdownSelector\n} from \"core-app/modules/common/hide-section/add-section-dropdown/add-section-dropdown.component\";\nimport {\n AutocompleteSelectDecorationComponent,\n autocompleteSelectDecorationSelector\n} from \"core-app/modules/common/autocomplete/autocomplete-select-decoration.component\";\nimport {\n ContentTabsComponent,\n contentTabsSelector\n} from \"core-app/modules/common/tabs/content-tabs/content-tabs.component\";\nimport {\n CopyToClipboardDirective,\n copyToClipboardSelector\n} from \"core-app/modules/common/copy-to-clipboard/copy-to-clipboard.directive\";\nimport {\n ConfirmFormSubmitController,\n confirmFormSubmitSelector\n} from \"core-components/modals/confirm-form-submit/confirm-form-submit.directive\";\nimport {MainMenuResizerComponent, mainMenuResizerSelector} from \"core-components/resizer/main-menu-resizer.component\";\nimport {\n GlobalSearchInputComponent,\n globalSearchSelector\n} from \"core-app/modules/global_search/input/global-search-input.component\";\nimport {\n collapsibleSectionAugmentSelector,\n CollapsibleSectionComponent\n} from \"core-app/modules/common/collapsible-section/collapsible-section.component\";\nimport {\n EnterpriseBannerBootstrapComponent,\n enterpriseBannerSelector\n} from \"core-components/enterprise-banner/enterprise-banner-bootstrap.component\";\nimport {\n ProjectMenuAutocompleteComponent,\n projectMenuAutocompleteSelector\n} from \"core-components/projects/project-menu-autocomplete/project-menu-autocomplete.component\";\nimport {\n RemoteFieldUpdaterComponent,\n remoteFieldUpdaterSelector\n} from \"core-app/modules/common/remote-field-updater/remote-field-updater.component\";\nimport {\n WorkPackageOverviewGraphComponent,\n wpOverviewGraphSelector\n} from \"core-app/modules/work-package-graphs/overview/wp-overview-graph.component\";\nimport {\n WorkPackageQuerySelectDropdownComponent,\n wpQuerySelectSelector\n} from \"core-components/wp-query-select/wp-query-select-dropdown.component\";\nimport {\n GlobalSearchTitleComponent,\n globalSearchTitleSelector\n} from \"core-app/modules/global_search/title/global-search-title.component\";\nimport {\n GlobalSearchTabsComponent,\n globalSearchTabsSelector\n} from \"core-app/modules/global_search/tabs/global-search-tabs.component\";\nimport {MainMenuToggleComponent, mainMenuToggleSelector} from \"core-components/main-menu/main-menu-toggle.component\";\nimport {\n MembersAutocompleterComponent,\n membersAutocompleterSelector\n} from \"core-app/modules/members/members-autocompleter.component\";\nimport {EnterpriseBaseComponent, enterpriseBaseSelector} from \"core-components/enterprise/enterprise-base.component\";\nimport {\n EEActiveSavedTrialComponent,\n enterpriseActiveSavedTrialSelector\n} from \"core-components/enterprise/enterprise-active-trial/ee-active-saved-trial.component\";\nimport {\n TriggerActionsEntryComponent,\n triggerActionsEntryComponentSelector\n} from \"core-app/modules/time_entries/edit/trigger-actions-entry.component\";\nimport {\n BacklogsPageComponent,\n backlogsPageComponentSelector\n} from \"core-app/modules/backlogs/backlogs-page/backlogs-page.component\";\nimport {\n attributeValueMacro,\n AttributeValueMacroComponent\n} from \"core-app/modules/fields/macros/attribute-value-macro.component\";\nimport {\n attributeLabelMacro,\n AttributeLabelMacroComponent\n} from \"core-app/modules/fields/macros/attribute-label-macro.component\";\nimport {\n AttributeHelpTextComponent,\n attributeHelpTextSelector\n} from \"core-app/modules/fields/help-texts/attribute-help-text.component\";\nimport {\n quickInfoMacroSelector,\n WorkPackageQuickinfoMacroComponent\n} from \"core-app/modules/fields/macros/work-package-quickinfo-macro.component\";\nimport {\n EditableQueryPropsComponent,\n editableQueryPropsSelector\n} from \"core-app/modules/admin/editable-query-props/editable-query-props.component\";\nimport {SlideToggleComponent, slideToggleSelector} from \"core-app/modules/common/slide-toggle/slide-toggle.component\";\n\nexport const globalDynamicComponents:OptionalBootstrapDefinition[] = [\n { selector: appBaseSelector, cls: ApplicationBaseComponent },\n { selector: attributeHelpTextSelector, cls: AttributeHelpTextComponent },\n { selector: wpEmbeddedTableMacroSelector, cls: EmbeddedTablesMacroComponent, embeddable: true },\n { selector: colorsAutocompleterSelector, cls: ColorsAutocompleter },\n { selector: zenModeComponentSelector, cls: ZenModeButtonComponent },\n { selector: attachmentsSelector, cls: AttachmentsComponent, embeddable: true },\n { selector: usersAutocompleterSelector, cls: UserAutocompleterComponent },\n { selector: membersAutocompleterSelector, cls: MembersAutocompleterComponent },\n { selector: globalSearchTabsSelector, cls: GlobalSearchTabsComponent },\n { selector: globalSearchWorkPackagesSelector, cls: GlobalSearchWorkPackagesComponent },\n { selector: homescreenNewFeaturesBlockSelector, cls: HomescreenNewFeaturesBlockComponent },\n { selector: customDateActionAdminSelector, cls: CustomDateActionAdminComponent },\n { selector: boardsMenuSelector, cls: BoardsMenuComponent },\n { selector: globalSearchWorkPackagesSelectorEntry, cls: GlobalSearchWorkPackagesEntryComponent },\n { selector: notificationsContainerSelector, cls: NotificationsContainerComponent },\n { selector: adminTypeFormConfigurationSelector, cls: TypeFormConfigurationComponent, },\n { selector: ckeditorAugmentedTextareaSelector, cls: CkeditorAugmentedTextareaComponent, embeddable: true },\n { selector: persistentToggleSelector, cls: PersistentToggleComponent },\n { selector: userAvatarSelector, cls: UserAvatarComponent },\n { selector: hideSectionLinkSelector, cls: HideSectionLinkComponent },\n { selector: showSectionDropdownSelector, cls: ShowSectionDropdownComponent },\n { selector: addSectionDropdownSelector, cls: AddSectionDropdownComponent },\n { selector: autocompleteSelectDecorationSelector, cls: AutocompleteSelectDecorationComponent },\n { selector: contentTabsSelector, cls: ContentTabsComponent },\n { selector: globalSearchTitleSelector, cls: GlobalSearchTitleComponent },\n { selector: copyToClipboardSelector, cls: CopyToClipboardDirective },\n { selector: confirmFormSubmitSelector, cls: ConfirmFormSubmitController },\n { selector: mainMenuResizerSelector, cls: MainMenuResizerComponent },\n { selector: mainMenuToggleSelector, cls: MainMenuToggleComponent },\n { selector: globalSearchSelector, cls: GlobalSearchInputComponent },\n { selector: collapsibleSectionAugmentSelector, cls: CollapsibleSectionComponent },\n { selector: enterpriseBannerSelector, cls: EnterpriseBannerBootstrapComponent },\n { selector: enterpriseBaseSelector, cls: EnterpriseBaseComponent },\n { selector: enterpriseActiveSavedTrialSelector, cls: EEActiveSavedTrialComponent },\n { selector: projectMenuAutocompleteSelector, cls: ProjectMenuAutocompleteComponent },\n { selector: remoteFieldUpdaterSelector, cls: RemoteFieldUpdaterComponent },\n { selector: wpOverviewGraphSelector, cls: WorkPackageOverviewGraphComponent },\n { selector: wpQuerySelectSelector, cls: WorkPackageQuerySelectDropdownComponent },\n { selector: triggerActionsEntryComponentSelector, cls: TriggerActionsEntryComponent, embeddable: true },\n { selector: backlogsPageComponentSelector, cls: BacklogsPageComponent },\n { selector: attributeValueMacro, cls: AttributeValueMacroComponent, embeddable: true },\n { selector: attributeLabelMacro, cls: AttributeLabelMacroComponent, embeddable: true },\n { selector: quickInfoMacroSelector, cls: WorkPackageQuickinfoMacroComponent, embeddable: true },\n { selector: editableQueryPropsSelector, cls: EditableQueryPropsComponent },\n { selector: slideToggleSelector, cls: SlideToggleComponent }\n];\n\n\n\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from \"@angular/core\";\nimport {MembersAutocompleterComponent} from \"core-app/modules/members/members-autocompleter.component\";\nimport {NgSelectModule} from \"@ng-select/ng-select\";\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n NgSelectModule\n ],\n exports: [ ],\n declarations: [\n MembersAutocompleterComponent\n ]\n})\nexport class OpenprojectMembersModule { }\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {EnterpriseTrialService} from \"core-components/enterprise/enterprise-trial.service\";\nimport {EnterpriseBaseComponent} from \"core-components/enterprise/enterprise-base.component\";\nimport {EnterpriseTrialModal} from \"core-components/enterprise/enterprise-modal/enterprise-trial.modal\";\nimport {EETrialFormComponent} from \"core-components/enterprise/enterprise-modal/enterprise-trial-form/ee-trial-form.component\";\nimport {EETrialWaitingComponent} from \"core-components/enterprise/enterprise-trial-waiting/ee-trial-waiting.component\";\nimport {EEActiveTrialComponent} from \"core-components/enterprise/enterprise-active-trial/ee-active-trial.component\";\nimport {EEActiveSavedTrialComponent} from \"core-components/enterprise/enterprise-active-trial/ee-active-saved-trial.component\";\nimport {FormsModule, ReactiveFormsModule} from \"@angular/forms\";\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n FormsModule,\n ReactiveFormsModule\n ],\n providers: [\n EnterpriseTrialService\n ],\n declarations: [\n EnterpriseBaseComponent,\n EnterpriseTrialModal,\n EETrialFormComponent,\n EETrialWaitingComponent,\n EEActiveTrialComponent,\n EEActiveSavedTrialComponent,\n ]\n})\nexport class OpenprojectEnterpriseModule {\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {Inject, Injectable, Injector} from \"@angular/core\";\nimport {DOCUMENT} from \"@angular/common\";\nimport {DynamicContentModal} from \"core-components/modals/modal-wrapper/dynamic-content.modal\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\n\nconst iframeSelector = '.iframe-target-wrapper';\n\n@Injectable({ providedIn: 'root' })\nexport class ModalWrapperAugmentService {\n\n constructor(@Inject(DOCUMENT) protected documentElement:Document,\n protected injector:Injector,\n protected opModalService:OpModalService) {\n }\n\n /**\n * Create initial listeners for Rails-rendered modals\n */\n public setupListener() {\n const matches = this.documentElement.querySelectorAll('section[data-augmented-model-wrapper]');\n for (let i = 0; i < matches.length; ++i) {\n this.wrapElement(jQuery(matches[i]) as JQuery);\n }\n }\n\n /**\n * Wrap a section[data-augmented-modal-wrapper] element\n */\n public wrapElement(element:JQuery) {\n // Find activation link\n let activationLink = element.find('.modal-wrapper--activation-link');\n let activationSelector = element.data('activationSelector');\n\n if (activationSelector) {\n activationLink = jQuery(activationSelector);\n }\n\n const initializeNow = element.data('modalInitializeNow');\n\n if (initializeNow) {\n this.show(element);\n } else {\n activationLink.click((evt:JQuery.TriggeredEvent) => {\n this.show(element);\n evt.preventDefault();\n });\n }\n }\n\n private show(element:JQuery) {\n // Set modal class name\n const modalClassName = element.data('modalClassName');\n // Append CSP-whitelisted IFrame for onboarding\n const iframeUrl = element.data('modalIframeUrl');\n\n // Set template from wrapped element\n const wrappedElement = element.find('.modal-wrapper--content');\n let modalBody = wrappedElement.html();\n\n if (iframeUrl) {\n modalBody = this.appendIframe(modalBody, iframeUrl);\n }\n\n this.opModalService.show(\n DynamicContentModal,\n this.injector,\n {\n modalBody: modalBody,\n modalClassName: modalClassName\n }\n );\n }\n\n private appendIframe(body:string, url:string) {\n let subdom = jQuery(body);\n let iframe = jQuery('');\n iframe.attr('src', url);\n\n subdom.find(iframeSelector).append(iframe);\n\n return subdom.html();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {Inject, Injectable} from \"@angular/core\";\nimport {DOCUMENT} from \"@angular/common\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\n\n@Injectable({ providedIn: 'root' })\nexport class PathScriptAugmentService {\n\n constructor(@Inject(DOCUMENT) protected documentElement:Document) {\n }\n\n /**\n * Import required javascript paths from backend-rendered pages\n * This provides a replacement for the asset pipeline that was previously used\n * to load javascripts in the backend.\n *\n * This approach retains the ability to dynamically load code (from a specific set of paths only)\n * while defining the dependency in the rails template to ensure developer visibility.\n */\n public loadRequiredScripts() {\n const matches = this.documentElement.querySelectorAll('meta[name=\"required_script\"]');\n for (let i = 0; i < matches.length; ++i) {\n const name = matches[i].content;\n debugLog(\"Loading required script \" + name);\n import('../dynamic-scripts/' + name);\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {NgModule} from '@angular/core';\nimport {ModalWrapperAugmentService} from \"core-app/modules/augmenting/services/modal-wrapper.augment.service\";\nimport {PathScriptAugmentService} from \"core-app/modules/augmenting/services/path-script.augment.service\";\n\n@NgModule({\n providers: [\n ModalWrapperAugmentService,\n PathScriptAugmentService\n ],\n})\nexport class OpenprojectAugmentingModule {\n constructor(modalWrapper:ModalWrapperAugmentService,\n pathScript:PathScriptAugmentService) {\n // Setup augmenting services\n modalWrapper.setupListener();\n pathScript.loadRequiredScripts();\n }\n}\n\n","import {Injectable, Injector} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n/*\n * This service conditionally creates two settings buttons (on the user menu and on\n * the login menu) that give access to the Revit Plugin settings.\n */\n@Injectable()\nexport class RevitAddInSettingsButtonService {\n private readonly labelText:string;\n private readonly groupLabelText:string;\n\n constructor(readonly injector:Injector,\n readonly i18n:I18nService) {\n const onRevitAddInEnvironment = window.navigator.userAgent.search('Revit') > -1;\n\n if (onRevitAddInEnvironment) {\n this.labelText = i18n.t('js.revit.revit_add_in_settings');\n this.groupLabelText = i18n.t('js.revit.revit_add_in');\n\n this.addUserMenuItem();\n this.addLoginMenuItem();\n }\n }\n\n public addUserMenuItem():void {\n const userMenu = document.getElementById('user-menu');\n\n if (userMenu) {\n const menuItem:HTMLElement = document.createElement('li');\n menuItem.dataset.name = this.labelText;\n menuItem.innerHTML = `\n \n ${this.labelText}\n \n `;\n\n menuItem.addEventListener('click', () => this.goToSettings());\n userMenu.appendChild(menuItem);\n }\n }\n\n public addLoginMenuItem() {\n const loginModal = document.querySelector('#nav-login-content');\n\n if (loginModal) {\n const loginMenuItem:HTMLElement = document.createElement('div');\n\n loginMenuItem.dataset.name = this.labelText;\n loginMenuItem.innerHTML = `\n
        \n

        \n \n ${this.groupLabelText}\n \n

        \n
        \n
        \n ${this.labelText}\n
        \n
        \n
        \n `;\n loginModal.appendChild(loginMenuItem);\n\n const settingsButton = loginModal.querySelector('.revit-add-in-button');\n\n settingsButton!.addEventListener('click', () => this.goToSettings());\n }\n }\n\n goToSettings() {\n window.RevitBridge.sendMessageToRevit('GoToSettings', '1', '');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {APP_INITIALIZER, ApplicationRef, Injector, NgModule} from '@angular/core';\nimport {ReactiveFormsModule} from '@angular/forms';\nimport {OpenprojectHalModule} from 'core-app/modules/hal/openproject-hal.module';\n\nimport {OpContextMenuTrigger} from 'core-components/op-context-menu/handlers/op-context-menu-trigger.directive';\nimport {States} from 'core-components/states.service';\nimport {PaginationService} from 'core-components/table-pagination/pagination-service';\nimport {MainMenuResizerComponent} from 'core-components/resizer/main-menu-resizer.component';\nimport {ExternalQueryConfigurationService} from 'core-components/wp-table/external-configuration/external-query-configuration.service';\nimport {ExternalRelationQueryConfigurationService} from 'core-components/wp-table/external-configuration/external-relation-query-configuration.service';\nimport {ConfirmDialogModal} from \"core-components/modals/confirm-dialog/confirm-dialog.modal\";\nimport {ConfirmDialogService} from \"core-components/modals/confirm-dialog/confirm-dialog.service\";\nimport {DynamicContentModal} from \"core-components/modals/modal-wrapper/dynamic-content.modal\";\nimport {PasswordConfirmationModal} from \"core-components/modals/request-for-confirmation/password-confirmation.modal\";\nimport {OpenprojectFieldsModule} from \"core-app/modules/fields/openproject-fields.module\";\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {CommentService} from \"core-components/wp-activity/comment-service\";\nimport {OpDragScrollDirective} from \"core-app/modules/common/ui/op-drag-scroll.directive\";\nimport {OpenprojectPluginsModule} from \"core-app/modules/plugins/openproject-plugins.module\";\nimport {ConfirmFormSubmitController} from \"core-components/modals/confirm-form-submit/confirm-form-submit.directive\";\nimport {ProjectMenuAutocompleteComponent} from \"core-components/projects/project-menu-autocomplete/project-menu-autocomplete.component\";\nimport {OpenProjectFileUploadService} from \"core-components/api/op-file-upload/op-file-upload.service\";\nimport {OpenProjectDirectFileUploadService} from './components/api/op-file-upload/op-direct-file-upload.service';\nimport {LinkedPluginsModule} from \"core-app/modules/plugins/linked-plugins.module\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {DynamicBootstrapper} from \"core-app/globals/dynamic-bootstrapper\";\nimport {OpenprojectWorkPackagesModule} from 'core-app/modules/work_packages/openproject-work-packages.module';\nimport {OpenprojectAttachmentsModule} from 'core-app/modules/attachments/openproject-attachments.module';\nimport {OpenprojectEditorModule} from 'core-app/modules/editor/openproject-editor.module';\nimport {OpenprojectGridsModule} from \"core-app/modules/grids/openproject-grids.module\";\nimport {OpenprojectRouterModule} from \"core-app/modules/router/openproject-router.module\";\nimport {OpenprojectWorkPackageRoutesModule} from \"core-app/modules/work_packages/openproject-work-package-routes.module\";\nimport {BrowserModule} from \"@angular/platform-browser\";\nimport {OpenprojectCalendarModule} from \"core-app/modules/calendar/openproject-calendar.module\";\nimport {OpenprojectGlobalSearchModule} from \"core-app/modules/global_search/openproject-global-search.module\";\nimport {MainMenuToggleComponent} from \"core-components/main-menu/main-menu-toggle.component\";\nimport {MainMenuNavigationService} from \"core-components/main-menu/main-menu-navigation.service\";\nimport {OpenprojectAdminModule} from \"core-app/modules/admin/openproject-admin.module\";\nimport {OpenprojectDashboardsModule} from \"core-app/modules/dashboards/openproject-dashboards.module\";\nimport {OpenprojectWorkPackageGraphsModule} from \"core-app/modules/work-package-graphs/openproject-work-package-graphs.module\";\nimport {WpPreviewModal} from \"core-components/modals/preview-modal/wp-preview-modal/wp-preview.modal\";\nimport {PreviewTriggerService} from \"core-app/globals/global-listeners/preview-trigger.service\";\nimport {OpenprojectOverviewModule} from \"core-app/modules/overview/openproject-overview.module\";\nimport {OpenprojectMyPageModule} from \"core-app/modules/my-page/openproject-my-page.module\";\nimport {OpenprojectProjectsModule} from \"core-app/modules/projects/openproject-projects.module\";\nimport {KeyboardShortcutService} from \"core-app/modules/a11y/keyboard-shortcut-service\";\nimport {globalDynamicComponents} from \"core-app/global-dynamic-components.const\";\nimport {OpenprojectMembersModule} from \"core-app/modules/members/members.module\";\nimport {OpenprojectEnterpriseModule} from \"core-components/enterprise/openproject-enterprise.module\";\nimport {OpenprojectAugmentingModule} from \"core-app/modules/augmenting/openproject-augmenting.module\";\nimport {RevitAddInSettingsButtonService} from \"core-app/modules/bim/revit_add_in/revit-add-in-settings-button.service\";\n\n@NgModule({\n imports: [\n // The BrowserModule must only be loaded here!\n BrowserModule,\n // Commons\n OpenprojectCommonModule,\n // Router module\n OpenprojectRouterModule,\n // Hal Module\n OpenprojectHalModule,\n\n // CKEditor\n OpenprojectEditorModule,\n // Display + Edit field functionality\n OpenprojectFieldsModule,\n OpenprojectGridsModule,\n OpenprojectAttachmentsModule,\n\n // Project module\n OpenprojectProjectsModule,\n\n // Work packages and their routes\n OpenprojectWorkPackagesModule,\n OpenprojectWorkPackageRoutesModule,\n\n // Work packages in graph representation\n OpenprojectWorkPackageGraphsModule,\n\n // Calendar module\n OpenprojectCalendarModule,\n\n // Dashboards\n OpenprojectDashboardsModule,\n\n // Overview\n OpenprojectOverviewModule,\n\n // MyPage\n OpenprojectMyPageModule,\n\n // Global Search\n OpenprojectGlobalSearchModule,\n\n // Admin module\n OpenprojectAdminModule,\n OpenprojectEnterpriseModule,\n\n // Plugin hooks and modules\n OpenprojectPluginsModule,\n // Linked plugins dynamically generated by bundler\n LinkedPluginsModule,\n\n // Members\n OpenprojectMembersModule,\n\n // Angular Forms\n ReactiveFormsModule,\n\n // Augmenting Module\n OpenprojectAugmentingModule,\n ],\n providers: [\n { provide: States, useValue: new States() },\n { provide: APP_INITIALIZER, useFactory: initializeServices, deps: [Injector], multi: true },\n PaginationService,\n OpenProjectFileUploadService,\n OpenProjectDirectFileUploadService,\n // Split view\n CommentService,\n ConfirmDialogService,\n RevitAddInSettingsButtonService,\n ],\n declarations: [\n OpContextMenuTrigger,\n\n // Modals\n ConfirmDialogModal,\n DynamicContentModal,\n PasswordConfirmationModal,\n WpPreviewModal,\n\n // Main menu\n MainMenuResizerComponent,\n MainMenuToggleComponent,\n\n // Project autocompleter\n ProjectMenuAutocompleteComponent,\n\n // Form configuration\n OpDragScrollDirective,\n ConfirmFormSubmitController,\n ]\n})\nexport class OpenProjectModule {\n\n // noinspection JSUnusedGlobalSymbols\n ngDoBootstrap(appRef:ApplicationRef) {\n\n // Register global dynamic components\n // this is necessary to ensure they are not tree-shaken\n // (if they are not used anywhere in Angular, they would be removed)\n DynamicBootstrapper.register(...globalDynamicComponents);\n\n // Perform global dynamic bootstrapping of our entry components\n // that are in the current DOM response.\n DynamicBootstrapper.bootstrapOptionalDocument(appRef, document);\n\n // Call hook service to allow modules to bootstrap additional elements.\n // We can't use ngDoBootstrap in nested modules since they are not called.\n const hookService = (appRef as any)._injector.get(HookService);\n hookService\n .call('openProjectAngularBootstrap')\n .forEach((results:{ selector:string, cls:any }[]) => {\n DynamicBootstrapper.bootstrapOptionalDocument(appRef, document, results);\n });\n }\n}\n\nexport function initializeServices(injector:Injector) {\n return () => {\n const PreviewTrigger = injector.get(PreviewTriggerService);\n const mainMenuNavigationService = injector.get(MainMenuNavigationService);\n const keyboardShortcuts = injector.get(KeyboardShortcutService);\n // Conditionally add the Revit Add-In settings button\n injector.get(RevitAddInSettingsButtonService);\n\n mainMenuNavigationService.register();\n\n PreviewTrigger.setupListener();\n\n keyboardShortcuts.register();\n };\n}\n","import {OpenProjectModule} from 'core-app/angular4-modules';\nimport {enableProdMode} from '@angular/core';\nimport * as jQuery from \"jquery\";\nimport {environment} from './environments/environment';\nimport {platformBrowserDynamic} from '@angular/platform-browser-dynamic';\nimport {SentryReporter} from \"core-app/sentry/sentry-reporter\";\nimport {whenDebugging} from \"core-app/helpers/debug_output\";\nimport {enableReactiveStatesLogging} from \"reactivestates\";\nimport {initializeLocale} from \"core-app/init-locale\";\n\n(window as any).global = window;\n\n// Ensure we set the correct dynamic frontend path\n// based on the RAILS_RELATIVE_URL_ROOT setting\n// https://webpack.js.org/guides/public-path/\nconst ASSET_BASE_PATH = '/assets/frontend/';\n\n// Sets the relative base path\nwindow.appBasePath = jQuery('meta[name=app_base_path]').attr('content') || '';\n\n// Ensure to set the asset base for dynamic code loading\n// https://webpack.js.org/guides/public-path/\n__webpack_public_path__ = window.appBasePath + ASSET_BASE_PATH;\n\nwindow.ErrorReporter = new SentryReporter();\n\nrequire('core-app/init-vendors');\nrequire('core-app/init-globals');\n\nif (environment.production) {\n enableProdMode();\n}\n\n// Enable debug logging for reactive states\nwhenDebugging(() => {\n (window as any).enableReactiveStatesLogging = () => enableReactiveStatesLogging(true);\n (window as any).disableReactiveStatesLogging = () => enableReactiveStatesLogging(false);\n});\n\n// Import the correct locale early on\ninitializeLocale()\n .then(() => {\n jQuery(function () {\n // Due to the behaviour of the Edge browser we need to wait for 'DOM ready'\n platformBrowserDynamic()\n .bootstrapModule(OpenProjectModule)\n .then(platformRef => {\n jQuery('body').addClass('__ng2-bootstrap-has-run');\n });\n });\n });\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Scope} from \"@sentry/hub\";\nimport {Severity} from \"@sentry/types\";\nimport {Event as SentryEvent} from \"@sentry/types\";\nimport {environment} from \"../../environments/environment\";\n\nexport type ScopeCallback = (scope:Scope) => void;\n\n\nexport interface CaptureInterface {\n /** Capture a message */\n captureMessage(msg:string, level?:MessageSeverity):void;\n\n /** Capture an exception(!) only */\n captureException(err:Error):void;\n}\n\nexport interface SentryClient extends CaptureInterface {\n configureScope(scope:ScopeCallback):void;\n withScope(scope:ScopeCallback):void;\n}\n\nexport interface ErrorReporter extends CaptureInterface {\n /** Register a context callback handler */\n addContext(...callbacks:ScopeCallback[]):void;\n}\n\nexport type MessageSeverity = 'fatal'|'error'|'warning'|'log'|'info'|'debug';\n\ninterface QueuedMessage {\n type:'captureMessage'|'captureException';\n args:any[];\n}\n\nexport class SentryReporter implements ErrorReporter {\n\n private contextCallbacks:ScopeCallback[] = [];\n\n private messageStack:QueuedMessage[] = [];\n\n private readonly sentryConfigured:boolean = true;\n\n private client:any;\n\n constructor() {\n const sentryElement = document.querySelector('meta[name=openproject_sentry]') as HTMLElement|null;\n if (sentryElement) {\n import('@sentry/browser').then((Sentry) => {\n Sentry.init({\n dsn: sentryElement.dataset.dsn!,\n debug: !environment.production,\n ignoreErrors: [\n // Transition movements,\n 'The transition has been superseded by a different transition',\n // Uncaught promise rejections\n 'Uncaught (in promise)'\n ],\n beforeSend: (event) => this.filterEvent(event)\n });\n\n this.sentryLoaded(Sentry);\n });\n } else {\n this.sentryConfigured = false;\n this.messageStack = [];\n }\n }\n\n public sentryLoaded(client:any) {\n this.client = client;\n client.configureScope(this.setupContext.bind(this));\n\n // Send all messages from before sentry got loaded\n this.messageStack.forEach((item) => {\n this[item.type].bind(this).apply(item.args);\n });\n }\n\n public captureMessage(msg:string, severity:MessageSeverity = 'info') {\n if (!this.client) {\n return this.handleOfflineMessage('captureMessage', Array.from(arguments));\n }\n\n this.client.withScope((scope:Scope) => {\n this.setupContext(scope);\n this.client.captureMessage(msg, Severity.fromString(severity));\n });\n }\n\n public captureException(err:Error|string) {\n if (!this.client || !err) {\n this.handleOfflineMessage('captureException', Array.from(arguments));\n throw err;\n }\n\n if (typeof err === 'string') {\n return this.captureMessage(err, 'error');\n }\n\n this.client.withScope((scope:Scope) => {\n this.setupContext(scope);\n this.client.captureException(err);\n });\n }\n\n public addContext(...callbacks:ScopeCallback[]):void {\n this.contextCallbacks.push(...callbacks);\n\n if (this.client) {\n /** Add to global context as well */\n callbacks.forEach(cb => this.client.configureScope(cb));\n }\n }\n\n /**\n * Remember a message or error for later handling\n * @param type\n * @param args\n */\n private handleOfflineMessage(type:'captureMessage'|'captureException', args:any[]) {\n if (this.sentryConfigured) {\n this.messageStack.push({ type, args });\n } else {\n console.log(\"[ErrorReporter] Would queue sentry message %O %O, but is not configured.\", type, args);\n }\n }\n\n /**\n * Set up the current scope for the event to be sent.\n * @param scope\n */\n private setupContext(scope:Scope) {\n scope.setTag('locale', I18n.locale);\n scope.setTag('domain', window.location.hostname);\n scope.setTag('url_path', window.location.pathname);\n scope.setExtra('url_query', window.location.search);\n\n /** Execute callbacks */\n this.contextCallbacks.forEach(cb => cb(scope));\n }\n\n /**\n * Filters the event content's or removes\n * it from being sent.\n *\n * @param event\n */\n private filterEvent(event:SentryEvent):SentryEvent|null {\n const unsupportedBrowser = document.body.classList.contains('-unsupported-browser');\n if (unsupportedBrowser) {\n console.warn(\"Browser is not supported, skipping sentry reporting completely.\");\n return null;\n }\n\n return event;\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nexport function initializeLocale() {\n const meta = document.querySelector('meta[name=openproject_initializer]') as HTMLMetaElement;\n I18n.locale = meta.dataset.locale || 'en';\n I18n.firstDayOfWeek = parseInt(meta.dataset.firstDayOfWeek!, 10);\n\n // Override the default pluralization function to allow\n // \"other\" to be used as a fallback for \"one\" in languages where one is not set\n // (japanese, for example)\n I18n.pluralization[\"default\"] = function (count:number) {\n switch (count) {\n case 0:\n return [\"zero\", \"other\"];\n case 1:\n return [\"one\", \"other\"];\n default:\n return [\"other\"];\n }\n };\n\n return import(/* webpackChunkName: \"locale\" */ `../locales/${I18n.locale}.js`);\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2021 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {combine, deriveRaw, input, State} from 'reactivestates';\nimport {map, mapTo, take} from 'rxjs/operators';\nimport {merge, Observable} from 'rxjs';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {QuerySchemaResource} from 'core-app/modules/hal/resources/query-schema-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {Injectable} from \"@angular/core\";\n\n@Injectable()\nexport abstract class WorkPackageViewBaseService {\n /** Internal state to push non-persisted updates */\n protected updatesState = input();\n\n /** Internal pristine state filled during +initialize+ only */\n protected pristineState = input();\n\n constructor(protected readonly querySpace:IsolatedQuerySpace) {\n }\n\n /**\n * Get the state value from the current query.\n *\n * @param {QueryResource} query\n * @returns {T} Instance of the state value for this type.\n */\n public abstract valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource):T|undefined;\n\n /**\n * Initialize this table state from the given query resource,\n * and possibly the associated schema.\n *\n * @param {QueryResource} query\n * @param {QuerySchemaResource} schema\n */\n public initialize(query:QueryResource, results:WorkPackageCollectionResource, schema?:QuerySchemaResource) {\n const initial = this.valueFromQuery(query, results)!;\n this.pristineState.putValue(initial);\n }\n\n public update(value:T) {\n this.updatesState.putValue(value);\n }\n\n public clear(reason:string) {\n this.pristineState.clear(reason);\n this.updatesState.clear(reason);\n }\n\n /**\n * Get the combined pristine and update value changes\n * @param unsubscribe\n */\n public live$():Observable {\n return merge(\n this.pristineState.values$(),\n this.updatesState.values$(),\n );\n }\n\n /**\n * Get pristine upstream changes\n *\n * @param unsubscribe\n */\n public pristine$():Observable {\n return this\n .pristineState\n .values$();\n }\n\n /**\n * Get only the local update changes\n *\n * @param unsubscribe\n */\n public updates$():Observable {\n return this\n .updatesState\n .values$();\n }\n\n /**\n * Get only the local update changes\n *\n * @param unsubscribe\n */\n public changes$():Observable {\n return this\n .updatesState\n .changes$();\n }\n\n public onReady() {\n return this\n .pristineState\n .values$()\n .pipe(\n take(1),\n mapTo(null)\n )\n .toPromise();\n }\n\n /** Get the last updated value from either pristine or update state */\n protected get lastUpdatedState():State {\n const combinedRaw = combine(this.pristineState, this.updatesState);\n\n return deriveRaw(combinedRaw,\n ($) => $\n .pipe(\n map(([pristine, current]) => {\n if (current === undefined) {\n return pristine;\n }\n return current;\n })\n )\n );\n }\n\n /**\n * Helper to set the value of the current state\n * @param val\n */\n protected set current(val:T|undefined) {\n if (val) {\n this.updatesState.putValue(val);\n } else {\n this.updatesState.clear();\n }\n }\n\n /**\n * Get the value of the current state, if any.\n */\n protected get current():T|undefined {\n return this.lastUpdatedState.value;\n }\n}\n\n@Injectable()\nexport abstract class WorkPackageQueryStateService extends WorkPackageViewBaseService {\n /**\n * Check whether the state value does not match the query resource's value.\n * @param query The current query resource\n */\n abstract hasChanged(query:QueryResource):boolean;\n\n /**\n * Apply the current state value to query\n *\n * @return Whether the query should be visibly updated.\n */\n abstract applyToQuery(query:QueryResource):boolean;\n}\n"],"sourceRoot":"webpack:///"}