{"version":3,"sources":["./src/app/modules/common/notifications/notifications-container.component.ts","./src/app/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts","./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/modules/work_packages/routing/split-view-routes.template.ts","./src/app/modules/bim/bcf/helper/bcf-path-helper.service.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/relation-cell-builder.ts","./src/app/components/wp-activity/activity-link.component.ts","./src/app/modules/hal/dm-services/query-dm.service.ts","./src/app/components/op-context-menu/op-context-menu.types.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/a11y/double-click-or-tap.directive.ts","./src/app/modules/hal/dm-services/relations-dm.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/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/modules/common/authoring/authoring.component.ts","./src/app/modules/common/authoring/authoring.html","./src/app/components/work-packages/wp-breadcrumb/wp-breadcrumb.component.ts","./src/app/components/work-packages/wp-breadcrumb/wp-breadcrumb.html","./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-single-view-tabs/activity-panel/activity-on-overview.component.ts","./src/app/components/wp-single-view-tabs/activity-panel/activity-on-overview.html","./src/app/components/wp-copy/wp-copy-split-view.component.ts","./src/app/components/wp-new/wp-new-split-view.html","./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-table/timeline/wp-timeline.ts","./src/app/components/op-context-menu/op-context-menu.service.ts","./src/app/components/wp-new/wp-create.service.ts","./src/app/components/wp-fast-table/builders/modes/rows-builder.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/filters/abstract-filter-date-time-value/abstract-filter-date-time-value.controller.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/hal/dm-services/work-package-dm.service.ts","./src/app/components/modals/modal-wrapper/dynamic-content.modal.ts","./src/app/components/modals/modal-wrapper/dynamic-content.modal.html","./src/app/modules/common/ckeditor/ckeditor-setup.service.ts","./src/app/modules/fields/edit/edit-field.service.ts","./src/app/components/wp-query-select/wp-query-select-dropdown.component.ts","./src/app/components/wp-query-select/wp-query-select.template.html","./src/app/components/wp-table/wp-table-scroll-sync.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/components/wp-relations/wp-relations-create/wp-relations-create.component.ts","./src/app/components/wp-relations/wp-relations-create/wp-relation-create.template.html","./src/app/components/filters/filter-date-time-value/filter-date-time-value.component.ts","./src/app/components/filters/filter-date-time-value/filter-date-time-value.component.html","./src/app/components/wp-card-view/event-handler/click-handler.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/hal/dm-services/payload-dm.service.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service.ts","./src/app/components/filters/query-filters/query-filters.component.ts","./src/app/components/filters/query-filters/query-filters.component.html","./src/app/modules/fields/edit/edit-form/edit-form.component.ts","./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/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/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/schema-resource.ts","./src/app/modules/hal/resources/type-resource.ts","./src/app/modules/hal/resources/schema-dependency-resource.ts","./src/app/modules/hal/resources/wp-collection-resource.ts","./src/app/modules/hal/resources/form-resource.ts","./src/app/modules/hal/resources/query-filter-instance-schema-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/status-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/dm-services/type-dm.service.ts","./src/app/modules/hal/services/hal-aware-error-handler.ts","./src/app/modules/hal/openproject-hal.module.ts","./src/app/components/op-context-menu/handlers/op-types-context-menu.directive.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/components/wp-fast-table/builders/modes/grouped/group-header-builder.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/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/modules/hal/dm-services/root-dm.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/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.directive.ts","./src/app/components/wp-fast-table/builders/timeline/timeline-row-builder.ts","./src/app/components/work-packages/work-package-comment/wp-comment-field.component.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/wp-table/configuration-modal/wp-table-configuration-relation-selector.ts","./src/app/components/wp-table/configuration-modal/wp-table-configuration-relation-selector.html","./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/components/wp-relations/wp-relations-group/wp-relations-group.component.ts","./src/app/components/wp-relations/wp-relations-group/wp-relations-group.template.html","./src/app/components/wp-buttons/wp-details-view-button/wp-details-view-button.component.ts","./src/app/components/wp-buttons/wp-button.template.html","./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/external-configuration/external-relation-query-configuration.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/components/wp-table/embedded/wp-embedded-table-entry.component.ts","./src/app/modules/common/help-texts/attribute-help-text.component.ts","./src/app/modules/common/help-texts/attribute-help-text.component.html","./src/app/modules/boards/board/board-dm.service.ts","./src/app/modules/grids/widgets/widget-changeset.ts","./src/app/modules/grids/widgets/abstract-widget.component.ts","./src/app/modules/hal/dm-services/news-dm.service.ts","./src/app/modules/common/gon/gon.service.ts","./src/app/modules/common/back-routing/back-button.component.ts","./src/app/modules/hal/dm-services/status-dm.service.ts","./src/app/components/wp-list/wp-list.service.ts","./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/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/work-packages/wp-breadcrumb/wp-breadcrumb-parent.component.ts","./src/app/components/work-packages/wp-breadcrumb/wp-breadcrumb-parent.html","./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/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/op-context-menu/handlers/op-settings-dropdown-menu.directive.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/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/dm-services/query-order-dm.service.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/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/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/modules/fields/display/display-field.service.ts","./src/app/modules/common/path-helper/apiv3/path-resources.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts","./src/app/modules/common/path-helper/apiv3/work_packages/apiv3-work-package-paths.ts","./src/app/modules/common/path-helper/apiv3/work_packages/apiv3-work-packages-paths.ts","./src/app/modules/common/path-helper/apiv3/users/apiv3-user-paths.ts","./src/app/modules/common/path-helper/apiv3/users/apiv3-users-paths.ts","./src/app/modules/common/path-helper/apiv3/queries/apiv3-query-paths.ts","./src/app/modules/common/path-helper/apiv3/queries/apiv3-queries-paths.ts","./src/app/modules/common/path-helper/apiv3/types/apiv3-types-paths.ts","./src/app/modules/common/path-helper/apiv3/versions/apiv3-version-paths.ts","./src/app/modules/common/path-helper/apiv3/projects/apiv3-project-paths.ts","./src/app/modules/common/path-helper/apiv3/projects/apiv3-projects-paths.ts","./src/app/modules/common/path-helper/apiv3/grids/apiv3-grid-paths.ts","./src/app/modules/common/path-helper/apiv3/grids/apiv3-grids-paths.ts","./src/app/modules/common/path-helper/apiv3/news/apiv3-news-paths.ts","./src/app/modules/common/path-helper/apiv3/news/apiv3-newses-paths.ts","./src/app/modules/common/path-helper/apiv3/time-entries/apiv3-time-entry-paths.ts","./src/app/modules/common/path-helper/apiv3/time-entries/apiv3-time-entries-paths.ts","./src/app/modules/common/path-helper/apiv3/memberships/apiv3-memberships-paths.ts","./src/app/modules/common/path-helper/apiv3/groups/apiv3-groups-path.ts","./src/app/modules/common/path-helper/apiv3/apiv3-paths.ts","./src/app/modules/common/path-helper/path-helper.service.ts","./src/app/components/main-menu/main-menu-navigation.service.ts","./src/app/modules/common/browser/device.service.ts","./src/app/components/wp-buttons/wp-status-button/wp-status-button.component.ts","./src/app/components/wp-buttons/wp-status-button/wp-status-button.html","./src/app/modules/common/model-auth/model-auth.service.ts","./src/app/components/wp-fast-table/builders/modes/plain/plain-render-pass.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/components/projects/project-cache.service.ts","./src/app/modules/hal/resources/relation-resource.ts","./src/app/modules/fields/display/field-types/multiple-lines-string-objects-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/components/wp-edit-form/display-field-renderer.ts","./src/app/components/filters/query-filter/query-filter.component.ts","./src/app/components/filters/query-filter/query-filter.component.html","./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/hal/dm-services/query-form-dm.service.ts","./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/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/work-packages/work-package-authorization.service.ts","./src/app/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts","./src/app/modules/hal/resources/grid-widget-resource.ts","./src/app/modules/hal/services/hal-resource-notification.service.ts","./src/app/modules/hal/dm-services/membership-dm.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/modules/work_packages/routing/wp-split-view/wp-split-view.component.ts","./src/app/modules/work_packages/routing/wp-split-view/wp-split-view.html","./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/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/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/components/wp-card-view/event-handler/double-click-handler.ts","./src/app/modules/fields/edit/services/hal-resource-editing.service.ts","./src/app/globals/tree-menu.ts","./src/app/components/filters/filter-date-times-value/filter-date-times-value.component.ts","./src/app/components/filters/filter-date-times-value/filter-date-times-value.component.html","./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","./src/app/components/filters/filter-boolean-value/filter-boolean-value.component.ts","./src/app/components/filters/filter-boolean-value/filter-boolean-value.component.html","./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/hal/dm-services/user-dm.service.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-entry.component.ts","./src/app/components/wp-activity/activity-entry.component.html","./src/app/components/modals/editor/macro-wp-button-modal/wp-button-macro.modal.ts","./src/app/components/modals/editor/macro-wp-button-modal/wp-button-macro.modal.html","./src/app/components/table-pagination/pagination-instance.ts","./src/app/components/wp-table/wp-table-configuration.ts","./src/app/components/states/state-cache.service.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/hal/dm-services/help-text-dm.service.ts","./src/app/components/wp-table/configuration-modal/tabs/display-settings-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/display-settings-tab.component.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/modules/fields/edit/edit-field.component.ts","./src/app/components/wp-single-view-tabs/watchers-tab/wp-watchers.service.ts","./src/app/modules/fields/edit/field-types/formattable-edit-field.component.ts","./src/app/components/modals/save-modal/save-query.modal.ts","./src/app/components/modals/save-modal/save-query.modal.html","./src/app/modules/hal/dm-services/version-dm.service.ts","./src/app/components/wp-copy/wp-copy-full-view.component.ts","./src/app/components/wp-new/wp-new-full-view.html","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service.ts","./src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service.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/wp-timeline.today-line.ts","./src/app/components/wp-table/timeline/global-elements/timeline-static-element.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/modules/work_packages/openproject-work-packages.module.ts","./src/app/components/wp-list/wp-list-checksum.service.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/card-view-handler-registry.ts","./src/app/components/wp-table/external-configuration/external-query-configuration.component.ts","./src/app/modules/boards/board/board-cache.service.ts","./src/app/components/wp-activity/user/user-activity.component.html","./src/app/components/wp-activity/user/user-activity.component.ts","./src/app/components/wp-table/sort-header/sort-header.directive.ts","./src/app/components/wp-table/sort-header/sort-header.directive.html","./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/hal/dm-services/configuration-dm.service.ts","./src/app/components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component.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/modules/common/help-texts/attribute-help-text.modal.ts","./src/app/modules/common/help-texts/help-text.modal.html","./src/app/components/wp-table/configuration-modal/tabs/sort-by-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/sort-by-tab.component.html","./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/modules/hal/dm-services/project-dm.service.ts","./src/app/components/work-packages/wp-subject/wp-subject.component.ts","./src/app/components/work-packages/wp-subject/wp-subject.html","./src/app/components/wp-new/wp-new-split-view.component.ts","./src/app/modules/work_packages/query-space/isolated-graph-query-space.ts","./src/app/modules/work_packages/query-space/wp-isolated-graph-query-space.directive.ts","./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/filters/filter-integer-value/filter-integer-value.component.ts","./src/app/components/filters/filter-integer-value/filter-integer-value.component.html","./src/app/components/work-packages/wp-single-view/wp-single-view.component.ts","./src/app/components/work-packages/wp-single-view/wp-single-view.html","./src/app/init-globals.ts","./src/app/modules/common/browser/browser-detector.service.ts","./src/app/components/wp-table/configuration-modal/tabs/filters-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/filters-tab.component.html","./src/app/modules/common/notifications/notification.component.ts","./src/app/modules/common/notifications/notification.component.html","./src/vendor/i18n.js-exposed","./src/app/components/wp-fast-table/builders/ui-state-link-builder.ts","./src/app/modules/hal/dm-services/abstract-dm.service.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/datepicker.ts","./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/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/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/ckeditor/ckeditor-augmented-textarea.component.ts","./src/app/ckeditor/ckeditor-augmented-textarea.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/overview-tab/overview-tab.component.ts","./src/app/components/wp-single-view-tabs/overview-tab/overview-tab.html","./src/app/components/wp-single-view-tabs/wp-linked-resource-cache.service.ts","./src/app/components/wp-table/configuration-modal/tabs/timelines-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/timelines-tab.component.html","./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/modules/work_packages/routing/wp-view-page/wp-view-page.component.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/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/hal/dm-services/time-entry-dm.service.ts","./src/app/modules/attachments/attachments.component.ts","./src/app/modules/attachments/attachments.html","./src/app/modules/common/draggable-autocomplete/draggable-autocomplete.component.ts","./src/app/modules/common/draggable-autocomplete/draggable-autocomplete.component.html","./src/app/modules/bim/ifc_models/xeokit/xeokit-server.js","./src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts","./src/app/components/datetime/timezone.service.ts","./src/app/components/modals/share-modal/query-sharing-form.component.ts","./src/app/components/modals/share-modal/query-sharing-form.html","./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-custom-actions/wp-custom-actions/wp-custom-action.component.ts","./src/app/components/wp-custom-actions/wp-custom-actions/wp-custom-action.component.html","./src/app/components/wp-new/wp-new-full-view.component.ts","./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/components/wp-custom-actions/wp-custom-actions.component.ts","./src/app/components/wp-custom-actions/wp-custom-actions.component.html","./src/app/helpers/op-icon-builder.ts","./src/app/components/op-context-menu/op-context-menu.component.ts","./src/app/components/op-context-menu/op-context-menu.html","./src/app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service.ts","./src/app/components/wp-table/table-pagination/wp-table-pagination.component.ts","./src/app/components/table-pagination/table-pagination.component.html","./src/app/modules/common/notifications/upload-progress.component.ts","./src/app/components/wp-relations/wp-relations.component.ts","./src/app/components/wp-relations/wp-relations.template.html","./src/app/components/wp-details/wp-details-toolbar.component.ts","./src/app/components/wp-details/wp-details-toolbar.html","./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/components/table-pagination/table-pagination.component.ts","./src/app/modules/bim/bcf/helper/viewpoints.service.ts","./src/app/modules/common/autocomplete/version-autocompleter.component.ts","./src/app/modules/hal/dm-services/grid-dm.service.ts","./src/app/components/wp-fast-table/builders/modes/grouped/grouped-classes.constants.ts","./src/app/components/user/user-cache.service.ts","./src/app/modules/common/help-texts/attribute-help-text.service.ts","./src/app/components/wp-table/external-configuration/external-query-configuration.service.ts","./src/app/components/wp-activity/revision/revision-activity.component.ts","./src/app/components/wp-activity/revision/revision-activity.component.html","./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/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/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/highlightable-display-field.module.ts","./src/app/modules/fields/display/field-types/date-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/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/components/wp-fast-table/builders/cell-builder.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/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-single-view-tabs/relations-tab/relations-tab.component.ts","./src/app/components/wp-single-view-tabs/relations-tab/relations-tab.html","./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/modules/hal/resources/time-entry-resource.ts","./src/app/helpers/angular/inject-field.decorator.ts","./src/app/components/wp-table/configuration-modal/tabs/columns-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/columns-tab.component.html","./src/app/modules/work_packages/routing/wp-full-view/wp-full-view.component.ts","./src/app/modules/work_packages/routing/wp-full-view/wp-full-view.html","./src/app/modules/work_packages/routing/wp-view-base/work-package-single-view.base.ts","./src/app/components/wp-relations/wp-relation-row/wp-relation-row.component.ts","./src/app/components/wp-relations/wp-relation-row/wp-relation-row.template.html","./src/app/modules/boards/board/board-list/board-lists.service.ts","./src/app/components/wp-table/embedded/embedded-tables-macro.component.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/components/op-context-menu/handlers/wp-status-dropdown-menu.directive.ts","./src/app/modules/common/autocomplete/create-autocompleter.component.ts","./src/app/globals/augmenting/modal-wrapper.augment.service.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/components/modals/share-modal/query-sharing.modal.ts","./src/app/components/modals/share-modal/query-sharing.modal.html","./src/app/modules/common/openproject-common.module.ts","./src/app/components/user/user-avatar/user-avatar.component.ts","./src/app/components/wp-relations/wp-relations.service.ts","./src/app/components/work-packages/work-package-cache.service.ts","./src/app/modules/hal/resources/grid-resource.ts","./src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.component.ts","./src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.html","./src/app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component.ts","./src/app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component.html","./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/globals/global-listeners/request-for-confirmation.ts","./src/app/globals/global-listeners.ts","./src/app/globals/global-listeners/augmented-date-picker.ts","./src/app/globals/global-listeners/link-hijacking.ts","./src/app/globals/global-listeners/refresh-on-form-changes.ts","./src/app/globals/global-listeners/top-menu-scroll.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/globals/openproject.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/bcf-viewer-bridge/revit-bridge.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/bcf/openproject-bcf.module.ts","./src/app/misc/datepicker-defaults.js","./src/app/components/wp-custom-actions/date-action/custom-date-action-admin.component.ts","./src/app/components/wp-custom-actions/date-action/custom-date-action-admin.html","./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/bim/ifc_models/toolbar/import-export-bcf/bcf-import-button.component.ts","./src/app/modules/time_entries/shared/modal/base.modal.ts","./src/app/modules/hal/resources/user-resource.ts","./src/app/modules/boards/boards-sidebar/boards-menu.component.ts","./src/app/modules/boards/boards-sidebar/boards-menu.component.html","./src/app/components/wp-card-view/event-handler/right-click-handler.ts","./src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts","./src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html","./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/modules/bim/ifc_models/toolbar/import-export-bcf/bcf-export-button.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/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/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-costs/wp-display/costs-by-type-display-field.module.ts","./src/app/modules/plugins/linked/openproject-costs/wp-display/currency-display-field.module.ts","./src/app/modules/plugins/linked/openproject-costs/hal/resources/budget-resource.ts","./src/app/modules/plugins/linked/openproject-costs/augment/cost-subform.augment.service.ts","./src/app/modules/plugins/linked/openproject-costs/augment/planned-costs-form.ts","./src/app/modules/plugins/linked/openproject-costs/augment/cost-budget-subform.augment.service.ts","./src/app/modules/plugins/linked/openproject-costs/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/components/time-entries/time-entry-cache.service.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/overview/wp-overview-graph.template.html","./src/app/modules/work-package-graphs/overview/wp-overview-graph.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/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-changeset.ts","./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/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/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/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/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/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/modules/global_search/global-search-work-packages-entry.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/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/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/global-dynamic-components.const.ts","./src/app/modules/members/members.module.ts","./src/app/components/enterprise/openproject-enterprise.module.ts","./src/app/angular4-modules.ts","./src/main.ts","./src/app/sentry/sentry-reporter.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts"],"names":["notificationsContainerSelector","NotificationsContainerComponent","notificationsService","cdRef","super","stack","this","current","values$","pipe","untilDestroyed","subscribe","detectChanges","WorkPackageViewDropdownMenuDirective","elementRef","opContextMenu","I18n","wpDisplayRepresentationService","wpTableTimeline","evt","buildItems","show","items","contextMenuId","push","linkText","t","icon","onClick","setDisplayRepresentation","isVisible","toggle","WorkPackageChangeset","key","val","setValue","updateForm","payload","description","applyChanges","pristineResource","isNew","setNewDefaultFor","WorkPackageStatesInitializationService","states","querySpace","wpTableColumns","wpTableGroupBy","wpTableSortBy","wpTableFilters","wpTableSum","wpTableHierarchies","wpTableHighlighting","wpTableRelationColumns","wpTablePagination","wpTableOrder","wpTableAdditionalElements","wpCacheService","wpListChecksumService","authorisationService","wpDisplayRepresentation","query","results","clearStates","putValue","initializeFromQuery","updateQuerySpace","updateChecksum","form","schema","_","each","filtersSchemas","elements","schemas","get","$href","initializeFilters","queryForm","queries","columns","allowedValues","sortBy","groupBy","displayRepresentation","additionalRequiredWorkPackages","clear","tableRendered","href","initModelAuth","$links","forEach","wp","updateWorkPackage","groups","initialize","initialized","updateIfDifferent","value","applyToQuery","reason","UserLinkComponent","user","showUserPath","name","WorkPackageReplacementLabelComponent","wpeditForm","$element","jQuery","nativeElement","target","closest","length","field","fields","fieldName","handleUserActivate","activate","AttachmentCollectionResource","source","$initialize","HalEventsService","_events","events$","asObservable","resourceType","debounceTimeInMs","event","acc","curr","concat","resourceReference","id","_type","next","AccessibleByKeyboardComponent","execute","isDisabled","emit","handleClick","contextMenuTdClassName","contextMenuSpanClassName","contextMenuLinkClassName","contextColumnIcon","OpTableAction","injector","workPackage","makeSplitViewRoutes","baseRoute","menuItemClass","showComponent","newComponent","url","redirectTo","reloadOnSearch","data","bodyClasses","menuItem","partition","newRoute","views","component","parent","allowMovingInEditMode","BcfPathHelperService","pathHelper","projectIdentifier","projectPath","filters","viewpoint","relationGroupClass","workPackageId","workPackageTable","column","emptyRelationCell","buildCell","from","relation","type","denormalized","to","workPackages","targetId","row","createEmptyRelationRow","tr","buildEmptyRow","identifier","relationClassIdentifier","document","createElement","dataset","classList","add","jRow","columnId","typeLabel","reverseRelationType","relationLabel","textContent","createTextNode","find","empty","append","cell","table","tablePass","relationRowBuilder","isApplicable","clone","renderedOrder","position","fromId","state","wpRelations","hasValue","size","relationsToExtendFor","relationRow","buildEmptyRelationRow","additionalClasses","appendRelationLabel","spliceRow","classIdentifier","belongsTo","renderType","hidden","relationType","renderedRow","oldRow","newRow","refreshRow","hasRelationColumns","timelineBody","createDocumentFragment","timelineBuilder","wpId","secondary","build","appendChild","highlightAttribute","mode","window","getComputedStyle","body","property","tableBody","children","backgroundClass","isInline","dragActionRegistry","actionService","td","canPickup","span","dragDropHandleBuilder","configuration","dragAndDropEnabled","withLoadedPositions","then","positions","handle","element","replaceChild","firstElementChild","rowBuilder","prepare","doRender","postRender","highlighting","render","relations","dragDropHandle","timeline","replacement","refreshRelationRow","replaceWith","map","selector","renderedInfo","last","after","index","splice","renderPlaceholderRow","placeholderRow","classIdentifer","relationCellTdClassName","relationCellIndicatorClassName","RelationCellbuilder","expanded","getExpandFor","relationState","relationsForColumn","indicator","renderIndicator","badge","renderBadge","setAttribute","ActivityLinkComponent","activityHtmlId","activityNo","activityLabel","QueryDmService","halResourceService","http","UrlParamsHelper","QueryFilters","PayloadDm","queryData","queryId","path","api","v3","toString","withOptionalProject","default","stream","toPromise","undefined","pagination","buildV3GetQueryFromQueryResource","ids","timestamp","operator","values","filter","n","updatedAt","work_packages","JSON","stringify","extractPayload","patch","post","delete","starred","unstar","star","listParams","list","mapSchemasIntoFilters","extract","OpContextMenuLocalsToken","RestrictedWpTableConfigurationService","locals","disabledTabs","_tabs","el","disableBecause","LinkHandling","isClickedWithModifier","modifier","ctrlKey","shiftKey","metaKey","middleButton","button","DoubleClickOrTapDirective","stopEventPropagation","eventHandler","tapCount","eventStopReturnCode","preventDefault","stopPropagation","RelationsDmService","collection","workPackageIds","validIds","test","Promise","resolve","toPath","toJson","QueryFiltersService","available","$embedded","allowedFilterValue","getFilterSchema","WorkPackageCreateSettingsMenuDirective","halEditing","changeFor","getForm","loadedForm","positionArgs","assign","my","at","configureFormLink","configureForm","queryCustomFields","customFields","splitViewRoute","WorkPackageViewHighlightingService","Banners","eeShowBanners","selectedAttributes","attr","lastUpdatedState","getValueOr","filteredValue","update","highlight","highlightingMode","highlightedAttributes","isEqual","isEmpty","conditional","WorkPackageCreateButtonComponent","$state","currentProject","transition","text","createWithDropdown","createButton","explanation","observeUntil","allowed","allowedWhen","combined","module","permission","split","can","updateDisabledState","transitionUnregisterFn","onSuccess","bind","ngOnDestroy","disabled","includes","WorkPackageCommentFieldHandler","handler","active","inEditMode","inFlight","onDestroy","change","withText","raw","writable","required","hasDefault","commentValue","deactivate","reset","focus","complete","trigger","querySelector","onlyCancel","WorkPackageEditActionsBarComponent","editForm","onSave","onCancel","_saving","save","cancel","saving","submit","catch","AuthoringComponent","PathHelper","timezoneService","createdOnTime","parseDatetime","createdOn","timeago","fromNow","time","format","userLink","userPath","author","idFromLink","projectActivityPath","project","WorkPackageBreadcrumbComponent","hierarchy","inputActive","ancestors","hierarchyCount","AttachmentsUploadComponent","ConfigurationService","draggingOver","uploadLabel","dropFiles","dropFilesHint","foldersWarning","maxFileSize","maximumAttachmentFileSize","filePicker","click","dataTransfer","dropEffect","dfFiles","files","i","uploadFiles","containsFiles","Array","types","contains","indexOf","countBefore","filterFolders","resource","uploadAttachments","addNotice","file","console","warn","EditFieldControlsComponent","basePath","segment","resourceClass","params","headers","config","encoder","fromObject","withCredentials","responseType","_request","method","request","response","deserialize","catchError","error","throwError","parse","BcfProjectResource","BcfTopicAuthorizationMap","String","BcfTopicResource","preserveNull","deserializer","moment","serializer","toISOString","bcfTopicService","Error","comments","viewpoints","BcfExtensionResource","bcfExtensionService","bcfProjectService","topics","extensions","bcfApiVersion","appBasePath","bcfApiBase","projects","startsWith","parts","replace","pathOrId","UserAvatarRendererService","colors","container","users","renderName","multiLine","avatar","sep","classes","userInitials","getInitials","colorCode","toHsl","fallback","className","style","background","image","Image","src","title","alt","onload","characters","lastSpace","lastIndexOf","toUpperCase","join","AngularTrackingHelpers","compareByAttribute","attribute","a","b","compareByHref","halHref","_index","item","compareByName","trackByName","trackByHref","trackByProperty","prop","trackByHrefAndProperty","propertyName","trackByTrackingIdentifier","compareByHrefOrString","NewestActivityOnOverviewComponent","latestActivityInfo","ngOnInit","activities","updateActivities","latestActivities","visible","reverse","unfilteredActivities","slice","info","startIndex","WorkPackageCopySplitViewComponent","WorkPackageRelationsHierarchyComponent","wpRelationsHierarchyService","showEditForm","parentHeadline","childrenHeadline","workPackagePath","canModifyHierarchy","changeParent","canAddRelation","addRelation","childrenQueryProps","showHierarchies","loadWorkPackage","toLoad","parentId","require","requireAll","timelineElementCssClass","timelineBackgroundElementClass","timelineGridElementCssClass","timelineMarkerSelectionStartClass","timelineHeaderCSSClass","timelineHeaderSelector","TimelineViewParametersSettings","zoomLevel","zoomLevelOrder","getPixelPerDayForZoomLevel","requiredPixelMarginLeft","TimelineViewParameters","now","hour","minute","seconds","dateDisplayStart","dateDisplayEnd","settings","activeSelectionMode","selectionModeStart","maxSteps","pixelPerDay","diff","Math","ceil","calculatePositionValueForDayCountingPx","viewParams","days","calculatePositionValueForDayCount","getTimeSlicesForHeader","vp","unit","startView","endView","inViewport","rest","startOf","end","endOf","isBefore","sliceStart","sliceEnd","viewport","visibleViewportAtCalculationTime","isSameOrAfter","isSameOrBefore","firstRest","lastRest","pop","inViewportAndBoundaries","e","isNil","calculateDaySpan","visibleWorkPackages","loadedWorkPackages","viewParameters","earliest","latest","start","startDate","date","due","dueDate","isAfter","OPContextMenuService","componentFactoryResolver","FocusHelper","appRef","$transitions","isOpening","hostElement","portalHostElement","bodyPortalHost","onStart","close","on","which","ESCAPE","that","getElementById","addEventListener","menu","portal","injectorFor","attach","display","setTimeout","reposition","onOpen","activeMenu","detach","onClose","css","injectorTokens","WeakMap","service","set","WorkPackageCreateService","hooks","workPackageDmService","halEvents","newWorkPackageCreatedSubject","comittedChanges","commit","wasNew","newWorkPackageCreated","changes$","changeset","eventType","getEmptyForm","fromCreateForm","typedCreateForm","createHalResourceOfType","$plain","initializeNewResource","edit","call","copyFrom","$source","emptyCreateForm","stopEditing","changePromise","continueExistingEdit","createNewWithDefaults","updateValue","clearSome","changeType","projectedResource","hasChanges","typeEmpty","typeMatches","createNewTypedWorkPackage","createNewWorkPackage","except","applyDefaults","applyDefaultsFromFilters","RowsBuilder","cssClassCustomOption","DisplayField","context","activeChange","texts","placeholder","constructor","isFormattable","valueString","displayText","options","emptyDiv","ActivityPanelBaseController","$transition","wpActivity","visibleActivities","onlyComments","commentsOnly","showAll","isReversed","togglerText","observe","getVisibleActivities","showToggler","shouldShowToggler","count_all","count_with_comments","getActivitiesWithComments","activity","rowId","relationRowClass","locateTableRow","locateTableRowByIdentifier","locatePredecessorBySelector","previous","previousElementSibling","matches","scrollTableRowIntoView","scrollParent","containerTop","scrollTop","containerBottom","height","elemTop","offsetTop","elemBottom","createLocalInjector","fieldHandler","AbstractDateTimeValueController","remove","isValidISODateTime","isValidISODate","d","parseISODatetime","formattedISODateTime","formattedISODate","lowerBoundary","upperBoundary","hours","minutes","rendered","additionalParents","deferred","parentsWithVisibleChildren","hierarchies","originalRowIndex","object","ancestor","originalRows","deferInsertion","buildWithHierarchy","buildEmpty","markRendered","renderAllDeferredChildren","ancestorChain","inTable","newElements","child","uniqBy","insertUnderParent","getOrBuildRow","ancestorGroups","ancestorRow","buildAncestorRow","insertAtExistingHierarchy","previousAncestor","isAncestor","buildRenderInfo","hierarchyRoot","hierarchyGroup","ancestorClasses","ancestorRowData","_table","isEnabled","builder","cellBuilder","resourceSubscription","requireAndStream","unsubscribe","rowContainer","first","errors","waitForContainer","findCell","addClass","width","parseInt","editingPortalService","create","findContainer","refresh","removeClass","focusElement","addColumn","tableAndTimelineContainer","reject","interval","setInterval","clearInterval","forms","destroy","typedState","existing","scrollContainer","tbody","timelineController","builders","lastRenderPass","editing","findIndex","renderedRows","rows","buildIndex","redrawTableAndTimeline","renderPass","performRenderPass","requestAnimationFrame","innerHTML","result","pass","insert","buildRows","WorkPackageDmService","force","getAllPaginated","workPackagesFormPath","typeId","_links","DynamicContentModal","closeOnOutsideClick","modalClassName","modalBody","closeMe","off","CKEditorSetupService","wrapper","initialData","editor","OPConstrainedEditor","OPClassicEditor","toolbarWrapper","contentWrapper","contentLanguage","rtl","createCustomized","openProject","createConfig","language","content","ui","view","toolbar","setData","cb","getData","trim","macros","helpURL","textFormattingHelp","pluginContext","OpenProject","EditFieldService","wpQuerySelectSelector","WorkPackageQuerySelectDropdownComponent","ref","QueryDm","CurrentProject","loadingIndicator","wpStaticQueries","mainMenuService","toggleService","loading","noResults","search","label","scope_default","scope_starred","scope_global","scope_private","no_results","hiddenCategories","reportsBodySelector","queryResultsContainer","_queryResultsContainerElement","getAttribute","onActivate","initializeAutocomplete","addClickHandler","unregisterTransitionListener","searchInput","_wpQueryMenuSearchInput","buttonArrowLeft","setupAutoCompletion","updateMenuOnChanges","loadQueries","combinedQueries","query_props","all","sortQueries","categorized","public","private","auto_id","category","flatten","sortByLabel","sort","toLowerCase","localeCompare","loadingPromise","listNonHidden","querycomplete","transformQueries","thisCategory","expandCollapseCategory","promise","input","defineJQueryQueryComplete","delay","select","ul","selected","autocompleteUi","is","_event","sourceEvent","originalEvent","appendTo","autoFocus","minLength","thisComponent","widget","autocomplete","_create","_super","_search","_renderItem","link","buildQueryItemUrl","li","setInitialHighlighting","_renderMenu","currentCategory","option","labelFunction","_renderItemData","scrollIntoView","behavior","block","currentLi","getQueryParams","currentId","query_id","currentProps","onWorkPackagesPage","onWorkPackagesReportPage","hasClass","currentIdSelected","matchesStaticQueryProps","allOpen","onSummary","changes","not","toggleClass","go","reload","closeWhenOnMobile","static_link","highlightBySelector","ENTER","clickedWithModifier","isStatic","stopImmediatePropagation","location","loadQuery","highlightSelected","clickedCategory","selectorTimelineSide","getPlattformAgnosticScrollAmount","originalValue","delta","syncWheelEvent","jev","elementTable","elementTimeline","scrollTarget","ev","deltaX","deltaY","x","y","getXandYScrollDeltas","scrollLeft","createScrollSync","elTable","elTimeline","timelineVisible","syncedLeft","syncedRight","halNotification","destroyImmediately","removeAttachment","dragHint","destroyConfirmation","removeFile","arg","downloadPath","previewElement","draggableHTML","outerHTML","setDragImage","isImage","fileName","attachmentDownloadPath","attachment","ext","imageFileExtensions","customName","$event","confirm","setDragData","attachments","deletedAttachments","updateAttachments","setupResourceUpdateListener","setupAttachmentDeletionCallback","forResource","newResource","$formElement","newAttachments","attachmentsBackend","destroyRemovedAttachments","attachmentsUpdatable","updateElements","WorkPackageRelationsCreateComponent","notificationService","showRelationsCreateForm","selectedRelationType","DEFAULT","relationTypes","LOCALIZED_RELATION_TYPES","abort","addNewRelation","selectedWpId","createCommonRelation","addCommonRelation","relatedWorkPackage","showSave","toggleRelationsCreateForm","err","handleRawError","FilterDateTimeValueComponent","shouldFocus","filterChanged","isoDateParser","CardClickHandler","card","handleWorkPackage","setSelection","openFullViewOnMobile","deviceService","isMobile","wpCardView","findRenderedCard","wpTableSelection","setMultiSelectionFrom","renderedCards","toggleRow","wpTableFocus","updateFocus","tableActionsService","tableRowClassName","commonRowClassName","relationCellBuilder","contextLinkBuilder","augmentedColumns","buildAugmentedColumns","getColumns","unshift","actionsColumnEnabled","columnMenuEnabled","createEmptyRow","colSpan","cells","newCells","oldTd","isColumnBeingEdited","prepend","activeFields","changedAttributes","oldCell","isSelected","cancelButton","buildCancelButton","wpCreate","wpInlineCreate","canAdd","canReference","buttonTexts","hasReferenceClass","registerCreationCallback","refreshOnColumnChanges","registerCancelHandler","resetRow","updates$","isActive","onNewWorkPackage","currentWorkPackage","__initialized_at","isEmbedded","newInlineWorkPackageCreated","cancelCreation","removeWorkPackageRow","showRow","addWorkPackageRow","referenceComponentClass","referenceClass","createOrContinueWorkPackage","editingSubscription","changesetUpdates$","overriddenSchema","insertRow","workPackageEditForm","renderInlineCreateRow","activateMissingFields","hideRow","rowElement","startEditing","buildNew","columnCount","PayloadDmService","nonLinkProperties","hasOwnProperty","isArray","currentSchema","WorkPackageViewSortByService","pristineState","comparer","wasManuallySorted","isManuallySorted","isManualSortingMode","candidate","criteria","findAvailableDirection","direction","newValue","manualSortObject","persisted","availableState","endsWith","filtersChanged","QueryFiltersComponent","wpFiltersService","bannerService","showCloseFilter","remainingFilters","focusElementIndex","open_filter","label_filter_add","close_filter","upsale_for_more","upsale_link","close_form","selected_filter_list","button_delete","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","dropdownPanel","_updatePosition","EditFormComponent","editFormRouting","initializeEditMode","skippedFields","onSavedEmitter","registeredFields","confirmText","requiresConfirmation","warnOnLeavingUnsaved","unregisterListener","onBefore","blockedTransition","editMode","waitForField","ctrl","setActive","editContainer","savedResource","isInitial","closeEditFields","hasActiveFields","keys","skipField","activateOnForm","changed","FilterDateValueComponent","isValid","parseDate","parser","uniqueEmbeddedTableName","Date","initialLoadingIndicator","renderTable","showTablePagination","providedConfiguration","queryProps","projectContext","wpStatesInitialization","urlParamsHelper","tableVisible","firstPage","paginationObject","offset","loadResults","loadingIndicatorService","tableActions","externalHeight","onError","onQueryLoaded","loadedQuery","ngAfterViewInit","setActions","page","perPage","distinctUntilChanged","withLatestFrom","initializeStates","onUpdated","valuesPromise","opModalService","onDataUpdated","withFilters","loadForm","take","total","count","setLoaded","compactTableStyle","formPromise","QueryFormDm","load","updateStatesFromForm","pageSize","queryProjectScope","message","EditFormPortalComponent","editField","onEditFieldReady","editFieldHandler","schemaInput","changeInput","componentClass","getSpecificClassFor","fieldInjector","FocusHelperService","minimumOffsetForNewSwitchInMs","lastFocusSwitch","lastPriority","allowFocusSwitch","priority","checkTimeout","throttleAndCheckIfAllowedFocusChangeBasedOnTimeout","focusser","focusable","FOCUSABLE_SELECTORS","getFocusableElement","$focusable","checkIfAllowedFocusChange","WorkPackageViewHierarchyIdentationService","wpViewHierarchies","wpRelationHierarchy","isList","applicable","renderedWorkPackageIds","ancestorIds","ancestorCount","lastAncestor","canIndent","predecessorId","newParentId","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","fieldSchema","isAttributeEditable","noWarnings","positionOffset","getPosition","$onUserActivate","startDragOverActivation","activateIfEditable","WorkPackageCardDragAndDropService","reorderService","dragService","componentRef","cardView","dragContainer","scrollContainers","moves","canDragOutOf","accepts","dragInto","onMoved","toIndex","newOrder","move","currentOrder","updateOrder","onRemoved","onAdded","addWorkPackageToQuery","parentElement","removeChild","_workPackages","activeInlineCreateWp","existingNewWp","o","uniq","workPackageAddedHandler","removeCard","DomHelpers","setBodyCursor","cursor","setProperty","dependencies","validationErrors","halInitializer","errorIdentifier","isValidationError","_dependencies","dependency","self","definesAllowedValues","staticSchema","dependentSchema","forValue","resultingSchema","merge","idPart","decodeURIComponent","WikiPageResource","MeetingContentResource","PostResource","statuses","schemaCacheService","without","$linkableKeys","halResourceDefaultConfig","WorkPackage","cls","attrTypes","status","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","TypeDmService","typeUrl","root","internal_error","errorMessages","ErrorReporter","captureException","captureMessage","handleError","OpenprojectHalModule","provide","useClass","multi","useFactory","registerResource","deps","OpTypesContextMenuDirective","browserDetector","stateName","ariaLabel","class","inlineClass","ConfirmDialogModal","confirmed","button_continue","button_cancel","close_popup","dangerHighlighting","defaultTo","passedData","closeOnEscape","closeByEscape","closeByDocument","showClose","defaults","confirmAndClose","OpenprojectAccessibilityModule","NoResultsComponent","setHostClass","groupClassNameFor","group","collapse","expand","colspan","togglerIconClass","collapsed","escape","headerBuilder","currentGroup","nextGroup","matchingGroup","groupClass","buildGroupRow","appendNonWorkPackageRow","buildSingleRow","matchesMultiValue","valueLink","l","joinedOrderedHrefs","objects","isEqualWith","appendRow","collapsedGroups","getGroupData","groupIndex","parentNode","affected","AbstractFieldService","attributeType","fieldType","defaultFieldType","getClassFor","fieldClass","attributes","addFieldType","configurationDm","loadConfiguration","userPreference","timezone","systemPreference","startOfWeekPresent","locale","firstDayOfWeek","pref","OpContextMenuHandler","afterFocusOn","openerEvent","of","collision","DragAndDropHelpers","reinsert","sibling","insertBefore","RootDmService","setExpandFor","additionalPositionArgs","action","startAddRelationPredecessor","startAddRelationFollower","wpViewIndentation","indent","outdent","triggerContextMenuAction","rowSelector","openContextMenu","contextMenuEnabled","keyCode","F10","altKey","SELECTOR","findRenderedRow","groupIdentifier","parents","collapsedState","t0","performance","refreshExpansionState","t1","blur","keepTab","takeUntil","stopAllSubscriptions","redrawTable","lastValue","renderHierarchyState","classNames","match","isCollapsed","orderedWorkPackages","initialSetup","observeChange","changedId","refreshRows","ifShouldFocus","selection$","renderSelectionState","registerSelectAllListener","registerDeselectAllListener","live$","renderVisibility","inlineCreateService","updateRenderedOrder","rowIndex","findRowIndex","handleDrop","onNewOrder","switchToManualSorting","wpListService","sourceIndex","onCloned","original","subjectWithId","maxWidth","onShadowInserted","isEdge","changeShadowElement","order","mappedOrder","currentRenderedOrder","renderedWorkPackages","getElementsByClassName","eventHandlers","stateTransformers","viewRef","attachTo","WpTableHoverSync","tableAndTimeline","lastHoveredElement","eventListener","handleHover","passive","removeEventListener","removeAllHoverClasses","parentTableRow","locateHoveredTableRow","parentTimelineRow","locateHoveredTimelineRow","removeOldAndAddNewHoverClass","hovered","extractWorkPackageId","tableRow","timelineRow","zone","limitedResults","configurationObject","tableSummary","tableSummaryHints","combineLatest","timelines","numTableColumns","scrollSyncUpdate","manualSortEnabled","wpTableHoverSync","controller","getTableAndTimelineElement","tableElement","$tableSide","$timelineSide","timelineCellClassName","TimelineRowBuilder","rowClasses","WorkPackageCommentFieldComponent","isBusy","rawValue","WorkPackageWatchersCountComponent","wpWatcherService","watchers","EditFormRoutingService","QueryFilterInstanceResource","memoizedCurrentSchemas","$copy","isValueRequired","operatorSymbol","availableOperators","BoardActionsRegistryService","mapping","localizedName","WorkPackageService","successful_delete","defaultHandling","workPackagesBulkDeletePath","addSuccess","urlParams","buildQueryString","UntilDestroyedMixin","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","IconTriggeredContextMenuComponent","menuItems","additional","WorkPackageViewGroupByService","cur","environment","production","QueryResource","WorkPackageRelationsGroupComponent","onToggleGroupBy","groupByType","groupByRelation","groupByWorkPackageType","toggleElement","WorkPackageDetailsViewButtonComponent","transitions","accessKey","activeState","listState","iconClass","activateLabel","deactivateLabel","transitionListener","openListView","openDetailsView","extend","focusedWorkPackage","currentDetailsState","performAction","HalLink","requestMethod","templated","templateValues","regexp","RegExp","$callable","linkFunc","$fetch","Board","grid","updateImmediately","isAction","isFree","isNewWidget","widgets","createdAt","startColumn","actionAttribute","ContainHelpers","insideOrSelf","within","whenOutside","callback","activeElement","collapsedGroupClass","ancestorId","hierarchyGroupClass","hierarchyRootClass","ancestorClassIdentifier","ExternalRelationQueryConfigurationService","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","resetInputField","onEmptyError","emitSave","focusInputOnError","WorkPackageEmbeddedTableEntryComponent","getInputsFromData","attributeHelpTextSelector","AttributeHelpTextComponent","helpTextDm","attributeHelpTexts","exists","open_dialog","helpTextId","attributeScope","additionalLabel","helpText","BoardDmService","GridDm","boardPath","one","board","fetchSchema","projectBoardsPath","createGrid","createForm","createHalResource","i18n","resourceChanged","editableName","widgetIdentifier","defaultValue","setChangesetOptions","Object","NewsDmService","news","GonService","gon","BackButtonComponent","backRoutingService","goBack","customBackMethod","linkClass","StatusDmService","WorkPackagesListService","wpListInvalidQueryService","queryRequests","queryLoading","q","ensurePerPageKnown","streamQueryRequest","queryParams","conditionallyLoadForm","decodedProps","getCurrentQueryProps","buildV3GetQueryFromJsonParams","handleQueryLoadingError","fromQueryParams","encodeQueryJsonParams","additionalParams","getPaginationInfo","currentQuery","loadResultsList","reloadQuery","loadDefaultQuery","addError","toggleStarred","currentForm","loadWithParams","findDefault","restoreQuery","isPerPageKnown","FilterDatesValueComponent","spacer","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","$","keyCodes","WorkPackageViewSumService","sums","updatesState","WorkPackageBreadcrumbParentComponent","wpRelationsHierarchy","onSwitch","isSaving","edit_parent","set_or_remove_parent","remove_parent","set_parent","newParent","WorkPackageSettingsButtonComponent","WpTableExportModal","httpClient","notifications","closePopup","exportPreparing","isLoading","downloadSwitched","exportOptions","buildExportOptions","safeUnsubscribe","representations","addColumnsToHref","performRequest","download","linkHeaderUrl","pollUntilDownload","subscription","getter","columnIds","removeSearch","addSearch","downloadHref","downloadLink","WorkPackageViewFiltersService","incomplete","loadCurrentFiltersSchemas","rawFilters","newFilters","filterOrId","availableSchemas","getFilter","mapper","every","isCompletelyDefined","cloneFilters","invisibleFilters","currentFilterResources","newState","isComplete","differenceBy","$load","WorkPackageViewRelationColumnsService","eachCallback","findById","relationColumnType","typeHref","RELATION_TO_TYPE","RELATION_OF_TYPE","nextState","WorkPackageInlineCreateService","referenceTarget","reference","newInlineWorkPackageReferenced","canCreateWorkPackages","OpSettingsMenuDirective","focusAfterClose","queryUpdate","formUpdate","allowAction","modelName","initialTab","cannot","allowQueryAction","create_new","allowFormAction","allowWorkPackageAction","divider","internalSortColumn","internalContextMenuColumn","CKEditorPreviewService","preview","refs","getEmbeddable","entry","matchedElements","resolveComponentFactory","attachView","hostView","changeDetectorRef","detachView","OpenprojectProjectsModule","ClickPositionMapper","setPosition","setSelectionRange","originalEvt","caretRangeFromPoint","clientX","clientY","startOffset","rangeParent","range","createRange","setStart","rangeOffset","Changeset","k","form$","cache","updatePristineResource","buildPayloadFromChanges","_pristineResource","Proxy","proxyGet","getSchemaName","isPristine","hasActivePromiseRequest","setNewDefaults","putFromPromiseIfPristine","lockVersion","plainPayload","getLinkedValue","cloneDeep","minimalPayload","isArrayType","links","valueExists","QueryOrderDmService","orderPath","wpIds","TabPortalOutlet","availableTabs","outletElement","activeTabs","currentTab","tab","instance","activateInstance","_getComponentRootNode","tabName","setAttachedHost","dispose","createComponent","rootNodes","WorkPackageIsolatedQuerySpaceDirective","useExisting","OpenProjectHeaderInterceptor","req","csrf_token","newHeaders","clonedRequest","HighlightColDirective","thead","siblings","currentTarget","highlightColBootstrap","usersAutocompleterSelector","UserAutocompleterComponent","userTracker","onChange","clearAfterSelection","allowEmpty","multiple","initialSelection","requests","searchTerm","getAvailableUsers","inputFilters","updateInputField","getElementsByName","setInitialSelection","filterInput","lastRequestedValue","input$","u","searchFilters","res","isNaN","onFocus","onModelChange","OpModalLocalsToken","OpModalService","opening","closeOnEscapeFunction","activeModal","withErrors","Subject","setErrors","setClickOffset","tagName","subject","handleUserSubmit","newErrors","isErrorenous","onSubmit","handleUserCancel","messages","previewPath","outlet","createDomOutlet","localInjector","attachComponentPortal","ExternalRelationQueryConfigurationComponent","useValue","DisplayFieldService","apply","SimpleResourceCollection","SimpleResource","toParams","WorkPackageViewColumnsService","isCurrentlyEqualTo","c","toApply","oldColumns","newColumns","relationColumns","isLast","mapped","setColumns","compact","fromIndex","moveColumn","newColumn","PROPERTY","revisions","available_watchers","available_projects","userId","me","availableProjects","projectId","available_assignees","versions","gridId","newsId","timeEntryId","apiV3Base","priorities","time_entries","memberships","help_texts","grids","base","term","idOnly","attachmentIdentifier","slug","staticBase","forumIdentifier","projectForumPath","messageIdentifier","projectsPath","projectWorkPackagesPath","usersPath","workPackagesPath","MainMenuNavigationService","navigationEvents$","names","toggler","targetLi","log","mainItems","wrap","elementId","wrapperElement","wrapMainItem","recreateToggler","activeRoot","navigateUp","unbind","wrapInner","_i","contents","parentURL","header","upLink","parentLink","before","DeviceService","mobileWidthTreshold","innerWidth","WorkPackageStatusButtonComponent","workPackageReadOnly","workPackageStatusBlocked","isReadonly","AuthorisationService","modelLinks","doModify","PlainRenderPass","Attachable","Base","addAttachment","pull","$isHal","max","updateState","uploads","finished","performUpload","notification","addAttachmentUpload","r","ErrorEvent","opFileUpload","uploadAndMapResponse","Field","WorkPackageRelationsAutocomplete","inputPlaceholder","additionalFilters","hiddenOverflowContainer","onSelected","onEmptySelected","searchInput$","appendToContainer","results$","queryString","autocompleteWorkPackages","ensureLoaded","availableRelationCandidates","filterCandidatesFor","onWorkPackageSelected","HalResource","$loaded","$halType","other","_name","_fieldName","$loadResource","$self","properties","OpIcon","iconTitle","ProjectCacheService","projectDmService","RelationResource","includeParentChild","includeParentchild","RELATION_TYPES","reverseType","renderEmpty","renderValues","div","percentLabel","avatarRenderer","renderMultiple","editableClassName","readOnlyClassName","displayClassName","fieldCache","renderFieldValue","setSpanAttributes","schemaName","getField","getText","getAriaLabel","getFieldForCurrentContext","isCustomMultiLinesField","isUserMultiLinesField","displayFieldService","getDefaultPlaceholder","titleContent","labelContent","getLabelContent","displayName","QueryFilterComponent","deactivateFilter","showValuesInput","onFilterUpdated","removeThisFilter","URLParamsEncoder","encodeURIComponent","VersionResource","WorkPackageCopyController","copying","copiedWorkPackageId","stateParams","copiedFromWorkPackageId","createCopyFrom","titleService","setFirstPart","sourceChangeset","copyWorkPackage","copyChangeset","ProgressDisplayField","roundedProgress","round","Number","WorkPackageActivityTabComponent","QueryFormDmService","optionalId","WorkPackageViewAdditionalElementsService","requireInvolvedRelations","requireHierarchyElements","loadAdditional","getInvolvedWorkPackages","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","top","bottom","scrollY","scrollX","amount","scrollTo","pageXOffset","pageYOffset","FilterToggledMultiselectValueComponent","RootDm","halSorting","_availableOptions","fetchAllowedValues","ngSelectInstance","castArray","_isEmpty","loadAllowedValues","availableOptions","loadingPromises","isUserResource","resources","addMeValue","currentUser","setValues","repositionDropdown","WorkPackageAuthorization","workPackageDetailsCopyPath","workPackageCopyPath","copyLink","allActions","allowedActions","validActions","isPermitted","linkForAction","HookService","opContextMenuService","authorization","permittedActions","getPermittedActions","timeEntryCreateService","actions","permittedActionsWithLinks","getPermittedPluginActions","indexBy","GridWidgetResource","endRow","startRow","endColumn","HalResourceNotificationService","isCreate","handleErrorResponse","errorBody","retrieveError","showGeneralError","createHalResourceOfClass","errorResource","showError","showApiErrorMessages","showCustomError","attributeName","details","i18nString","lookup","MembershipDmService","listRequest","availableProjectsUrl","OpContextMenuTrigger","open","Mousetrap","OpenprojectHalModuleHelpers","lazy","obj","setter","isObject","done","configurable","enumerable","defineProperty","ObservableArray","cloneHalResourceCollection","v","initializeHalProperties","halResource","asHalResource","loaded","_embedded","setupProperty","instanceName","sourceName","sourceObj","propName","setSource","$embeddableKeys","createLinkedResource","setEmbeddedAsProperties","KeepTabService","updateTabs","isCurrentState","currentShowTab","currentDetailsTab","lastActiveTab","currentShowState","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","WorkPackageSplitViewComponent","firstRoute","backRouting","observeWorkPackage","isFirstRoute","isSameID","workPackageI","setRowState","whenChanged","goToBaseState","initializeTexts","closeDetailsView","goTofullScreen","WorkPackageFilterByTextInputComponent","searchTermChanged","pristine$","currentSearchFilter","upstreamTerm","timestampOfLastValue","isValueOlderThan","findOperator","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","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","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","__webpack_require__","code","exports","CommentService","workPackageNotificationService","quoteEvents","comment","addComment","errorAndReject","WorkPackageRelationsCountComponent","relationCount","childrenCount","WorkPackageSingleCardComponent","showInfoButton","showStatusButton","showRemoveButton","draggable","orientation","shrinkOnMobile","onRemove","uiStateLinkClass","detailsView","cardHighlighting","attributeHighlighting","bcfSnapshotPath","bcfViewpoints","CardDblClickHandler","ChangesetStates","changesets","initializeMembers","ResourceChangesetCommit","saved","HalResourceEditingService","hook","stateGroup","buildRequestPayload","retainFrom","onSaved","multiState","newChangeset","hrefs","tree","selectedPage","FilterDateTimesValueComponent","begin","OpModalComponent","openingEvent","modalElement","MainMenuToggleService","elementMinWidth","defaultWidth","localStorageKey","localStorageStateKey","global","htmlNode","getElementsByTagName","mainMenu","hideElements","titleData","titleData$","changeData","changeData$","elementWidth","guardedLocalStorage","menuCollapsed","closeMenu","setWidth","saveWidth","offsetWidth","showNavigation","savedWidth","widthToSave","maxMenuWidth","snapBack","setToggleTitle","toggleClassHidden","changeEvent","Event","toggleTitle","groupByProperty","groupName","groupedRowClassName","FilterBooleanValueComponent","true","false","webpackAsyncContext","PERMITTED_CONTEXT_MENU_ACTIONS","UserDmService","hint","button_save","selectedPageInput","applyAndClose","_language","debouncedLanguageLoader","debounce","loadLanguageAsMode","language_hint","languageClass","codeMirrorInstance","getValue","lang","imported","CodeMirror","fromTextArea","codeMirrorPane","lineNumbers","smartIndent","autofocus","updateCodeMirrorMode","newLanguage","setOption","updateLanguage","includeParent","include_parent","selectedIncludeParent","updateIncludeParent","pageValue","ActivityEntryComponent","activityType","WpButtonMacroModal","none","selected_type","button_style","button_style_hint","selectedType","buttonStyle","availableTypes","typeSelect","PaginationInstance","limit","min","WorkPackageTableConfiguration","providedConfig","inlineCreateEnabled","hierarchyToggleEnabled","isCardView","filtersExpanded","showFilterButton","filterButtonText","StateCacheService","holdValuesForSeconds","cacheDurationInMs","stale","clearAndPutFromPromise","idsToRequest","loadAll","WpDestroyModal","busy","childrenDeletionConfirmed","label_visibility_settings","warning","label_confirm_children_deletion","workPackageLabel","singleWorkPackage","singleWorkPackageChildren","childCount","hasChildren","childUnits","deletesChildren","mustConfirmChildren","blockedDueToUnconfirmedChildren","performBulkDelete","confirmDeletion","HelpTextDmService","WpTableConfigurationDisplaySettingsTab","wpTableSums","displayMode","availableGroups","displaySums","choose_mode","label_group_by","display_sums","display_sums_hint","display_mode","grouped","hierarchy_hint","setEnabled","updateGroup","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","queryOrderDm","causedUpdates","assignPosition","buildDelta","upstreamOrder","pos","OpEditingPortalSchemaToken","OpEditingPortalHandlerToken","OpEditingPortalChangesetToken","editModeClassName","EditFieldComponent","markForCheck","parseValue","WorkPackageWatchersService","$update","FormattableEditFieldComponent","initializationError","isPreview","previewHtml","editorType","getEditorTypeFor","registerOnSubmit","getCurrentValue","attachmentLabel","getTransformedContent","previewContext","SaveQueryModal","queryName","isStarred","isPublic","save_as","label_name","queryNameField","savedQuery","saveQueryAs","VersionDmService","WorkPackageCopyFullViewComponent","successState","wpDisplayListRepresentation","wpDisplayCardRepresentation","WorkPackageViewDisplayRepresentationService","representation","WorkPackageRelationsHierarchyService","childWpId","wpToBecomeChild","args","parent_id","childWorkPackage","parentWorkPackage","WorkPackageFormAttributeGroupComponent","elem","descriptor","registerWorkPackageMouseHandler","getRenderInfo","workPackageTimeline","bar","renderer","renderInfo","dateStates","placeholderForEmptyCell","mouseDownStartDay","jBody","getCursorOffsetInDaysFromLeft","leftOffset","getAbsoluteLeftCoordinates","cursorOffsetLeftInPx","createMouseMoveFn","offsetDayCurrent","offsetX","dayUnderCursor","onDaysMoved","dates","assignDateValues","applyDateValues","keyPressFn","handleMouseMoveOnEmptyCell","isLeaf","canMoveDates","displayPlaceholderUnderCursor","onmouseleave","onmousedown","pointerEvents","offsetDayStart","dateForCreate","mouseDownType","onMouseDown","onmousemove","widthInDays","moved","onmouseup","cancelled","disableViewParamsCalculation","noop","resetCursor","onMouseDownEnd","refreshView","stopAndRefresh","queryDm","loadIdsUpdatedSince","workPackageCollection","updateWorkPackageList","saveWorkPackage","workPackageMouseDownFn","WorkPackageCellLabels","center","leftHover","rightHover","renderers","latestRenderInfo","wpElement","cellRenderer","getMarginLeftOfLeftSide","getMarginLeftOfRightSide","getPaddingLeftForIncomingRelationLines","getPaddingRightForOutgoingRelationLines","isMilestone","cellElement","html","cellContainer","elementShape","createAndAddLabels","milestone","generic","lazyInit","dateDisplaysOnMouseMove","valueOf","zIndex","applyTypeColor","assignDate","updateLabels","initialStartDate","initialDueDate","projection","forceCursor","visibility","backgroundImage","offsetStart","duration","minWidth","checkForActiveSelectionMode","checkForSpecialDisplaySituations","labelCenter","labelLeft","containerRight","labelRight","labelFarRight","labelHoverLeft","labelHoverRight","bg","selectionMode","isParentWithVisibleChildren","borderStyle","borderWidth","borderBottom","activeDragNDrop","labelConfiguration","getNormalizedLabels","renderLabel","renderHoverLabels","inHierarchyMode","diamond","initialDate","marginLeft","ri","wpTimeline","cellRenderers","getCellsFor","synchronizeCells","refreshSingleCell","renderInfoFor","currentlyActive","workPackageIdOrder","wpTableDirective","_viewParameters","cellsRenderer","selectionParams","refreshRequest","outerContainer","registerTimeline","orderedRows","timelineState","isAutoZoom","applyAutoZoomLevel","calculateViewParams","refreshAllCells","currentWidth","scrollWidth","activateSelectionMode","getParentScrollContainer","nonVisibleDaysLeft","viewPortRight","daysUntilViewPortEnds","resetSelectionMode","currentParams","newParams","subtract","dayCountForMarginLeft","visibleDays","isSame","getFirstDayInViewport","getLastDayInViewport","daysSpan","timelineWidthInPx","confirmDialog","confirmDelete","showAnchorRight","isSortable","setAsSingleSortCriteria","addSortCriteria","isGroupable","isCurrentlyGroupedBy","setBy","isFirst","focusColumn","removeColumn","wpTimelineService","workPackageTimelineTableController","onRefreshRequested","innerHeader","renderLabels","activeZoomLevel","renderLabelsDays","renderLabelsWeeks","renderLabelsMonths","renderLabelsQuarters","renderLabelsYears","renderTimeSlices","quarter_number","marginTop","cellCallback","addLabelCell","workPackagePrefix","TimelineRelationElement","belongsToId","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","finishElement","offsetToday","dayProgress","checkForWeekendHighlight","day","gridContainer","paddingTop","WorkPackageWatcherEntryComponent","panelCtrl","deleting","watcher","removeWatcher","sum","sumsSchema","renderContent","totalSums","appendFirstLabel","factoryFor","relatedTo","refreshTable","getRelationTypeFromQuery","buildQueryProps","toId","configureTable","openTableConfigurationModal","bootstrapAttributeGroups","bootstrapAttributeGroupsCalled","hookService","WorkPackagesListChecksumService","newQueryChecksum","getNewChecksum","routePromise","isUninitialized","isIdDifferent","maintainUrlQueryState","isChecksumDifferent","isOutdated","checksum","visibleChecksum","otherId","otherChecksum","hasCurrentQueryID","hasCurrentChecksum","idChanged","checksumChanged","visibleChecksumChanged","pick","WorkPackageViewHandlerToken","WorkPackageViewHandlerRegistry","factory","eventScope","EVENT","handleEvent","WorkPackageCardViewService","CardViewHandlerRegistry","ExternalQueryConfigurationComponent","openConfigurationModal","BoardCacheService","boardDm","_state","UserActivityComponent","sanitization","wpLinkedActivities","commentService","userCacheService","userCanEdit","userCanQuote","focused","label_created_on","label_updated_on","quote_comment","edit_comment","updateCommentText","isComment","isBcfComment","detail","userName","userAvatar","focussing","rawComment","updateComment","quotedText","newActivity","finally","quoted","line","focusEditIcon","postedComment","bypassSecurityTrustHtml","SortHeaderDirective","toggleHierarchy","openMenu","sortColumn","onReadyWithAvailable","latestSortElement","headerColumn","currentSortDirection","setActiveColumnClass","sortable","directionClass","getDirectionClass","isHierarchyColumn","columnType","columnName","hierarchyIcon","isHierarchyDisabled","setHierarchyIcon","toggleState","disable","BoardService","Gon","boardCache","boardActions","boardsList","unnamed_board","action_board","unnamed_list","loadAllPromise","allInScope","boards","buildOrderAndUpdate","reorderWidgets","sortWidgets","boardName","addFreeQuery","addActionQueries","WorkPackageTypeStatusComponent","v3ErrorIdentifierMultipleErrors","ErrorResource","isMultiErrorMessage","extractMultiError","perAttribute","ConfigurationDmService","$configuration","WorkPackageViewToggleButton","detectView","OpenprojectEditorModule","WorkPackageViewFocusService","focusAfterRender","setFocusAfterRender","withLoadingIndicator","delayStopTime","source$","delayedStop","stop","withDelayedLoadingIndicator","LoadingIndicator","indicatorTemplate","stopper","LoadingIndicatorService","getIndicatorAt","DebouncedEventEmitter","takeUntil$","emitter","debouncer","generatorOrNext","AttributeHelpTextModal","editText","SortModalObject","WpTableConfigurationSortByTab","sort_criteria_1","sort_criteria_2","sort_criteria_3","sorting_mode","automatic","manually","availableDirections","availableColumns","allColumns","sortationObjects","emptyColumn","sortingMode","sortElements","manualSortColumn","getMatchingSort","getManualSortingOption","updateSortingMode","updateUsedColumns","fillUpSortElements","usedColumns","WpRelationInlineCreateService","removeRelation","toState","fromState","fromParams","WorkPackagesBaseComponent","onClickOrEnter","ClickOrEnterHandler","processEvent","ProjectDmService","WorkPackageSubjectComponent","uiRouterGlobals","uniqueElementIdentifier","WorkPackageNewSplitViewComponent","chartType","WpIsolatedGraphQuerySpaceProviders","TimeEntryFormComponent","showWorkPackageField","modifiedEntry","spentOn","wpRequired","workPackageSelected","setCustomFields","entries","keySchema","signalModifiedEntry","paginationService","getCachedPerPage","updateFromObject","OpenProjectFileUploadService","upload","uploadUrl","staticDownloadLocation","uploadSingle","whenFinished","formData","FormData","metadata","reportProgress","promises","observable","Response","PartitionedQuerySpacePageComponent","tableInformationLoaded","toolbarButtonComponents","filterAllowed","currentPartition","hasQueryProps","setPartition","removeTransitionSubscription","isFirstLoad","setupInformationLoadedListener","queryParamListener","unRegisterTitleListener","updateTitle","onQueryUpdated","removeQueryChangeListener","updateQueryName","querySaving","getStaticName","titleEditingEnabled","shouldUpdateHtmlTitle","visibly","loadFirstPage","reloadCurrentResultsList","additionalLoadingTime","loadCurrentQueryFromParams","saveQueryFromTitle","FilterIntegerValueComponent","WorkPackageSingleViewComponent","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","BrowserDetector","documentElement","hasBodyClass","WpTableConfigurationFiltersTab","columnsLabel","selectedColumns","multiSelectLabel","upsaleRelationColumns","upsaleRelationColumnsLink","replaceIfComplete","NotificationComponent","uploadCount","checkedClassName","UiStateLinkBuilder","AbstractDmService","listUrl","oneUrl","listParamsString","filterParam","queryPropsString","webpackEmptyAsyncContext","configurationService","timeoutAfter","nextValue","autoHidePopups","createNotification","createAttachmentUploadNotification","QueryFilterResource","SchemaCacheService","forceUpdate","OpTitleService","getTitle","titleParts","setTitle","activeFieldContainerClassName","activeFieldClassName","EditForm","errorsPerAttribute","loadFieldSchema","renderField","showEditingBlockedError","requireVisible","activateWhenNeeded","openFields","handleSubmissionErrors","resetChange","handleErroneousAttributes","erroneousAttributes","getInvolvedAttributes","getMessagesPerAttribute","setErrorsForFields","erroneousFields","focusOnFirstError","loadFormAndCheck","activateField","prototype","padding","number","substr","isFunction","func","isSet","isString","isBoolean","decimalAdjust","exp","NaN","lazyEvaluate","scope","dest","DATE","day_names","abbr_day_names","month_names","abbr_month_names","meridian","NUMBER_FORMAT","precision","separator","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","toFixed","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","iterations","obj1","obj2","p","WorkPackagesGridComponent","wpTableHighlight","wpList","showResizer","resizerClass","resizerStorageKey","gridOrientation","WorkPackageFilterContainerComponent","visible$","DatePicker","datepickerElem","datepickerFormat","datepickerCont","datepickerInstance","startOfWeek","datepicker","_defaults","firstDay","mergedOptions","showWeeks","changeMonth","changeYear","closeText","dateFormat","defaultDate","showButtonPanel","yearRange","hide","hideDuringScroll","reshowTimeout","scroll","clearTimeout","visibleAndActive","elementFromPoint","onInputChange","setup","datePickerInstance","showDatePicker","keydown","initialValue","onSelect","parseISODate","toDate","WorkPackageViewSelectionService","selectionState","_emptyState","wpState","getSelectedWorkPackageIds","selectionCount","activeRowIndex","renderedElements","selectAll","WpResizerDirective","resizeStyle","moving","resizingElement","elementClass","localStorageValue","parseLocalStorageValue","toggleFullscreenColumns","resizer","applyColumnLayout","actualElementWidth","resizeEvent","dispatchEvent","manageErrorClass","deltas","relative","newWidth","toggleColumns","checkWidth","fullScreenLeftView","shouldBePresent","resizeEnd","resizeStart","resizeMove","WpChildrenInlineCreateService","addExistingChildWp","canAddChild","WorkPackageFilterValues","excluded","filterAlreadyApplied","setValueFor","findSpecialValue","isLoggedIn","fromSelfLink","BannersService","_banners","bannersVisible","bannersNotVisible","callMaybe","WorkPackageListViewComponent","wpViewFilters","showListView","showResultOverlay$","incomplete$","wpTableConfiguration","updateViewRepresentation","valueFromQuery","ckeditorAugmentedTextareaSelector","CkeditorAugmentedTextareaComponent","Notifications","isEditing","textareaSelector","formElement","wrappedTextArea","removeAttr","initialContent","$attachmentsElement","pageWasEdited","setupAttachmentAddedCallback","setupAttachmentRemovalSignal","ckEditorInstance","getRawData","addUploadedAttachmentsToForm","setLabel","model","removedUrls","downloadLocation","fire","textareaId","substring","ckContent","maxValue","toArray","addedAttachments","markEdited","WorkPackageAutocompleterComponent","changeModel","opened","closed","keyPressed","WorkPackageOverviewTabComponent","WorkPackageLinkedResourceCache","cacheDurationInSeconds","isCached","WpTableConfigurationTimelinesTab","availableZoomLevels","display_timelines","display_timelines_hint","zoom","weeks","months","quarters","years","auto","availableLabels","allPropertyColumns","availableAttributes","OpQueryConfigurationLocalsToken","OpQueryConfigurationTriggerEvent","WorkPackageCardViewComponent","wpViewOrder","cardDragDrop","cardsRemovable","showEmptyResultsBox","isResultEmpty","addNewCard","inReference","referenceOutputs","setReferenceMode","onReferenced","updateRenderedCardsValues","registerDragAndDrop","onCardSaved","CollectionResource","WorkPackageViewPageComponent","inputs","stateName$","containerClasses","button_settings","WpRelationInlineAddExistingComponent","queryFilters","buildQueryFilters","newRelationId","addExisting","buildV3GetFilterIdFromFilter","buildV3GetFilters","HalResourceSortingService","halType","sortingProperty","States","posts","timeEntries","QueryAvailableDataStates","GlobalStateChanges","camelCase","WorkPackageBaseResource","truncateSubject","truncate","otherWorkPackage","resourceNames","linked","touch","createWorkPackage","hasOverriddenSchema","WorkPackageResource","TimeEntryWorkPackageAutocompleterComponent","modeSwitch","errorNotificationHandler","DebouncedRequestSwitchmap","requestHandler","errorHandler","debounceMs","loading$","lastResult","output$","until","TimeEntryDmService","payloadDm","attachmentsSelector","AttachmentsComponent","allowUploading","DraggableAutocompleteComponent","dragula","_selected","updateAvailableOptions","columnsGroup","createGroup","drag","drop","autoscroll","drake","dragging","clearModel","cfg","_dataDir","dataDir","_error","ifc_models","projectData","models","viewerContent","modelsLoaded","shown_models","viewerConfigs","saoEnabled","_projectId","modelId","attachmentId","metadata_attachment_ids","utils","loadJSON","attachmentUrl","xkt_attachment_ids","loadArraybuffer","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","daysFromToday","today","datetimeString","durationString","asHours","toHours","dateTime","dateFormatPresent","timeFormatPresent","timeFormat","QuerySharingForm","showInMenu","visibleForOthers","showInMenuText","visibleForOthersText","isSave","updatePublic","updateStarred","OpCkeditorComponent","ckEditorSetup","ckEditorType","onInitialized","onContentChange","onInitializationFailed","allowManualMode","manualMode","errorTitle","debouncedEmitter","leading","_content","notificationOnError","newVal","initializeEditor","editorPromise","opCkeditorReplacementContainer","enableManualMode","disableManualMode","WorkPackageStaticQueriesService","CurrentUserService","assignee","created_at","updated_at","gantt","latest_activity","created_by_me","assigned_to_me","recently_created","all_open","summary","pp","pa","matched","HalResourceService","httpError","expected","retrieved","allResults","toEprops","getEmptyResource","getResourceClassOfType","fromType","toType","getResourceClassOfAttribute","defaultClass","typeConfig","deflated","eprops","btoa","WpCustomActionComponent","wpSchemaCacheService","savedWp","fetchAction","WorkPackageNewFullViewComponent","EditFieldHandler","_onSubmitHandlers","AccessibleClickDirective","SPACE","DEFAULT_PAGINATION_OPTIONS","PaginationService","loadPaginationOptions","initialPageOptions","localStoragePerPage","initialLength","paginationOptions","perPageOptions","maxVisiblePageOptions","optionsTruncationSize","WorkPackageFiltersService","WorkPackagesListInvalidQueryService","queryFormDm","buildQueryResource","restoreFilters","restoreColumns","restoreSortBy","restoreGroupBy","restoreOtherProperties","querySchema","filterInstanceSchema","recreatedFilter","stubQuery","sortBys","WpCustomActionsComponent","customActions","opIconElement","OPContextMenuComponent","ViewerBridgeService","WorkPackageTablePaginationComponent","wpPagination","showPerPage","showPageSelections","infoText","paginationInfoText","setPerPage","pageNumber","UploadProgressComponent","completed","Sent","UploadProgress","updateProgress","WorkPackageRelationsComponent","relationGroups","relationGroupKeys","relationsPresent","relations_header","currentRelations","loadedRelations","observablesToGetZipped","buildRelationGroups","normalizedType","relatedBy","stateValues","relatedWpIds","relatedWpId","getRelatedWorkPackageId","getRelatedWorkPackages","relatedWorkPackages","WorkPackageSplitViewToolbarComponent","button_more","ActivityEntryInfo","forceReverse","orderedIndex","activityDate","version","dateOfPrevious","commentsSortedInDescendingOrder","aggregated","sortedActivityList","sorted","TablePaginationComponent","hideForSinglePageResults","updateResults","label_previous","label_next","per_page","no_other_page","currentRange","pageNumbers","postPageNumbers","prePageNumbers","totalEntries","updateCurrentRangeLabel","updatePageNumbers","showPage","onUpdatedPage","totalItems","lowerBound","getLowerPageBound","upperBound","getUpperPageBound","maxVisible","getMaxVisiblePageOptions","truncSize","getOptionsTruncationSize","currentPage","startingDiff","truncatePageNums","perform","disectFrom","disectLength","truncateFrom","truncationSize","truncatedNums","ViewpointsService","viewpointHref","bcfApi","getViewPointResource","wpCache","wpProjectId","topicUUID$","setBcfTopic$","viewpoint$","viewerBridge","getViewpoint$","topicUUID","topicHref","bcfTopic","createBcfTopic$","wpPayload","convertBCF","guid","VersionAutocompleterComponent","versionDm","openDirectly","onCreate","canCreateNewActionElements","createAllowed","createNewVersion","canCreateVersionInProject","createVersion","getVersionPayload","closeSelect","definingProject","GridDmService","rowGroupClassName","collapsedRowClass","UserCacheService","userDmService","AttributeHelpTextsService","helpTexts","ExternalQueryConfigurationService","originator","_portalHostElement","_bodyPortalHost","externalQueryConfigurationComponent","hasAttached","RevisionActivityComponent","loadAuthor","revision","revisionPath","showRevision","formattedRevision","formattedIdentifier","revision_identifier","revisionLink","committed_revision_link","formattedDatetime","authorName","userActive","showUser","userLabel","floatValue","parseFloat","parsedValue","SelectAutocompleterRegisterService","_fields","assignment","valuesLoaded","newElement","onKeydown","handleUserKeydown","onAfterViewInit","_autocompleterComponent","requiredPlaceholder","valuesLoadingPromise","initialValueLoading","loadValues","selectAutocompleterRegister","getAutocompleterOfAttribute","overflowingSelector","valueOptions","availableValues","sortValues","addEmptyOption","mapAllowedValue","loadValuesFromBackend","tap","cacheKey","cacheValue","fetchAllowedValueQuery","allowedValuesFilter","addValue","selectedOption","emptyOption","getEmptyOption","isRequired","currentValueInvalid","requestFocus","nullOption","openAutocompleteSelectField","findValueOption","_selectedOption","adjustPosition","valueOption","sortValuesByName","nameA","nameB","buildSelectedOption","checkCurrentValueValidity","filterParams","prefix","suffix","onValueSelected","projectStatusCodeCssClass","ensureDefaultCode","projectStatusI18n","_availableStatusCodes","currentStatusCode","availableStatuses","recentWorkPackageIds","timeEntryDm","timeEntry","sortValuesByRecentIds","toLocaleString","useGrouping","maximumFractionDigits","bootstrapOptionalEmbeddable","unescape","UNESCAPED_EXPRESSION","ESCAPED_EXPRESSION","derivedText","formattedDuration","derivedPropertyName","derivedValue","actual","renderActual","derived","renderDerived","derivedValueString","actualPresent","valueEmpty","derivedEmpty","colorize","shouldHighlight","viewHighlighting","shouldHighlightInline","canOverdue","formattedDate","translatedValue","linkTitle","logTime","wpID","projectCacheService","URI","projectTimeEntriesPath","work_package_id","appendTimelogLink","timelogElement","showTimelogWidget","addHighlight","hlClass","divContainer","renderAbridgedValues","dots","uiStateBuilder","linkToShow","innerText","OpenprojectFieldsModule","editFieldService","selectAutocompleterRegisterService","addSpecificFieldType","FocusDirective","uiStatebuilder","detailsLink","linkToDetails","contextMenu","built","buildElement","FirstRouteService","WorkPackageFilterButtonComponent","setupObserver","currentlyVisibleFilters","UrlParamsHelperService","paramsData","encodeColumns","encodeSums","encodeTimelineVisible","encodeHighlightingMode","encodeHighlightedAttributes","hi","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","BackRoutingService","preferListOverSplit","backRoute","isDetailsState","currentDetailsSubState","paramsFromCopy","route","_backRoute","TableDragActionService","shadowElement","backToDefault","determineParent","relationHierarchyService","isFlatList","relationRoot","findRelationRowRoot","previousWpId","isHiearchyRoot","loadParentOfWP","inGroup","isRoot","groupedAttribute","groupedValue","getValueForGroup","groupHeader","applies","tdClassName","editCellContainer","CellBuilder","displayElement","FilterStringValueComponent","enter_text","whenDebugging","debugLog","timeOutput","msg","WorkPackageNotificationService","addWorkPackageFullscreenLink","QUERY_SORT_BY_ASC","QUERY_SORT_BY_DESC","WorkPackageRelationsTabComponent","WorkPackageViewContextMenu","selectedWorkPackages","getSelectedWorkPackages","WorkPackageContextMenuHelper","deleteSelectedWorkPackages","editSelectedWorkPackages","copySelectedWorkPackages","addNewChildWp","logTimeForSelectedWorkPackage","screenfull","zenModeComponentSelector","ZenModeButtonComponent","enabled","onchange","isFullscreen","deactivateZenMode","inZenMode","exit","activateZenMode","TimeEntryResource","InjectField","token","Reflect","getMetadata","_val","WpTableConfigurationColumnsTab","availableColumnsOptions","column2Like","availableColumnsMap","keyBy","selectedColumnMap","columnsHelp","upsaleCheckOutLink","setColumnsById","updateSelected","WorkPackagesFullViewComponent","full_view","setWorkPackageScopeProperties","displayWatchButton","WorkPackageSingleViewBase","tabs","subjectWithType","showStaticPagePath","updateFocusAnchorLabel","tabLabel","focusAnchorLabel","WorkPackageRelationRowComponent","showRelationInfo","userInputs","newRelationText","showDescriptionEditForm","showRelationTypesForm","fieldController","removeButton","description_label","toggleDescription","updateRelation","availableRelationTypes","textarea","relationDescriptionTextarea","textlen","cancelDescriptionEdit","savedRelation","updateRelationType","BoardListsService","filterJson","buildQueryRequest","freeBoardQueryFilter","addQuery","manualSort","wpEmbeddedTableMacroSelector","EmbeddedTablesMacroComponent","CurrentProjectService","detect","getCurrent","projectName","OpUnlinkTableAction","WpTableConfigurationModalPrependToken","WpTableConfigurationModalComponent","prependModalComponent","applyButton","wpTableConfigurationService","tabPortalHost","tabContentOutlet","activeComponents","saveChanges","WorkPackageChildrenQueryComponent","addExistingChildEnabled","WorkPackageStatusDropdownDirective","postIcon","postIconTitle","updateStatus","CreateAutocompleterComponent","finishedLoading","hideSelected","add_new_action","_openDirectly","openSelect","ModalWrapperAugmentService","wrapElement","activationLink","activationSelector","iframeUrl","appendIframe","subdom","iframe","WpTableConfigurationService","FocusWithinDirective","focusedObservable","DragAndDropService","escapeListener","containers","member","setupAutoscroll","initializeDrake","setOuterScrollContainer","getMember","invalid","copy","revertOnSpill","removeOnSpill","mirrorContainer","ignoreInputTextSelection","QuerySharingModal","saveQuery","OpenprojectCommonModule","routerState","addContext","setUser","email","mail","setTag","setExtra","bootstrapModule","withComponents","userAvatarSelector","UserAvatarComponent","RelationStateGroup","WorkPackageRelationsService","relationsDm","relationStates","updateRelationsStateTo","loadInvolved","accumulateRelationsFromInvolved","removeFromStates","insertIntoStates","relationsToInsert","relevant","isInvolved","getWorkPackageId","WorkPackageCacheService","immediate","skipOnIdentical","loadWorkPackagesCollectionsFor","pagedResults","loadWorkPackageById","GridBaseResource","widgetResource","GridResource","WorkPackageTimelineButtonComponent","minZoomLevel","maxZoomLevel","isMaxLevel","isMinLevel","zoomIn","zoomOut","zoomAuto","updateZoomWithDelta","toggleTimeline","enableAutozoom","ScrollableTabsComponent","currentTabId","hideLeftButton","hideRightButton","pane","scrollPane","determineScrollButtonVisibility","scrollIntoVisibleArea","clientWidth","tabId","tabRightBorderAt","outerWidth","onScroll","scrollRight","ResizerComponent","resizing","customHandler","cursorClass","buttons","oldX","pageX","touches","oldY","startY","pageY","newX","newY","setResizeCursor","bindEventListener","setAutoCursor","mouseMoveHandler","onMouseMove","mouseUpHandler","onMouseUp","origin","absolute","userMeta","registerRequestForConfirmation","getPluginContext","services","passwordConfirmationModal","modals","passwordConfirmation","password_confirmation","registerListener","augmentedDatePicker","linkElement","hashPos","performAnchorHijacking","pageIsSubmitted","marginBottom","returnValue","inputId","serialize","refreshOnFormChanges","prevScrollPos","currentScrollPos","scrollHeaderOnMobile","WorkPackageCommentComponent","editTitle","cancelTitle","fieldLabel","canAddComment","showAbove","quote","commentContainer","scrollToBottom","wpDetails","createComment","scrollableContainer","scrollHeight","edition","localStorage","getItem","setItem","bcfPathHelper","snapshotPath","BcfDetectorService","revitMessageReceivedSource","_trackingIdNumber","_ready$","revitMessageReceived$","RevitBridge","hookUpRevitListener","trackingId","newTrackingId","sendMessageToRevit","messageType","viewpointJson","messagePayload","snapshot","snapshot_type","snapshot_data","viewerVisible","jsonPayload","sendMessageToOpenProject","messageString","mapTo","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","observeChanges","refreshViewpoints","isAllowedTo","loadViewpointFromRoute","snapshotURL","setViewpointsOnGallery","showViewpoint","deleteViewPoint$","gallery","saveViewpoint$","showIndex","selectViewpointInGallery","titleText","deleteViewpoint","setThumbnailProperties","small","medium","big","viewpointCount","dynamicThumbnailHeight","galleryViewpoints","observeCreation","switchMap","observables","viewPointItem","forkJoin","newViewpoint","bootstrapCalled","isBimEdition","navigator","userAgent","regions","regional","setDefaults","gotoToday","_gotoToday","inst","_getInst","dateStr","_formatDate","_hideDatepicker","showWeek","calculateWeek","dayOfWeek","setDate","iso8601Week","_originalGotoToday","_selectDate","_inlineDatepicker2","_inlineDatepicker","beforeShow","_get","_checkOffsetOriginal","_checkOffset","isFixed","_offset","alterOffset","inp","customDateActionAdminSelector","CustomDateActionAdminComponent","valueVisible","onKey","currentKey","currentFieldValue","operators","fieldValue","selectedOperator","visibleValue","toggleValueVisibility","updateDbValue","I18nService","_i18n","translateId","parameters","WorkPackageViewHierarchies","setState","initialState","CausedUpdatesService","EnterpriseBannerComponent","leftMargin","enterpriseFeature","opReferrer","AbstractWorkPackageButtonComponent","labelKey","textKey","activationPrefix","deactivationPrefix","createdEntry","setModifiedEntry","createNewTimeEntry","OpenprojectAttachmentsModule","indicatorCollapsedClass","additionalHierarchyRowClassName","SingleHierarchyRowBuilder","leaf","appendHierarchyIndicator","hierarchyLevel","hierarchyElement","buildHierarchyIndicator","hierarchyIndicator","indicatorWidth","indentation","BcfImportButtonComponent","import","projectImportIssuePath","TimeEntryBaseModal","areYouSure","workPackageCacheService","UserResource","active_user_statuses","boardsMenuSelector","BoardsMenuComponent","boardService","trackById","currentProjectIdentifier","boards$","observeAll","focusBackArrow","loadAllBoards","CardRightClickHandler","WpTableConfigurationHighlightingTab","entireRowMode","lastEntireRowAttribute","availableInlineHighlightedAttributes","availableRowHighlightedAttributes","highlighting_mode","inline","inline_all_attributes","entire_row_by","upsaleAttributeHighlighting","availableHighlightedAttributes","setSelectedValues","updateMode","currentValues","updateHighlightingAttributes","WorkPackageWatchersTabComponent","allowedToView","allowedToAdd","allowedToRemove","watching","loadingError","loadCurrentWatchers","availableWatchersPath","addWatcher","$prepare","user_id","WorkPackageCreateComponent","wpViewFocus","cancelState","closeEditFormWhenNewWorkPackageSaved","showForm","createdWorkPackage","newWorkPackage","loginPath","back_url","BcfExportButtonComponent","export","exportLink","projectExportIssuesPath","showDelayedExport","field_description","confirm_button","password","passwordValuePresent","passwordConfirmationField","sanitizer","string","sanitize","HTML","_knownHookNames","externalQueryConfiguration","externalRelationQueryConfiguration","htmlSanitizeService","ckEditorPreview","pathHelperService","dynamicContent","run","ImageHelpers","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","loadIfNecessary","showCosts","renderCostAsLink","renderCostAsText","costObjectId","spentUnits","costType","addSeparator","BudgetResource","CostSubformAugmentService","templateEl","template","PlannedCostsFormAugment","objId","objName","makeEditable","edit_and_focus","currency","getCurrency","insertAfter","CostBudgetSubformAugmentService","row_identifier","buildRefreshRequest","HTMLInputElement","element_id","fixed_date","extendFieldType","workPackageSingleContextMenu","workPackageTableContextMenu","listen","initializeCostsPlugin","DocumentResource","LinkedPluginsModule","GridArea","storedGuid","newGuid","s4","otherArea","rowOverlaps","columnOverlaps","sink","isRow","gridDm","numColumns","numRows","mousedOverArea","$mousedOverArea","BehaviorSubject","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","static","calendarPlugins","alreadyLoaded","setupWorkPackagesListener","initializeCalendar","ucCalendar","getApi","addTooltip","toWPFullView","fetchInfo","successCallback","failureCallback","updateTimeframe","calendarEvents","calendarEventsFunction","setCalendarHeight","setCalendarHeader","filtersEmpty","endDate","defaultQueryProps","datesIntervalFilter","tooltip","tooltipContentString","extendedProps","track","removeTooltip","history","pushState","inherit","calendarHeight","heightElement","topOfCalendar","topOfHeightElement","calendarElement","calendarHeader","calendarDate","calendarUnit","lower","changeView","setCalendarsDate","refetchEvents","warnOnTooManyResults","mapToCalendarEvents","eventDate","exclusiveEnd","allDay","tooManyResultsText","MAX_DISPLAYED","props","sanitizedValue","toStringMethod","renameWidget","destroyedEntry","timeEntryEdit","timeEntryCreate","timeEntryCache","minHour","maxHour","labelIntervalHours","scaleRatio","calendarSlotLabelFormat","calendarSlotLabelInterval","calendarContentHeight","calendarAllDaySlot","calendarDisplayEventTime","calendarSlotEventOverlap","calendarEditable","calendarMinTime","calendarMaxTime","calendarEventOverlap","stillEvent","memoizedCreateAllowed","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","reduce","updateEntries","GridWidgetsService","Hook","registeredWidgets","registration","OpenprojectTimeEntriesModule","CALENDAR_ROUTES","OpenprojectCalendarModule","forChild","domSanitizer","entriesLoaded","documentsUrl","orders","project_id","newsDm","addedBy","newsAuthorName","age","newsCreated","authorLink","newsAuthorPath","newsDmParams","setupNews","newsPath","GridInitializationService","myPageForm","WpGraphConfigurationSettingsTab","tabInner","WpGraphConfigurationFiltersTab","WpGraphConfiguration","chartOptions","is_public","_forms","persistChanges","reloadQueries","createInitial","queryCreationParams","queryPromises","queryParam","formFor","_configuration","_formsPromise","loadForms","queryTabs","formPromises","graphConfiguration","onConfigured","configureItem","configurationComponent","WorkPackageEmbeddedGraphComponent","chartHeight","chartLabels","chartData","datasets","setChartOptions","updateChartData","uniqLabels","array","labelCountMaps","countMap","setHeight","responsive","maintainAspectRatio","legend","plugins","datalabels","align","chartTypeDefaults","scales","xAxes","stacked","ticks","yAxes","inputChartOptions","initializeConfiguration","loadQueriesInitially","persistAndReload","repaint","ensureQueryAndLoad","updateGraph","query$","skip","ensureFormAndSaveQuery","initializationProps","onResourceChanged","QuerySpacedTabComponent","wpGraphConfiguration","initializeQuerySpace","group_by","chart_type","currentChartType","initializeAvailableGroups","initializeAvailableChartType","availableChartTypes","graphConfigurationService","displayModeSingle","availableGroupBy","additionalFilter","setQueryProps","graphParams","sortedDatasets","propsBoth","propsOpen","propsClosed","sortingArray","baseProps","subprojectId","displaySingle","embeddedGraphSingle","embeddedGraphMulti","projectCache","project$","inEdit","newEditResource","valueChanged$","rawText","textValue","canAddAttachments","setupVariables","newText","currentRawText","clickedElementIsLinkWithinDisplayContainer","textEmpty","initial","memorizeRawText","reinitialize","memorizeCustomText","customText","htmlText","projectDm","loadAndRender","loadProjectSchema","loadedEntry","timeEntryEditService","changedEntry","oldEntryIndex","newEntries","anEntry","sumsByDateSpent","sortedEntries","currentDate","projectDmParams","membershipDm","viewAll","entriesByRoles","membersAddable","listMembersParams","partitionEntriesByRole","sortUsersByName","totalMembers","listAvailableProjects","listAvailableProjectsParams","projectMembershipsPath","principal","membership","roles","role","OpenprojectGridsModule","defaultColumns","assignedFilters","assignedProps","accountableFilters","accountableProps","createdFilters","createdProps","watchedFilters","watchedProps","registerWidgets","ApplicationBaseComponent","OPENPROJECT_ROUTES","abstract","squash","flash_message","dynamic","loadChildren","OpenprojectBoardsModule","OpenprojectIFCModelsModule","bodyClass","cssClass","updateMenuItem","menuItemTitle","stateService","wpBase","onEnter","onExit","router","start_onboarding_tour","paramsCopy","sync","profiler","MiniProfiler","pageTransition","pathname","setIfFirst","initializeUiRouterListeners","forRoot","useHash","uiRouter","urlService","strictMode","encode","decode","equals","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","externalRelationQuery","drag_to_activate","label_group","new_group","label_inactive","custom_field","add_group","add_table","inactives","no_filter_query","noFilterQuery","submitted","updateHiddenFields","dropModel","activeGroups","inactiveAttributes","groupsDrake","attributeDrake","updateInactives","newGroup","editQuery","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","MouseEvent","bubbles","cancelable","fireEvent","keyboardShortcutsHelpPath","domLists","focusElements","firstLink","findListInPage","focusItemOffset","highlightTextInline","setColorOptions","updateInput","selectedColorId","selectedColor","highlightingClass","globalSearchService","wpFilters","resultsHidden","tableConfiguration","debounceTime","newSearchTerm","newProjectScope","newFeatures","descriptionNewFeatures","learnAbout","i18nBase","isStandardEdition","translated","bypassSecurityTrustResourceUrl","i18nPrefix","list_styling_class","bcf_api_link","GlobalSearchWorkPackagesEntryComponent","PersistentToggleComponent","isHidden","$targetNotification","getTargetNotification","isNowHidden","slideUp","slideDown","displayed","sections","removeHiddenOnSubmit","section","HideSectionLinkComponent","hideSectionService","sectionName","hideSection","ShowSectionDropdownComponent","HideSectionService","optValue","hideSecWithName","prev","trackByKey","selectable","htmlId","AutocompleteSelectDecorationComponent","multiselect","labelForId","syncInputFieldName","inputName","updateSelection","removeCurrentSyncedFields","createSyncedField","gonTabs","CopyToClipboardDirective","clickTarget","clipboardTarget","supported","queryCommandSupported","execCommand","addNotification","ConfirmFormSubmitController","$form","openConfirmationDialog","PathHelperService","markable","setMarkedOption","all_projects","current_project","current_project_and_all_descendants","search_dots","close_search","toggleTopMenuClass","unregister","btn","toggleMobileSearch","submitNonEmptySearch","wpPath","openCloseMenu","searchedTerm","isOpen","selectedItem","followSelectedItem","searchInScope","currentScope","statusId","followItem","hashFreeQuery","queryWithoutHash","fetchSearchResults","searchResultsToOptions","wpBySubjectOrId","searchItems","searchOptions","detailedSearchOptions","suggestion","itemsList","markItem","selectedItems","forcePageLoad","isAfterSearch","replaceState","submitSearch","serviceScope","unregisterGlobalListener","onFocusOut","onEnterBeforeResultsLoaded","clearSearch","CollapsibleSectionComponent","sectionTitle","nextElementSibling","sectionBody","EnterpriseBannerBootstrapComponent","textMessage","linkMessage","referrer","LazyLoadedAutocompleter","_renderLazyMenu","pageElements","maxItemsPerPage","shownHeight","_pages","_repositionMenu","_resizeMenu","renderItem","mark","pages","_renderMenuPage","outerHeight","isScrollbarBottom","widgetName","literalMatches","literalSearch","fuseInstance","str","setupParams","shouldSort","tokenize","threshold","maxPatternLength","minMatchCharLength","autocompleteValues","fuzzyResults","fuzzySearch","augmentedResultSet","onItemSelected","onNoResultsFound","dropdownMenu","projectMenuAutocomplete","loadProjects","addInputHandlers","scrollCurrentProjectIntoView","projectLink","currentMenuItem","projectLevelListPath","augmentWithParents","currentLevel","matchedParents","touchMoved","currentProjectHeight","scrollValue","htmlMode","keyCodesArray","TAB","SHIFT","updater","remoteFieldKey","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","valid","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","timeEntryDmService","editTimeEntry","deleteTimeEntry","globalDynamicComponents","OpenprojectMembersModule","OpenprojectEnterpriseModule","bootstrapOptionalDocument","_injector","ExternalQueryConfiguration","ExternalRelationQueryConfiguration","ModalWrapper","PreviewTrigger","mainMenuNavigationService","keyboardShortcuts","setupListener","contextCallbacks","messageStack","sentryConfigured","sentryElement","Sentry","dsn","debug","ignoreErrors","beforeSend","filterEvent","sentryLoaded","client","configureScope","setupContext","severity","handleOfflineMessage","withScope","fromString","callbacks","hostname","meta","enableReactiveStatesLogging","disableReactiveStatesLogging","platformRef","WorkPackageViewBaseService","combinedRaw","pristine","WorkPackageQueryStateService"],"mappings":"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B,8bCrCxC,gBACE,mBAAQ,sDAKN,yBAKA,yBAGF,OACF,Q,MAfK,0CAIK,8CACA,0BAAAnjF,KAAA,KAJA,wBAAmB,uBAQjB,kCAEA,6C,qFCXZ,IAAI6K,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,IAED,6BAA8B,CAC7B,OACA,EACA,IAED,yBAA0B,CACzB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,EACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,GAED,WAAY,CACX,OACA,EACA,IAED,WAAY,CACX,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,GAED,iBAAkB,CACjB,OACA,EACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,EACA,EACA,EACA,IAED,2BAA4B,CAC3B,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,EACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,+BAAgC,CAC/B,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,GAED,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,EACA,EACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED,mBAAoB,CACnB,OACA,EACA,KAED,yCAA0C,CACzC,OACA,EACA,EACA,KAED,iBAAkB,CACjB,O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rX,OACf,IAAK,cACH,OAAO,KACT,IAAK,YACH,OAAO,GACT,QACE,OAAO,SA9CR,GAAAo7F,gCAAiC,E,wBAD7B,K,qDAAA,IAA6B,sBAtO7B,CAET,IAGA,KACA,KAGA,IACA,KAKA,KACA,KACA,KAIA,KACA,IACA,KAEA,KACA,KAEA,KACA,KACA,KAEA,KACA,KACD,SAhDQ,CAEP,IAEA,IAEA,KAEA,KAEA,KAEA,S,KA2EA,IAA2B,qjBApC3B,KACA,KACA,KAGA,KACA,KAGA,KACA,KAGA,KACA,KACA,KACA,KAGA,KACA,KAGA,IACA,IAGA,KACA,KAGA,KACA,KAEA,KAEA,IACA,GACA,IAEA,IAEA,GAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAEA,KACA,KAGA,KACA,GACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,GACA,GACA,GACA,GACA,GAEA,KACA,KAGA,KACA,IACA,KACA,IACA,KACA,KACA,GACArP,EACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACAkO,GAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,KACA,KAIA,KACA,KAGA,KACA,KACA,MAA2B,uD,KAjF3B,GAAkC,qjBA3ElC,KACA,KACA,KAGA,KACA,KAGA,KACA,KAGA,KACA,KACA,KACA,KAGA,KACA,KAGA,IACA,IAGA,KACA,KAGA,KACA,KAEA,KAEA,IACA,GACA,IAEA,IAEA,GAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAEA,KACA,KAGA,KACA,GACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,GACA,GACA,GACA,GACA,GAEA,KACA,KAGA,KACA,IACA,KACA,IACA,KACA,KACA,GACAlO,EACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACAkO,GAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,KACA,KAIA,KACA,KAGA,KACA,KACA,MAA2B,uD,KAtD3B,KAA+B,qjBAtG/B,KACA,KACA,KAGA,KACA,KAGA,KACA,KAGA,KACA,KACA,KACA,KAGA,KACA,KAGA,IACA,IAGA,KACA,KAGA,KACA,KAEA,KAEA,IACA,GACA,IAEA,IAEA,GAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAEA,KACA,KAGA,KACA,GACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,GACA,GACA,GACA,GACA,GAEA,KACA,KAGA,KACA,IACA,KACA,IACA,KACA,KACA,GACAlO,EACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACAkO,GAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,KACA,KAIA,KACA,KAGA,KACA,KACA,MAA2B,uD,KAF3B,KAA4B,qjBA1J5B,KACA,KACA,KAGA,KACA,KAGA,KACA,KAGA,KACA,KACA,KACA,KAGA,KACA,KAGA,IACA,IAGA,KACA,KAGA,KACA,KAEA,KAEA,IACA,GACA,IAEA,IAEA,GAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAEA,KACA,KAGA,KACA,GACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,GACA,GACA,GACA,GACA,GAEA,KACA,KAGA,KACA,IACA,KACA,IACA,KACA,KACA,GACAlO,EACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACAkO,GAGA,KACA,KACA,KACA,KACA,KACA,KACA,KAC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","file":"main.e6d0c89cd222ee3d221e.js","sourcesContent":["// -- 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\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","//-- 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\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","import {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\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}\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 {WorkPackageCacheService} from '../work-packages/work-package-cache.service';\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\";\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 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 wpCacheService:WorkPackageCacheService,\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.wpCacheService.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(results.elements);\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.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.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.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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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-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\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-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 {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, scan} from \"rxjs/operators\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\n\nexport interface HalEvent {\n id:string;\n eventType:string;\n resourceType:string;\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 scan((acc, curr) => acc.concat(curr))\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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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-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 {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):Ng2StateDeclaration[] {\n return [\n {\n name: baseRoute + '.details',\n url: '/details/{workPackageId:[0-9]+}',\n redirectTo: baseRoute + '.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 partition: '-split',\n newRoute: baseRoute + '.new',\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: showComponent }\n }\n },\n {\n name: baseRoute + '.details.overview',\n url: '/overview',\n component: WorkPackageOverviewTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: baseRoute + '.details'\n }\n },\n {\n name: baseRoute + '.details.activity',\n url: '/activity',\n component: WorkPackageActivityTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: baseRoute + '.details'\n }\n },\n {\n name: baseRoute + '.details.relations',\n url: '/relations',\n component: WorkPackageRelationsTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: baseRoute + '.details'\n }\n },\n {\n name: baseRoute + '.details.watchers',\n url: '/watchers',\n component: WorkPackageWatchersTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: baseRoute + '.details'\n }\n },\n // Split create route\n {\n name: baseRoute + '.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: baseRoute + '.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-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 {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","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 if (!this.actionService.canPickup(workPackage)) {\n return td;\n }\n\n td.classList.add(tdClassName, '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 {QueryOrder} from \"core-app/modules/hal/dm-services/query-order-dm.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 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 {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 {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","//-- 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\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {PayloadDmService} from 'core-app/modules/hal/dm-services/payload-dm.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {QueryFormResource} from 'core-app/modules/hal/resources/query-form-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {Injectable} from '@angular/core';\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {Observable} from \"rxjs\";\nimport {QueryFiltersService} from \"core-components/wp-query/query-filters.service\";\nimport {DmListParameter} from \"core-app/modules/hal/dm-services/dm.service.interface\";\nimport {AbstractDmService} from \"core-app/modules/hal/dm-services/abstract-dm.service\";\nimport {HttpClient} from \"@angular/common/http\";\nimport * as URI from 'urijs';\n\nexport interface PaginationObject {\n pageSize:number;\n offset:number;\n}\n\n@Injectable()\nexport class QueryDmService extends AbstractDmService {\n constructor(protected halResourceService:HalResourceService,\n protected http:HttpClient,\n protected pathHelper:PathHelperService,\n protected UrlParamsHelper:UrlParamsHelperService,\n protected QueryFilters:QueryFiltersService,\n protected PayloadDm:PayloadDmService) {\n super(halResourceService,\n pathHelper);\n }\n\n /**\n * Stream the response for the given query request\n * @param queryData\n * @param queryId\n * @param projectIdentifier\n */\n public stream(queryData:Object, queryId?:string, projectIdentifier?:string|null):Observable {\n let path:string;\n\n if (queryId) {\n path = this.pathHelper.api.v3.queries.id(queryId).toString();\n } else {\n path = this.pathHelper.api.v3.withOptionalProject(projectIdentifier).queries.default.toString();\n }\n\n return this.halResourceService\n .get(path, queryData);\n }\n\n public find(queryData:Object, queryId?:string, projectIdentifier?:string|null):Promise {\n return this.stream(queryData, queryId, projectIdentifier).toPromise();\n }\n\n public findDefault(queryData:Object, projectIdentifier?:string|null):Promise {\n return this.find(queryData, undefined, projectIdentifier);\n }\n\n public reload(query:QueryResource, pagination:PaginationObject):Promise {\n let path = this.pathHelper.api.v3.queries.id(query.id!).toString();\n\n return this.halResourceService\n .get(path, pagination)\n .toPromise();\n }\n\n public loadResults(query:QueryResource, pagination:PaginationObject):Promise {\n if (!query.results) {\n throw 'No results embedded when expected';\n }\n\n let queryData = this.UrlParamsHelper.buildV3GetQueryFromQueryResource(query, pagination);\n let url = URI(query.href!).path();\n\n return this.halResourceService\n .get(url, queryData)\n .toPromise();\n }\n\n public loadIdsUpdatedSince(ids:any, timestamp:any):Promise {\n const filters = [\n {\n id: {\n operator: '=',\n values: ids.filter((n:String|null) => n) // no null values\n },\n },\n {\n updatedAt: {\n operator: '<>d',\n values: [timestamp, '']\n }\n }\n ];\n\n return this.halResourceService\n .get(this.pathHelper.api.v3.work_packages.toString(), { filters: JSON.stringify(filters) })\n .toPromise();\n }\n\n public update(query:QueryResource, form:QueryFormResource):Observable {\n const payload = this.extractPayload(query, form);\n return this.patch(query.id!, payload);\n }\n\n public patch(id:string, payload:{ [key:string]:unknown }):Observable {\n let path:string = this.pathHelper.api.v3.queries.id(id).toString();\n return this.halResourceService\n .patch(path, payload);\n }\n\n public create(query:QueryResource, form:QueryFormResource):Promise {\n const payload:any = this.extractPayload(query, form);\n let path:string = this.pathHelper.api.v3.queries.toString();\n\n return this.halResourceService\n .post(path, payload)\n .toPromise();\n }\n\n public delete(query:QueryResource) {\n return query.delete();\n }\n\n public toggleStarred(query:QueryResource) {\n if (query.starred) {\n return query.unstar();\n } else {\n return query.star();\n }\n }\n\n public listNonHidden(projectIdentifier:string|null|undefined):Promise> {\n let listParams:DmListParameter = {\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 return this.list(listParams);\n }\n\n private extractPayload(query:QueryResource, form:QueryFormResource):QueryResource {\n // Extracting requires having the filter schemas loaded as the dependencies\n this.QueryFilters.mapSchemasIntoFilters(query, form);\n return this.PayloadDm.extract(query, form.schema);\n }\n\n protected listUrl():string {\n return this.pathHelper.api.v3.queries.toString();\n }\n\n protected oneUrl(id:number|string):string {\n return this.pathHelper.api.v3.queries.id(id).toString();\n }\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","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-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\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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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';\n\n@Directive({\n selector: '[doubleClickOrTap]',\n})\nexport class DoubleClickOrTapDirective {\n @Input('doubleClickOrTapStopEvent') stopEventPropagation:boolean = true;\n @Output('doubleClickOrTap') eventHandler = new EventEmitter();\n\n @HostListener('dblclick', ['$event'])\n @HostListener('tap', ['$event'])\n public handleClick(event:any):boolean {\n // Pass along double clicks immediately\n // Or when the hammer.js event tap count reaches two\n if (event.type === 'dblclick' || event.tapCount === 2) {\n this.eventHandler.emit(event);\n return this.eventStopReturnCode(event);\n }\n\n\n return true;\n }\n\n /**\n * If requested to stop event propagation, stop it\n * and return false.\n * Otherwise, return true.\n *\n * @param event Event being handled\n */\n private eventStopReturnCode(event:Event):boolean {\n if (this.stopEventPropagation) {\n event.preventDefault();\n\n if (!!event.stopPropagation) {\n event.stopPropagation();\n }\n\n return false;\n }\n\n return true;\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\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injectable} from '@angular/core';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {buildApiV3Filter} from 'core-app/components/api/api-v3/api-v3-filter-builder';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\n\n@Injectable()\nexport class RelationsDmService {\n\n constructor(private halResourceService:HalResourceService,\n private pathHelper:PathHelperService) {\n\n }\n\n public load(workPackageId:string):Promise {\n return this.halResourceService.get>(\n this.pathHelper.api.v3.work_packages.id(workPackageId).relations, {})\n .toPromise()\n .then((collection:CollectionResource) => collection.elements);\n }\n\n public loadInvolved(workPackageIds:string[]):Promise {\n let validIds = _.filter(workPackageIds, id => /\\d+/.test(id));\n\n if (validIds.length === 0) {\n return Promise.resolve([]);\n }\n\n return this.halResourceService.get>(\n this.pathHelper.api.v3.relations.toPath(),\n {\n filters: buildApiV3Filter('involved', '=', validIds).toJson()\n })\n .toPromise()\n .then((collection:CollectionResource) => collection.elements);\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {QueryFilterInstanceSchemaResource} 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\";\n\n@Injectable()\nexport class QueryFiltersService {\n\n /**\n * Get the matching schema of the filter resource\n * from the schema\n */\n public 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 * Map all filters of the query with the appropriate schema.\n * @param query\n * @param form\n */\n public mapSchemasIntoFilters(query:QueryResource, form:QueryFormResource) {\n query.filters.forEach(filter => {\n filter.schema = this.getFilterSchema(filter, form)!;\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//++\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-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 {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-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 {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} 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\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 /**\n * Required HTML id for the edit field\n */\n public abstract get htmlId():string;\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-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 {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","//-- 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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 \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// ++\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","
\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-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 {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-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, 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 {SimpleResource, SimpleResourceCollection} from \"core-app/modules/common/path-helper/apiv3/path-resources\";\nimport {Injector} from \"@angular/core\";\nimport {Constructor} from \"@angular/cdk/table\";\n\nexport class BcfResourcePath extends SimpleResource {\n constructor(readonly injector:Injector,\n basePath:string,\n 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} 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 {throwError} from \"rxjs/internal/observable/throwError\";\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-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 {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\";\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 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.pathHelper.api.v3.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","// -- 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\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 {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})\nexport class NewestActivityOnOverviewComponent extends ActivityPanelBaseController {\n @Input('workPackage') public workPackage:WorkPackageResource;\n\n public latestActivityInfo:ActivityEntryInfo[] = [];\n public trackByHref = AngularTrackingHelpers.trackByHref;\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","// -- 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\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","\n \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-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, 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 {WorkPackageCacheService} from '../../work-packages/work-package-cache.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\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 wpCacheService:WorkPackageCacheService,\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.wpCacheService.loadWorkPackage(this.workPackage.id!).values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n\n let toLoad:string[] = [];\n let parentId = this.workPackage.parent?.id?.toString();\n\n if (parentId) {\n toLoad.push(parentId.toString());\n\n this.wpCacheService\n .require(parentId)\n .then((parent:WorkPackageResource) => {\n this.workPackage.parent = parent;\n });\n }\n\n this.wpCacheService.requireAll(toLoad);\n });\n }\n}\n","
\n
\n
\n

\n

\n
\n
\n \n \n \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-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 * 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}\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 {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-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 {Injectable, Injector} from '@angular/core';\nimport {WorkPackageCacheService} from '../work-packages/work-package-cache.service';\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\";\n\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 {WorkPackageDmService} from \"core-app/modules/hal/dm-services/work-package-dm.service\";\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\";\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 wpCacheService:WorkPackageCacheService,\n protected halResourceService:HalResourceService,\n protected querySpace:IsolatedQuerySpace,\n protected authorisationService:AuthorisationService,\n protected halEditing:HalResourceEditingService,\n protected workPackageDmService:WorkPackageDmService,\n protected halEvents:HalEventsService) {\n super();\n\n this.halEditing\n .comittedChanges\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.halEvents.push(wp, { eventType: 'created' });\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) {\n return this.getEmptyForm(projectIdentifier).then(form => {\n return this.fromCreateForm(form);\n });\n }\n\n public createNewTypedWorkPackage(projectIdentifier:string|undefined|null, type:number) {\n return this.workPackageDmService.typedCreateForm(type, projectIdentifier).then(form => {\n return this.fromCreateForm(form);\n });\n }\n\n public fromCreateForm(form:FormResource):WorkPackageChangeset {\n let wp = this.halResourceService.createHalResourceOfType('WorkPackage', form.payload.$plain());\n wp.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.workPackageDmService.emptyCreateForm(request).then(form => {\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 = fromCreateForm(form);\n let wp = this.halResourceService.createHalResourceOfType('WorkPackage', form.payload.$plain());\n\n wp.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.workPackageDmService.emptyCreateForm({}, projectIdentifier);\n }\n\n return this.form;\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) {\n let changePromise = this.continueExistingEdit(type);\n\n if (!changePromise) {\n changePromise = this.createNewWithDefaults(projectIdentifier, type);\n }\n\n return changePromise.then((change:WorkPackageChangeset) => {\n this.authorisationService.initModelAuth('work_package', change.pristineResource);\n this.halEditing.updateValue(newWorkPackageHref, change);\n this.wpCacheService.updateWorkPackage(change.pristineResource);\n\n return change;\n });\n }\n\n protected reset() {\n this.wpCacheService.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 protected createNewWithDefaults(projectIdentifier:string|null|undefined, type?:number) {\n let changePromise = null;\n\n if (type) {\n changePromise = this.createNewTypedWorkPackage(projectIdentifier, type);\n } else {\n changePromise = this.createNewWorkPackage(projectIdentifier);\n }\n\n return changePromise.then((change:WorkPackageChangeset) => {\n if (!change) {\n throw 'No new work package was created';\n }\n\n let except:string[] = [];\n\n if (type) {\n except = ['type'];\n }\n\n this.applyDefaults(change, change.projectedResource, except);\n\n return change;\n });\n }\n\n /**\n * Apply values to the work package from the current set of filters\n *\n * @param changeset\n * @param wp\n * @param except\n */\n private applyDefaults(change:WorkPackageChangeset, wp:WorkPackageResource, except:string[]) {\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 filter = new WorkPackageFilterValues(this.injector, change, query.filters, except);\n filter.applyDefaultsFromFilters();\n }\n }\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","// -- 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\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-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 {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 {WorkPackageCacheService} from '../../work-packages/work-package-cache.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\";\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 wpCacheService:WorkPackageCacheService,\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.wpCacheService\n .observe(this.workPackageId)\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/**\n * Return the row html id attribute for the given work package ID.\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 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","//-- 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\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} from '@angular/core';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\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","import {Injector} from '@angular/core';\nimport {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.service';\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\";\n\nexport class HierarchyRenderPass extends PrimaryRenderPass {\n\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() states:States;\n @InjectField() wpCacheService:WorkPackageCacheService;\n @InjectField() wpTableHierarchies:WorkPackageViewHierarchiesService;\n\n // Remember which rows were already rendered\n private 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.wpCacheService.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-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 {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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.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 class TableEditForm extends EditForm {\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() public wpCacheService:WorkPackageCacheService;\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.wpCacheService\n .requireAndStream(this.workPackageId)\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 // 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}\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';\n\nimport {States} from '../states.service';\nimport {WorkPackageCacheService} from '../work-packages/work-package-cache.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';\n\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\";\n\nexport class WorkPackageTable {\n\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() wpCacheService:WorkPackageCacheService;\n @InjectField() states:States;\n @InjectField() I18n:I18nService;\n\n public originalRows:string[] = [];\n public originalRowIndex:{ [id:string]:WorkPackageTableRow } = {};\n\n // WP rows builder\n // Ordered by priority\n private builders = [\n new HierarchyRowsBuilder(this.injector, this),\n new GroupedRowsBuilder(this.injector, this),\n new PlainRowsBuilder(this.injector, this)\n ];\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.wpCacheService.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","//-- 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\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {Injectable} from \"@angular/core\";\nimport {States} from \"core-components/states.service\";\nimport {buildApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\n\n@Injectable()\nexport class WorkPackageDmService {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService,\n protected states:States) {\n }\n\n /**\n * Loads a WorkPackage.\n *\n * @param id The ID of the WorkPackage.\n * @param force Bypass any cached value?\n * @returns {IPromise|IPromise} A promise for the WorkPackage.\n */\n public loadWorkPackageById(id:string, force = false) {\n const url = this.pathHelper.api.v3.work_packages.id(id).toString();\n\n return this.halResourceService.get(url).toPromise();\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 public loadWorkPackagesCollectionsFor(ids:string[]):Promise {\n return this.halResourceService.getAllPaginated(\n this.pathHelper.api.v3.work_packages.toString(),\n ids.length,\n {\n filters: buildApiV3Filter('id', '=', ids).toJson(),\n }\n ) as any; // WorkPackageCollectionResource does not satisfy constraint HalResource[]\n }\n\n /**\n * Returns a promise to post `/api/v3/work_packages/form`.\n *\n * @returns An empty work package form resource.\n */\n public emptyCreateForm(request:any, projectIdentifier?:string|null):Promise {\n return this.halResourceService\n .post(this.workPackagesFormPath(projectIdentifier), request)\n .toPromise();\n }\n\n /**\n * Returns a promise to post `/api/v3/work_packages/form` where the\n * type has already been set to the one provided.\n *\n * @param typeId: The id of the type to initialize the form with\n * @param projectIdentifier: The project to which the work package is initialized\n * @returns An empty work package form resource.\n */\n public typedCreateForm(typeId:number, projectIdentifier:string|undefined|null):Promise {\n\n const typeUrl = this.pathHelper.api.v3.types.id(typeId).toString();\n const request = { _links: { type: { href: typeUrl } } };\n\n return this.halResourceService\n .post(this.workPackagesFormPath(projectIdentifier), request)\n .toPromise();\n }\n\n /**\n * Create a work package from a form payload\n *\n * @param payload\n * @return {Promise}\n */\n public createWorkPackage(payload:any):Promise {\n return this.halResourceService\n .post(this.pathHelper.api.v3.work_packages.path, payload)\n .toPromise();\n }\n\n private workPackagesFormPath(projectIdentifier:string|null|undefined):string {\n if (projectIdentifier) {\n return this.pathHelper.api.v3.projects.id(projectIdentifier).work_packages.form.toString();\n } else {\n return this.pathHelper.api.v3.work_packages.form.toString();\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// ++\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","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 create(type:'full'|'constrained', wrapper:HTMLElement, context:ICKEditorContext, initialData:string|null = null) {\n const editor = 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 return editor\n .createCustomized(contentWrapper, {\n openProject: this.createConfig(context),\n initialData: initialData,\n language: {\n content: contentLanguage\n }\n })\n .then((editor) => {\n // Add decoupled toolbar\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 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-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 {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-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 {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 {QueryDmService} from 'core-app/modules/hal/dm-services/query-dm.service';\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\";\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 QueryDm:QueryDmService,\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.QueryDm\n .listNonHidden(this.CurrentProject.identifier)\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(`#wp-query-menu-item-${ui.item.auto_id} .wp-query-menu--item-link`)\n .focus();\n }\n\n return false;\n },\n appendTo: '.wp-query-menu--results-container',\n classes: {\n 'ui-autocomplete': 'wp-query-menu--search-ul -inplace',\n 'ui-menu-divider': 'wp-query-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', '.wp-query-menu--item');\n this._search('');\n },\n _renderItem: function (this:{}, ul:any, item:IAutocompleteItem) {\n const link = jQuery('')\n .addClass('wp-query-menu--item-link')\n .attr('href', thisComponent.buildQueryItemUrl(item))\n .text(item.label);\n\n const li = jQuery('
  • ')\n .addClass(`ui-menu-item wp-query-menu--item`)\n .attr('id', `wp-query-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 wp-query-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('.wp-query-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(`.wp-query-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(`#wp-query-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('.wp-query-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', '.wp-query-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","
    \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-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\nexport const selectorTableSide = \".work-packages-tabletimeline--table-side\";\nexport const selectorTimelineSide = \".work-packages-tabletimeline--timeline-side\";\nconst jQueryScrollSyncEventNamespace = \".scroll-sync\";\nconst scrollStep = 15;\n\n\nfunction getXandYScrollDeltas(ev: WheelEvent): [number, number] {\n let x = ev.deltaX;\n let y = ev.deltaY;\n\n if (ev.shiftKey) {\n x = y;\n y = 0;\n }\n\n return [x, y];\n}\n\nfunction getPlattformAgnosticScrollAmount(originalValue: number) {\n if (originalValue === 0) {\n return originalValue;\n }\n\n let delta = scrollStep;\n\n // Browser-specific logic\n // TODO\n\n if (originalValue < 0) {\n delta *= -1;\n }\n return delta;\n}\n\nfunction syncWheelEvent(jev: JQuery.TriggeredEvent, elementTable: JQuery, elementTimeline: JQuery) {\n const scrollTarget = jev.target;\n const ev: WheelEvent = jev.originalEvent as any;\n let [deltaX, deltaY] = getXandYScrollDeltas(ev);\n\n if (deltaY === 0) {\n return;\n }\n\n deltaX = getPlattformAgnosticScrollAmount(deltaX); // apply only in target div\n deltaY = getPlattformAgnosticScrollAmount(deltaY); // apply in both divs\n\n window.requestAnimationFrame(function () {\n elementTable[0].scrollTop = elementTable[0].scrollTop + deltaY;\n elementTimeline[0].scrollTop = elementTimeline[0].scrollTop + deltaY;\n\n scrollTarget.scrollLeft = scrollTarget.scrollLeft + deltaX;\n });\n}\n\n/**\n * Activate or deactivate the scroll-sync between the table and timeline view.\n *\n * @param $element true if the timeline is visible, false otherwise.\n */\nexport function createScrollSync($element:JQuery) {\n\n var elTable = jQuery($element).find(selectorTableSide);\n var elTimeline = jQuery($element).find(selectorTimelineSide);\n\n return (timelineVisible: boolean) => {\n\n // state vars\n var syncedLeft = false;\n var syncedRight = false;\n\n if (timelineVisible) {\n // setup event listener for table\n elTable.on(\"wheel\" + jQueryScrollSyncEventNamespace, (jev: JQuery.TriggeredEvent) => {\n syncWheelEvent(jev, elTable, elTimeline);\n });\n elTable.on(\"scroll\" + jQueryScrollSyncEventNamespace, (ev: JQuery.TriggeredEvent) => {\n syncedLeft = true;\n if (!syncedRight) {\n elTimeline[0].scrollTop = ev.target.scrollTop;\n }\n if (syncedLeft && syncedRight) {\n syncedLeft = false;\n syncedRight = false;\n }\n });\n\n // setup event listener for timeline\n elTimeline.on(\"wheel\" + jQueryScrollSyncEventNamespace, (jev: JQuery.TriggeredEvent) => {\n syncWheelEvent(jev, elTable, elTimeline);\n });\n elTimeline.on(\"scroll\" + jQueryScrollSyncEventNamespace, (ev: JQuery.TriggeredEvent) => {\n syncedRight = true;\n if (!syncedLeft) {\n elTable[0].scrollTop = ev.target.scrollTop;\n }\n if (syncedLeft && syncedRight) {\n syncedLeft = false;\n syncedRight = false;\n }\n });\n } else {\n elTable.off(jQueryScrollSyncEventNamespace);\n }\n };\n\n}\n","
  • \n \n \n \n\n {{ 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-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, 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-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 {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","import {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageCacheService} from '../../work-packages/work-package-cache.service';\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 protected wpCacheService:WorkPackageCacheService) {\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
    \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-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, 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","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(wpId, element, evt);\n\n return false;\n }\n\n\n protected handleWorkPackage(wpId:any, element:JQuery, evt:JQuery.TriggeredEvent) {\n this.setSelection(wpId, element, evt);\n\n // open work package on mobile after first click\n this.openFullViewOnMobile(wpId);\n }\n\n protected openFullViewOnMobile(wpId:string) {\n if (this.deviceService.isMobile) {\n this.$state.go(\n 'work-packages.show',\n {workPackageId: wpId}\n );\n }\n }\n\n protected setSelection(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 // 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 {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 if (column.id.startsWith('__internal') || this.isColumnBeingEdited(workPackage, column)) {\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-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 {\n AfterViewInit,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostListener,\n Injector,\n Input,\n OnInit\n} from '@angular/core';\nimport {AuthorisationService} from 'core-app/modules/common/model-auth/model-auth.service';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {filter} from 'rxjs/operators';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {onClickOrEnter} from '../wp-fast-table/handlers/click-or-enter-handler';\nimport {WorkPackageTable} from '../wp-fast-table/wp-fast-table';\nimport {WorkPackageCreateService} from '../wp-new/wp-create.service';\nimport {\n inlineCreateCancelClassName,\n InlineCreateRowBuilder,\n inlineCreateRowClassName\n} from './inline-create-row-builder';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {FocusHelperService} from 'core-app/modules/common/focus/focus-helper';\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\";\n\n@Component({\n selector: '[wpInlineCreate]',\n templateUrl: './wp-inline-create.component.html'\n})\nexport class WorkPackageInlineCreateComponent extends UntilDestroyedMixin implements OnInit, AfterViewInit {\n\n @Input('wp-inline-create--table') table:WorkPackageTable;\n @Input('wp-inline-create--project-identifier') projectIdentifier:string;\n\n // inner state\n public canAdd:boolean = false;\n public canReference:boolean = false;\n\n // Inline create / reference row is active\n public mode:'inactive'|'create'|'reference' = 'inactive';\n\n public focus:boolean = false;\n\n public text = this.wpInlineCreate.buttonTexts;\n\n private currentWorkPackage:WorkPackageResource|null;\n\n private workPackageEditForm:EditForm|undefined;\n\n private editingSubscription:Subscription|undefined;\n\n private $element:JQuery;\n\n constructor(public readonly injector:Injector,\n protected readonly elementRef:ElementRef,\n protected readonly FocusHelper:FocusHelperService,\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 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 }\n\n get isActive():boolean {\n return this.mode !== 'inactive';\n }\n\n ngAfterViewInit() {\n // Mirror the row height in timeline\n const container = jQuery(this.table.timelineBody);\n container.addClass('-inline-create-mirror');\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.currentWorkPackage!.overriddenSchema = 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-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 {Injectable} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\n\n@Injectable()\nexport class PayloadDmService {\n public extract(resource:T, schema:SchemaResource) {\n let payload:any = {\n '_links': {}\n }\n\n var nonLinkProperties = [];\n\n for(var key in schema) {\n if (schema.hasOwnProperty(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.extract(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","// -- 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\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-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 {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 isHiddenFilter(filter:QueryFilterResource) {\n return _.includes(this.wpTableFilters.hidden, filter.id);\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 = !!_.find(this.filters, (f) => f.id !== 'search' && this.isFilterAvailable(f.id));\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 var 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(id:string):boolean {\n return (this.wpTableFilters.availableFilters.some(filter => filter.id === id));\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","
    \n \n\n \n \n\n
      \n
    • \n \n\n
      \n \n \n
      \n
    • \n\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-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, 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\";\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 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 ngOnDestroy() {\n this.unregisterListener();\n }\n\n ngOnInit() {\n this.editMode = this.initializeEditMode;\n\n if (this.initializeEditMode) {\n this.start();\n }\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","//-- 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\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
    \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 {QueryDmService} from 'core-app/modules/hal/dm-services/query-dm.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\";\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() QueryDm:QueryDmService;\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 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 promise = this.QueryDm.loadResults(query, pagination)\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 {QueryDmService} from 'core-app/modules/hal/dm-services/query-dm.service';\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 {QueryFormDmService} from \"core-app/modules/hal/dm-services/query-form-dm.service\";\nimport {distinctUntilChanged, map, take, withLatestFrom} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\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() QueryDm:QueryDmService;\n @InjectField() opModalService:OpModalService;\n @InjectField() tableActionsService:OpTableActionsService;\n @InjectField() wpTableTimeline:WorkPackageViewTimelineService;\n @InjectField() wpTablePagination:WorkPackageViewPaginationService;\n @InjectField() QueryFormDm:QueryFormDmService;\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 this.loadingIndicator = this.QueryDm\n .loadResults(query, this.wpTablePagination.paginationObject)\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 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 = this.QueryFormDm\n .load(query)\n .then((form:QueryFormResource) => {\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.QueryDm\n .find(\n this.queryProps,\n this.queryId,\n this.queryProjectScope\n )\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","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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\nimport {WorkPackageViewDisplayRepresentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.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 wpCacheService:WorkPackageCacheService,\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.wpCacheService.require(predecessorId);\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-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 {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageCacheService} from '../work-package-cache.service';\nimport {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\";\n\n@Component({\n selector: 'wp-watcher-button',\n templateUrl: './wp-watcher-button.html'\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 wpCacheService:WorkPackageCacheService) {\n super();\n }\n\n ngOnInit() {\n this.wpCacheService.loadWorkPackage(this.workPackage.id!)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.setWatchStatus();\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.wpCacheService.loadWorkPackage(this.workPackage.id!, true);\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-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 {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.service';\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {States} from 'core-components/states.service';\nimport {\n displayClassName,\n DisplayFieldRenderer,\n editFieldContainerClass\n} from 'core-components/wp-edit-form/display-field-renderer';\n\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,\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 {IFieldSchema} from \"core-app/modules/fields/field.base\";\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\";\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('fieldName') public fieldName:string;\n @Input('resource') public resource:HalResource;\n @Input('wrapperClasses') public wrapperClasses?:string;\n @Input('displayFieldOptions') public displayFieldOptions:any = {};\n @Input('displayPlaceholder') public displayPlaceholder?:string;\n @Input('isDropTarget') 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 halNotification:HalResourceNotificationService,\n protected ConfigurationService:ConfigurationService,\n protected opContextMenu:OPContextMenuService,\n protected halEditing:HalResourceEditingService,\n protected wpCacheService:WorkPackageCacheService,\n // Get parent field group from injector\n 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 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() {\n const fieldSchema = this.resource.schema[this.fieldName] as IFieldSchema;\n return this.resource.isAttributeEditable(this.fieldName) && fieldSchema && fieldSchema.writable;\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}\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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.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 wpCacheService:WorkPackageCacheService,\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.wpCacheService.require(wpId);\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 => this.wpCacheService.require(id)))\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-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 {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {InputState} from 'reactivestates';\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\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-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 {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-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 {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","//-- 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\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 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-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 {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-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 {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';\n\nexport interface QueryFilterInstanceSchemaResourceLinks {\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\n public get _type() {\n return 'QueryFilterInstanceSchema';\n }\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 let newFilter = new QueryFilterInstanceResource(this.injector, source, true, this.halInitializer, 'QueryFilterInstance');\n\n newFilter.schema = this;\n\n return newFilter;\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-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\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-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\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-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 {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {CallableHalLink} from 'core-app/modules/hal/hal-link/hal-link';\n\nexport class HelpTextResource extends HalResource {\n\n public id:string;\n public attribute:string;\n public attributeCaption:string;\n public scope:string;\n public helpText:api.v3.Formattable;\n}\n\nexport interface HelpTextResource {\n editText?:CallableHalLink;\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\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-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 {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-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 {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-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 {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","//-- 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\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-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 {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-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 {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-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 {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 ProjectResource extends HalResource {\n @InjectField() private schemaCacheService:SchemaCacheService;\n\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 * Get the schema of the project\n * ensure that it's loaded\n *\n * TODO this is duplicating the WorkPackageResource#schema getter\n */\n public get schema():SchemaResource {\n const state = this.schemaCacheService.state(this as any);\n\n if (!state.hasValue()) {\n throw `Accessing schema of ${this.id} without it being loaded.`;\n }\n\n return state.value!;\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-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 {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class GroupResource extends HalResource {\n public name:string;\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\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","//-- 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\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injectable} from '@angular/core';\nimport {RootResource} from 'core-app/modules/hal/resources/root-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {TypeResource} from 'core-app/modules/hal/resources/type-resource';\nimport {States} from 'core-app/components/states.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\n\n@Injectable()\nexport class TypeDmService {\n constructor(protected halResourceService:HalResourceService,\n protected states:States,\n protected pathHelper:PathHelperService) {\n }\n\n public loadAll(projectIdentifier:string|undefined):Promise {\n const typeUrl = this.pathHelper.api.v3.withOptionalProject(projectIdentifier).types.toString();\n\n return this.halResourceService\n .get>(typeUrl)\n .toPromise()\n .then((result:CollectionResource) => {\n // TODO move into a TypeCacheService\n _.each(result.elements, (type) => this.states.types.get(type.href!).putValue(type));\n return result.elements;\n });\n }\n\n public load():Promise {\n return this.halResourceService\n .get(this.pathHelper.api.v3.root.toString())\n .toPromise();\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-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 {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 {ConfigurationDmService} from 'core-app/modules/hal/dm-services/configuration-dm.service';\nimport {HelpTextDmService} from 'core-app/modules/hal/dm-services/help-text-dm.service';\nimport {PayloadDmService} from 'core-app/modules/hal/dm-services/payload-dm.service';\nimport {QueryDmService} from 'core-app/modules/hal/dm-services/query-dm.service';\nimport {QueryFormDmService} from 'core-app/modules/hal/dm-services/query-form-dm.service';\nimport {RelationsDmService} from 'core-app/modules/hal/dm-services/relations-dm.service';\nimport {RootDmService} from 'core-app/modules/hal/dm-services/root-dm.service';\nimport {TypeDmService} from 'core-app/modules/hal/dm-services/type-dm.service';\nimport {OpenProjectHeaderInterceptor} from 'core-app/modules/hal/http/openproject-header-interceptor';\nimport {UserDmService} from 'core-app/modules/hal/dm-services/user-dm.service';\nimport {ProjectDmService} from 'core-app/modules/hal/dm-services/project-dm.service';\nimport {GridDmService} from \"core-app/modules/hal/dm-services/grid-dm.service\";\nimport {TimeEntryDmService} from './dm-services/time-entry-dm.service';\nimport {CommonModule} from \"@angular/common\";\nimport {NewsDmService} from './dm-services/news-dm.service';\nimport {StatusDmService} from \"core-app/modules/hal/dm-services/status-dm.service\";\nimport {VersionDmService} from \"core-app/modules/hal/dm-services/version-dm.service\";\nimport {QueryOrderDmService} from \"core-app/modules/hal/dm-services/query-order-dm.service\";\nimport {MembershipDmService} from \"core-app/modules/hal/dm-services/membership-dm.service\";\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 ConfigurationDmService,\n GridDmService,\n HelpTextDmService,\n MembershipDmService,\n NewsDmService,\n PayloadDmService,\n ProjectDmService,\n QueryDmService,\n QueryOrderDmService,\n QueryFormDmService,\n RelationsDmService,\n RootDmService,\n TimeEntryDmService,\n TypeDmService,\n UserDmService,\n StatusDmService,\n VersionDmService,\n HalResourceNotificationService\n ]\n})\nexport class OpenprojectHalModule { }\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\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} 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 private loadingPromise:Promise;\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 this.loadingPromise = this\n .wpCreate\n .getEmptyForm(this.projectIdentifier)\n .then(form => {\n return this.buildItems(form.schema.type.allowedValues);\n });\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n this.loadingPromise.then(() => {\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-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 {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-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// ++ 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-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, 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","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 {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\";\n\nexport class GroupedRenderPass extends PlainRenderPass {\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 this.workPackageTable.originalRows.forEach((wpId:string) => {\n let row = this.workPackageTable.originalRowIndex[wpId];\n let nextGroup = this.matchingGroup(row.object);\n\n if (nextGroup && currentGroup !== nextGroup) {\n const groupClass = groupClassNameFor(nextGroup);\n let rowElement = this.headerBuilder.buildGroupRow(nextGroup, this.colspan);\n this.appendNonWorkPackageRow(rowElement, groupClass);\n currentGroup = nextGroup;\n }\n\n row.group = currentGroup;\n this.buildSingleRow(row);\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 const hidden = group.collapsed;\n\n let additionalClasses:string[] = [];\n\n let [tr, _] = this.rowBuilder.buildEmpty(row.object);\n additionalClasses.push(groupedRowClassName(group.index));\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","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 colspan = this.wpTableColumns.columnCount + 1;\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, 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","// -- 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\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-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 {Injectable} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {ConfigurationDmService} from \"core-app/modules/hal/dm-services/configuration-dm.service\";\nimport {ConfigurationResource} from \"core-app/modules/hal/resources/configuration-resource\";\nimport * as moment from \"moment\";\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 configurationDm:ConfigurationDmService) {\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 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.configurationDm.load().toPromise().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, index:number|string, container:HTMLElement) {\n index = typeof index === 'string' ? parseInt(index, 10) : index;\n\n const children = Array.from(container.children);\n\n // Append to end if unknown index or no child nodes\n if (index < 0 || index >= children.length || children.length === 0) {\n container.appendChild(el);\n }\n\n // Get the element to insert before\n const sibling = children[index];\n if (sibling) {\n container.insertBefore(el, sibling);\n } else {\n container.appendChild(el);\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//++\n\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injectable} from '@angular/core';\nimport {RootResource} from 'core-app/modules/hal/resources/root-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\n\n@Injectable()\nexport class RootDmService {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService) {\n }\n\n public load():Promise {\n return this.halResourceService\n .get(this.pathHelper.api.v3.root.toString())\n .toPromise();\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {States} from '../../../states.service';\nimport {displayClassName, editableClassName, readOnlyClassName} from '../../../wp-edit-form/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 {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(table:WorkPackageTable) {\n return jQuery(table.tableAndTimelineContainer);\n }\n\n constructor(public readonly injector:Injector, table:WorkPackageTable) {\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 {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(table:WorkPackageTable) {\n return jQuery(table.tableAndTimelineContainer);\n }\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\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 {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 protected table:WorkPackageTable) {\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(table:WorkPackageTable) {\n return jQuery(table.tableAndTimelineContainer);\n }\n\n public abstract handleEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean;\n\n protected openContextMenu(evt:JQuery.TriggeredEvent, workPackageId:string, positionArgs?:any):void {\n const handler = new WorkPackageTableContextMenu(this.injector, workPackageId, jQuery(evt.target) as JQuery, positionArgs, this.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\";\n\nexport class ContextMenuClickHandler extends ContextMenuHandler {\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n super(injector, table);\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(table:WorkPackageTable, 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 super.openContextMenu(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';\n\nexport class ContextMenuKeyboardHandler extends ContextMenuHandler {\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n super(injector, table);\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(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean {\n if (!table.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(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\";\n\nexport class ContextMenuRightClickHandler extends ContextMenuHandler {\n\n @InjectField() readonly wpTableSelection:WorkPackageViewSelectionService;\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n\n super(injector, table);\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(table:WorkPackageTable) {\n return jQuery(table.tableAndTimelineContainer);\n }\n\n public handleEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean {\n if (!table.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,] = this.table.findRenderedRow(wpId);\n\n if (!this.wpTableSelection.isSelected(wpId)) {\n this.wpTableSelection.setSelection(wpId, index);\n }\n\n super.openContextMenu(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 {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-components/wp-edit-form/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 table:WorkPackageTable) {\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(table:WorkPackageTable) {\n return jQuery(table.tbody);\n }\n\n public handleEvent(table:WorkPackageTable, 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] = table.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 }\n\n // Multiple selection if shift present\n if (evt.shiftKey) {\n this.wpTableSelection.setMultiSelectionFrom(table.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 // 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 {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-components/wp-edit-form/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 table:WorkPackageTable) {\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(table:WorkPackageTable) {\n return jQuery(table.tbody);\n }\n\n public handleEvent(table:WorkPackageTable, 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 this.$state.go(\n 'work-packages.show',\n {workPackageId: wpId}\n );\n\n return false;\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {GroupedRowsBuilder} from '../../builders/modes/grouped/grouped-rows-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {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\";\n\nexport class GroupRowHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public querySpace:IsolatedQuerySpace;\n\n private builder:GroupedRowsBuilder;\n\n constructor(public readonly injector:Injector, table:WorkPackageTable) {\n this.builder = new GroupedRowsBuilder(injector, table);\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(table:WorkPackageTable) {\n return jQuery(table.tbody);\n }\n\n public handleEvent(table:WorkPackageTable, 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 let state = this.collapsedState.value || {};\n\n state[groupIdentifier] = !state[groupIdentifier];\n this.collapsedState.putValue(state);\n\n // Refresh groups\n var t0 = performance.now();\n this.builder.refreshExpansionState();\n var t1 = performance.now();\n debugLog('Group redraw took ' + (t1 - t0) + ' milliseconds.');\n }\n\n private get collapsedState() {\n return this.querySpace.collapsedGroups;\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 {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, table:WorkPackageTable) {\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(table:WorkPackageTable) {\n return jQuery(table.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 {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 table:WorkPackageTable) {\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(table:WorkPackageTable) {\n return jQuery(table.tableAndTimelineContainer);\n }\n\n protected workPackage:WorkPackageResource;\n\n public handleEvent(table:WorkPackageTable, 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, _] = table.findRenderedRow(classIdentifier);\n\n // Update single selection if no modifier present\n this.wpTableSelection.setSelection(workPackageId, index);\n\n this.$state.go(\n (this.keepTab as any)[state],\n {workPackageId: workPackageId, focus: true}\n );\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 all affected 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.selection$()\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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\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 wpCacheService:WorkPackageCacheService;\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) => {\n const wpId:string = el.dataset.workPackageId!;\n const rowIndex = this.findRowIndex(el);\n\n try {\n const workPackage = await this.wpCacheService.require(wpId);\n const newOrder = await this.wpTableOrder.move(this.currentOrder, wpId, rowIndex);\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 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.wpCacheService.require(wpId);\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.wpCacheService.require(wpId);\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(order.map(id => this.wpCacheService.require(id)));\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 {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,\n WorkPackageViewHandlerRegistry\n} from \"core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry\";\n\ntype StateTransformers = {\n // noinspection JSUnusedLocalSymbols\n new(injector:Injector, table:WorkPackageTable):any;\n};\n\nexport type TableEventHandler = WorkPackageViewEventHandler;\n\nexport class TableHandlerRegistry extends WorkPackageViewHandlerRegistry {\n\n protected eventHandlers:((t:WorkPackageTable) => WorkPackageViewEventHandler)[] = [\n // Hierarchy expansion/collapsing\n t => new HierarchyClickHandler(this.injector, t),\n // Clicking or pressing Enter on a single cell, editable or not\n t => new EditCellHandler(this.injector, t),\n // Clicking on the details view\n t => new WorkPackageStateLinksHandler(this.injector, t),\n // Clicking on the row (not within a cell)\n t => new RowClickHandler(this.injector, t),\n // Double Clicking on the cell within the row\n t => new RowDoubleClickHandler(this.injector, t),\n // Clicking on group headers\n t => new GroupRowHandler(this.injector, t),\n // Right clicking on rows\n t => new ContextMenuRightClickHandler(this.injector, t),\n // Left clicking on the dropdown icon\n t => new ContextMenuClickHandler(this.injector, t),\n // SHIFT+ALT+F10 on rows\n t => new ContextMenuKeyboardHandler(this.injector, t),\n // Clicking on relations cells\n t => new RelationsCellHandler(this.injector, t)\n ];\n\n protected readonly stateTransformers:StateTransformers[] = [\n SelectionTransformer,\n RowsTransformer,\n ColumnsTransformer,\n TimelineTransformer,\n HierarchyTransformer,\n RelationsTransformer,\n HighlightingTransformer,\n DragAndDropTransformer\n ];\n\n attachTo(viewRef:WorkPackageTable) {\n this.stateTransformers.map((cls) => {\n return new cls(this.injector, viewRef);\n });\n\n super.attachTo(viewRef);\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\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).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 {{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-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 {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input,\n NgZone,\n OnInit,\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 {TableHandlerRegistry} from 'core-components/wp-fast-table/handlers/table-handler-registry';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {combineLatest} from 'rxjs';\nimport {States} from '../states.service';\nimport {\n WorkPackageTableConfiguration,\n WorkPackageTableConfigurationObject\n} from 'core-app/components/wp-table/wp-table-configuration';\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {createScrollSync} from \"core-components/wp-table/wp-table-scroll-sync\";\nimport {WpTableHoverSync} from \"core-components/wp-table/wp-table-hover-sync\";\nimport {WorkPackageTimelineTableController} from \"core-components/wp-table/timeline/container/wp-timeline-container.directive\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\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 WorkPackagesTableController extends UntilDestroyedMixin implements OnInit {\n\n @Input() projectIdentifier:string;\n @Input('configuration') configurationObject:WorkPackageTableConfigurationObject;\n\n public trackByHref = AngularTrackingHelpers.trackByHref;\n\n public configuration:WorkPackageTableConfiguration;\n\n private $element:JQuery;\n\n private scrollSyncUpdate:(timelineVisible:boolean) => any;\n\n private wpTableHoverSync:WpTableHoverSync;\n\n public tableElement:HTMLElement;\n\n public workPackageTable:WorkPackageTable;\n\n public tbody:JQuery;\n\n public query:QueryResource;\n\n public timeline:HTMLElement;\n\n public locale:string;\n\n public text:any;\n\n public results:WorkPackageCollectionResource;\n\n public groupBy:QueryGroupByResource|null;\n\n public columns:QueryColumn[];\n\n public numTableColumns:number;\n\n public timelineVisible:boolean;\n\n public manualSortEnabled:boolean;\n\n public limitedResults = false;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly states:States,\n readonly querySpace:IsolatedQuerySpace,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly zone:NgZone,\n readonly wpTableGroupBy:WorkPackageViewGroupByService,\n readonly wpTableTimeline:WorkPackageViewTimelineService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly wpTableSortBy:WorkPackageViewSortByService) {\n super();\n }\n\n ngOnInit():void {\n this.configuration = new WorkPackageTableConfiguration(this.configurationObject);\n this.$element = jQuery(this.elementRef.nativeElement);\n\n // Clear any old table subscribers\n this.querySpace.stopAllSubscriptions.next();\n\n this.locale = I18n.locale;\n\n this.text = {\n cancel: I18n.t('js.button_cancel'),\n noResults: {\n title: I18n.t('js.work_packages.no_results.title'),\n description: I18n.t('js.work_packages.no_results.description')\n },\n limitedResults: (count:number, total:number) => {\n return I18n.t('js.work_packages.limited_results', { count: count, total: total });\n },\n tableSummary: I18n.t('js.work_packages.table.summary'),\n tableSummaryHints: [\n I18n.t('js.work_packages.table.text_inline_edit'),\n I18n.t('js.work_packages.table.text_select_hint'),\n I18n.t('js.work_packages.table.text_sort_hint')\n ].join(' ')\n };\n\n let statesCombined = combineLatest([\n this.querySpace.results.values$(),\n this.wpTableGroupBy.live$(),\n this.wpTableColumns.live$(),\n this.wpTableTimeline.live$(),\n this.wpTableSortBy.live$()\n ]);\n\n statesCombined.pipe(\n this.untilDestroyed()\n ).subscribe(([results, groupBy, columns, timelines, sort]) => {\n this.query = this.querySpace.query.value!;\n this.results = results;\n\n this.groupBy = groupBy;\n this.columns = columns;\n // Total columns = all available columns + id + checkbox\n this.numTableColumns = this.columns.length + 2;\n\n if (this.scrollSyncUpdate && this.timelineVisible !== timelines.visible) {\n this.scrollSyncUpdate(timelines.visible);\n }\n\n this.timelineVisible = timelines.visible;\n\n this.manualSortEnabled = this.wpTableSortBy.isManualSortingMode;\n this.limitedResults = this.manualSortEnabled && results.total > results.count;\n\n this.cdRef.detectChanges();\n });\n\n this.cdRef.detectChanges();\n }\n\n public ngOnDestroy():void {\n super.ngOnDestroy();\n this.wpTableHoverSync.deactivate();\n }\n\n public registerTimeline(controller:WorkPackageTimelineTableController, timelineBody:HTMLElement) {\n const tbody = this.$element.find('.work-package--results-tbody');\n const scrollContainer = this.$element.find('.work-package-table--container')[0];\n this.workPackageTable = new WorkPackageTable(\n this.injector,\n // Outer container for both table + Timeline\n this.$element[0],\n // Scroll container for the table/timeline\n scrollContainer,\n // Table tbody to insert into\n tbody[0],\n // Timeline body to insert into\n timelineBody,\n // Timeline controller\n controller,\n // Table configuration\n this.configuration\n );\n this.tbody = tbody;\n controller.workPackageTable = this.workPackageTable;\n new TableHandlerRegistry(this.injector).attachTo(this.workPackageTable);\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","import {Injector} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {WorkPackageCacheService} from '../../../work-packages/work-package-cache.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\";\n\nexport const timelineCellClassName = 'wp-timeline-cell';\n\nexport class TimelineRowBuilder {\n\n @InjectField() public states:States;\n @InjectField() public wpTableTimeline:WorkPackageViewTimelineService;\n @InjectField() public wpCacheService:WorkPackageCacheService;\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","// -- 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\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\n @InjectField() public ConfigurationService:ConfigurationService;\n\n public get name() {\n return 'comment';\n }\n\n public get required() {\n return true;\n }\n\n ngOnInit() {\n super.ngOnInit();\n this.rawValue = this.rawValue || '';\n }\n}\n","import {Component, Input, OnInit} from '@angular/core';\nimport {WorkPackageCacheService} from '../../work-packages/work-package-cache.service';\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';\n\n@Component({\n templateUrl: './wp-relations-count.html',\n selector: 'wp-watchers-count',\n})\nexport class WorkPackageWatchersCountComponent extends UntilDestroyedMixin implements OnInit {\n @Input('wpId') wpId:string;\n public count:number = 0;\n\n constructor(protected wpCacheService:WorkPackageCacheService,\n protected wpWatcherService:WorkPackageWatchersService) {\n super();\n }\n\n ngOnInit():void {\n this.wpCacheService.loadWorkPackage(this.wpId.toString()).values$()\n .pipe(\n this.untilDestroyed()\n ).subscribe((workPackage) => {\n this.wpWatcherService.require(workPackage)\n .then((watchers:HalResource[]) => {\n this.count = watchers.length;\n });\n });\n }\n}\n"," 0\"\n [textContent]=\"count\">\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\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-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 {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';\n\nexport class QueryFilterInstanceResource extends HalResource {\n public filter:QueryFilterResource;\n public operator:QueryOperatorResource;\n public values:HalResource[]|string[];\n public schema:QueryFilterInstanceSchemaResource;\n private memoizedCurrentSchemas:{ [key:string]:QueryFilterInstanceSchemaResource } = {};\n\n /**\n * Create a copied filter, taking over the manually set schema instance.\n */\n public $copy():T {\n let clone = super.$copy() as any;\n clone.schema = this.schema;\n\n return clone;\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.schema || !this.operator) {\n return null;\n }\n\n let key = this.operator.href!.toString();\n\n if (this.memoizedCurrentSchemas[key] === undefined) {\n this.memoizedCurrentSchemas[key] = this.schema.resultingSchema(this.operator);\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.schema.availableOperators, (operator:QueryOperatorResource) => operator.id === operatorSymbol) as QueryOperatorResource|undefined;\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 };\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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {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 */\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}","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\";\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 }\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(filter.schema.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","
    \n
    \n \n &ngsp;\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//++\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-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 {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\";\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|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-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 {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/hal/dm-services/query-order-dm.service\";\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-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 {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","// -- 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\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","//-- 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\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 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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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","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","
    \n \n \n \n \n
    \n

    {{ selectedTitle }}\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 {\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() protected readonly 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 {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-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 {AttributeHelpTextsService} from './attribute-help-text.service';\nimport {HelpTextDmService} from 'core-app/modules/hal/dm-services/help-text-dm.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/common/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 helpTextDm:HelpTextDmService,\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 if (element.dataset.helpTextId) {\n this.helpTextId = element.dataset.helpTextId!;\n this.attribute = element.dataset.attribute!;\n this.attributeScope = element.dataset.attributeScope!;\n this.additionalLabel = element.dataset.additionalLabel!;\n }\n\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.helpTextDm.load(this.helpTextId);\n } else {\n return this.attributeHelpTexts.require(this.attribute, this.attributeScope);\n }\n }\n}\n\n","\n \n {{ additionalLabel }}\n\n","import {Injectable} from \"@angular/core\";\nimport {from, Observable} from \"rxjs\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {GridDmService} from \"core-app/modules/hal/dm-services/grid-dm.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {map, tap} from \"rxjs/operators\";\nimport {Board, BoardType} from \"core-app/modules/boards/board/board\";\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class BoardDmService {\n\n constructor(protected GridDm:GridDmService,\n protected PathHelper:PathHelperService,\n protected authorisationService:AuthorisationService,\n protected CurrentProject:CurrentProjectService,\n protected halResourceService:HalResourceService) {\n }\n\n /**\n * Return all boards in the current scope of the project\n *\n * @param projectIdentifier\n */\n public allInScope(projectIdentifier:string|null = this.CurrentProject.identifier) {\n const path = this.boardPath(projectIdentifier);\n\n return from(\n this.GridDm.list({ filters: [['scope', '=', [path]]] })\n )\n .pipe(\n tap(collection => this.authorisationService.initModelAuth('boards', collection.$links)),\n map(collection => collection.elements.map(grid => new Board(grid)))\n );\n }\n\n /**\n * Load one board based on ID\n */\n public one(id:number):Observable {\n return from(this.GridDm.one(id))\n .pipe(\n map(grid => new Board(grid))\n );\n }\n\n /**\n * Save the changes to the board\n */\n public save(board:Board) {\n return this.fetchSchema(board)\n .then(schema => this.GridDm.update(board.grid, schema))\n .then(grid => {\n board.grid = grid;\n return board;\n });\n }\n\n private fetchSchema(board:Board) {\n return this.GridDm.updateForm(board.grid)\n .then((form) => form.schema);\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|null = this.CurrentProject.identifier) {\n return this.PathHelper.projectBoardsPath(projectIdentifier);\n }\n\n /**\n * Create a new board\n * @param type\n * @param name\n */\n public async create(type:BoardType, name:string, actionAttribute?:string):Promise {\n return this.createGrid(type, name, actionAttribute)\n .then(grid => new Board(grid));\n }\n\n public delete(board:Board):Promise {\n if (!board.grid.delete) {\n return Promise.reject(\"Deletion not possible\");\n }\n\n return board.grid.delete();\n }\n\n\n private createGrid(type:BoardType, name:string, actionAttribute?:string):Promise {\n const path = this.boardPath();\n let payload:any = _.set({ name: name }, '_links.scope.href', path);\n payload.options = {\n type: type,\n };\n\n if (actionAttribute) {\n payload.options.attribute = actionAttribute;\n }\n\n return this.GridDm\n .createForm(payload)\n .then((form) => {\n let resource = this.halResourceService.createHalResource(form.payload.$source);\n return this.GridDm.create(resource, form.schema);\n });\n }\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-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 {Injectable} from '@angular/core';\nimport {AbstractDmService} from \"core-app/modules/hal/dm-services/abstract-dm.service\";\nimport {NewsResource} from \"core-app/modules/hal/resources/news-resource\";\n\n@Injectable()\nexport class NewsDmService extends AbstractDmService {\n protected listUrl() {\n return this.pathHelper.api.v3.news.toString();\n }\n\n protected oneUrl(id:number|string) {\n return this.pathHelper.api.v3.news.id(id).toString();\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\nimport {Injectable} from \"@angular/core\";\n\ndeclare global {\n interface Window {\n gon:GonType;\n }\n}\n\nexport interface GonType {\n [key:string]:unknown;\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-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 {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-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 {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injectable} from '@angular/core';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {StatusResource} from \"core-app/modules/hal/resources/status-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\n\n@Injectable()\nexport class StatusDmService {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService) {\n }\n\n public one(id:string|number):Promise {\n return this.halResourceService\n .get(this.pathHelper.api.v3.statuses.id(id).toString())\n .toPromise();\n }\n\n public list():Promise> {\n return this.halResourceService\n .get>(this.pathHelper.api.v3.statuses.toString())\n .toPromise();\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// ++\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 {QueryFormDmService} from 'core-app/modules/hal/dm-services/query-form-dm.service';\nimport {PaginationObject, QueryDmService} from 'core-app/modules/hal/dm-services/query-dm.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 {from, Observable, of} from 'rxjs';\nimport {input} from \"reactivestates\";\nimport {catchError, mergeMap, share, switchMap, take} from \"rxjs/operators\";\nimport {WorkPackageViewPaginationService} 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\";\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 QueryDm:QueryDmService,\n protected QueryFormDm:QueryFormDmService,\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.QueryDm.stream(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 list from an existing query object.\n */\n public loadResultsList(query:QueryResource, additionalParams:PaginationObject):Promise {\n return this.QueryDm\n .loadResults(query, additionalParams)\n .then((loadedQuery) => {\n\n this.wpStatesInitialization.updateQuerySpace(loadedQuery, loadedQuery.results);\n this.wpStatesInitialization.updateChecksum(loadedQuery, loadedQuery.results);\n return query.results;\n });\n }\n\n /**\n * Reload the list of work packages for the current query keeping the\n * pagination options.\n */\n public reloadCurrentResultsList():Promise {\n let pagination = this.getPaginationInfo();\n let query = this.currentQuery;\n\n return this.loadResultsList(query, pagination);\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.QueryFormDm.load(query).then((form:QueryFormResource) => {\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.QueryDm.create(query, form);\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.QueryDm.delete(query);\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.QueryDm.update(query, form).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.QueryDm.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 private 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.QueryFormDm.loadWithParams(queryProps, queryId, projectIdentifier)\n .then(form => {\n this.QueryDm.findDefault({ pageSize: 0 }, projectIdentifier)\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-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 {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 \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\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 {QueryDmService} from \"core-app/modules/hal/dm-services/query-dm.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() QueryDm:QueryDmService;\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-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 {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\";\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 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-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 {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 {WPFocusState} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service\";\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 // Current focused work package (e.g, row preselected for details button)\n focusedWorkPackage:InputState = input();\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-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 {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","// -- 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\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 \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-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 {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","import {ChangeDetectorRef, Component, ElementRef, Inject, OnDestroy, OnInit, ViewChild} 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, HttpResponse} from '@angular/common/http';\nimport {\n LoadingIndicatorService,\n withDelayedLoadingIndicator\n} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\nimport {switchMap, takeWhile, map} from 'rxjs/operators';\nimport {interval, Observable, Subscription} from 'rxjs';\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\n\ninterface ExportLink extends HalLink {\n identifier:string;\n}\n\n/*\nModal for exporting work packages to different formats. The user may choose from a variety of formats (e.g. PDF and CSV).\n\nThe backend may choose to provide the export right away (synchronously) or delayed. In the later case, the modal will poll the\nbackend until the export is done.\nBecause the modal has to deal with both cases, without knowing upfront whether the download will be delayed or not, it needs\nto treat every download expecting it to be delayed. Because of this, the modal cannot simply provide download hrefs which would\n allow the browser to download the export but rather has to first check whether an export is delayed or not, and if it is delayed,\n it has to wait until the export is ready. Because of the necessary check, the modal has a hidden link that it clicks on to perform\n the actual download once the export is ready (delayed or not).\n\nThe 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})\nexport class WpTableExportModal extends OpModalComponent implements OnInit, OnDestroy {\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 public downloadHref:string;\n public isLoading = false;\n private subscription?:Subscription;\n\n @ViewChild('downloadLink') downloadLink:ElementRef;\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.downloadSwitched(this.locals.link);\n } else {\n this.querySpace.results\n .valuesPromise()\n .then((results) => this.exportOptions = this.buildExportOptions(results!));\n }\n }\n\n ngOnDestroy() {\n super.ngOnDestroy();\n this.safeUnsubscribe();\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\n this.downloadSwitched(url);\n }\n\n private downloadSwitched(url:string) {\n this\n .performRequest(url)\n .subscribe(\n (data) => {\n if (data.status === 200) {\n this.download(data.url!);\n }\n\n if (data.status === 202 && this.linkHeaderUrl(data)) {\n this.pollUntilDownload(this.linkHeaderUrl(data)!);\n }\n },\n (error:HttpErrorResponse) => this.handleError(error.message));\n }\n\n private pollUntilDownload(url:string) {\n this.isLoading = true;\n\n this.subscription = interval(1000)\n .pipe(\n switchMap(() => this.performRequest(url)),\n takeWhile(response => response.status === 200, true),\n map(response => JSON.parse(response.body)),\n takeWhile(body => body.status === 'Processing', true),\n withDelayedLoadingIndicator(this.loadingIndicator.getter('modal')),\n ).subscribe(body => {\n if (body.status === 'Completed') {\n this.download(body.link!);\n } else if (body.status === 'Error') {\n this.handleError(body.message);\n }\n },\n error => this.handleError(error.message),\n () => this.isLoading = false\n );\n }\n\n private performRequest(url:string):Observable> {\n return this\n .httpClient\n .get(url, { observe: 'response', responseType: 'text' });\n }\n\n private handleError(error:string) {\n this.isLoading = false;\n this.notifications.addError(error || 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 private download(url:string) {\n this.downloadHref = url;\n\n setTimeout(() => {\n this.downloadLink.nativeElement.click();\n this.service.close();\n });\n }\n\n private linkHeaderUrl(data:HttpResponse) {\n let link = data.headers.get('link');\n\n if (!link) {\n return null;\n }\n\n let match = link.match(/<([^>]+)>/);\n\n if (!match) {\n return null;\n } else {\n return match[1];\n }\n }\n\n private safeUnsubscribe() {\n if (this.subscription) {\n this.subscription.unsubscribe();\n }\n }\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-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 {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 'id',\n 'parent',\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 'subjectOrId'\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.loadCurrentFiltersSchemas(filters).then(() => {\n this.availableState.putValue(schema.filtersSchemas.elements);\n this.pristineState.putValue(filters);\n });\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 /**\n * Ensure all filter schemas are loaded.\n * @param filters\n */\n private loadCurrentFiltersSchemas(filters:QueryFilterInstanceResource[]):Promise {\n return Promise.all(filters.map((filter:QueryFilterInstanceResource) => {\n const href = `/api/v3/queries/filter_instance_schemas/${filter.id}`;\n if (filter.schema) {\n return filter.schema.$load();\n } else {\n return this.states.schemas\n .get(href)\n .valuesPromise()\n .then(schema => filter.schema = schema as QueryFilterInstanceSchemaResource);\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// ++\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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\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\";\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 wpCacheService:WorkPackageCacheService,\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.wpCacheService.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-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 {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() protected readonly 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","//-- 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\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","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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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/widgets/datepicker.js');\nrequire('jquery-ui/ui/widgets/dialog.js');\nrequire('jquery-ui/ui/widgets/autocomplete.js');\nrequire('jquery-ui/ui/widgets/sortable.js');\nrequire('jquery-ui/ui/widgets/tooltip.js');\nrequire('./misc/datepicker-defaults');\n\nrequire('jquery-ui/ui/i18n/datepicker-en-GB.js');\nrequire('jquery-ui/ui/i18n/datepicker-de.js');\n\nrequire('jquery-ui/ui/widgets/dialog.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!../vendor/i18n\");\n\n// Localization for fullcalendar\nrequire(\"@fullcalendar/core/locales-all.min\");\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\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-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 {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 ChangeMap = { [attribute:string]:unknown };\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) => delete this.changes[k]);\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):void {\n this.changes[key] = value;\n }\n\n /**\n * Get a single value from the changeset\n * @param key\n */\n public get(key:string):unknown|undefined {\n return this.changes[key];\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 {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\";\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 change set */\n public projectedResource:T;\n\n constructor(pristineResource:T,\n public readonly state?:InputState>,\n loadedForm:FormResource|null = null) {\n this.updatePristineResource(pristineResource);\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 public getSchemaName(attribute:string):string {\n if (this.projectedResource.getSchemaName) {\n return this.projectedResource.getSchemaName(attribute);\n } else {\n return attribute;\n }\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 as string;\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 * Return a shallow copy of the changes\n */\n public get changes():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) {\n const fieldSchema = this.schema[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 * Special case for schema , which is overridden.\n * @param key\n */\n private proxyGet(key:string) {\n if (key === 'schema') {\n return this.schema;\n }\n\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.get(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 public setValue(key:string, val:any) {\n this.changeset.set(key, val);\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 return this.form$.getValueOr(this.pristineResource).schema;\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:unknown, key:string) => {\n const fieldSchema:IFieldSchema|undefined = this.schema[key];\n if (!(typeof (fieldSchema) === 'object' && fieldSchema.writable)) {\n debugLog(`Trying to write ${key} but is not writable in schema`);\n return;\n }\n\n // Override in _links if it is a linked property\n if (reference._links[key]) {\n plainPayload._links[key] = this.getLinkedValue(val, fieldSchema);\n } else {\n plainPayload[key] = val;\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|undefined = this.schema[key];\n if (!(typeof (fieldSchema) === 'object' && 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-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 {Injectable} from '@angular/core';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {HttpClient} from \"@angular/common/http\";\n\nexport type QueryOrder = { [wpId:string]:number };\n\n@Injectable()\nexport class QueryOrderDmService {\n constructor(protected http:HttpClient,\n protected pathHelper:PathHelperService) {\n }\n\n public get(id:string):Promise {\n return this.http\n .get(\n this.orderPath(id)\n )\n .toPromise()\n .then(result => result || {});\n }\n\n public update(id:string, delta:QueryOrder):Promise {\n return this.http\n .patch(\n this.orderPath(id),\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(id, delta);\n }\n\n protected orderPath(id:string) {\n return this.pathHelper.api.v3.queries.id(id).order.toString();\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-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 {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\";\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 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-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, 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-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, 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\";\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.pathHelper.api.v3.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 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-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 {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\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 get active() {\n return true;\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 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 /**\n * Return a unique ID for this edit field\n */\n public get htmlId() {\n return `wp-${this.resource.id}-inline-edit--field-${this.fieldName}`;\n }\n\n /**\n * Return the field label\n */\n public get fieldLabel() {\n return this.schema.name || this.fieldName;\n }\n\n public get 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","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","// -- 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\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","import {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {Constructor} from \"@angular/cdk/table\";\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 public optionalId(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 public filtered(filters:ApiV3FilterBuilder) {\n return this.toString() + '/?' + filters.toParams();\n }\n}\n\nexport class SimpleResource {\n public readonly path:string;\n\n constructor(protected basePath:string, readonly id:string|number) {\n this.path = `${this.basePath}/${id}`;\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-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 {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\";\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 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","// -- 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\nimport {SimpleResource} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class ApiV3WorkPackagePaths extends SimpleResource {\n constructor(basePath:string, readonly workPackageId:string|number) {\n super(basePath, workPackageId);\n }\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/relations\n public readonly relations = this.path + '/relations';\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/revisions\n public readonly revisions = this.path + '/revisions';\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/activities\n public readonly activities = this.path + '/activities';\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/available_watchers\n public readonly available_watchers = this.path + '/available_watchers';\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/available_projects\n public readonly available_projects = this.path + '/available_projects';\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\nimport {ApiV3WorkPackagePaths} from 'core-app/modules/common/path-helper/apiv3/work_packages/apiv3-work-package-paths';\nimport {\n SimpleResource,\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class ApiV3WorkPackagesPaths extends SimpleResourceCollection {\n // Base path\n public readonly path:string;\n\n constructor(basePath:string) {\n super(basePath, 'work_packages');\n }\n\n // Static paths\n\n // /api/v3/(projects/:projectIdentifier)/work_packages/form\n public readonly form = new SimpleResource(this.path, 'form');\n\n // /api/v3/(projects/:projectIdentifier)/work_packages/:workPackageId\n public id(workPackageId:string|number):ApiV3WorkPackagePaths {\n return new ApiV3WorkPackagePaths(this.path, workPackageId);\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\nimport {SimpleResource} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class ApiV3UserPaths extends SimpleResource {\n constructor(basePath:string, readonly userId:string|number) {\n super(basePath, userId);\n }\n\n // /api/v3/users/(:userId)/avatar\n public readonly avatar = this.path + '/avatar';\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\nimport {\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\nimport {ApiV3UserPaths} from \"core-app/modules/common/path-helper/apiv3/users/apiv3-user-paths\";\n\nexport class Apiv3UsersPaths extends SimpleResourceCollection {\n constructor(basePath:string) {\n super(basePath, 'users');\n }\n\n // Static paths\n\n // /api/v3/users/me\n public readonly me = this.path + '/me';\n\n // /api/v3/users/:userId\n public id(userId:string|number) {\n return new ApiV3UserPaths(this.path, userId);\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\nimport {SimpleResource} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class Apiv3QueryPaths extends SimpleResource {\n constructor(basePath:string, queryId:string|number) {\n super(basePath, queryId);\n }\n\n // Static paths\n readonly form = new SimpleResource(this.path, 'form');\n\n // Order path\n readonly order = new SimpleResource(this.path, 'order');\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\nimport {\n SimpleResource,\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\nimport {Apiv3QueryPaths} from 'core-app/modules/common/path-helper/apiv3/queries/apiv3-query-paths';\n\nexport class Apiv3QueriesPaths extends SimpleResourceCollection {\n constructor(basePath:string) {\n super(basePath, 'queries');\n }\n\n // Static paths\n readonly form = new SimpleResource(this.path, 'form');\n\n readonly default = new SimpleResource(this.path, 'default');\n\n // /api/v3/users/:userId\n public id(userId:string|number):Apiv3QueryPaths {\n return new Apiv3QueryPaths(this.path, userId);\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\nimport {\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\nimport {Apiv3QueryPaths} from 'core-app/modules/common/path-helper/apiv3/queries/apiv3-query-paths';\n\nexport class Apiv3TypesPaths extends SimpleResourceCollection {\n constructor(basePath:string) {\n super(basePath, 'types');\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\nimport {\n SimpleResource,\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class Apiv3VersionPaths extends SimpleResourceCollection {\n // Base path\n public readonly path:string;\n // /api/v3/versions/form\n public readonly form = new SimpleResource(this.path, 'form');\n\n public readonly availableProjects = new SimpleResource(this.path, 'available_projects');\n\n constructor(basePath:string) {\n super(basePath, 'versions');\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\nimport {SimpleResource} from 'core-app/modules/common/path-helper/apiv3/path-resources';\nimport {Apiv3QueriesPaths} from 'core-app/modules/common/path-helper/apiv3/queries/apiv3-queries-paths';\nimport {Apiv3TypesPaths} from \"core-app/modules/common/path-helper/apiv3/types/apiv3-types-paths\";\nimport {ApiV3WorkPackagesPaths} from \"core-app/modules/common/path-helper/apiv3/work_packages/apiv3-work-packages-paths\";\nimport {Apiv3VersionPaths} from \"core-app/modules/common/path-helper/apiv3/versions/apiv3-version-paths\";\n\nexport class Apiv3ProjectPaths extends SimpleResource {\n // Base path\n public readonly path:string;\n\n constructor(projectPath:string, readonly projectId:string|number) {\n super(projectPath, projectId);\n }\n\n // /api/v3/projects/:project_id/available_assignees\n public readonly available_assignees = this.path + '/available_assignees';\n\n public readonly queries = new Apiv3QueriesPaths(this.path);\n\n public readonly types = new Apiv3TypesPaths(this.path);\n\n public readonly work_packages = new ApiV3WorkPackagesPaths(this.path);\n\n public readonly versions = new Apiv3VersionPaths(this.path);\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\nimport {SimpleResourceCollection} from 'core-app/modules/common/path-helper/apiv3/path-resources';\nimport {Apiv3ProjectPaths} from 'core-app/modules/common/path-helper/apiv3/projects/apiv3-project-paths';\n\nexport class Apiv3ProjectsPaths extends SimpleResourceCollection {\n constructor(basePath:string) {\n super(basePath, 'projects');\n }\n\n // /api/v3/projects/:projectIdentifier\n public id(projectIdentifier:string|number):Apiv3ProjectPaths {\n return new Apiv3ProjectPaths(this.path, projectIdentifier);\n }\n\n // /api/v3/projects/schema\n public readonly schema = this.path + '/schema';\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\nimport {\n SimpleResource\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class Apiv3GridPaths extends SimpleResource {\n constructor(basePath:string, gridId:string|number) {\n super(basePath, gridId);\n }\n\n // Static paths\n readonly form = new SimpleResource(this.path, 'form');\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\nimport {\n SimpleResource,\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\nimport {Apiv3GridPaths} from \"core-app/modules/common/path-helper/apiv3/grids/apiv3-grid-paths\";\n\nexport class Apiv3GridsPaths extends SimpleResourceCollection {\n constructor(basePath:string) {\n super(basePath, 'grids');\n }\n\n public id(gridId:string|number) {\n return new Apiv3GridPaths(this.path, gridId);\n }\n\n public form() {\n return new SimpleResource(this.path, 'form');\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\nimport {\n SimpleResource\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class Apiv3NewsPaths extends SimpleResource {\n constructor(basePath:string, newsId:string|number) {\n super(basePath, newsId);\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\nimport {\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\nimport {Apiv3NewsPaths} from \"core-app/modules/common/path-helper/apiv3/news/apiv3-news-paths\";\n\nexport class Apiv3NewsesPaths extends SimpleResourceCollection {\n constructor(basePath:string) {\n super(basePath, 'news');\n }\n\n public id(gridId:string|number) {\n return new Apiv3NewsPaths(this.path, gridId);\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\nimport {\n SimpleResource\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class Apiv3TimeEntryPaths extends SimpleResource {\n constructor(basePath:string, newsId:string|number) {\n super(basePath, newsId);\n }\n\n // Static paths\n readonly form = new SimpleResource(this.path, 'form');\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\nimport {\n SimpleResource,\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\nimport {Apiv3TimeEntryPaths} from \"core-app/modules/common/path-helper/apiv3/time-entries/apiv3-time-entry-paths\";\n\nexport class Apiv3TimeEntriesPaths extends SimpleResourceCollection {\n constructor(basePath:string) {\n super(basePath, 'time_entries');\n }\n\n public id(timeEntryId:string|number) {\n return new Apiv3TimeEntryPaths(this.path, timeEntryId);\n }\n\n public readonly form = new SimpleResource(this.path, 'form');\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\nimport {SimpleResourceCollection} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class Apiv3MembershipsPaths extends SimpleResourceCollection {\n constructor(basePath:string) {\n super(basePath, 'memberships');\n }\n\n // /api/v3/memberships/available_projects\n public readonly available_projects = this.path + '/available_projects';\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\nimport {\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\n\nexport class Apiv3GroupsPaths extends SimpleResourceCollection {\n constructor(basePath:string) {\n super(basePath, 'groups');\n }\n\n public toString():string {\n throw 'Backend does not yet offer this end point';\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\nimport {ApiV3WorkPackagesPaths} from 'core-app/modules/common/path-helper/apiv3/work_packages/apiv3-work-packages-paths';\nimport {Apiv3UsersPaths} from 'core-app/modules/common/path-helper/apiv3/users/apiv3-users-paths';\nimport {Apiv3ProjectsPaths} from 'core-app/modules/common/path-helper/apiv3/projects/apiv3-projects-paths';\nimport {\n SimpleResource,\n SimpleResourceCollection\n} from 'core-app/modules/common/path-helper/apiv3/path-resources';\nimport {Apiv3QueriesPaths} from 'core-app/modules/common/path-helper/apiv3/queries/apiv3-queries-paths';\nimport {Apiv3ProjectPaths} from 'core-app/modules/common/path-helper/apiv3/projects/apiv3-project-paths';\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {Apiv3TypesPaths} from \"core-app/modules/common/path-helper/apiv3/types/apiv3-types-paths\";\nimport {Apiv3GridsPaths} from \"core-app/modules/common/path-helper/apiv3/grids/apiv3-grids-paths\";\nimport {Apiv3NewsesPaths} from \"core-app/modules/common/path-helper/apiv3/news/apiv3-newses-paths\";\nimport {Apiv3TimeEntriesPaths} from \"core-app/modules/common/path-helper/apiv3/time-entries/apiv3-time-entries-paths\";\nimport {Apiv3VersionPaths} from \"core-app/modules/common/path-helper/apiv3/versions/apiv3-version-paths\";\nimport {Apiv3MembershipsPaths} from \"core-app/modules/common/path-helper/apiv3/memberships/apiv3-memberships-paths\";\nimport {Apiv3GroupsPaths} from \"core-app/modules/common/path-helper/apiv3/groups/apiv3-groups-path\";\n\nexport class ApiV3Paths {\n // Base path\n public readonly apiV3Base = this.appBasePath + '/api/v3';\n\n // /api/v3/attachments\n public readonly attachments = new SimpleResource(this.apiV3Base, 'attachments');\n\n // /api/v3/configuration\n public readonly configuration = new SimpleResource(this.apiV3Base, 'configuration');\n\n // /api/v3/root\n public readonly root = new SimpleResource(this.apiV3Base, '');\n\n // /api/v3/statuses\n public readonly statuses = new SimpleResourceCollection(this.apiV3Base, 'statuses');\n\n // /api/v3/relations\n public readonly relations = new SimpleResourceCollection(this.apiV3Base, 'relations');\n\n // /api/v3/priorities\n public readonly priorities = new SimpleResourceCollection(this.apiV3Base, 'priorities');\n\n // /api/v3/time_entries\n public readonly time_entries = new Apiv3TimeEntriesPaths(this.apiV3Base);\n\n // /api/v3/memberships\n public readonly memberships = new Apiv3MembershipsPaths(this.apiV3Base);\n\n // /api/v3/news\n public readonly news = new Apiv3NewsesPaths(this.apiV3Base);\n\n // /api/v3/types\n public readonly types = new Apiv3TypesPaths(this.apiV3Base);\n\n // /api/v3/versions\n public readonly versions = new Apiv3VersionPaths(this.apiV3Base);\n\n // /api/v3/work_packages\n public readonly work_packages = new ApiV3WorkPackagesPaths(this.apiV3Base);\n\n // /api/v3/queries\n public readonly queries = new Apiv3QueriesPaths(this.apiV3Base);\n\n // /api/v3/projects\n public readonly projects = new Apiv3ProjectsPaths(this.apiV3Base);\n\n // /api/v3/users\n public readonly users = new Apiv3UsersPaths(this.apiV3Base);\n\n // /api/v3/help_texts\n public readonly help_texts = new SimpleResourceCollection(this.apiV3Base, 'help_texts');\n\n // /api/v3/grids\n public readonly grids = new Apiv3GridsPaths(this.apiV3Base);\n\n // /api/v3/groups\n public readonly groups = new Apiv3GroupsPaths(this.apiV3Base);\n\n\n constructor(readonly appBasePath:string) {\n }\n\n /**\n * Returns possible subpaths either in this api root or below /projects/:id/\n *\n * @param {string | number} projectIdentifier\n * @returns {Apiv3ProjectPaths | this}\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 /**\n * returns a resource segment from (/base)/api/v3/(resource)\n * @param segment\n */\n public resource(segment:string) {\n if (!segment.startsWith('/')) {\n segment = '/' + segment;\n }\n\n return this.apiV3Base + segment;\n }\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 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 public wpBySubjectOrId(term:string, idOnly:boolean = false) {\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 return this.apiV3Base +\n '/work_packages?' +\n filters.toParams({ sortBy: '[[\"updatedAt\",\"desc\"]]', offset: '1', pageSize: '10' });\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\nimport {ApiV3Paths} from 'core-app/modules/common/path-helper/apiv3/apiv3-paths';\nimport {Injectable} from '@angular/core';\n\n@Injectable({ providedIn: 'root' })\nexport class PathHelperService {\n public readonly appBasePath:string;\n public readonly api:{ v3:ApiV3Paths };\n\n constructor() {\n this.appBasePath = window.appBasePath ? window.appBasePath : '';\n this.api = {\n v3: new ApiV3Paths(this.appBasePath)\n };\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 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 projectTimelinesPath(projectId:string) {\n return this.projectPath(projectId) + '/timelines';\n }\n\n public projectTimeEntriesPath(projectIdentifier:string) {\n return this.projectPath(projectIdentifier) + '/time_entries';\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 var 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 userPath(id:string|number) {\n return this.usersPath() + '/' + 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}\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 {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-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 {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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {concatAll} from \"rxjs/operators\";\nimport {combineLatest} from \"rxjs\";\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 wpCacheService:WorkPackageCacheService,\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.workPackage.isReadonly) {\n return this.text.workPackageReadOnly;\n } else if (this.workPackage.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 allowed() {\n return this.workPackage.isAttributeEditable('status');\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// ++\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","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","//-- 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\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 {HttpErrorResponse} from \"@angular/common/http\";\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 pathHelper:PathHelperService;\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 = '';\n\n if (this.isNew || !this.id || !this.attachmentsBackend) {\n href = this.pathHelper.api.v3.attachments.path;\n } else {\n href = this.addAttachment.$link.href;\n }\n\n return this.opFileUpload.uploadAndMapResponse(href, files);\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\n if (!this.pathHelper) {\n this.pathHelper = this.injector.get(PathHelperService);\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-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 {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.resource.isAttributeEditable(this.name);\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-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 {\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-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 {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 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 === 'new';\n }\n\n public get persisted() {\n return !!(this.id && this.id !== 'new');\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 const fieldSchema = this.schema[property];\n return this.$links.update && fieldSchema && fieldSchema.writable;\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-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, 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-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 {MultiInputState} from 'reactivestates';\nimport {States} from '../states.service';\nimport {StateCacheService} from '../states/state-cache.service';\nimport {Injectable} from '@angular/core';\nimport {ProjectResource} from 'core-app/modules/hal/resources/project-resource';\nimport {ProjectDmService} from 'core-app/modules/hal/dm-services/project-dm.service';\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class ProjectCacheService extends StateCacheService {\n\n constructor(readonly states:States,\n readonly schemaCacheService:SchemaCacheService,\n readonly projectDmService:ProjectDmService) {\n super();\n }\n\n protected loadAll(ids:string[]):Promise {\n return Promise\n .all(ids.map(id => this.load(id)))\n .then(_ => undefined);\n }\n\n updateValue(id:string, val:ProjectResource) {\n this.schemaCacheService.ensureLoaded(val).then(() => {\n super.updateValue(id, val);\n });\n }\n\n protected load(id:string):Promise {\n return this\n .projectDmService\n .one(parseInt(id))\n .then((project) => {\n return this.schemaCacheService.ensureLoaded(project).then(() => project);\n });\n }\n\n protected get multiState():MultiInputState {\n return this.states.projects;\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//++\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 name:string;\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-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 {ResourcesDisplayField} from \"./resources-display-field.module\";\nimport {cssClassCustomOption} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class MultipleLinesStringObjectsDisplayField 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-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 {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-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 {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 {MultipleLinesStringObjectsDisplayField} from \"core-app/modules/fields/display/field-types/multiple-lines-string-objects-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\";\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() 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);\n\n return span;\n }\n\n public renderFieldValue(resource:T,\n name:string,\n change:ResourceChangeset|null,\n placeholder?:string):[DisplayField|null, HTMLSpanElement] {\n const span = document.createElement('span');\n const schemaName = this.getSchemaName(resource, change, name);\n const fieldSchema = resource.schema[schemaName];\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, schemaName, 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, resource));\n\n return [field, span];\n }\n\n public getField(resource:T,\n fieldSchema:IFieldSchema,\n name:string,\n change:ResourceChangeset|null):DisplayField {\n let field = this.fieldCache[name];\n\n if (!field) {\n field = this.fieldCache[name] = this.getFieldForCurrentContext(resource, name, fieldSchema);\n }\n\n field.apply(resource, fieldSchema);\n field.activeChange = change;\n\n return field;\n }\n\n private getFieldForCurrentContext(resource:T, name: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 MultipleLinesStringObjectsDisplayField(name, context) as DisplayField;\n }\n const isUserMultiLinesField = ['[]User'].indexOf(fieldSchema.type) >= 0;\n if (this.container === 'single-view' && isUserMultiLinesField) {\n return new MultipleLinesUserFieldModule(name, context) as DisplayField;\n }\n\n // We handle progress differently in the timeline\n if (this.container === 'timeline' && name === 'percentageDone') {\n return new ProgressTextDisplayField(name, context);\n }\n\n return this.displayFieldService.getField(resource, name, 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):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 if (field.writable) {\n span.classList.add(editableClassName);\n span.setAttribute('role', 'button');\n } else {\n span.classList.add(readOnlyClassName);\n }\n }\n\n private getAriaLabel(field:DisplayField, resource:T):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 && resource.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 schema name from either the changeset, the resource (if available) or\n * return the attribute itself.\n *\n * @param resource\n * @param change\n * @param name\n */\n private getSchemaName(resource:T, change:ResourceChangeset|null, name:string) {\n if (change) {\n return change.getSchemaName(name);\n }\n\n if (!!resource.getSchemaName) {\n return resource.getSchemaName(name);\n }\n\n return name;\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","// -- 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\nimport {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageFiltersService} from 'core-components/filters/wp-filters/wp-filters.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\";\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 wpFiltersService:WorkPackageFiltersService,\n readonly I18n:I18nService,\n readonly bannerService:BannersService) {\n }\n\n public onFilterUpdated(filter:QueryFilterInstanceResource) {\n this.filter = filter;\n this.showValuesInput = this.filter.currentSchema!.isValueRequired();\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.filter.schema.availableOperators;\n this.showValuesInput = this.filter.currentSchema!.isValueRequired();\n }\n}\n","\n \n \n\n \n
    \n\n \n\n \n
    \n\n \n \n
    \n \n\n \n\n \n\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-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 {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-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 {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-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 {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.wpCacheService.loadWorkPackage(this.copiedWorkPackageId)\n .values$()\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.wpCacheService.updateWorkPackage(copyChangeset.pristineResource);\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-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 {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-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 {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-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 {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injectable} from '@angular/core';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {QueryFormResource} from 'core-app/modules/hal/resources/query-form-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport * as URI from 'urijs';\n\n@Injectable()\nexport class QueryFormDmService {\n constructor(readonly halResourceService:HalResourceService,\n protected pathHelper:PathHelperService) {\n }\n\n /**\n * Load the query form for the given existing (or new) query resource\n * @param query\n */\n public load(query:QueryResource):Promise {\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 return query.$links.update(payload);\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 = {}):Promise {\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.pathHelper.api.v3.projects.id(projectIdentifier).toString()\n };\n\n }\n\n let href:string = this.pathHelper.api.v3.queries.optionalId(queryId).form.toString();\n href = URI(href).search(params).toString();\n\n return this.halResourceService\n .post(href, payload)\n .toPromise();\n }\n\n public 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-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 {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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.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\";\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 wpCacheService:WorkPackageCacheService,\n readonly wpRelations:WorkPackageRelationsService) {\n }\n\n public initialize(rows:WorkPackageResource[]) {\n // Add relations to the stack\n Promise.all([\n this.requireInvolvedRelations(rows.map(el => el.id!)),\n this.requireHierarchyElements(rows)\n ]).then((results:string[][]) => {\n this.loadAdditional(_.flatten(results));\n });\n }\n\n private loadAdditional(wpIds:string[]) {\n this.wpCacheService.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, true)\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","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 this.pointCB(evt);\n this.onMove(evt);\n });\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) {\n this.elements.push(el);\n }\n\n public onUp() {\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-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 {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 {RootDmService} from 'core-app/modules/hal/dm-services/root-dm.service';\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\";\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 RootDm:RootDmService,\n readonly halResourceService:HalResourceService,\n readonly halSorting:HalResourceSortingService,\n readonly PathHelper:PathHelperService,\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.RootDm.load());\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.PathHelper.api.v3.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","//-- 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\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-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 {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\n\nexport class GridWidgetResource extends HalResource {\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","// -- 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\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\";\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\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 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 attributeName = resource.schema[errorResource.details.attribute].name;\n let attributeType = resource.schema[errorResource.details.attribute].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","//-- 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\nimport {Injectable} from '@angular/core';\nimport {AbstractDmService} from \"core-app/modules/hal/dm-services/abstract-dm.service\";\nimport {MembershipResource} from \"core-app/modules/hal/resources/membership-resource\";\nimport {DmListParameter} from \"core-app/modules/hal/dm-services/dm.service.interface\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\n\n@Injectable()\nexport class MembershipDmService extends AbstractDmService {\n public listAvailableProjects(params:DmListParameter|null) {\n return this.listRequest(this.availableProjectsUrl(), params) as Promise>;\n }\n\n protected listUrl() {\n return this.pathHelper.api.v3.memberships.toString();\n }\n\n protected oneUrl(id:number|string) {\n return this.pathHelper.api.v3.memberships.id(id).toString();\n }\n\n protected availableProjectsUrl() {\n return this.pathHelper.api.v3.memberships.available_projects.toString();\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-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 {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\nconst ObservableArray:any = require('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-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 {StateService, Transition, TransitionService} from '@uirouter/core';\nimport {ReplaySubject} from 'rxjs';\nimport {Injectable} from \"@angular/core\";\n\n@Injectable()\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\n if (stateName === 'details') {\n return this.$state.includes('work-packages.partitioned.list.details.*');\n }\n\n return false;\n }\n\n public updateTabs(stateName?:string) {\n\n // Ignore the switch from show#activity to details#activity\n // and show details#overview instead\n\n if (stateName === 'work-packages.show.activity') {\n this.currentTab = 'overview';\n return this.notify();\n }\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-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 {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-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 {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","
    \n
    \n
      \n \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n \n
    • \n
    • \n \n \n
    • \n
    • \n \n \n
    • \n
    • \n \n \n
    • \n
    \n
    \n
    \n \n \n\n \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-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, 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 {WorkPackageCacheService} from \"app/components/work-packages/work-package-cache.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\";\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 readonly wpCacheService:WorkPackageCacheService) {\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-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 {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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free 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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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-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 {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 name:string;\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-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\nexport type FilterOperator = '='|'!*'|'!'|'~'|'o'|'>t-'|'<>d'|'**'|'ow' ;\n\nexport interface ApiV3FilterValue {\n operator:FilterOperator;\n values:any;\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:any):this {\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-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 {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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {WorkPackageCacheService} from '../../work-packages/work-package-cache.service';\nimport {combineLatest} from 'rxjs';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\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 wpCacheService:WorkPackageCacheService,\n protected wpRelations:WorkPackageRelationsService) {\n super();\n }\n\n ngOnInit():void {\n this.wpRelations.require(this.wpId.toString());\n\n combineLatest(\n this.wpRelations.state(this.wpId.toString()).values$(),\n this.wpCacheService.loadWorkPackage(this.wpId.toString()).values$()\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","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 {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() public onRemove = new EventEmitter();\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 cardView:WorkPackageCardViewService,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit():void {\n // Update selection state\n this.wpTableSelection.selection$()\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 openSplitScreen(wp:WorkPackageResource) {\n let classIdentifier = this.classIdentifier(wp);\n this.wpTableSelection.setSelection(wp.id!, this.cardView.findRenderedCard(classIdentifier));\n this.$state.go(\n splitViewRoute(this.$state),\n { workPackageId: wp.id! }\n );\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 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
    ","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 this.handleWorkPackage(wpId);\n\n return false;\n }\n\n protected handleWorkPackage(wpId:string) {\n this.$state.go(\n 'work-packages.show',\n {workPackageId: wpId}\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// ++\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 {StateCacheService} from \"core-components/states/state-cache.service\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.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.changes;\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 comittedChanges = new Subject();\n\n /** State group of changes to wrap */\n private stateGroup = new ChangesetStates();\n\n constructor(protected readonly injector:Injector,\n protected readonly halEvents:HalEventsService,\n protected readonly hook:HookService) {\n super();\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.comittedChanges.next(commit);\n this.reset(change);\n\n const eventType = commit.wasNew ? 'created' : 'updated';\n this.halEvents.push(commit.resource, { eventType }) ;\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 {resource} Hal resource to edit\n * @param {form:FormResource} Initialize with an existing form\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 load(href:string):Promise {\n return Promise.reject('Loading not applicable for changesets.') as any;\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 protected loadAll(hrefs:string[]) {\n return Promise.all(hrefs.map(href => this.load(href))) as any;\n }\n\n protected get multiState():MultiInputState {\n return this.stateGroup.changesets;\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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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].tree-menu--container').each(function(_i:number, tree:HTMLElement) {\n let selectedPage = $(tree).data('selected-page');\n if (selectedPage) {\n let selected = $('[slug=' + selectedPage + ']', tree);\n selected.toggleClass('-selected', true);\n selected[0].scrollIntoView();\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","//-- 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\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","
    \n \n \n \n\n \n \n\n \n \n \n \n \n \n
    \n","import {ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy, OnInit} from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {OpModalService} from 'core-components/op-modals/op-modal.service';\n\nexport abstract class OpModalComponent 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 constructor(public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef) {\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-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 {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('.wp-query-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","//-- 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\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 public text = {\n placeholder: this.I18n.t('js.placeholders.selection'),\n true: this.I18n.t('js.general_text_Yes'),\n false: this.I18n.t('js.general_text_No')\n };\n\n constructor(readonly I18n:I18nService) {\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[0] = val;\n this.filterChanged.emit(this.filter);\n }\n\n public get hasNoValue() {\n return _.isEmpty(this.filter.values);\n }\n\n public get availableOptions() {\n return [true, false];\n }\n}\n","
    \n \n
    \n","var map = {\n\t\"./apl/apl.js\": [\n\t\t\"4kmW\",\n\t\t0,\n\t\t26\n\t],\n\t\"./asciiarmor/asciiarmor.js\": [\n\t\t\"Jt+K\",\n\t\t0,\n\t\t27\n\t],\n\t\"./asn.1/asn.1.js\": [\n\t\t\"0OHD\",\n\t\t0,\n\t\t28\n\t],\n\t\"./asterisk/asterisk.js\": [\n\t\t\"yGjk\",\n\t\t0,\n\t\t29\n\t],\n\t\"./brainfuck/brainfuck.js\": [\n\t\t\"oF4/\",\n\t\t0,\n\t\t30\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\t31\n\t],\n\t\"./cmake/cmake.js\": [\n\t\t\"qE+Q\",\n\t\t0,\n\t\t32\n\t],\n\t\"./cobol/cobol.js\": [\n\t\t\"JNJg\",\n\t\t0,\n\t\t33\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\t34\n\t],\n\t\"./crystal/crystal.js\": [\n\t\t\"JRJP\",\n\t\t0,\n\t\t35\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\t36\n\t],\n\t\"./d/d.js\": [\n\t\t\"zRyg\",\n\t\t0,\n\t\t37\n\t],\n\t\"./dart/dart.js\": [\n\t\t\"6q/U\",\n\t\t0,\n\t\t5,\n\t\t38\n\t],\n\t\"./diff/diff.js\": [\n\t\t\"3fnu\",\n\t\t0,\n\t\t39\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\t17\n\t],\n\t\"./dockerfile/dockerfile.js\": [\n\t\t\"R6x9\",\n\t\t0,\n\t\t1,\n\t\t40\n\t],\n\t\"./dtd/dtd.js\": [\n\t\t\"/YIB\",\n\t\t0,\n\t\t41\n\t],\n\t\"./dylan/dylan.js\": [\n\t\t\"PLH4\",\n\t\t0,\n\t\t42\n\t],\n\t\"./ebnf/ebnf.js\": [\n\t\t\"AvIz\",\n\t\t0,\n\t\t43\n\t],\n\t\"./ecl/ecl.js\": [\n\t\t\"rSpl\",\n\t\t0,\n\t\t44\n\t],\n\t\"./eiffel/eiffel.js\": [\n\t\t\"t86p\",\n\t\t0,\n\t\t45\n\t],\n\t\"./elm/elm.js\": [\n\t\t\"Rba3\",\n\t\t0,\n\t\t46\n\t],\n\t\"./erlang/erlang.js\": [\n\t\t\"9RTS\",\n\t\t0,\n\t\t47\n\t],\n\t\"./factor/factor.js\": [\n\t\t\"yv4w\",\n\t\t0,\n\t\t1,\n\t\t48\n\t],\n\t\"./fcl/fcl.js\": [\n\t\t\"xvvs\",\n\t\t0,\n\t\t49\n\t],\n\t\"./forth/forth.js\": [\n\t\t\"CDkR\",\n\t\t0,\n\t\t50\n\t],\n\t\"./fortran/fortran.js\": [\n\t\t\"UYub\",\n\t\t0,\n\t\t51\n\t],\n\t\"./gas/gas.js\": [\n\t\t\"Upog\",\n\t\t0,\n\t\t52\n\t],\n\t\"./gfm/gfm.js\": [\n\t\t\"RKCW\",\n\t\t0,\n\t\t7,\n\t\t1,\n\t\t53\n\t],\n\t\"./gherkin/gherkin.js\": [\n\t\t\"tkAH\",\n\t\t0,\n\t\t54\n\t],\n\t\"./go/go.js\": [\n\t\t\"T/QY\",\n\t\t0,\n\t\t55\n\t],\n\t\"./groovy/groovy.js\": [\n\t\t\"X7TR\",\n\t\t0,\n\t\t56\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\t18\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\t57\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\t58\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\t19\n\t],\n\t\"./htmlmixed/htmlmixed.js\": [\n\t\t\"1p+/\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t24\n\t],\n\t\"./http/http.js\": [\n\t\t\"scEK\",\n\t\t0,\n\t\t59\n\t],\n\t\"./idl/idl.js\": [\n\t\t\"HqpV\",\n\t\t0,\n\t\t60\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\t61\n\t],\n\t\"./jsx/jsx.js\": [\n\t\t\"onn/\",\n\t\t0,\n\t\t2,\n\t\t25\n\t],\n\t\"./julia/julia.js\": [\n\t\t\"NGrM\",\n\t\t0,\n\t\t62\n\t],\n\t\"./livescript/livescript.js\": [\n\t\t\"5RX+\",\n\t\t0,\n\t\t63\n\t],\n\t\"./lua/lua.js\": [\n\t\t\"jrMQ\",\n\t\t0,\n\t\t64\n\t],\n\t\"./markdown/markdown.js\": [\n\t\t\"lZu9\",\n\t\t0,\n\t\t7\n\t],\n\t\"./mathematica/mathematica.js\": [\n\t\t\"ztbM\",\n\t\t0,\n\t\t65\n\t],\n\t\"./mbox/mbox.js\": [\n\t\t\"6mA5\",\n\t\t0,\n\t\t66\n\t],\n\t\"./mirc/mirc.js\": [\n\t\t\"o5kb\",\n\t\t0,\n\t\t67\n\t],\n\t\"./mllike/mllike.js\": [\n\t\t\"NU+Z\",\n\t\t0,\n\t\t68\n\t],\n\t\"./modelica/modelica.js\": [\n\t\t\"lQiH\",\n\t\t0,\n\t\t69\n\t],\n\t\"./mscgen/mscgen.js\": [\n\t\t\"6gTk\",\n\t\t0,\n\t\t70\n\t],\n\t\"./mumps/mumps.js\": [\n\t\t\"Q7su\",\n\t\t0,\n\t\t71\n\t],\n\t\"./nginx/nginx.js\": [\n\t\t\"srmC\",\n\t\t0,\n\t\t72\n\t],\n\t\"./nsis/nsis.js\": [\n\t\t\"bYLO\",\n\t\t0,\n\t\t1,\n\t\t73\n\t],\n\t\"./ntriples/ntriples.js\": [\n\t\t\"PWBO\",\n\t\t0,\n\t\t74\n\t],\n\t\"./octave/octave.js\": [\n\t\t\"mybg\",\n\t\t0,\n\t\t75\n\t],\n\t\"./oz/oz.js\": [\n\t\t\"yhmh\",\n\t\t0,\n\t\t76\n\t],\n\t\"./pascal/pascal.js\": [\n\t\t\"lB9V\",\n\t\t0,\n\t\t77\n\t],\n\t\"./pegjs/pegjs.js\": [\n\t\t\"ZGb1\",\n\t\t0,\n\t\t2,\n\t\t78\n\t],\n\t\"./perl/perl.js\": [\n\t\t\"kG+r\",\n\t\t0,\n\t\t79\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\t20\n\t],\n\t\"./pig/pig.js\": [\n\t\t\"860+\",\n\t\t0,\n\t\t80\n\t],\n\t\"./powershell/powershell.js\": [\n\t\t\"naPG\",\n\t\t0,\n\t\t81\n\t],\n\t\"./properties/properties.js\": [\n\t\t\"3Fvf\",\n\t\t0,\n\t\t82\n\t],\n\t\"./protobuf/protobuf.js\": [\n\t\t\"cHwl\",\n\t\t0,\n\t\t83\n\t],\n\t\"./pug/pug.js\": [\n\t\t\"W+/v\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t6\n\t],\n\t\"./puppet/puppet.js\": [\n\t\t\"cwoo\",\n\t\t0,\n\t\t84\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\t85\n\t],\n\t\"./r/r.js\": [\n\t\t\"kD6b\",\n\t\t0,\n\t\t86\n\t],\n\t\"./rpm/rpm.js\": [\n\t\t\"Qs4+\",\n\t\t0,\n\t\t87\n\t],\n\t\"./rst/rst.js\": [\n\t\t\"jIQM\",\n\t\t0,\n\t\t1,\n\t\t88\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\t89\n\t],\n\t\"./sas/sas.js\": [\n\t\t\"Sh3j\",\n\t\t0,\n\t\t90\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\t91\n\t],\n\t\"./shell/shell.js\": [\n\t\t\"AvDn\",\n\t\t0,\n\t\t92\n\t],\n\t\"./sieve/sieve.js\": [\n\t\t\"1dRh\",\n\t\t0,\n\t\t93\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\t21\n\t],\n\t\"./smalltalk/smalltalk.js\": [\n\t\t\"n4Nj\",\n\t\t0,\n\t\t94\n\t],\n\t\"./smarty/smarty.js\": [\n\t\t\"QWhe\",\n\t\t0,\n\t\t95\n\t],\n\t\"./solr/solr.js\": [\n\t\t\"xhF3\",\n\t\t0,\n\t\t96\n\t],\n\t\"./soy/soy.js\": [\n\t\t\"vH+N\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t22\n\t],\n\t\"./sparql/sparql.js\": [\n\t\t\"++e5\",\n\t\t0,\n\t\t97\n\t],\n\t\"./spreadsheet/spreadsheet.js\": [\n\t\t\"bEWP\",\n\t\t0,\n\t\t98\n\t],\n\t\"./sql/sql.js\": [\n\t\t\"/9rB\",\n\t\t0,\n\t\t99\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\t8\n\t],\n\t\"./swift/swift.js\": [\n\t\t\"wOIU\",\n\t\t0,\n\t\t100\n\t],\n\t\"./tcl/tcl.js\": [\n\t\t\"BEBj\",\n\t\t0,\n\t\t101\n\t],\n\t\"./textile/textile.js\": [\n\t\t\"TD3l\",\n\t\t0,\n\t\t102\n\t],\n\t\"./tiddlywiki/tiddlywiki.js\": [\n\t\t\"9+NH\",\n\t\t0,\n\t\t103\n\t],\n\t\"./tiki/tiki.js\": [\n\t\t\"Km7L\",\n\t\t0,\n\t\t104\n\t],\n\t\"./toml/toml.js\": [\n\t\t\"0sou\",\n\t\t0,\n\t\t105\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\t23\n\t],\n\t\"./troff/troff.js\": [\n\t\t\"s1o1\",\n\t\t0,\n\t\t106\n\t],\n\t\"./ttcn-cfg/ttcn-cfg.js\": [\n\t\t\"hmTv\",\n\t\t0,\n\t\t107\n\t],\n\t\"./ttcn/ttcn.js\": [\n\t\t\"TYrp\",\n\t\t0,\n\t\t108\n\t],\n\t\"./turtle/turtle.js\": [\n\t\t\"P3N9\",\n\t\t0,\n\t\t109\n\t],\n\t\"./twig/twig.js\": [\n\t\t\"SII/\",\n\t\t0,\n\t\t1,\n\t\t110\n\t],\n\t\"./vb/vb.js\": [\n\t\t\"Kr55\",\n\t\t0,\n\t\t111\n\t],\n\t\"./vbscript/vbscript.js\": [\n\t\t\"axah\",\n\t\t0,\n\t\t112\n\t],\n\t\"./velocity/velocity.js\": [\n\t\t\"/kYp\",\n\t\t0,\n\t\t113\n\t],\n\t\"./verilog/verilog.js\": [\n\t\t\"m2bc\",\n\t\t0,\n\t\t114\n\t],\n\t\"./vhdl/vhdl.js\": [\n\t\t\"PP56\",\n\t\t0,\n\t\t115\n\t],\n\t\"./vue/vue.js\": [\n\t\t\"aT2M\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t8,\n\t\t6,\n\t\t1,\n\t\t116\n\t],\n\t\"./webidl/webidl.js\": [\n\t\t\"PVgs\",\n\t\t0,\n\t\t117\n\t],\n\t\"./xml/xml.js\": [\n\t\t\"1eCo\",\n\t\t0,\n\t\t118\n\t],\n\t\"./xquery/xquery.js\": [\n\t\t\"bJEP\",\n\t\t0,\n\t\t119\n\t],\n\t\"./yacas/yacas.js\": [\n\t\t\"WThJ\",\n\t\t0,\n\t\t120\n\t],\n\t\"./yaml-frontmatter/yaml-frontmatter.js\": [\n\t\t\"0gIM\",\n\t\t0,\n\t\t1,\n\t\t121\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\t122\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-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 {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injectable} from '@angular/core';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\n\n@Injectable()\nexport class UserDmService {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService) {\n }\n\n public load(id:number|string):Promise {\n const path = this.pathHelper.api.v3.users.id(id).toString();\n\n return this.halResourceService\n .get(path)\n .toPromise();\n }\n}\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-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 {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-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 {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-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 {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-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 {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","// -- 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\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","
    \n
    \n \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// ++\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 {WorkPackageDmService} from \"core-app/modules/hal/dm-services/work-package-dm.service\";\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 readonly workPackageDmService:WorkPackageDmService,\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.workPackageDmService\n .emptyCreateForm({}, this.currentProject.identifier)\n .then((form:any) => {\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
    \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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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-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\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-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 {InputState, MultiInputState, State} from 'reactivestates';\nimport {Observable} from \"rxjs\";\nimport {auditTime, map, startWith} from \"rxjs/operators\";\n\nexport abstract class StateCacheService {\n private cacheDurationInMs:number;\n\n constructor(private holdValuesForSeconds:number = 3600) {\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 * Update the value due to application changes.\n *\n * @param id The value's identifier.\n * @param val The value.\n */\n public updateValue(id:string, val:T) {\n this.multiState.get(id).putValue(val);\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 * 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 * @param id The value's identifier.\n * @param force Load the value anyway.\n */\n public require(id:string, force:boolean = false):Promise {\n const state = this.multiState.get(id);\n\n // Refresh when stale or being forced\n if (this.stale(state) || force) {\n let promise = this.load(id);\n state.clearAndPutFromPromise(promise);\n return promise;\n }\n\n return state.valuesPromise() as Promise;\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 value's identifier.\n * @param force Load the value anyway.\n */\n public requireAndStream(id:string, force:boolean = false):Observable {\n const state = this.multiState.get(id);\n\n // Refresh when stale or being forced\n if (this.stale(state) || force) {\n state.clear();\n state.putFromPromiseIfPristine(() => this.load(id));\n }\n\n return state.values$();\n }\n\n /**\n * Require the states of the given ids to be loaded if they're empty or stale,\n * or all when force is given.\n * @param ids Ids to require\n * @param force Load the values anyway\n * @return {Promise} An empty promise to mark when the set of states is filled.\n */\n public requireAll(ids:string[], force:boolean = false):Promise {\n let idsToRequest:string[];\n\n if (force) {\n idsToRequest = ids;\n } else {\n idsToRequest = ids.filter((id:string) => this.stale(this.multiState.get(id)));\n }\n\n if (idsToRequest.length === 0) {\n return Promise.resolve(undefined);\n }\n\n return this.loadAll(idsToRequest);\n }\n\n /**\n * Returns whether the state\n * @param state\n * @return {boolean}\n */\n protected stale(state:InputState):boolean {\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 * Returns the internal state object\n */\n protected abstract get multiState():MultiInputState;\n\n /**\n * Load a single value into the cache state.\n * Subclassses need to ensure it gets loaded and resolve or reject the promise\n * @param id The identifier of the value object of type T.\n */\n protected abstract load(id:string):Promise;\n\n /**\n * Load a set of required values, fill the results into the appropriate states\n * and return a promise when all values are inserted.\n */\n protected abstract loadAll(ids:string[]):Promise;\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\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();\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","//-- 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\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {HelpTextResource} from 'core-app/modules/hal/resources/help-text-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {Injectable} from '@angular/core';\n\n@Injectable()\nexport class HelpTextDmService {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService) {\n }\n\n public loadAll():Promise> {\n return this.halResourceService\n .get>(this.pathHelper.api.v3.help_texts.toString())\n .toPromise();\n }\n\n public load(helpTextId:string):Promise {\n return this.halResourceService\n .get(this.pathHelper.api.v3.help_texts.id(helpTextId).toString())\n .toPromise();\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
    \n
    \n
    \n
    \n \n
    \n
    \n\n
    \n\n
    \n
    \n
    \n \n
    \n
    \n\n
    \n
    \n
    \n","import {QueryOrder} from \"core-app/modules/hal/dm-services/query-order-dm.service\";\nimport {debugLog, timeOutput} from \"core-app/helpers/debug_output\";\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 return this.delta[wpId] || this.positions[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-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 {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 {QueryOrder, QueryOrderDmService} from \"core-app/modules/hal/dm-services/query-order-dm.service\";\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\";\n\n\n@Injectable()\nexport class WorkPackageViewOrderService extends WorkPackageQueryStateService {\n\n constructor(protected readonly querySpace:IsolatedQuerySpace,\n protected readonly queryOrderDm:QueryOrderDmService,\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.queryOrderDm.update(this.currentQuery.id!, delta);\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.queryOrderDm.get(this.currentQuery.id!)\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","// -- 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\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 this.schema = this.schema || this.change.schema[this.name];\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[this.name];\n\n if (!fieldSchema) {\n return handler.deactivate(false);\n }\n\n this.change = change;\n this.schema = change.schema[this.name];\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 get name() {\n // Get the mapped schema name, as this is not always the attribute\n // e.g., startDate in table for milestone => date attribute\n return this.change.getSchemaName(this.handler.fieldName);\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 public get resource() {\n return this.change.projectedResource;\n }\n\n /**\n * Initialize the field after constructor was called.\n */\n protected initialize() {\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-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 {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","// 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-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 {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-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 {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injectable} from '@angular/core';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {buildApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\n\n@Injectable()\nexport class VersionDmService {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService) {\n }\n\n public createVersion(payload:any):Promise {\n return this.halResourceService\n .post(this.pathHelper.api.v3.versions.path, payload)\n .toPromise();\n }\n\n public emptyCreateForm(payload:any):Promise {\n return this.halResourceService\n .post(this.pathHelper.api.v3.versions.form.toString(), payload)\n .toPromise();\n }\n\n\n public one(id:string|number):Promise {\n return this.halResourceService\n .get(this.pathHelper.api.v3.versions.id(id).toString())\n .toPromise();\n }\n\n public list():Promise> {\n return this.halResourceService\n .get>(this.pathHelper.api.v3.versions.toString())\n .toPromise();\n }\n\n public listForProject(projectId:string):Promise> {\n return this.halResourceService\n .get>(this.pathHelper.api.v3.projects.id(projectId).versions.toString())\n .toPromise();\n }\n\n public canCreateVersionInProject(id:string):Promise {\n return this.halResourceService\n .get>(\n this.pathHelper.api.v3.versions.availableProjects.toString(),\n { filters: buildApiV3Filter('id', '=', [id]).toJson() }\n )\n .toPromise()\n .then((collection) => {\n return collection.elements.length === 1;\n });\n }\n\n public listProjectsAvailableForVersions():Promise> {\n return this.halResourceService\n .get>(this.pathHelper.api.v3.versions.availableProjects.toString())\n .toPromise();\n }\n\n public patch(resource:VersionResource, payload:Object):Promise {\n return this.halResourceService\n .patch(\n this.pathHelper.api.v3.versions.id(resource.id!).toString(),\n payload)\n .toPromise();\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\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","// -- 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\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","//-- 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\nimport {WorkPackageCacheService} from '../../work-packages/work-package-cache.service';\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\";\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 wpCacheService:WorkPackageCacheService) {\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.pathHelper.api.v3.work_packages.id(parentId).toString()\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.wpCacheService.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.wpCacheService\n .require(childWpId)\n .then((wpToBecomeChild:WorkPackageResource|undefined) => {\n return this.changeParent(wpToBecomeChild!, workPackage.id!)\n .then(wp => {\n this.wpCacheService.loadWorkPackage(workPackage.id!, true);\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.wpCacheService.require(parentWorkPackage.id!, true).then((wp) => {\n this.halEvents.push(wp, {\n eventType: 'association',\n relatedWorkPackage: null,\n relationType: 'child'\n });\n });\n }\n this.wpCacheService.updateWorkPackage(wp);\n })\n .catch((error) => {\n this.notificationService.handleRawError(error, childWorkPackage);\n return Promise.reject(error);\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 {{ descriptor.label }}\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-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, Injector, Input} 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\";\n\n@Component({\n selector: 'wp-attribute-group',\n templateUrl: './wp-attribute-group.template.html'\n})\nexport class WorkPackageFormAttributeGroupComponent {\n @Input() public workPackage:WorkPackageResource;\n @Input() public group:GroupDescriptor;\n\n public text = {\n date: {\n startDate: this.I18n.t('js.label_no_start_date'),\n dueDate: this.I18n.t('js.label_no_due_date')\n },\n };\n\n constructor(readonly I18n:I18nService,\n public wpeditForm:EditFormComponent,\n protected injector:Injector) {\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","// -- 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\nimport {Injector} from '@angular/core';\nimport * as moment from 'moment';\nimport {WorkPackageCacheService} from '../../../work-packages/work-package-cache.service';\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 {QueryDmService} from 'core-app/modules/hal/dm-services/query-dm.service';\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\";\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 wpCacheService:WorkPackageCacheService,\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 // But adding a relation to it is.\n if (!renderInfo.workPackage.isLeaf && !renderInfo.viewParams.activeSelectionMode) {\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\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 if (!(wp.isLeaf && renderer.canMoveDates(wp))) {\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 renderInfo.change.clear();\n renderer.update(bar, labels, renderInfo);\n renderer.onMouseDownEnd(labels, renderInfo.change);\n workPackageTimeline.refreshView();\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(stopAndRefresh);\n }\n\n }\n\n function saveWorkPackage(change:WorkPackageChangeset) {\n const queryDm:QueryDmService = injector.get(QueryDmService);\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 queryDm.loadIdsUpdatedSince(ids, updatedAt).then(workPackageCollection => {\n wpCacheService.updateWorkPackageList(workPackageCollection.elements);\n\n halEvents.push(result.resource, { eventType: 'updated' });\n return querySpace.timelineRendered.pipe(take(1)).toPromise();\n });\n })\n .catch((error) => {\n notificationService.handleRawError(error, renderInfo.workPackage);\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 {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../../../states.service';\nimport {WorkPackageCacheService} from '../../../work-packages/work-package-cache.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\";\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 }\n\n}\n\nexport class WorkPackageTimelineCell {\n @InjectField() wpCacheService:WorkPackageCacheService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() halEvents:HalEventsService;\n @InjectField() notificationService:WorkPackageNotificationService;\n @InjectField() states:States;\n @InjectField() loadingIndicator:LoadingIndicatorService;\n\n private wpElement:HTMLDivElement|null = null;\n\n private elementShape:string;\n\n private timelineCell:JQuery;\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 (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 this.clear();\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.wpCacheService,\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 (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 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 '../../../wp-edit-form/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\";\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 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 }\n\n public get type():string {\n return 'bar';\n }\n\n public canMoveDates(wp:WorkPackageResource) {\n return wp.schema.startDate.writable && wp.schema.dueDate.writable && wp.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\n const viewParams = renderInfo.viewParams;\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 // 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 // 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 or for parents (clamps)\n const id = type.id;\n if (selectionMode || this.isParentWithVisibleChildren(wp)) {\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 /**\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 */\n checkForSpecialDisplaySituations(renderInfo:RenderInfo, bar:HTMLElement) {\n const wp = renderInfo.workPackage;\n let selectionMode = renderInfo.viewParams.activeSelectionMode;\n\n // Cannot edit the work package if it has children\n if (!wp.isLeaf && !selectionMode) {\n bar.classList.add('-readonly');\n } else {\n bar.classList.remove('-readonly');\n }\n\n // Display the parent as clamp-style when it has children in the table\n if (this.isParentWithVisibleChildren(wp)) {\n bar.classList.add('-clamp-style');\n bar.style.borderStyle = 'solid';\n bar.style.borderWidth = '2px';\n bar.style.borderBottom = 'none';\n bar.style.background = 'none';\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 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 return wp.schema.date.writable && wp.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 const labels = new WorkPackageCellLabels(null, labelLeft, null, labelRight, labelHoverRight, labelFarRight);\n this.updateLabels(false, labels, renderInfo.change);\n\n return labels;\n }\n\n protected renderHoverLabels(labels:WorkPackageCellLabels, change:WorkPackageChangeset) {\n this.renderLabel(change, labels, 'rightHover', 'date');\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 // 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 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-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 {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) {\n const renderInfo = this.renderInfoFor(cell.workPackageId);\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):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 };\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\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 {WorkPackagesTableController} from \"core-components/wp-table/wp-table.directive\";\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} from \"rxjs\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\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 constructor(public readonly injector:Injector,\n private elementRef:ElementRef,\n private states:States,\n public wpTableDirective:WorkPackagesTableController,\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 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.wpTableDirective.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.untilDestroyed(),\n takeUntil(this.querySpace.stopAllSubscriptions),\n filter(() => this.initialized && this.wpTableTimeline.isVisible)\n )\n .subscribe(([orderedRows, changes, timelineState]) => {\n // Remember all visible rows in their order of appearance.\n this.workPackageIdOrder = orderedRows.filter(row => !row.hidden);\n this.refreshView();\n });\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 // 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\n // Calculate view parameters\n this.workPackageIdOrder.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 daysSpan = calculateDaySpan(this.workPackageIdOrder, 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.wpTableDirective.timeline.scrollLeft = 0;\n }\n\n this.wpTableTimeline.appliedZoomLevel = zoomLevel;\n return;\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-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 {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-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, 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-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, 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","// -- 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\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","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-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 {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-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 {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-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, 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-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 {AfterViewInit, Directive, ElementRef, Injector} 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\";\n\n@Directive({\n selector: '[wpTableSumsRow]'\n})\nexport class WorkPackageTableSumsRowController implements AfterViewInit {\n\n private text:{ sum:string };\n\n private $element:JQuery;\n\n constructor(readonly injector:Injector,\n readonly elementRef:ElementRef,\n readonly querySpace:IsolatedQuerySpace,\n readonly states:States,\n readonly displayFieldService:DisplayFieldService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly wpTableSums:WorkPackageViewSumService,\n readonly I18n:I18nService) {\n\n this.text = {\n sum: I18n.t('js.label_sum')\n };\n }\n\n ngAfterViewInit():void {\n this.$element = jQuery(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 if (sum && resource.sumsSchema) {\n resource.sumsSchema.$load().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.empty();\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 // build\n columns.forEach((column, i:number) => {\n const td = document.createElement('td');\n td.classList.add('wp-table--sum-container');\n const div = this.renderContent(resource.totalSums!, column.id, schema[column.id]);\n\n if (i === 0) {\n this.appendFirstLabel(div);\n // colspan 2 for the d&d column\n td.setAttribute('colspan', '2');\n }\n\n td.appendChild(div);\n this.$element.append(td);\n });\n\n // Append last empty td\n this.$element.append(``);\n }\n\n private renderContent(sums:any, name:string, fieldSchema:IFieldSchema) {\n const div = document.createElement('div');\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 private appendFirstLabel(div:HTMLElement) {\n const span = document.createElement('span');\n span.textContent = `${this.text.sum}`;\n jQuery(div).prepend(span);\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-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, 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","// -- 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\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 {WorkPackagesTableController} from 'core-components/wp-table/wp-table.directive';\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 {WorkPackageDetailsViewButtonComponent} from 'core-components/wp-buttons/wp-details-view-button/wp-details-view-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 {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.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 {KeepTabService} from 'core-components/wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {QueryFormDmService} from 'core-app/modules/hal/dm-services/query-form-dm.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 {WorkPackageDmService} from \"core-app/modules/hal/dm-services/work-package-dm.service\";\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\";\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 WorkPackageCacheService,\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 WorkPackageCacheService,\n SchemaCacheService,\n\n KeepTabService,\n WorkPackageDmService,\n\n WorkPackagesActivityService,\n WorkPackageRelationsService,\n WorkPackageWatchersService,\n\n QueryFormDmService,\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 WorkPackagesTableController,\n WorkPackagesTableConfigMenu,\n WorkPackageTablePaginationComponent,\n\n WpResizerDirective,\n\n WorkPackageTableSumsRowController,\n\n // Filters\n QueryFiltersComponent,\n QueryFilterComponent,\n FilterBooleanValueComponent,\n FilterDateValueComponent,\n FilterDatesValueComponent,\n FilterDateTimeValueComponent,\n FilterDateTimesValueComponent,\n FilterIntegerValueComponent,\n FilterStringValueComponent,\n FilterToggledMultiselectValueComponent,\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\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\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 exports: [\n WorkPackagesTableController,\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) {\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-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 {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","import {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 WorkPackageViewHandlerClass {\n new(injector:Injector):WorkPackageViewEventHandler;\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 {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, 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\";\n\nexport interface QueryConfigurationLocals {\n service:any;\n currentQuery:any;\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 AfterViewInit {\n\n @ViewChild('embeddedTableForConfiguration', { static: true }) private embeddedTable:WorkPackageEmbeddedTableComponent;\n\n constructor(@Inject(OpQueryConfigurationLocalsToken) readonly locals:QueryConfigurationLocals,\n readonly cdRef:ChangeDetectorRef) {\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 this.locals.callback(this.embeddedTable.buildQueryProps());\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 {StateCacheService} from \"core-components/states/state-cache.service\";\nimport {multiInput, MultiInputState} from \"reactivestates\";\nimport {Board} from \"core-app/modules/boards/board/board\";\nimport {BoardDmService} from \"core-app/modules/boards/board/board-dm.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class BoardCacheService extends StateCacheService {\n\n protected _state = multiInput();\n\n constructor(protected boardDm:BoardDmService) {\n super();\n }\n\n protected load(id:string):Promise {\n return this.boardDm\n .one(parseInt(id))\n .toPromise()\n .then((board:Board) => {\n this.updateValue(id, board);\n return board;\n });\n\n }\n\n protected loadAll(ids:string[] = []):Promise {\n return Promise\n .all(ids.map(id => this.load(id)))\n .then(() => undefined);\n }\n\n protected get multiState():MultiInputState {\n return this._state;\n }\n\n update(board:Board) {\n this.updateValue(board.id!, board);\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-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 {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {WorkPackageCacheService} from '../../work-packages/work-package-cache.service';\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 AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input,\n OnInit\n} from \"@angular/core\";\nimport {UserCacheService} from \"core-components/user/user-cache.service\";\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\";\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, AfterViewInit {\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 wpCacheService:WorkPackageCacheService,\n readonly ConfigurationService:ConfigurationService,\n readonly userCacheService:UserCacheService,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n super(elementRef, injector);\n }\n\n public ngOnInit() {\n super.ngOnInit();\n\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.userCacheService\n .require(this.activity.user.idFromLink)\n .then((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\n public shouldHideIcons():boolean {\n return !((this.isComment || this.isBcfComment) && this.focussing());\n }\n\n public ngAfterViewInit() {\n if (window.location.hash === 'activity-' + this.activityNo) {\n this.elementRef.nativeElement.scrollIntoView(true);\n }\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.wpCacheService.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 public get htmlId() {\n return `user_activity_edit_field_${this.activityNo}`;\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.sanitization.bypassSecurityTrustHtml(this.activity.comment.html);\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\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","
    \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","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 {BoardDmService} from \"core-app/modules/boards/board/board-dm.service\";\nimport {BoardCacheService} from \"core-app/modules/boards/board/board-cache.service\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {GonService} from \"core-app/modules/common/gon/gon.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {BoardActionsRegistryService} from \"core-app/modules/boards/board/board-actions/board-actions-registry.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 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 boardDm:BoardDmService,\n protected PathHelper:PathHelperService,\n protected Gon:GonService,\n protected CurrentProject:CurrentProjectService,\n protected halResourceService:HalResourceService,\n protected boardCache:BoardCacheService,\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.boardDm\n .allInScope()\n .toPromise()\n .then((boards) => {\n boards.forEach(b => this.buildOrderAndUpdate(b));\n return boards;\n });\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) {\n this.reorderWidgets(board);\n return this.boardDm.save(board)\n .then(board => {\n board.sortWidgets();\n this.boardCache.update(board);\n return board;\n });\n }\n\n /**\n * Create a new board\n * @param name\n */\n public async create(params:CreateBoardParams):Promise {\n const board = await this.boardDm.create(params.type, this.boardName(params), params.attribute);\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!).addActionQueries(board);\n }\n\n await this.save(board);\n\n return board;\n }\n\n public delete(board:Board):Promise {\n return this.boardDm\n .delete(board)\n .then(() => this.boardCache.clearSome(board.id!));\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 /**\n * Put the board widgets in correct order and update cache\n */\n private buildOrderAndUpdate(board:Board) {\n board.sortWidgets();\n this.boardCache.update(board);\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\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-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 {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-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 {Injectable} from '@angular/core';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {ConfigurationResource} from 'core-app/modules/hal/resources/configuration-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {shareReplay} from \"rxjs/operators\";\nimport {Observable} from \"rxjs\";\n\n@Injectable()\nexport class ConfigurationDmService {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService) {\n }\n\n private $configuration:Observable;\n\n public load():Observable {\n if (this.$configuration) {\n return this.$configuration;\n }\n\n return this.$configuration = this.halResourceService\n .get(this.pathHelper.api.v3.configuration.toString())\n .pipe(\n shareReplay()\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// ++\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-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 {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-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 {Injectable} from '@angular/core';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {InputState} from 'reactivestates';\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\";\n\nexport interface WPFocusState {\n workPackageId:string;\n focusAfterRender:boolean;\n}\n\n@Injectable()\nexport class WorkPackageViewFocusService {\n\n public state:InputState;\n\n constructor(public querySpace:IsolatedQuerySpace,\n public wpTableSelection:WorkPackageViewSelectionService) {\n this.state = querySpace.focusedWorkPackage;\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.state.value;\n\n if (value && value.focusAfterRender) {\n callback(value.workPackageId);\n value.focusAfterRender = false;\n this.state.putValue(value, 'Setting focus to false after callback.');\n }\n }\n\n public get focusedWorkPackage():string | null {\n const value = this.state.value;\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 clear() {\n this.state.clear();\n }\n\n public whenChanged():Observable {\n return this.state.values$()\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.state.putValue({workPackageId: workPackageId, focusAfterRender: setFocusAfterRender});\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\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-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 {ChangeDetectorRef, Component, ElementRef, Inject} 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})\nexport class AttributeHelpTextModal extends OpModalComponent {\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 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
    \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 {{ 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","// -- 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\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-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 {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-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 {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\";\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(table:WorkPackageTable, evt:JQuery.TriggeredEvent) {\n onClickOrEnter(evt, () => this.processEvent(table, 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-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 {Injectable} from '@angular/core';\nimport {ProjectResource} from 'core-app/modules/hal/resources/project-resource';\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {Apiv3ProjectsPaths} from \"core-app/modules/common/path-helper/apiv3/projects/apiv3-projects-paths\";\nimport {AbstractDmService} from \"core-app/modules/hal/dm-services/abstract-dm.service\";\n\n@Injectable()\nexport class ProjectDmService extends AbstractDmService {\n public schema():Promise {\n return this.halResourceService\n .get(this.projectsPath.schema)\n .toPromise();\n }\n\n protected listUrl():string {\n return this.projectsPath.toString();\n }\n\n protected oneUrl(id:number|string):string {\n return this.projectsPath.id(id).toString();\n }\n\n private get projectsPath():Apiv3ProjectsPaths {\n return this.pathHelper.api.v3.projects;\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\nimport {Component, Input, OnInit} from '@angular/core';\nimport {UIRouterGlobals} from '@uirouter/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageCacheService} from '../work-package-cache.service';\nimport {randomString} from \"core-app/helpers/random-string\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\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 wpCacheService:WorkPackageCacheService) {\n super();\n }\n\n ngOnInit() {\n if (!this.workPackage) {\n this.wpCacheService.loadWorkPackage(this.uiRouterGlobals.params['workPackageId'])\n .values$()\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","// -- 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\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","import {Injectable} from '@angular/core';\nimport {input} from 'reactivestates';\nimport {ChartType} from 'chart.js';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\n\n@Injectable()\nexport class IsolatedGraphQuerySpace extends IsolatedQuerySpace {\n chartType = input();\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\nimport {Directive} 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 {TableDragActionsRegistryService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-actions-registry.service\";\nimport {IsolatedGraphQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-graph-query-space\";\nimport {WorkPackageIsolatedQuerySpaceDirective} from \"core-app/modules/work_packages/query-space/wp-isolated-query-space.directive\";\nimport {WorkPackageViewHierarchyIdentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy-indentation.service\";\n\nexport const WpIsolatedGraphQuerySpaceProviders = [\n // Open the isolated space first, order is important here\n { provide: IsolatedQuerySpace, useClass: IsolatedGraphQuerySpace },\n OpTableActionsService,\n\n // Work package table services\n WorkPackagesListChecksumService,\n WorkPackagesListService,\n WorkPackageViewRelationColumnsService,\n WorkPackageViewPaginationService,\n WorkPackageViewGroupByService,\n WorkPackageViewHierarchiesService,\n WorkPackageViewSortByService,\n WorkPackageViewColumnsService,\n WorkPackageViewFiltersService,\n WorkPackageViewTimelineService,\n WorkPackageViewSelectionService,\n WorkPackageViewSumService,\n WorkPackageViewAdditionalElementsService,\n WorkPackageViewFocusService,\n WorkPackageViewHighlightingService,\n WorkPackageService,\n WorkPackageViewHierarchyIdentationService,\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 HalResourceEditingService,\n WorkPackageCreateService,\n\n WorkPackageStatesInitializationService,\n\n // Table Drag & Drop actions\n TableDragActionsRegistryService,\n];\n\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-graph-query-space]',\n providers: WpIsolatedGraphQuerySpaceProviders\n})\nexport class WorkPackageIsolatedGraphQuerySpaceDirective extends WorkPackageIsolatedQuerySpaceDirective {\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 {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\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\";\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() entry:TimeEntryResource;\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.entry)\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(this.entry.schema);\n this.cdRef.detectChanges();\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.entry.schema[field].required;\n }\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}\n","\n
    \n\n
    \n
    \n
    \n \n \n
    \n\n
    \n
    \n
    \n \n \n
    \n\n
    \n
    \n
    \n \n \n
    \n\n
    \n
    \n
    \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-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 {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-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 {Injectable} from '@angular/core';\nimport {PaginationObject} from 'core-app/modules/hal/dm-services/query-dm.service';\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 {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-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 {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","// -- 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\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\";\n\nexport interface ToolbarButtonComponentDefinition {\n component:ComponentType;\n containerClasses?:string;\n show?:() => boolean;\n inputs?:{ [inputName:string]:any };\n outputs?:{ [outputName:string]:Function };\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() 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 querySaving:boolean;\n\n /** Do we currently have query props ? */\n hasQueryProps:boolean;\n\n /** Listener callbacks */\n unRegisterTitleListener:Function;\n removeTransitionSubscription:Function;\n\n /** Determine when query is initially loaded */\n tableInformationLoaded = 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 ngOnInit() {\n super.ngOnInit();\n\n this.hasQueryProps = !!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.hasQueryProps = !!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.tableInformationLoaded = 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 saveQueryFromTitle(val:string) {\n if (this.currentQuery && this.currentQuery.persisted) {\n this.updateQueryName(val);\n } else {\n this.wpListService\n .create(this.currentQuery!, val)\n .then(() => this.querySaving = false)\n .catch(() => this.querySaving = false);\n }\n }\n\n updateQueryName(val:string) {\n this.querySaving = true;\n this.currentQuery!.name = val;\n this.wpListService.save(this.currentQuery)\n .then(() => this.querySaving = false)\n .catch(() => this.querySaving = false);\n }\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\n if (firstPage) {\n promise = this.loadFirstPage();\n } else {\n promise = this.wpListService.reloadCurrentResultsList();\n }\n\n if (visibly) {\n this.loadingIndicator = promise.then(() => {\n return this.additionalLoadingTime();\n });\n }\n\n return promise;\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-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\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\";\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 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.filter.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","
    \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// ++\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 {WorkPackageCacheService} from '../work-package-cache.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\";\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 wpCacheService:WorkPackageCacheService,\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(resource, ['project']);\n }\n\n const attributeGroups = resource.schema._attributeGroups;\n this.groupedFields = this.rebuildGroupedFields(resource, 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 /**\n *\n * @param attributeGroups\n * @returns {any}\n */\n private rebuildGroupedFields(resource:WorkPackageResource, 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(resource, 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(resource:WorkPackageResource, fieldNames:string[]):FieldDescriptor[] {\n const descriptors:FieldDescriptor[] = [];\n\n fieldNames.forEach((fieldName:string) => {\n if (fieldName === 'date') {\n descriptors.push(this.getDateField(resource));\n return;\n }\n\n if (!resource.schema[fieldName]) {\n debugLog('Unknown field for current schema', fieldName);\n return;\n }\n\n const field:DisplayField = this.displayField(resource, 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(resource:WorkPackageResource):FieldDescriptor {\n let object:any = {\n name: 'date',\n label: this.I18n.t('js.work_packages.properties.date'),\n multiple: false\n };\n\n if (resource.schema.hasOwnProperty('date')) {\n object.field = this.displayField(resource, 'date');\n } else {\n object.fields = [this.displayField(resource, 'startDate'), this.displayField(resource, 'dueDate')];\n object.multiple = true;\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 = workPackage.schema;\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(resource:WorkPackageResource, name:string):DisplayField {\n return this.displayFieldService.getField(\n resource,\n name,\n resource.schema[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","
    \n
    \n \n
    \n\n
    \n \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","// -- 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\nimport 'hammerjs';\n\n// Global scripts previously part of the application.js\n// Avoid require.context since that crashes angular regularly\nrequire('./globals/augmenting/modal-wrapper.augment.service');\nrequire('./globals/dynamic-bootstrapper');\nrequire('./globals/global-listeners');\nrequire('./globals/openproject');\nrequire('./globals/tree-menu');\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","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\n public onSave() {\n if (this.filters) {\n this.wpTableFilters.replaceIfComplete(this.filters);\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// ++\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","
    \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","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 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","//-- 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\nimport {DmListParameter, DmServiceInterface} from \"core-app/modules/hal/dm-services/dm.service.interface\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Injectable} from '@angular/core';\n\n// This only needs to be Injectable for the tests to work\n@Injectable()\nexport abstract class AbstractDmService implements DmServiceInterface {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService) {\n }\n\n public list(params:DmListParameter|null):Promise> {\n return this.listRequest(this.listUrl(), params) as Promise>;\n }\n\n\n public one(id:number):Promise {\n return this.halResourceService.get(this.oneUrl(id).toString()).toPromise();\n }\n\n protected listRequest(url:string, params:DmListParameter|null) {\n return this.halResourceService.get(url + this.listParamsString(params)).toPromise();\n }\n\n protected listParamsString(params:DmListParameter|null):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\n\n protected abstract listUrl():string;\n protected abstract oneUrl(id:number|string):string;\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-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 {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-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 {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 schema:QueryFilterInstanceSchemaResource;\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-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 {InputState, 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';\n\n@Injectable()\nexport class SchemaCacheService {\n\n constructor(readonly states:States,\n readonly halResourceService:HalResourceService) {\n }\n\n /**\n * Ensure the given schema identified by its href is currently loaded.\n * @param href The schema's href.\n * @return A promise with the loaded schema.\n */\n ensureLoaded(resource:HalResource):Promise {\n const state = this.state(resource);\n\n if (state.hasValue()) {\n return Promise.resolve(state.value);\n } else {\n return this.load(resource).valuesPromise() as Promise;\n }\n }\n\n /**\n * Get the associated schema state of the work package\n * without initializing a new resource.\n */\n state(resource:HalResource):InputState {\n const schema = resource.$links.schema;\n\n if (!schema) {\n throw `Resource ${resource} has no schema!`;\n }\n\n return this.states.schemas.get(schema.href!);\n }\n\n /**\n * Load the associated schema for the given work package, if needed.\n */\n load(resource:HalResource, forceUpdate = false):State {\n const state = this.state(resource);\n\n if (forceUpdate) {\n state.clear();\n }\n\n state.putFromPromiseIfPristine(() => {\n const schemaResource = this.halResourceService.createLinkedResource(resource, 'schema', resource.$links.schema.$link);\n return schemaResource.$load() as any;\n });\n\n return state;\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-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 {Injector} from '@angular/core';\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {Subscription} from 'rxjs';\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 });\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 private loadFieldSchema(fieldName:string, noWarnings:boolean = false):Promise {\n const schemaName = this.change.getSchemaName(fieldName);\n\n return new Promise((resolve, reject) => {\n this.loadFormAndCheck(schemaName, noWarnings);\n const fieldSchema:IFieldSchema = this.change.schema[schemaName];\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 schemaName\n * @param noWarnings\n */\n private loadFormAndCheck(fieldName:string, noWarnings:boolean = false) {\n const schemaName = this.change.getSchemaName(fieldName);\n\n // Ensure the form is being loaded if necessary\n this.change\n .getForm()\n .then((form) => {\n // Look up whether we're actually editable\n const fieldSchema = form.schema[schemaName];\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-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 {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input} 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\";\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 {\n @Input() public configuration:WorkPackageTableConfiguration;\n @Input() public showResizer:boolean = false;\n @Input() public resizerClass:string = '';\n @Input() public resizerStorageKey: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-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 {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit, Output} 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 this.wpTableFilters.replaceIfComplete(filters);\n this.filtersChanged.emit(this.filters);\n }\n}\n","\n\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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 '../../common/config/configuration.service';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\n\nexport class DatePicker {\n public datepickerFormat = 'yy-mm-dd';\n\n private datepickerCont: JQuery = jQuery(this.datepickerElem);\n private datepickerInstance:any = null;\n\n constructor(readonly ConfigurationService:ConfigurationService,\n readonly timezoneService:TimezoneService,\n private datepickerElem:JQuery,\n private date:any,\n private options:any) {\n this.initialize(options);\n }\n\n private initialize(options:any) {\n const firstDayOfWeek = this.ConfigurationService.startOfWeekPresent() ?\n this.ConfigurationService.startOfWeek() : (jQuery.datepicker as any)._defaults.firstDay;\n\n var mergedOptions = _.extend({}, options, {\n firstDay: firstDayOfWeek,\n showWeeks: true,\n changeMonth: true,\n changeYear: true,\n closeText: I18n.t('js.button_confirm'),\n dateFormat: this.datepickerFormat,\n defaultDate: this.timezoneService.formattedISODate(this.date),\n showButtonPanel: true,\n yearRange: \"-15:+20\"\n });\n\n this.datepickerInstance = this.datepickerCont.datepicker(mergedOptions);\n\n // Disable autocomplete to avoid overlay\n this.datepickerCont.attr('autocomplete', 'off');\n }\n\n public clear() {\n this.datepickerInstance.datepicker('setDate', null);\n }\n\n public destroy() {\n this.hide();\n this.datepickerInstance.datepicker('destroy');\n }\n\n public hide() {\n this.datepickerInstance.datepicker('hide');\n this.datepickerCont.scrollParent().off('scroll');\n }\n\n public show() {\n this.datepickerInstance.datepicker('show');\n this.hideDuringScroll();\n }\n\n public reshow() {\n this.datepickerInstance.datepicker('show');\n }\n\n private hideDuringScroll() {\n let reshowTimeout:any = null;\n let scrollParent = this.datepickerCont.scrollParent();\n\n scrollParent.scroll(() => {\n this.datepickerInstance.datepicker('hide');\n if (reshowTimeout) {\n clearTimeout(reshowTimeout);\n }\n\n reshowTimeout = setTimeout(() => {\n if (this.visibleAndActive()) {\n this.datepickerInstance.datepicker('show');\n }\n }, 50);\n });\n }\n\n private visibleAndActive() {\n var input = this.datepickerCont;\n\n try {\n return document.elementFromPoint(input.offset()!.left, input.offset()!.top) === input[0] &&\n document.activeElement === input[0];\n } catch(e) {\n console.error(\"Failed to test visibleAndActive \" + e)\n return false;\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// ++\n\nimport {Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {DatePicker} from 'core-app/modules/common/op-date-picker/datepicker';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\n\n@Component({\n selector: 'op-date-picker',\n templateUrl: './op-date-picker.component.html'\n})\nexport class OpDatePickerComponent implements OnInit, OnDestroy {\n @Output() public onChange = new EventEmitter();\n @Output() public onInputChange = new EventEmitter();\n @Output() public onClose = new EventEmitter();\n @Input() public initialDate?:string;\n\n private $element:JQuery;\n private datePickerInstance:DatePicker;\n private input:JQuery;\n\n public constructor(private elementRef:ElementRef,\n private ConfigurationService:ConfigurationService,\n private timezoneService:TimezoneService) {\n }\n\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.input = this.$element.find('input');\n this.input.on('change', () => this.onInputChange.emit(this.currentValue()))\n this.setup();\n }\n\n ngOnDestroy() {\n this.datePickerInstance && this.datePickerInstance.destroy();\n }\n\n public setup() {\n this.input.focus(() => this.showDatePicker());\n this.input.keydown((event) => {\n if (this.isEmpty()) {\n this.datePickerInstance.clear();\n }\n });\n }\n\n private isEmpty():boolean {\n return this.currentValue().trim() === '';\n }\n\n private currentValue():string {\n return this.input.val() as string;\n }\n\n private showDatePicker() {\n let options:any = {\n onSelect: (date:any) => {\n this.datePickerInstance.hide();\n\n let val = date;\n\n if (this.isEmpty()) {\n val = null;\n }\n\n this.input.val(val);\n this.input.trigger('change');\n this.onChange.emit(val);\n },\n onClose: () => this.onClose.emit()\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.ConfigurationService,\n this.timezoneService,\n this.input,\n initialValue,\n options\n );\n\n this.datePickerInstance.show();\n }\n}\n","
    \n \n
    \n","import {input} from 'reactivestates';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.service';\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\";\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 implements OnDestroy {\n\n private selectionState = input();\n\n public constructor(readonly querySpace:IsolatedQuerySpace,\n readonly states:States,\n readonly wpCacheService:WorkPackageCacheService,\n readonly opContextMenu:OPContextMenuService) {\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 isSelected(workPackageId:string) {\n return this.currentState.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.selectionState.putValue(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.currentState.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.selectionState.putValue(this._emptyState);\n }\n\n /**\n * Observe selection state\n */\n public selection$() {\n return this.selectionState.values$();\n }\n\n /**\n * Get current selection state.\n * @returns {WorkPackageViewSelectionState}\n */\n public get currentState():WorkPackageViewSelectionState {\n return this.selectionState.value as WorkPackageViewSelectionState;\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.currentState.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.currentState.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.currentState;\n state.selected[workPackageId] = newState;\n this.selectionState.putValue(state);\n }\n\n /**\n * Override current selection with the given work package id.\n */\n public setSelection(wpId:string, position:number) {\n let state:WorkPackageViewSelectionState = {\n selected: {},\n activeRowIndex: position\n };\n state.selected[wpId] = true;\n\n this.selectionState.putValue(state);\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.currentState;\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.selectionState.putValue(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","//-- 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\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-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 {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\";\n\n@Injectable()\nexport class WpChildrenInlineCreateService extends WorkPackageInlineCreateService implements WpRelationInlineCreateServiceInterface {\n\n constructor(readonly injector:Injector,\n protected readonly wpRelationsHierarchyService:WorkPackageRelationsHierarchyService) {\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 const wp = this.referenceTarget;\n return wp && !wp.isMilestone && wp.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","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\";\n\nexport class WorkPackageFilterValues {\n\n @InjectField() currentUser:CurrentUserService;\n @InjectField() halResourceService:HalResourceService;\n\n constructor(public injector:Injector,\n private change:WorkPackageChangeset,\n private filters:QueryFilterInstanceResource[],\n private excluded:string[] = []) {\n\n }\n\n public applyDefaultsFromFilters() {\n _.each(this.filters, filter => {\n // Ignore any filters except =\n if (filter.operator.id !== '=') {\n return;\n }\n\n // Exclude filters specified in constructor\n if (this.excluded.indexOf(filter.id) !== -1) {\n return;\n }\n\n // Avoid setting a value if current value is in filter list\n // and more than one value selected\n if (this.filterAlreadyApplied(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 this.setValueFor(filter.id, value);\n }\n });\n }\n\n private setValueFor(field:string, value:string|HalResource) {\n let newValue = this.findSpecialValue(value, field) || value;\n\n if (newValue) {\n this.change.projectedResource[field] = newValue;\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(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 = this.change.projectedResource[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","// -- 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\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-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 {ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, OnInit} 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\";\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 showListView: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 querySpace:IsolatedQuerySpace,\n readonly wpViewFilters:WorkPackageViewFiltersService,\n readonly deviceService:DeviceService,\n readonly CurrentProject:CurrentProjectService,\n readonly wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService,\n readonly cdRef:ChangeDetectorRef) {\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\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 protected showResizerInCardView():boolean {\n return false;\n }\n\n protected updateViewRepresentation(query:QueryResource) {\n this.showListView = !(this.deviceService.isMobile ||\n this.wpDisplayRepresentation.valueFromQuery(query) === wpDisplayCardRepresentation);\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-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, 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","\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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 a project management system.\n// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See doc/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-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 {StateService} from '@uirouter/core';\nimport {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.service';\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\";\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 wpCacheService:WorkPackageCacheService) {\n super();\n\n this.workPackageId = this.$state.params.workPackageId;\n wpCacheService.loadWorkPackage(this.workPackageId)\n .values$()\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","// -- 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\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 {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

    \n
    \n
    \n \n {{ text.labels[key] }}\n \n
    \n
    \n \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n","import {InjectionToken} from \"@angular/core\";\n\nexport const OpQueryConfigurationLocalsToken = new InjectionToken('OpQueryConfigurationLocalsToken');\nexport const OpQueryConfigurationTriggerEvent = 'op:queryconfiguration:trigger';\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, 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 {WorkPackageViewHandlerToken} 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\";\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 {\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\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 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 this.querySpace.results\n .values$()\n .pipe(\n withLatestFrom(this.querySpace.query.values$()),\n this.untilDestroyed(),\n filter(([results, query]) => results && !this.causedUpdates.includes(query))\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 new registry(this.injector).attachTo(this);\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-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 {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-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 {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\";\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: 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-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, 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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.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\";\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 wpCacheService:WorkPackageCacheService,\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.wpCacheService.loadWorkPackage(this.workPackage.id!, true);\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-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 {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 forResource(resource:HalResource):InputState|undefined {\n const stateName = _.camelCase(resource._type) + 's';\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 && 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","//-- 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\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 {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {States} from 'core-components/states.service';\nimport {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.service';\nimport {SchemaCacheService} from 'core-components/schemas/schema-cache.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 {WorkPackageDmService} from \"core-app/modules/hal/dm-services/work-package-dm.service\";\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\";\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}\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 public overriddenSchema:SchemaResource|undefined = undefined;\n @InjectField() I18n:I18nService;\n @InjectField() tates:States;\n @InjectField() wpActivity:WorkPackagesActivityService;\n @InjectField() workPackageDmService:WorkPackageDmService;\n @InjectField() wpCacheService:WorkPackageCacheService;\n @InjectField() schemaCacheService:SchemaCacheService;\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 public get isReadonly():boolean {\n return this.status && this.status.isReadonly;\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 isMilestone():boolean {\n return this.schema.hasOwnProperty('date');\n }\n\n public get isLeaf():boolean {\n var children = this.$links.children;\n return !(children && children.length > 0);\n }\n\n /**\n * Return whether the user in general has permission to edit the work package.\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.isNew || !!this.$links.update;\n }\n\n public previewPath() {\n if (!this.isNew) {\n return this.pathHelper.api.v3.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 /**\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 const fieldSchema = this.schema[property];\n\n return this.isEditable &&\n fieldSchema &&\n fieldSchema.writable &&\n (!this.isReadonly || property === 'status');\n }\n\n private performUpload(files:UploadFile[]) {\n let href = '';\n\n if (this.isNew) {\n href = this.pathHelper.api.v3.attachments.path;\n } else {\n href = this.attachments.$href!;\n }\n\n return this.opFileUpload.uploadAndMapResponse(href, files);\n }\n\n public getSchemaName(name:string):string {\n if (this.isMilestone && (name === 'startDate' || name === 'dueDate')) {\n return 'date';\n } else {\n return name;\n }\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 /**\n * Assign values from the form for a newly created work package resource.\n * @param form\n */\n public initializeNewResource(form:FormResource) {\n this.overriddenSchema = form.schema;\n this.$source.id = 'new';\n\n // Ensure type is set to identify the resource\n this._type = 'WorkPackage';\n\n // Since the ID will change upon saving, keep track of the WP\n // with the actual creation date\n this.__initialized_at = Date.now();\n\n // Set update link to form\n this['update'] = this.$links.update = form.$links.self;\n // Use POST /work_packages for saving link\n this['updateImmediately'] = this.$links.updateImmediately = (payload) => {\n return this.workPackageDmService.createWorkPackage(payload);\n };\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 * Get the current schema, assuming it is either:\n * 1. Overridden by the current loaded form\n * 2. Available as a schema state\n *\n * If it is neither, an exception is raised.\n */\n public get schema():SchemaResource {\n if (this.hasOverriddenSchema) {\n return this.overriddenSchema!;\n }\n\n const state = this.schemaCacheService.state(this as any);\n\n if (!state.hasValue()) {\n throw `Accessing schema of ${this.id} without it being loaded.`;\n }\n\n return state.value!;\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.wpCacheService.require(newValue.parent.id!, true);\n }\n\n return this.wpCacheService.updateWorkPackage(newValue as any);\n }\n\n public get hasOverriddenSchema():boolean {\n return this.overriddenSchema != null;\n }\n}\n\nexport const WorkPackageResource = Attachable(WorkPackageBaseResource);\n\nexport interface WorkPackageResource extends WorkPackageBaseResource, WorkPackageResourceLinks, WorkPackageResourceEmbedded {\n}\n","// -- copyright\n// OpenProject is a project management system.\n// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See doc/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,\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 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 debounceMs = 250) {\n\n /** Output switchmap observable */\n this.output$ = concat(\n of([]),\n this.input$.pipe(\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 )\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","//-- 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\nimport {Injectable} from '@angular/core';\nimport {AbstractDmService} from \"core-app/modules/hal/dm-services/abstract-dm.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {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 {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {PayloadDmService} from \"core-app/modules/hal/dm-services/payload-dm.service\";\n\n@Injectable()\nexport class TimeEntryDmService extends AbstractDmService {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService,\n protected payloadDm:PayloadDmService) {\n super(halResourceService, pathHelper);\n }\n\n protected listUrl() {\n return this.pathHelper.api.v3.time_entries.toString();\n }\n\n protected oneUrl(id:number|string) {\n return this.pathHelper.api.v3.time_entries.id(id).toString();\n }\n\n public update(resource:TimeEntryResource, schema:SchemaResource|null = null) {\n let payload = this.extractPayload(resource, schema);\n\n return this.halResourceService.patch(resource.updateImmediately.$link.href, payload).toPromise();\n }\n\n public updateForm(resource:TimeEntryResource, schema:SchemaResource|null = null) {\n let payload = this.extractPayload(resource, schema);\n\n return this.halResourceService.post(this.pathHelper.api.v3.time_entries.id(resource.idFromLink).form.toString(),\n payload).toPromise();\n }\n\n public createForm(payload:{}) {\n return this.halResourceService.post(this.pathHelper.api.v3.time_entries.form.toString(), payload).toPromise();\n }\n\n public create(payload:{}):Promise {\n return this.halResourceService\n .post(this.pathHelper.api.v3.time_entries.path, payload)\n .toPromise();\n }\n\n public delete(resource:TimeEntryResource) {\n return this.halResourceService\n .delete(this.pathHelper.api.v3.time_entries.id(resource.idFromLink).toString())\n .toPromise();\n }\n\n public extractPayload(resource:TimeEntryResource|null = null, schema:SchemaResource|null = null) {\n if (resource && schema) {\n return this.payloadDm.extract(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-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, 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","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","import {utils} from \"@xeokit/xeokit-sdk/src/viewer/scene/utils\";\n/**\n * Default server client which loads content via HTTP from the file system.\n */\nclass XeokitServer {\n\n /**\n *\n * @param cfg\n * @param.cfg.dataDir Base directory for content.\n */\n constructor(cfg = {}) {\n this._dataDir = cfg.dataDir || \"\";\n }\n\n /**\n * Gets the manifest of all projects.\n * @param done\n * @param error\n */\n getProjects(done, _error) {\n done({ projects: window.gon.ifc_models.projects });\n }\n\n /**\n * Gets a manifest for a project.\n * @param projectId\n * @param done\n * @param error\n */\n getProject(projectData, done, _error) {\n var manifestData = {\n id: projectData[0].id,\n name: projectData[0].name,\n models: window.gon.ifc_models.models,\n viewerContent: {\n modelsLoaded: window.gon.ifc_models.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, modelId, done, error) {\n const attachmentId = window.gon.ifc_models.metadata_attachment_ids[modelId];\n console.log(`Loading model metadata for: ${attachmentId}`);\n utils.loadJSON(this.attachmentUrl(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, modelId, done, error) {\n const attachmentId = window.gon.ifc_models.xkt_attachment_ids[modelId];\n console.log(`Loading model geometry for: ${attachmentId}`);\n utils.loadArraybuffer(this.attachmentUrl(attachmentId), done, error);\n }\n\n attachmentUrl(attachmentId) {\n return \"/api/v3/attachments/\" + attachmentId + \"/content\";\n }\n}\n\nexport {XeokitServer};","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 {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 @InjectField() pathHelper:PathHelperService;\n @InjectField() bcfApi:BcfApiService;\n @InjectField() viewpointsService:ViewpointsService; \n\n private _viewer:any;\n\n // private _loaded:BehaviorSubject = new BehaviorSubject(false);\n // readonly loaded$:Observable = this._loaded.asObservable().pipe(shareReplay({refCount: true, bufferSize: 1}));\n\n private $loaded = new Subject();\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();\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.$loaded.complete());\n\n viewerUI.loadProject(projects[0][\"id\"]);\n\n this.viewer = viewerUI;\n });\n }\n\n public destroy() {\n this.$loaded.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\n // TODO: Remove this?\n public onLoad$():Observable {\n return this.$loaded;\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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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: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","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-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, 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-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 {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\",\"subject\",\"startDate\",\"dueDate\"],\"tv\":true,\"tzl\":\"years\",\"hi\":true,\"g\":\"\",\"t\":\"id:asc\",\"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\n const matched = _.find(this.all, item =>\n item.query_props && item.query_props === JSON.stringify(queryProps)\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-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 {Injectable, Injector} from '@angular/core';\nimport {HttpClient, HttpErrorResponse, HttpParams} from '@angular/common/http';\nimport {throwError} from 'rxjs/internal/observable/throwError';\nimport {catchError, map} from 'rxjs/operators';\nimport {Observable} 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 {initializeHalProperties} from 'core-app/modules/hal/helpers/hal-resource-builder';\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\";\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:CollectionResource[] = [];\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-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\nimport {Component, HostListener, Input} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.service';\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\";\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 wpCacheService:WorkPackageCacheService,\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.post(this.action.href + '/execute', payload)\n .toPromise()\n .then((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.wpSchemaCacheService.ensureLoaded(savedWp).then(() => {\n this.wpCacheService.updateWorkPackage(savedWp, true);\n this.halEditing.stopEditing(savedWp);\n this.halEvents.push(savedWp, { eventType: \"updated\" });\n });\n }).catch((errorResource:any) => {\n this.notificationService.handleRawError(errorResource, this.workPackage);\n });\n }\n\n @HostListener('mouseenter') onMouseEnter() {\n this.fetchAction();\n }\n}\n\n","\n {{action.name}}\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\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","// -- 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\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 inEditMode:boolean;\n\n /** Whether the field is currently active */\n active:boolean;\n\n /** Whether the field is being saved */\n 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 errorMessageOnLabel?:string;\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 /**\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 * 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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {keyCodes} from 'core-app/modules/common/keyCodes.enum';\n\n@Directive({\n selector: '[accessibleClick]',\n})\nexport class AccessibleClickDirective {\n @Input('accessibleClickStopEvent') stopEventPropagation:boolean = true;\n @Output('accessibleClick') onClick = new EventEmitter();\n\n @HostListener('click', ['$event'])\n @HostListener('keydown', ['$event'])\n public handleClick(event:JQuery.TriggeredEvent) {\n if (event.type === 'click' || event.which === keyCodes.ENTER || event.which === keyCodes.SPACE) {\n\n if (this.stopEventPropagation) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n this.onClick.emit(event);\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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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\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-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 {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-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 {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';\nimport {QueryFormDmService} from \"core-app/modules/hal/dm-services/query-form-dm.service\";\n\n@Injectable()\nexport class WorkPackagesListInvalidQueryService {\n constructor(protected halResourceService:HalResourceService,\n protected queryFormDm:QueryFormDmService) {}\n\n public restoreQuery(query:QueryResource, form:QueryFormResource) {\n let payload = this.queryFormDm.buildQueryResource(form);\n\n this.restoreFilters(query, payload, form.schema);\n this.restoreColumns(query, payload, form.schema);\n this.restoreSortBy(query, payload, form.schema);\n this.restoreGroupBy(query, payload, form.schema);\n this.restoreOtherProperties(query, 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","// -- 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\nimport {Component, Input} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\n@Component({\n selector: 'wp-custom-actions',\n templateUrl: './wp-custom-actions.component.html'\n})\nexport class WpCustomActionsComponent {\n\n @Input() workPackage:WorkPackageResource;\n\n public get actions() {\n return this.workPackage.customActions;\n }\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 {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;\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","
    \n \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 * 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 * Load event\n */\n abstract onLoad$():Observable;\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\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","
    \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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {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 {{value}}%\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 public file:UploadFile;\n public value:number = 0;\n public error:boolean = false;\n public completed = false;\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","//-- 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\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 {WorkPackageCacheService} from '../work-packages/work-package-cache.service';\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\";\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 wpCacheService:WorkPackageCacheService) {\n super();\n }\n\n ngOnInit() {\n this.canAddRelation = !!this.workPackage.addRelation;\n\n this.wpRelations.state(this.workPackage.id!).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.wpCacheService.loadWorkPackage(this.workPackage.id!).values$()\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 return this.wpCacheService.loadWorkPackage(wpId).values$();\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

    \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-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 {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","// -- 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\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 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-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 {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","// -- 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\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","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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\n\n\n@Injectable()\nexport class ViewpointsService {\n topicUUID:string|number;\n\n @InjectField() bcfApi:BcfApiService;\n @InjectField() viewerBridge:ViewerBridgeService;\n @InjectField() wpCache:WorkPackageCacheService;\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.wpCache.require(workPackage.id!, 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) => this.wpCache.require(workPackage.id!, 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-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 {AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, Output} from '@angular/core';\nimport {VersionDmService} from \"core-app/modules/hal/dm-services/version-dm.service\";\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\";\n\n@Component({\n templateUrl: './create-autocompleter.component.html',\n selector: 'version-autocompleter'\n})\nexport class VersionAutocompleterComponent extends CreateAutocompleterComponent implements AfterViewInit {\n @Input() public openDirectly:boolean = false;\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 versionDm:VersionDmService,\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.versionDm\n .canCreateVersionInProject(this.currentProject.id!)\n .catch(() => false);\n }\n\n protected createNewVersion(name:string) {\n this.versionDm.createVersion(this.getVersionPayload(name))\n .then((version) => {\n this.onCreate.emit(version);\n })\n .catch(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.pathHelper.api.v3.projects.id(this.currentProject.id!).path\n }\n };\n\n return payload;\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\nimport {Injectable} 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 {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {PayloadDmService} from \"core-app/modules/hal/dm-services/payload-dm.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {AbstractDmService} from \"core-app/modules/hal/dm-services/abstract-dm.service\";\n\n@Injectable()\nexport class GridDmService extends AbstractDmService {\n constructor(protected halResourceService:HalResourceService,\n protected pathHelper:PathHelperService,\n protected payloadDm:PayloadDmService) {\n super(halResourceService,\n pathHelper);\n }\n\n public createForm(resource:GridResource|null|any = null, schema:SchemaResource|null = null) {\n let payload = this.extractPayload(resource, schema);\n\n return this.halResourceService.post(this.pathHelper.api.v3.grids.form().toString(),\n payload).toPromise();\n }\n\n public create(resource:GridResource, schema:SchemaResource|null = null):Promise {\n let payload = this.extractPayload(resource, schema);\n\n return this.halResourceService.post(this.pathHelper.api.v3.grids.path,\n payload).toPromise();\n }\n\n public update(resource:GridResource, schema:SchemaResource|null = null):Promise {\n let payload = this.extractPayload(resource, schema);\n\n return this.halResourceService.patch(this.pathHelper.api.v3.grids.id(resource.id!).toString(),\n payload).toPromise();\n }\n\n public updateForm(resource:GridResource, schema:SchemaResource|null = null) {\n let payload = this.extractPayload(resource, schema);\n\n return this.halResourceService.post(this.pathHelper.api.v3.grids.id(resource.idFromLink).form.toString(),\n payload).toPromise();\n }\n\n public extractPayload(resource:GridResource|null = null, schema:SchemaResource|null = null) {\n if (resource && schema) {\n let payload = this.payloadDm.extract(resource, 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 = resource.widgets.map((widget) => {\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 } else if (!(resource instanceof HalResource)) {\n return resource;\n } else {\n return {};\n }\n }\n\n protected listUrl() {\n return this.pathHelper.api.v3.grids.toString();\n }\n\n protected oneUrl(id:number|string) {\n return this.pathHelper.api.v3.grids.id(id).toString();\n }\n}\n","// Separated from render passes to avoid cyclic dependencies\nexport const rowGroupClassName = 'wp-table--group-header';\nexport const collapsedRowClass = '-collapsed';\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 {MultiInputState} from \"reactivestates\";\nimport {Injectable} from '@angular/core';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {StateCacheService} from 'core-components/states/state-cache.service';\nimport {UserDmService} from 'core-app/modules/hal/dm-services/user-dm.service';\nimport {States} from 'core-components/states.service';\n\n@Injectable({ providedIn: 'root' })\nexport class UserCacheService extends StateCacheService {\n\n constructor(readonly states:States,\n readonly userDmService:UserDmService) {\n super();\n }\n\n protected load(id:number|string):Promise {\n return this.userDmService.load(id);\n }\n\n protected loadAll(ids:string[]):Promise {\n const promises = ids.map(id => this.load(id));\n return Promise.all(promises).then(() => undefined);\n }\n\n protected get multiState():MultiInputState {\n return this.states.users;\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\nimport {input} from 'reactivestates';\nimport {HelpTextResource} from 'core-app/modules/hal/resources/help-text-resource';\nimport {HelpTextDmService} from 'core-app/modules/hal/dm-services/help-text-dm.service';\nimport {Injectable} from '@angular/core';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\n\n@Injectable({ providedIn: 'root' })\nexport class AttributeHelpTextsService {\n private helpTexts = input();\n\n constructor(private helpTextDm:HelpTextDmService) {\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.helpTexts.putFromPromiseIfPristine(() =>\n this.helpTextDm\n .loadAll()\n .then((resources:CollectionResource) => resources.elements)\n );\n\n return new Promise((resolve, reject) => {\n this.helpTexts\n .valuesPromise()\n .then(() => resolve(this.find(attribute, scope)));\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","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 {ExternalQueryConfigurationComponent} from \"core-components/wp-table/external-configuration/external-query-configuration.component\";\nimport {\n OpQueryConfigurationLocalsToken,\n OpQueryConfigurationTriggerEvent\n} 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 public setupListener() {\n // Listen to keyups on window to close context menus\n jQuery(window)\n .on(OpQueryConfigurationTriggerEvent,\n (event:JQuery.TriggeredEvent, originator:JQuery, currentQuery:any) => {\n this.show(originator, currentQuery);\n return false;\n });\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(currentQuery:any,\n callback:(newQuery:any) => void,\n disabledTabs:{[key:string]:string} = {}) {\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({\n callback: callback,\n currentQuery: currentQuery,\n disabledTabs: disabledTabs\n })\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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free 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 {UserCacheService} from \"core-components/user/user-cache.service\";\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\";\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 userCacheService:UserCacheService) {\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.userCacheService\n .require(this.activity.author.idFromLink)\n .then((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
    \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-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 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-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 {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) {\n if (!isNaN(value)) {\n let floatValue = parseFloat(value);\n return moment.duration(floatValue, 'hours');\n }\n\n return value;\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 = this.resource[this.name];\n }\n\n return parsedValue;\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// ++\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-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} 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\";\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\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\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","\n\n","
    \n \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// ++\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 ? 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-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\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-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 {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-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 * 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\";\n\n@Component({\n template: `\n \n\n \n\n \n\n `\n})\nexport class DateEditFieldComponent extends EditFieldComponent {\n @InjectField() readonly timezoneService:TimezoneService;\n\n public onValueSelected(data:string) {\n this.value = this.parser(data);\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 * Return the default date for the datepicker instance.\n * If this field is the finish date, we select the start date + 1 as the default.\n */\n public get defaultDate():String {\n const isDueDate = this.name === 'dueDate';\n\n if (isDueDate) {\n return this.resource.startDate;\n }\n\n return '';\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-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 {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 a project management system.\n// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See doc/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 a project management system.\n// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See doc/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 {TimeEntryDmService} from \"core-app/modules/hal/dm-services/time-entry-dm.service\";\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\";\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() public timeEntryDm:TimeEntryDmService;\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 .timeEntryDm\n .list({ filters: [['user_id', '=', ['me']]], sortBy: [[\"updated_on\", \"desc\"]], pageSize: RECENT_TIME_ENTRIES_MAGIC_NUMBER })\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-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 {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-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 {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-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 {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-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 {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-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 {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('read-value--html', 'wiki', 'highlight', '-multiline');\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-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\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-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 {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-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 {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\n /** Optionally test if we can inject highlighting service */\n @InjectField(WorkPackageViewHighlightingService, null) viewHighlighting:WorkPackageViewHighlightingService;\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.name);\n return this.context.container !== 'table' || shouldHighlight;\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\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\";\n\nexport class DateDisplayField extends HighlightableDisplayField {\n @InjectField() timezoneService:TimezoneService;\n\n public render(element:HTMLElement, displayText:string):void {\n super.render(element, displayText);\n\n // Highlight overdue tasks\n if (this.shouldHighlight && this.canOverdue) {\n const diff = this.timezoneService.daysFromToday(this.value);\n element.classList.add(Highlighting.overdueDate(diff));\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","// -- 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\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-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 {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-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 {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-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 { DurationDisplayField } from './duration-display-field.module';\nimport { PathHelperService } from 'core-app/modules/common/path-helper/path-helper.service';\nimport { ProjectCacheService } from \"core-components/projects/project-cache.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\";\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() projectCacheService:ProjectCacheService;\n @InjectField() timeEntryCreateService:TimeEntryCreateService;\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.projectCacheService\n .require(this.resource.project.idFromLink)\n .then((project:ProjectResource) => {\n const href = URI(this.PathHelper.projectTimeEntriesPath(project.identifier))\n .search({ work_package_id: wpID })\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.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-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 {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-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 {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-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 {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-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 {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-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 {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-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 {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-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 {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 element.innerHTML = `\n \n ${projectStatusI18n(code, this.I18n)}\n \n `;\n }\n}\n","// -- copyright\n// OpenProject is a project management system.\n// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See doc/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 a project management system.\n// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See doc/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 element.innerHTML = '';\n element.appendChild(link);\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-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 {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\";\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n OpenprojectAccessibilityModule,\n OpenprojectEditorModule,\n ],\n exports: [\n EditFieldControlsComponent,\n EditFormPortalComponent,\n EditFormComponent,\n EditableAttributeFieldComponent,\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 EditableAttributeFieldComponent,\n ProjectStatusEditFieldComponent,\n ]\n})\nexport class OpenprojectFieldsModule {\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\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\";\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('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-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 {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\";\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('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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","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-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 {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-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 {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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 && value.$href.match(/^\\/api\\/v3\\/string_objects/i)) {\n return value.$href.match(/value=([^&]+)/)[1].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-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 {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 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\n if (!this.backRoute || this.backRoute.name.includes('new')) {\n this.$state.go(baseRoute, this.$state.params);\n } else {\n if (this.keepTab.isDetailsState(this.backRoute.parent)) {\n if (preferListOverSplit) {\n this.$state.go(baseRoute, this.$state.params);\n } else {\n this.$state.go(baseRoute + this.keepTab.currentDetailsSubState, this.$state.params);\n }\n } else {\n this.$state.go(this.backRoute.name, this.backRoute.params);\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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\nimport {relationRowClass} from \"core-components/wp-fast-table/helpers/wp-table-row-helpers\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HierarchyDragActionService extends TableDragActionService {\n\n @InjectField() private wpTableHierarchies:WorkPackageViewHierarchiesService;\n @InjectField() private relationHierarchyService:WorkPackageRelationsHierarchyService;\n @InjectField() private wpCacheService:WorkPackageCacheService;\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:HTMLElement):Promise {\n let previous = el.previousElementSibling;\n var parent = null;\n\n if (previous !== null && !this.isFlatList(previous)) {\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 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 if (this.isHiearchyRoot(previous, previousWpId)) {\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 isFlatList(previous:Element):boolean {\n const inGroup = previous.className.indexOf(hierarchyGroupClass('')) >= 0;\n const isRoot = previous.className.indexOf(hierarchyRootClass('')) >= 0;\n\n return !(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.wpCacheService.require(wpId)\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\";\n\nexport class GroupByDragActionService extends TableDragActionService {\n\n @InjectField() wpTableGroupBy:WorkPackageViewGroupByService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() halEvents:HalEventsService;\n @InjectField() halNotification:HalResourceNotificationService;\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 && 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","import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {\n DisplayFieldRenderer,\n editFieldContainerClass\n} from '../../wp-edit-form/display-field-renderer';\nimport {Injector} from '@angular/core';\nimport {QueryColumn} from \"core-components/wp-query/query-column\";\nexport const tdClassName = 'wp-table--cell-td';\nexport const editCellContainer = 'wp-table--cell-container';\n\nexport class CellBuilder {\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 = workPackage.schema[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","//-- 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\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","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-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 {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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\n\n@Injectable()\nexport class WorkPackageNotificationService extends HalResourceNotificationService {\n\n constructor(readonly injector:Injector,\n protected wpCacheService:WorkPackageCacheService) {\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.wpCacheService.require(resource.id!, true)\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-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 {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-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 {Transition} from '@uirouter/core';\nimport {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.service';\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\";\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 wpCacheService:WorkPackageCacheService) {\n super();\n }\n\n ngOnInit() {\n const wpId = this.workPackageId || this.$transition.params('to').workPackageId;\n this.wpCacheService.loadWorkPackage(wpId)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp) => {\n this.workPackageId = wp.id!;\n this.workPackage = wp;\n });\n }\n\n}\n","
    \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-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 {AbstractWorkPackageButtonComponent} from '../wp-buttons.module';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\n\nconst screenfull:any = require('screenfull/dist/screenfull.js');\n\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 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","//-- 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\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 // TODO: extract the whole overridden Schema stuff into halresource or use the schemaCacheService\n // to place it there\n @InjectField() schemaCacheService:SchemaCacheService;\n\n public overriddenSchema:SchemaResource|undefined = undefined;\n\n /**\n * Get the current schema, assuming it is either:\n * 1. Overridden by the current loaded form\n * 2. Available as a schema state\n *\n * If it is neither, an exception is raised.\n */\n public get schema():SchemaResource {\n if (this.hasOverriddenSchema) {\n return this.overriddenSchema!;\n }\n\n const state = this.schemaCacheService.state(this as any);\n\n if (!state.hasValue()) {\n throw `Accessing schema of ${this.id} without it being loaded.`;\n }\n\n return state.value!;\n }\n\n public get hasOverriddenSchema():boolean {\n return this.overriddenSchema != null;\n }\n\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","import \"reflect-metadata\";\nimport {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) {\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);\n } else {\n const type = Reflect.getMetadata('design:type', target, property);\n return this.injector.get(type);\n }\n },\n set: function(this:InjectableClass, _val:any) {\n debugLog(\"Trying to set InjectField property \" + property);\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 \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-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 {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","
    \n\n \n\n
    \n
    \n
    \n\n \n\n
    \n \n
    \n
    \n
      \n
    • \n \n \n
    • \n
    • \n \n \n
    • \n
    • \n \n \n
    • \n
    • \n \n
    • \n
    \n
    \n
    \n\n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
      \n \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-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 {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 {ProjectCacheService} from 'core-components/projects/project-cache.service';\nimport {OpTitleService} from 'core-components/html/op-title.service';\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.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\";\n\nexport class WorkPackageSingleViewBase extends UntilDestroyedMixin {\n\n @InjectField() wpCacheService:WorkPackageCacheService;\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() projectCacheService:ProjectCacheService;\n @InjectField() authorisationService:AuthorisationService;\n @InjectField() cdRef:ChangeDetectorRef;\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 @InjectField() readonly titleService:OpTitleService;\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.wpCacheService.require(this.workPackageId)\n .catch((error) => this.notificationService.handleRawError(error));\n\n /** Stream updates of the work package */\n this.wpCacheService.state(this.workPackageId)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.init();\n this.cdRef.detectChanges();\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.projectCacheService\n .require(this.workPackage.project.idFromLink)\n .then(() => {\n this.projectIdentifier = this.workPackage.project.identifier;\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 public get isEditable() {\n return this.workPackage.isEditable;\n }\n}\n","import {WorkPackageCacheService} from '../../work-packages/work-package-cache.service';\nimport {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\";\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 wpCacheService:WorkPackageCacheService,\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.wpCacheService\n .observe(this.relatedWorkPackage.id!)\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.wpCacheService.updateWorkPackage(this.relatedWorkPackage);\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 \n \n
    \n\n
    \n \n \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 {Injectable} from \"@angular/core\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {QueryFormDmService} from \"core-app/modules/hal/dm-services/query-form-dm.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {QueryDmService} from \"core-app/modules/hal/dm-services/query-dm.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\";\n\n@Injectable({ providedIn: 'root' })\nexport class BoardListsService {\n\n private readonly v3 = this.pathHelper.api.v3;\n\n constructor(private readonly CurrentProject:CurrentProjectService,\n private readonly pathHelper:PathHelperService,\n private readonly QueryDm:QueryDmService,\n private readonly halResourceService:HalResourceService,\n private readonly QueryFormDm:QueryFormDmService,\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.QueryFormDm\n .loadWithParams(\n {\n pageSize: 0,\n filters: filterJson\n },\n undefined,\n this.CurrentProject.identifier,\n this.buildQueryRequest(params),\n )\n .then(form => {\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 const query = this.QueryFormDm.buildQueryResource(form);\n return this.QueryDm.create(query, form);\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.resource(\"/queries/sort_bys/manualSorting-asc\") },\n { \"href\": this.v3.resource(\"/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-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// ++ 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-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 {Injectable} from \"@angular/core\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.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 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.PathHelper.api.v3.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 {QueryFormDmService} from 'core-app/modules/hal/dm-services/query-form-dm.service';\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\";\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 queryFormDm:QueryFormDmService,\n readonly wpStatesInitialization:WorkPackageStatesInitializationService,\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.queryFormDm\n .load(query)\n .then((form:QueryFormResource) => {\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-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, 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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.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\";\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 wpCacheService:WorkPackageCacheService,\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.wpCacheService\n .observe(this.workPackage.id!)\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-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 {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 this.halEvents.push(this.workPackage, { eventType: 'updated' });\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","// -- 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\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 (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","// -- 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\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","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-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 {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 dragContainer = member.dragContainer;\n\n if (this.autoscroll) {\n this.autoscroll.add(dragContainer);\n } else {\n this.setupAutoscroll([dragContainer]);\n }\n\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","//-- 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\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-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 {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 {AttributeHelpTextComponent} from 'core-app/modules/common/help-texts/attribute-help-text.component';\nimport {AttributeHelpTextModal} from 'core-app/modules/common/help-texts/attribute-help-text.modal';\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\";\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 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\n OpDatePickerComponent,\n OpDateTimeComponent,\n OpIcon,\n AutofocusDirective,\n\n AttributeHelpTextComponent,\n AttributeHelpTextModal,\n FocusWithinDirective,\n FocusDirective,\n AuthoringComponent,\n\n // Notifications\n NotificationsContainerComponent,\n NotificationComponent,\n UploadProgressComponent,\n OpDateTimeComponent,\n\n // Entries for ng1 downgraded components\n AttributeHelpTextComponent,\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 declarations: [\n OpDatePickerComponent,\n OpDateTimeComponent,\n OpIcon,\n AutofocusDirective,\n\n AttributeHelpTextComponent,\n AttributeHelpTextModal,\n FocusWithinDirective,\n FocusDirective,\n AuthoringComponent,\n\n // Notifications\n NotificationsContainerComponent,\n NotificationComponent,\n UploadProgressComponent,\n OpDateTimeComponent,\n\n OPContextMenuComponent,\n IconTriggeredContextMenuComponent,\n\n // Entries for ng1 downgraded components\n AttributeHelpTextComponent,\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\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})\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-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 {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","import {RelationsDmService} from 'core-app/modules/hal/dm-services/relations-dm.service';\nimport {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 {StateCacheService} from '../states/state-cache.service';\nimport {Injectable} from \"@angular/core\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\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 private relationStates:RelationStateGroup;\n\n /*@ngInject*/\n constructor(private relationsDm:RelationsDmService,\n private PathHelper:PathHelperService,\n private halResource:HalResourceService) {\n super();\n this.relationStates = new RelationStateGroup();\n }\n\n protected get multiState() {\n return this.relationStates.relations;\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):Promise {\n return new Promise((resolve, reject) => {\n this.relationsDm\n .load(id)\n .then(elements => {\n this.updateRelationsStateTo(id, elements);\n resolve(this.state(id).value!);\n })\n .catch(reject);\n });\n }\n\n protected loadAll(ids:string[]) {\n return new Promise((resolve, reject) => {\n this.relationsDm\n .loadInvolved(ids)\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.PathHelper.api.v3.work_packages.id(fromId).toString() },\n to: {href: this.PathHelper.api.v3.work_packages.id(relatedWpId).toString() }\n },\n type: relationType\n };\n\n const path = this.PathHelper.api.v3.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, fill\n * the associated relations state\n *\n * @param wpId The wpId the relations belong to\n * @param relations The relation resource array.\n */\n private updateRelationsStateTo(wpId:string, relations:RelationResource[]) {\n const state = this.multiState.get(wpId);\n const relationsToInsert = _.keyBy(relations, r => r.id!);\n\n state.putValue(relationsToInsert, 'Overriding relations state.');\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(id => {\n const relevant = relations.filter(r => r.isInvolved(id));\n this.updateRelationsStateTo(id, relevant);\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// ++\n\nimport {MultiInputState, State} from 'reactivestates';\nimport {States} from '../states.service';\nimport {StateCacheService} from '../states/state-cache.service';\nimport {SchemaCacheService} from './../schemas/schema-cache.service';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Injectable} from '@angular/core';\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {WorkPackageDmService} from \"core-app/modules/hal/dm-services/work-package-dm.service\";\n\nfunction getWorkPackageId(id:string|null):string {\n return (id || 'new').toString();\n}\n\n@Injectable()\nexport class WorkPackageCacheService extends StateCacheService {\n\n /*@ngInject*/\n constructor(private states:States,\n private schemaCacheService:SchemaCacheService,\n private workPackageDmService:WorkPackageDmService) {\n super();\n }\n\n public updateValue(id:string, val:WorkPackageResource) {\n this.updateWorkPackageList([val], false);\n }\n\n updateWorkPackage(wp:WorkPackageResource, immediate:boolean = false):Promise {\n const wpId = getWorkPackageId(wp.id!);\n\n if (immediate || wp.isNew) {\n this.multiState.get(wpId).putValue(wp);\n return Promise.resolve();\n } else {\n return this.schemaCacheService.ensureLoaded(wp).then(() => {\n this.multiState.get(wpId).putValue(wp);\n });\n }\n }\n\n updateWorkPackageList(list:WorkPackageResource[], skipOnIdentical = true) {\n for (var i of list) {\n const wp = i;\n const workPackageId = getWorkPackageId(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 this.multiState.get(workPackageId).putValue(wp);\n });\n }\n }\n\n /**\n * Wrapper around `require(id)`.\n *\n * @deprecated\n */\n loadWorkPackage(workPackageId:string, forceUpdate = false):State {\n const state = this.state(workPackageId);\n\n // Several services involved in the creation of work packages\n // use this method to resolve the latest created work package,\n // so let them just subscribe.\n if (workPackageId === 'new') {\n return state;\n }\n\n this.require(workPackageId, forceUpdate);\n return state;\n }\n\n protected loadAll(ids:string[]) {\n return new Promise((resolve, reject) => {\n this.workPackageDmService\n .loadWorkPackagesCollectionsFor(_.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.updateWorkPackageList(results.elements);\n }\n\n resolve(undefined);\n });\n }, reject);\n });\n }\n\n protected load(id:string) {\n return new Promise((resolve, reject) => {\n\n const errorAndReject = (error:any) => {\n reject(error);\n };\n\n this.workPackageDmService.loadWorkPackageById(id, true)\n .then((workPackage:WorkPackageResource) => {\n this.schemaCacheService.ensureLoaded(workPackage).then(() => {\n this.multiState.get(id).putValue(workPackage);\n resolve(workPackage);\n }, errorAndReject);\n }, errorAndReject);\n });\n }\n\n protected get multiState():MultiInputState {\n return this.states.workPackages;\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//++\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 name:string;\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","// -- 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\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","
      \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","
    \n
      \n
    • \n \n
    • \n
    \n
    \n \n
    \n
    \n \n
    \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-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 {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 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-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 {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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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\";\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 = '';\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\n}(jQuery));\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 .datepicker() // Create datepicker with defaults\n .datepicker('show'); // And show immediately since the click is not yet wired to the datepicker instance\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-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\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-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\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
    \n\n \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-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 {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {WorkPackageCacheService} from '../work-package-cache.service';\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\";\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 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 wpCacheService:WorkPackageCacheService,\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 get htmlId() {\n return 'wp-comment-field';\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.wpCacheService.updateWorkPackage(this.workPackage);\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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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';\n\n/**\n * OpenProject instance methods\n */\nexport class OpenProject {\n\n public pluginContext:InputState = input();\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\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","// -- 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\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 {Injectable, Injector} from '@angular/core';\nimport {Observable, Subject} from \"rxjs\";\nimport {distinctUntilChanged, filter, first, 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 {input} from \"reactivestates\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {ViewpointsService} from \"core-app/modules/bim/bcf/helper/viewpoints.service\";\nimport {map} from \"rxjs/operators\";\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 private revitMessageReceivedSource = new Subject<{ messageType:string, trackingId:string, messagePayload:string }>();\n private _trackingIdNumber = 0;\n private _ready$ = input(false);\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 console.log(\"window.RevitBridge is already there, so let's hook up the Revit Listener\");\n this.hookUpRevitListener();\n } else {\n console.log('Waiting for Revit Plugin to become ready.');\n window.addEventListener('revit.plugin.ready', () => {\n console.log('CAPTURED EVENT \"revit.plugin.ready\"');\n this.hookUpRevitListener();\n });\n }\n }\n\n public viewerVisible() {\n return this._ready$.getValueOr(false);\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 = JSON.parse(message.messagePayload);\n\n viewpointJson.snapshot = {\n snapshot_type: 'png',\n snapshot_data: viewpointJson.snapshot\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 console.log('The Revit bridge is not ready yet.');\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._ready$.putValue(true);\n }\n\n newTrackingId():string {\n this._trackingIdNumber = this._trackingIdNumber + 1;\n return String(this._trackingIdNumber);\n }\n\n onLoad$():Observable {\n return this\n ._ready$\n .values$()\n .pipe(mapTo(undefined));\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 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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.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\";\n\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 {\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 = this.viewerBridge.viewerVisible();\n projectId: string;\n\n constructor(readonly state:StateService,\n readonly bcfAuthorization:BcfAuthorizationService,\n readonly viewerBridge:ViewerBridgeService,\n readonly wpCache:WorkPackageCacheService,\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 protected observeChanges() {\n this.wpCache\n .observe(this.workPackage.id!)\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) => this.showViewpoint(this.workPackage, index),\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","// -- 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\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 {RevitBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/revit-bridge.service\";\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\";\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) {\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","//-- 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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\njQuery(function($) {\n var regions = $.datepicker.regional;\n var regional = regions[I18n.locale] || regions[''];\n\n // see ./app/helpers/application_helper.rb:508\n if (typeof I18n.firstDayOfWeek === 'number') {\n regional.firstDay = I18n.firstDayOfWeek;\n }\n\n $.datepicker.setDefaults(regional);\n\n var gotoToday = $.datepicker._gotoToday;\n\n $.datepicker._gotoToday = function (id) {\n gotoToday.call(this, id);\n var target = $(id),\n inst = this._getInst(target[0]),\n dateStr = $.datepicker._formatDate(inst);\n target.val(dateStr);\n target.blur();\n $.datepicker._hideDatepicker();\n };\n\n var defaults = {\n showWeek: true,\n changeMonth: true,\n changeYear: true,\n yearRange: 'c-100:c+10',\n dateFormat: 'yy-mm-dd',\n showButtonPanel: true,\n calculateWeek: function (day) {\n var dayOfWeek = new Date(+day);\n\n if (day.getDay() != 1) {\n dayOfWeek.setDate(day.getDate() - day.getDay() + 1);\n }\n\n return $.datepicker.iso8601Week(dayOfWeek);\n }\n };\n\n $.datepicker.setDefaults(defaults);\n\n $.extend($.datepicker, {\n\n _originalGotoToday: $.datepicker._gotoToday,\n _gotoToday: function(id) {\n var target = $(id),\n inst = this._getInst(target[0]),\n today = new Date(),\n date = this._formatDate(inst, today.getDate(), today.getMonth(), today.getFullYear());\n this._originalGotoToday(id);\n this._selectDate(id, date);\n },\n\n // Reference the orignal function so we can override it and call it later\n _inlineDatepicker2: $.datepicker._inlineDatepicker,\n\n // Override the _inlineDatepicker method\n _inlineDatepicker: function (target, inst) {\n\n // Call the original\n this._inlineDatepicker2(target, inst);\n\n var beforeShow = $.datepicker._get(inst, 'beforeShow');\n\n if (beforeShow) {\n beforeShow.apply(target, [target, inst]);\n }\n },\n _checkOffsetOriginal: $.datepicker._checkOffset,\n\n _checkOffset: function(inst, offset, isFixed) {\n var _offset = $.datepicker._checkOffsetOriginal(inst, offset, isFixed);\n var alterOffset = this._get(inst, 'alterOffset');\n if (alterOffset) {\n var inp = inst.input ? inst.input[0] : null;\n // trigger custom callback\n return alterOffset.apply(inp, [_offset]);\n }\n return _offset;\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// ++\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 \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\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-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\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 = { collapsed: {}, ...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-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 {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 }\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 { TimeEntryDmService } from \"core-app/modules/hal/dm-services/time-entry-dm.service\";\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';\n\n@Injectable()\nexport class TimeEntryCreateService {\n\n constructor(readonly opModalService:OpModalService,\n readonly injector:Injector,\n readonly halResource:HalResourceService,\n readonly timeEntryDm:TimeEntryDmService,\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, { entry: changeset.pristineResource, 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\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.timeEntryDm.createForm(payload).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'] = form.schema;\n entry.overriddenSchema = form.schema;\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.timeEntryDm.create(payload);\n };\n\n entry.state.putValue(entry);\n\n return entry;\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\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 visble 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","// -- 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\nimport {Component} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {BcfPathHelperService} from \"core-app/modules/bim/bcf/helper/bcf-path-helper.service\";\n\n@Component({\n template: `\n \n \n {{text.import}} \n \n `,\n selector: 'bcf-import-button',\n})\nexport class BcfImportButtonComponent {\n public text = {\n import: this.I18n.t('js.bcf.import')\n };\n\n constructor(readonly I18n:I18nService,\n readonly currentProject:CurrentProjectService,\n readonly bcfPathHelper:BcfPathHelperService) {\n }\n\n public handleClick() {\n var projectIdentifier = this.currentProject.identifier;\n if (projectIdentifier) {\n var url = this.bcfPathHelper.projectImportIssuePath(projectIdentifier);\n window.location.href = url;\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 { WorkPackageCacheService } from 'core-app/components/work-packages/work-package-cache.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\n @InjectField() workPackageCacheService:WorkPackageCacheService;\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 entry() {\n return this.locals.entry;\n }\n\n public get showWorkPackageField() {\n return this.locals.showWorkPackageField !== undefined ? this.locals.showWorkPackageField : true;\n }\n\n public saveEntry() {\n this.editForm.save()\n .then(() => {\n // reload workPackage\n if (this.entry.workPackage) {\n this.workPackageCacheService.require(this.entry.workPackage.id, true);\n }\n this.service.close();\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","//-- 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\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 name: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","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 {BoardCacheService} from \"core-app/modules/boards/board/board-cache.service\";\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\";\n\nexport const boardsMenuSelector = 'boards-menu';\n\n@Component({\n selector: boardsMenuSelector,\n templateUrl: './boards-menu.component.html'\n})\n\nexport class BoardsMenuComponent implements OnInit {\n trackById = AngularTrackingHelpers.compareByAttribute('id');\n\n currentProjectIdentifier = this.currentProject.identifier;\n\n public boards$:Observable = this.boardCache.observeAll().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 boardCache:BoardCacheService,\n private readonly currentProject:CurrentProjectService,\n private readonly mainMenuService:MainMenuNavigationService) {\n }\n\n ngOnInit() {\n // When activating the work packages 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\n private focusBackArrow() {\n let buttonArrowLeft = jQuery('*[data-name=\"board_view\"] .main-menu--arrow-left-to-project');\n buttonArrowLeft.focus();\n }\n}\n","
    \n
      \n
    • \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 {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 {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 if (currentValues === undefined) {\n this.selectedAttributes = this.availableInlineHighlightedAttributes;\n } else {\n this.selectedAttributes = currentValues;\n }\n }\n}\n","
    \n \n \n
    \n

    \n
    \n \n \n
    \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-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 {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 {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.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\";\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 wpCacheService:WorkPackageCacheService,\n readonly cdRef:ChangeDetectorRef,\n readonly pathHelper:PathHelperService) {\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.wpCacheService.loadWorkPackage(this.workPackageId)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.loadCurrentWatchers();\n });\n\n this.availableWatchersPath = this.pathHelper.api.v3.work_packages.id(this.workPackageId).available_watchers;\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.wpCacheService.loadWorkPackage(this.workPackage.id!, true);\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.wpCacheService.loadWorkPackage(this.workPackage.id!, true);\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-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 {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 {WorkPackageCacheService} from '../work-packages/work-package-cache.service';\nimport {WorkPackageCreateService} from './wp-create.service';\nimport {takeWhile} from 'rxjs/operators';\nimport {RootDmService} from 'core-app/modules/hal/dm-services/root-dm.service';\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\";\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 wpCacheService:WorkPackageCacheService,\n protected readonly pathHelper:PathHelperService,\n protected readonly cdRef:ChangeDetectorRef,\n protected readonly RootDm:RootDmService) {\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.pathHelper.api.v3.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.wpCacheService.loadWorkPackage(this.stateParams['parent_id'])\n .values$()\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.RootDm.load().then((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 const type = this.stateParams.type ? parseInt(this.stateParams.type) : undefined;\n const project = this.stateParams.projectPath;\n\n return this.wpCreate.createOrContinueWorkPackage(project, type);\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-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, OnDestroy, OnInit, Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {BcfPathHelperService} from \"core-app/modules/bim/bcf/helper/bcf-path-helper.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\nimport {StateService} from \"@uirouter/core\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {WpTableExportModal} from \"core-components/modals/export-modal/wp-table-export.modal\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\n\n@Component({\n template: `\n \n \n {{text.export}} \n \n `,\n selector: 'bcf-export-button',\n})\nexport class BcfExportButtonComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n public text = {\n export: this.I18n.t('js.bcf.export')\n };\n public query:QueryResource;\n public exportLink:string;\n\n constructor(readonly I18n:I18nService,\n readonly currentProject:CurrentProjectService,\n readonly bcfPathHelper:BcfPathHelperService,\n readonly querySpace:IsolatedQuerySpace,\n readonly queryUrlParamsHelper:UrlParamsHelperService,\n readonly opModalService:OpModalService,\n readonly injector:Injector,\n readonly state:StateService) {\n super();\n }\n\n ngOnInit() {\n this.querySpace.query\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((query) => {\n this.query = query;\n\n let projectIdentifier = this.currentProject.identifier;\n let filters = this.queryUrlParamsHelper.buildV3GetFilters(this.query.filters);\n this.exportLink = this.bcfPathHelper.projectExportIssuesPath(\n projectIdentifier!,\n JSON.stringify(filters)\n );\n });\n }\n\n public showDelayedExport(event:any) {\n this.opModalService.show(WpTableExportModal, this.injector, { link: this.exportLink });\n event.preventDefault();\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\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-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 {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 {HelpTextDmService} from \"../hal/dm-services/help-text-dm.service\";\nimport {AttributeHelpTextsService} from \"../common/help-texts/attribute-help-text.service\";\nimport {AttributeHelpTextModal} from \"../common/help-texts/attribute-help-text.modal\";\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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\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\";\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 helpTextDm: this.injector.get(HelpTextDmService),\n attributeHelpTexts: this.injector.get(AttributeHelpTextsService),\n displayField: this.injector.get(DisplayFieldService),\n editField: this.injector.get(EditFieldService),\n wpCache: this.injector.get(WorkPackageCacheService),\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 };\n\n // Random collection of classes needed outside of angular\n public readonly classes = {\n modals: {\n passwordConfirmation: PasswordConfirmationModal,\n attributeHelpTexts: AttributeHelpTextModal,\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-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// ++ 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","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-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 {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-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\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\n\ninterface ICostsByType {\n costObjectId:string;\n costType:{\n name:string;\n };\n staticPath:{\n href:string;\n };\n spentUnits:number;\n}\n\nexport class CostsByTypeDisplayField extends DisplayField {\n\n public wpCacheService:any;\n\n public apply(resource:any, schema:IFieldSchema) {\n super.apply(resource, schema);\n this.wpCacheService = this.injector.get(WorkPackageCacheService);\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.wpCacheService.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 + '?cost_type_id=' + val.costObjectId;\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\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-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 {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 {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-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 {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 container.append(row);\n rowIndex += 1;\n\n container.find('.costs-date-picker').datepicker();\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-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\nexport class PlannedCostsFormAugment {\n\n public obj:JQuery;\n public objId:string;\n public objName: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\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\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-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 {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('#cost_object_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 {CostsByTypeDisplayField} from './wp-display/costs-by-type-display-field.module';\nimport {CurrencyDisplayField} from './wp-display/currency-display-field.module';\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/openproject-costs/augment/planned-costs-form\";\nimport {CostBudgetSubformAugmentService} from \"core-app/modules/plugins/linked/openproject-costs/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 displayFieldService.addFieldType(CostsByTypeDisplayField, 'costs', ['costsByType']);\n displayFieldService.addFieldType(CurrencyDisplayField, 'currency', ['laborCosts', 'materialCosts', 'overallCosts']);\n\n let halResourceService = pluginContext.services.halResource;\n halResourceService.registerResource('Budget', {cls: BudgetResource});\n\n pluginContext.hooks.workPackageSingleContextMenu(function (params:any) {\n return {\n key: 'log_costs',\n icon: 'icon-projects',\n indexBy: function (actions:any) {\n var 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 var 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 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 Documents Plugin\n//\n// Former OpenProject Core functionality extracted into a plugin.\n//\n// Copyright (C) 2009-2014 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// # Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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 Documents Plugin\n//\n// Former OpenProject Core functionality extracted into a plugin.\n//\n// Copyright (C) 2009-2014 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// # Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 OpenprojectAvatars} from './linked/openproject-avatars/main';\nimport {PluginModule as OpenprojectCosts} from './linked/openproject-costs/main';\nimport {PluginModule as OpenprojectDocuments} from './linked/openproject-documents/main';\n\n@NgModule({\n imports: [\n OpenprojectAvatars,\n OpenprojectCosts,\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 {GridDmService} from \"core-app/modules/hal/dm-services/grid-dm.service\";\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';\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 gridDm:GridDmService,\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().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 = this.gridDm.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 .gridDm\n .update(resource, schema)\n .then(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.gridDm.updateForm(this.resource)\n .then((form) => {\n this.schema = form.schema;\n });\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-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, 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","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-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 { 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-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 {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 {AfterViewInit, Component, ElementRef, Input, OnInit, SecurityContext, ViewChild} 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 {EventApi, EventInput} from '@fullcalendar/core';\nimport {EventSourceError} from '@fullcalendar/core/structs/event-source';\nimport {take} from 'rxjs/operators';\nimport {ToolbarInput} from '@fullcalendar/core/types/input-types';\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\ninterface CalendarViewEvent {\n el:HTMLElement;\n event:EventApi;\n jsEvent:MouseEvent;\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, AfterViewInit {\n @ViewChild(FullCalendarComponent) ucCalendar:FullCalendarComponent;\n @Input() projectIdentifier:string;\n @Input() static:boolean = false;\n static MAX_DISPLAYED = 100;\n\n public tooManyResultsText:string|null;\n\n public calendarPlugins = [dayGridPlugin];\n public calendarHeight:Function;\n public calendarEvents:Function;\n public calendarHeader:ToolbarInput|boolean;\n\n private alreadyLoaded = false;\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 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 // Clear any old subscribers\n this.querySpace.stopAllSubscriptions.next();\n\n this.setupWorkPackagesListener();\n\n this.initializeCalendar();\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('eventRender', (event:CalendarViewEvent) => {\n this.addTooltip(event);\n });\n this.ucCalendar.getApi().setOption('eventClick', (event:CalendarViewEvent) => {\n this.toWPFullView(event);\n });\n }\n\n public calendarEventsFunction(fetchInfo:{ start:Date, end:Date, timeZone:string },\n successCallback:(events:EventInput[]) => void,\n failureCallback:(error:EventSourceError) => 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.calendarEvents = this.calendarEventsFunction.bind(this);\n this.setCalendarHeight();\n this.setCalendarHeader();\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\n public get calendarEditable() {\n return false;\n }\n\n public get calendarEventLimit() {\n return false;\n }\n\n public get calendarLocale() {\n return this.i18n.locale;\n }\n\n public get calendarFixedWeekCount() {\n return false;\n }\n\n public get calendarDefaultView() {\n if (this.static) {\n return 'dayGridWeek';\n } else {\n return null;\n }\n }\n\n public get calendarFirstDay() {\n return this.configuration.startOfWeek();\n }\n\n private get calendarElement() {\n return jQuery(this.element.nativeElement).find('.fc-view-container');\n }\n\n private setCalendarHeight() {\n if (this.static) {\n this.calendarHeight = () => {\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 };\n } else {\n this.calendarHeight = () => {\n // -12 for the bottom padding\n return jQuery(window).height()! - this.calendarElement.offset()!.top - 12;\n };\n }\n }\n\n public setCalendarHeader() {\n if (this.static) {\n this.calendarHeader = false;\n } else {\n this.calendarHeader = {\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 (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-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, 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","// -- copyright\n// OpenProject is a project management system.\n// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See doc/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {MultiInputState} from 'reactivestates';\nimport {States} from '../states.service';\nimport {StateCacheService} from '../states/state-cache.service';\nimport {Injectable} from '@angular/core';\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {TimeEntryDmService} from \"core-app/modules/hal/dm-services/time-entry-dm.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class TimeEntryCacheService extends StateCacheService {\n\n constructor(readonly states:States,\n readonly schemaCacheService:SchemaCacheService,\n readonly timeEntryDm:TimeEntryDmService) {\n super();\n }\n\n protected loadAll(ids:string[]):Promise {\n return Promise\n .all(ids.map(id => this.load(id)))\n .then(_ => undefined);\n }\n\n updateValue(id:string, val:TimeEntryResource) {\n this.schemaCacheService.ensureLoaded(val).then(() => {\n super.updateValue(id, val);\n });\n }\n\n protected load(id:string):Promise {\n return this\n .timeEntryDm\n .one(parseInt(id))\n .then((timeEntry) => {\n return this.schemaCacheService.ensureLoaded(timeEntry).then(() => timeEntry);\n });\n }\n\n protected get multiState():MultiInputState {\n return this.states.timeEntries;\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 \"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 }\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\";\n\n@Injectable()\nexport class TimeEntryEditService {\n\n constructor(readonly opModalService:OpModalService,\n readonly injector:Injector,\n readonly halResource:HalResourceService,\n readonly i18n:I18nService) {\n }\n\n public edit(entry:TimeEntryResource) {\n return new Promise<{entry:TimeEntryResource, action:'update'|'destroy'}>((resolve, reject) => {\n const modal = this.opModalService.show(TimeEntryEditModal, this.injector, { entry: entry });\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
    \n\n \n\n \n \n
    \n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n EventEmitter,\n Injector,\n Input,\n OnInit,\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 {Duration, EventApi, EventInput, View} from '@fullcalendar/core';\nimport {EventSourceError} from '@fullcalendar/core/structs/event-source';\nimport {ToolbarInput} from '@fullcalendar/core/types/input-types';\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\nimport {TimeEntryDmService} from \"core-app/modules/hal/dm-services/time-entry-dm.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 {TimeEntryCacheService} from \"core-components/time-entries/time-entry-cache.service\";\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';\n\ninterface CalendarViewEvent {\n el:HTMLElement;\n event:EventApi;\n jsEvent:MouseEvent;\n}\n\ninterface CalendarMoveEvent {\n el:HTMLElement;\n event:EventApi;\n oldEvent:EventApi;\n delta:Duration;\n revert:() => void;\n jsEvent:Event;\n view:View;\n}\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 OnInit, AfterViewInit {\n @ViewChild(FullCalendarComponent) ucCalendar:FullCalendarComponent;\n @Input() projectIdentifier:string;\n @Input() static:boolean = false;\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 calendarPlugins = [timeGrid, interactionPlugin];\n public calendarEvents:Function;\n public calendarHeader:ToolbarInput|boolean = {\n right: '',\n center: 'title',\n left: 'prev,next today'\n };\n public calendarSlotLabelFormat = (info:any) => (this.maxHour - info.date.hour) / this.scaleRatio;\n public calendarSlotLabelInterval = `${this.labelIntervalHours}:00:00`;\n public calendarContentHeight = 605;\n public calendarAllDaySlot = false;\n public calendarDisplayEventTime = false;\n public calendarSlotEventOverlap = false;\n public calendarEditable = false;\n public calendarMinTime = `${this.minHour - 1}:00:00`;\n public calendarMaxTime = `${this.maxHour}:00:00`;\n public calendarEventOverlap = (stillEvent:any) => !stillEvent.classNames.includes(TIME_ENTRY_CLASS_NAME);\n\n protected memoizedTimeEntries:{ start:Date, end:Date, entries:Promise> };\n public memoizedCreateAllowed:boolean = false;\n\n public text = {\n logTime: this.i18n.t('js.button_log_time')\n };\n\n constructor(readonly states:States,\n readonly timeEntryDm:TimeEntryDmService,\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 timeEntryCache:TimeEntryCacheService,\n private colors:ColorsService,\n private browserDetector:BrowserDetector) {\n }\n\n ngOnInit() {\n this.initializeCalendar();\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('eventRender', (event:CalendarViewEvent) => {\n this.alterEventEntry(event);\n });\n this.ucCalendar.getApi().setOption('eventDestroy', (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:EventSourceError) => 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 .timeEntryDm\n .list({ filters: this.dmFilters(start, end), pageSize: 500 })\n .then(collection => {\n this.memoizedCreateAllowed = !!collection.createTimeEntry;\n\n collection.elements.forEach(timeEntry => this.timeEntryCache.updateValue(timeEntry.id!, timeEntry));\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 return (this.maxHour - info.date.hour) / this.scaleRatio;\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 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 initializeCalendar() {\n this.calendarEvents = this.calendarEventsFunction.bind(this);\n }\n\n public get calendarEventLimit() {\n return false;\n }\n\n public get calendarLocale() {\n return this.i18n.locale;\n }\n\n public get calendarFixedWeekCount() {\n return false;\n }\n\n public get calendarDefaultView() {\n return 'timeGridWeek';\n }\n\n public get calendarFirstDay() {\n return this.configuration.startOfWeek();\n }\n\n private get calendarElement() {\n return jQuery(this.element.nativeElement).find('.fc-view-container');\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 .timeEntryDm\n .update(entry, entry.schema)\n .then(event => {\n this.updateEventSet(event, 'update');\n })\n .catch((e) => {\n this.notifications.handleRawError(e);\n event.revert();\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.timeEntryCache.updateValue(event.id!, event);\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.append(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 formattedDuration = this.timezone.formattedDuration(event.event.extendedProps.entry.hours);\n\n jQuery(event.el)\n .find('.fc-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","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\";\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\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 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 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-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, 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-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 {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\";\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-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 {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\";\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 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.pathHelper.api.v3.apiV3Base}/documents?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 { NewsDmService } from \"core-app/modules/hal/dm-services/news-dm.service\";\nimport { CurrentProjectService } from \"core-components/projects/current-project.service\";\nimport { DmListParameter } from \"core-app/modules/hal/dm-services/dm.service.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 newsDm:NewsDmService,\n readonly currentProject:CurrentProjectService,\n readonly cdr:ChangeDetectorRef\n ) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.newsDm\n .list(this.newsDmParams)\n .then(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:DmListParameter = {\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 {GridDmService} from \"core-app/modules/hal/dm-services/grid-dm.service\";\n\n@Injectable()\nexport class GridInitializationService {\n constructor(readonly gridDm:GridDmService,\n readonly halResourceService:HalResourceService) {}\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 .gridDm\n .list({ filters: [['scope', '=', [path]]] })\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 return new Promise((resolve, reject) => {\n let payload = {\n '_links': {\n 'scope': {\n 'href': path\n }\n }\n };\n\n this\n .gridDm\n .createForm(payload)\n .then((form) => {\n let source = form.payload.$source;\n\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 this.gridDm.create(resource, form.schema)\n .then((resource) => {\n resolve(resource);\n })\n .catch(() => {\n reject();\n });\n });\n });\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 {QueryFormDmService} from \"core-app/modules/hal/dm-services/query-form-dm.service\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {QueryDmService} from \"core-app/modules/hal/dm-services/query-dm.service\";\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\";\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 queryFormDm:QueryFormDmService,\n protected readonly queryDm:QueryDmService,\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.queryFormDm\n .loadWithParams(\n {pageSize: 0},\n undefined,\n this.currentProject.identifier,\n WpGraphConfiguration.queryCreationParams(this.I18n, !!this.currentProject.identifier)\n )\n .then(form => {\n const query = this.queryFormDm.buildQueryResource(form);\n\n return this.queryDm.create(query, form);\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.queryDm\n .find(\n Object.assign({pageSize: 0}, params.props),\n params.id,\n this.currentProject.identifier,\n )\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 .queryDm\n .update(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.queryFormDm\n .load(query)\n .then((form:QueryFormResource) => {\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-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 { 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-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 {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 let chartTypeDefaults:ChartOptions = {};\n\n if (this.chartType === 'horizontalBar') {\n chartTypeDefaults = {\n scales: {\n xAxes: [{\n stacked: true,\n ticks: {\n callback: (value:number) => {\n if (Math.floor(value) === value) {\n return value;\n } else {\n return 0;\n }\n }\n }\n }],\n yAxes:\n [{\n stacked: true\n }]\n }\n };\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","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-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 {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 {QueryFormDmService} from \"core-app/modules/hal/dm-services/query-form-dm.service\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\nimport {QueryDmService} from \"core-app/modules/hal/dm-services/query-dm.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {StateService} from '@uirouter/core';\nimport {skip} from 'rxjs/operators';\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 queryDm:QueryDmService,\n protected readonly querySpace:IsolatedQuerySpace,\n protected readonly queryFormDm:QueryFormDmService) {\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);\n } else {\n this.queryFormDm.load(query).then((form) => {\n this.queryForm = form;\n this.saveQuery(query);\n });\n }\n }\n\n private saveQuery(query:QueryResource) {\n this.inFlight = true;\n\n this\n .queryDm\n .update(query, this.queryForm)\n .toPromise()\n .then((query) => {\n this.inFlight = false;\n return query;\n })\n .catch(() => this.inFlight = false);\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.queryFormDm\n .loadWithParams(\n queryProps,\n undefined,\n projectIdentifier,\n this.queryCreationParams()\n )\n .then(form => {\n const query = this.queryFormDm.buildQueryResource(form);\n\n return this.queryDm.create(query, form).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","\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-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 {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","// -- 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\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 {ProjectCacheService} from \"core-components/projects/project-cache.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\";\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 projectCache:ProjectCacheService,\n protected readonly currentProject:CurrentProjectService,\n protected readonly cdRef:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.project$ = this.projectCache.requireAndStream(this.currentProject.id!);\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-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, 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 {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\n\nexport class CustomTextChangeset extends ResourceChangeset<{ [key:string]:unknown; }> {\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 {CustomTextChangeset} from \"core-app/modules/grids/widgets/custom-text/custom-text-changeset\";\nimport {UploadFile} from \"core-components/api/op-file-upload/op-file-upload.service\";\n\n@Injectable()\nexport class CustomTextEditFieldService extends EditFieldHandler {\n public fieldName = 'text';\n public inEdit = false;\n public inEditMode = false;\n public inFlight = false;\n\n public valueChanged$:BehaviorSubject;\n\n public changeset:CustomTextChangeset;\n\n constructor(protected elementRef:ElementRef,\n protected injector:Injector) {\n super();\n }\n\n errorMessageOnLabel:string;\n\n onFocusOut():void {\n // interface\n }\n\n public initialize(value:GridWidgetResource) {\n this.changeset = new CustomTextChangeset(this.newEditResource(value));\n this.valueChanged$ = new BehaviorSubject(value.options['text'] as string);\n }\n\n public reinitialize(value:GridWidgetResource) {\n this.changeset = new CustomTextChangeset(this.newEditResource(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('text', { 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('text');\n }\n\n public handleUserCancel() {\n this.deactivate();\n }\n\n public get active() {\n return this.inEdit;\n }\n\n public activate(withText?:string) {\n this.inEdit = true;\n }\n\n deactivate():void {\n this.changeset.clear();\n this.inEdit = false;\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 private newEditResource(value:GridWidgetResource) {\n return { text: value.options.text,\n getEditorTypeFor: () => 'full',\n canAddAttachments: value.grid.canAddAttachments,\n uploadAttachments: (files:UploadFile[]) => value.grid.uploadAttachments(files) };\n }\n}\n","\n\n \n \n\n\n\n \n \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 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';\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 readonly sanitization:DomSanitizer,\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\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","// -- 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\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 {ProjectDmService} from \"core-app/modules/hal/dm-services/project-dm.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {ProjectCacheService} from \"core-components/projects/project-cache.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\";\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 projectDm:ProjectDmService,\n protected readonly projectCache:ProjectCacheService,\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.projectCache.requireAndStream(this.currentProject.id!);\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.projectDm.schema();\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} 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 {TimeEntryDmService} from \"core-app/modules/hal/dm-services/time-entry-dm.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 {TimeEntryCacheService} from \"core-components/time-entries/time-entry-cache.service\";\n\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 timeEntryCache:TimeEntryCacheService;\n\n constructor(readonly timeEntryDm:TimeEntryDmService,\n 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.timeEntryDm.list({ filters: this.dmFilters(), pageSize: 500 })\n .then((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.timeEntryCache.require(entry.id!).then((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","\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 {TimeEntryDmService} from \"core-app/modules/hal/dm-services/time-entry-dm.service\";\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 timeEntryDm:TimeEntryDmService,\n 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(timeEntryDm, 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 {DmListParameter} from \"core-app/modules/hal/dm-services/dm.service.interface\";\nimport {ProjectDmService} from \"core-app/modules/hal/dm-services/project-dm.service\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\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 projectDm:ProjectDmService,\n readonly currentProject:CurrentProjectService,\n readonly cdr:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this\n .projectDm\n .list(this.projectDmParams)\n .then((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 projectDmParams():DmListParameter {\n return { sortBy: [['name', 'asc']],\n filters: [['parent_id', '=', [this.currentProject.id!]]] };\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 \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 {DmListParameter} from \"core-app/modules/hal/dm-services/dm.service.interface\";\nimport {MembershipResource} from \"core-app/modules/hal/resources/membership-resource\";\nimport {MembershipDmService} from \"core-app/modules/hal/dm-services/membership-dm.service\";\nimport {RoleResource} from \"core-app/modules/hal/resources/role-resource\";\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 i18n:I18nService,\n protected readonly injector:Injector,\n readonly membershipDm:MembershipDmService,\n readonly currentProject:CurrentProjectService,\n readonly cdr:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.membershipDm\n .list(this.listMembersParams)\n .then(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.membershipDm\n .listAvailableProjects(this.listAvailableProjectsParams)\n .then(collection => {\n this.membersAddable = collection.total > 0;\n })\n .catch(() => {\n // nothing bad, the user is just not allowed to add members to the project\n\n });\n }\n\n public get isEditable() {\n return false;\n }\n\n public userPath(user:UserResource) {\n return this.pathHelper.userPath(user.id!);\n }\n\n public userName(user:UserResource) {\n return user.name;\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 public isGroup(principal:UserResource) {\n return this.pathHelper.api.v3.groups.id(principal.id!).toString() === principal.href;\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 this.userName(a).localeCompare(this.userName(b));\n });\n });\n }\n\n private get listMembersParams() {\n let params:DmListParameter = { sortBy: [['created_on', '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:DmListParameter = {};\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","// -- 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\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 {ProjectDmService} from \"core-app/modules/hal/dm-services/project-dm.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 {ProjectCacheService} from \"core-components/projects/project-cache.service\";\nimport {Observable} from \"rxjs\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.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 projectDm:ProjectDmService,\n protected readonly projectCache:ProjectCacheService,\n protected readonly currentProject:CurrentProjectService,\n protected readonly cdRef:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.project$ = this.projectCache.requireAndStream(this.currentProject.id!);\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-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 {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\";\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\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 }\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-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\";\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-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 {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\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 if (wpBase === null) {\n\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 const source = transition.options().source;\n\n // Get the current path and compare\n const path = window.location.pathname;\n const target = stateService.href(toState, toParams);\n\n if (target && path !== 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-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 {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-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 {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-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 {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-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 {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-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 {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 {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 {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} 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\";\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';\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 {\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:Drake;\n private groupsDrake:Drake;\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.dragula.createGroup('groups', {\n moves: (el, source, handle:HTMLElement) => handle.classList.contains('group-handle')\n });\n\n // Setup attributes\n this.dragula.createGroup('attributes', {\n moves: (el, source, handle:HTMLElement) => handle.classList.contains('attribute-handle')\n });\n\n this.dragula.dropModel(\"attributes\")\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((event) => {\n console.log(event);\n });\n\n // Get attribute id\n this.groups = JSON.parse(this.element.dataset.activeGroups!);\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 return this.down && (groups || attributes);\n }\n });\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 JSON.parse(group.query),\n (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 private updateHiddenFields() {\n const hiddenField = this.form.find('.admin-type-form--hidden-field');\n hiddenField.val(JSON.stringify(this.groups));\n }\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//++\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-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 {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\";\n\n@NgModule({\n imports: [\n DragulaModule.forRoot(),\n OpenprojectCommonModule\n ],\n providers: [\n ],\n declarations: [\n TypeFormAttributeGroupComponent,\n TypeFormQueryGroupComponent,\n TypeFormConfigurationComponent,\n GroupEditInPlaceComponent\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-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 {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-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 {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 {WorkPackageCacheService} from \"core-components/work-packages/work-package-cache.service\";\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 wpCacheService:WorkPackageCacheService,\n readonly opModalService:OpModalService) {\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.wpCacheService.require(workPackageId)\n .then((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","// -- 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\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-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 {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-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 {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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 'g t': this.projectScoped('projectTimelinesPath'),\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","// -- 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\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-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 {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-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 {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\";\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\n {{ text.learnAbout }}\n `,\n selector: homescreenNewFeaturesBlockSelector,\n styleUrls: ['./new-features.component.sass'],\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\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","// -- 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\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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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-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// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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-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, 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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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-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 {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-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, 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","// -- copyright\n// OpenProject is a project management system.\n// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See doc/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),\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-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-2017 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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-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 {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-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 {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","// -- 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\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 {CollectionResource} from \"core-app/modules/hal/resources/collection-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 {map, tap, take, filter} from \"rxjs/internal/operators\";\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\";\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}\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 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:JQuery.TriggeredEvent) {\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.fetchSearchResults(hashFreeQuery, hashFreeQuery !== query)\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 let href:string = this.PathHelperService.api.v3.wpBySubjectOrId(query, idOnly);\n\n return this.halResourceService\n .get>(href);\n\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 } 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-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\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-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 {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-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, 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 jQuery('#' + selector).html(val);\n });\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 {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-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, 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-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 {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\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\";\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\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 return { name: el.name, id: el.id, href: el.id };\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.api.v3.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.api.v3.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.appBasePath + '/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-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, 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})\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-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 {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-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 {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-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, 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-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 {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 a project management system.\n// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See doc/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-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, 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 {TimeEntryCacheService} from \"core-components/time-entries/time-entry-cache.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {TimeEntryDmService} from \"core-app/modules/hal/dm-services/time-entry-dm.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\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})\nexport class TriggerActionsEntryComponent {\n @InjectField() readonly timeEntryEditService:TimeEntryEditService;\n @InjectField() readonly timeEntryCache:TimeEntryCacheService;\n @InjectField() readonly timeEntryDmService:TimeEntryDmService;\n @InjectField() readonly notificationsService:NotificationsService;\n @InjectField() readonly elementRef:ElementRef;\n @InjectField() readonly 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.timeEntryDmService\n .delete(entry)\n .then(() => {\n window.location.reload();\n })\n .catch((error) => {\n this.notificationsService.addError(error || this.text.error);\n });\n });\n }\n\n protected loadEntry() {\n let timeEntryId = this.elementRef.nativeElement.dataset['entry'];\n\n return this.timeEntryCache\n .require(timeEntryId);\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 {\n AttributeHelpTextComponent,\n attributeHelpTextSelector\n} from \"core-app/modules/common/help-texts/attribute-help-text.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\";\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];\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// ++\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-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 {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-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 {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 {LinkedPluginsModule} from \"core-app/modules/plugins/linked-plugins.module\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {ModalWrapperAugmentService} from \"core-app/globals/augmenting/modal-wrapper.augment.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\";\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 providers: [\n { provide: States, useValue: new States() },\n { provide: APP_INITIALIZER, useFactory: initializeServices, deps: [Injector], multi: true },\n PaginationService,\n OpenProjectFileUploadService,\n // Split view\n CommentService,\n ConfirmDialogService,\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 ExternalQueryConfiguration = injector.get(ExternalQueryConfigurationService);\n const ExternalRelationQueryConfiguration = injector.get(ExternalRelationQueryConfigurationService);\n const ModalWrapper = injector.get(ModalWrapperAugmentService);\n const PreviewTrigger = injector.get(PreviewTriggerService);\n const mainMenuNavigationService = injector.get(MainMenuNavigationService);\n const keyboardShortcuts = injector.get(KeyboardShortcutService);\n\n mainMenuNavigationService.register();\n\n // Setup modal wrapping\n ModalWrapper.setupListener();\n\n PreviewTrigger.setupListener();\n\n keyboardShortcuts.register();\n\n // Setup query configuration listener\n ExternalQueryConfiguration.setupListener();\n ExternalRelationQueryConfiguration.setupListener();\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\";\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('./app/init-globals');\n\nconst meta = jQuery('meta[name=openproject_initializer]');\nI18n.locale = meta.data('defaultLocale');\nI18n.locale = meta.data('locale');\nI18n.firstDayOfWeek = parseInt(meta.data('firstDayOfWeek'), 10);\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\njQuery(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","// -- 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\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-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 {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\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 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:///"}