{"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/configuration-modal/services/configuration-modal/configuration-modal.service.ts","./src/app/modules/grids/widgets/time-entries/current-user/configuration-modal/configuration.modal.html","./src/app/modules/grids/widgets/time-entries/current-user/configuration-modal/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","showing","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","wpTableSums","limitedResults","inlineCreateVisible","sumVisible","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","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":"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,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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R,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,OACX,OAAQ,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,MAAM,KAAKwO,MAMvC,SAAS26D,EAAoB3pD,GAClC,MAAO,eAAeA,EAMjB,SAAS4pD,EAAwB3uE,GACtC,OAAOA,EAAgBuF,MAAM,KAAK,GAM7B,SAASqpE,EAAsB5uE,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,mBAAoB,CAC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,KAAAC,aAIrB,WAAWkB,GAChB,OAAOjC,KAAK2E,UAAY1C,EAAMsB,sBAGhC,eAAetB,GACb,OAAOA,EAAMsB,uBAAyB,KAGjC,aAAatB,GAClB,MAAM0C,EAAU3E,KAAK2E,QAGrB,OAFA1C,EAAMsB,sBAAoC,OAAZoB,OAAmB2F,EAAY3F,GAEtD,EAGT,cACE,OAAO3E,KAAK6W,iBAAiB9D,WAAW,MAG1C,aACE,MAAMpO,EAAU3E,KAAK2E,QACrB,OAAQA,GAAWA,IAAYiwF,EAGjC,cACE,OAAO50F,KAAK2E,UAAYkwF,EAGnB,yBAAyBE,GAC9B/0F,KAAK8T,OAAOihF,I,sCAnCHD,GAA2C,sB,yBAA3CA,EAA2C,QAA3CA,EAA2C,a,qBCxCxD,IAAI7nF,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,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","file":"main.6b4dbbf2413552ba021e.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 = elementTable[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 EventEmitter,\n OnInit, Output\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 @Output('wp-inline-create--showing') showing = new EventEmitter();\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 this.showing.emit(this.canAdd || this.canReference);\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\";\nimport {WorkPackageViewSumService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service\";\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 // We need to sync certain height difference to the timeline\n // depending on whether inline create or sums rows are being shown\n public inlineCreateVisible = false;\n public sumVisible = 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 readonly wpTableSums:WorkPackageViewSumService,\n ) {\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 this.wpTableSums.live$()\n ]);\n\n statesCombined.pipe(\n this.untilDestroyed()\n ).subscribe(([results, groupBy, columns, timelines, sort, sums]) => {\n this.query = this.querySpace.query.value!;\n\n this.results = results;\n this.sumVisible = sums;\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 document\n .querySelectorAll(`#${selector} input[type=\"checkbox\"]:not([disabled])`)\n .forEach((el:HTMLInputElement) => el.checked = checked);\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++) {\n if (boxes[i].checked === false) {\n all_checked = false;\n }\n }\n for (let i = 0; i < boxes.length; i++) {\n boxes[i].checked = !all_checked;\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 {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.inputIsValidDate()) {\n this.onChange.emit(this.currentValue);\n } else {\n this.onChange.emit('');\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/configuration-modal/services/configuration-modal/configuration-modal.service\";\n\n@Component({\n templateUrl: './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/configuration-modal/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/configuration-modal/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:///"}