{"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/globals/global-listeners/top-menu.ts","./src/app/modules/work_packages/routing/split-view-routes.template.ts","./src/app/modules/bim/bcf/helper/bcf-path-helper.service.ts","./src/locales lazy ^\\.\\/.*\\.js$ namespace object","./src/app/components/wp-fast-table/builders/relation-cell-builder.ts","./src/app/components/wp-activity/activity-link.component.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/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service.ts","./src/app/components/wp-query/query-filters.service.ts","./src/app/components/op-context-menu/handlers/wp-create-settings-menu.directive.ts","./src/app/modules/work_packages/routing/split-view-routes.helper.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service.ts","./src/app/components/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/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/rows-builder.ts","./src/app/components/wp-fast-table/builders/modes/grouped/group-header-builder.ts","./src/app/components/wp-fast-table/builders/relations/relation-row-builder.ts","./src/app/components/wp-fast-table/builders/relations/relations-render-pass.ts","./src/app/components/wp-fast-table/builders/timeline/timeline-render-pass.ts","./src/app/components/wp-fast-table/builders/highlighting/row-highlight-render-pass.ts","./src/app/components/wp-fast-table/builders/drag-and-drop/drag-drop-handle-builder.ts","./src/app/components/wp-fast-table/builders/drag-and-drop/drag-drop-handle-render-pass.ts","./src/app/components/wp-fast-table/builders/primary-render-pass.ts","./src/app/components/wp-fast-table/builders/modes/plain/plain-render-pass.ts","./src/app/components/wp-fast-table/builders/modes/grouped/grouped-render-pass.ts","./src/app/components/wp-fast-table/builders/modes/grouped/grouped-rows-builder.ts","./src/app/components/wp-fast-table/builders/modes/hierarchy/hierarchy-render-pass.ts","./src/app/components/wp-fast-table/builders/modes/hierarchy/hierarchy-rows-builder.ts","./src/app/components/wp-fast-table/builders/modes/plain/plain-rows-builder.ts","./src/app/components/wp-edit-form/table-edit-form.ts","./src/app/components/wp-fast-table/wp-table-editing.ts","./src/app/components/wp-fast-table/wp-fast-table.ts","./src/app/modules/common/ckeditor/ckeditor-setup.service.ts","./src/app/modules/fields/edit/edit-field.service.ts","./src/app/components/wp-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/modules/fields/display/field-types/highlightable-display-field.module.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-fast-table/builders/table-action-renderer.ts","./src/app/components/wp-fast-table/builders/rows/single-row-builder.ts","./src/app/components/wp-inline-create/inline-create-row-builder.ts","./src/app/components/wp-inline-create/wp-inline-create.component.html","./src/app/components/wp-inline-create/wp-inline-create.component.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service.ts","./src/app/components/filters/query-filters/query-filters.component.ts","./src/app/components/filters/query-filters/query-filters.component.html","./src/app/modules/fields/edit/services/global-edit-form-changes-tracker/global-edit-form-changes-tracker.service.ts","./src/app/modules/fields/edit/edit-form/edit-form.component.ts","./src/app/components/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/hal/schemas/work-package-schema-proxy.ts","./src/app/modules/common/focus/focus-helper.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy-indentation.service.ts","./src/app/components/work-packages/wp-watcher-button/wp-watcher-button.component.ts","./src/app/components/work-packages/wp-watcher-button/wp-watcher-button.html","./src/app/helpers/selection-helpers.ts","./src/app/modules/fields/edit/field/editable-attribute-field.component.ts","./src/app/modules/fields/edit/field/editable-attribute-field.component.html","./src/app/components/wp-buttons/wp-fold-toggle-button/wp-fold-toggle-button.component.ts","./src/app/components/wp-card-view/services/wp-card-drag-and-drop.service.ts","./src/app/helpers/dom/set-window-cursor.helper.ts","./src/app/modules/hal/resources/type-resource.ts","./src/app/modules/hal/resources/wp-collection-resource.ts","./src/app/modules/hal/resources/form-resource.ts","./src/app/modules/hal/resources/root-resource.ts","./src/app/modules/hal/resources/query-operator-resource.ts","./src/app/modules/hal/resources/help-text-resource.ts","./src/app/modules/hal/resources/wiki-page-resource.ts","./src/app/modules/hal/resources/meeting-content-resource.ts","./src/app/modules/hal/resources/post-resource.ts","./src/app/modules/hal/resources/time-entry-resource.ts","./src/app/modules/hal/resources/news-resource.ts","./src/app/modules/hal/resources/membership-resource.ts","./src/app/modules/hal/resources/role-resource.ts","./src/app/modules/hal/resources/project-resource.ts","./src/app/modules/hal/resources/group-resource.ts","./src/app/modules/hal/services/hal-resource.config.ts","./src/app/modules/hal/services/hal-aware-error-handler.ts","./src/app/modules/hal/openproject-hal.module.ts","./src/app/components/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/modules/fields/field.service.ts","./src/app/modules/common/config/configuration.service.ts","./src/app/components/op-context-menu/op-context-menu-handler.ts","./src/app/modules/common/drag-and-drop/drag-and-drop.helpers.ts","./src/app/components/wp-fast-table/builders/timeline/timeline-row-builder.ts","./src/app/components/work-packages/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/apiv3/endpoints/grids/apiv3-grid-paths.ts","./src/app/modules/apiv3/paths/apiv3-list-resource.interface.ts","./src/app/modules/apiv3/endpoints/grids/apiv3-grids-paths.ts","./src/app/modules/apiv3/cache/cachable-apiv3-resource.ts","./src/app/modules/apiv3/endpoints/time-entries/apiv3-time-entry-paths.ts","./src/app/modules/apiv3/cache/cachable-apiv3-collection.ts","./src/app/modules/apiv3/endpoints/time-entries/time-entry-cache.service.ts","./src/app/modules/apiv3/endpoints/time-entries/apiv3-time-entries-paths.ts","./src/app/modules/apiv3/endpoints/projects/apiv3-available-projects-paths.ts","./src/app/modules/apiv3/endpoints/memberships/apiv3-memberships-paths.ts","./src/app/modules/apiv3/endpoints/users/apiv3-user-paths.ts","./src/app/modules/apiv3/endpoints/users/apiv3-users-paths.ts","./src/app/modules/apiv3/endpoints/types/apiv3-type-paths.ts","./src/app/modules/apiv3/endpoints/types/apiv3-types-paths.ts","./src/app/modules/apiv3/endpoints/queries/apiv3-query-order.ts","./src/app/modules/apiv3/endpoints/queries/apiv3-query-form.ts","./src/app/modules/apiv3/endpoints/queries/apiv3-query-paths.ts","./src/app/modules/apiv3/endpoints/queries/apiv3-queries-paths.ts","./src/app/modules/apiv3/endpoints/relations/apiv3-relations-paths.ts","./src/app/modules/apiv3/endpoints/work_packages/api-v3-work-package-paths.ts","./src/app/modules/apiv3/endpoints/work_packages/apiv3-work-package-form.ts","./src/app/modules/apiv3/endpoints/work_packages/work-package.cache.ts","./src/app/modules/apiv3/endpoints/work_packages/api-v3-work-package-cached-subresource.ts","./src/app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths.ts","./src/app/modules/apiv3/endpoints/versions/apiv3-version-paths.ts","./src/app/modules/apiv3/endpoints/versions/apiv3-versions-paths.ts","./src/app/modules/apiv3/endpoints/projects/apiv3-project-paths.ts","./src/app/modules/apiv3/endpoints/projects/project.cache.ts","./src/app/modules/apiv3/endpoints/projects/apiv3-projects-paths.ts","./src/app/modules/apiv3/endpoints/statuses/apiv3-status-paths.ts","./src/app/modules/apiv3/endpoints/statuses/apiv3-statuses-paths.ts","./src/app/modules/apiv3/endpoints/news/apiv3-news-paths.ts","./src/app/modules/apiv3/endpoints/help_texts/apiv3-help-texts-paths.ts","./src/app/modules/apiv3/endpoints/configuration/apiv3-configuration-path.ts","./src/app/modules/apiv3/virtual/apiv3-board-path.ts","./src/app/modules/apiv3/virtual/apiv3-boards-paths.ts","./src/app/modules/apiv3/api-v3.service.ts","./src/app/modules/common/editable-toolbar-title/editable-toolbar-title.html","./src/app/modules/common/editable-toolbar-title/editable-toolbar-title.component.ts","./src/app/components/wp-table/embedded/wp-embedded-table-entry.component.ts","./src/app/modules/grids/widgets/widget-changeset.ts","./src/app/modules/grids/widgets/abstract-widget.component.ts","./src/app/modules/common/gon/gon.service.ts","./src/app/modules/common/back-routing/back-button.component.ts","./src/app/modules/hal/resources/schema-resource.ts","./src/app/components/wp-list/wp-list.service.ts","./src/app/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/hal/resources/query-filter-instance-schema-resource.ts","./src/app/modules/projects/openproject-projects.module.ts","./src/app/modules/common/set-click-position/set-click-position.ts","./src/app/modules/fields/changeset/changeset.ts","./src/app/modules/fields/changeset/resource-changeset.ts","./src/app/modules/hal/schemas/hal-payload.helper.ts","./src/app/components/wp-table/configuration-modal/tab-portal-outlet.ts","./src/app/modules/work_packages/query-space/wp-isolated-query-space.directive.ts","./src/app/modules/hal/http/openproject-header-interceptor.ts","./src/app/modules/apiv3/cache/state-cache.service.ts","./src/app/modules/common/highlight-col/highlight-col.directive.ts","./src/app/modules/common/autocomplete/user-autocompleter.component.ts","./src/app/modules/common/autocomplete/user-autocompleter.component.html","./src/app/components/op-modals/op-modal.service.ts","./src/app/modules/fields/edit/field-handler/hal-resource-edit-field-handler.ts","./src/app/modules/fields/edit/editing-portal/editing-portal-service.ts","./src/app/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/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts","./src/app/modules/common/path-helper/path-helper.service.ts","./src/app/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/fields/display/field-types/multiple-lines-custom-options-display-field.module.ts","./src/app/modules/fields/display/field-types/progress-text-display-field.module.ts","./src/app/modules/fields/display/field-types/multiple-lines-user-display-field.module.ts","./src/app/modules/fields/display/display-field-renderer.ts","./src/app/modules/common/model-auth/model-auth.service.ts","./src/app/modules/hal/resources/mixins/attachable-mixin.ts","./src/app/modules/fields/field.base.ts","./src/app/components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.component.ts","./src/app/components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.html","./src/app/modules/hal/resources/hal-resource.ts","./src/app/modules/common/icon/op-icon.ts","./src/app/modules/hal/resources/relation-resource.ts","./src/app/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/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/common/op-date-picker/datepicker.ts","./src/app/modules/hal/resources/grid-widget-resource.ts","./src/app/modules/hal/services/hal-resource-notification.service.ts","./src/app/components/op-context-menu/handlers/op-context-menu-trigger.directive.ts","./src/app/modules/hal/helpers/lazy-accessor.ts","./src/app/modules/hal/helpers/hal-resource-builder.ts","./src/app/components/wp-single-view-tabs/keep-tab/keep-tab.service.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service.ts","./src/app/modules/common/colors/colors.service.ts","./src/app/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/modules/common/slide-toggle/slide-toggle.component.ts","./src/app/modules/common/slide-toggle/slide-toggle.component.html","./src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts","./src/app/components/wp-card-view/wp-single-card/wp-single-card.component.html","./src/app/modules/fields/edit/services/hal-resource-editing.service.ts","./src/app/globals/tree-menu.ts","./src/app/components/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/fields/display/field-types/combined-date-display.field.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/globals/onboarding/helpers.ts","./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/modals/wp-destroy-modal/wp-destroy.modal.ts","./src/app/components/modals/wp-destroy-modal/wp-destroy.modal.html","./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/components/wp-fast-table/handlers/cell/edit-cell-handler.ts","./src/app/components/wp-fast-table/handlers/cell/relations-cell-handler.ts","./src/app/components/op-context-menu/wp-context-menu/wp-table-context-menu.directive.ts","./src/app/components/wp-fast-table/handlers/context-menu/context-menu-handler.ts","./src/app/components/wp-fast-table/handlers/context-menu/context-menu-click-handler.ts","./src/app/components/wp-fast-table/handlers/context-menu/context-menu-keyboard-handler.ts","./src/app/components/wp-fast-table/handlers/context-menu/context-menu-rightclick-handler.ts","./src/app/components/wp-fast-table/handlers/row/click-handler.ts","./src/app/components/wp-fast-table/handlers/row/double-click-handler.ts","./src/app/components/wp-fast-table/handlers/row/group-row-handler.ts","./src/app/components/wp-fast-table/handlers/row/hierarchy-click-handler.ts","./src/app/components/wp-fast-table/handlers/row/wp-state-links-handler.ts","./src/app/components/wp-fast-table/handlers/state/columns-transformer.ts","./src/app/components/wp-fast-table/handlers/state/hierarchy-transformer.ts","./src/app/components/wp-fast-table/handlers/state/relations-transformer.ts","./src/app/components/wp-fast-table/handlers/state/rows-transformer.ts","./src/app/components/wp-fast-table/handlers/state/selection-transformer.ts","./src/app/components/wp-fast-table/handlers/state/timeline-transformer.ts","./src/app/components/wp-fast-table/handlers/state/highlighting-transformer.ts","./src/app/components/wp-fast-table/handlers/state/drag-and-drop-transformer.ts","./src/app/components/wp-fast-table/handlers/state/group-fold-transformer.ts","./src/app/components/wp-fast-table/handlers/table-handler-registry.ts","./src/app/components/wp-table/wp-table-hover-sync.ts","./src/app/components/wp-table/wp-table.directive.html","./src/app/components/wp-table/wp-table.component.ts","./src/app/modules/fields/edit/edit-field.component.ts","./src/app/components/wp-single-view-tabs/watchers-tab/wp-watchers.service.ts","./src/app/modules/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/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/modules/augmenting/dynamic-scripts lazy ^\\.\\/.*$ namespace object","./src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service.ts","./src/app/components/wp-fast-table/builders/modes/grouped/group-sums-builder.ts","./src/app/components/wp-form-group/wp-attribute-group.template.html","./src/app/components/wp-form-group/wp-attribute-group.component.ts","./src/app/components/wp-table/timeline/cells/wp-timeline-cell-mouse-handler.ts","./src/app/components/wp-table/timeline/cells/wp-timeline-cell.ts","./src/app/components/wp-table/timeline/cells/timeline-cell-renderer.ts","./src/app/components/wp-table/timeline/cells/timeline-milestone-cell-renderer.ts","./src/app/components/wp-table/timeline/cells/wp-timeline-cells-renderer.ts","./src/app/components/wp-table/timeline/container/wp-timeline-container.directive.ts","./src/app/components/wp-table/timeline/container/wp-timeline-container.html","./src/app/components/op-context-menu/handlers/op-columns-context-menu.directive.ts","./src/app/components/wp-table/timeline/header/wp-timeline-header.directive.ts","./src/app/components/wp-table/timeline/header/wp-timeline-header.html","./src/app/components/wp-table/timeline/global-elements/timeline-relation-element.ts","./src/app/components/wp-table/timeline/global-elements/wp-timeline-relations.directive.ts","./src/app/components/wp-table/timeline/global-elements/timeline-static-element.ts","./src/app/components/wp-table/timeline/global-elements/wp-timeline.today-line.ts","./src/app/components/wp-table/timeline/global-elements/wp-timeline-static-elements.directive.ts","./src/app/components/wp-table/timeline/grid/wp-timeline-grid.directive.ts","./src/app/components/wp-single-view-tabs/watchers-tab/wp-watcher-entry.component.ts","./src/app/components/wp-single-view-tabs/watchers-tab/wp-watcher-entry.html","./src/app/components/wp-table/wp-table-sums-row/wp-table-sums-row.directive.ts","./src/app/components/wp-relations/embedded/wp-relation-query.html","./src/app/components/wp-relations/embedded/relations/wp-relation-query.component.ts","./src/app/components/wp-table/config-menu/config-menu.component.ts","./src/app/components/wp-table/config-menu/config-menu.template.html","./src/app/components/time-entries/time-entry-changeset.ts","./src/app/modules/work_packages/openproject-work-packages.module.ts","./src/app/components/wp-list/wp-list-checksum.service.ts","./src/app/globals/global-listeners/action-menu.ts","./src/app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry.ts","./src/app/components/wp-card-view/services/wp-card-view.service.ts","./src/app/components/wp-card-view/event-handler/click-handler.ts","./src/app/components/wp-card-view/event-handler/double-click-handler.ts","./src/app/components/wp-card-view/event-handler/right-click-handler.ts","./src/app/components/wp-card-view/event-handler/card-view-handler-registry.ts","./src/app/components/wp-table/external-configuration/external-query-configuration.component.ts","./src/app/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/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/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/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/job-status/job-status-modal/job-status.modal.ts","./src/app/modules/job-status/job-status-modal/job-status.modal.html","./src/app/modules/time_entries/form/form.component.ts","./src/app/modules/time_entries/form/form.component.html","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-table-pagination.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service.ts","./src/app/components/api/op-file-upload/op-file-upload.service.ts","./src/app/modules/work_packages/routing/partitioned-query-space-page/partitioned-query-space-page.component.html","./src/app/modules/work_packages/routing/partitioned-query-space-page/partitioned-query-space-page.component.ts","./src/app/components/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/modules/fields/display/field-types/date-display-field.module.ts","./src/app/modules/apiv3/forms/apiv3-form-resource.ts","./src/app/globals/global-listeners/request-for-confirmation.ts","./src/app/globals/global-listeners/toggable-fieldset.ts","./src/app/globals/global-listeners/setup-server-response.ts","./src/app/globals/global-listeners.ts","./src/app/globals/onboarding/onboarding_tour_trigger.ts","./src/app/globals/global-listeners/augmented-date-picker.ts","./src/app/globals/global-listeners/link-hijacking.ts","./src/app/globals/global-listeners/danger-zone-validation.ts","./src/app/globals/global-listeners/refresh-on-form-changes.ts","./src/app/globals/global-listeners/top-menu-scroll.ts","./src/app/globals/global-listeners/settings.ts","./src/app/globals/global-listeners/color-preview.ts","./src/app/globals/global-helpers.ts","./src/app/globals/openproject.ts","./src/app/modules/common/browser/browser-detector.service.ts","./src/app/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/fields/help-texts/attribute-help-text.service.ts","./src/app/modules/fields/help-texts/help-text.modal.html","./src/app/modules/fields/help-texts/attribute-help-text.modal.ts","./src/app/modules/fields/help-texts/attribute-help-text.component.html","./src/app/modules/fields/help-texts/attribute-help-text.component.ts","./src/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/$_lazy_route_resource lazy namespace object","./src/app/modules/common/notifications/notifications.service.ts","./src/app/modules/hal/resources/query-filter-resource.ts","./src/app/components/schemas/schema-cache.service.ts","./src/app/components/html/op-title.service.ts","./src/app/modules/fields/edit/edit-form/edit-form.ts","./src/vendor/i18n.js","./src/app/components/wp-grid/wp-grid.component.ts","./src/app/components/filters/filter-container/filter-container.directive.ts","./src/app/components/filters/filter-container/filter-container.directive.html","./src/app/modules/common/op-date-picker/op-date-picker.component.ts","./src/app/modules/common/op-date-picker/op-date-picker.component.html","./src/app/modules/hal/resources/status-resource.ts","./src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service.ts","./src/app/components/resizer/wp-resizer.component.ts","./src/app/components/wp-relations/embedded/children/wp-children-inline-create.service.ts","./src/app/components/api/op-file-upload/op-direct-file-upload.service.ts","./src/app/components/wp-edit-form/work-package-filter-values.ts","./src/app/modules/common/enterprise/banners.service.ts","./src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts","./src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html","./src/app/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/backlogs/backlogs-page/backlogs-page.component.ts","./src/app/modules/hal/resources/work-package-resource.ts","./src/app/modules/common/autocomplete/te-work-package-autocompleter.component.ts","./src/app/modules/common/autocomplete/te-work-package-autocompleter.component.html","./src/app/helpers/rxjs/debounced-input-switchmap.ts","./src/app/modules/apiv3/paths/path-resources.ts","./src/app/modules/attachments/attachments.component.ts","./src/app/modules/attachments/attachments.html","./src/app/modules/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.ts","./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/components/wp-fast-table/builders/modes/grouped/grouped-classes.constants.ts","./src/app/components/op-context-menu/handlers/wp-group-toggle-dropdown-menu.directive.ts","./src/app/modules/apiv3/paths/apiv3-resource.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/edit/field-types/combined-date-edit-field.component.ts","./src/app/modules/fields/display/field-types/text-display-field.module.ts","./src/app/modules/fields/display/field-types/float-display-field.module.ts","./src/app/modules/fields/display/field-types/integer-display-field.module.ts","./src/app/modules/fields/display/field-types/resource-display-field.module.ts","./src/app/modules/fields/display/field-types/formattable-display-field.module.ts","./common/expression.service.ts","./src/app/modules/fields/display/field-types/duration-display-field.module.ts","./src/app/modules/fields/display/field-types/datetime-display-field.module.ts","./src/app/modules/fields/display/field-types/boolean-display-field.module.ts","./src/app/modules/fields/display/field-types/work-package-display-field.module.ts","./src/app/modules/fields/display/field-types/wp-spent-time-display-field.module.ts","./src/app/modules/fields/display/field-types/id-display-field.module.ts","./src/app/modules/fields/display/field-types/highlighted-resource-display-field.module.ts","./src/app/modules/fields/display/field-types/type-display-field.module.ts","./src/app/modules/fields/display/field-types/user-display-field.module.ts","./src/app/modules/fields/display/field-types/multiple-user-display-field.module.ts","./src/app/modules/fields/display/field-types/wp-id-display-field.module.ts","./src/app/modules/fields/display/field-types/project-status-display-field.module.ts","./src/app/modules/fields/display/field-types/plain-formattable-display-field.module.ts","./src/app/modules/fields/display/field-types/linked-work-package-display-field.module.ts","./src/app/modules/fields/openproject-fields.module.ts","./src/app/modules/fields/edit/edit-field.initializer.ts","./src/app/modules/fields/display/display-field.initializer.ts","./src/app/modules/common/focus/focus.directive.ts","./src/app/modules/hal/resources/schema-dependency-resource.ts","./src/app/components/wp-table/table-actions/actions/details-table-action.ts","./src/app/components/wp-table/table-actions/actions/context-menu-table-action.ts","./src/app/components/wp-table/table-actions/table-actions.service.ts","./src/app/modules/router/first-route-service.ts","./src/app/components/wp-buttons/wp-filter-button/wp-filter-button.component.ts","./src/app/components/wp-buttons/wp-filter-button/wp-filter-button.html","./src/app/components/wp-query/url-params-helper.ts","./src/app/modules/common/back-routing/back-routing.service.ts","./src/app/components/wp-table/drag-and-drop/actions/table-drag-action.service.ts","./src/app/components/wp-table/drag-and-drop/actions/hierarchy-drag-action.service.ts","./src/app/components/wp-table/drag-and-drop/actions/group-by-drag-action.service.ts","./src/app/components/wp-table/drag-and-drop/actions/table-drag-actions-registry.service.ts","./src/app/helpers/images/path-helper.ts","./src/app/components/wp-fast-table/builders/cell-builder.ts","./src/app/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/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/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/modules/apiv3/endpoints/grids/apiv3-grid-form.ts","./src/app/components/wp-relations/wp-relations.service.ts","./src/app/modules/hal/resources/grid-resource.ts","./src/app/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/modules/hal/schemas/schema-proxy.ts","./src/app/components/work-packages/work-package-comment/work-package-comment.component.html","./src/app/components/work-packages/work-package-comment/work-package-comment.component.ts","./src/app/modules/bim/bcf/fields/display/bcf-thumbnail-field.module.ts","./src/app/modules/bim/bcf/helper/bcf-detector.service.ts","./src/app/modules/bim/bcf/api/bcf-authorization.service.ts","./src/app/modules/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component.html","./src/app/modules/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component.ts","./src/app/modules/bim/bcf/bcf-wp-attribute-group/bcf-new-wp-attribute-group.component.ts","./src/app/modules/bim/revit_add_in/revit-bridge.service.ts","./src/app/modules/bim/bcf/openproject-bcf.module.ts","./src/app/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/datepicker/datepicker.modal.helper.ts","./src/app/components/datepicker/datepicker.modal.html","./src/app/components/datepicker/datepicker.modal.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/components/modals/modal-wrapper/dynamic-content.modal.ts","./src/app/components/modals/modal-wrapper/dynamic-content.modal.html","./src/app/modules/common/html-sanitize/html-sanitize.service.ts","./src/app/modules/plugins/plugin-context.ts","./src/app/modules/plugins/openproject-plugins.module.ts","./src/app/modules/plugins/linked/budgets/hal/resources/budget-resource.ts","./src/app/modules/plugins/linked/budgets/augment/cost-subform.augment.service.ts","./src/app/modules/plugins/linked/budgets/augment/planned-costs-form.ts","./src/app/modules/plugins/linked/budgets/augment/cost-budget-subform.augment.service.ts","./src/app/modules/plugins/linked/budgets/main.ts","./src/app/modules/plugins/linked/costs/wp-display/costs-by-type-display-field.module.ts","./src/app/modules/plugins/linked/costs/wp-display/currency-display-field.module.ts","./src/app/modules/plugins/linked/costs/main.ts","./src/app/helpers/images/resizer.ts","./src/app/modules/plugins/linked/openproject-avatars/avatar-upload-form/avatar-upload-form.html","./src/app/modules/plugins/linked/openproject-avatars/avatar-upload-form/avatar-upload-form.component.ts","./src/app/modules/plugins/linked/openproject-avatars/main.ts","./src/app/modules/plugins/linked/openproject-documents/hal/resources/document-resource.ts","./src/app/modules/plugins/linked/openproject-documents/main.ts","./src/app/modules/plugins/linked-plugins.module.ts","./src/app/modules/grids/areas/grid-area.ts","./src/app/modules/grids/areas/grid-widget-area.ts","./src/app/modules/grids/areas/grid-gap.ts","./src/app/modules/grids/grid/area.service.ts","./src/app/modules/grids/widgets/header/header.component.ts","./src/app/modules/grids/widgets/header/header.component.html","./src/app/modules/grids/grid/remove-widget.service.ts","./src/app/modules/grids/widgets/menu/widget-abstract-menu.component.ts","./src/app/modules/grids/widgets/menu/widget-menu.component.html","./src/app/modules/grids/widgets/menu/widget-menu.component.ts","./src/app/modules/calendar/wp-calendar/wp-calendar.template.html","./src/app/modules/calendar/wp-calendar/wp-calendar.component.ts","./src/app/modules/grids/widgets/wp-calendar/wp-calendar.component.ts","./src/app/modules/grids/widgets/wp-calendar/wp-calendar.component.html","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-configuration.modal.html","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-configuration.modal.ts","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-menu.component.ts","./src/app/modules/time_entries/edit/edit.modal.ts","./src/app/modules/time_entries/edit/edit.service.ts","./src/app/modules/calendar/te-calendar/te-calendar.template.html","./src/app/modules/calendar/te-calendar/te-calendar.component.ts","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user.component.ts","./src/app/modules/grids/widgets/time-entries/current-user/time-entries-current-user.component.html","./src/app/modules/grids/widgets/widgets.service.ts","./src/app/modules/calendar/wp-calendar-entry/wp-calendar-entry.component.ts","./src/app/modules/calendar/wp-calendar-entry/wp-calendar-entry.component.html","./src/app/modules/time_entries/openproject-time-entries.module.ts","./src/app/modules/calendar/openproject-calendar.module.ts","./src/app/modules/grids/widgets/documents/documents.component.html","./src/app/modules/grids/widgets/documents/documents.component.ts","./src/app/modules/grids/widgets/news/news.component.html","./src/app/modules/grids/widgets/news/news.component.ts","./src/app/modules/grids/grid/initialization.service.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/settings-tab.component.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/settings-tab.component.html","./src/app/modules/work-package-graphs/configuration-modal/tabs/filters-tab.component.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/filters-tab.component.html","./src/app/modules/work-package-graphs/configuration/wp-graph-configuration.ts","./src/app/modules/work-package-graphs/configuration/wp-graph-configuration.service.ts","./src/app/modules/work-package-graphs/configuration-modal/wp-graph-configuration.modal.ts","./src/app/modules/grids/widgets/menu/wp-set-menu.component.ts","./src/app/modules/grids/widgets/wp-graph/wp-graph-menu.component.ts","./src/app/modules/work-package-graphs/embedded/wp-embedded-graph.html","./src/app/modules/work-package-graphs/embedded/wp-embedded-graph.component.ts","./src/app/modules/grids/widgets/wp-graph/wp-graph.component.ts","./src/app/modules/grids/widgets/wp-graph/wp-graph.component.html","./src/app/modules/grids/widgets/wp-table/wp-table-menu.component.ts","./src/app/modules/grids/widgets/wp-table/wp-table.component.html","./src/app/modules/grids/widgets/wp-table/wp-table.component.ts","./src/app/modules/grids/widgets/wp-table/wp-table-qs.component.ts","./src/app/modules/grids/widgets/wp-table/wp-table-qs.component.html","./src/app/modules/work-package-graphs/configuration-modal/tabs/abstract-query-spaced-tab.component.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/filters-tab-inner.component.html","./src/app/modules/work-package-graphs/configuration-modal/tabs/filters-tab-inner.component.ts","./src/app/modules/work-package-graphs/configuration-modal/tabs/settings-tab-inner.component.html","./src/app/modules/work-package-graphs/configuration-modal/tabs/settings-tab-inner.component.ts","./src/app/modules/work-package-graphs/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-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/editable-query-props/editable-query-props.component.ts","./src/app/modules/admin/editable-query-props/editable-query-props.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/modules/fields/macros/attribute-model-loader.service.ts","./src/app/modules/fields/display/display-field.component.ts","./src/app/modules/fields/macros/attribute-value-macro.html","./src/app/modules/fields/macros/attribute-value-macro.component.ts","./src/app/helpers/string-helpers.ts","./src/app/modules/fields/macros/attribute-label-macro.html","./src/app/modules/fields/macros/attribute-label-macro.component.ts","./src/app/modules/fields/macros/work-package-quickinfo-macro.html","./src/app/modules/fields/macros/work-package-quickinfo-macro.component.ts","./src/app/global-dynamic-components.const.ts","./src/app/modules/members/members.module.ts","./src/app/components/enterprise/openproject-enterprise.module.ts","./src/app/modules/augmenting/services/modal-wrapper.augment.service.ts","./src/app/modules/augmenting/services/path-script.augment.service.ts","./src/app/modules/augmenting/openproject-augmenting.module.ts","./src/app/modules/bim/revit_add_in/revit-add-in-settings-button.service.ts","./src/app/angular4-modules.ts","./src/main.ts","./src/app/sentry/sentry-reporter.ts","./src/app/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","form$","hasValue","create","schema","projectedResource","WorkPackageStatesInitializationService","states","querySpace","wpTableColumns","wpTableGroupBy","wpTableGroupFold","wpTableSortBy","wpTableFilters","wpTableSum","wpTableHierarchies","wpTableHighlighting","wpTableRelationColumns","wpTablePagination","wpTableOrder","wpTableAdditionalElements","apiV3Service","wpListChecksumService","authorisationService","wpDisplayRepresentation","query","results","clearStates","putValue","initializeFromQuery","updateQuerySpace","updateChecksum","form","_","each","filtersSchemas","elements","schemas","get","$href","initializeFilters","queryForm","queries","columns","allowedValues","sortBy","groupBy","displayRepresentation","additionalRequiredWorkPackages","clear","tableRendered","href","initModelAuth","$links","forEach","wp","work_packages","cache","updateWorkPackage","groups","initialize","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","resourceReference","id","_type","next","AccessibleByKeyboardComponent","execute","isDisabled","emit","handleClick","contextMenuTdClassName","contextMenuSpanClassName","contextMenuLinkClassName","contextColumnIcon","OpTableAction","injector","workPackage","ANIMATION_RATE_MS","TopMenu","menuContainer","hover","menuIsOpen","withHeadingFoldOutAtBorder","setupDropdownClick","registerEventHandlers","closeOnBodyClick","accessibility","skipContentClickListener","on","visibleLink","not","first","trigger","attr","dropdown","isOpen","closing","open","opening","startHover","stopHover","closeAllItems","removeClass","addClass","openDropdowns","ix","item","close","self","wrapper","document","getElementById","addEventListener","contains","dropdowns","filter","find","menu_start_position","undefined","tagName","innerHeight","position","top","css","hasClass","children","wiki_heading","it","click","toggleClick","e","preventDefault","dontCloseWhenUsing","closeOtherItems","slideAndFocus","immediate","slideUp","stopPropagation","bind","callback","slideDown","focusFirstInputOrLink","toDrop","hide","toFocus","blur","setTimeout","focus","toggler","makeSplitViewRoutes","baseRoute","menuItemClass","showComponent","newComponent","makeFullWidth","routeName","url","redirectTo","reloadOnSearch","data","bodyClasses","menuItem","newRoute","partition","views","component","parent","allowMovingInEditMode","BcfPathHelperService","pathHelper","projectIdentifier","projectPath","filters","viewpoint","map","webpackAsyncContext","req","__webpack_require__","o","Promise","resolve","then","Error","code","ids","keys","Object","module","exports","relationCellTdClassName","relationCellIndicatorClassName","RelationCellbuilder","column","td","createElement","classList","add","dataset","expanded","getExpandFor","relationState","wpRelations","state","relations","relationsForColumn","indicator","renderIndicator","badge","renderBadge","appendChild","setAttribute","textContent","ActivityLinkComponent","activityHtmlId","activityNo","activityLabel","OpContextMenuLocalsToken","RestrictedWpTableConfigurationService","locals","disabledTabs","_tabs","el","disableBecause","LinkHandling","isClickedWithModifier","modifier","ctrlKey","shiftKey","metaKey","middleButton","button","DoubleClickOrTapDirective","stopEventPropagation","eventHandler","type","tapCount","eventStopReturnCode","WorkPackageViewCollapsedGroupsService","workPackageViewGroupByService","schemaCacheService","groupTypesWithHeaderCellsWhenCollapsed","isMilestone","of","wpTypesToShowInCollapsedGroupHeaders","updatesState","getValueOr","getDefaultState","config","allGroupsAreCollapsed","allGroupsAreExpanded","collapsedGroups","allGroupsChanged","lastChangedGroup","groupedBy","currentGroupedBy","getAllGroupsCollapsedState","currentGroups","groupIdentifier","newCollapsedState","newState","update","collapsedState","groupUpdatedState","reduce","updatedState","group","identifier","currentCollapsedGroupsState","firstGroupIdentifier","firstGroupCollapsedState","allGroupsHaveTheSameCollapseState","every","QueryFiltersService","schemaCache","available","$embedded","allowedFilterValue","getFilterSchema","updateValue","WorkPackageCreateSettingsMenuDirective","halEditing","workPackages","changeFor","getForm","loadedForm","positionArgs","assign","my","at","configureFormLink","configureForm","queryCustomFields","customFields","splitViewRoute","WorkPackageViewHighlightingService","Banners","isInline","eeShowBanners","selectedAttributes","lastUpdatedState","mode","filteredValue","highlight","highlightingMode","highlightedAttributes","isEqual","isEmpty","conditional","WorkPackageCreateButtonComponent","$state","currentProject","transition","text","createWithDropdown","createButton","explanation","observeUntil","allowed","allowedWhen","combined","permission","split","can","updateDisabledState","transitionUnregisterFn","onSuccess","ngOnDestroy","disabled","includes","WorkPackageCommentFieldHandler","handler","active","inEditMode","inFlight","onDestroy","change","withText","raw","writable","required","hasDefault","commentValue","deactivate","reset","complete","querySelector","onlyCancel","WorkPackageEditActionsBarComponent","editForm","onSave","onCancel","_saving","save","cancel","saving","submit","catch","AuthoringComponent","PathHelper","timezoneService","createdOnTime","parseDatetime","createdOn","timeago","fromNow","time","format","userLink","userPath","author","idFromLink","from","path","projectActivityPath","project","WorkPackageBreadcrumbComponent","hierarchy","inputActive","ancestors","hierarchyCount","AttachmentsUploadComponent","ConfigurationService","halResourceService","draggingOver","uploadLabel","dropFiles","dropFilesHint","foldersWarning","maxFileSize","maximumAttachmentFileSize","filePicker","dataTransfer","dropEffect","dfFiles","files","i","uploadFiles","containsFiles","Array","types","indexOf","countBefore","filterFolders","resource","uploadAttachments","addNotice","file","size","console","warn","EditFieldControlsComponent","basePath","segment","resourceClass","params","headers","encoder","fromObject","withCredentials","responseType","_request","method","body","http","request","response","deserialize","catchError","error","throwError","parse","BcfProjectResource","BcfTopicAuthorizationMap","String","BcfTopicResource","preserveNull","deserializer","moment","serializer","timestamp","toISOString","bcfTopicService","toPath","comments","viewpoints","BcfExtensionResource","bcfExtensionService","bcfProjectService","topics","extensions","bcfApiVersion","appBasePath","window","bcfApiBase","projects","startsWith","parts","replace","pathOrId","UserAvatarRendererService","colors","container","users","renderName","multiLine","span","avatar","render","sep","classes","userInitials","getInitials","colorCode","toHsl","fallback","className","style","background","image","Image","src","toString","title","alt","onload","replaceWith","characters","lastSpace","lastIndexOf","toUpperCase","join","AngularTrackingHelpers","compareByAttribute","attribute","a","b","compareByHref","halHref","_index","compareByName","trackByName","trackByHref","trackByProperty","prop","trackByHrefAndProperty","propertyName","trackByTrackingIdentifier","compareByHrefOrString","NewestActivityOnOverviewComponent","latestActivityInfo","workPackageId","ngOnInit","activities","updateActivities","latestActivities","visible","reverse","unfilteredActivities","slice","info","startIndex","WorkPackageCopySplitViewComponent","WorkPackageRelationsHierarchyComponent","wpRelationsHierarchyService","showEditForm","parentHeadline","childrenHeadline","workPackagePath","canModifyHierarchy","changeParent","canAddRelation","addRelation","childrenQueryProps","JSON","stringify","operator","values","showHierarchies","requireAndStream","parentId","timelineElementCssClass","timelineBackgroundElementClass","timelineGridElementCssClass","timelineMarkerSelectionStartClass","timelineHeaderCSSClass","timelineHeaderSelector","TimelineViewParametersSettings","zoomLevel","zoomLevelOrder","getPixelPerDayForZoomLevel","requiredPixelMarginLeft","TimelineViewParameters","now","hour","minute","seconds","dateDisplayStart","dateDisplayEnd","clone","settings","activeSelectionMode","selectionModeStart","maxSteps","pixelPerDay","diff","Math","ceil","calculatePositionValueForDayCountingPx","viewParams","days","calculatePositionValueForDayCount","getTimeSlicesForHeader","vp","unit","startView","endView","inViewport","rest","startOf","end","endOf","isBefore","sliceStart","sliceEnd","viewport","visibleViewportAtCalculationTime","isSameOrAfter","isSameOrBefore","firstRest","splice","lastRest","pop","inViewportAndBoundaries","concat","isNil","calculateDaySpan","visibleWorkPackages","loadedWorkPackages","viewParameters","earliest","latest","renderedRow","wpId","start","startDate","date","due","dueDate","isAfter","OPContextMenuService","componentFactoryResolver","FocusHelper","appRef","$transitions","isOpening","hostElement","portalHostElement","bodyPortalHost","onStart","which","ESCAPE","that","menu","portal","injectorFor","attach","display","reposition","onOpen","activeMenu","detach","onClose","injectorTokens","WeakMap","service","set","newWorkPackageHref","WorkPackageCreateService","hooks","halEvents","newWorkPackageCreatedSubject","committedChanges","commit","wasNew","newWorkPackageCreated","changes$","changeset","withOptionalProject","forPayload","toPromise","fromCreateForm","initializeNewResource","edit","call","copyFrom","$source","post","stopEditing","defaults","changePromise","continueExistingEdit","createNewWithDefaults","clearSome","changeType","hasChanges","typeEmpty","typeMatches","withFiltersPayload","filterDefaults","mergedPayload","merge","_links","createNewWorkPackage","defaultsFromFilters","object","except","applyDefaultsFromFilters","fromFilter","forTypePayload","toApiPayload","links","$plain","createHalResourceOfType","__initialized_at","Date","updateImmediately","cssClassCustomOption","DisplayField","context","activeChange","texts","empty","placeholder","constructor","isFormattable","valueString","element","displayText","options","emptyDiv","ActivityPanelBaseController","$transition","wpActivity","visibleActivities","onlyComments","commentsOnly","showAll","isReversed","togglerText","require","getVisibleActivities","showToggler","shouldShowToggler","count_all","count_with_comments","getActivitiesWithComments","activity","index","rowId","relationRowClass","locateTableRow","locateTableRowByIdentifier","isInsideCollapsedGroup","listClass","locatePredecessorBySelector","selector","previous","previousElementSibling","matches","scrollTableRowIntoView","scrollParent","containerTop","scrollTop","containerBottom","height","elemTop","offsetTop","elemBottom","createLocalInjector","fieldHandler","AbstractDateTimeValueController","remove","isValidISODateTime","isValidISODate","d","parseISODatetime","formattedISODateTime","formattedISODate","lowerBoundary","upperBoundary","hours","minutes","to","RowsBuilder","workPackageTable","table","groupClassNameFor","collapse","expand","colspan","togglerIconClass","row","collapsed","innerHTML","escape","count","relationGroupClass","relationCellClassName","emptyRelationCell","buildCell","relation","denormalized","targetId","createEmptyRelationRow","tr","buildEmptyRow","relationClassIdentifier","jRow","columnId","typeLabel","reverseRelationType","relationLabel","createTextNode","append","cell","tablePass","relationRowBuilder","isApplicable","renderedOrder","fromId","relationsToExtendFor","relationRow","buildEmptyRelationRow","additionalClasses","appendRelationLabel","spliceRow","classIdentifier","belongsTo","renderType","hidden","relationType","oldRow","newRow","refreshRow","hasRelationColumns","timelineBody","createDocumentFragment","timelineBuilder","secondary","build","highlightAttribute","getComputedStyle","property","tableBody","backgroundClass","dragActionRegistry","actionService","canPickup","dragDropHandleBuilder","configuration","dragAndDropEnabled","withLoadedPositions","positions","handle","replaceChild","firstElementChild","rowBuilder","prepare","doRender","postRender","highlighting","dragDropHandle","timeline","replacement","refreshRelationRow","renderedInfo","last","after","renderPlaceholderRow","placeholderRow","classIdentifer","originalRows","originalRowIndex","buildEmpty","appendRow","headerBuilder","sumsBuilder","currentGroup","nextGroup","matchingGroup","groupsChanged","renderSumsRow","groupClass","rowElement","buildGroupRow","appendNonWorkPackageRow","buildSingleRow","isArray","matchesMultiValue","valueLink","l","joinedOrderedHrefs","objects","sort","isEqualWith","sums","buildSumsRow","columnCount","builder","getGroupData","rendered","tableAndTimelineContainer","groupIndex","parentNode","affected","toggleClass","additionalParents","deferred","parentsWithVisibleChildren","hierarchies","ancestor","deferInsertion","buildWithHierarchy","markRendered","renderAllDeferredChildren","ancestorChain","inTable","newElements","child","uniqBy","insertUnderParent","getOrBuildRow","ancestorGroups","ancestorRow","buildAncestorRow","insertAtExistingHierarchy","previousAncestor","isAncestor","buildRenderInfo","hierarchyRoot","hierarchyGroup","ancestorClasses","ancestorRowData","_table","isEnabled","cellBuilder","resourceSubscription","unsubscribe","rowContainer","errors","waitForContainer","findCell","width","parseInt","editingPortalService","findContainer","refresh","focusElement","addColumn","noWarnings","loadFieldSchema","reject","interval","setInterval","clearInterval","forms","destroy","typedState","existing","scrollContainer","tbody","timelineController","hierarchyRowsBuilder","groupedRowsBuilder","plainRowsBuilder","builders","lastRenderPass","editing","findIndex","renderedRows","rows","buildIndex","redrawTableAndTimeline","renderPass","performRenderPass","requestAnimationFrame","result","pass","insert","buildRows","t0","performance","refreshExpansionState","t1","CKEditorSetupService","initialData","load","editorClass","OPConstrainedEditor","OPClassicEditor","toolbarWrapper","contentWrapper","contentLanguage","rtl","editor","createCustomized","openProject","createConfig","language","content","ui","view","toolbar","setData","cb","getData","trim","macros","helpURL","textFormattingHelp","pluginContext","OpenProject","EditFieldService","wpQuerySelectSelector","WorkPackageQuerySelectDropdownComponent","ref","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","collection","combinedQueries","query_props","all","sortQueries","categorized","starred","default","public","private","auto_id","category","flatten","sortByLabel","toLowerCase","localeCompare","loadingPromise","filterNonHidden","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","currentIdSelected","matchesStaticQueryProps","allOpen","onSummary","changes","go","reload","closeWhenOnMobile","static_link","highlightBySelector","ENTER","clickedWithModifier","isStatic","stopImmediatePropagation","location","loadQuery","highlightSelected","clickedCategory","selectorTimelineSide","jQueryScrollSyncEventNamespace","getPlattformAgnosticScrollAmount","originalValue","delta","syncWheelEvent","jev","elementTable","elementTimeline","scrollTarget","ev","deltaX","deltaY","x","y","getXandYScrollDeltas","scrollLeft","createScrollSync","elTable","elTimeline","timelineVisible","syncedLeft","syncedRight","off","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","HighlightableDisplayField","colorize","shouldHighlight","viewHighlighting","shouldHighlightInline","WorkPackageRelationsCreateComponent","notificationService","showRelationsCreateForm","selectedRelationType","DEFAULT","relationTypes","LOCALIZED_RELATION_TYPES","abort","addNewRelation","selectedWpId","createCommonRelation","addCommonRelation","eventType","relatedWorkPackage","showSave","toggleRelationsCreateForm","err","handleRawError","FilterDateTimeValueComponent","shouldFocus","filterChanged","isoDateParser","tableActionsService","tableRowClassName","commonRowClassName","relationCellBuilder","contextLinkBuilder","augmentedColumns","buildAugmentedColumns","getColumns","unshift","actionsColumnEnabled","columnMenuEnabled","createEmptyRow","colSpan","cells","newCells","oldTd","isColumnBeingEdited","prepend","activeFields","changedAttributes","oldCell","wpTableSelection","isSelected","inlineCreateRowClassName","cancelButton","buildCancelButton","wpCreate","wpInlineCreate","wpTableFocus","canAdd","canReference","buttonTexts","hasReferenceClass","registerCreationCallback","refreshOnColumnChanges","registerCancelHandler","resetRow","updates$","isActive","onNewWorkPackage","currentWorkPackage","isEmbedded","updateFocus","newInlineWorkPackageCreated","cancelCreation","removeWorkPackageRow","showRow","addWorkPackageRow","referenceComponentClass","referenceClass","createOrContinueWorkPackage","editingSubscription","changesetUpdates$","insertRow","workPackageEditForm","renderInlineCreateRow","activateMissingFields","hideRow","startEditing","buildNew","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","GlobalEditFormChangesTrackerService","i18nService","activeForms","Map","thereAreFormsWithUnsavedChanges","returnValue","delete","editFormRouting","globalEditFormChangesTrackerService","initializeEditMode","skippedFields","onSavedEmitter","registeredFields","confirmText","requiresConfirmation","warnOnLeavingUnsaved","unregisterListener","onBefore","blockedTransition","editMode","addToActiveForms","removeFromActiveForms","waitForField","ctrl","setActive","editContainer","savedResource","isInitial","closeEditFields","hasActiveFields","skipField","activateOnForm","take","changed","FilterDateValueComponent","isValid","parseDate","parser","uniqueEmbeddedTableName","initialLoadingIndicator","renderTable","showTablePagination","providedConfiguration","queryId","queryProps","projectContext","wpStatesInitialization","urlParamsHelper","buildV3GetQueryFromQueryResource","encodeQueryJsonParams","tableVisible","firstPage","pagination","paginationObject","offset","wpListService","loadQueryFromExisting","queryProjectScope","loadingIndicatorService","tableActions","externalHeight","onError","onQueryLoaded","loadedQuery","ngAfterViewInit","setActions","page","perPage","distinctUntilChanged","withLatestFrom","initializeStates","onUpdated","valuesPromise","opModalService","onDataUpdated","withFilters","loadForm","total","setLoaded","compactTableStyle","formPromise","apiv3Service","updateStatesFromForm","pageSize","message","double","keepTab","requestedState","EditFormPortalComponent","editField","onEditFieldReady","editFieldHandler","schemaInput","changeInput","componentClass","getSpecificClassFor","fieldInjector","WorkPackageSchemaProxy","receiver","isReadonly","propertySchema","ofProperty","isAttributeEditable","status","scheduleManually","hasOwnProperty","FocusHelperService","minimumOffsetForNewSwitchInMs","lastFocusSwitch","lastPriority","allowFocusSwitch","priority","checkTimeout","throttleAndCheckIfAllowedFocusChangeBasedOnTimeout","focusser","focusable","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","positionOffset","getPosition","$onUserActivate","startDragOverActivation","activateIfEditable","WorkPackageFoldToggleButtonComponent","WorkPackageCardDragAndDropService","reorderService","dragService","componentRef","cardView","dragContainer","scrollContainers","moves","card","canDragOutOf","accepts","dragInto","onMoved","toIndex","newOrder","move","currentOrder","updateOrder","onRemoved","onAdded","addWorkPackageToQuery","parentElement","removeChild","_workPackages","activeInlineCreateWp","existingNewWp","uniq","workPackageAddedHandler","removeCard","DomHelpers","setBodyCursor","cursor","setProperty","validationErrors","halInitializer","errorIdentifier","isValidationError","idPart","decodeURIComponent","HelpTextResource","WikiPageResource","MeetingContentResource","PostResource","timeEntries","without","$linkableKeys","halResourceDefaultConfig","WorkPackage","cls","attrTypes","Activity","Relation","Schema","Type","Status","SchemaDependency","User","Group","Collection","WorkPackageCollection","AttachmentCollection","Query","Form","FormPayload","QueryFilterInstance","QueryFilterInstanceSchema","QueryFilter","Root","QueryOperator","HelpText","CustomAction","WikiPage","MeetingContent","Post","Project","Role","Grid","GridWidget","TimeEntry","Membership","News","Version","internal_error","errorMessages","ErrorReporter","captureException","captureMessage","handleError","OpenprojectHalModule","provide","useClass","multi","useFactory","registerResource","deps","OpTypesContextMenuDirective","browserDetector","isMobile","stateName","getEmptyForm","ariaLabel","class","inlineClass","ConfirmDialogModal","confirmed","button_continue","button_cancel","close_popup","dangerHighlighting","defaultTo","passedData","closeOnEscape","closeByEscape","closeOnOutsideClick","closeByDocument","showClose","closeMe","confirmAndClose","OpenprojectAccessibilityModule","NoResultsComponent","setHostClass","AbstractFieldService","attributeType","fieldType","defaultFieldType","getClassFor","fieldClass","attributes","addFieldType","loadConfiguration","userPreference","timezone","prepareAttachmentURL","systemPreference","startOfWeekPresent","locale","firstDayOfWeek","pref","OpContextMenuHandler","afterFocusOn","openerEvent","collision","DragAndDropHelpers","reinsert","previousIndex","currentIndex","pointOfInsertion","insertBefore","timelineCellClassName","TimelineRowBuilder","rowClasses","WorkPackageCommentFieldComponent","isBusy","rawValue","WorkPackageWatchersCountComponent","wpWatcherService","watchers","EditFormRoutingService","QueryFilterInstanceResource","memoizedCurrentSchemas","api","v3","apiV3Base","resultingSchema","currentSchema","isValueRequired","operatorSymbol","availableOperators","BoardActionsRegistryService","mapping","localizedName","WorkPackageService","UrlParamsHelper","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","isAction","isFree","isNewWidget","widgets","createdAt","startColumn","actionAttribute","ContainHelpers","insideOrSelf","within","whenOutside","activeElement","collapsedGroupClass","ancestorId","hierarchyGroupClass","hierarchyRootClass","ancestorClassIdentifier","ExternalRelationQueryConfigurationService","subResource","extractPayload","patch","listParamsString","filterParam","toParams","queryPropsString","apiRoot","createCache","force","stale","observable","shareReplay","clearAndLoad","observe","switchMap","mapTo","updateFor","source$","tap","touch","extractPayloadFromSchema","observeAll","ensureLoaded","cacheResponse","projectId","toJson","available_projects","me","wpIds","withOptionalId","queryFilters","setSchemas","buildQueryResource","URI","order","mapSchemasIntoFilters","parameterised","filter_instance_schemas","queryData","unstar","star","listParams","list","workPackageIds","validIds","test","filtered","revisions","available_watchers","skipOnIdentical","multiState","updateWorkPackageList","loadCollectionsFor","pagedResults","term","idOnly","additionalParams","n","getAllPaginated","version","versions","available_assignees","statuses","$configuration","grids","newBoard","sortWidgets","board","fetchSchema","boardPath","scope","createGrid","projectBoardsPath","forType","apiV3CollectionEndpoint","apiV3CustomEndpoint","documents","root","apiV3SingularEndpoint","priorities","time_entries","memberships","news","help_texts","job_statuses","boards","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","i18n","resourceChanged","editableName","widgetIdentifier","defaultValue","setChangesetOptions","GonService","gon","BackButtonComponent","backRoutingService","goBack","customBackMethod","linkClass","SchemaResource","match","availableAttributes","fieldSchema","WorkPackagesListService","wpListInvalidQueryService","queryRequests","queryLoading","q","ensurePerPageKnown","streamQueryRequest","queryParams","conditionallyLoadForm","decodedProps","getCurrentQueryProps","buildV3GetQueryFromJsonParams","handleQueryLoadingError","fromQueryParams","reloadQuery","currentQuery","loadDefaultQuery","addError","toggleStarred","currentForm","loadWithParams","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","renderedWorkPackages","$","stopAllSubscriptions","keyCodes","WorkPackageViewSumService","WorkPackageBreadcrumbParentComponent","wpRelationsHierarchy","onSwitch","isSaving","edit_parent","set_or_remove_parent","remove_parent","set_parent","newParent","WorkPackageSettingsButtonComponent","WpTableExportModal","httpClient","notifications","closePopup","exportPreparing","requestExport","exportOptions","buildExportOptions","representations","addColumnsToHref","json","replaceWithJobModal","job_id","jobId","showError","columnIds","removeSearch","addSearch","WorkPackageViewFiltersService","incomplete","rawFilters","newFilters","filterOrId","availableSchemas","getFilter","mapper","isCompletelyDefined","cloneFilters","invisibleFilters","currentFilterResources","isComplete","differenceBy","WorkPackageViewRelationColumnsService","eachCallback","findById","relationColumnType","typeHref","RELATION_TO_TYPE","RELATION_OF_TYPE","nextState","WorkPackageInlineCreateService","referenceTarget","reference","newInlineWorkPackageReferenced","canCreateWorkPackages","OpSettingsMenuDirective","focusAfterClose","queryUpdate","formUpdate","action","allowAction","modelName","initialTab","cannot","allowQueryAction","create_new","allowFormAction","allowWorkPackageAction","divider","internalSortColumn","internalContextMenuColumn","CKEditorPreviewService","preview","refs","getEmbeddable","entry","matchedElements","resolveComponentFactory","attachView","hostView","changeDetectorRef","detachView","QueryFilterInstanceSchemaResource","_dependencies","dependency","definesAllowedValues","staticSchema","dependentSchema","forValue","dependencies","OpenprojectProjectsModule","ClickPositionMapper","setPosition","setSelectionRange","originalEvt","caretRangeFromPoint","clientX","clientY","startOffset","rangeParent","range","createRange","setStart","rangeOffset","Changeset","k","pristineValue","getItem","updatePristineResource","buildPayloadFromChanges","_pristineResource","Proxy","proxyGet","isPristine","hasActivePromiseRequest","setNewDefaults","putFromPromiseIfPristine","getValue","lockVersion","plainPayload","getLinkedValue","cloneDeep","minimalPayload","isArrayType","valueExists","HalPayloadHelper","nonLinkProperties","TabPortalOutlet","availableTabs","outletElement","activeTabs","currentTab","tab","instance","activateInstance","_getComponentRootNode","tabName","setAttachedHost","dispose","createComponent","rootNodes","WorkPackageIsolatedQuerySpaceDirective","useExisting","OpenProjectHeaderInterceptor","csrf_token","newHeaders","clonedRequest","StateCacheService","holdValuesForSeconds","cacheDurationInMs","loader","clearAndPutFromPromise","observeChange","mapped","isValueOlderThan","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","closeOnEscapeFunction","activeModal","withErrors","Subject","setErrors","setClickOffset","subject","handleUserSubmit","newErrors","isErrorenous","onSubmit","handleUserCancel","messages","previewPath","outlet","createDomOutlet","localInjector","attachComponentPortal","ExternalRelationQueryConfigurationComponent","useValue","DisplayFieldService","apply","WorkPackageViewColumnsService","isCurrentlyEqualTo","c","toApply","oldColumns","newColumns","relationColumns","isLast","setColumns","compact","fromIndex","moveColumn","newColumn","PROPERTY","Apiv3Paths","base","PathHelperService","attachmentIdentifier","slug","staticBase","forumIdentifier","projectForumPath","messageIdentifier","newsId","projectsPath","projectWorkPackagesPath","suffix","usersPath","workPackagesPath","MainMenuNavigationService","navigationEvents$","names","targetLi","log","mainItems","wrap","elementId","wrapperElement","wrapMainItem","recreateToggler","activeRoot","navigateUp","parents","unbind","wrapInner","_i","contents","parentURL","header","upLink","parentLink","before","DeviceService","mobileWidthTreshold","innerWidth","WorkPackageStatusButtonComponent","workPackageReadOnly","workPackageStatusBlocked","$load","renderEmpty","renderValues","div","percentLabel","avatarRenderer","renderMultiple","editableClassName","readOnlyClassName","displayClassName","fieldCache","renderFieldValue","setSpanAttributes","requestedAttribute","attributeName","getField","getText","getAriaLabel","getFieldForCurrentContext","isCustomMultiLinesField","isUserMultiLinesField","displayFieldService","getDefaultPlaceholder","titleContent","labelContent","getLabelContent","displayName","mappedName","AuthorisationService","modelLinks","doModify","Attachable","Base","addAttachment","pull","$isHal","max","updateState","uploads","finished","performUpload","notification","addAttachmentUpload","r","ErrorEvent","directUploadURL","opDirectFileUpload","uploadAndMapResponse","opFileUpload","prepareAttachment","Field","WorkPackageRelationsAutocomplete","inputPlaceholder","additionalFilters","hiddenOverflowContainer","onSelected","onEmptySelected","isLoading","searchInput$","appendToContainer","results$","queryString","autocompleteWorkPackages","availableRelationCandidates","filterCandidatesFor","one","onWorkPackageSelected","HalResource","$loaded","$halType","other","_name","_fieldName","$loadResource","$self","properties","OpIcon","iconTitle","RelationResource","includeParentChild","includeParentchild","RELATION_TYPES","reverseType","QueryFilterComponent","deactivateFilter","showValuesInput","showValues","removeThisFilter","URLParamsEncoder","encodeURIComponent","VersionResource","WorkPackageCopyController","copying","copiedWorkPackageId","stateParams","copiedFromWorkPackageId","createCopyFrom","titleService","setFirstPart","sourceChangeset","copyWorkPackage","copyChangeset","ProgressDisplayField","roundedProgress","round","Number","WorkPackageActivityTabComponent","WorkPackageViewAdditionalElementsService","requireInvolvedRelations","requireHierarchyElements","requireSumsSchema","loadAdditional","requireAll","getInvolvedWorkPackages","sumsSchema","DomAutoscrollService","down","scrollWhenOutside","maxSpeed","margin","autoScroll","point","pointCB","init","onMove","onUp","setScroll","cleanAnimation","cancelAnimationFrame","animationFrame","windowAnimationFrame","scrolling","targetObject","underPoint","inside","dispatched","getElementsUnderPoint","getTarget","outerScrollContainer","scrollTick","scrollAutomatically","scrollx","scrolly","rect","left","right","bottom","scrollY","scrollX","amount","scrollTo","pageXOffset","pageYOffset","FilterToggledMultiselectValueComponent","halSorting","currentUser","_availableOptions","fetchAllowedValues","ngSelectInstance","castArray","_isEmpty","loadAllowedValues","availableOptions","loadingPromises","isUserResource","resources","addMeValue","createHalResource","setValues","repositionDropdown","WorkPackageAuthorization","workPackageDetailsCopyPath","workPackageCopyPath","copyLink","allActions","allowedActions","validActions","isPermitted","linkForAction","HookService","opContextMenuService","authorization","permittedActions","getPermittedActions","timeEntryCreateService","actions","permittedActionsWithLinks","getPermittedPluginActions","indexBy","triggerContextMenuAction","DatePicker","datepickerElemIdentifier","datepickerTarget","configurationService","datepickerFormat","datepickerCont","hideDuringScroll","datepickerInstance","reshowTimeout","clearTimeout","visibleAndActive","startOfWeek","mergedOptions","weekNumbers","getWeek","dateObj","week","dateFormat","defaultDate","weekdays","shorthand","longhand","months","weekAbbreviation","datePickerInstances","removeEventListener","dates","setDate","isInViewport","getBoundingClientRect","documentElement","clientHeight","clientWidth","GridWidgetResource","endRow","startRow","endColumn","halResource","HalResourceNotificationService","isCreate","handleErrorResponse","errorBody","retrieveError","showGeneralError","createHalResourceOfClass","errorResource","showApiErrorMessages","showCustomError","details","i18nString","lookup","OpContextMenuTrigger","Mousetrap","OpenprojectHalModuleHelpers","lazy","obj","getter","setter","isObject","done","configurable","enumerable","defineProperty","cloneHalResourceCollection","v","$copy","initializeHalProperties","asHalResource","loaded","_embedded","setupProperty","instanceName","sourceName","sourceObj","propName","setSource","$embeddableKeys","createLinkedResource","setEmbeddedAsProperties","KeepTabService","updateTabs","isCurrentState","currentShowTab","currentDetailsTab","lastActiveTab","currentShowState","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","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","FalseValue","TrueValue","ApiV3FilterBuilder","filterMap","only","toAdd","pickBy","toFilterObject","mergeParams","transformedFilters","serializeFilter","URLSearchParams","transformedFilter","typeName","operatorAndValues","serializeFilterValue","filterValue","buildApiV3Filter","WorkPackageRelationQueryBase","queryUrlParamsHelper","embeddedTable","isInitialized","filtersLength","projectValuesCount","loadedFiltersLength","valid_subset","webpackContext","webpackContextResolve","CommentService","workPackageNotificationService","quoteEvents","comment","addComment","errorAndReject","WorkPackageRelationsCountComponent","relationCount","childrenCount","slideToggleSelector","SlideToggleComponent","valueChanged","inputName","containerId","containerClasses","inputId","onValueChanged","WorkPackageSingleCardComponent","showInfoButton","showStatusButton","showRemoveButton","draggable","orientation","shrinkOnMobile","onRemove","stateLinkClicked","uiStateLinkClass","detailsView","live$","detail","stateToEmit","setSelection","findRenderedCard","cardHighlighting","attributeHighlighting","bcfSnapshotPath","bcfViewpoints","ChangesetStates","changesets","initializeMembers","ResourceChangesetCommit","saved","changeMap","HalResourceEditingService","hook","buildRequestPayload","retainFrom","onSaved","newChangeset","tree","selectedPage","FilterDateTimesValueComponent","begin","OpModalComponent","openingEvent","modalElement","MainMenuToggleService","deviceService","elementMinWidth","defaultWidth","localStorageKey","localStorageStateKey","global","htmlNode","getElementsByTagName","mainMenu","hideElements","titleData","titleData$","changeData","changeData$","elementWidth","guardedLocalStorage","menuCollapsed","closeMenu","setWidth","saveWidth","offsetWidth","showNavigation","savedWidth","widthToSave","maxMenuWidth","snapBack","setToggleTitle","toggleClassHidden","changeEvent","Event","toggleTitle","groupByProperty","groupName","groupedRowClassName","groupTypeFromIdentifier","groupIdFromIdentifier","FilterBooleanValueComponent","onFilterUpdated","PERMITTED_CONTEXT_MENU_ACTIONS","CombinedDateDisplayField","startDateElement","createDateDisplayField","dueDateElement","separator","dateElement","dateDisplayField","formattedDate","hint","button_save","selectedPageInput","applyAndClose","_language","debouncedLanguageLoader","debounce","loadLanguageAsMode","language_hint","languageClass","codeMirrorInstance","lang","imported","CodeMirror","fromTextArea","codeMirrorPane","lineNumbers","smartIndent","autofocus","updateCodeMirrorMode","newLanguage","setOption","updateLanguage","includeParent","include_parent","selectedIncludeParent","updateIncludeParent","pageValue","ActivityEntryComponent","activityType","demoProjectName","scrumDemoProjectName","onboardingTourStorageKey","waitForElement","execFunction","MutationObserver","mutations","observerInstance","disconnect","childList","subtree","demoProjectsLinks","demoProjects","demoProjectsLink","scrumDemoProjectsLink","preventClickHandler","WpButtonMacroModal","none","selected_type","button_style","button_style_hint","selectedType","buttonStyle","availableTypes","typeSelect","PaginationInstance","limit","min","WorkPackageTableConfiguration","providedConfig","contextMenuEnabled","inlineCreateEnabled","hierarchyToggleEnabled","isCardView","filtersExpanded","showFilterButton","filterButtonText","WpDestroyModal","busy","childrenDeletionConfirmed","label_visibility_settings","warning","label_confirm_children_deletion","workPackageLabel","singleWorkPackage","singleWorkPackageChildren","childCount","hasChildren","childUnits","deletesChildren","mustConfirmChildren","blockedDueToUnconfirmedChildren","performBulkDelete","confirmDeletion","WpTableConfigurationDisplaySettingsTab","wpTableSums","displayMode","availableGroups","displaySums","choose_mode","label_group_by","display_sums","display_sums_hint","display_mode","grouped","hierarchy_hint","setEnabled","updateGroup","MIN_ORDER","MAX_ORDER","ORDER_DISTANCE","isAscendingOrder","buildInsertPosition","rebuildPositions","minMaxPositions","redistribute","abs","positionSwap","insertAsFirst","predecessorPosition","buildUpPredecessorPosition","reorderedInsert","successorPosition","positionFor","distance","myPosition","neighbor","neighborPosition","DEFAULT_ORDER","livePosition","firstPosition","lastPosition","itemsToDistribute","space","any","causedUpdates","assignPosition","buildDelta","updatedAt","upstreamOrder","pos","orderedWorkPackages","setExpandFor","additionalPositionArgs","startAddRelationPredecessor","startAddRelationFollower","wpViewIndentation","indent","outdent","rowSelector","openContextMenu","keyCode","F10","altKey","SELECTOR","findRenderedRow","itemClicked","setMultiSelectionFrom","toggleRow","selectionChanged","getSelectedWorkPackageIds","workPackageViewCollapsedGroupsService","toggleGroupCollapseState","takeUntil","redrawTable","lastValue","renderHierarchyState","classNames","isCollapsed","initialSetup","changedId","refreshRows","ifShouldFocus","renderSelectionState","registerSelectAllListener","registerDeselectAllListener","renderVisibility","inlineCreateService","updateRenderedOrder","sibling","rowIndex","collapsedGroupId","collapsedGroupElements","getElementsByClassName","collapsedGroupLastChild","findRowIndex","handleDrop","onNewOrder","switchToManualSorting","changeShadowElement","sourceIndex","onCloned","original","subjectWithId","maxWidth","onShadowInserted","isEdge","mappedOrder","currentRenderedOrder","groupsCollapseEvent","setGroupsCollapseState","eventHandlers","stateTransformers","viewRef","attachTo","cssClassRowHovered","WpTableHoverSync","tableAndTimeline","lastHoveredElement","eventListener","handleHover","passive","removeAllHoverClasses","parentTableRow","locateHoveredTableRow","parentTimelineRow","locateHoveredTimelineRow","removeOldAndAddNewHoverClass","hovered","extractWorkPackageId","tableRow","timelineRow","zone","limitedResults","configurationObject","tableSummary","tableSummaryHints","combineLatest","timelines","numTableColumns","scrollSyncUpdate","manualSortEnabled","wpTableHoverSync","controller","getTableAndTimelineElement","tableElement","$tableSide","$timelineSide","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","WorkPackageCopyFullViewComponent","successState","wpDisplayListRepresentation","wpDisplayCardRepresentation","WorkPackageViewDisplayRepresentationService","representation","WorkPackageRelationsHierarchyService","childWpId","wpToBecomeChild","args","parent_id","childWorkPackage","parentWorkPackage","GroupSumsBuilder","sum","renderColumns","renderContent","appendFirstLabel","wpEditForm","fixColumns","fromEvent","debounceTime","elem","descriptor","lastOffset","classNameLeftHandle","classNameRightHandle","registerWorkPackageMouseHandler","getRenderInfo","workPackageTimeline","bar","renderer","renderInfo","dateStates","placeholderForEmptyCell","mouseDownStartDay","jBody","getCursorOffsetInDaysFromLeft","leftOffset","getAbsoluteLeftCoordinates","cursorOffsetLeftInPx","createMouseMoveFn","offsetDayCurrent","offsetX","dayUnderCursor","onDaysMoved","assignDateValues","applyDateValues","keyPressFn","handleMouseMoveOnEmptyCell","isLeaf","canMoveDates","displayPlaceholderUnderCursor","onmouseleave","onmousedown","pointerEvents","offsetDayStart","dateForCreate","mouseDownType","onMouseDown","onmousemove","widthInDays","moved","onmouseup","cancelled","disableViewParamsCalculation","noop","resetCursor","cancelChange","stopAndRefresh","onMouseDownEnd","filterUpdatedSince","saveWorkPackage","refreshView","classNameActiveDrag","workPackageMouseDownFn","classNameLeftLabel","classNameRightContainer","classNameRightLabel","classNameLeftHoverLabel","classNameRightHoverLabel","classNameHoverStyle","classNameFarRightLabel","classNameShowOnHover","classNameHideOnHover","WorkPackageCellLabels","center","leftHover","rightHover","withAlternativeLabels","renderers","latestRenderInfo","wpElement","cellRenderer","getMarginLeftOfLeftSide","getMarginLeftOfRightSide","getPaddingLeftForIncomingRelationLines","getPaddingRightForOutgoingRelationLines","cellElement","html","cellContainer","elementShape","isDuplicatedCell","createAndAddLabels","milestone","generic","lazyInit","label_children_derived_duration","dateDisplaysOnMouseMove","ganttChartRowHeight","valueOf","zIndex","applyTypeColor","assignDate","updateLabels","initialStartDate","initialDueDate","projection","forceCursor","visibility","backgroundImage","setElementPositionAndSize","checkForActiveSelectionMode","checkForSpecialDisplaySituations","offsetStart","duration","labelCenter","labelLeft","containerRight","labelRight","labelFarRight","labelHoverLeft","labelHoverRight","bg","selectionMode","minWidth","derivedStartDate","derivedDueDate","previousChildrenDurationBar","childrenDurationBar","childrenDurationHoverContainer","visibleChildren","activeDragNDrop","labelConfiguration","getNormalizedLabels","renderLabel","renderHoverLabels","inHierarchyMode","diamond","initialDate","marginLeft","ri","wpTimeline","cellRenderers","getCellsFor","synchronizeCells","refreshSingleCell","renderInfoFor","currentlyActive","workPackageIdOrder","rowClassIdentifier","wpTableComponent","_viewParameters","cellsRenderer","selectionParams","refreshRequest","collapsedGroupsCellsMap","orderedRows","wpsWithGroupHeaderCell","tableWorkPackage","shouldBeShownInCollapsedGroupHeaders","outerContainer","registerTimeline","commonPipes","timelineState","setupManageCollapsedGroupHeaderCells","isAutoZoom","applyAutoZoomLevel","calculateViewParams","refreshAllCells","refreshCollapsedGroupsHeaderCells","currentWidth","scrollWidth","activateSelectionMode","getParentScrollContainer","nonVisibleDaysLeft","viewPortRight","daysUntilViewPortEnds","resetSelectionMode","currentParams","newParams","getWorkPackagesToCalculateTimelineWidthFrom","subtract","dayCountForMarginLeft","visibleDays","isSame","getFirstDayInViewport","getLastDayInViewport","workPackagesToCalculateWidthFrom","daysSpan","timelineWidthInPx","manageCollapsedGroupHeaderCells","groupsCollapseConfig","tableWorkPackages","refreshAllGroupHeaderCells","collapsedGroupsChange","collapsedGroupsChangeArray","groupsToUpdate","shouldManageCollapsedGroupHeaderCells","createCollapsedGroupHeaderCells","removeCollapsedGroupHeaderCells","keyGroupType","changedGroupId","changedGroupType","changedGroupWpsWithHeaderCellsIds","buildCellsAndRenderOnRow","collapsedGroupKey","wpTypeFunction","workPackagesWithGroupHeaderCell","confirmDialog","confirmDelete","showAnchorRight","isSortable","setAsSingleSortCriteria","addSortCriteria","isGroupable","isCurrentlyGroupedBy","setBy","isFirst","focusColumn","removeColumn","wpTimelineService","workPackageTimelineTableController","onRefreshRequested","innerHeader","renderLabels","activeZoomLevel","renderLabelsDays","renderLabelsWeeks","renderLabelsMonths","renderLabelsQuarters","renderLabelsYears","renderTimeSlices","quarter_number","marginTop","cellCallback","addLabelCell","workPackagePrefix","TimelineRelationElement","belongsToId","timelineGlobalElementCssClassname","newSegment","yPosition","color","workPackagesWithRelations","setupRelationSubscription","wps","relationsForWorkPackage","renderWorkPackagesRelations","workPackageWithRelation","removeRelationElementsForWorkPackage","renderElement","removeAllVisibleElements","renderElements","wpIdsWithRelations","involved","startCells","workPackageCells","endCells","startCell","idxFrom","workPackageIndex","endCell","idxTo","renderRelation","rowFrom","rowTo","canConnectRelations","startX","targetX","directionY","directionX","paddingRight","startLineWith","lastX","timelineStaticElementCssClassname","finishElement","offsetToday","dayProgress","checkForWeekendHighlight","day","gridContainer","paddingTop","WorkPackageWatcherEntryComponent","panelCtrl","deleting","watcher","removeWatcher","groupSumsBuilder","totalSums","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","close_menu","install_menu_logic","drop_down","open_menu","WorkPackageViewHandlerToken","WorkPackageViewHandlerRegistry","factory","eventScope","EVENT","handleEvent","WorkPackageCardViewService","renderedCards","CardClickHandler","handleWorkPackage","wpCardView","CardDblClickHandler","ExternalQueryConfigurationComponent","openConfigurationModal","buildUrlParams","UserActivityComponent","sanitization","wpLinkedActivities","commentService","ngZone","userCanEdit","userCanQuote","focused","label_created_on","label_updated_on","quote_comment","edit_comment","updateCommentText","isComment","isBcfComment","userId","userName","userAvatar","runOutsideAngular","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","boardActions","boardsList","currentBoard$","unnamed_board","action_board","unnamed_list","loadAllPromise","allInScope","reorderWidgets","boardName","addFreeQuery","addInitialColumnsForAction","WorkPackageTypeStatusComponent","v3ErrorIdentifierMultipleErrors","ErrorResource","isMultiErrorMessage","extractMultiError","perAttribute","WorkPackageViewToggleButton","detectView","OpenprojectEditorModule","WorkPackageViewFocusService","focusAfterRender","setFocusAfterRender","withLoadingIndicator","delayStopTime","delayedStop","stop","withDelayedLoadingIndicator","LoadingIndicator","indicatorTemplate","stopper","LoadingIndicatorService","getIndicatorAt","DebouncedEventEmitter","takeUntil$","emitter","debouncer","generatorOrNext","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","WorkPackageSubjectComponent","uiRouterGlobals","uniqueElementIdentifier","WorkPackageNewSplitViewComponent","chartType","WpIsolatedGraphQuerySpaceProviders","JobStatusModal","redirect","redirect_errors","redirect_link","download_starts","click_to_download","downloadHref","listenOnJobStatus","performRequest","continuedStatus","onResponse","handleRedirect","handleDownload","download","statusIcon","iconForStatus","downloadUrl","downloadLink","jobUrl","TimeEntryFormComponent","showWorkPackageField","modifiedEntry","spentOn","wpRequired","workPackageSelected","setCustomFields","entries","keySchema","signalModifiedEntry","paginationService","getCachedPerPage","updateFromObject","OpenProjectFileUploadService","upload","uploadUrl","staticDownloadLocation","uploadSingle","whenFinished","formData","FormData","metadata","reportProgress","promises","Response","PartitionedQuerySpacePageComponent","showToolbar","toolbarButtonComponents","filterAllowed","currentPartition","filterContainerDefinition","showToolbarSaveButton","setPartition","removeTransitionSubscription","isFirstLoad","setupInformationLoadedListener","queryParamListener","unRegisterTitleListener","updateTitle","onQueryUpdated","removeQueryChangeListener","updateTitleName","toolbarDisabled","getStaticName","titleEditingEnabled","shouldUpdateHtmlTitle","visibly","loadFirstPage","getPaginationInfo","additionalLoadingTime","loadCurrentQueryFromParams","changeChangesFromTitle","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","DateDisplayField","showSchedulingMode","schedulingIcon","canOverdue","daysFromToday","isClosed","APIv3FormResource","registerRequestForConfirmation","getPluginContext","services","passwordConfirmationModal","modals","passwordConfirmation","password_confirmation","registerListener","createFieldsetToggleStateLabel","legend","labelClass","toggleLabel","legendLink","setFieldsetToggleState","fieldset","getFieldset","setupToggableFieldsets","fieldsets","contentArea","slideToggle","toggleFieldset","setupServerResponse","upToggle","initMainMenuExpandStatus","firstErrorSpan","focusFirstErroneousField","activateFlashNotice","activateFlashError","ajaxComplete","ajaxSend","csrf_meta_tag","token","setRequestHeader","ajaxStop","addClickEventToAllErrorMessages","resizeTo","error_focus","input_focus","substr","activateFlash","triggerTour","allowInput","augmentedDatePicker","linkElement","hashPos","performAnchorHijacking","pageIsSubmitted","marginBottom","dangerZoneVerification","expectedValue","pageWasEdited","serialize","refreshOnFormChanges","prevScrollPos","currentScrollPos","scrollHeaderOnMobile","URL","demoProjectsAvailable","currentTourPart","sessionStorage","tourCancelled","searchParams","setItem","once","detectOnboardingTour","wasDisabled","checked","vendor","langSelectSwitchData","settingName","newLang","textArea","storedValue","delivery_method","isNone","wasChecked","removeAttr","listenToSettingChanges","func","previewColor","keyup","actualValue","GlobalHelpers","boxes","all_checked","helpers","edition","localStorage","BrowserDetector","hasBodyClass","WpTableConfigurationFiltersTab","columnsLabel","selectedColumns","multiSelectLabel","upsaleRelationColumns","upsaleRelationColumnsLink","replaceIfComplete","helpTexts","helpText","editText","attributeHelpTextSelector","attributeHelpTexts","exists","open_dialog","helpTextId","attributeScope","additionalLabel","requireById","NotificationComponent","uploadCount","checkedClassName","UiStateLinkBuilder","webpackEmptyAsyncContext","timeoutAfter","nextValue","autoHidePopups","createNotification","createAttachmentUploadNotification","QueryFilterResource","SchemaCacheService","stateKey","getSchemaHref","hrefs","OpTitleService","getTitle","titleParts","setTitle","activeFieldContainerClassName","activeFieldClassName","EditForm","errorsPerAttribute","renderField","showEditingBlockedError","requireVisible","activateWhenNeeded","openFields","handleSubmissionErrors","resetChange","handleErroneousAttributes","erroneousAttributes","getInvolvedAttributes","getMessagesPerAttribute","setErrorsForFields","erroneousFields","focusOnFirstError","loadFormAndCheck","activateField","prototype","padding","number","toFixed","precision","decimalAdjust","isFunction","isSet","isString","isNumber","isBoolean","exp","NaN","lazyEvaluate","dest","DATE","day_names","abbr_day_names","month_names","abbr_month_names","meridian","NUMBER_FORMAT","delimiter","strip_insignificant_zeros","CURRENCY_FORMAT","sign_first","PERCENTAGE_FORMAT","SIZE_UNITS","DEFAULT_OPTIONS","defaultLocale","defaultSeparator","fallbacks","translations","missingBehaviour","missingTranslationPrefix","initializeOptions","locales","localeParts","firstFallback","secondFallback","nullableFallbackLocale","pluralization","currentLocale","scopes","fullScope","getFullScope","pluralizationLookupWithoutFallback","pluralizerKey","pluralizerKeys","pluralizer","pluralizationLookup","am","pm","prepareOptions","arguments","createTranslationOptions","translationOptions","translate","translation","optionsWithoutDefault","translationOption","interpolate","pluralize","missingTranslation","regex","nullPlaceholder","missingPlaceholder","s","p1","p2","toNumber","formattedNumber","negative","buffer","sign","toCurrency","localize","toPercentage","localizedValue","toTime","convertedDate","fraction","UTC","setTime","$1","$2","$3","$6","$4","$5","strftime","meridianOptions","getTime","weekDay","getDay","getDate","year","getFullYear","month","getMonth","getHours","hour12","secs","getSeconds","mins","getMinutes","getTimezoneOffset","absOffsetHours","absOffsetMinutes","timezoneoffset","dateString","toHumanSize","kb","iterations","obj1","obj2","p","WorkPackagesGridComponent","wpTableHighlight","wpList","showResizer","resizerClass","resizerStorageKey","gridOrientation","WorkPackageFilterContainerComponent","visible$","isAvailable","OpDatePickerComponent","initializeDatepicker","datePickerInstance","inputIsValidDate","relatedTarget","calendarContainer","inputElement","dateInput","initialValue","selectedDates","dateStr","onKeyDown","parseISODate","toDate","openOnClick","onInputChange","StatusResource","WorkPackageViewSelectionService","selectedWorkPackageIds","activeRowIndex","_emptyState","wpState","selectionCount","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","OpenProjectDirectFileUploadService","getDirectUploadFormFrom","uploadToExternal","finishUpload","completeUpload","fileSize","contentType","form_fields","WorkPackageFilterValues","excluded","handlers","applyFirstValue","setToNull","filterAlreadyApplied","mapFilterToAttribute","setValueFor","findSpecialValue","isLoggedIn","fromSelfLink","BannersService","_banners","bannersVisible","bannersNotVisible","callMaybe","WorkPackageListViewComponent","wpViewFilters","showTableView","tableInformationLoaded","showResultOverlay$","incomplete$","wpTableConfiguration","updateViewRepresentation","selectedRow","selectedCard","previousSibling","valueFromQuery","openInFullView","handleWorkPackageClicked","ckeditorAugmentedTextareaSelector","CkeditorAugmentedTextareaComponent","Notifications","isEditing","textareaSelector","formElement","wrappedTextArea","initialContent","$attachmentsElement","setupAttachmentAddedCallback","setupAttachmentRemovalSignal","ckEditorInstance","getRawData","addUploadedAttachmentsToForm","setLabel","model","removedUrls","downloadLocation","fire","textareaId","substring","ckContent","maxValue","toArray","addedAttachments","setup","markEdited","WorkPackageAutocompleterComponent","changeModel","opened","closed","keyPressed","WorkPackageOverviewTabComponent","WorkPackageLinkedResourceCache","cacheDurationInSeconds","isCached","WpTableConfigurationTimelinesTab","availableZoomLevels","display_timelines","display_timelines_hint","zoom","weeks","quarters","years","auto","availableLabels","allPropertyColumns","OpQueryConfigurationLocalsToken","WorkPackageCardViewComponent","wpViewOrder","cardDragDrop","cardsRemovable","showEmptyResultsBox","isResultEmpty","addNewCard","inReference","referenceOutputs","setReferenceMode","onReferenced","updateRenderedCardsValues","registerDragAndDrop","registry","onCardSaved","CollectionResource","WorkPackageViewPageComponent","inputs","stateName$","button_settings","WpRelationInlineAddExistingComponent","buildQueryFilters","newRelationId","addExisting","buildV3GetFilterIdFromFilter","buildV3GetFilters","HalResourceSortingService","halType","sortingProperty","States","posts","QueryAvailableDataStates","GlobalStateChanges","camelCase","backlogsPageComponentSelector","BacklogsPageComponent","WorkPackageBaseResource","truncateSubject","truncate","otherWorkPackage","resourceNames","linked","wpCacheService","WorkPackageResource","TimeEntryWorkPackageAutocompleterComponent","modeSwitch","errorNotificationHandler","DebouncedRequestSwitchmap","requestHandler","errorHandler","preFilterNull","debounceMs","loading$","lastResult","output$","until","SimpleResourceCollection","SimpleResource","attachmentsSelector","AttachmentsComponent","allowUploading","DraggableAutocompleteComponent","dragula","_selected","updateAvailableOptions","columnsGroup","createGroup","drag","drop","autoscroll","drake","dragging","clearModel","ifcModels","ifc_models","_error","projectData","models","viewerContent","modelsLoaded","shown_models","viewerConfigs","saoEnabled","_projectId","modelId","attachmentId","metadata_attachment_ids","utils","loadJSON","attachmentContentPath","xkt_attachment_ids","loadArraybuffer","shouldShowViewer","viewerVisible$","BehaviorSubject","XeokitViewerModule","server","viewerUI","BIMViewer","alert","objectName","objectType","objectId","loadProject","viewer","_viewer","setKeyboardEnabled","saveBCFViewpoint","spacesVisible","bitmaps","routeWithViewer","viewpointsService","getViewPoint$","loadBCFViewpoint","bimDetailsPath","TimezoneService","setupLocale","datetime","isTimezoneSet","local","tz","getTimeFormat","utc","getDateFormat","today","datetimeString","durationString","asHours","toHours","dateTime","dateFormatPresent","timeFormatPresent","timeFormat","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","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","progressBar","progressPercentage","innerText","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","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","wpProjectId","topicUUID$","setBcfTopic$","viewpoint$","viewerBridge","getViewpoint$","topicUUID","topicHref","bcfTopic","createBcfTopic$","wpPayload","convertBCF","guid","VersionAutocompleterComponent","openDirectly","onCreate","canCreateNewActionElements","createAllowed","createNewVersion","getVersionPayload","closeSelect","definingProject","rowGroupClassName","collapsedRowClass","WorkPackageGroupToggleDropdownMenuDirective","wpViewCollapsedGroups","setAllGroupsCollapseStateTo","APIv3ResourcePath","APIv3GettableResource","APIv3ResourceCollection","ExternalQueryConfigurationService","_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","cacheKey","cacheValue","fetchAllowedValueQuery","allowedValuesFilter","addValue","selectedOption","emptyOption","getEmptyOption","isRequired","currentValueInvalid","requestFocus","nullOption","openAutocompleteSelectField","findValueOption","_selectedOption","adjustPosition","valueOption","sortValuesByName","nameA","nameB","buildSelectedOption","checkCurrentValueValidity","filterParams","prefix","onValueSelected","projectStatusCodeCssClass","ensureDefaultCode","projectStatusI18n","_availableStatusCodes","currentStatusCode","availableStatuses","recentWorkPackageIds","timeEntry","sortValuesByRecentIds","text_no_start_date","text_no_due_date","showDatePickerModal","currentStartDate","currentDueDate","toLocaleString","useGrouping","maximumFractionDigits","bootstrapOptionalEmbeddable","unescape","UNESCAPED_EXPRESSION","ESCAPED_EXPRESSION","derivedText","formattedDuration","derivedPropertyName","derivedValue","actual","renderActual","derived","renderDerived","derivedValueString","actualPresent","valueEmpty","derivedEmpty","translatedValue","linkTitle","logTime","wpID","projectTimeEntriesPath","appendTimelogLink","timelogElement","showTimelogWidget","addHighlight","hlClass","divContainer","renderAbridgedValues","dots","uiStateBuilder","linkToShow","bulb","pulldown","OpenprojectFieldsModule","editFieldService","selectAutocompleterRegisterService","addSpecificFieldType","FocusDirective","SchemaDependencyResource","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","route","preferListOverSplit","goToOtherState","backRoute","currentDetailsSubState","isDetailsState","goBackToDetailsState","goBackNotToDetailsState","goBackToPreviousState","paramsFromCopy","_backRoute","TableDragActionService","shadowElement","backToDefault","determineParent","relationHierarchyService","nextElementSibling","droppedIntoGroup","relationRoot","findRelationRowRoot","previousWpId","isHiearchyRoot","loadParentOfWP","inGroup","isRoot","skipDroppedIntoGroup","elementGroups","previousGroups","nextGroups","isLastElementOfGroup","elementAlreadyBelongsToGroup","elementGroup","groupedAttribute","groupedValue","getValueForGroup","groupHeader","applies","ImageHelpers","imagePath","tdClassName","editCellContainer","CellBuilder","displayElement","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","InjectField","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","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","Apiv3GridForm","RelationStateGroup","WorkPackageRelationsService","relationsStateValue","loadInvolved","accumulateRelationsFromInvolved","removeFromStates","insertIntoStates","relevant","isInvolved","GridBaseResource","widgetResource","GridResource","WorkPackageTimelineButtonComponent","minZoomLevel","maxZoomLevel","isMaxLevel","isMinLevel","zoomIn","zoomOut","zoomAuto","updateZoomWithDelta","toggleTimeline","enableAutozoom","ScrollableTabsComponent","currentTabId","hideLeftButton","hideRightButton","pane","scrollPane","determineScrollButtonVisibility","scrollIntoVisibleArea","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","SchemaProxy","proxyMethod","__","argumentsList","WorkPackageCommentComponent","editTitle","cancelTitle","fieldLabel","canAddComment","showAbove","quote","commentContainer","scrollToBottom","wpDetails","createComment","scrollableContainer","scrollHeight","bcfPathHelper","snapshotPath","BcfDetectorService","authorizationMap","extension","authorized$","bcfAuthorization","bcf","add_viewpoint","show_viewpoint","delete_viewpoint","text_are_you_sure","notice_successful_create","notice_successful_delete","galleryOptions","thumbnailsColumns","thumbnailsAutoHide","thumbnailSize","imageAnimation","previewAnimation","previewCloseOnEsc","previewKeyboardNavigation","imageSize","imageArrowsAutoHide","thumbnailsMargin","thumbnailMargin","previewDownload","previewCloseOnClick","arrowPrevIcon","arrowNextIcon","closeIcon","downloadIcon","thumbnailActions","breakpoint","imagePercent","thumbnailsPercent","galleryImages","viewAllowed","viewerVisible","observeChanges","refreshViewpoints","isAllowedTo","loadViewpointFromRoute","snapshotURL","setViewpointsOnGallery","showViewpoint","deleteViewPoint$","gallery","saveViewpoint$","showIndex","selectViewpointInGallery","titleText","deleteViewpoint","setThumbnailProperties","small","medium","big","viewpointCount","dynamicThumbnailHeight","galleryViewpoints","observeCreation","observables","viewPointItem","forkJoin","newViewpoint","snapshot","snapshot_data","revitMessageReceivedSource","trackingIdNumber","revitMessageReceived$","RevitBridge","hookUpRevitListener","trackingId","newTrackingId","sendMessageToRevit","messageType","viewpointJson","messagePayload","snapshot_type","jsonPayload","sendMessageToOpenProject","messageString","bootstrapCalled","isBimEdition","navigator","userAgent","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","reloadWorkPackageAndClose","setModifiedEntry","createNewTimeEntry","OpenprojectAttachmentsModule","indicatorCollapsedClass","additionalHierarchyRowClassName","SingleHierarchyRowBuilder","leaf","appendHierarchyIndicator","hierarchyLevel","hierarchyElement","buildHierarchyIndicator","hierarchyIndicator","indicatorWidth","indentation","BcfImportButtonComponent","import","import_hover","projectImportIssuePath","TimeEntryBaseModal","areYouSure","formInFlight","UserResource","active_user_statuses","boardsMenuSelector","BoardsMenuComponent","boardService","trackById","currentProjectIdentifier","boards$","focusBackArrow","loadAllBoards","selectedBoardId","DatePickerModalHelper","setHours","firstDate","secondDate","parsedDate1","parsedDate2","currentlyActivatedDateField","datePicker","setDatepickerRestrictions","enforceDate","currentMonth","currentYear","setDates","redraw","disableFunction","isStateOfCurrentActivatedField","monthContainer","highlightRangeInSingleMonth","selectedElements","selectRangeFromUntil","datepickerShowsDate","firstDay","datepickerIsInDateRange","selectedElement","toDateString","firstDayOfMonthElement","firstDayOfMonth","nextUntil","datepickerHelper","manualScheduling","endDate","isParent","isSwitchedFromManualToAutomatic","singleDate","htmlId","isWritable","setCurrentActivatedField","initialActivatedField","isSchedulable","showDateSelection","onDataChange","removeDateSelection","isSavable","mappedDate","enforceManualChangesToDatepicker","validDate","setRangeClasses","showMonths","inline","handleDatePickerChange","onMonthChange","onYearChange","toggleField","setRangeClassesAndToggleActiveField","setDateAndToggleActiveField","areDatesEqual","otherDateIndex","overwriteDatePickerWithNewDates","sortDates","newDate","forceDatePickerUpdate","toggleCurrentActivatedField","output","changeSchedulingMode","WpTableConfigurationHighlightingTab","entireRowMode","lastEntireRowAttribute","availableInlineHighlightedAttributes","availableRowHighlightedAttributes","highlighting_mode","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","export_hover","exportLink","projectExportIssuesPath","showDelayedExport","field_description","confirm_button","password","passwordValuePresent","passwordConfirmationField","modalClassName","modalBody","sanitizer","string","sanitize","HTML","_knownHookNames","externalQueryConfiguration","externalRelationQueryConfiguration","htmlSanitizeService","ckEditorPreview","pathHelperService","dynamicContent","run","BudgetResource","CostSubformAugmentService","templateEl","template","PlannedCostsFormAugment","objId","objName","makeEditable","edit_and_focus","currency","getCurrency","insertAfter","CostBudgetSubformAugmentService","row_identifier","buildRefreshRequest","HTMLInputElement","element_id","fixed_date","extendFieldType","listen","initializeCostsPlugin","loadIfNecessary","showCosts","renderCostAsLink","renderCostAsText","costType","spentUnits","addSeparator","workPackageSingleContextMenu","workPackageTableContextMenu","resizeImage","maxSize","canvas","ctx","getContext","drawImage","dataUrl","toDataURL","dataURItoBlob","dataURI","bytes","atob","mime","ia","Uint8Array","Blob","resizeFile","reader","FileReader","readerEvent","readAsDataURL","fileInvalid","label_choose_avatar","upload_instructions","error_too_large","wrong_file_format","button_update","uploading","_evt","avatarFilePicker","dataURL","blob","avatarFile","avatarPreviewUrl","progress","onFilePickerChanged","uploadAvatar","DocumentResource","LinkedPluginsModule","GridArea","storedGuid","newGuid","s4","otherArea","rowOverlaps","columnOverlaps","sink","isRow","numColumns","numRows","mousedOverArea","$mousedOverArea","helpMode","rowCount","buildAreas","area","unusedRows","widgetAreas","removeRow","unusedColumns","gridAreas","buildGridAreas","gridGaps","buildGridGaps","gridAreaIds","buildGridAreaIds","buildGridWidgetAreas","persist","writeAreaChangesToWidgets","saveGrid","payloadWidget","w","widgetResources","isSingleCell","scrollIntoViewIfNeeded","updatedGrid","assignAreasWidget","newGrid","takenIds","newWidget","buildGridAreasRow","buildGridGapRow","writeAreaChangeToWidget","excludeRow","movedWidgets","rowWidgets","moveSubsequentRowWidgets","excludeColumn","columnWidgets","moveSubsequentColumnWidgets","ignoredArea","gridResource","isGap","removedWidget","cleanupUnusedAreas","rebuildAndPersist","subsequentWidget","layout","onRenamed","renamed","GridRemoveWidgetService","removeWidget","menuItemList","removeItem","resizeSubject","static","alreadyLoaded","ucCalendar","getApi","addTooltip","toWPFullView","resizeObserver","ResizeObserver","updateSize","setupWorkPackagesListener","initializeCalendar","fetchInfo","successCallback","failureCallback","updateTimeframe","calendarOptions","fixedWeekCount","calendarEventsFunction","plugins","initialView","calendarHeight","headerToolbar","buildHeader","filtersEmpty","defaultQueryProps","datesIntervalFilter","tooltip","tooltipContentString","extendedProps","track","removeTooltip","history","pushState","inherit","heightElement","topOfCalendar","topOfHeightElement","calendarElement","calendarDate","calendarUnit","lower","changeView","setCalendarsDate","refetchEvents","warnOnTooManyResults","mapToCalendarEvents","eventDate","exclusiveEnd","allDay","tooManyResultsText","MAX_DISPLAYED","props","sanitizedValue","toStringMethod","renameWidget","displayedDays","firstDayOffset","momentFirstDayOffset","localeData","onConfigured","configureItem","destroyedEntry","createChangeset","TIME_ENTRY_CLASS_NAME","ADD_ENTRY_CLASS_NAME","ADD_ENTRY_PROHIBITED_CLASS_NAME","timeEntryEdit","timeEntryCreate","minHour","maxHour","labelIntervalHours","scaleRatio","memoizedCreateAllowed","hiddenDays","contentHeight","slotEventOverlap","slotLabelInterval","slotLabelFormat","allDaySlot","displayEventTime","slotMinTime","slotMaxTime","eventOverlap","stillEvent","setHiddenDays","alterEventEntry","beforeEventRemove","dispatchEventClick","moveEvent","fetchTimeEntries","buildEntries","memoizedTimeEntries","dmFilters","createTimeEntry","setRatio","buildTimeEntryEntries","buildAuxEntries","dateSums","calculateDateSums","maxHours","oldRatio","smallerSuitableRatio","hoursDistribution","entryName","calendarEntries","m","sumEntry","addEntry","startEditable","backgroundColor","borderColor","rendering","formatNumber","editEvent","addEvent","modificationAction","updateEventSet","revert","foundIndex","appendAddIcon","appendSum","prependDuration","appendFadeout","addIcon","fadeout","hslaStart","toHsla","hslaEnd","workPackageName","divisor","cdr","updateConfiguration","updateEntries","GridWidgetsService","Hook","registeredWidgets","registration","OpenprojectTimeEntriesModule","CALENDAR_ROUTES","OpenprojectCalendarModule","forChild","domSanitizer","entriesLoaded","documentsUrl","orders","project_id","addedBy","newsAuthorName","age","newsCreated","authorLink","newsAuthorPath","newsDmParams","setupNews","newsPath","myPageForm","WpGraphConfigurationSettingsTab","tabInner","WpGraphConfigurationFiltersTab","WpGraphConfiguration","chartOptions","is_public","_forms","persistChanges","reloadQueries","createInitial","queryCreationParams","queryPromises","queryParam","formFor","_configuration","_formsPromise","loadForms","queryTabs","formPromises","graphConfiguration","configurationComponent","WorkPackageEmbeddedGraphComponent","chartHeight","chartLabels","chartData","datasets","setChartOptions","updateChartData","uniqLabels","array","labelCountMaps","countMap","setHeight","responsive","maintainAspectRatio","datalabels","align","chartTypeDefaults","scales","setChartAxesValues","inputChartOptions","changeableValuesAxis","stacked","ticks","constantValuesAxis","yAxes","xAxes","initializeConfiguration","loadQueriesInitially","persistAndReload","repaint","ensureQueryAndLoad","updateGraph","query$","skip","ensureFormAndSaveQuery","initializationProps","onResourceChanged","QuerySpacedTabComponent","wpGraphConfiguration","initializeQuerySpace","group_by","chart_type","currentChartType","initializeAvailableGroups","initializeAvailableChartType","availableChartTypes","graphConfigurationService","displayModeSingle","availableGroupBy","additionalFilter","setQueryProps","graphParams","sortedDatasets","propsBoth","propsOpen","propsClosed","sortingArray","baseProps","subprojectId","displaySingle","embeddedGraphSingle","embeddedGraphMulti","project$","inEdit","initializeChangeset","valueChanged$","rawText","textValue","resourceSource","canAddAttachments","schemaSource","setupVariables","newText","currentRawText","clickedElementIsLinkWithinDisplayContainer","textEmpty","initial","memorizeRawText","reinitialize","memorizeCustomText","customText","htmlText","loadAndRender","loadProjectSchema","loadedEntry","timeEntryEditService","changedEntry","oldEntryIndex","newEntries","anEntry","sumsByDateSpent","sortedEntries","currentDate","projectListParams","viewAll","entriesByRoles","membersAddable","listMembersParams","partitionEntriesByRole","sortUsersByName","totalMembers","listAvailableProjectsParams","projectMembershipsPath","principal","membership","roles","role","OpenprojectGridsModule","defaultColumns","assignedFilters","assignedProps","accountableFilters","accountableProps","createdFilters","createdProps","watchedFilters","watchedProps","registerWidgets","appBaseSelector","ApplicationBaseComponent","OPENPROJECT_ROUTES","abstract","squash","flash_message","dynamic","loadChildren","OpenprojectBoardsModule","OpenprojectIFCModelsModule","OpenprojectBacklogsModule","OpenprojectReportingModule","OpenProjectJobStatusModule","bodyClass","cssClass","updateMenuItem","menuItemTitle","stateService","wpBase","onEnter","onExit","router","start_onboarding_tour","paramsCopy","sync","profiler","MiniProfiler","pageTransition","pathname","pathWithSearch","setIfFirst","initializeUiRouterListeners","forRoot","useHash","uiRouter","urlService","strictMode","encode","decode","equals","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","emptyTypeGroup","Gon","externalRelationQuery","drag_to_activate","label_group","new_group","label_inactive","custom_field","add_group","add_table","inactives","no_filter_query","noFilterQuery","submitted","updateHiddenFields","groupsDrake","attributeDrake","activeGroups","inactiveAttributes","updateInactives","newGroup","editQuery","hiddenField","emptyGroup","resetToDefault","addGroupAndOpenQuery","onValueChange","editedName","showEEOnlyHint","leaveEditingMode","deleteGroup","removeAttribute","rename","edit_query","EditableQueryPropsComponent","externalQuery","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","newSearchTerm","newProjectScope","new_features_image","newFeatures","descriptionNewFeatures","learnAbout","i18nBase","isStandardEdition","translated","bypassSecurityTrustResourceUrl","i18nPrefix","list_styling_class","bcf_api_link","GlobalSearchWorkPackagesEntryComponent","PersistentToggleComponent","isHidden","$targetNotification","getTargetNotification","isNowHidden","displayed","sections","removeHiddenOnSubmit","section","HideSectionLinkComponent","hideSectionService","sectionName","hideSection","ShowSectionDropdownComponent","HideSectionService","optValue","hideSecWithName","prev","trackByKey","selectable","AutocompleteSelectDecorationComponent","multiselect","labelForId","syncInputFieldName","updateSelection","removeCurrentSyncedFields","createSyncedField","gonTabs","CopyToClipboardDirective","clickTarget","clipboardTarget","supported","queryCommandSupported","execCommand","addNotification","ConfirmFormSubmitController","$form","openConfirmationDialog","markable","setMarkedOption","all_projects","current_project","current_project_and_all_descendants","search_dots","close_search","toggleTopMenuClass","unregister","btn","toggleMobileSearch","submitNonEmptySearch","wpPath","openCloseMenu","searchedTerm","selectedItem","followSelectedItem","searchInScope","currentScope","statusId","followItem","hashFreeQuery","queryWithoutHash","fetchSearchResults","searchResultsToOptions","filterBySubjectOrId","searchItems","searchOptions","detailedSearchOptions","suggestion","itemsList","markItem","selectedItems","forcePageLoad","isAfterSearch","replaceState","submitSearch","serviceScope","unregisterGlobalListener","onFocusOut","onEnterBeforeResultsLoaded","clearSearch","CollapsibleSectionComponent","sectionTitle","sectionBody","EnterpriseBannerBootstrapComponent","textMessage","linkMessage","referrer","LazyLoadedAutocompleter","_renderLazyMenu","pageElements","maxItemsPerPage","shownHeight","_pages","_repositionMenu","_resizeMenu","renderItem","mark","pages","_renderMenuPage","scroll","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","keydown","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","timeEntryId","editTimeEntry","deleteTimeEntry","not_found","cache$","loadWorkPackage","DisplayFieldComponent","containerType","getDisplayFieldInstance","displayClass","displayFieldContext","resourceLoader","invalid_attribute","hostTitle","markError","attributeFromLocalizedName","StringHelpers","capitalize","loadResourceAttribute","detailed","workPackage$","globalDynamicComponents","OpenprojectMembersModule","OpenprojectEnterpriseModule","wrapElement","activationLink","activationSelector","iframeUrl","appendIframe","subdom","iframe","OpenprojectAugmentingModule","modalWrapper","pathScript","setupListener","loadRequiredScripts","RevitAddInSettingsButtonService","labelText","groupLabelText","addUserMenuItem","addLoginMenuItem","userMenu","goToSettings","loginModal","loginMenuItem","bootstrapOptionalDocument","_injector","PreviewTrigger","mainMenuNavigationService","keyboardShortcuts","contextCallbacks","messageStack","sentryConfigured","sentryElement","Sentry","dsn","debug","ignoreErrors","beforeSend","filterEvent","sentryLoaded","client","configureScope","setupContext","severity","handleOfflineMessage","withScope","fromString","callbacks","hostname","meta","enableReactiveStatesLogging","disableReactiveStatesLogging","platformRef","WorkPackageViewBaseService","combinedRaw","pristine","WorkPackageQueryStateService"],"mappings":"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OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,cAAe,CACd,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,WAAY,CACX,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,UAAW,CACV,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,aAAc,CACb,OACA,KAED,cAAe,CACd,OACA,MAGF,SAASC,EAAoBC,GAC5B,IAAIC,EAAoBC,EAAEJ,EAAKE,GAC9B,OAAOG,QAAQC,UAAUC,MAAK,WAC7B,IAAInD,EAAI,IAAIoD,MAAM,uBAAyBN,EAAM,KAEjD,MADA9C,EAAEqD,KAAO,mBACHrD,KAIR,IAAIsD,EAAMV,EAAIE,GAAMlH,EAAK0H,EAAI,GAC7B,OAAOP,EAAoB/C,EAAEsD,EAAI,IAAIH,MAAK,WACzC,OAAOJ,EAAoBjO,EAAE8G,EAAI,MAGnCiH,EAAoBU,KAAO,WAC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GAAKA,EAAE78D,KACpF,YAAI6+B,GAAQA,EAAKzzB,OAAOsoB,KAASA,EAAI3P,kBAGvC,KAAA+4B,uBAAyC,YAAOj9C,KAAK+8D,qBAAsBC,GAAKA,EAAE78D,KAChF,YAAI6+B,GAAQA,EAAK9vB,IAAI2kB,GAAOA,EAAI3P,cAAe7B,eAIjD,KAAA46C,qBAAuB,IAAI,IAG3B,KAAA73D,+BAAiC,cAGjC,KAAAa,YAAc,e,sCA7CH42D,I,yBAAAA,EAAkB,QAAlBA,EAAkB,a,kCCX/B,IAAYK,EAAZ,2CAAYA,GACV,6BACA,iBACA,sBACA,sBACA,oBACA,kBACA,sBACA,8BACA,wBACA,sBACA,0BACA,8BACA,kBACA,oBACA,gCACA,4BACA,kCACA,gCACA,wBACA,wBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,8BACA,gCACA,wBACA,4BACA,4BACA,4BACA,4BACA,6BACA,6BACA,6BACA,6BACA,6BACA,6BACA,6BACA,mBACA,6BACA,2BACA,yBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,mBACA,mBACA,mBACA,6BACA,mCACA,+BACA,yBACA,uBACA,qBACA,yBACA,uCACA,qCACA,qCACA,iCACA,uCACA,qCAnGF,CAAYA,MAAQ,M,kCC4BpB,0EAMO,MAAMC,UAAkC,IAE7C,YAAmBv6D,GACjB9C,MAAM8C,GAGD,eAAeiB,GACpB,QAASA,EAAMw2B,KAGV,WAAWx2B,GAChB7D,KAAK+xC,cAAc/tC,WAAWH,EAAMw2B,MAG/B,WAAWx2B,GAChB,OAAOA,EAAMw2B,OAASr6B,KAAK48B,UAGtB,aAAa/4B,GAElB,OADAA,EAAMw2B,KAAOr6B,KAAK48B,WACX,EAGF,SACL58B,KAAKwT,aAAaxP,UAAUhE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,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,gBAAiB,OACjB,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,UAAW,OACX,aAAc,OACd,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,U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D,eAAgB,CACf,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,uBAAwB,CACvB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,EACA,EACA,IAED,uBAAwB,CACvB,OACA,EACA,IAED,aAAc,CACb,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,EACA,EACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,GAED,yCAA0C,CACzC,OACA,EACA,EACA,IAED,uBAAwB,CACvB,OACA,EACA,GAED,iBAAkB,CACjB,OACA,EACA,IAED,iCAAkC,CACjC,OACA,EACA,EACA,EACA,EACA,IAED,2BAA4B,CAC3B,OACA,EACA,EACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,yBAA0B,CACzB,OACA,EACA,GAED,+BAAgC,CAC/B,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,yBAA0B,CACzB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,EACA,IAED,yBAA0B,CACzB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,aAAc,CACb,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,EACA,EACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,KAED,6BAA8B,CAC7B,OACA,EACA,KAED,yBAA0B,CACzB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,EACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,GAED,WAAY,CACX,OACA,EACA,KAED,WAAY,CACX,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,GAED,iBAAkB,CACjB,OACA,EACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,KAED,mBAAoB,CACnB,OACA,EACA,KAED,mBAAoB,CACnB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,EACA,EACA,EACA,IAED,2BAA4B,CAC3B,OACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,EACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,KAED,+BAAgC,CAC/B,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,uBAAwB,CACvB,OACA,EACA,KAED,6BAA8B,CAC7B,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,uBAAwB,CACvB,OACA,EACA,EACA,EACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,KAED,yBAA0B,CACzB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,EACA,KAED,aAAc,CACb,OACA,EACA,KAED,yBAA0B,CACzB,OACA,EACA,KAED,yBAA0B,CACzB,OACA,EACA,KAED,uBAAwB,CACvB,OACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,EACA,EACA,GACA,EACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED,eAAgB,CACf,OACA,EACA,KAED,qBAAsB,CACrB,OACA,EACA,KAED,mBAAoB,CACnB,OACA,EACA,KAED,yCAA0C,CACzC,OACA,EACA,EACA,KAED,iBAAkB,CACjB,OACA,EACA,GAED,eAAgB,CACf,OACA,EACA,MAGF,SAASC,EAAoBC,GAC5B,IAAIC,EAAoBC,EAAEJ,EAAKE,GAC9B,OAAOG,QAAQC,UAAUC,MAAK,WAC7B,IAAInD,EAAI,IAAIoD,MAAM,uBAAyBN,EAAM,KAEjD,MADA9C,EAAEqD,KAAO,mBACHrD,KAIR,IAAIsD,EAAMV,EAAIE,GAAMlH,EAAK0H,EAAI,GAC7B,OAAOL,QAAQu0B,IAAIl0B,EAAI8U,MAAM,GAAGxV,IAAIG,EAAoB/C,IAAImD,MAAK,WAChE,OAAOJ,EAAoBjO,EAAE8G,EAAI,MAGnCiH,EAAoBU,KAAO,WAC1B,OAAOC,OAAOD,KAAKX,IAEpBC,EAAoBjH,GAAK,OACzB6H,EAAOC,QAAUb,G,kCCvpBjB,kCAAO,MAAM89E,EAAiC,CAC5C,CACEtrF,IAAK,WACL4kC,KAAM,UACNhpB,SAAU,eAEZ,CACE5b,IAAK,iBACLN,KAAM,YACNklC,KAAM,OACNhpB,SAAU,eAEZ,CACE5b,IAAK,OACL4kC,KAAM,OACNhpB,SAAU,eAEZ,CACE5b,IAAK,SACL4kC,KAAM,SACNhpB,SAAU,eAEZ,CACE5b,IAAK,aACL4kC,KAAM,MACNhpB,SAAU,eAEZ,CACE5b,IAAK,cACL4kC,KAAM,OACNhpB,SAAU,iB,kCCFd,kDAEO,MAAM2vE,UAAiC,IAA9C,c,oBACE,KAAAt1E,KAAO,CACL4X,YAAa,CACXxF,UAAWhqB,KAAKU,KAAKU,EAAE,0BACvB+oB,QAASnqB,KAAKU,KAAKU,EAAE,0BAIlB,OAAOwuB,EAAqBC,GACjCD,EAAQmE,UAAY,GAEpB,IAAIo5D,EAAmBntF,KAAKotF,uBAAuB,aAC/CC,EAAiBrtF,KAAKotF,uBAAuB,WAE7CE,EAAYpiF,SAASoF,cAAc,QACvCg9E,EAAU/7E,YAAc,MAExBqe,EAAQve,YAAY87E,GACpBv9D,EAAQve,YAAYi8E,GACpB19D,EAAQve,YAAYg8E,GAGd,uBAAuBpjE,GAC7B,IAAIsjE,EAAcriF,SAASoF,cAAc,QACrCk9E,EAAmB,IAAI,IAAiBvjE,EAAMjqB,KAAKovB,SACnDxX,EAAO5X,KAAKud,SAAS0M,GACvBjqB,KAAK2a,gBAAgB8yE,cAAcztF,KAAKud,SAAS0M,IACjDjqB,KAAK4X,KAAK4X,YAAYvF,GAKxB,OAHAujE,EAAiBrjB,MAAMnqE,KAAKud,SAAUvd,KAAKwC,QAC3CgrF,EAAiBjsE,OAAOgsE,EAAa31E,GAE9B21E,K,iOC3DL,eACE,eAEI,8DAEJ,OACF,O,uBAFM,0CC8BL,MAAM,UAAkC,IAqB7C,YAAqB/sF,EAC0BsR,EAC1BjS,EACAa,GAEnBZ,MAAMgS,EAAQjS,EAAOW,GALF,KAAAA,aAC0B,KAAAsR,SAC1B,KAAAjS,QACA,KAAAa,OAtBd,KAAA22C,SAAU,EACV,KAAAgQ,WAAY,EACZ,KAAAJ,eAAgB,EAChB,KAAAE,qBAAsB,EAGtB,KAAA7N,KAAc,GAId,KAAA1hC,KAAW,CAChB0K,MAAOtiB,KAAKU,KAAKU,EAAE,4CACnBssF,KAAM1tF,KAAKU,KAAKU,EAAE,0CAClBk4C,KAAMt5C,KAAKU,KAAKU,EAAE,0CAClBusF,YAAa3tF,KAAKU,KAAKU,EAAE,kBACzBwlD,cAAe5mD,KAAKU,KAAKU,EAAE,oBAC3BylD,YAAa7mD,KAAKU,KAAKU,EAAE,yBASzBpB,KAAKoqF,aAAepqF,KAAKs5C,KAAOt5C,KAAK8R,OAAOwnC,KAKvC,cAAcz4C,GACnBb,KAAKq3C,SAAU,EACfr3C,KAAKs5C,KAAOt5C,KAAKoqF,aACjBpqF,KAAKsnD,QAAQzmD,GAGf,kBACEb,KAAK4tF,kBAAkB9mF,cAAcyG,S,sCAvC5B,GAAyB,eAsBhB,KAAkB,sB,uBAtB3B,EAAyB,qD,OAAA,K,+hCDrCtC,gBACE,gBACE,gBACE,oBAOA,eACF,OAEA,gBACE,iBAA6B,kCAAU,EAAAsgF,cAAA,MACrC,qBACE,mBACA,gBACE,oBAKA,kBACE,kBACE,uBAOI,mEAPJ,OASF,OACF,OACA,eACA,aAAG,eAAK,2CAA+B,OAAM,OAC/C,OACF,OACF,OACF,OACA,kBACE,qBACQ,iCAAS,EAAAvmC,QAAA,MAIjB,OACA,qBACQ,iCAAS,EAAAumC,cAAA,MAIjB,OACF,OACF,OACF,Q,MAtD8C,iCAOA,yCAM5B,wCAIF,wCAWI,qCAKL,wCAUD,iDACA,mCAKA,+CACA,mC,iHElDR,eACE,eAEI,8DAEJ,OACF,O,uBAFM,0CC8BL,MAAM,UAA4B,IA8BvC,YAAqBrtF,EAC0BsR,EAC1BjS,EACAa,GAEnBZ,MAAMgS,EAAQjS,EAAOW,GALF,KAAAA,aAC0B,KAAAsR,SAC1B,KAAAjS,QACA,KAAAa,OA/Bd,KAAA22C,SAAU,EACV,KAAAgQ,WAAY,EACZ,KAAAJ,eAAgB,EAChB,KAAAE,qBAAsB,EAMtB,KAAA2mC,UAAmB,GAMnB,KAAAC,wBAA0B1pF,EAAE2pF,SAAS,IAAMhuF,KAAKiuF,mBAAmBjuF,KAAK4gC,UAAW,KAInF,KAAAhpB,KAAW,CAChB0K,MAAOtiB,KAAKU,KAAKU,EAAE,oCACnBw/B,SAAU5gC,KAAKU,KAAKU,EAAE,uCACtB8sF,cAAeluF,KAAKU,KAAKU,EAAE,4CAC3BusF,YAAa3tF,KAAKU,KAAKU,EAAE,kBACzBwlD,cAAe5mD,KAAKU,KAAKU,EAAE,oBAC3BylD,YAAa7mD,KAAKU,KAAKU,EAAE,yBASzBpB,KAAKmuF,cAAgBr8E,EAAOq8E,eAAiB,gBAC7CnuF,KAAK6gC,QAAU/uB,EAAO+uB,QAEtB,MAAM83B,EAAQ34D,KAAKmuF,cAAcx1B,MAAM,kBAErC34D,KAAK4gC,SADH+3B,EACcA,EAAM,GAEN,OAIb,cAAc93D,GACnBb,KAAK6gC,QAAU7gC,KAAKouF,mBAAmB3pB,WACvC,MAAM4pB,EAAOruF,KAAK4gC,UAAY,OAC9B5gC,KAAKmuF,cAAgB,YAAYE,EAEjCruF,KAAKq3C,SAAU,EACfr3C,KAAKsnD,QAAQzmD,GAGf,kBACE,qCAAqB4O,KAAM6+E,IACzB,MAAMC,EAAaD,EAASpqD,QAC5BlkC,KAAKouF,mBAAqBG,EAAWC,aACnCxuF,KAAKyuF,eAAe3nF,cACpB,CACE4nF,aAAa,EACbC,aAAa,EACbC,WAAW,EACXzoF,MAAOnG,KAAK6gC,QACZ7pB,KAAM,OAMd,eACE,OAAOhX,KAAK8tF,UAGd,aAAalsF,GACX5B,KAAK8tF,UAAYlsF,EACjB5B,KAAK+tF,0BAGP,mBAAmBntD,GAEjB,IAAKA,GAAyB,SAAbA,EACf,OAAO5gC,KAAK6uF,qBAAqB,IAGnC,UAAiD,KAAmBjuD,KAAYA,QAC7EnxB,KAAK,KACJzP,KAAK6uF,qBAAqBjuD,KAE3BpmB,MAAOlO,IACNsR,QAAQoB,MAAM,2BAA2B4hB,MAAat0B,KACtDtM,KAAK6uF,qBAAqB,MAIhC,qBAAqBC,GACnB,MAAMtuD,EAASxgC,KAAKouF,mBACpB5tD,GAAUA,EAAOuuD,UAAU,OAAQD,GAGrC,eAAet8C,GACRA,EAKDA,EAASmmB,MAAM,SACjB34D,KAAK4gC,SAAW4R,EAEhB50B,QAAQoB,MAAM,uCAAyCwzB,GAPvDxyC,KAAK4gC,SAAW,I,sCAxGT,GAAmB,eA+BV,KAAkB,sB,uBA/B3B,EAAmB,qD,OAAA,K,knCDrChC,gBACE,gBACE,gBACE,oBAOA,eACF,OAEA,gBACE,iBACE,uBAIA,aACA,iBACE,oBAKA,kBACE,kBACE,uBAOI,yCAAiB,EAAAouD,eAAA,MAPrB,OASF,OACF,OACA,gBACF,OACF,OACF,OACA,kBACE,qBACQ,iCAAS,EAAA1nC,QAAA,MAIjB,OACA,qBACQ,iCAAS,EAAAumC,cAAA,MAIjB,OACF,OACF,OACF,Q,MAvD8C,iCAOA,yCAO5B,kCAMJ,4CAWI,mCAKL,iDAQC,iDACA,mCAKA,+CACA,mC,gIEnDR,eACE,eAEI,8DAEJ,OACF,O,uBAFM,0CC8BL,MAAM,UAA6B,IAwBxC,YAAqBrtF,EAC0BsR,EAC1BjS,EACAa,GAEnBZ,MAAMgS,EAAQjS,EAAOW,GALF,KAAAA,aAC0B,KAAAsR,SAC1B,KAAAjS,QACA,KAAAa,OAzBd,KAAA22C,SAAU,EACV,KAAAgQ,WAAY,EACZ,KAAAJ,eAAgB,EAChB,KAAAE,qBAAsB,EAItB,KAAA7N,KAAc,GACd,KAAA21C,eAAwB,EAIxB,KAAAr3E,KAAW,CAChB0K,MAAOtiB,KAAKU,KAAKU,EAAE,sCACnBssF,KAAM1tF,KAAKU,KAAKU,EAAE,oCAClBk4C,KAAMt5C,KAAKU,KAAKU,EAAE,oCAClB8tF,eAAgBlvF,KAAKU,KAAKU,EAAE,8CAC5BusF,YAAa3tF,KAAKU,KAAKU,EAAE,kBACzBwlD,cAAe5mD,KAAKU,KAAKU,EAAE,oBAC3BylD,YAAa7mD,KAAKU,KAAKU,EAAE,yBASzBpB,KAAKoqF,aAAepqF,KAAKs5C,KAAOt5C,KAAK8R,OAAOwnC,KAC5Ct5C,KAAKmvF,sBAAwBnvF,KAAKivF,cAAgBjvF,KAAK8R,OAAOm9E,cAKzD,cAAcpuF,GACnBb,KAAKq3C,SAAU,EACfr3C,KAAKs5C,KAAOt5C,KAAKoqF,aACjBpqF,KAAKivF,cAAgBjvF,KAAKmvF,sBAC1BnvF,KAAKsnD,QAAQzmD,GAGf,kBACEb,KAAK4tF,kBAAkB9mF,cAAcyG,QAGvC,oBAAoB3L,GAClB5B,KAAKmvF,sBAAwBvtF,G,sCAhDpB,GAAoB,eAyBX,KAAkB,sB,uBAzB3B,EAAoB,qD,OAAA,K,+xCDrCjC,gBACE,gBACE,gBACE,oBAOA,eACF,OAEA,gBACE,iBAA6B,kCAAU,EAAAisF,cAAA,MACrC,qBACE,mBACA,gBACE,oBAKA,kBACE,kBACE,uBAOI,mEAPJ,OAUF,OACF,OACF,OACA,iBACE,kBACE,oBACE,kBACE,uBAOQ,yCAAiB,EAAAuB,oBAAA,MAPzB,OASF,OACA,SACF,OACF,OACF,OACA,eACF,OACF,OACF,OACA,kBACE,qBACQ,iCAAS,EAAA9nC,QAAA,MAIjB,OACA,qBACQ,iCAAS,EAAAumC,cAAA,MAIjB,OACF,OACF,OACF,Q,MAxE8C,iCAOA,yCAM5B,wCAIF,wCAWI,qCAiBM,gDAIV,4CAIH,wCAQC,iDACA,mCAKA,+CACA,mC,2DEnCP,MAAM,EAEX,YAAqBh0C,EACA9wC,GADA,KAAA8wC,iBACA,KAAA9wC,WAOd,2BAA2Bo9E,EAAkB1kE,GAClD,OAAO,IAAIlS,QAAyC,CAACC,EAASquB,KAC9C79B,KAAK65C,eAAe94C,KAAK,IAAoBf,KAAK+I,SAAU,CAAE+J,KAAMqzE,EAAU1kE,QAASA,IAC/F+5C,aAAan7D,UAAWo7D,IACxBA,EAAMpkB,SACR7nC,EAAQ,CAACsD,KAAM2oD,EAAM3oD,KAAM2O,QAASg6C,EAAMh6C,cAU3C,yBAAyB63B,GAC9B,OAAO,IAAI/pC,QAAgB,CAACC,EAASnL,KACnC,MAAMgrF,EAAY/1C,GAAQ,GACZt5C,KAAK65C,eAAe94C,KAAK,EAA2Bf,KAAK+I,SAAU,CAAEuwC,KAAM+1C,IACnF7zB,aAAan7D,UAAWo7D,IACxBA,EAAMpkB,SACR7nC,EAAQisD,EAAMniB,UAUf,cAAczY,EAAgBstD,GACnC,OAAO,IAAI5+E,QAAkD,CAACC,EAASnL,KACvDrE,KAAK65C,eAAe94C,KAAK,EAAqBf,KAAK+I,SAAU,CAAE83B,QAASA,EAASstD,cAAeA,IACxG3yB,aAAan7D,UAAWo7D,IACxBA,EAAMpkB,SACR7nC,EAAQ,CAAC2+E,cAAe1yB,EAAM0yB,cAAettD,QAAS46B,EAAM56B,cAU7D,oBAAoByY,EAAa21C,GACtC,OAAO,IAAI1/E,QAAgB,CAACC,EAASnL,KACrBrE,KAAK65C,eAAe94C,KAAK,EAAsBf,KAAK+I,SAAS,CAAEuwC,KAAMA,EAAM21C,cAAeA,IAClGzzB,aAAan7D,UAAWo7D,IACxBA,EAAMpkB,SACR7nC,EAAQ,CACN8pC,KAAMmiB,EAAMniB,KACZ21C,cAAexzB,EAAMwzB,qB,sCA/DpB,GAAmB,sB,yBAAnB,EAAmB,QAAnB,EAAmB,a,kCCPhC,wH,wBC3BI,8B,oBACmB,kCAA2B,sBAA3B,CAA2B,4B,wBAI9C,0B,oBACe,kCAA2B,sBAA3B,CAA2B,0BAA3B,CAA2B,0BD8BvC,MAAMK,EASX,YAAqB50E,EACAha,GADA,KAAAga,aACA,KAAAha,OAIrB,WACEV,KAAKkyD,UAAYlyD,KAAKgJ,YAAY0S,QAAQJ,WAE1Ctb,KAAKuvF,aAAevvF,KAAKgxB,SAAS7oB,O,sCAjBzBmnF,GAAsB,sB,uBAAtBA,EAAsB,sbCtCnC,gBACE,gBACE,oCAKA,gCAMF,OACF,Q,MAdK,uCACE,wCACgB,0C,sFCFvB,4MAAO,MAAME,EAAkB,eAClBC,EAAuB,gBACvBC,EAA2B,6BAGjC,SAASC,EAAe//D,EAAgB3O,EAAkB2uE,GAEhD,IAAIC,kBAAiB,SAAUC,EAAWC,GACvD,GAAIlpF,OAAO+oB,GAAS3oB,OAGlB,OAFA8oF,EAAiBC,kBACjBJ,OAIKr+B,QAAQ1qD,OAAOoa,GAAW,GAAI,CACrCgvE,WAAW,EACXC,SAAS,IAIN,SAASC,IACd,IAAIC,EAAe,GACfC,EAAmBxpF,OAAO,kCAAoC2oF,EAAkB,KAChFc,EAAwBzpF,OAAO,kCAAoC4oF,EAAuB,KAS9F,OAPIY,EAAiBppF,QACnBmpF,EAAalvF,KAAKmvF,GAEhBC,EAAsBrpF,QACxBmpF,EAAalvF,KAAKovF,GAGbF,EAGF,SAASG,EAAoBjkF,GAClCA,EAAEC,iBACFD,EAAEO,oB,kCCTJ,sI,8DCvBM,eACE,eAEI,8DAEJ,OACF,O,uBAFM,0C,wBA4BM,oB,kCACQ,2BAAyB,mCAAzB,CAAyB,iBDU5C,MAAM2jF,UAA2B,IA2BtC,YAAqBhwF,EAC0BsR,EACzB4F,EACAjU,EACD5D,EACAa,GAEnBZ,MAAMgS,EAAQjS,EAAOW,GAPF,KAAAA,aAC0B,KAAAsR,SACzB,KAAA4F,iBACA,KAAAjU,eACD,KAAA5D,QACA,KAAAa,OA9Bd,KAAA22C,SAAU,EACV,KAAAgQ,WAAY,EACZ,KAAAJ,eAAgB,EAChB,KAAAE,qBAAsB,EAMtB,KAAAr0C,KAAc,GACd,KAAA2O,QAAiB,GAIjB,KAAA7J,KAAW,CAChB0K,MAAOtiB,KAAKU,KAAKU,EAAE,8CACnBqvF,KAAMzwF,KAAKU,KAAKU,EAAE,iBAClBsvF,cAAe1wF,KAAKU,KAAKU,EAAE,4CAC3BuvF,aAAc3wF,KAAKU,KAAKU,EAAE,oDAC1BwvF,kBAAmB5wF,KAAKU,KAAKU,EAAE,yDAC/BusF,YAAa3tF,KAAKU,KAAKU,EAAE,kBACzBwlD,cAAe5mD,KAAKU,KAAKU,EAAE,oBAC3BylD,YAAa7mD,KAAKU,KAAKU,EAAE,yBAWzBpB,KAAK6wF,aAAe7wF,KAAK8S,KAAO9S,KAAK8R,OAAOgB,KAC5C9S,KAAKyhB,QAAUzhB,KAAK8R,OAAO2P,QAC3BzhB,KAAK8wF,YAA+B,WAAjB9wF,KAAKyhB,QAExBzhB,KACGyD,aACAkpB,oBAAoB3sB,KAAK0X,eAAe5C,YACxClP,cACAxB,KACAgpB,KAAK,IACL/sB,UAAW+D,IACVpE,KAAK+wF,eAAiB3sF,EAAK5B,OAAOsQ,KAAK9N,gBAItC,cAAcnE,GACnBb,KAAKq3C,SAAU,EACfr3C,KAAKyhB,QAAUzhB,KAAK8wF,YAAc,SAAW,GAC7C9wF,KAAK8S,KAAO9S,KAAK6wF,aACjB7wF,KAAKsnD,QAAQzmD,GAGf,kBACEb,KAAKgxF,WAAWlqF,cAAcyG,S,sCA1DrBijF,GAAkB,eA4BT,KAAkB,0C,uBA5B3BA,EAAkB,qD,OAAA,K,y4CChD/B,gBACE,gBAGE,gBACE,oBAOA,eACF,OAEA,gBACE,iBAA6B,kCAAU,EAAA3C,cAAA,MACrC,qBACE,mBACA,gBACE,oBAKA,kBACE,kBACE,wBAKI,mEAEF,qBAGA,2BAIF,OACF,OACF,OACF,OACF,OAEA,kBACE,kBACE,oBACE,kBACE,oBAGO,oEAHP,OAMF,OACA,SACF,OACF,OACF,OACA,eACF,OACF,OACA,kBACE,qBACQ,iCAAS,EAAAvmC,QAAA,MAIjB,OACA,qBACQ,iCAAS,EAAAumC,cAAA,MAIjB,OACF,OACF,OACF,Q,MA3E8C,iCAOA,yCAM5B,iDAIF,iDAYU,wCAAyB,4BAGzB,yCAkBH,sCAGT,0CAIH,qDAOG,iDACA,mCAKA,+CACA,mC,gGC/Cd,kCAAO,MAAMoD,EAEX,YAAmB33C,EACAW,EACAV,GAFA,KAAAD,OACA,KAAAW,QACA,KAAAV,UAGZ,oBACL,OAAOv5C,KAAKu5C,SAAWv5C,KAAKs5C,KAAO,GAAK,EAGnC,kBAAkB43C,GACvB,OAAOzpE,KAAK0pE,IAAInxF,KAAKu5C,QAAUv5C,KAAKs5C,KAAM43C,GAGrC,WACLlxF,KAAKs5C,MAAQ,EAGR,eACLt5C,KAAKs5C,MAAQ,K,kCClBjB,kCAAO,MAAM83C,EAiDX,YAAYC,GA/CL,KAAA/4C,cAAuB,EAGvB,KAAA6B,mBAA4B,EAG5B,KAAAxL,sBAA+B,EAG/B,KAAA2iD,oBAA6B,EAG7B,KAAA1iD,mBAA4B,EAG5B,KAAAqJ,gBAAyB,EAGzB,KAAAnpC,kBAAgC,KAGhC,KAAAyiF,qBAA8B,EAG9B,KAAAC,wBAAiC,EAGjC,KAAAh6D,oBAA6B,EAG7B,KAAAmZ,YAAqB,EAGrB,KAAA8gD,YAAqB,EAGrB,KAAA13C,aAAsB,EAGtB,KAAA23C,iBAA0B,EAG1B,KAAAC,kBAA2B,EAG3B,KAAAC,iBAA0BlxF,KAAKU,EAAE,oBAGtCiD,EAAEC,KAAK+sF,EAAgB,CAAClrF,EAAO09D,KAE5B7jE,KADU6jE,GACU19D,O,kCCvD3B,kM,yBCKY,aACE,aAAC,kBACD,kBACF,Q,yBAFS,iCACD,2C,yBATZ,cACE,eACE,kBACA,oBAA8C,aAC9C,kBACF,OACA,aACE,sBAIF,OACA,YACE,kBACF,OACF,Q,qBAZY,2CACF,oEAGF,oDAME,oD,yBAvBZ,QACE,YACE,kBACA,aACA,iBACE,QAGF,OACF,OACA,uBAgBF,Q,oBAxBU,wCAGJ,gHAKC,wF,yBA2BD,iBACE,QACF,Q,wCADE,gD,yBALJ,aACE,aAAC,kBACD,YACA,kBACA,yBAGF,Q,mCANS,iCAED,sCACE,6C,yBAVd,QACE,eACE,kBACA,oBACF,OACA,aACE,sBAQF,OACF,Q,oBAZY,wCAGJ,wC,uCAUR,cACE,mBACE,iBACE,mBAGO,uFAHP,OAKF,OACA,QACF,OACF,O,uBALa,oDAGT,8DDvBH,MAAM0rF,UAAuB,IAuBlC,YAAqBrxF,EACAqqD,EAC0B/4C,EAC1BpR,EACAb,EACA4X,EACA9U,EACAmtC,EACA6I,EACA9L,EACAyrB,GACnBx4D,MAAMgS,EAAQjS,EAAOW,GAXF,KAAAA,aACA,KAAAqqD,qBAC0B,KAAA/4C,SAC1B,KAAApR,OACA,KAAAb,QACA,KAAA4X,SACA,KAAA9U,SACA,KAAAmtC,eACA,KAAA6I,gBACA,KAAA9L,sBACA,KAAAyrB,qBAzBd,KAAAw5B,MAAO,EAGP,KAAAC,2BAA4B,EAE5B,KAAAn6E,KAAW,CAChBo6E,0BAA2BhyF,KAAKU,KAAKU,EAAE,gCACvCusF,YAAa3tF,KAAKU,KAAKU,EAAE,yBACzBoqC,QAASxrC,KAAKU,KAAKU,EAAE,qBACrB6wF,QAASjyF,KAAKU,KAAKU,EAAE,oBACrBiZ,OAAQra,KAAKU,KAAKU,EAAE,oBACpB2J,MAAO/K,KAAKU,KAAKU,EAAE,wBACnB8wF,gCAAiClyF,KAAKU,KAAKU,EAAE,6DAiB/C,WACEtB,MAAMqkB,WAENnkB,KAAK6V,aAAe7V,KAAK8R,OAAO+D,aAChC7V,KAAKmyF,iBAAmBnyF,KAAKU,KAAKU,EAAE,uBAAwB,CAAE6yB,MAAOj0B,KAAK6V,aAAa5O,SAGtD,IAA7BjH,KAAK6V,aAAa5O,SACpBjH,KAAKoyF,kBAAoBpyF,KAAK6V,aAAa,GAC3C7V,KAAKqyF,0BAA4BryF,KAAKoyF,kBAAkBnmF,UAG1DjM,KAAK4X,KAAK0K,MAAQtiB,KAAKU,KAAKU,EAAE,uCAAwC,CAAEkhC,MAAOtiC,KAAKmyF,mBAClFnyF,KAAK4X,KAAKA,KAAO5X,KAAKU,KAAKU,EAAE,sCAAuC,CAClEkhC,MAAOtiC,KAAKmyF,iBACZl+D,MAAOj0B,KAAK6V,aAAa5O,SAG7BjH,KAAK4X,KAAK06E,WAAc3sF,IACtB,MAAMsuB,EAAQj0B,KAAKiM,SAAStG,GAAIsB,OAChC,OAAOjH,KAAKU,KAAKU,EAAE,+BAAgC,CAAE6yB,MAAOA,KAG9Dj0B,KAAK4X,KAAK26E,YAAe5sF,GACvB3F,KAAKU,KAAKU,EAAE,8CAA+C,CAAEoxF,WAAYxyF,KAAK4X,KAAK06E,WAAW3sF,KAE9F3F,KAAK4X,KAAK66E,gBAAkBzyF,KAAKU,KAAKU,EAAE,mDAG5C,sCACE,OAAOpB,KAAK0yF,sBAAwB1yF,KAAK+xF,0BAG3C,0BAGE,GAAI/xF,KAAKoyF,mBAAqBpyF,KAAKqyF,0BAA2B,CAC/CryF,KAAKqyF,0BAA0BprF,OAG9C,QAAmB5C,EAAEmH,KAAKxL,KAAK6V,aAAclQ,GAC3CA,EAAGsG,UAAYtG,EAAGsG,SAAShF,OAAS,GAGjC,gBAAgBskC,GACrB,OAAIvrC,KAAK8xF,MAAQ9xF,KAAK2yF,kCAItB3yF,KAAK8xF,MAAO,EACZ9xF,KAAK6qD,mBAAmB+nC,kBAAkB5yF,KAAK6V,aAAa3G,IAAI+C,GAAMA,EAAG/J,KAAM,GAC5EuH,KAAK,KACJzP,KAAK8xF,MAAO,EACZ9xF,KAAKsnD,QAAQ/b,GACbvrC,KAAK8vC,aAAazqC,MAAM,2CAGpBrF,KAAKyX,OAAOxX,QAAQkO,KAAKT,WAC3B1N,KAAKs4D,mBAAmBC,QAAO,KAGlC/9C,MAAM,KACLxa,KAAK8xF,MAAO,MAhBP,EAsBJ,SAAS9oF,GACd,OAAIA,EAAY6yC,eAAe,YACtB7yC,EAAYiD,SAEZ,I,sCA7GA4lF,GAAc,yBAyBL,KAAkB,6F,uBAzB3BA,EAAc,24BC7C3B,gBACE,gBAIE,gBACE,cACE,cACG,iCAAS,EAAAvqC,QAAA,MAEZ,OACF,OACA,eACF,OAEA,gBACE,+BA2BA,+BAgBA,sBAYF,OAEA,iBACE,oBAGQ,iCAAS,EAAAurC,gBAAA,MACjB,OACA,qBAEQ,iCAAS,EAAAvrC,QAAA,MACjB,OACF,OACF,OACF,Q,MA5EW,mCAGmC,yCAI1B,yCA2BA,6CAgBT,2CAgBG,2CACA,mEAIA,4C,sFC/Ed,sI,wBC4BU,iB,oBAEM,wD,wBAmBJ,oB,kCACQ,2BAA0B,wDAA1B,CAA0B,iBDvCvC,MAAMwrC,EA6BX,YAAqB/pF,EACArI,EACAoC,EACAK,EACA4vF,GAJA,KAAAhqF,WACA,KAAArI,OACA,KAAAoC,iBACA,KAAAK,qBACA,KAAA4vF,cA9Bd,KAAAC,YAA8C,UAI9C,KAAAC,gBAAyC,GAGzC,KAAAC,aAAsB,EAEtB,KAAAt7E,KAAO,CACZu7E,YAAanzF,KAAKU,KAAKU,EAAE,4DACzBgyF,eAAgBpzF,KAAKU,KAAKU,EAAE,qBAC5BkhB,MAAOtiB,KAAKU,KAAKU,EAAE,qBACnBouB,YAAaxvB,KAAKU,KAAKU,EAAE,2BACzBwyC,cAAe5zC,KAAKU,KAAKU,EAAE,6BAC3B8iC,QAAS,UAAOlkC,KAAKU,KAAKU,EAAE,gDAC5BiyF,aAAcrzF,KAAKU,KAAKU,EAAE,uCAC1BkyF,kBAAmB,UAAOtzF,KAAKU,KAAKU,EAAE,0DACtCmyF,aAAc,CACZrvD,QAASlkC,KAAKU,KAAKU,EAAE,qDACrBoyF,QAASxzF,KAAKU,KAAKU,EAAE,qDACrBwa,UAAW5b,KAAKU,KAAKU,EAAE,uDACvBqyF,eAAgB,UAAOzzF,KAAKU,KAAKU,EAAE,yDAWhC,SAELpB,KAAKmD,mBAAmBuwF,WAAgC,cAArB1zF,KAAKgzF,aAGxC,IAAIn+E,EAA6B,YAArB7U,KAAKgzF,YAA4BhzF,KAAKm5B,aAAe,KACjEn5B,KAAK8C,eAAe0R,OAAOK,GAG3B7U,KAAK+yF,YAAYW,WAAW1zF,KAAKkzF,aAG5B,YAAY3tF,GACjBvF,KAAKgzF,YAAc,UACnBhzF,KAAKm5B,aAAe90B,EAAEmH,KAAKxL,KAAKizF,gBAAiBp+E,GAASA,EAAMtP,OAASA,IAAS,KAGpF,WACMvF,KAAKmD,mBAAmBy5B,UAC1B58B,KAAKgzF,YAAc,YACVhzF,KAAK8C,eAAe7C,UAC7BD,KAAKgzF,YAAc,WAGrBhzF,KAAKkzF,YAAclzF,KAAK+yF,YAAY9yF,QAEpCD,KAAK8C,eACFspD,UACA38C,KAAK,KACJzP,KAAKizF,gBAAkB5uF,EAAEY,OAAOjF,KAAK8C,eAAewS,UAAW,QAC/DtV,KAAKm5B,aAAen5B,KAAK8C,eAAe7C,W,sCAlEnC6yF,GAAsC,oD,uBAAtCA,EAAsC,86BCZnD,cACE,eACE,cACA,gBACE,gBACE,kBACE,kBACO,4DADP,OAIA,oBACA,YACA,iBACA,aACA,kBACF,OACF,OACF,OACA,iBACE,iBACE,mBACE,mBACO,4DADP,OAIA,qBACA,aACA,kBACA,aACA,wBAGF,OACF,OACF,OACA,iBACE,iBACE,mBACE,oBACO,4DADP,OAIA,sBACA,aACA,kBACA,aACA,qBAAQ,kCAAU,EAAAa,YAAA,mBAIhB,2BAIF,OACF,OACF,OACF,OAEA,cAEA,eACE,iBACE,iBACE,mBACE,oBACO,iEADP,OAIA,SACA,kBACF,OACF,OACF,OAEF,OACF,OACF,Q,MA3EO,+CAKU,sCAGmC,uDAEpC,wDAEkC,2CAQjC,sCAGgC,yDAEjC,0DAEA,iDAUC,sCAG+B,iDAEhC,kDAMI,0CAiBD,sCAEP,0CACwC,uD,gOClE7C,MAAMC,GAAa,WAEbC,EAAY,WAIZC,EAAiB,MAMvB,MAAM,EAgBX,YAAqBlhC,EACAl7B,EACA5N,EACAmH,EACA65C,GAJA,KAAAlY,QACA,KAAAl7B,YACA,KAAA5N,OACA,KAAAmH,QACA,KAAA65C,YAfb,KAAA9hC,MAAmB,GAkBpB,aAeL,OAdA,YAAW,sBAAsBhpC,KAAK8pB,QAAQ9pB,KAAKixB,QAAS,KAIrDjxB,KAAK+zF,mBAIR/zF,KAAKg0F,sBAHLh0F,KAAKi0F,qBAOT,YAAS,8BAA+Bj0F,KAAKgpC,OAEtChpC,KAAKgpC,MAQN,mBACN,IAAI/oC,EAEJ,IAAK,IAAI8c,EAAI,EAAGid,EAAIh6B,KAAK4yD,MAAM3rD,OAAQ8V,EAAIid,EAAGjd,IAAK,CACjD,MAAM7U,EAAKlI,KAAK4yD,MAAM71C,GAChBlR,EAAW7L,KAAK03B,UAAUxvB,GAGhC,GAAI6U,IAAM/c,KAAKixB,MAKf,QAAgBvlB,IAAZzL,QAAsCyL,IAAbG,GAM7B,GAAIA,EAAW5L,EACb,OAAO,OANPA,EAAU4L,EAUd,OAAO,EAOD,mBACN,IAAKslF,EAAKjhB,GAAOlwE,KAAKk0F,gBACtBl0F,KAAKm0F,aAAahD,EAAKjhB,GAOjB,sBAGN,GAAIlwE,KAAK4yD,MAAM3rD,QAAU,QAAmCyE,IAA9B1L,KAAK03B,UAAU13B,KAAK8pB,MAEhD,YADA9pB,KAAKgpC,MAAMhpC,KAAK8pB,MAlGO,GAuGzB,GAAuB,OAAnB9pB,KAAK8qE,WAAgE,IAA1CrjD,KAAK2sE,IAAIp0F,KAAK8qE,UAAY9qE,KAAKixB,QAAgBjxB,KAAKq0F,eACjF,OAIF,GAAmB,IAAfr0F,KAAKixB,MACP,OAAOjxB,KAAKs0F,gBAId,MAAMC,EAAsBv0F,KAAKw0F,6BAGjC,GAAID,GAAuBV,EAEzB,OADA,YAAS,yDACF7zF,KAAKy0F,kBAId,MAAMC,EAAoB10F,KAAK20F,YAAY30F,KAAKixB,MAAQ,GAExD,QAA0BvlB,IAAtBgpF,EAIF,YADA10F,KAAKgpC,MAAMhpC,KAAK8pB,MAAQyqE,EAAsB,MAKhD,GAAIG,GAAqBb,EAEvB,OADA,YAAS,uDACF7zF,KAAKy0F,kBAKd,MAAMG,EAAWntE,KAAKg9D,OAAOiQ,EAAoBH,GAAuB,GAGxE,GAAIK,EAAW,EAEb,OADA,YAAS,qEACF50F,KAAKy0F,kBAGdz0F,KAAKgpC,MAAMhpC,KAAK8pB,MAAQyqE,EAAsBK,EAMxC,gBAEN,MAAMF,EAAoB10F,KAAK20F,YAAY30F,KAAKixB,MAAQ,GAItDjxB,KAAKgpC,MAAMhpC,KAAK8pB,WADQpe,IAAtBgpF,EA9JqB,EAiKCA,EAAoB,KAQxC,eACN,MAAMG,EAAa70F,KAAK20F,YAAY30F,KAAKixB,OACnC6jE,EAAW90F,KAAK4yD,MAAM5yD,KAAK8qE,WAC3BiqB,EAAmB/0F,KAAK20F,YAAY30F,KAAK8qE,WAI/C,YAAmBp/D,IAAfmpF,QAAiDnpF,IAArBqpF,IAKhC/0F,KAAKgpC,MAAMhpC,KAAK8pB,MAAQirE,EACxB/0F,KAAKgpC,MAAM8rD,GAAYD,GAEhB,GAQD,6BACN,IAAIN,GAA6BS,MAEjC,IAAK,IAAIj4E,EAAI,EAAGA,EAAI/c,KAAKixB,MAAOlU,IAAK,CACnC,MAAM7U,EAAKlI,KAAK4yD,MAAM71C,GAChBlR,EAAW7L,KAAK03B,UAAUxvB,GAI9BqsF,OADe7oF,IAAbG,EACoB7L,KAAKgpC,MAAM9gC,GAAMqsF,EAAsBT,EAEvCjoF,EAI1B,OAAO0oF,EAMD,YAAYtjE,GAClB,MAAMnH,EAAO9pB,KAAK4yD,MAAM3hC,GACxB,OAAOjxB,KAAKi1F,aAAanrE,GASnB,aAAaA,GAEnB,YAA4Bpe,IAArB1L,KAAKgpC,MAAMlf,GAAsB9pB,KAAK03B,UAAU5N,GAAQ9pB,KAAKgpC,MAAMlf,GAOpE,kBAGN,IAAIqnE,EAAMnxF,KAAKk1F,cACXhlB,EAAMlwE,KAAKm1F,aAEfn1F,KAAKm0F,aAAahD,EAAKjhB,GAMjB,aAAaihB,EAAYjhB,GAC/B,MAAMklB,EAAoBp1F,KAAK4yD,MAAM3rD,OAGrC,IAAIouF,EAAQ5tE,KAAKg9D,OAAOvU,EAAMihB,IAAQiE,EAAoB,IAI1D,GAAIC,EAAQ,EAAG,CACb,GAAKnlB,EAAMklB,GAAsBvB,EAC/B3jB,GAAOklB,MACF,MAAKjE,EAAMiE,GAAsBxB,GAItC,KAAM,2EAHNzC,GAAOiE,EAOTC,EAAQ5tE,KAAKg9D,OAAOvU,EAAMihB,IAAQiE,EAAoB,IAIxD,IAAK,IAAIr4E,EAAI,EAAGA,EAAIq4E,EAAmBr4E,IAAK,CAC1C,MAAM+M,EAAO9pB,KAAK4yD,MAAM71C,GACxB/c,KAAKgpC,MAAMlf,GAAQqnE,EAAOp0E,EAAIs4E,GAalC,sBACE,IAAIlE,EAAa0C,EACb3jB,EAAa0jB,EACb0B,GAAc,EAElB,IAAK,IAAIv4E,EAAI/c,KAAK4yD,MAAM3rD,OAAS,EAAG8V,GAAK,EAAGA,IAAK,CAC/C,IAAI+M,EAAO9pB,KAAK4yD,MAAM71C,GAClBlR,EAAW7L,KAAKi1F,aAAanrE,QAEhBpe,IAAbG,IACFslF,EAAM1pE,KAAK0pE,IAAItlF,EAAUslF,GACzBjhB,EAAMzoD,KAAKyoD,IAAIrkE,EAAUqkE,GACzBolB,GAAM,GAIV,OAAIA,GAAOnE,IAAQjhB,EACV,CAACihB,EAAKjhB,GAEN,CA9SgB,EA8SAlwE,KAAK4yD,MAAM3rD,OAAS6sF,GAQ/C,oBACE,MAAMhqE,EAAO9pB,KAAK4yD,MAAM,GACxB,OAAO5yD,KAAKi1F,aAAanrE,GAO3B,mBACE,IAAK,IAAI/M,EAAI/c,KAAK4yD,MAAM3rD,OAAS,EAAG8V,GAAK,EAAGA,IAAK,CAC/C,IAAI+M,EAAO9pB,KAAK4yD,MAAM71C,GAClBlR,EAAW7L,KAAKi1F,aAAanrE,GAGjC,QAAiBpe,IAAbG,EACF,OAAOA,I,gEC/RR,MAAM,UAAoC,IAE/C,YAA+BjJ,EACAa,EACAd,EACA4yF,EACAvyF,EACA6L,GAC7B/O,MAAM8C,GANuB,KAAAA,aACA,KAAAa,eACA,KAAAd,SACA,KAAA4yF,gBACA,KAAAvyF,gBACA,KAAA6L,aAIxB,WAAWhL,EAAqBC,EAAuCtB,GAO5E,OALKqB,EAAM6uC,WAAa1yC,KAAK03B,UAAUp1B,YACrCtC,KAAKoG,aAAavC,GAIhB7D,KAAKgD,cAAcmvC,oBACdnyC,KAAKy3B,sBAGPloB,QAAQC,UAMJ,KAAKojD,EAAgB9oC,EAAai3B,G,mDAE7C,IAAI+pB,EAAmBlY,EAAM9zB,UAAW52B,GAAOA,IAAO4hB,GAOtD,OALA8oC,EAAM3pC,OAAO6hD,EAAW,GACxBlY,EAAM3pC,OAAO83B,EAAS,EAAGj3B,SAEnB9pB,KAAKw1F,eAAe5iC,EAAO9oC,EAAMi3B,EAAS+pB,GAEzClY,KAMF,OAAOA,EAAgB9oC,GAG5B,OAFAzlB,EAAEouB,OAAOmgC,EAAO1qD,GAAMA,IAAO4hB,GAC7B9pB,KAAKwU,OAAO,CAAE,CAACsV,IAAQ,IAChB8oC,EAMI,IAAIA,EAAgB9oC,EAAai3B,GAAiB,G,mDAU7D,OATiB,IAAbA,GACF6R,EAAM1xD,KAAK4oB,GACXi3B,EAAU6R,EAAM3rD,OAAS,GAEzB2rD,EAAM3pC,OAAO83B,EAAS,EAAGj3B,SAGrB9pB,KAAKw1F,eAAe5iC,EAAO9oC,EAAMi3B,GAEhC6R,KAGT,iBACE,OAAO5yD,KAAK65D,aAAannB,UAG3B,mBACE,OAAO1yC,KAAK4C,WAAWiB,MAAMsC,MASf,eAAeysD,EAAgB9oC,EAAai3B,EAAgB+pB,EAAwB,M,mDAClG,MAAMpzC,QAAkB13B,KAAKy3B,sBACvBuR,EAAQ,IAAI,EAAoB4pB,EAAOl7B,EAAW5N,EAAMi3B,EAAS+pB,GAAW2qB,mBAE5Ez1F,KAAKwU,OAAOw0B,MAGpB,gBACE,OAAOhpC,KAAKwT,aAMD,OAAOw1B,G,mDAClB,IAAI/oC,EAAUD,KAAK03B,UAAUjkB,WAAW,IAIxC,GAHAzT,KAAK03B,UAAU1zB,SAAS,OAAD,wBAAM/D,GAAY+oC,IAGrChpC,KAAK65D,aAAannB,UAAW,CAC/B,MAAMgjD,QAAkB11F,KACrByD,aACAqB,QAAQoD,GAAGlI,KAAK65D,cAChBjH,MACAp+C,OAAOw0B,GAEVhpC,KAAK65D,aAAa67B,UAAYA,EAG9B11F,KAAKu1F,cAAc/kF,IAAIxQ,KAAK65D,cAI9B75D,KAAKoG,aAAapG,KAAK65D,cAGvB75D,KAAK4C,WAAWiB,MAAMG,SAAShE,KAAK65D,iBAM/B,sBACL,GAAI75D,KAAK65D,aAAannB,UAAW,EACjB1yC,KAAK03B,UAAUvxB,QAGd,IAAMnG,KAAK03B,UAAUovC,iBAAiB,OACnD9mE,KAAK03B,UAAUryB,MAAM,gCAIvBrF,KAAK03B,UAAU8sC,yBACb,IAAMxkE,KACLyD,aACAqB,QAAQoD,GAAGlI,KAAK65D,cAChBjH,MACAluD,YAEM1E,KAAK03B,UAAU2sC,cAExBrkE,KAAK03B,UAAU1zB,SAAS,IAG1B,OAAOhE,KAAK03B,UACTx3B,UACAC,KAAK,OAAAi3C,EAAA,GAAK,IACVvqB,YAGE,eAAehpB,IAOtB,sBACE,MAAM8xF,EAAgB31F,KAAK4C,WACxBkB,QACAqC,MACA3B,SACA0K,IAAIvJ,GAAM3F,KAAK2C,OAAOkT,aAAanR,IAAIiB,EAAGuC,IAAKuL,WAAW9N,IAE7D,GAAI3F,KAAK65D,aAAannB,WAAa1yC,KAAK03B,UAAU2sC,aAChD,OAAOsxB,EACF,CACL,MAAMj+D,EAAY13B,KAAK03B,UAAUvxB,MACjC,OAAO9B,EAAEY,OAAO0wF,EAAgBhwF,IAC9B,MAAMiwF,EAAMl+D,EAAU/xB,EAAGuC,IACzB,YAAewD,IAARkqF,EAAoBA,EAAM/B,KAKvC,aAAahwF,GAEX,OADAA,EAAMgyF,oBAAsB71F,KAAK03B,UAAUjkB,WAAW,KAC/C,EAGT,WAAW5P,GACT,OAAO,G,sCApLE,GAA2B,8D,yBAA3B,EAA2B,QAA3B,EAA2B,a,6MClCjC,MAAM,UAAwB,IAoBnC,YAA4BkF,GAC1BjJ,QAD0B,KAAAiJ,WAZ5B,YACE,MAAO,uCAGT,eACE,MAAO,IAAI,OAAoB,MAG1B,WAAWg4B,GAChB,OAAOl6B,OAAOk6B,EAAKzN,iBAAiBqH,2BAO5B,aAAapH,EAAwB1yB,GAC7C,YAAS,6BAA8BA,EAAIkG,QAC3ClG,EAAI0L,iBAGJ,IAAIxF,EAASF,OAAOhG,EAAIkG,QAAQC,QAAQ,IAAI,KAExCI,EAAYL,EAAOoH,KAAK,aAE5B,IAAK/G,EAEH,OADA,YAAS,sCAAuCvG,EAAIkG,SAC7C,EAIT,MAAM0yB,EAAa1yB,EAAOC,QAAQ,IAAI,KAEhCkd,EAAgBuV,EAAWtrB,KAAK,iBAChCnF,EAAchJ,KAAK2C,OAAOkT,aAAanR,IAAIwf,GAAe/d,MAE1D6vB,EAAkByD,EAAWtrB,KAAK,mBAGlC/J,EAAOmvB,EAAMsL,QAAQ+S,aAAa5oC,EAAagtB,GAG/C4pB,EAAiB,IAAoBC,YAAYh/C,GAUvD,OAPAuD,EAAKkD,SAASF,GACXqI,KAAMqJ,IACLA,EAAQgnC,gBAAgB13C,OACxB0Q,EAAQvL,MAAMqyC,KAEfplC,MAAM,IAAMzT,EAAO4D,SAAS,OAExB,GAzDM,aAAd,c,0BAA4B,M,6BACd,aAAd,c,0BAAgC,M,6DCP5B,MAAM,UAA6B,IAiBxC,YAA4B5B,GAC1BjJ,QAD0B,KAAAiJ,WAZ5B,YACE,MAAO,yDAGT,eACE,MAAO,IAAI,IAGN,WAAWg4B,GAClB,OAAOl6B,OAAOk6B,EAAKzN,iBAAiBqH,2BAO1B,aAAapH,EAAwB1yB,GAC7C,YAAS,oCAAqCA,EAAIkG,QAClDlG,EAAI0L,iBAGJ,MACMuoB,EADKjuB,OAAOhG,EAAIkG,QAAQC,QAAQ,IAAI,KACtBmH,KAAK,YAInB+V,EADard,OAAOhG,EAAIkG,QAAQC,QAAQ,IAAI,KACjBmH,KAAK,iBAStC,OANInO,KAAKqD,uBAAuBsN,aAAauT,KAAmB4Q,EAC9D90B,KAAKqD,uBAAuBowB,SAASvP,GAErClkB,KAAKqD,uBAAuByyF,aAAa5xE,EAAe4Q,IAGnD,GArCM,aAAd,c,0BAAqC,M,iGCNjC,MAAM,UAAoC,IAI/C,YAAmB/rB,EACGmb,EACAtd,EACAmvF,EAA6B,GAC7BxiE,GACpBzzB,MAAMiJ,EAAUmb,EAAetd,EAAUmvF,GAAwB,GALhD,KAAAhtF,WACG,KAAAmb,gBACA,KAAAtd,WACA,KAAAmvF,yBACA,KAAAxiE,QAIf,yBAAyBwtC,GAC9B,OAAQA,EAAOp/D,KACb,IAAK,oBACH3B,KAAKuzB,MAAMgL,mBAAmBy3D,4BAA4Bh2F,KAAKgJ,aAC/D,MAEF,IAAK,mBACHhJ,KAAKuzB,MAAMgL,mBAAmB03D,yBAAyBj2F,KAAKgJ,aAC5D,MAEF,IAAK,mBACHhJ,KAAKk2F,kBAAkBC,OAAOn2F,KAAKgJ,aACnC,MAEF,IAAK,oBACHhJ,KAAKk2F,kBAAkBE,QAAQp2F,KAAKgJ,aACpC,MAEF,QACElJ,MAAM65E,yBAAyB5Y,KA7BtB,aAAd,c,0BAAgC,M,wCCD5B,MAAe,EAIpB,YAA4Bh4D,GAAA,KAAAA,WAG5B,kBACE,MAAO,IAAI,IAON,WAAWg4B,GAChB,OAAOl6B,OAAOk6B,EAAKzN,iBAAiBqH,2BAK5B,gBAAgBpH,EAAwB1yB,EAA2BqjB,EAAsBjO,GACjG,MAAM6C,EAAU,IAAI,EAA4B9Y,KAAK+I,SAAUmb,EAAerd,OAAOhG,EAAIkG,QAAmBkP,EAAcsd,GAC1HvzB,KAAKS,cAAcM,KAAK+X,EAASjY,IArBpB,aAAd,c,0BAAmC,M,oDCF/B,MAAM,UAAgC,EAE3C,YAA4BkI,GAC1BjJ,MAAMiJ,GADoB,KAAAA,WAI5B,YACE,MAAO,0BAGT,eACE,MAAO,IAAI,IAGN,YAAYg4B,EAA0BlgC,GAC3C,IAAIkG,EAASF,OAAOhG,EAAIkG,QAIxB,GAAIA,EAAOC,QAAQ,IAAI,KAAoBC,OAEzC,OADA,YAAS,iDACF,EAGTpG,EAAI0L,iBACJ1L,EAAIgM,kBAGJ,MACMid,EADU/iB,EAAOC,QAAQhH,KAAKq2F,aACfloF,KAAK,iBAM1B,OAJI2b,GACF9pB,KAAKs2F,gBAAgBv1D,EAAKzN,iBAAkBzyB,EAAKipB,IAG5C,G,gBCrCJ,MAAM,UAAmC,EAE9C,YAA4B/gB,GAC1BjJ,MAAMiJ,GADoB,KAAAA,WAI5B,YACE,MAAO,4BAGT,eACE,OAAO/I,KAAKq2F,YAGP,YAAY5nF,EAA+B5N,GAChD,IAAK4N,EAAU6kB,iBAAiBiE,cAAc+5D,mBAC5C,OAAO,EAGT,IAAIvqF,EAASF,OAAOhG,EAAIkG,QAExB,GAAMlG,EAAI01F,UAAY,IAASC,MAAO31F,EAAI0R,WAAY1R,EAAI41F,OACxD,OAAO,EAGT51F,EAAI0L,iBACJ1L,EAAIgM,kBAGJ,MACMid,EADU/iB,EAAOC,QAAQhH,KAAK02F,UACfvoF,KAAK,iBAG1B,IAAItC,EAAW,CAAEsK,GAAI,WAAYC,GAAI,cAAe9C,GAAIvM,GAIxD,OAFAjH,MAAMw2F,gBAAgB7nF,EAAU6kB,iBAAkBzyB,EAAKipB,EAAMje,IAEtD,G,4BChCJ,MAAM,UAAqC,EAIhD,YAA4B9C,GAC1BjJ,MAAMiJ,GADoB,KAAAA,WAI5B,YACE,MAAO,+BAGT,eACE,MAAO,IAAI,QAAsB,MAG5B,WAAWg4B,GAChB,OAAOl6B,OAAOk6B,EAAKzN,iBAAiBqH,2BAG/B,YAAYoG,EAA0BlgC,GAC3C,IAAKkgC,EAAKzN,iBAAiBiE,cAAc+5D,mBACvC,OAAO,EAET,IAAIvqF,EAASF,OAAOhG,EAAIkG,QAIxB,GAAIA,EAAOC,QAAQ,IAAI,KAAoBC,OAEzC,OADA,YAAS,iDACF,EAGTpG,EAAI0L,iBACJ1L,EAAIgM,kBAGJ,MACMid,EADU/iB,EAAOC,QAAQhH,KAAK02F,UACfvoF,KAAK,iBAE1B,GAAI2b,EAAM,CACR,IAAKmH,GAAU8P,EAAKzN,iBAAiBqjE,gBAAgB7sE,GAEhD9pB,KAAKuvC,iBAAiBC,WAAW1lB,IACpC9pB,KAAKuvC,iBAAiB05C,aAAan/D,EAAMmH,GAG3CjxB,KAAKs2F,gBAAgBv1D,EAAKzN,iBAAkBzyB,EAAKipB,GAGnD,OAAO,GAhDM,aAAd,c,0BAAwC,M,2FCCpC,MAAM,EASX,YAA4B/gB,GAAA,KAAAA,WAG5B,YACE,MAAO,kBAGT,eACE,MAAO,IAAI,IAGN,WAAWg4B,GAChB,OAAOl6B,OAAOk6B,EAAKzN,iBAAiBgL,OAG/B,YAAYyC,EAA0BlgC,GAC3C,IAAIkG,EAASF,OAAOhG,EAAIkG,QAGxB,GAAIA,EAAO0+B,GAAG,MAAQ1+B,EAAO2H,SAAS+2B,GAAG,KACvC,OAAO,EAKT,GAAI1+B,EAAOiF,SAAS,GAAG,MAAuBjF,EAAOiF,SAAS,GAAG,KAE/D,OADA,YAAS,iCACF,EAIT,IAAI4jB,EAAU7oB,EAAOC,QAAQhH,KAAK02F,UAC9B5sE,EAAO8F,EAAQzhB,KAAK,iBACpB6nB,EAAkBpG,EAAQzhB,KAAK,mBAEnC,IAAK2b,EACH,OAAO,EAGT,IAAKmH,EAAO4C,GAAOkN,EAAKzN,iBAAiBqjE,gBAAgB3gE,GAwBzD,OArBMn1B,EAAIyR,SAAWzR,EAAI2R,SAAW3R,EAAI0R,WACtCvS,KAAKuvC,iBAAiB05C,aAAan/D,EAAMmH,GACzC8P,EAAK61D,YAAYpuF,KAAK,CAAE0b,cAAe4F,EAAM2wB,QAAQ,KAInD55C,EAAI0R,UACNvS,KAAKuvC,iBAAiBsnD,sBAAsB91D,EAAKzN,iBAAiByL,aAAcjV,EAAMmH,IAIpFpwB,EAAIyR,SAAWzR,EAAI2R,UACrBxS,KAAKuvC,iBAAiBunD,UAAUhtE,GAGlCiX,EAAKg2D,iBAAiBvuF,KAAKxI,KAAKuvC,iBAAiBynD,6BAKjDh3F,KAAK8vC,aAAac,YAAY9mB,IACvB,GArEM,aAAd,c,0BAA4B,iB,6BACd,aAAd,c,0BAA4B,M,6BACd,aAAd,c,0BAA6B,M,8BACf,aAAd,c,0BAAsC,M,uCACxB,aAAd,c,0BAAkC,M,+DCN9B,MAAM,EAQX,YAA4B/gB,GAAA,KAAAA,WAG5B,YACE,MAAO,qBAGT,eACE,MAAO,IAAI,IAGN,WAAWg4B,GAChB,OAAOl6B,OAAOk6B,EAAKzN,iBAAiBgL,OAG/B,YAAYyC,EAA0BlgC,GAC3C,IAAIkG,EAASF,OAAOhG,EAAIkG,QAGxB,GAAI,IAAaqL,sBAAsBvR,GACrC,OAAO,EAKT,GAAIkG,EAAOiF,SAAS,GAAG,MAAuBjF,EAAOiF,SAAS,GAAG,KAE/D,OADA,YAAS,iCACF,EAIT,IACI8d,EADU/iB,EAAOC,QAAQhH,KAAK02F,UAAU1vF,QAAQ,IAAI,KACrCmH,KAAK,iBAGxB,SAAIpH,EAAO0+B,GAAG,OAAQ1+B,EAAO2H,SAAS+2B,GAAG,QAKzCzlC,KAAK8vC,aAAac,YAAY9mB,GAE9BiX,EAAK61D,YAAYpuF,KAAK,CAAE0b,cAAe4F,EAAM2wB,QAAQ,KAE9C,IAjDM,aAAd,c,0BAA4B,iB,6BACd,aAAd,c,0BAA4B,M,6BACd,aAAd,c,0BAAsC,M,uCACxB,aAAd,c,0BAAkC,M,2ECd9B,MAAM,EAMX,YAA4B1xC,GAAA,KAAAA,WAG5B,YACE,MAAO,0BAGT,eACE,MAAO,IAAI,gBAGN,WAAWg4B,GAChB,OAAOl6B,OAAOk6B,EAAKzN,iBAAiBgL,OAG/B,YAAYyC,EAA0BlgC,GAC3CA,EAAI0L,iBACJ1L,EAAIgM,kBAEJ,IACIwH,EADcxN,OAAOhG,EAAIkG,QAAQ+lE,QAAQ,IAAI,KACf3+D,KAAK,mBAEvCnO,KAAKi3F,sCAAsCC,yBAAyB7iF,IAzBvD,aAAd,c,0BAAgC,M,iCAClB,aAAd,c,0BAA2D,M,4ECFvD,MAAM,UAA8B,IAKzC,YAA4BtL,GAC1BjJ,QAD0B,KAAAiJ,WAI5B,YACE,MAAO,wBAGT,eACE,MAAO,iCAGF,WAAWg4B,GAChB,OAAOl6B,OAAOk6B,EAAKzN,iBAAiBgL,OAG/B,aAAa/K,EAAwB1yB,GAC1C,IAIIipB,EAJSjjB,OAAOhG,EAAIkG,QAGHC,QAAQ,IAAI,KACdmH,KAAK,iBAMxB,OAJAnO,KAAKmD,mBAAmB1B,OAAOqoB,GAE/BjpB,EAAI0nC,2BACJ1nC,EAAI0L,kBACG,GA9BM,aAAd,c,0BAA4B,M,6BACd,aAAd,c,0BAAwC,M,yCCCpC,MAAM,EASX,YAA4BxD,GAAA,KAAAA,WAG5B,YACE,MAAO,qBAGT,eACE,MAAO,IAAI,IAGN,WAAWg4B,GAChB,OAAOl6B,OAAOk6B,EAAKzN,iBAAiBqH,2BAK/B,YAAYoG,EAA0BlgC,GAE3C,GAAIA,EAAI0R,UAAY1R,EAAIyR,SAAWzR,EAAI2R,SAAW3R,EAAI41F,OACpD,OAAO,EAIT,MAAM1vF,EAASF,OAAOhG,EAAIkG,QACpB6oB,EAAU7oB,EAAOC,QAAQhH,KAAK02F,UAC9B5lF,EAAQ8e,EAAQzhB,KAAK,WACrB+V,EAAgB0L,EAAQzhB,KAAK,iBAGnCpH,EAAOC,QAAQ,KAAKqG,OAMpB,IACI2oB,EADMjvB,EAAOC,QAAQ,IAAI,KACHmH,KAAK,oBAC1B8iB,EAAO5sB,GAAK08B,EAAKzN,iBAAiBqjE,gBAAgB3gE,GASvD,OANAh2B,KAAKuvC,iBAAiB05C,aAAa/kE,EAAe+M,GAElD8P,EAAK4nD,iBAAiBngF,KAAK,CAAE0b,cAAeA,EAAey2B,eAAgB7pC,IAE3EjQ,EAAI0L,iBACJ1L,EAAIgM,mBACG,GArDM,aAAd,c,0BAA4B,iB,6BACd,aAAd,c,0BAA6B,M,8BACf,aAAd,c,0BAA4B,M,6BACd,aAAd,c,0BAAsC,M,uCACxB,aAAd,c,0BAAkC,M,+DCZ9B,MAAM,EAKX,YAA4B9D,EACTwqB,GADS,KAAAxqB,WACT,KAAAwqB,QAEjBvzB,KAAK6C,eACF0tC,WACApwC,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,uBAE3B58D,UAAU,KACT,GAAIkzB,EAAMsF,aAAa5xB,OAAS,EAAG,CAEjC,IAAIy4B,EAAKC,YAAY/Y,MAErB2M,EAAM6jE,cAEN,IAAIv3D,EAAKF,YAAY/Y,MAErB,YAAS,uBAAyBiZ,EAAKH,GAAM,sBApBtC,aAAd,c,0BAAgC,M,iCAClB,aAAd,c,0BAAoC,M,mHCKhC,MAAM,GAKX,YAA4B32B,EAChBwqB,GADgB,KAAAxqB,WAG1B/I,KAAKmD,mBACFotC,WACApwC,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,sBAC1B,OAAA/tD,EAAA,GAAK4B,GAAUA,EAAMtP,WACrB,OAAAg4C,EAAA,MAEDn5C,UAAU,KAEJL,KAAKmD,mBAAmBy5B,WAC3BrJ,EAAM2L,2BAIZ,IAAIm4D,EAAYr3F,KAAKmD,mBAAmBy5B,UAExC58B,KAAKmD,mBACFotC,WACApwC,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,sBAC1B,OAAA1xD,EAAA,GAAO,IAAMvL,KAAK4C,WAAW0C,cAAchD,aAE5CjC,UAAWyQ,IAENA,EAAMtP,YAAc61F,GACtBr3F,KAAKs3F,qBAAqBxmF,GAG5BumF,EAAYvmF,EAAMtP,YAOhB,qBAAqBsP,GAC3B,MAAM4pB,EAAW16B,KAAK4C,WAAW0C,cAAca,MAG/CU,OAAO,iCAAiC6D,YAAY,CAACqS,EAAUw6E,KACrDA,EAAW5+B,MAAM,2BAA6B,IAAI71C,KAAK,MAKjE,MAAMgR,EAAuC,GAG7CzvB,EAAEC,KAAKwM,EAAMgjB,UAAW,CAAC0jE,EAAqB1tE,KAE5CjjB,OAAO,IAAI,aAAmBijB,qCAAwCiR,YAAY,KAAyBy8D,GAG3G,MAAMj7D,EAAgBrxB,SAAS2O,cAAc,sCAAsCiQ,GAE/EyS,IACEi7D,EACFj7D,EAAchsB,UAAUC,IAAI,8BAE5B+rB,EAAchsB,UAAUkiB,OAAO,+BAKnC,MAAMqI,EAAWj0B,OAAO,IAAI,aAAoBijB,IAGhDgR,EAASC,YAAY,aAAoBjR,GAAO0tE,GAGhD18D,EAASvvB,OAAO,IAAI,KAAqBjH,KAAK,CAACyY,EAAG9K,KAEhD,MAAMgf,EAAQpqB,OAAOoL,GAAIgf,QAGpB6C,EAAU7C,KACbyJ,EAASzJ,GAAOkF,OAASqhE,EACzB1jE,EAAU7C,GAASumE,OAOrB1mF,EAAM0nB,MACR,YAAuB1nB,EAAM0nB,MAI/Bx4B,KAAK4C,WAAW0C,cAActB,SAAS02B,EAAU,yDA/FpC,aAAd,c,0BAAwC,M,0CAC1B,aAAd,c,0BAAgC,M,kCCZ5B,MAAM,GAKX,YAA4B3xB,EAChBwqB,GADgB,KAAAxqB,WAG1B/I,KAAKqD,uBACFktC,WACApwC,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,uBAE3B58D,UAAU,KACTkzB,EAAM2L,4BAZG,aAAd,c,0BAA4C,M,8CAC9B,aAAd,c,0BAAgC,M,gECA5B,MAAM,GAOX,YAA4Bn2B,EACTwqB,GADS,KAAAxqB,WACT,KAAAwqB,QAGjBvzB,KAAK4C,WACFqD,YACA/F,UACAC,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,uBAE3B58D,UAAU,KACT,IAAI2+B,EAGFA,EADEh/B,KAAKgD,cAAcmvC,oBACdnyC,KAAKuD,aAAasyF,sBAElB71F,KAAK4C,WAAWkB,QAAQqC,MAAO3B,SAGxC+uB,EAAMkkE,aAAaz4D,KAIvBh/B,KAAK2C,OAAOkT,aAAa+wD,gBACtBzmE,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,qBAAqBp1D,gBAC/C,OAAA0D,EAAA,GAAO,KACL,IAAImvB,EAAW16B,KAAK4C,WAAW0C,cAAcmO,WAAW,IACxD,OAAOinB,GAAYA,EAASzzB,OAAS,KAGxC5G,UAAU,EAAEq3F,EAAW/xF,WACX+F,IAAP/F,GAIJ3F,KAAKuzB,MAAMokE,YAAYhyF,MAzCd,aAAd,c,0BAAyB,M,kCACX,aAAd,c,0BAA4B,O,qCACd,aAAd,c,0BAA2B,O,oCACb,aAAd,c,0BAAqB,M,+CCAjB,MAAM,GAOX,YAA4BoD,EACAwqB,GADA,KAAAxqB,WACA,KAAAwqB,QAG1BvzB,KAAK4C,WAAW0C,cAAcpF,UAC3BC,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,uBAE3B58D,UAAU,KAETL,KAAK8vC,aAAa8nD,cAAe9tE,IAC/B,MAAM8F,EAAU,YAAe9F,GAC3B8F,EAAQ3oB,SACV,YAAuB6iB,GACvB9pB,KAAKuqB,YAAYkT,aAAa7N,GAAS,QAO/C5vB,KAAKuvC,iBAAiBu5C,QACnB3oF,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,uBAE3B58D,UAAWyQ,IACV9Q,KAAK63F,qBAAqB/mF,KAI9B9Q,KAAKuvC,iBAAiBuoD,0BAA0B,IACvCvkE,EAAMwL,cAEf/+B,KAAKuvC,iBAAiBwoD,8BAMhB,qBAAqBjnF,GAC3B,MAAMse,EAAUvoB,OAAO7G,KAAKuzB,MAAMoH,2BAElCvL,EAAQ5jB,KAAK,IAAI,OAAqB,OAAoBd,YAAY,KAEtErG,EAAEC,KAAKwM,EAAMy0B,SAAU,CAACA,EAAkBrhB,KACxCkL,EAAQ5jB,KAAK,IAAI,6BAA2C0Y,OAAmB6W,YAAY,IAAkBwK,MAlDlG,aAAd,c,0BAAsC,M,wCACxB,aAAd,c,0BAAkC,M,oCACpB,aAAd,c,0BAAgC,M,kCAClB,aAAd,c,0BAAiC,O,oDCZ7B,MAAM,GAKX,YAAqBx8B,EACAwqB,GADA,KAAAxqB,WACA,KAAAwqB,QAEnBvzB,KAAKY,gBACFkoF,QACA3oF,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,uBAE3B58D,UAAWyQ,IACV9Q,KAAKg4F,iBAAiBlnF,EAAMyT,WAO1B,iBAAiBA,GACvB,MAAMtD,EAAYpa,OAAO7G,KAAKuzB,MAAMoH,2BAA2BjsB,SAC/DuS,EAAUzV,KAAK,+CAA+C/J,OAAO8iB,GACrEtD,EAAUzV,KAAK,4CAA4CuvB,YAAY,oBAAqBxW,IAtB/E,aAAd,c,0BAAgC,M,kCAClB,aAAd,c,0BAAqC,O,wDCJjC,MAAM,GAKX,YAA4Bxb,EAChBwqB,GADgB,KAAAxqB,WAE1B/I,KAAKoD,oBACFmtC,WACApwC,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,sBAC1B,OAAAzjB,EAAA,MAEDn5C,UAAU,IAAMkzB,EAAM6jE,gBAXZ,aAAd,c,0BAAyC,O,2CAC3B,aAAd,c,0BAAgC,M,2JCY5B,MAAM,GAcX,YAA4BruF,EACTwqB,GADS,KAAAxqB,WACT,KAAAwqB,QAIQ,OAArBvzB,KAAKogD,cAITpgD,KAAKi4F,oBAAoBpnD,4BACtB1wC,KAAK,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,uBAC/B58D,UAAiBypB,GAAS,4CACzB,MAAMk3B,QAAiBhhD,KAAKuD,aAAaiN,IAAIxQ,KAAKkhD,aAAcp3B,GAChE9pB,KAAKk4F,oBAAoBl3C,OAG7BhhD,KAAK4C,WAAWq6D,qBACb98D,KAAK,OAAAi3C,GAAA,GAAK,IACV/2C,UAAU,KACTL,KAAKogD,YAAa3tB,OAAOzyB,KAAKuzB,MAAM+K,SAGxCt+B,KAAKogD,YAAYb,SAAS,CACxBgB,cAAevgD,KAAKuzB,MAAM+K,MAC1BkiB,iBAAkB,CAACxgD,KAAKuzB,MAAM8K,iBAC9BuiB,QAAS,KAAM,EACfH,MAAO,CAACxuC,EAAQzK,EAAYmwB,KAC1B,IAAKA,EAAOpnB,UAAUlF,SAAS,kCAC7B,OAAO,EAGT,MAAMye,EAAc7X,EAAGxB,QAAQyT,cACzBlb,EAAchJ,KAAK2C,OAAOkT,aAAanR,IAAIolB,GAAM3jB,MACvD,QAAS6C,GAAehJ,KAAKo3B,cAAcC,UAAUruB,IAEvD83C,QAAS,CAAO7uC,EAAgBlL,EAAoBS,EAAoB2wF,IAA6B,4CACnG,MAAMruE,EAAc7X,EAAGxB,QAAQyT,cAC/B,IAAIk0E,EAEJ,IACE,MAAMpvF,QAAoBhJ,KAAKyD,aAAamC,cAAcsC,GAAG4hB,GAAMplB,MAAMmoB,YAEzE,GAAI,YAAuBsrE,GAAU,CACnC,MACME,EADyBn7E,MAAM3B,KAAK48E,EAAS5nF,WAAW/E,KAAK+lB,GAAaA,EAAU3Y,SAAS,iBACnDiI,QAAQ,eAAuB,IACzEy3E,EAAyB9wF,EAAO+wF,uBAAuB,aAAoBF,IAC3EG,EAA0BF,EAAuBA,EAAuBrxF,OAAS,GACvFmxF,EAAWp4F,KAAKy4F,aAAaD,QAE7BJ,EAAWp4F,KAAKy4F,aAAaxmF,GAG/B,MAAM+uC,QAAiBhhD,KAAKuD,aAAa09C,KAAKjhD,KAAKkhD,aAAcp3B,EAAMsuE,SAEjEp4F,KAAKo3B,cAAcshE,WAAW1vF,EAAaiJ,GACjDjS,KAAKk4F,oBAAoBl3C,GACzBhhD,KAAKo3B,cAAcuhE,WAAW33C,GAG9B,IAAIn9C,EAAQ7D,KAAK4C,WAAWiB,MAAMsC,MAC9BtC,GAAS7D,KAAKgD,cAAc41F,sBAAsB/0F,WAC9C7D,KAAK24C,cAAcv+B,KAAKvW,IAEhC,MAAOyI,GACPtM,KAAKoqC,gBAAgByD,eAAevhC,GAGpCtM,KAAKo3B,cAAcyhE,oBAAoB5mF,GAAI,GAE3C,KAAmBg3C,SAASh3C,EAAIA,EAAGxB,QAAQqoF,cAAgB,EAAGtxF,OAGlE45C,UAAYnvC,IACV,MAAM6X,EAAc7X,EAAGxB,QAAQyT,cACzB88B,EAAWhhD,KAAKuD,aAAakvB,OAAOzyB,KAAKkhD,aAAcp3B,GAC7D9pB,KAAKk4F,oBAAoBl3C,IAE3BK,QAAgBpvC,GAAmB,4CACjC,MAAM6X,EAAc7X,EAAGxB,QAAQyT,cACzBlb,QAAoBhJ,KAAKyD,aAAamC,cAAcsC,GAAG4hB,GAAMplB,MAAMmoB,YACnEurE,EAAWp4F,KAAKy4F,aAAaxmF,GAEnC,OAAOjS,KAAKo3B,cACTshE,WAAW1vF,EAAaiJ,GACxBxC,KAAK,IAAY,4CAChB,MAAMuxC,QAAiBhhD,KAAKuD,aAAaiN,IAAIxQ,KAAKkhD,aAAcp3B,EAAMsuE,GAItE,OAHAp4F,KAAKk4F,oBAAoBl3C,GACzBhhD,KAAKo3B,cAAcuhE,WAAW33C,IAEvB,MAERxmC,MAAM,KAAM,MAEjBu+E,SAAU,CAAO7xE,EAAmB8xE,IAAyB,4CAE3D,MAAMlvE,EAAckvE,EAASvoF,QAAQyT,cAC/Blb,QAAoBhJ,KAAKyD,aAAamC,cAAcsC,GAAG4hB,GAAMplB,MAAMmoB,YAEnE8G,EAAUzM,EAAMjb,SAAShF,OACzBoJ,EAAKnF,SAASoF,cAAc,MAClCD,EAAGkB,YAAcvI,EAAYiwF,gBAC7B5oF,EAAGy+B,QAAUnb,EACbtjB,EAAGE,UAAUC,IAAI,oBAAqB,WAEtC0W,EAAMlF,MAAMk3E,SAAW,QACvBhyE,EAAM6M,UAAY1jB,EAAGy6B,aAEvBquD,iBAAmBlnF,IACZjS,KAAKkmD,gBAAgBkzC,QACxBp5F,KAAKo3B,cAAcyhE,oBAAoB5mF,IAG3CiI,SAAWjI,IACJjS,KAAKkmD,gBAAgBkzC,QACxBp5F,KAAKo3B,cAAcyhE,oBAAoB5mF,GAAI,OASrC,oBAAoB2gD,G,mDAChCA,EAAQvuD,EAAEu9C,KAAKgR,GAEf,MAAMymC,QAAoB9pF,QAAQu0B,IAChC8uB,EAAM1jD,IACJ4a,GAAQ9pB,KAAKyD,aAAamC,cAAcsC,GAAG4hB,GAAMplB,MAAMmoB,cAK3D7sB,KAAKuzB,MAAMkkE,aAAa4B,MAG1B,oBACE,OAAOr5F,KAAKm3B,mBAAmBzyB,IAAI1E,KAAK+I,UAG1C,mBACE,OAAO/I,KACJs5F,qBACApqF,IAAK2kB,GAAQA,EAAI3P,eAGtB,2BACE,OAAOlkB,KACJ4C,WACAm6D,qBACAtpD,WAAW,IAQR,aAAaxB,GAEnB,OADaiL,MAAM3B,KAAKvb,KAAKuzB,MAAM+K,MAAMi6D,uBAAuB,MACpDn7E,QAAQnL,IAAO,GA5Kd,aAAd,c,0BAAsC,M,8BACxB,aAAd,c,0BAA0C,M,kCAC5B,aAAd,c,0BAAmD,O,2CACrC,aAAd,c,0BAA+C,O,uCACjC,aAAd,c,0BAA6C,O,qCAC/B,aAAd,c,0BAA4C,O,oCAC9B,aAAd,c,0BAA+C,O,uCACjC,aAAd,c,0BAA4C,O,oCAC9B,aAAd,c,0BAA6C,O,qCAC/B,aAAd,c,0BAAkD,O,0CACZ,aAAtC,YAAY,KAAoB,M,uFC3B5B,MAAM,GAKX,YAA4BlJ,EAChBwqB,GADgB,KAAAxqB,WAE1B/I,KAAKi3F,sCACF1mD,WACApwC,KACC,OAAAg3F,EAAA,GAAUn3F,KAAK4C,WAAWq6D,sBAC1B,OAAAzjB,EAAA,MAEDn5C,UAAWk5F,GAAwBhmE,EAAMimE,uBAAuBD,EAAoBzoF,SAX1E,aAAd,c,0BAA2D,M,6DAC7C,aAAd,c,0BAAgC,M,kCC6B5B,MAAM,WAA6B,KAA1C,c,oBAEY,KAAA2oF,cAAiE,CAEzE,IAAM,IAAI,EAAsBz5F,KAAK+I,UAErC,IAAM,IAAI,EAAgB/I,KAAK+I,UAE/B,IAAM,IAAI,EAA6B/I,KAAK+I,UAE5C,IAAM,IAAI,EAAgB/I,KAAK+I,UAE/B,IAAM,IAAI,EAAsB/I,KAAK+I,UAErC,IAAM,IAAI,EAAgB/I,KAAK+I,UAE/B,IAAM,IAAI,EAA6B/I,KAAK+I,UAE5C,IAAM,IAAI,EAAwB/I,KAAK+I,UAEvC,IAAM,IAAI,EAA2B/I,KAAK+I,UAE1C,IAAM,IAAI,EAAqB/I,KAAK+I,WAGnB,KAAA2wF,kBAAwC,CACzD,GACA,GACA,EACA,GACA,GACA,GACA,GACA,GACA,IAGF,SAASC,GACP35F,KAAK05F,kBAAkBxqF,IAAKg0C,GACnB,IAAIA,EAAIljD,KAAK+I,SAAU4wF,EAAQrmE,mBAGxCxzB,MAAM85F,SAASD,I,qECrDnB,MAAME,GAAqB,cAEpB,MAAMC,GAYX,YAAoBC,GAAA,KAAAA,mBAVZ,KAAAC,mBAAoC,KAEpC,KAAAC,cAAiBp5F,IACvB,MAAMkG,EAASlG,EAAIkG,OACfA,GAAUA,IAAW/G,KAAKg6F,oBAC5Bh6F,KAAKk6F,YAAYnzF,GAEnB/G,KAAKg6F,mBAAqBjzF,GAM5B,WACEyZ,OAAOpV,iBAAiB,YAAapL,KAAKi6F,cAAe,CAAEE,SAAS,IAGtE,aACE35E,OAAO66D,oBAAoB,YAAar7E,KAAKi6F,eAC7Cj6F,KAAKo6F,wBAGC,sBAAsBx+D,GAC5B,MAAMltB,EAASktB,EAAM50B,QAAQ,MAC7B,OAAsB,IAAlB0H,EAAOzH,OACF,KAEFyH,EAAO,GAGR,yBAAyBktB,GAC/B,MAAMltB,EAASktB,EAAM50B,QAAQ,wBAC7B,OAAsB,IAAlB0H,EAAOzH,OACF,KAEFyH,EAAO,GAGR,YAAYkhB,GAClB,MAAMhpB,EAAWC,OAAO+oB,GAClByqE,EAAiBr6F,KAAKs6F,sBAAsB1zF,GAC5C2zF,EAAoBv6F,KAAKw6F,yBAAyB5zF,GAGjC,OAAnByzF,GAAiD,OAAtBE,EAK/Bv6F,KAAKy6F,6BAA6BJ,EAAgBE,GAJhDv6F,KAAKo6F,wBAOD,qBAAqBvmE,GAC3B,OAAOwJ,SAASxJ,EAAImP,aAAa,yBAG3B,6BAA6Bq3D,EAA+BE,GAClE,MAAMG,EAA6B,OAAnBL,EAA0BA,EAAiBE,EACrDzwE,EAAO9pB,KAAK26F,qBAAqBD,GAEjCE,EAAkB56F,KAAK+5F,iBAAiBvuF,KAAK,aAAese,GAAM/f,QAClE8wF,EAAqB76F,KAAK+5F,iBAAiBvuF,KAAK,cAAgBse,GAAM7iB,OAChDjH,KAAK+5F,iBAAiBvuF,KAAK,cAAgBse,GAAM/f,QACjD/J,KAAK+5F,iBAAiBvuF,KAAK,uBAAyBse,GAAM/f,QAEtFs1B,sBAAsB,KACpBr/B,KAAKo6F,wBACLS,EAAYlwF,SAASkvF,IACrBe,EAASjwF,SAASkvF,MAId,wBACN75F,KAAK+5F,iBACFvuF,KAAK,gBACLd,YAAYmvF,K,oDCvGX,c,sBAEA,iB,sBACA,iB,sBACA,c,sBAWM,qB,0BAFJ,gBACE,iBACE,4BACF,OACF,Q,qBAFa,0C,0BAGb,gBAEE,wBAQF,Q,mCARc,+BAAuB,8DAAvB,CAAuB,2BAAvB,CAAuB,gCAAvB,CAAuB,kD,uBAWnC,iBACE,+BAEF,Q,0BALF,gBAEE,wBAIF,Q,qBAJgD,wD,0BAOpD,mBACA,gBACE,aACE,eACE,qBACA,eACE,iBAAQ,QAAwB,OAChC,QACF,OACF,OACF,OACF,OACA,Q,qBAVM,2CAIU,qCACR,oD,yBAOR,mB,qBAEO,mDAA4C,6D,uBAYvD,iBAEE,wBAGF,Q,MAHc,0EAA6D,mCAA7D,CAA6D,oD,wDAxE7E,gBACE,gBACE,kBACE,mBACE,uBAEA,uBACA,uBACA,uBACF,OACA,oBACE,eAAM,SAAqB,OAC3B,kBACA,gBAAM,SAA0B,OAClC,OACA,mBACE,cACE,wBAKA,wBAWA,wBAOF,OACF,OACA,2BAaA,oBACA,2BAMA,iBACA,iBAGA,OACF,OACF,OAEA,yBAOA,kBACE,iCACF,OACF,Q,oBA5Ea,wDAEc,kEACA,uDACd,wDAGC,kCAEA,uCAIA,wDAKA,kCAAmD,8BAYnD,6FAQiC,iEAclC,yEASH,wDAKH,kDCOA,MAAM,WAAmC,KA+C9C,YAAqBr5F,EACAuI,EACApG,EACAC,EACAlC,EACAb,EACAi7F,EACAh4F,EACAlC,EACAiC,EACAG,GACnBlD,QAXmB,KAAAU,aACA,KAAAuI,WACA,KAAApG,SACA,KAAAC,aACA,KAAAlC,OACA,KAAAb,QACA,KAAAi7F,OACA,KAAAh4F,iBACA,KAAAlC,kBACA,KAAAiC,iBACA,KAAAG,gBApDX,KAAA+zF,iBAAmB,IAAI,IACvB,KAAAH,YAAc,IAAI,IAClB,KAAAjO,iBAAmB,IAAI,IAE1B,KAAAllE,YAAc,KAAuBA,YAoCrC,KAAAs3E,gBAAiB,EAgBxB,WACE/6F,KAAKu3B,cAAgB,IAAI,KAA8Bv3B,KAAKg7F,qBAC5Dh7F,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eAGvC9G,KAAK4C,WAAWq6D,qBAAqB70D,OAErCpI,KAAKyoD,OAAS/nD,KAAK+nD,OAEnBzoD,KAAK4X,KAAO,CACVyC,OAAQ3Z,KAAKU,EAAE,oBACfghC,UAAW,CACT9f,MAAO5hB,KAAKU,EAAE,qCACdY,YAAatB,KAAKU,EAAE,4CAEtB25F,eAAgB,CAAC9mE,EAAcgmB,IACtBv5C,KAAKU,EAAE,mCAAoC,CAAE6yB,MAAOA,EAAOgmB,MAAOA,IAE3EghD,aAAcv6F,KAAKU,EAAE,kCACrB85F,kBAAmB,CACjBx6F,KAAKU,EAAE,2CACPV,KAAKU,EAAE,2CACPV,KAAKU,EAAE,0CACP0hB,KAAK,MAGY,OAAAq4E,GAAA,GAAc,CACjCn7F,KAAK4C,WAAWkB,QAAQ5D,UACxBF,KAAK8C,eAAegmF,QACpB9oF,KAAK6C,eAAeimF,QACpB9oF,KAAKY,gBAAgBkoF,QACrB9oF,KAAKgD,cAAc8lF,UAGN3oF,KACbH,KAAKI,kBACLC,UAAU,EAAEyD,EAASoB,EAASH,EAASq2F,EAAWjhE,MAClDn6B,KAAK6D,MAAQ7D,KAAK4C,WAAWiB,MAAMsC,MAEnCnG,KAAK8D,QAAUA,EAEf9D,KAAKkF,QAAUA,EACflF,KAAK+E,QAAUA,EAEf/E,KAAKq7F,gBAAkBr7F,KAAK+E,QAAQkC,OAAS,EAEzCjH,KAAKs7F,kBAAoBt7F,KAAKgqC,kBAAoBoxD,EAAU72E,SAC9DvkB,KAAKs7F,iBAAiBF,EAAU72E,SAGlCvkB,KAAKgqC,gBAAkBoxD,EAAU72E,QAEjCvkB,KAAKu7F,kBAAoBv7F,KAAKgD,cAAcmvC,oBAC5CnyC,KAAK+6F,eAAiB/6F,KAAKu7F,mBAAqBz3F,EAAQm2C,MAAQn2C,EAAQmwB,MAExEj0B,KAAKH,MAAMS,kBAGbN,KAAKH,MAAMS,gBAGN,cACLR,MAAM4Y,cACN1Y,KAAKw7F,iBAAiB9hF,aAGjB,iBAAiB+hF,EAA+ChlE,GACrE,MAAM6H,EAAQt+B,KAAK4G,SAAS4E,KAAK,gCAC3B6yB,EAAkBr+B,KAAK4G,SAAS4E,KAAK,kCAAkC,GAC7ExL,KAAKszB,iBAAmB,IAAI,KAC1BtzB,KAAK+I,SAEL/I,KAAK4G,SAAS,GAEdy3B,EAEAC,EAAM,GAEN7H,EAEAglE,EAEAz7F,KAAKu3B,eAEPv3B,KAAKs+B,MAAQA,EACbm9D,EAAWnoE,iBAAmBtzB,KAAKszB,iBACnC,IAAI,GAAqBtzB,KAAK+I,UAAU6wF,SAAS55F,MAGjD,MAAM+5F,EAAmB/5F,KAAK07F,6BAC9B17F,KAAK27F,aAAe5B,EAAiB,GACrC/5F,KAAKo4B,SAAW2hE,EAAiB,GAGjC/5F,KAAKw7F,iBAAmB,IAAI1B,GAAiB95F,KAAK4G,UAClD5G,KAAKw7F,iBAAiBl0F,WAGtBtH,KAAKs7F,iBAAmB,aAAiBt7F,KAAK4G,UAC9C5G,KAAKs7F,iBAAiBt7F,KAAKgqC,iBAE3BhqC,KAAKH,MAAMS,gBAGb,iBACE,OAAON,KAAKu3B,cAAcoZ,WAGpB,6BACN,MAAMirD,EAAa57F,KAAK4G,SAAS4E,KAAK,4CAChCqwF,EAAgB77F,KAAK4G,SAAS4E,KAAK,+CAEzC,GAA6B,IAAzBqwF,EAAc50F,QAAsC,IAAtB20F,EAAW30F,OAC3C,MAAM,IAAIyI,MAAM,iBAGlB,MAAO,CAACksF,EAAW,GAAIC,EAAc,K,uCAjL5B,IAA0B,mH,wBAA1B,GAA0B,owED7EvC,yB,KAA6D,sB,qIE4B7D,wOAgBO,MAAMC,EAA6B,IAAI,IAAe,0BAChDC,EAA8B,IAAI,IAAe,2BACjDC,EAAgC,IAAI,IAAe,6BAKnDC,EAAoB,WAG1B,MAAeC,UAA2B,IAO/C,YAAqBx7F,EACAF,EACwC2Y,EACN3W,EACGsW,EACrCjZ,EACAkJ,GACnBjJ,QAPmB,KAAAY,OACA,KAAAF,aACwC,KAAA2Y,SACN,KAAA3W,SACG,KAAAsW,UACrC,KAAAjZ,QACA,KAAAkJ,WAXd,KAAAiC,KAAOhL,KAaZA,KAAKwC,OAASxC,KAAKwC,QAAUxC,KAAKmZ,OAAO3W,OAAOi5C,WAAWz7C,KAAKyG,MAE5DzG,KAAKmZ,OAAOrI,OACd9Q,KAAKmZ,OAAOrI,MACT5Q,UACAC,KACCH,KAAKI,kBAENC,UAAW8Y,IAGV,IAFoBA,EAAO3W,OAAOi5C,WAAWz7C,KAAKyG,MAGhD,OAAOqS,EAAQY,YAAW,GAG5B1Z,KAAKmZ,OAASA,EACdnZ,KAAKwC,OAAS2W,EAAO3W,OAAOi5C,WAAWz7C,KAAKyG,MAC5CzG,KAAKgG,aACLhG,KAAKH,MAAMs8F,iBAKnB,WACEn8F,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eACvC9G,KAAKgG,aAGP,0BACE,OAAIhG,KAAK4G,SACA5G,KAAK4G,SACTI,QApDmC,oCAqDnCmH,KApDoC,yBAsDhC,KAIX,eACE,OAAOnO,KAAK8Y,QAAQG,SAGtB,YACE,OAAOjZ,KAAKud,SAASvd,KAAKyG,MAG5B,WAGE,OAAOzG,KAAKmZ,OAAO3W,OAAOitE,WAAWzvE,KAAK8Y,QAAQ1R,WAGpD,UAAiBjB,GACfnG,KAAKud,SAASvd,KAAKyG,MAAQzG,KAAKo8F,WAAWj2F,GAG7C,kBACE,MAAkB,YAAdnG,KAAKyG,KACAzG,KAAKU,KAAKU,EAAE,2BAGd,GAGT,eACE,OAAOpB,KAAKmZ,OAAO1W,kBAMX,cAMA,WAAWb,GACnB,OAAOA,G,sCA7FWs6F,GAAkB,yBASlBF,GAA6B,KAC7BF,GAA0B,KAC1BC,GAA2B,sB,uBAX3BG,EAAkB,mB,kCCtBxC,8DAGO,MAAMG,UAAmC,IAEpC,KAAKrzF,GACb,OAAOA,EAAY8gD,SAASwyC,UACzB7sF,KAAMk0B,GACEA,EAAWn/B,W,oCALb63F,I,yBAAAA,EAA0B,QAA1BA,EAA0B,Y,aAA1BA,I,kCCPb,kG,6UA6BO,MAAME,UAAsC,IAJnD,c,oBAKkB,KAAAr1F,MAAQlH,KAGjB,KAAAw8F,qBAAsB,EAKtB,KAAAC,WAAoB,EACpB,KAAAC,YAAqB,GACrB,KAAA9kF,KAAW,GAEX,KAAA+kF,WAAa38F,KAAKud,SAASq/E,iBAAiB58F,KAAKkH,MAAMT,MAE9D,WACE3G,MAAMqkB,WAENnkB,KAAK8Y,QAAQ+jF,iBAAiB,IAAM78F,KAAK88F,mBACzC98F,KAAK4X,KAAO,CACVmlF,gBAAiB/8F,KAAKU,KAAKU,EAAE,wCAC7BgZ,KAAMpa,KAAKU,KAAKU,EAAE,yBAA0B,CAAC6hB,UAAWjjB,KAAKwC,OAAOiE,OACpE4T,OAAQra,KAAKU,KAAKU,EAAE,2BAA4B,CAAC6hB,UAAWjjB,KAAKwC,OAAOiE,QAIrE,gBAAgB+5B,GAChBxgC,KAAKud,SAASpb,OACjBmL,WAAW,IAAMkzB,EAAO3B,QAAQkC,KAAKxzB,SAIlC,kBACL,OAAOvN,KAAKwgC,OACTw8D,wBACAvtF,KAAM7N,IACL5B,KAAK2pD,SAAW/nD,IAIf,gBAAgBuE,GAGjBnG,KAAK2pD,WAAaxjD,IACpBnG,KAAK2pD,SAAWxjD,GAIb,mBAML,OALAnG,KAAK88F,kBACFrtF,KAAK,KACJzP,KAAK8Y,QAAQuwD,sBAGV,EAGT,sBACE,MAAO,CACL9rD,SAAUvd,KAAKmZ,OAAOjX,iBACtBm/B,OAAQ,OACR47D,eAAgBj9F,KAAKi9F,eACrBntE,QAAS,CAAEyQ,IAAKvgC,KAAKwC,OAAOstB,SAAW9vB,KAAKwC,OAAOstB,QAAQyQ,MAI/D,qBACE,OAAOvgC,KAAK8Y,QAAQmkF,eAAej9F,KAAKud,UAGnC,QACDvd,KAAKwgC,QAAUxgC,KAAKwgC,OAAOv6B,cAC7BjG,KAAKwgC,OAAOK,QAAU7gC,KAAK2pD,SAE3B3pD,KAAKH,MAAMs8F,gBAIf,eACE,OAAIn8F,KAAKmG,OAASnG,KAAKmG,MAAMkT,IACpBrZ,KAAKmG,MAAMkT,IAEX,GAIX,aAAoBzX,GAClB5B,KAAKmG,MAAQ,CAAEkT,IAAKzX,GAGf,UACL,QAAS5B,KAAKmG,OAASnG,KAAKmG,MAAMkT,KAG1B,aACJrZ,KAAKud,SAASpb,OAASnC,KAAKwgC,QAE9BxgC,KAAK2Z,S,oCAjGE4iF,I,uBAAAA,EAA6B,qD,OAAA,K,KAM7B,KAAqB,G,09BANrBA,I,kCC7Bb,sL,2BAgBO,MAAMW,UAAuB,IAmBlC,YAAqB18F,EAC0BsR,EAC1BpR,EACAiC,EACAC,EACA+1C,EACAvO,EACAvqC,EACAD,GACnBE,MAAMgS,EAAQjS,EAAOW,GATF,KAAAA,aAC0B,KAAAsR,SAC1B,KAAApR,OACA,KAAAiC,SACA,KAAAC,aACA,KAAA+1C,gBACA,KAAAvO,kBACA,KAAAvqC,QACA,KAAAD,uBA1Bd,KAAAu9F,UAAmB,GACnB,KAAAC,WAAY,EACZ,KAAAC,UAAW,EACX,KAAA3zC,QAAS,EAIT,KAAA9xC,KAAO,CACZ0K,MAAOtiB,KAAKU,KAAKU,EAAE,+BACnBwW,KAAM5X,KAAKU,KAAKU,EAAE,8BAClBk8F,QAASt9F,KAAKU,KAAKU,EAAE,oBACrBm8F,WAAYv9F,KAAKU,KAAKU,EAAE,wBACxB4wF,0BAA2BhyF,KAAKU,KAAKU,EAAE,gCACvCusF,YAAa3tF,KAAKU,KAAKU,EAAE,yBACzBwlD,cAAe5mD,KAAKU,KAAKU,EAAE,oBAC3BylD,YAAa7mD,KAAKU,KAAKU,EAAE,yBAepB,UAAU+X,GACfnZ,KAAKo9F,UAAYjkF,EAAOikF,UACxBp9F,KAAKq9F,SAAWlkF,EAAOkkF,SAGlB,SACLr9F,KAAKw9F,eAAe12F,cAAcyG,QAGpC,mBACE,OAAO1G,OAAO,kCAGT,YAAY0kC,GACjB,GAAIvrC,KAAK0pD,SAAW1pD,KAAKm9F,UACvB,OAGFn9F,KAAK0pD,QAAS,EACd,MAAM7lD,EAAQ7D,KAAK4C,WAAWiB,MAAMsC,MACpCtC,EAAMsgC,OAASnkC,KAAKq9F,SAEpBr9F,KAAK24C,cACFp2C,OAAOsB,EAAO7D,KAAKm9F,WACnB1tF,KAAMguF,GACDz9F,KAAKo9F,YAAcK,EAAWx5D,QACzBjkC,KAAK24C,cAAcqhB,cAAcyjC,GAAYhuF,KAAK,IAAMzP,KAAKsnD,QAAQ/b,KAG9EvrC,KAAKsnD,QAAQ/b,GACNh8B,QAAQC,SAAQ,KAExBgL,MAAOwE,GAAchf,KAAKoqC,gBAAgByD,eAAe7uB,IACzDvP,KAAK,IAAMzP,KAAK0pD,QAAS,I,sCAhEnBwzC,GAAc,eAoBL,KAAkB,wE,uBApB3BA,EAAc,qD,OAAA,K,29BC5C3B,gBACE,gBAGE,gBACE,eAEA,cACE,cAEI,2CAAmB,EAAA51C,QAAA,MAEvB,OACF,OACF,OAEA,iBACE,gBACE,kBACA,gBACE,kBACE,uBAMI,0DANJ,OAQF,OACF,OACF,OAEA,sBACE,gBACA,iCAEI,oCAAY,EAAAgxB,UAAA,MAGhB,OACF,OAEA,kBACE,qBACQ,iCAAS,EAAAolB,YAAA,MAGjB,OACA,qBAEQ,iCAAS,EAAAp2C,QAAA,MACjB,OACF,OACF,OACF,OACF,Q,MAnDU,2CAME,yCAO6C,8CASzC,oCAOJ,6DAEA,0BAAe,wBAAf,CAAe,uBAUX,+CAAgC,mCAIhC,mD,sGCrBhB,kJ,mFC7BA,gBAGE,sBAGW,gEACT,gBACE,gBACE,2BACF,OACA,eACE,eACE,iCACF,OACA,eACE,mBAIE,eACF,OACF,OACF,OACF,OAEA,6BAGA,kCAAqB,2EACrB,OACF,OACF,O,uBA7Ba,0CAA2B,0BAA3B,CAA2B,iBAMhB,6CAQN,6CASE,6CAA8B,0BDW3C,MAAMq2C,UAAyC,IANtD,c,oBAOS,KAAAC,aAAe,sB,oCADXD,I,uBAAAA,EAAgC,quBCrC7C,uB,KAEE,+B,0FDmCWA,I,kCERb,0JAMO,MAAME,EAA8B,OAC9BC,EAA8B,OAIpC,MAAMC,UAAoD,IAC/D,YAA4Bp7F,EACAC,GAC1B9C,MAAM8C,GAFoB,KAAAD,SACA,KAAAC,aAIrB,WAAWiB,GAChB,OAAO7D,KAAKC,UAAY4D,EAAMsB,sBAGhC,eAAetB,GACb,OAAOA,EAAMsB,uBAAyB,KAGjC,aAAatB,GAClB,MAAM5D,EAAUD,KAAKC,QAGrB,OAFA4D,EAAMsB,sBAAoC,OAAZlF,OAAmByL,EAAYzL,GAEtD,EAGT,cACE,OAAOD,KAAK+W,iBAAiBtD,WAAW,MAG1C,aACE,MAAMxT,EAAUD,KAAKC,QACrB,OAAQA,GAAWA,IAAY49F,EAGjC,cACE,OAAO79F,KAAKC,UAAY69F,EAGnB,yBAAyBE,GAC9Bh+F,KAAKwU,OAAOwpF,I,sCAnCHD,GAA2C,sB,yBAA3CA,EAA2C,QAA3CA,EAA2C,a,qBCxCxD,IAAI7uF,EAAM,CACT,gBAAiB,CAChB,OACA,EACA,IAED,mBAAoB,CACnB,OACA,EACA,IAED,4BAA6B,CAC5B,OACA,EACA,IAED,+BAAgC,CAC/B,OACA,EACA,IAED,aAAc,CACb,OACA,EACA,EACA,GAED,gBAAiB,CAChB,OACA,EACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,GAED,wBAAyB,CACxB,OACA,EACA,GAED,sBAAuB,CACtB,OACA,EACA,GAED,yBAA0B,CACzB,OACA,EACA,GAED,oBAAqB,CACpB,OACA,EACA,GAED,uBAAwB,CACvB,OACA,EACA,GAED,8BAA+B,CAC9B,OACA,EACA,GAED,iCAAkC,CACjC,OACA,EACA,GAED,wBAAyB,CACxB,OACA,EACA,GAED,2BAA4B,CAC3B,OACA,EACA,GAED,4BAA6B,CAC5B,OACA,EACA,GAED,+BAAgC,CAC/B,OACA,EACA,GAED,mBAAoB,CACnB,OACA,EACA,GAED,sBAAuB,CACtB,OACA,EACA,GAED,uBAAwB,CACvB,OACA,EACA,GAED,0BAA2B,CAC1B,OACA,EACA,GAED,oBAAqB,CACpB,OACA,EACA,GAED,uBAAwB,CACvB,OACA,EACA,GAED,mBAAoB,CACnB,OACA,EACA,GAED,sBAAuB,CACtB,OACA,EACA,GAED,kBAAmB,CAClB,OACA,EACA,GAED,qBAAsB,CACrB,OACA,EACA,GAED,uBAAwB,CACvB,OACA,EACA,GAED,0BAA2B,CAC1B,OACA,EACA,GAED,0BAA2B,CAC1B,OACA,EACA,GAED,6BAA8B,CAC7B,OACA,EACA,GAED,kBAAmB,CAClB,OACA,EACA,IAED,qBAAsB,CACrB,OACA,EACA,IAED,WAAY,CACX,OACA,EACA,IAED,cAAe,CACd,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,oBAAqB,CACpB,OACA,EACA,IAED,YAAa,CACZ,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,iBAAkB,CACjB,OACA,EACA,IAED,oBAAqB,CACpB,OACA,EACA,IAED,aAAc,CACb,OACA,EACA,IAED,gBAAiB,CAChB,OACA,EACA,IAED,YAAa,CACZ,OACA,EACA,IAED,eAAgB,CACf,OACA,EACA,IAED,0BAA2B,CAC1B,OACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,IAED,0BAA2B,CAC1B,OACA,EACA,IAED,6BAA8B,CAC7B,OACA,EACA,IAED,wBAAyB,CACxB,OACA,EACA,IAED,2BAA4B,CAC3B,OACA,EACA,IAED,8BAA+B,CAC9B,OACA,EACA,GAED,iCAAkC,CACjC,OACA,EACA,IAGF,SAASC,EAAoBC,GAC5B,IAAIC,EAAoBC,EAAEJ,EAAKE,GAC9B,OAAOG,QAAQC,UAAUC,MAAK,WAC7B,IAAInD,EAAI,IAAIoD,MAAM,uBAAyBN,EAAM,KAEjD,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A,IAEA,KAEA,KAEA,KAEA,S,KAoEA,KAA0B,0jBApC1B,KACA,KACA,KAGA,KACA,KAGA,KACA,KAGA,KACA,KACA,KACA,KAGA,KACA,KAGA,IACA,IAGA,KACA,KAGA,KACA,KAEA,KAEA,KACA,GACA,IAEA,IAEA,GAGA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAEA,KACA,KAGA,KACA,GACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,GACA,GACA,GACA,GACA,GAEA,KACA,KAGA,KACA,IACA,KACA,IACA,KACA,KACA,GACA,EACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACAhB,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,KACA,KAGA,KACA,KACA,KAIA,KACA,KAGA,KACA,KACA,MAA2B,uD,KAlF3B,GAAkC,0jBA/ElC,KACA,KACA,KAGA,KACA,KAGA,KACA,KAGA,KACA,KACA,KACA,KAGA,KACA,KAGA,IACA,IAGA,KACA,KAGA,KACA,KAEA,KAEA,KACA,GACA,IAEA,IAEA,GAGA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAEA,KACA,KAGA,KACA,GACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,GACA,GACA,GACA,GACA,GAEA,KACA,KAGA,KACA,IACA,KACA,IACA,KACA,KACA,GACA,EACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACAA,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,KACA,KAGA,KACA,KACA,KAIA,KACA,KAGA,KACA,KACA,MAA2B,uD,KAvD3B,KAA+B,0jBA1G/B,KACA,KACA,KAGA,KACA,KAGA,KACA,KAGA,KACA,KACA,KACA,KAGA,KACA,KAGA,IACA,IAGA,KACA,KAGA,KACA,KAEA,KAEA,KACA,GACA,IAEA,IAEA,GAGA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAEA,KACA,KAGA,KACA,GACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,GACA,GACA,GACA,GACA,GAEA,KACA,KAGA,KACA,IACA,KACA,IACA,KACA,KACA,GACA,EACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACAA,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,KACA,KAGA,KACA,KACA,KAIA,KACA,KAGA,KACA,KACA,MAA2B,uD,KAF3B,KAA4B,0jBA/J5B,KACA,KACA,KAGA,KACA,KAGA,KACA,KAGA,KACA,KACA,KACA,KAGA,KACA,KAGA,IACA,IAGA,KACA,KAGA,KACA,KAEA,KAEA,KACA,GACA,IAEA,IAEA,GAGA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAEA,KACA,KAGA,KACA,GACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACA,GACA,GACA,GACA,GACA,GAEA,KACA,KAGA,KACA,IACA,KACA,IACA,KACA,KACA,GACA,EACA,KAGA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KAGA,KACAA,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,KACA,KAGA,KACA,KACA,KAIA,KACA,KAGA,KACA,KACA,MAA2B,wD,kCC3V/B,0EAMO,MAAMkB,EACX,YAAsBpmD,EACArzC,GADA,KAAAqzC,kBACA,KAAArzC,SAOf,kBAAkB5T,EACA20C,GAEvB,IAAI24D,EAAmBnxG,KAAKoxG,eAAevtG,EAAO20C,GAC9C64D,EAAgC9hG,QAAQC,UAc5C,OAZIxP,KAAKsxG,oBAEEtxG,KAAKuxG,cAAc1tG,EAAMqE,KAClCmpG,EAAerxG,KAAKwxG,sBAAsB3tG,EAAMqE,GAAI,MAEpDlI,KAAKqF,SAEIrF,KAAKyxG,oBAAoBN,KAClCE,EAAerxG,KAAKwxG,sBAAsB3tG,EAAMqE,GAAIipG,KAGtDnxG,KAAK+rB,IAAIloB,EAAMqE,GAAIipG,GACZE,EAGF,OAAOxtG,EAAqB20C,GACjC,IAAI24D,EAAmBnxG,KAAKoxG,eAAevtG,EAAO20C,GAElDx4C,KAAK+rB,IAAIloB,EAAMqE,GAAIipG,GAEnBnxG,KAAKwxG,sBAAsB3tG,EAAMqE,GAAIipG,GAGhC,WAAWttG,EAAqB20C,GACrC,IAAI24D,EAAmBnxG,KAAKoxG,eAAevtG,EAAO20C,GAIlD,OAFAx4C,KAAK+rB,IAAIloB,EAAMqE,GAAIipG,GAEZnxG,KAAKwxG,sBAAsB3tG,EAAMqE,GAAI,MAGvC,gBAAgBrE,EACA20C,GACrB,IAAI24D,EAAmBnxG,KAAKoxG,eAAevtG,EAAO20C,GAElD,OAAOx4C,KAAK0xG,WAAW7tG,EAAMqE,GAAIipG,GAG5B,kBAAkB10C,EACAD,EACAzvD,IACnB/M,KAAKsxG,mBAAqBtxG,KAAK0xG,WAAWj1C,EAAOD,MACnDx8D,KAAK+rB,IAAI0wC,EAAOD,GAEhBzvD,KAII,IAAI7E,EAAgBypG,GAC1B3xG,KAAKkI,GAAKA,EACVlI,KAAK2xG,SAAWA,EAGX,QACL3xG,KAAKkI,GAAK,KACVlI,KAAK2xG,SAAW,KAChB3xG,KAAK4xG,gBAAkB,KAGlB,kBACL,OAAQ5xG,KAAKkI,KAAOlI,KAAK2xG,SAGnB,cAAcE,GACpB,OAAO7xG,KAAKkI,KAAO2pG,EAGb,oBAAoBC,GAC1B,OAAO9xG,KAAK2xG,UAAYG,IAAkB9xG,KAAK2xG,SAGzC,WAAWE,EAAqBC,GACtC,MAAMC,IAAsB/xG,KAAKkI,GAC3B8pG,IAAuBhyG,KAAK2xG,SAC5BM,EAAajyG,KAAKkI,KAAO2pG,EAEzBK,EAAmBJ,IAAkB9xG,KAAK2xG,SAC1CQ,EAA0BnyG,KAAK2xG,WAAaG,GAAiB9xG,KAAK4xG,gBAExE,OAEGG,GAAqBC,KAGpBC,IAEEA,GAAaC,IAAoBJ,GAAiB9xG,KAAK4xG,mBAEvDG,GAAqBI,GAKrB,eAAetuG,EAAqB20C,GAC1C,OAAOx4C,KAAK8qD,gBAAgBzS,sBAAsBx0C,EAAOQ,EAAE+tG,KAAK55D,EAAY,CAAC,OAAQ,aAG/E,sBAAsBtwC,EAAgBypG,GAG5C,OAFA3xG,KAAK4xG,gBAAkBD,EAEhB3xG,KAAKyX,OAAOswB,GACjB,IACA,CAAElE,YAAa8tE,EAAUrqE,SAAUp/B,GACnC,CAAEw0D,OAAQ,CAAEC,QAAQ,M,sCAtHbu0C,GAA+B,iC,yBAA/BA,EAA+B,QAA/BA,EAA+B,a,kCCQ5C,kDAgBA,SAASmB,EAAWrqG,GAClB,IAAIkjB,EAAOrkB,OAAOmB,EAAMmG,KAAK+c,MAEzBljB,EAAMjB,SAAWmkB,EAAK1f,KAAK,6BAA6B9G,IAAI,KAC9DwmB,EAAK1f,KAAK,wBAAwBd,YAAY,QAAQc,KAAK,QAAQoB,QAAQ,KAE3E/F,OAAO,QAAQsjC,IAAI,QAASkoE,IAkBzB,SAASC,EAAmBpnF,GACjCA,EAAK1f,KAAK,mBAAmB5B,GAAG,QAAU5B,KAf5C,SAAmBkjB,GACjB,IAAIqnF,EAAYrnF,EAAK1f,KAAK,mBAErB+mG,EAAUvmG,SAAS,UACtBumG,EAAU/mG,KAAK,QAAQwB,UAAU,KAAmB,WAClDulG,EAAU/mG,KAAK,gBAAgB+B,QAE/B1G,OAAO,QAAQ+C,GAAG,QAAS,CAACshB,KAAMA,EAAKxmB,IAAI,IAAK2tG,MAElDE,EAAU5nG,SAAS,SAOnB6nG,CAAUtnF,GAGV,IAAInkB,EAASF,OAAOmB,EAAMjB,SACtBA,EAAO0+B,GAAG,eAAiB1+B,EAAOC,QAAQ,UAAUy+B,GAAG,gBACzDz9B,EAAMuE,qB,kCC1FZ,oEAyBO,MAAMkmG,EAA8B,IAzB3C,UAyB+C,GAAiD,oBAOzF,MAAeC,EAEpB,YAA4B3pG,GAAA,KAAAA,WAK5B,SAAS4wF,GACP35F,KAAKy5F,cAAcvqF,IAAIyjG,IACrB,IAAI75F,EAAU65F,EAAQhZ,GAOtB,OANa7gF,EAAQ85F,WAAWjZ,GAEzB/vF,GAAGkP,EAAQ+5F,MAAO/5F,EAAQ49E,SAAW71F,IAC1CiY,EAAQg6F,YAAYnZ,EAAS94F,KAGxBiY,O,oCChDb,8DAKO,MAAMi6F,EACX,YAA4BnwG,GAAA,KAAAA,aAGrB,gBAAgB+C,GAErB,MAAO,UAAUA,EAAGuC,GAGtB,oBACE,OAAOlI,KAAK4C,WAAW0C,cAAcmO,WAAW,IAG3C,iBAAiBuiB,GAGtB,OAFc3xB,EAAEy6B,UAAU9+B,KAAKgzG,cAAgBtyD,GAASA,EAAK1qB,kBAAoBA,GAK5E,0BAA0BngB,GAC/B7V,KAAK4C,WAAW0C,cAActB,SAC5B6R,EAAa3G,IAAKvJ,IACT,CACLqwB,gBAAiBh2B,KAAKg2B,gBAAgBrwB,GACtCue,cAAeve,EAAGuC,GAClBiuB,QAAQ,O,sCAzBL48E,GAA0B,Y,yBAA1BA,EAA0B,QAA1BA,EAA0B,a,4JCKhC,MAAME,EASX,YAA4BlqG,EAChB23C,GADgB,KAAA33C,WAI5B,YACE,MAAO,sBAGT,eACE,MAAO,WAGF,WAAW23C,GAChB,OAAO75C,OAAO65C,EAAKz/B,UAAUna,eAGxB,YAAY45C,EAAmC7/C,GACpD,IAAIkG,EAASF,OAAOhG,EAAIkG,QAGxB,GAAIA,EAAO0+B,GAAG,MAAQ1+B,EAAO2H,SAAS+2B,GAAG,KACvC,OAAO,EAIT,IAAI7V,EAAU7oB,EAAOC,QAAQ,kBACzB8iB,EAAO8F,EAAQzhB,KAAK,iBAExB,OAAK2b,IAIL9pB,KAAKkzG,kBAAkBxyD,EAAM52B,EAAM8F,EAAS/uB,IAErC,GAIC,kBAAkB6/C,EAAmC52B,EAAU8F,EAAgB/uB,GACvFb,KAAKipF,aAAavoC,EAAM52B,EAAM8F,EAAS/uB,GAEvC6/C,EAAKk2C,YAAYpuF,KAAK,CAAE0b,cAAe4F,EAAM2wB,QAAQ,IAG7C,aAAaiG,EAAmC52B,EAAa8F,EAAgB/uB,GACrF,IAAIm1B,EAAkBpG,EAAQzhB,KAAK,mBAC/B8iB,EAAQjxB,KAAKmzG,WAAWjqB,iBAAiBlzD,GAGvCn1B,EAAIyR,SAAWzR,EAAI2R,SAAW3R,EAAI0R,UACtCvS,KAAKuvC,iBAAiB05C,aAAan/D,EAAMmH,GAIvCpwB,EAAI0R,UACNvS,KAAKuvC,iBAAiBsnD,sBAAsB72F,KAAKmzG,WAAWH,cAAelpF,EAAMmH,IAI/EpwB,EAAIyR,SAAWzR,EAAI2R,UACrBxS,KAAKuvC,iBAAiBunD,UAAUhtE,GAGlC42B,EAAKq2C,iBAAiBvuF,KAAKxI,KAAKuvC,iBAAiBynD,6BAKjDh3F,KAAK8vC,aAAac,YAAY9mB,IA1EjB,aAAd,c,0BAA4B,M,oCACd,aAAd,c,0BAAqB,iB,6BACP,aAAd,c,0BAA+B,M,uCACjB,aAAd,c,0BAA2B,M,mCACb,aAAd,c,0BAAyB,M,iCCVrB,MAAMspF,EAIX,YAA4BrqG,EAChB23C,GADgB,KAAA33C,WAI5B,YACE,MAAO,yBAGT,eACE,MAAO,WAGF,WAAW23C,GAChB,OAAO75C,OAAO65C,EAAKz/B,UAAUna,eAGxB,YAAY45C,EAAmC7/C,GACpD,IAAIkG,EAASF,OAAOhG,EAAIkG,QAGxB,GAAIA,EAAO0+B,GAAG,MAAQ1+B,EAAO2H,SAAS+2B,GAAG,KACvC,OAAO,EAIT,IACI3b,EADU/iB,EAAOC,QAAQ,kBACVmH,KAAK,iBAExB,OAAK2b,IAIL42B,EAAKk2C,YAAYpuF,KAAK,CAAE0b,cAAe4F,EAAM2wB,QAAQ,KAC9C,IApCM,aAAd,c,0BAAqB,iB,6BACP,aAAd,c,0BAA+B,M,2FCE3B,MAAM,EAOX,YAA4B1xC,EAChB23C,GADgB,KAAA33C,WAI5B,YACE,MAAO,kCAGT,eACE,MAAO,WAGF,WAAW23C,GAChB,OAAO75C,OAAO65C,EAAKz/B,UAAUna,eAGxB,YAAY45C,EAAmC7/C,GACpD,IAAIkG,EAASF,OAAOhG,EAAIkG,QAIxB,GAAIA,EAAOC,QAAQ,IAAI,KAAoBC,OAEzC,OADA,YAAS,iDACF,EAGTpG,EAAI0L,iBACJ1L,EAAIgM,kBAGJ,MAAM+iB,EAAU7oB,EAAOC,QAAQ,kBACzB8iB,EAAO8F,EAAQzhB,KAAK,iBAE1B,IAAK2b,EACH,OAAO,EACF,CACL,IAAIkM,EAAkBpG,EAAQzhB,KAAK,mBAC/B8iB,EAAQjxB,KAAKmzG,WAAWjqB,iBAAiBlzD,GAExCh2B,KAAKuvC,iBAAiBC,WAAW1lB,IACpC9pB,KAAKuvC,iBAAiB05C,aAAan/D,EAAMmH,GAG3C,MAAMnY,EAAU,IAAI,IAA2B9Y,KAAK+I,SAAU+gB,EAAMjjB,OAAOhG,EAAIkG,QAAmB,GAAI25C,EAAK0nC,gBAC3GpoF,KAAKS,cAAcM,KAAK+X,EAASjY,GAGnC,OAAO,GAnDM,aAAd,c,0BAA+B,M,uCACjB,aAAd,c,0BAAyB,M,iCACX,aAAd,c,0BAA4B,M,oDCJxB,MAAM,UAAgC,IAA7C,c,oBAEY,KAAA44F,cAAyE,CAEjFnvB,GAAK,IAAI2oC,EAAiBjzG,KAAK+I,SAAUuhE,GAEzCA,GAAK,IAAI8oC,EAAoBpzG,KAAK+I,SAAUuhE,GAE5ClpE,GAAK,IAAI,EAAsBpB,KAAK+I,SAAU3H,O,kCCpBlD,0H,gFAmBO,MAAMiyG,EAMX,YAA8DvhG,EACzCqmC,EACAt4C,GAFyC,KAAAiS,SACzC,KAAAqmC,kBACA,KAAAt4C,QAGrB,WACMG,KAAK8R,OAAOq5C,UACdnrD,KAAKg4C,WAAah4C,KAAKm4C,gBAAgBshB,8BAA8Bz5D,KAAK8R,OAAO+nD,cAEjF75D,KAAKg4C,WAAah4C,KAAK8R,OAAO+nD,aAIlC,kBAGEvsD,WAAW,KACTtN,KAAK0mF,cAAc4sB,uBAAuB,KACxCtzG,KAAK8rB,QAAQJ,SACT1rB,KAAK8R,OAAOq5C,UACdnrD,KAAK8R,OAAO/E,SAAS/M,KAAK0mF,cAAc6sB,kBAExCvzG,KAAK8R,OAAO/E,SAAS/M,KAAK0mF,cAAciqB,qBAG5C3wG,KAAKH,MAAMS,kBAIf,cACE,OAAON,KAAK8R,OAAOga,S,sCApCVunF,GAAmC,KAM1B,KAA+B,sB,uBANxCA,EAAmC,qD,OAAA,K,6EAFnC,CAAC,CAAC,CAAE1tD,QAAS,IAA6BC,SAAU,SAAyC,0JxKjB1G,UACE,gCAIF,Q,MAHI,wCAAyB,6B,0XyKE3B,yB,qBACa,kCAAgC,0B,uCAkBzC,oCACwB,oEAEtB,qBACF,O,wBAFwB,uCACyB,iD,uCAEjD,oCACwB,gEAGtB,qBACF,O,wBAFwB,wCADA,sCAEwB,gD,wBAIpD,iB,qBACK,mC,yBAGH,iBACE,iBACE,8BAIF,OACF,Q,qBALsB,qCAAsB,uBAAtB,CAAsB,+B,wBAM5C,iB,qBAEM,wC,yBAGJ,aACE,kBACF,Q,yBADwB,kC,yBAF1B,gBACE,sBAGF,Q,qBAHM,mC,uCArDV,gBAEK,+DAAsB,yDAEzB,8BAMA,iBACE,sBACF,OACA,iBACE,QACA,yBACF,OACA,gBACE,0BAGA,gBAEE,2CAKA,2CAMF,OACF,OACA,wBAGA,kBACE,wBAQA,wBAIA,uBAKF,OACF,O,uBAtDe,gCAOA,4BAGX,kFACc,mDAGC,0CAA2B,2BAIrC,2CACqB,oCAKA,mCAQvB,sCAIE,8BAQA,8DAIgD,mCCElD,MAAM4tD,UAA8B,IA6BzC,YAAqBhzG,EACAuI,EACA0qG,EACA/4F,EACAg5F,EACAC,EACA13F,EACAxY,EACA5D,EACAa,EACAkzG,GACnB9zG,MAAMU,EAAYuI,GAXC,KAAAvI,aACA,KAAAuI,WACA,KAAA0qG,eACA,KAAA/4F,aACA,KAAAg5F,qBACA,KAAAC,iBACA,KAAA13F,uBACA,KAAAxY,eACA,KAAA5D,QACA,KAAAa,OACA,KAAAkzG,SAjCd,KAAAC,aAAc,EACd,KAAAC,cAAe,EAMf,KAAAl3B,QAAgB,GAKhB,KAAAm3B,SAAU,EAEV,KAAAn8F,KAAO,CACZo8F,iBAAkBh0G,KAAKU,KAAKU,EAAE,uBAC9B6yG,iBAAkBj0G,KAAKU,KAAKU,EAAE,uBAC9B8yG,cAAel0G,KAAKU,KAAKU,EAAE,0BAC3B+yG,aAAcn0G,KAAKU,KAAKU,EAAE,0BAmBrB,WACLtB,MAAMqkB,WAENnkB,KAAKo0G,oBACLp0G,KAAKq0G,UAAoC,sBAAxBr0G,KAAKgxB,SAAS7oB,MAC/BnI,KAAKs0G,aAAuC,yBAAxBt0G,KAAKgxB,SAAS7oB,MAElCnI,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eACvC9G,KAAK2Z,QACL3Z,KAAK6zG,cAAgB7zG,KAAKgxB,SAASxc,OACnCxU,KAAK8zG,eAAiB9zG,KAAKgJ,YAAYs+E,WAEvCtnF,KAAK4G,SAASkG,KAAK,UAAW9M,KAAKuN,MAAMT,KAAK9M,OAC9CA,KAAK4G,SAASkG,KAAK,WAAY9M,KAAKqN,KAAKP,KAAK9M,OAE9CqE,EAAEC,KAAKtE,KAAKgxB,SAAS4rD,QAAUmM,IAC7B/oF,KAAK48E,QAAQ17E,KAAK6nF,EAAO+a,QAG3B9jG,KACGyD,aACAyd,MACAhZ,GAAGlI,KAAKgxB,SAASzqB,KAAK+U,YACtB5W,MACArE,UAAWkG,IACVvG,KAAKuG,KAAOA,EACZvG,KAAKu0G,OAAShuG,EAAK2B,GACnBlI,KAAKw0G,SAAWjuG,EAAKE,KACrBzG,KAAKy0G,WAAaluG,EAAK+a,OACvBthB,KAAKH,MAAMS,kBAGXkgB,OAAOgoB,SAASm4C,OAAS,aAAa3gF,KAAK0R,YAC7C1R,KAAK4zG,OAAOc,kBAAkB,KAC5BpnG,WAAW,KACTtN,KAAKQ,WAAWsG,cAAckgC,gBAAe,OAM9C,kBACL,SAAUhnC,KAAKq0G,WAAar0G,KAAKs0G,eAAiBt0G,KAAK20G,aAGlD,WACL70G,MAAMwH,SAAStH,KAAKgxB,SAASq2D,QAAQhuE,KACrCrZ,KAAKH,MAAMS,gBAGN,mBACL,OAAIN,KAAKiZ,WAAajZ,KAAK40G,WAClBrlG,QAAQC,UAEVxP,KAAK60G,gBAGP,eACL70G,KAAK2zG,eAAevsB,YAAYh/E,KAAKpI,KAAK80G,WAAW90G,KAAKgxB,SAASq2D,QAAQhuE,MAG7E,qBACE,OAAIhV,EAAEK,IAAI1E,KAAKgxB,SAAU,oBACb3sB,EAAEK,IAAI1E,KAAKgxB,SAAU,oBAAoBzrB,KAA5C,YAEA,KAIE,gB,mDAIX,OAHAvF,KAAKiZ,UAAW,QAEVjZ,KAAKwpE,WACJxpE,KAAK2zG,eAAekB,cAAc70G,KAAKgxB,SAAUhxB,KAAK40G,YAAc,IACxEnlG,KAAMslG,IACL/0G,KAAKgxB,SAAW+jF,EAChB/0G,KAAKo0G,oBACLp0G,KAAK0zG,mBAAmBjjF,QAAQzwB,KAAKgJ,aAAa,GAClDhJ,KACGyD,aACAmC,cACAC,MACAC,kBAAkB9F,KAAKgJ,eAE3BgsG,QAAQ,KACPh1G,KAAK0Z,YAAW,GAAO1Z,KAAKiZ,UAAW,OAItC,gBAELpS,OAAO,mBAAqB7G,KAAK0R,WAAa,MAAMnE,QAG/C,QACLvN,KAAK+zG,SAAU,EACf/zG,KAAKH,MAAMS,gBAGN,OACLN,KAAK+zG,SAAU,EACf/zG,KAAKH,MAAMS,gBAGN,YACL,OAAON,KAAK+zG,QAGd,UAAUzqC,IAIH,WAAWsrC,GAChB,IAAIK,EAASL,EAAWv8F,MAAM,MAC3BnJ,KAAI,SAASgmG,GACZ,MAAO,OAASA,KAEjBpyF,KAAK,IACR,OAAO9iB,KAAKw0G,SAAW,YAAcS,EAGvC,aACE,MAAO,4BAA4Bj1G,KAAK0R,WAG1C,WAAWnE,GACTzN,MAAM4Z,WAAWnM,GAEbA,GACFvN,KAAKm1G,gBAID,oBACNn1G,KAAKo1G,cAAgBp1G,KAAKyzG,aAAa4B,wBAAwBr1G,KAAKgxB,SAASq2D,QAAQyc,O,sCAjL5E0P,GAAqB,gH,uBAArBA,EAAqB,yzCDtDlC,wB,KACK,4B,wHE2BL,sL,uCCzBI,iBAGI,uEAIF,qBACF,O,wBAJI,qCAGO,yD,4DAIX,eAK8B,QAAqB,Q,qBADhD,sBACA,yBAAAtrG,IAHA,oEAG2B,mC,yBAC9B,YAAqB,QAAqB,Q,qBAArB,mC,wBAErB,qB,qBACS,oC,yBArBX,iBACE,uBAWA,oBAMA,oBAEA,0BAGF,Q,oBApBM,4CAUD,gCAKA,iCAIM,4C,wBAQT,qB,qBACS,oC,yBANX,iBACE,YACE,qBACA,QACF,OACA,0BAGF,Q,oBAPK,0CAED,mCAIO,4C,wBAGX,kB,oBACM,iC,yBAOJ,eAK8B,QAAqB,Q,qBADhD,sBACA,yBAAAA,IAHA,oEAG2B,mC,yBAE9B,YAAqB,QAAqB,Q,qBAArB,mC,wBAErB,qB,qBACS,oC,yBAbX,iBAGE,oBAOA,oBAEA,0BAGF,Q,oBAXK,gCAMA,iCAIM,4CDXN,MAAMotG,UAA4B,IAgCvC,YAAoBnyG,EACAH,EACAF,EACAO,EACA7C,EACAX,EACAa,GAClBZ,QAPkB,KAAAqD,qBACA,KAAAH,gBACA,KAAAF,iBACA,KAAAO,yBACA,KAAA7C,aACA,KAAAX,QACA,KAAAa,OA1Bb,KAAAkX,KAAO,CACZ29F,gBAAiBv1G,KAAKU,KAAKU,EAAE,mCAC7Bo0G,SAAUx1G,KAAKU,KAAKU,EAAE,sBACtBq0G,WAAY,kBA2Bd,kBACEnoG,WAAW,IAAMtN,KAAKgG,cAGhB,aACNhG,KAAK4vB,QAAU/oB,OAAO7G,KAAKQ,WAAWsG,eAEtC,YAAc,CACZ9G,KAAKgD,cAAc0yG,uBACnB11G,KAAKgD,cAAc8lF,UAElB3oF,KACCH,KAAKI,kBAENC,UAAU,KACT,IAAIs1G,EAAoB31G,KAAKgD,cAAc/C,QAAQ,GAE9C01G,GAAqB31G,KAAK41G,aAAajxG,QAAUgxG,EAAkBvlG,OAAOzL,MAG7E3E,KAAK61G,qBAAuBF,EAAkBpjE,UAF9CvyC,KAAK61G,qBAAuB,KAI9B71G,KAAK81G,uBAEL91G,KAAK+1G,SAAW/1G,KAAKgD,cAAcyoG,WAAWzrG,KAAK41G,cAEnD51G,KAAKg2G,eAAiBh2G,KAAKi2G,oBAE3Bj2G,KAAKH,MAAMS,kBAIfN,KAAKk2G,kBAA6C,YAAzBl2G,KAAK41G,aAAa1tG,GAEd,eAAzBlI,KAAK41G,aAAa1tG,KACpBlI,KAAKm2G,WAAa,QAEhBn2G,KAAKk2G,kBACPl2G,KAAKm2G,WAAa,YAC6D,WAAtEn2G,KAAKqD,uBAAuB48D,mBAAmBjgE,KAAK41G,eAC7D51G,KAAKm2G,WAAa,WAClBn2G,KAAKo2G,WAAcp2G,KAAK41G,aAAyC9iG,KAAKrM,MACS,WAAtEzG,KAAKqD,uBAAuB48D,mBAAmBjgE,KAAK41G,gBAC7D51G,KAAKm2G,WAAa,WAClBn2G,KAAKo2G,WAAa11G,KAAKU,EAAE,sBAAyBpB,KAAK41G,aAAqCx/E,eAI1Fp2B,KAAKk2G,oBACPl2G,KAAKq2G,cAAgB,iBACrBr2G,KAAKs2G,oBAAsBt2G,KAAK8C,eAAe85B,UAG/C58B,KAAK8C,eACFgmF,QACA3oF,KACCH,KAAKI,kBAENC,UAAU,KACTL,KAAKs2G,oBAAsBt2G,KAAK8C,eAAe85B,UAC/C58B,KAAKH,MAAMS,kBAIfN,KAAKmD,mBACF2lF,QACA3oF,KACCH,KAAKI,kBAENC,UAAU,KACTL,KAAKu2G,mBACLv2G,KAAKH,MAAMS,kBAIfN,KAAKu2G,oBAGPv2G,KAAKH,MAAMS,gBAGb,0BACE,OAAON,KAAKuzB,OAASvzB,KAAKuzB,MAAMgE,cAAcqX,kBAGhD,2BACE,OAAO5uC,KAAKuzB,OAASvzB,KAAKuzB,MAAMgE,cAAci6D,uBAGhD,gBAAgB3wF,GAQd,OAPIb,KAAKmD,mBAAmBqzG,eAC1Bx2G,KAAK8C,eAAe2zG,UAGtBz2G,KAAKu2G,mBAEL11G,EAAIgM,mBACG,EAGT,mBACM7M,KAAKmD,mBAAmBy5B,WAC1B58B,KAAK4X,KAAK29F,gBAAkB70G,KAAKU,EAAE,mCACnCpB,KAAKq2G,cAAgB,mBAErBr2G,KAAK4X,KAAK29F,gBAAkB70G,KAAKU,EAAE,mCACnCpB,KAAKq2G,cAAgB,qBAIjB,oBACN,IAAKr2G,KAAK61G,qBACR,MAAO,GAGT,OAAQ71G,KAAK61G,qBAAqBlxG,OAChC,KAAK,IACH,MAAO,MACT,KAAK,IACH,MAAO,OACT,QACE,MAAO,IAIb,uBACE3E,KAAK4vB,QAAQmL,YAAY,kBAAmB/6B,KAAK61G,uB,sCAxKxCP,GAAmB,wE,uBAAnBA,EAAmB,m/BC7ChC,gBAEE,uBAyBA,uBAUA,uBAKA,uBAiBF,Q,MA3D8C,8BAEH,yCAyBA,wCAYnC,sC,wPCpBD,MAAMoB,EAaX,YAAsBjzG,EACAiX,EACAonB,EACA5lB,EACAy6F,EACAj2G,EACAk2G,GANA,KAAAnzG,eACA,KAAAiX,aACA,KAAAonB,iBACA,KAAA5lB,qBACA,KAAAy6F,eACA,KAAAj2G,OACA,KAAAk2G,aAjBf,KAAAC,cAA6C,IAAI,IAA6B,MAI7E,KAAAj/F,KAAO,CACbk/F,cAAe92G,KAAKU,KAAKU,EAAE,iCAC3B21G,aAAe9sG,GAAgBjK,KAAKU,KAAKU,EAAE,2CACzC,CAAE6hB,UAAWjjB,KAAKU,KAAKU,EAAE,oCAAsC6I,KACjE+sG,aAAch3G,KAAKU,KAAKU,EAAE,iCAiBrB,cAAc0N,EAAgC9O,KAAK8hC,eAAehtB,WAAYo8C,GAAQ,GAC3F,OAAMA,QAAiCxlD,IAAxB1L,KAAKi3G,eAIbj3G,KAAKi3G,eAAiBj3G,KAC1ByD,aACAsyD,OACAmhD,WAAWpoG,GACX+d,YAPM7sB,KAAKi3G,eAaT,UAAUpiD,GACf,QAASA,EAAMvF,KAAK7pD,OAAOiwC,OAOtB,KAAKmf,GAEV,OADA70D,KAAKm3G,eAAetiD,GACb70D,KACJyD,aACAsyD,OACA7tD,GAAG2sD,GACHz6C,KAAKy6C,GAOG,OAAO32C,G,mDAClB,MAAM22C,QAAc70D,KACjByD,aACAsyD,OACAxzD,OAAO2b,EAAOpL,KAAM9S,KAAKo3G,UAAUl5F,GAASle,KAAK8hC,eAAehtB,WAAaoJ,EAAO+E,WAAW4J,YAUlG,MARoB,SAAhB3O,EAAOpL,WACH9S,KAAK42G,WAAWS,aAAaxiD,EAAO,CAAEpuD,KAAMzG,KAAK4X,KAAKo/F,qBAEtDh3G,KAAK22G,aAAajyG,IAAIwZ,EAAO+E,WAAYq0F,2BAA2BziD,SAGtE70D,KAAKoa,KAAKy6C,GAAOhoC,YAEhBgoC,KAGF,OAAOA,GACZ,OAAO70D,KACJyD,aACAsyD,OACA7tD,GAAG2sD,GACHnf,SACA7oB,YAMG,UAAU3O,GAChB,OAAIA,EAAOk5F,UACFl5F,EAAOk5F,UAGI,WAAhBl5F,EAAOpL,KACF9S,KAAK4X,KAAKm/F,aAAa74F,EAAO+E,WAGhCjjB,KAAK4X,KAAKk/F,cAOX,eAAejiD,GACrBA,EAAMvF,KAAK/0B,YAAc9S,KAAKyoD,IAAIrb,EAAMvF,KAAKI,QAAQzoD,OAAQ,GAC7D4tD,EAAMvF,KAAKI,QAAQxgD,IAAI,CAAC+C,EAAuBgf,KAC7Chf,EAAG29C,YAAc3+B,EAAQ,EACzBhf,EAAG+pE,UAAY/qD,EAAQ,EAChBhf,K,sCAjHAykG,GAAY,wE,yBAAZA,EAAY,QAAZA,EAAY,qBADC,U,kCCU1B,oF,iEC5BA,gBAEE,gBACE,qCAKF,OACA,gBACE,qCAIF,OACF,Q,oBAZ8B,uCAAwB,gCAAxB,CAAwB,oDAAxB,CAAwB,sBAOxB,uCAAwB,kDAAxB,CAAwB,qBDyB/C,MAAMa,G,sCAAAA,I,uBAAAA,EAA8B,yZCnC3C,sB,KAAK,4B,0EC4BL,oFAGO,MACMC,EAAkC,mDAExC,MAAMC,UAAsB,IAAnC,c,oBASS,KAAAn1D,mBAA4B,EAM5B,WACL,MAAO,kBAAkBtiD,KAAKw6C,WAGhC,oBACE,OAAIx6C,KAAK03G,sBACA13G,KAAKi9B,OAAO/tB,IAAI8P,GAASA,EAAMw7B,SAGjC,CAACx6C,KAAKw6C,SAGR,sBACL,OAAOx6C,KAAKqiD,kBAAoBm1D,EAG3B,wBACL,IAAIzyG,EAAU,GASd,OAPI/E,KAAK48E,QACP73E,EAAU,CAAC,CAAE63E,QAAS58E,KAAK48E,UAEpB58E,KAAKi9B,SACZl4B,EAAU/E,KAAKi9B,QAGV54B,EAAEkgC,QAAQx/B,EAAQmK,IAAKqO,GACxBA,EAAS8kC,kBAAoBm1D,EACxBx3G,KAAK23G,kBAAkBp6F,GAAU,GAEjCA,EAASq/D,QAAQ35D,YAKvB,0BACL,IAAI20F,EAAmB,GAoBvB,OAlBI53G,KAAK48E,QACPg7B,EAAa53G,KAAK48E,QAAQ35D,WAAa,CAACjjB,KAAKw6C,SAG7Cn2C,EAAEqB,QAAQ1F,KAAKi9B,OAASje,IACtB,GAAIA,EAAMqjC,kBAAoBm1D,EAAiC,CAC7D,MAAOv0F,EAAWymD,GAAY1pE,KAAK23G,kBAAkB34F,GACrD,IAAI/e,EAAU23G,EAAa30F,IAAc,GACzC20F,EAAa30F,GAAahjB,EAAQopB,OAAOqgD,QAChCkuC,EAAa54F,EAAM49D,QAAQ35D,WACpC20F,EAAa54F,EAAM49D,QAAQ35D,WAAW/hB,KAAK8d,EAAMw7B,SAGjDo9D,EAAa54F,EAAM49D,QAAQ35D,WAAa,CAACjE,EAAMw7B,WAK9Co9D,EAGC,kBAAkBr6F,GAI1B,MAAO,CAHSA,EAAS0f,OAAO,GAAG2/C,QAAQ35D,UAC5B1F,EAAS0f,OAAO/tB,IAAK+C,GAAqBA,EAAGuoC,a,kCClFhE,sIA4BO,MAAMq9D,UAAoC,IAS/C,YAAqBn3G,EACAb,EACAc,EACAC,GACnBd,QAJmB,KAAAY,OACA,KAAAb,QACA,KAAAc,iCACA,KAAAC,kBATd,KAAAgX,KAAW,CAChB8oC,KAAM1gD,KAAKU,KAAKU,EAAE,iBAClBgyD,KAAMpzD,KAAKU,KAAKU,EAAE,iBAClBg3B,SAAUp4B,KAAKU,KAAKU,EAAE,sBAUxB,WACuB,YAAc,CACjCpB,KAAKW,+BAA+BmoF,QACpC9oF,KAAKY,gBAAgBkoF,UAGR3oF,KACbH,KAAKI,kBACLC,UAAU,EAAEirB,EAAS8vE,MACrBp7F,KAAK83G,WAAWxsF,EAAS8vE,EAAU72E,SACnCvkB,KAAKH,MAAMS,kBAIR,WAAWgrB,EAAqB0e,GACjC1e,IAAY,IAMdtrB,KAAK+gC,KADHiJ,EACU,WAEA,IAPZhqC,KAAK+gC,KAAO,K,sCAhCL82E,GAA2B,0C,uBAA3BA,EAA2B,6SAdpC,mBAGE,oBACA,iBAIA,oBACF,Q,MANW,iEAGH,6C,4FCfZ,0HAiCO,MAAME,G,uBAAAA,I,oDAAAA,IAAuB,UAnBvB,CAET,IACA,IACA,KACD,SAVQ,CACP,IACA,IACA,S,oCChBJ,8GAcO,MAAMC,UAAoC,IAE/C,YAAmBp1G,EACA2sC,GACjBzvC,MAAM8C,GAFW,KAAAA,aACA,KAAA2sC,mBAIZ,UAAUrrB,GACf,OAAOlkB,KAAKyuD,qBAAuBvqC,EAG9B,cAAcnX,GACnB,MAAM5G,EAAQnG,KAAKC,QAEfkG,GAASA,EAAM8xG,mBACjBlrG,EAAS5G,EAAM+d,eACf/d,EAAM8xG,kBAAmB,EACzBj4G,KAAKwU,OAAOrO,IAIhB,yBACE,MAAMA,EAAQnG,KAAKC,QAEnB,GAAIkG,EACF,OAAOA,EAAM+d,cAIf,MAAMpgB,EAAU9D,KAAK4C,WAAWkB,QAAQqC,MACxC,OAAIrC,GAAWA,EAAQU,SAASyC,OAAS,EAChCnD,EAAQU,SAAS,GAAG0D,GAAIma,WAG1B,KAGF,cACL,OAAOriB,KAAK8oF,QACT3oF,KACC,YAAKyB,GAAqBA,EAAIsiB,eAC9B,eAIC,YAAYA,EAAsBg0F,GAA8B,GAEjEl4G,KAAKuvC,iBAAiBj4B,SACxBtX,KAAKuvC,iBAAiB6xC,YAAYl9D,GAAe,GAEnDlkB,KAAKwU,OAAO,CAAE0P,cAAeA,EAAe+zF,iBAAkBC,IAGhE,eAAer0G,EAAqBC,K,sCArDzBk0G,GAA2B,sB,yBAA3BA,EAA2B,QAA3BA,EAA2B,a,kCCbxC,kIAKO,SAASG,EAAwBlnG,EAA4BmnG,GAClE,OAAQzmD,IACN1gD,EAAU8Y,QAEH4nC,EAAQxxD,KACb,YACE,IAAM8Q,EAAUonG,YAAYD,GAC5B,IAAMnnG,EAAUqnG,OAChB,IAAMrnG,EAAUqnG,UAMjB,SAASC,EAA+BtnG,GAC7C,OAAQ0gD,IACNrkD,WAAW,IAAM2D,IAAY8Y,SAEtB4nC,EAAQxxD,KACb,YACE,OACA,IAAM8Q,IAAYqnG,OAClB,IAAMrnG,IAAYqnG,UAOnB,MAAME,EAcX,YAAmBvnG,GAAA,KAAAA,YAZX,KAAAwnG,kBACN,6SAcF,YAAmBxzE,GACjBjlC,KAAK+pB,QAGL,MAAM2uF,EAAU,IAAM14G,KAAKq4G,cAE3BpzE,EACGx1B,KAAKipG,GACLl+F,MAAMk+F,GAGJ,QAEL14G,KAAKs4G,OACLt4G,KAAKiR,UAAUk+B,QAAQnvC,KAAKy4G,mBAGvB,YAAYx9F,EAAO,IACxB3N,WAAW,IAAMtN,KAAKs4G,OAAQr9F,GAGzB,OACLjb,KAAKiR,UAAUzF,KAAK,kCAAkCinB,UAKnD,MAAMkmF,EAGX,YACE,OAAO34G,KAAKiR,UAAU,SAGxB,gBACE,OAAOjR,KAAKiR,UAAU,aAGxB,YACE,OAAOjR,KAAKiR,UAAU,SAKjB,OAAOxK,GACZ,OAAOzG,KAAKiR,UAAUnE,KAAK9M,KAAMyG,GAI5B,UAAUwK,GAKf,MAJyB,iBAAdA,IACTA,EAAYjR,KAAK44G,eAAe3nG,IAG3B,IAAIunG,EAAiBvnG,GAGtB,eAAexK,GACrB,OAAOI,OA3G8B,gCA2GI0E,OAAO,yBAAyB9E,Q,sCA/BhEkyG,I,yBAAAA,EAAuB,QAAvBA,EAAuB,qBADV,U,kCC3G1B,sFAIO,MAAME,EAKX,YAAYC,EAAgC/wG,EAA0B,KAH9D,KAAAgxG,QAAU,IAAI,IAIpB/4G,KAAKg5G,UAAY,IAAI,IACrBh5G,KAAKg5G,UACF74G,KACC,YAAa4H,GACb,YAAU+wG,IAEXz4G,UAAWuB,GAAQ5B,KAAK+4G,QAAQvwG,KAAK5G,IAGnC,KAAKuE,GACVnG,KAAKg5G,UAAU5wG,KAAKjC,GAGf,UAAU8yG,EAAsBj6F,EAAYpF,GACjD,OAAO5Z,KAAK+4G,QAAQ14G,UAAU44G,EAAiBj6F,EAAOpF,M,kCCxB1D,8G,wBCiDgB,oB,8BACQ,kCAAgC,wB,wBAmBxC,oB,yBACQ,2BAA2B,iB,uCAQvC,kBACE,mBACO,iFADP,OAKA,QACF,O,6DAFS,qEAHA,4BAA4B,gBAA5B,CAA4B,sBAInC,8B,uCAlDR,cAEE,gBACE,mBAKA,gBACE,iBACE,oBAGE,2GAEA,0BAgBA,oBAIA,0BAGF,OACF,OACF,OACF,OACA,gBACE,iBACE,0BAQF,OACF,OACF,O,gDAtDK,0CAIC,oDACA,+CAMI,mDACA,6CAGQ,qCAgBA,+CAAgC,2BAAhC,CAAgC,2BAIhC,2CASgB,+C,yBA7CpC,QACE,yBAuDF,Q,oBAtDO,4CDzBJ,MAAMs/F,EACX,YAAmB9oG,EACAmiC,GADA,KAAAniC,SACA,KAAAmiC,aAcd,MAAM4mE,EA6BX,YAAqBpwG,EACArI,EACAsC,GAFA,KAAA+F,WACA,KAAArI,OACA,KAAAsC,gBA7Bd,KAAA4U,KAAO,CACZ0K,MAAOtiB,KAAKU,KAAKU,EAAE,oBACnBouB,YAAaxvB,KAAKU,KAAKU,EAAE,2BACzBg4G,gBAAiBp5G,KAAKU,KAAKU,EAAE,kCAC7Bi4G,gBAAiBr5G,KAAKU,KAAKU,EAAE,kCAC7Bk4G,gBAAiBt5G,KAAKU,KAAKU,EAAE,oCAC7Bm4G,aAAc,CACZv3G,YAAahC,KAAKU,KAAKU,EAAE,iEACzBo4G,UAAWx5G,KAAKU,KAAKU,EAAE,+DACvBq4G,SAAUz5G,KAAKU,KAAKU,EAAE,8DACtB6wF,QAASjyF,KAAKU,KAAKU,EAAE,+DAIhB,KAAAs4G,oBAAsB,CAC7B,CAAC/0G,MAAO,IAAmB8B,KAAMzG,KAAKU,KAAKU,EAAE,uBAC7C,CAACuD,MAAO,IAAoB8B,KAAMzG,KAAKU,KAAKU,EAAE,yBAGzC,KAAAu4G,iBAAgC,GAChC,KAAAC,WAA0B,GAC1B,KAAAC,iBAAqC,GACrC,KAAAC,YAAyB,CAACrzG,KAAMzG,KAAK4X,KAAK4X,YAAajqB,KAAM,MAE7D,KAAAw0G,YAA0B,YAS1B,SACL,IAAIC,EAEFA,EADuB,cAArBh6G,KAAK+5G,YACQ/5G,KAAK65G,iBAAiBtuG,OAAO+iB,GAA4B,OAAlBA,EAAOle,QAE9C,CAAE,IAAI8oG,EAAgBl5G,KAAKi6G,iBAAkB,MAG9DD,EAAeA,EAAa9qG,IAAIof,GAAUtuB,KAAKk6G,gBAAgB5rF,EAAOle,OAAO7K,KAAO+oB,EAAOikB,YAC3FvyC,KAAKgD,cAAcwR,OAAOnQ,EAAEwmE,QAAQmvC,IAGtC,WACEh6G,KAAKgD,cACF0yG,uBACAr1G,UAAU,KACT,IAAIu5G,EAA0B55G,KAAKgD,cAAcsS,UAAU/J,OACxD4uB,IACSA,EAAK/pB,OAAOzL,MAAOiuC,SAAS,YAEtC1jC,IACCirB,IACQ,CAAC1zB,KAAM0zB,EAAK/pB,OAAO3J,KAAMlB,KAAM40B,EAAK/pB,OAAOzL,SAMtD3E,KAAK45G,WAAav1G,EAAEw3B,OAAO+9E,EAAY,QAEvC55G,KAAKm6G,yBAEL91G,EAAEC,KAAKtE,KAAKgD,cAAc/C,QAASk6B,IAC5BA,EAAK/pB,OAAOzL,MAAOiuC,SAAS,aAC/B5yC,KAAK65G,iBAAiB34G,KACpB,IAAIg4G,EAAgB,CAACzyG,KAAM0zB,EAAK/pB,OAAO3J,KAAMlB,KAAM40B,EAAK/pB,OAAOzL,OAC7Dw1B,EAAKoY,UAAU5tC,QAEfw1B,EAAK/pB,OAAO7K,OAASvF,KAAKi6G,iBAAiB10G,MAC7CvF,KAAKo6G,kBAAkB,aAK7Bp6G,KAAKq6G,oBACLr6G,KAAKs6G,uBAIJ,gBAAgBngF,EAAsBoL,GAC3CpL,EAAK/pB,OAAS/L,EAAEmH,KAAKxL,KAAK45G,WAAaxpG,GAAWA,EAAO7K,OAASggC,IAAavlC,KAAK85G,YACpF95G,KAAKq6G,oBAGA,oBACL,IAAIE,EAAcv6G,KAAK65G,iBACpBtuG,OAAO+D,GAAkB,OAAbA,EAAEc,QACdlB,IAAKof,GAA2BA,EAAOle,QAE1CpQ,KAAK25G,iBAAmBt1G,EAAEY,OAAOZ,EAAEw7D,aAAa7/D,KAAK45G,WAAYW,EAAa,QAAS,QAGlF,kBAAkBvjG,GACvBhX,KAAK+5G,YAAc/iG,EAGb,gBAAgB5G,EAAemiC,GACrC,OAAOluC,EAAEmH,KAAKxL,KAAKgD,cAAcsS,UAAW6kB,GACnCA,EAAK/pB,OAAOzL,QAAUyL,GAAU+pB,EAAKoY,UAAU5tC,QAAU4tC,GAI5D,qBACN,KAAOvyC,KAAK65G,iBAAiB5yG,OAAS,GACpCjH,KAAK65G,iBAAiB34G,KAAK,IAAIg4G,EAAgBl5G,KAAK85G,YAAa,MAI7D,yBACN95G,KAAKi6G,iBAAmBj6G,KAAK45G,WAAWpuG,KAAMc,GAAMA,EAAE/G,KAAMqtC,SAAS,mBACrE5yC,KAAK45G,WAAW3wF,OAAOjpB,KAAK45G,WAAWx8F,QAAQpd,KAAKi6G,kBAAmB,I,sCAnH9Dd,GAA6B,gC,uBAA7BA,EAA6B,6hCC1B1C,iBACE,gBAIE,cACA,gBACE,gBACE,kBACE,kBACO,4DAAyB,6BACf,EAAAiB,kBAAA,mBAFjB,OAKA,QACF,OACF,OACF,OAAM,gBACJ,gBACE,mBACE,mBACO,4DAAyB,6BACf,EAAAA,kBAAA,mBAFjB,OAKA,SACF,OACF,OACA,iBACE,SACF,OACF,OAEA,gCAyDF,OACF,Q,MAtFO,4DAKU,sCAIP,mDAOO,sCAIP,oDAIF,kDAIU,mD,4NCIX,MAAMI,UAAsC,IAGjD,YAAmBzxG,GACjBjJ,MAAMiJ,GADW,KAAAA,WAOH,KAAAmoC,wBAA0B,IAKnC,KAAA9a,aAAe,GA0Bf,KAAAmqC,gBAA2C,KAclC,KAAAtwB,YAAc,CAC5BuwB,UAAWxgE,KAAKU,KAAKU,EAAE,oCACvBmB,OAAQvC,KAAKU,KAAKU,EAAE,mCArCf,IAAIma,EAA0Bq1F,GACnC,OAAO5wG,KAAK6Q,YAAY08B,kBAAkBqjE,EAAM5wG,KAAKo2B,aAAc7a,EAAKrT,IAMnE,OAAOqT,EAA0B6X,GAEtC,MAAMkB,EAAWt0B,KAAK6Q,YAAYrF,KAAK4nB,EAAI7X,EAAMvb,KAAKo2B,cAEtD,YAAiB1qB,IAAb4oB,EACKt0B,KAAK6Q,YAAY4pG,eAAenmF,GAEhC/kB,QAAQsuB,SAUnB,aACE,SAAU79B,KAAKugE,iBAAmBvgE,KAAK0gE,uBAAyB1gE,KAAKugE,gBAAgBh7C,aAGvF,mBACE,QAASvlB,KAAK+vC,Q,sCAjDLyqE,GAA6B,Y,yBAA7BA,EAA6B,QAA7BA,EAA6B,YACzB,aAAd,c,0BAA0B,M,mICLtB,MAAM,UAA0C,IAO9C,kBAAkB7iG,GACvB,MAAM+iG,EAAU/iG,EAAWyb,KACrBunF,EAAYhjG,EAAW4D,OACvBq/F,EAAajjG,EAAWuG,OAAO,QAC/B4yC,EAAWn5C,EAAWuG,OAAO,MAGnC,OAAIy8F,EAAUl0G,MAAQk0G,EAAUl0G,KAAKkyD,MAAM,mBAChC+hD,EAAQvsG,MAAQusG,EAAQvsG,KAAKQ,4BAINjD,IAA3BolD,EAAS5sC,eAA+B4sC,EAAS5sC,gBAAkB02F,EAAW12F,e,oCAnB5E,I,yBAAA,EAAiC,QAAjC,EAAiC,Y,aAAjC,G,4BCYN,MAAM22F,G,sCAAAA,I,uBAAAA,EAAyB,kDAJzB,CACT,CAAEl1D,QAAS,IAAwBC,SAAU,MAC9C,oHANC,gBACE,kBACF,S,iFCvCJ,oFAQO,SAASk1D,EAAej6G,EAA2BkM,GACxD,MAAiB,UAAblM,EAAIiS,OAAkC,YAAbjS,EAAIiS,MAAsBjS,EAAIkqB,QAAU,IAASqd,SAC5Er7B,KACO,GAOJ,MAAeguG,EACb,YAAYh6E,EAA0BlgC,GAC3Ci6G,EAAej6G,EAAK,IAAMb,KAAKg7G,aAAaj6E,EAAKzN,iBAAkBzyB,O,kCCSvE,sI,yBC7BA,gBAIE,gBACE,qCAIF,OACA,gBACE,qCAIF,OACF,Q,oBAdK,2DACA,gFAEyB,uCAAwB,yFAAxB,CAAwB,oBAMxB,uCAAwB,4FAAxB,CAAwB,wBD4B/C,MAAMo6G,UAAoC,IAK/C,YAAsBC,EACAz3G,GACpB3D,QAFoB,KAAAo7G,kBACA,KAAAz3G,eAHN,KAAA03G,wBAA0B,mCAAmC,YAAa,IAO1F,WACOn7G,KAAKgJ,aACRhJ,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKk7G,gBAAgBh9F,OAAsB,eAC9C4H,mBACA3lB,KACCH,KAAKI,kBAENC,UAAWsF,IACV3F,KAAKgJ,YAAcrD,K,sCArBhBs1G,GAA2B,oC,uBAA3BA,EAA2B,8eCvCxC,sB,KAAK,4B,8EC4BL,sI,mF/Y5BA,gBAIE,sBAGW,gEACX,gBACI,gBACE,2BACA,gBACE,cAAG,uEAED,iBACF,OACF,OACF,OACA,2BAGF,OAEA,iBACE,kCACE,2EACF,OACF,OAEA,kBACE,yBAEF,OACF,OACF,O,uBA9Ba,0CAA2B,0BAA3B,CAA2B,iBAMhB,6CAQF,6CAA8B,yBAYlC,6EAAgE,qD+YM3E,MAAMG,UAAyC,K,oCAAzCA,I,uBAAAA,EAAgC,+uB/YpC7C,uB,KAEE,+B,sF+YkCWA,I,gbC9BN,MAAM,UAAgC,IAD7C,c,oBAEE,KAAAC,UAAY,e,oCADD,I,yBAAA,EAAuB,QAAvB,EAAuB,Y,aAAvB,G,4BCwDN,MAAMC,EAAqC,CAEhD,CAAE31D,QAAS,IAAoBC,SAAU,GACzC,IAGA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IAIA,IACA,IACA,IAEA,IACA,IAEA,IAGA,KAeK,MAAM,UAAoD,K,oCAApD,I,uBAAA,EAA2C,mEAF3C01D,GAAkC,Q,aAElC,I,kCCpHb,kM,kDCiBQ,iBACE,kBACF,Q,oBADQ,sC,yBAgBN,aACE,eACF,Q,yBADM,+B,yBAGN,YACE,iBACA,cAGF,Q,qBAJQ,mDACH,iDACA,sC,yBATP,QACE,gBACA,sBAIA,qBAMF,Q,oBAXkD,0CAC5C,yCAID,8DDhBN,MAAMC,UAAuB,IA6ClC,YAA+CzpG,EAC1BjS,EACAa,EACAF,EACAqO,EACApL,EACAs+B,EACAi8B,EACAD,GACnBj+D,MAAMgS,EAAQjS,EAAOW,GATwB,KAAAsR,SAC1B,KAAAjS,QACA,KAAAa,OACA,KAAAF,aACA,KAAAqO,aACA,KAAApL,eACA,KAAAs+B,mBACA,KAAAi8B,gBACA,KAAAD,aAlDd,KAAA9W,eAAgB,EAGhB,KAAAE,qBAAsB,EAEtB,KAAAvvC,KAAO,CACZ0K,MAAOtiB,KAAKU,KAAKU,EAAE,uBACnB68D,WAAYj+D,KAAKU,KAAKU,EAAE,wBACxBo6G,SAAUx7G,KAAKU,KAAKU,EAAE,0BACtBq6G,gBAAiBz7G,KAAKU,KAAKU,EAAE,iCAAmC,IAChEs6G,cAAe17G,KAAKU,KAAKU,EAAE,+BAC3B67B,OAAQj9B,KAAKU,KAAKU,EAAE,wBACpBu6G,gBAAiB37G,KAAKU,KAAKU,EAAE,iCAC7Bw6G,kBAAmB57G,KAAKU,KAAKU,EAAE,oCAO1B,KAAAmwE,WAAY,EAeZ,KAAAjvD,MAAetiB,KAAK4X,KAAK0K,MAGzB,KAAAu5F,aAA2B,KAehC77G,KAAK2+D,MAAQ7sD,EAAO6sD,MAGtB,WACE7+D,MAAMqkB,WACNnkB,KAAK87G,oBAGC,oBACN,YAAM,EAAG,KACN37G,KACC,YAAU,IAAMH,KAAK+7G,kBACrB,YAAUl9F,KAAcA,EAASH,MAAQ1e,KAAKg8G,gBAAgBn9F,EAASH,OAAO,GAC9E1e,KAAKI,iBACL,YAA4BJ,KAAK+hC,iBAAiBq7C,OAAO,WACzD/8E,UACFwe,GAAY7e,KAAKi8G,WAAWp9F,GAC5BG,GAAShf,KAAKylD,YAAYzmC,GAC1B,IAAMhf,KAAKuxE,WAAY,GAInB,gBACN,OAAQvxE,KAAK27C,QACX,IAAK,YACL,IAAK,UACL,IAAK,QACH,MAAO,aAET,IAAK,UACH,MAAO,iBAET,QACE,OAAO,MAQL,gBAAgB98B,GACtB,MAAO,CAAC,WAAY,cAAcjG,SAASiG,EAAS88B,QAG9C,WAAW98B,G,MACjB,IAAIH,EAAOG,EAASH,KAEpB,IAAKA,EACH,MAAM,IAAIhP,MAAMmP,GAGlB,IAAI88B,EAAS37C,KAAK27C,OAASj9B,EAAKi9B,OAEhC37C,KAAKw6C,QAAU97B,EAAK87B,SAClBx6C,KAAKU,KAAKU,EAAE,kCAAkCu6C,EAAU,CAAEsc,aAActc,IAE1E37C,KAAK+B,QAAU2c,EAAK3c,QAChB2c,EAAK3c,UACP/B,KAAKsiB,MAAQ5D,EAAK3c,QAAQugB,OAAStiB,KAAK4X,KAAK0K,MAC7CtiB,KAAKk8G,eAAex9F,EAAK3c,SACzB/B,KAAKm8G,eAA2B,QAAb,EAACz9F,EAAK3c,eAAO,eAAEq6G,WAGpCp8G,KAAKq8G,WAAar8G,KAAKs8G,gBACvBt8G,KAAKH,MAAMS,gBAGL,eAAeyB,IACjBA,aAAO,EAAPA,EAASy5G,aAAaz5G,aAAO,EAAPA,EAASk7B,UACjC3vB,WAAW,IAAMkT,OAAOgoB,SAASjjC,KAAOxD,EAAQy5G,SAAU,KAC1Dx7G,KAAKw6C,SAAW,KAAKx6C,KAAK4X,KAAK4jG,UAI3B,eAAee,QACD7wG,IAAhB6wG,IACFv8G,KAAK67G,aAAeU,EAEpBjvG,WAAW,IAAMtN,KAAKw8G,aAAa11G,cAAcsF,QAAS,KAItD,iBACN,OAAOpM,KACJ+9D,WACAr5D,IACC1E,KAAKy8G,OACL,CAAElrD,QAAS,WAAYhzC,aAAc,SAInC,YAAYS,GAClB,GAAsB,OAAlBA,aAAK,EAALA,EAAO28B,QAGT,OAFA37C,KAAKq8G,WAAa,iBAClBr8G,KAAKw6C,QAAUx6C,KAAKU,KAAKU,EAAE,6CAK7BpB,KAAKq8G,WAAa,aAClBr8G,KAAKw6C,SAAUx7B,aAAK,EAALA,EAAOw7B,UAAWx6C,KAAKU,KAAKU,EAAE,qBAC7CpB,KAAKg+D,cAAcjE,SAAS/5D,KAAKw6C,SAGnC,aACE,OAAOx6C,KAAKyD,aAAaqyD,aAAa5tD,GAAGlI,KAAK2+D,OAAOt8C,Y,sCAlK5Ck5F,GAAc,KA6CL,KAAkB,kF,uBA7C3BA,EAAc,qD,OAAA,K,ytBCtB3B,gBACE,gBAEE,gBACE,eACA,cACE,cAEE,iCAAS,EAAAj0D,QAAA,MAEX,OACF,OACF,OAEA,cACE,gBAEE,sBAGF,OACA,cACE,kBACA,kBACE,SACA,mBAMF,OACA,iCAaF,OACF,OACF,OACF,Q,MA5CU,oCAKA,wCAQ+B,gDAKY,sCACvC,uCACJ,6CAIG,qDACA,iCAGS,6D,qlBChCtB,sI,kFC6BI,gB,oBAEK,sDAAoD,8C,yBAGzD,gBAEE,sCAGF,Q,oBAH4B,iCAAkB,4B,wBAU5C,sC,oBAC0B,yBAAkB,yB,wBAG5C,e,oBACG,uC,yBAcL,QACE,gBAIA,gBACE,sCAGF,OACF,Q,kCARO,sDAA6C,uBAItB,iCAAkB,oBD7C7C,MAAMo1D,UAA+B,IAsB1C,YAAqB9mG,EACA/V,EACAg4D,GACnB/3D,QAHmB,KAAA8V,aACA,KAAA/V,QACA,KAAAg4D,OAtBZ,KAAA8kD,sBAA+B,EAE9B,KAAAC,cAAgB,IAAI,IAI9B,KAAAhlG,KAAO,CACLqwC,WAAY,CACVo/B,QAASrnF,KAAK63D,KAAKz2D,EAAE,yBACrB8xB,MAAOlzB,KAAK63D,KAAKz2D,EAAE,uBACnB4vB,SAAUhxB,KAAK63D,KAAKz2D,EAAE,0BACtB4H,YAAahJ,KAAK63D,KAAKz2D,EAAE,8BACzBy7G,QAAS78G,KAAK63D,KAAKz2D,EAAE,2BAEvB07G,WAAY98G,KAAK63D,KAAKz2D,EAAE,wCAGnB,KAAA27G,qBAA8B,EAC9B,KAAAvmG,aAA8C,GAQrD,WACExW,KAAK4V,WACF4pC,sBAAsBx/C,KAAK0sB,UAAUjqB,mBACrCvC,UACAC,KACCH,KAAKI,kBAENC,UAAUqsB,IACLA,GAAaA,EAAU1jB,cACzBhJ,KAAK+8G,qBAAsB,EAC3B/8G,KAAKH,MAAMs8F,kBAIjBn8F,KAAKg9G,kBACLh9G,KAAKH,MAAMS,gBAGb,YACE,OAAON,KAAK0sB,UAAUjqB,kBAGjB,oBAAoB8oC,GACzBvrC,KAAK48G,cAAcp0G,KAAK+iC,GAGnB,OACL,OAAOvrC,KAAKga,SAASO,SAGvB,iBAGE,OAAO,EAGF,WAAWrT,GAGhB,MAAc,gBAAVA,GAGKlH,KAAKwC,OAAOi5C,WAAWv0C,GAAOqS,SAIjC,kBACNzJ,OAAOmtG,QAAQj9G,KAAKwC,QAAQkD,QAAQ,EAAE/D,EAAKu7G,MACrCv7G,EAAIg3D,MAAM,mBACZ34D,KAAKwW,aAAatV,KAAK,CAAES,IAAKA,EAAK2gC,MAAO46E,EAAUz2G,SAK1D,aACE,OAAOzG,KAAK0sB,UAAUlqB,Q,sCAnFbk6G,GAAsB,gC,uBAAtBA,EAAsB,gD,OAAA,K,0qBC1BnC,wBAIE,mCAAW,EAAAS,oBAAA,MACX,gBAEE,gBAIA,gBACE,qCAIF,OAEA,gBAIA,gBACE,qCAIF,OAEA,sBAKA,uBAOA,iBAIA,iBACE,4CAIA,qBAGF,OAEA,iBAIA,iBACE,uCAGF,OAEA,iCAWF,OACF,Q,MA3EE,yBAAkB,2BAML,2DAAgD,yCAI/B,iCAAkB,yBAAlB,CAAkB,uBAOzC,yDAA8C,uCAIvB,iCAAkB,yBAAlB,CAAkB,qBAMzC,4CAKA,4CAQA,4DAAiD,0CAI1B,2CAIvB,4CAMA,2DAAgD,yCAIzB,iCAAkB,uBAKhC,yC,kLClCX,MAAM,EAGX,YAAYr5G,GACV9D,KAAKC,QAAU,IAAI,IAAmB6D,EAAQ40C,OAAQ50C,EAAQm2C,MAAOn2C,EAAQy2C,UAG/E,WACE,OAAOv6C,KAAKC,QAAQq5C,KAGtB,SAAgB13C,GACd5B,KAAKC,QAAQq5C,KAAO13C,EAGtB,cACE,OAAO5B,KAAKC,QAAQs5C,QAGtB,YAAmB33C,GACjB5B,KAAKC,QAAQs5C,QAAU33C,EAGzB,YACE,OAAO5B,KAAKC,QAAQg6C,MAGtB,UAAiBr4C,GACf5B,KAAKC,QAAQg6C,MAAQr4C,G,4BCflB,MAAM,UAAyC,IACpD,YAAmBgB,EACSw6G,GAC1Bt9G,MAAM8C,GADoB,KAAAw6G,oBAI5B,uBACE,OAAIp9G,KAAKC,QACA,CACLs6C,SAAUv6C,KAAKC,QAAQs5C,QACvBb,OAAQ14C,KAAKC,QAAQq5C,MAGhB,CACLiB,SAAUv6C,KAAKo9G,kBAAkBC,iBAAiB,IAClD3kE,OAAQ,GAMP,eAAe70C,EAAqBC,GACzC,OAAO,IAAI,EAA0BA,GAGhC,iBAAiBwqB,GACtB,IAAIsxD,EAAe5/E,KAAKC,QAEpBquB,EAAOgrB,OACTsmC,EAAatmC,KAAOhrB,EAAOgrB,MAEzBhrB,EAAOirB,UACTqmC,EAAarmC,QAAUjrB,EAAOirB,SAE5BjrB,EAAO2rB,QACT2lC,EAAa3lC,MAAQ3rB,EAAO2rB,OAG9Bj6C,KAAKwT,aAAaxP,SAAS47E,GAGtB,kBAAkB97E,GACvB,IAAI0Q,EAAS,CACX8kC,KAAMx1C,EAAQ40C,OACda,QAASz1C,EAAQy2C,SACjBN,MAAOn2C,EAAQm2C,MACfhmB,MAAOnwB,EAAQmwB,OAGjBj0B,KAAKs9G,iBAAiB9oG,GAGxB,cACE,OAAOxU,KAAK+W,iBAAiB5Q,O,sCArDpB,GAAgC,sB,yBAAhC,EAAgC,QAAhC,EAAgC,a,oCCf7C,8GAgCO,MAAMo3G,EACX,YAAsB5+F,EACAs9D,GADA,KAAAt9D,OACA,KAAAs9D,cAWf,qBAAqBjuE,EAAY8O,EAAoB2B,EAAgB,QAC1E,MAAM,QAAE2xD,EAAO,SAAEC,GAAarwE,KAAKw9G,OAAOxvG,EAAK8O,GAM/C,MAAO,CAAEszD,QAASA,EAASC,SALZA,EACZ5gE,KAAM6vB,GAAyBA,EAAOpwB,IAAK+C,IACjC,CAAE4M,SAAU5M,EAAIwrG,UAAWxrG,EAAGyrG,uBAAuBn4G,UAU7D,OAAOyI,EAAY8O,EAAoB2B,EAAgB,QAC5D3B,EAAQzY,EAAEkH,OAAOuR,EAAQY,GAAkC,cAAdA,EAAK5K,MAClD,MAAMs9D,EAA6B/rE,EAAE6K,IAAI4N,EAAQY,GAAoB1d,KAAK29G,aAAa3vG,EAAK0P,EAAMe,IAGlG,MAAO,CAAC2xD,UAASC,SADArwE,KAAK49G,aAAaxtC,IAU9B,aAAapiE,EAAY0P,EAA4Be,EAAgB,OAAQF,EAA6B,QAC/G,MAAMs/F,EAAW,IAAIC,SACfC,EAAW,CACf/7G,YAAa0b,EAAK1b,YAClBipC,SAAUvtB,EAAK4tB,YAAc5tB,EAAKjX,MAIpCo3G,EAAS1oF,OACP,WACA1P,KAAKC,UAAUq4F,IAIjBF,EAAS1oF,OAAO,OAAQzX,EAAMqgG,EAAS9yE,UAqBvC,MAAO,CAACvtB,EAnBW1d,KAChB2e,KACAC,QACCH,EACAzQ,EACA,CACE0Q,KAAMm/F,EAENtsD,QAAS,SACTjzC,iBAAiB,EACjBC,aAAcA,EAEdy/F,gBAAgB,IAGnB79G,KACC,gBAWE,aAAaiwE,GACnB,MAAM6tC,EAAW7tC,EAAQlhE,IAAI,EAAE7K,EAAG+sD,KACzBA,EACJjxD,KACC,YAAQU,GAAQA,EAAIiS,OAAS,IAAcorG,UAC3C,YAAKr9G,GAAkCb,KAAKi8E,YAAY5D,kBAAkBx3E,EAAI6d,QAE/EmO,aAGL,OAAOtd,QAAQu0B,IAAIm6E,I,sCA9FVV,GAA4B,sB,yBAA5BA,EAA4B,QAA5BA,EAA4B,a,gSCzDnC,yB,oBAEa,+C,yBAeT,gBAGE,yBAKF,Q,wCANI,mCACW,gDAA4C,4BAA5C,CAA4C,gCAA5C,CAA4C,gC,yBAJ7D,QACE,sBASF,Q,yBARM,wC,yBALR,gBAGE,gCAWF,Q,oBAXgB,mDC8Cf,MAAMY,UAA2C,IAXxD,c,oBAgBE,KAAAvmG,KAA+B,CAC7B,mBAAsB5X,KAAKU,KAAKU,EAAE,0CAClC,wBAA2BpB,KAAKU,KAAKU,EAAE,iDAqBzC,KAAAg9G,aAAc,EAGd,KAAAC,wBAA6D,GAG7D,KAAAC,eAAwB,EAGxB,KAAAC,iBAAsC,SAMtC,KAAAC,0BAAuD,CACrD/vG,UAAW,KAGb,WACE3O,MAAMqkB,WAENnkB,KAAKy+G,wBAA0Bz+G,KAAKyX,OAAOyG,OAAO2lB,YAClD7jC,KAAK0+G,aAAa1+G,KAAKyX,OAAOxX,SAC9BD,KAAK2+G,6BAA+B3+G,KAAKyqB,aAAahS,UAAU,GAAKd,IACnE,MAAMuG,EAASvG,EAAWuG,OAAO,MAC3Bw8F,EAAU/iG,EAAWyb,KAC3BpzB,KAAKy+G,wBAA0BvgG,EAAO2lB,YACtC7jC,KAAK0+G,aAAahE,GAClB16G,KAAKH,MAAMS,kBAIb,MAAMs+G,GAAe5+G,KAAK4C,WAAWqD,YAAY3D,WACjDtC,KAAKw9B,QAAQohF,EAAaA,GAG1B5+G,KAAK6+G,iCAGL7+G,KAAK8+G,mBACFziD,SACAl8D,KACCH,KAAKI,kBACLC,UAAU,KAEZL,KAAK65D,kBAAenuD,EACpB1L,KAAKw9B,SAAQ,GAAM,KAIrBx9B,KAAK++G,wBAA0B/+G,KAAKyqB,aAAahS,UAAU,GAAI,KAC7DzY,KAAKg/G,YAAYh/G,KAAK4C,WAAWiB,MAAMsC,SAGzCnG,KAAK4C,WAAWiB,MAAM3D,UAAUC,KAC9BH,KAAKI,kBACLC,UAAWwD,IACX7D,KAAKi/G,eAAep7G,KAUd,aAAaiN,GACrB9Q,KAAKu+G,iBAAoBztG,EAAM3C,MAAQ2C,EAAM3C,KAAKI,UAAauC,EAAM3C,KAAKI,UAAY,SAG9E,iCACRvO,KACG4C,WACAqD,YACA/F,UACAC,KAAK,YAAK,IACVE,UAAU,KACTL,KAAKo+G,aAAc,EACnBp+G,KAAKH,MAAMS,kBAIP,eAAeuD,GAEvB7D,KAAKg/G,YAAYn7G,GACjB7D,KAAK65D,aAAeh2D,EAEpB7D,KAAKH,MAAMS,gBAGb,cACER,MAAM4Y,cACN1Y,KAAK++G,0BACL/+G,KAAK2+G,+BACL3+G,KAAK8+G,mBAAmBI,4BAGnB,uBAAuBt9G,GACxB5B,KAAK65D,cAAgB75D,KAAK65D,aAAannB,UACzC1yC,KAAKm/G,gBAAgBv9G,GAErB5B,KAAK24C,cACFp2C,OAAOvC,KAAK65D,aAAej4D,GAC3B6N,KAAK,IAAMzP,KAAKo/G,iBAAkB,GAClC5kG,MAAM,IAAMxa,KAAKo/G,iBAAkB,GAI1C,gBAAgBx9G,GACd5B,KAAKo/G,iBAAkB,EACvBp/G,KAAK65D,aAAcpzD,KAAO7E,EAC1B5B,KAAK24C,cAAcv+B,KAAKpa,KAAK65D,cAC1BpqD,KAAK,IAAMzP,KAAKo/G,iBAAkB,GAClC5kG,MAAM,IAAMxa,KAAKo/G,iBAAkB,GAGxC,YAAYv7G,GAGLA,IAKDA,EAAM6uC,UACR1yC,KAAKi3D,cAAgBpzD,EAAM4C,KAE3BzG,KAAKi3D,cAAgBj3D,KAAKgiC,gBAAgBq9E,cAAcx7G,GAG1D7D,KAAKs/G,oBAAsBt/G,KAAK2D,qBAAqB2U,IAAI,QAAS,qBAG9DtY,KAAKu/G,yBACPv/G,KAAK+zE,aAAaC,aAAah0E,KAAKi3D,gBAIxC,QAAQuoD,GAAkB,EAAOjnE,GAAoB,GACnD,IAAItT,EACAphC,EAAQ7D,KAAK65D,aAEjB,GAAIthB,IAAc10C,EAChBohC,EAAUjlC,KAAKy/G,oBACV,CACL,IAAIjnE,EAAax4C,KAAK24C,cAAc+mE,oBACpCz6E,EAAUjlC,KAAK24C,cACZC,sBAAsB/0C,EAAO20C,EAAYx4C,KAAK8O,mBAC9C+d,YAGL,OAAI2yF,EACKx/G,KAAK+hC,iBAAmBkD,EAAQx1B,KAAM0pC,IAC3Cn5C,KAAKk4C,uBAAuBlyC,WAAWmzC,EAAaA,EAAYr1C,SACzD9D,KAAK2/G,0BAIT16E,EAAQx1B,KAAM0pC,IACnBn5C,KAAKk4C,uBAAuBlyC,WAAWmzC,EAAaA,EAAYr1C,WAI1D,gBACR,OAAI9D,KAAK65D,aACA75D,KAAK24C,cAAcihB,YAAY55D,KAAK65D,aAAc75D,KAAK8O,mBAAmB+d,YAE1E7sB,KAAK24C,cAAcinE,2BAA2B5/G,KAAK8O,mBAIpD,wBACR,OAAOS,QAAQC,UAGjB,qBAA+By1B,GAC7BjlC,KAAK84C,wBAAwBvlB,MAAM0R,QAAUA,EAGrC,wBACR,OAAO,G,oCAlNEk5E,I,uBAAAA,EAAkC,4DANlC,CAET,CAAEx4D,QAAS,IAAgCC,SAAU,KACrD,MACD,2hCDhEH,gBAEE,gBACE,gBACE,8BAKA,mCAGwB,kCAAU,EAAAi6D,uBAAA,KAAV,CAAyC,mCACxB,EAAAV,gBAAgB,OAEzD,OAEA,qBAeF,OACF,OAEA,gBACE,wBAKF,OAEA,gBAEE,gBAMA,kBAEF,OACF,Q,MArDM,mCAGa,0CAKW,sCAAuB,6BAAvB,CAAuB,4CAAvB,CAAuB,kCAS3C,mCAkBO,0EAA2D,sDAA3D,CAA2D,wDAA3D,CAA2D,mC,g3FC+B3D,aAAd,c,0BAAmB,M,2BACL,aAAd,c,0BAA2B,M,mCACb,aAAd,c,0BAAiC,M,sDAHvBhB,I,kCCpCb,gJAYO,MAAM2B,UAAoC,IAK/C,YAAqBp/G,EACA2U,GACnBvV,QAFmB,KAAAY,OACA,KAAA2U,cALL,KAAA04B,aAAsB,EAErB,KAAAC,cAAgB,IAAI,IAAmD,YAAmBhuC,OAO3G,YACE,OAAOq9B,SAASr9B,KAAKuL,OAAOqa,OAAO,IAGrC,UAAiBhkB,GAEb5B,KAAKuL,OAAOqa,OADO,iBAAV,EACY,CAAChkB,EAAIygB,YAEL,GAGvBriB,KAAKguC,cAAcxlC,KAAKxI,KAAKuL,QAG/B,WACE,OAASvL,KAAKwC,OAAO+I,OAAOvG,cAAwC,GAAGkD,IACrE,IAAK,YACL,IAAK,UACL,IAAK,YACL,IAAK,YACH,OAAOlI,KAAKU,KAAKU,EAAE,uCACrB,QACE,MAAO,IAIb,aACE,OAAOpB,KAAKqV,YAAY/B,GAAGtT,KAAKuL,S,sCArCvBu0G,GAA2B,sB,uBAA3BA,EAA2B,gZC1CxC,gBACE,kBAAO,sDAAP,OAQA,kBAIF,Q,MAbK,iCAAA53G,GAAA,IAKI,qCAAAA,GAAA,IACA,kCALA,wBAAmB,uBAQnB,6CACA,6B,0FCkBT,kY,yBCzBE,iBAEE,sCAGF,Q,qBAH4B,uCAAwB,6BAAxB,CAAwB,wB,wBAMlD,8B,qBACkB,mC,qBAElB,iC,KAAqB,2BAAsB,gC,yBAI3C,iBAEE,kBAAqC,aACrC,kBAGA,eAAM,eAAM,OACZ,uBACmD,aACnD,kBACA,eAAM,gBAAM,OACZ,2BAAqE,cACtE,Q,qBAVO,sCACA,qDAKK,0CACL,yDAEQ,uD,sBAiBR,kBACqE,YAAC,Q,4EAP5E,iBAGE,iBACE,kCACE,QACA,wBAEF,OACA,iCAEF,OACA,iBACE,sCAEF,OACF,Q,mCAfK,oCAGqB,iCACpB,8BAEM,wDAEa,iCAA6B,gCAIxB,uCAAwB,qB,yBAlB1D,iBAGE,cACE,eACA,wBAiBF,OACF,Q,qBAnB2C,oDAGlC,+CAAoE,+B,yBAkB7E,iBACE,cACE,YACE,kBACA,aACA,eAIF,OACF,OACF,Q,qBARY,oDAIH,oDAFA,yC,oEAQT,QACE,wBAGF,Q,mCAHe,sCAAiC,6C,wFAsB9C,WACE,wBAKF,Q,wCALe,iEAAsD,uD,8EAOrE,QACE,gBACE,gBACE,eAEF,OACF,OAEA,yBAIF,Q,wCARU,mCAIK,iEAAsD,gCAAtD,CAAsD,+C,yBAvBvE,iBAOE,gCAQA,gCAaF,Q,mCA3BK,oCAAiC,iCACjC,+BAAmC,sDAKA,gCAQxB,kC,4EAxGlB,gBAGE,sBAOA,iBACE,oCAGA,uCAIA,wBAcA,+BACF,OAEA,uBAyBA,uBAaA,gCAMA,kBACE,kBACE,uCAKF,OACF,OAEA,wBA6BF,Q,oBApHK,mDAEE,yCAOe,0CAKG,0CAGhB,0CAac,0CAIhB,8DAwB0D,uFAajD,8DAQgB,wCAA2B,yBAA3B,CAA2B,kBAA3B,CAA2B,8BAQpD,wCAAwD,+B,gEA2C3D,wB,oBAAa,0DAAmD,6CDxC7D,MAAM63G,UAAuC,IA2ClD,YAAqBr/G,EACCgX,EACAgD,EACA/X,EACAiT,EACAsG,EACAizD,EACA95D,EACAy0E,EACA/gF,EACAlJ,EACDW,EACA0lD,GACnBpmD,QAbmB,KAAAY,OACC,KAAAgX,iBACA,KAAAgD,aACA,KAAA/X,SACA,KAAAiT,aACA,KAAAsG,qBACA,KAAAizD,sBACA,KAAA95D,cACA,KAAAy0E,OACA,KAAA/gF,WACA,KAAAlJ,QACD,KAAAW,aACA,KAAA0lD,kBAnDL,KAAA85D,aAAsB,EAG/B,KAAAC,cAAkC,GAIlC,KAAAC,sBAAwB,IAAI,IAS5B,KAAAtoG,KAAO,CACZ8zB,YAAa,CACXpJ,MAAOtiC,KAAKU,KAAKU,EAAE,yBAErBsa,QAAS,CACPnC,SAAUvZ,KAAKU,KAAKU,EAAE,uCACtBguB,QAASpvB,KAAKU,KAAKU,EAAE,sBACrB++G,SAAUngH,KAAKU,KAAKU,EAAE,uCAGxB+F,OAAQ,CACNnF,YAAahC,KAAKU,KAAKU,EAAE,4CAE3Bg/G,QAAS,CACPC,UAAWrgH,KAAKU,KAAKU,EAAE,uBACvBk/G,cAAetgH,KAAKU,KAAKU,EAAE,8BAIrB,KAAAm/G,kBAA2B,EAoB9B,WACLvgH,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eAEvC,MAAMqS,EAASnZ,KAAK4V,WAAWE,UAAqD9V,KAAKgJ,aACzFhJ,KAAKkgH,sBAAsB93G,KAAKpI,KAAKwgH,YAAYrnG,EAAO1W,oBACxDzC,KAAKw9B,QAAQrkB,GAIbnZ,KAAKkgH,sBACF//G,KACCH,KAAKI,iBACL,YAA4C,CAAC8iB,EAAGC,IAAM9e,EAAEgT,QAAQ6L,EAAGC,IACnE,YAAI,IAAMnjB,KAAK4V,WAAWE,UAAU9V,KAAKgJ,eAE1C3I,UAAW8Y,GAAgCnZ,KAAKw9B,QAAQrkB,IAI3DnZ,KAAK4V,WACF4pC,sBAAsBx/C,KAAKgJ,aAC3B9I,UACAC,KACCH,KAAKI,kBAENC,UAAUkd,IACTvd,KAAKkgH,sBAAsB93G,KAAKpI,KAAKwgH,YAAYjjG,MAI/C,QAAQpE,GAEd,MAAMhX,EAAQnC,KAAKgJ,YAAY7G,MACzBob,EAAWpE,EAAO1W,kBAEnB8a,EAAS7B,QAGZ1b,KAAKi4C,eAAiB,CACpB1yC,KAAMvF,KAAK0a,WAAW+lG,uBAAuBljG,EAAS7B,QAAQJ,WAAYtb,KAAKgJ,YAAYd,IAC3F0pB,QAASrU,EAAS7B,QAAQnW,OAASvF,KAAK0X,eAAegpG,WAJzD1gH,KAAKi4C,eAAiB,CAAErmB,SAAS,EAAOrsB,KAAM,MAQ5CpD,IAAUnC,KAAK0X,eAAeipG,mBAChC3gH,KAAKi4C,eAAe/wC,MAAQlH,KAAK4gH,UAAUznG,EAAQ,CAAC,aAGtD,MAAM0nG,EAAkB7gH,KAAKwC,OAAO+a,GAAUujG,iBAC9C9gH,KAAKigH,cAAgBjgH,KAAK+gH,qBAAqB5nG,EAAQ0nG,GACvD7gH,KAAKH,MAAMS,gBAON,gBAAgBuU,GAErB,MAAMyC,EAAmC,IAAzBzC,EAAMmsG,QAAQ/5G,OAGxBg6G,EAAajhH,KAAKgJ,YAAY7G,SAAW0S,EAAMhR,MAErD,OAAOyT,GAAW2pG,EASb,YAAY39F,EAAe27E,GAChC,OAAOA,EAAKx4F,KAMP,oCACL,OAAOzG,KAAK8pF,KAAK78D,KAAK,2BAA4BjtB,KAAKgJ,aAGlD,wBAAwB6L,GAG7B,OAAO7U,KAAK8pF,KAAK78D,KAAK,0BAA2BpY,EAAO7U,KAAKgJ,aAAamgB,OAAS,KAG9E,0BAGL,OAAOnpB,KAAK8pF,KAAK78D,KAAK,qCAAsCjtB,KAAKgJ,aAAamgB,OAAS,KAGlF,4BAGL,OAAOnpB,KAAK8pF,KAAK78D,KAAK,uCAAwCjtB,KAAKgJ,aAAamgB,OAAS,KAM3F,cACE,MAAO,IAAInpB,KAAKgJ,YAAYd,GAG9B,yBACE,IAAIA,EAAKlI,KAAKgJ,YAAY0S,QAAQJ,WAE9BI,EAAU,YADI1b,KAAK0a,WAAW3L,YAAY7G,OACJlI,KAAKgJ,YAAY0S,QAAQjV,UACnE,OAAOzG,KAAKU,KAAKU,EAAE,qCAAsC,CAAE8/G,YAAaxlG,IAM1E,4BACE,OAAO1b,KAAKgJ,YAAY7G,QAAUnC,KAAKkmD,gBAAgBkzC,OAGjD,qBAAqBjgF,EAA6B0nG,GACxD,OAAKA,EAIEA,EAAgB3xG,IAAK2F,IAC1B,IAAIssG,EAAUnhH,KAAKohH,qBAAqBvsG,GAExC,MAAoB,kCAAhBA,EAAM1M,MACD,CACL1B,KAAMoO,EAAMpO,KACZyB,GAAIi5G,GAAW,YAAa,IAC5BH,QAAShhH,KAAK4gH,UAAUznG,EAAQtE,EAAMozC,YACtCn1C,KAAM+B,EAAM1M,MACZk5G,UAAU,GAGL,CACL56G,KAAMoO,EAAMpO,KACZyB,GAAIi5G,GAAW,YAAa,IAC5Bt9G,MAAO7D,KAAKkc,mBAAmBsgE,yBAAyB,IAAe3nE,EAAMopE,UAAUp6E,OACvFuyB,aAAcvhB,EAAMuhB,aACpB4qF,QAAS,CAACnsG,EAAMopE,UAAUp6E,OAC1BiP,KAAM+B,EAAM1M,MACZk5G,UAAU,KAtBP,GAgCH,UAAUloG,EAA6BmoG,GAC7C,MAAMC,EAAgC,GAuBtC,OArBAD,EAAW57G,QAAS0B,IAClB,GAAkB,SAAdA,EAEF,YADAm6G,EAAYrgH,KAAKlB,KAAKwhH,aAAaroG,IAIrC,IAAKA,EAAO3W,OAAOi5C,WAAWr0C,GAE5B,YADA,YAAS,mCAAoCA,GAI/C,MAAMF,EAAqBlH,KAAKyhH,aAAatoG,EAAQ/R,GACrDm6G,EAAYrgH,KAAK,CACfuF,KAAMW,EACNk7B,MAAOp7B,EAAMo7B,MACbolC,UAAU,EACVg6C,QAASx6G,EAAMwoB,cACfxoB,MAAOA,MAIJq6G,EAQD,aAAapoG,GACnB,IAAImV,EAAa,CACfgU,MAAOtiC,KAAKU,KAAKU,EAAE,oCACnBsmE,UAAU,GAWZ,OARIvuD,EAAO3W,OAAOi5C,WAAW,SAC3BntB,EAAOpnB,MAAQlH,KAAKyhH,aAAatoG,EAAQ,QACzCmV,EAAO7nB,KAAO,SAEd6nB,EAAOpnB,MAAQlH,KAAKyhH,aAAatoG,EAAQ,gBACzCmV,EAAO7nB,KAAO,gBAGT6nB,EAWD,YAAYtlB,GAClB,IAAIxG,EAASxC,KAAKwC,OAAOwG,GAErB24G,EAAyB,KACzBC,EAA0B54G,EAAY0S,SAAW1S,EAAY0S,QAAQnW,KASzE,OANEo8G,EADEn/G,EAAOq/G,WACIr/G,EAAOq/G,WAAWt8G,KAElB/C,EAAO+C,KAIf,CACLpD,MAAO6G,EAAY7G,MACnBK,OAAQm/G,EACRjmG,QAASkmG,GAIL,aAAazoG,EAA6B1S,GAChD,OAAOzG,KAAKmvE,oBAAoBN,SAC9B11D,EAAO1W,kBACPgE,EACA0S,EAAO3W,OAAOi5C,WAAWh1C,GACzB,CAAEwa,UAAW,cAAelY,SAAU/I,KAAK+I,SAAU+mB,QAAS,KAI1D,qBAAqBjb,GAC3B,IAAIitG,EAAwB9hH,KAAK4G,SAC9B4E,KAAK,qBAAwBqJ,EAAMpO,KAAO,MAC1C0H,KAxTsC,yBA0TzC,OAAI2zG,EACKA,EAAsBjhG,QAAQ,kBAAmB,IAEjD,GAIH,OAAOtD,GACb,OAAIvd,KAAK4V,WAAWuoB,WAAW5gB,GAAUjb,WAChCtC,KAAK4V,WAAWuoB,WAAWn+B,KAAKgJ,aAAa7C,MAAO3D,OAEpDxC,KAAKqV,YAAY/B,GAAGiK,I,sCA9TpBwiG,GAA8B,oI,uBAA9BA,EAA8B,43EC5F3C,wBAwHA,gBACE,gBACE,gBACE,gBACE,eACF,OACF,OAEA,wBAIA,8BAIF,OACF,Q,MAzIK,2BA4H6C,qDAIjC,gEAAiD,4CAMjD,uD,sPCpGV,MAAMgC,UAAyB,IAI7B,OAAOnyF,EAAqBC,GAIjC,GAHA/vB,MAAMyhB,OAAOqO,EAASC,GAGlB7vB,KAAKgiH,qBAAsB,CAC7B,MAAMC,EAAiB/2G,SAASoF,cAAc,QAC9C2xG,EAAe1xG,UAAUC,IAAI,gBAEzBxQ,KAAKud,SAASq+B,kBAChBqmE,EAAe1xG,UAAUC,IAAI,YAG/Bof,EAAQuf,QAAQ8yE,GAIlB,GAAIjiH,KAAKysC,iBAAmBzsC,KAAKkiH,WAAY,CAC3C,MAAM16F,EAAOxnB,KAAK2a,gBAAgBwnG,cAAcniH,KAAKmG,OAErDnG,KACGyD,aACA+wD,SACAtsD,GAAGlI,KAAKud,SAASo+B,OAAOzzC,IACxBxD,MACAmoB,YACApd,KAAMksC,IACFA,EAAOymE,UACVxyF,EAAQrf,UAAUC,IAAI,IAAaq0E,YAAYr9D,OAMvD,iBACE,OAAmD,IAA5C,CAAC,UAAW,QAAQpK,QAAQpd,KAAKyG,MAG1C,kBACE,OAAIzG,KAAKmG,MACAnG,KAAK2a,gBAAgB8yE,cAAcztF,KAAKmG,OAExC,GAIH,qBACN,MAAqB,cAAdnG,KAAKyG,MAAsC,SAAdzG,KAAKyG,MAjD5B,aAAd,c,0BAA8B,M,sCAChB,aAAd,c,0BAA2B,M,sECpC9B,8DAMO,MAAM47G,UAAiE,IAKrE,KAAKzjG,EAAiB,GAAIpc,EAA6B,MAC5D,OAAOxC,KACJkc,mBACAkR,KACCptB,KAAKwb,KACLxb,KAAK0wD,eAAe9xC,EAASpc,IAU5B,eAAeoc,EAAkBpc,EAA6B,MACnE,OAAO,IAAiBkuD,eAAe9xC,EAASpc,M,6ECkC7C,SAAS8/G,EAA+BtlD,GAC7Cx8C,OAAOihB,YACJ8gF,mBACA9yG,KAAM2f,IACL,MAAMyqB,EAAiBzqB,EAAQozF,SAAS3oE,eAClC4oE,EAA4BrzF,EAAQ3N,QAAQihG,OAAOC,qBAEzD3lD,EAAE9xD,UAAUtB,GACV,SACA,uCACA,SAAmB2hC,GACjB,MAAMnnC,EAAOyC,OAAO7G,MAEpB,QAAIoE,EAAKoH,KAAK,wCAAwCvE,QA3ChE,SACE7C,EACAmnC,EACAsO,EACA4hB,GAGA,OAFwBr3D,EAAKoH,KAAK,0BAEdvE,OAAS,IAI7BskC,EAAOh/B,iBACcstC,EAAe94C,KAAK06D,EAAO,UACnCD,aAAan7D,UAAWo7D,IAC/BA,EAAM/U,YACR7/C,OAAO,WACJoD,KAAK,CACJ6I,KAAM,SACNrM,KAAM,yBACNN,MAAOs1D,EAAMmnD,wBAEd/8E,SAASzhC,GAEZA,EAAK4F,QAAQ,cAIV,GAoBQ64G,CAAiBz+G,EAAMmnC,EAAQsO,EAAgB4oE,Q,gBClDhE,SAASK,EAA+BC,EAAenrG,GACrD,IAAIorG,EAAa,8BACbC,EAAcF,EAAOv3G,KAAK,UAAYw3G,GACtCE,EAAaH,EAAO92G,SAAS,KAEN,IAAvBg3G,EAAYh8G,SACdg8G,EAAcp8G,OAAO,YAAY8D,SAASq4G,GACvCr4G,SAAS,sBAEZu4G,EAAW/tF,OAAO8tF,IAGpBA,EAAYrrG,KAAK,IAAMA,GAGzB,SAASurG,EAAuBC,GAC9B,IAAIL,EAASK,EAASn3G,SAAS,UAG3Bm3G,EAASp3G,SAAS,aACpB82G,EAA+BC,EAAQriH,KAAKU,EAAE,uBAE9C0hH,EAA+BC,EAAQriH,KAAKU,EAAE,sBAIlD,SAASiiH,EAAYpxG,GACnB,IAAI2d,EAAU/oB,OAAOoL,GAErB,GAAI2d,EAAQ6V,GAAG,UACb,OAAO5+B,OAAOoL,GAAIvD,SACb,GAAIkhB,EAAQ6V,GAAG,YACpB,OAAO7V,EAGT,KAAM,uCAeD,SAAS0zF,IACd,MAAMC,EAAY18G,OAAO,wCAGzB08G,EAAU35G,GAAG,QAAS,0BAA0B,SAAS/I,GAIvD,OApBJ,SAAwBoR,GACtB,IAAImxG,EAAWC,EAAYpxG,GAE3BmxG,EAASn5G,KAAK,eAAgB,QAC9B,IAAIu5G,EAAcJ,EAAS53G,KAAK,SAAS1B,IAAI,kBAE7Cs5G,EAASroF,YAAY,aACrByoF,EAAYC,YAAY,QAExBN,EAAuBC,GAQrBM,CAAe1jH,MACfa,EAAI0L,iBACJ1L,EAAIgM,mBACG,KAIT02G,EACGj/G,MAAK,WACJ,IAAI8+G,EAAWC,EAAYrjH,MAE3B,IAAIwjH,EAAcJ,EAAS53G,KAAK,SAC5B43G,EAASp3G,SAAS,cACpBw3G,EAAYr2G,OAGdg2G,EAAuBC,M,4BCjGtB,SAASO,KA0HhB,WACE,IAAI14G,EAAUpE,OAAO,YACjB+8G,EAAW/8G,OAAO,uDAEE,IAApB+8G,EAAS38G,QAAgBgE,EAAQe,SAAS,sBAC5C43G,EAAS55G,QAAQ,SA9HnB65G,GAoJF,WACE,MAAMC,EAAiBj9G,OAAO,kBAAkBkD,QACzB+5G,EAAet4G,KAAK,KAAKD,OAAO,UAExCvB,QAAQ,SAvJvB+5G,GACAC,IACAC,IAkGA32G,YAAW,WACTzG,OAAO,gCAAgC4rB,WACtC,KAZH5rB,OAAO,QAAQ+C,GAAG,yBAA0B,2CAA2C,SAAU0C,GAChF,UAAXA,EAAEwG,MAAgC,KAAZxG,EAAEye,OAC1BlkB,OAAO7G,MAAM0O,OAAO,gDACjB5E,IAAI,oCACJ2oB,YAxFP5rB,OAAOqE,UAAUg5G,aAAaF,GAC9Bn9G,OAAOqE,UAAUg5G,aAAaD,GAS9Bp9G,OAAOqE,UAAUi5G,UAAS,SAAUn8G,EAAO4W,GACrC/X,OAAOmB,EAAMjB,OAAOmpD,eAAgBlpD,QAAQ,oBAAoBC,QAClEJ,OAAO,mBACPA,OAAO,mBAAmB9F,OAG5B,IAAIqjH,EAAgBv9G,OAAO,yBAE3B,GAAIu9G,EAAe,CACjB,IACEC,EAAQD,EAAcn6G,KAAK,WAE7B2U,EAAQ0lG,iBAHK,eAGoBD,GAGnCzlG,EAAQ0lG,iBAAiB,0BAA2B,cAItDz9G,OAAOqE,UAAUq5G,UAAS,WACpB19G,OAAO,oBACTA,OAAO,mBAAmBsG,OAE5Bq3G,OAIF39G,OAAO,mBAAmBuF,OAAM,WAC9BvF,OAAO7G,MAAM+6B,YAAY,UAAU3yB,OAAOq7G,YAAY,QAGxD,IAAIgB,EAAe,KACnB59G,OAAO2Z,QAAQ5W,GAAG,UAAU,WAItB66G,GACFpqC,aAAaoqC,GAEfA,EAAWn3G,YAAW,WACpBzG,OAAO2Z,QAAQxW,QAAQ,eACtB,QAILnD,OAAO,sBAAsBuF,OAAM,SAAUpE,GAC3CA,EAAM6E,qBAIR,IAAI63G,EAAc79G,OAAO,YAAYkD,QACjC46G,EAAc99G,OAAO,cAAckD,aACnB2B,IAAhBg5G,EACFA,EAAYn3G,aACa7B,IAAhBi5G,IACTA,EAAYp3G,QACmB,UAA3Bo3G,EAAY,GAAGh5G,SACjBg5G,EAAYt/E,UAIhBm/E,IAGA39G,OAAOqE,SAASwT,MAAM9U,GAAG,QAAS,gCAAgC,WAKhE,OAJA4W,OAAOnW,KAAKmW,OAAOD,YAAc,oBAC/B,GACA,6FAEK,KAoBX,SAASikG,IACP39G,OAAO,YAAYvC,MAAK,WACtB,IAAIyC,EAASF,OAAO7G,MACpB+G,EAAOqF,OAAM,SAAUvL,GACrB,IAAIqG,EAAQL,OAAO,IAAME,EAAOkD,KAAK,QAAS26G,OAAO,IAMrD,OALc,OAAV19G,IAEFA,EAAQL,OAAO,IAAME,EAAOkD,KAAK,QAAS26G,OAAO,GAAGv7F,OAAO,SAE7DtiB,EAAOgmE,OAAOlsE,IACP,QAcb,SAASgkH,EAAcpzF,GACD5qB,OAAO4qB,GAEbntB,MAAK,SAAUuG,EAAIyB,GACVzF,OAAOyF,GACfvL,UAIjB,SAASijH,IAEPa,EAAc,UAGhB,SAASZ,IACPY,EAAc,mC,ICtGL7nD,E,oCCgBX,SAAe8nD,EAAYr+G,G,mDACzB,YAAS,0CAA4CA,UAClC,mCACdsjB,MAAMtjB,ODnBFu2D,EA2GTn2D,SAzGE,WACAm2D,EAAE9xD,SAASwwE,iBACR9xE,GAAG,QAAU/I,IACZ,MAAMkG,EAASF,OAAOhG,EAAIkG,QAS1B,OEnDD,SAA6BlG,EAA2BkG,GACzDA,EAAOiF,SAAS,2BAClBjF,EACGkD,KAAK,eAAgB,OAExBuW,OAAOihB,YAAY8gF,mBAChB9yG,KAAK2f,IACa,IAAI,IACnB,yBACAroB,EAAOnF,MACP,CACE64E,aAAa,EACbsqC,YAAY,GAEdh+G,EAAO,GACPqoB,EAAQozF,SAASzoC,sBAERh5E,UF4BXikH,CAAoBnkH,EAAKkG,GG/C1B,SAAgClG,EAA2BkG,GAE3DmE,SAASG,SAASxK,EAAIkG,SACzBlG,EAAI0L,iBAIN,MAAM04G,EAAcl+G,EAAOC,QAAQ,KACnC,GAA2B,IAAvBi+G,EAAYh+G,OACd,OAGF,MAAMs/B,EAAO0+E,EAAYh7G,KAAK,SAAW,GACnCi7G,EAAU3+E,EAAKnpB,QAAQ,KAGhB,KAATmpB,GAA2B,IAAZ2+E,KAMF,IAAbA,GAA2B,MAAT3+E,IACpB/lB,OAAOgoB,SAASm4C,KAAOp6C,GAGzB1lC,EAAI0L,kBHyBE44G,CAAuBtkH,EAAKkG,IAErB,IAIX,MAAM45E,EAAOngE,OAAOgoB,SAASm4C,KAC7B,GAAIA,GAAQA,EAAKhgE,WAAW,KAC1B,IACE,MAAM1O,EAAK/G,SAAS2O,cAAc8mE,GAClC1uE,GAAMA,EAAG+0B,iBACT,MAAO16B,GAIPsR,QAAQyuD,IAAI,4CAA8CsU,EAAO,MAAQr0E,EAAEkuC,QAAU,KAWzF,GALAwiB,EAAE9xD,UAAUtB,GAAG,SAAU,QAAQ,WAC/B4W,OAAOihB,YAAY2jF,iBAAkB,KAInCl6G,SAAS2O,cAAc,sBAAuB,CAChD,IAAIgnB,EAAU31B,SAAS2O,cAAc,YACjCgnB,IACFA,EAAQ7e,MAAMqjG,aAAe,SIzD9B,IAEDC,EACAC,EJ2DFvoD,EAAEx8C,QAAQ5W,GAAG,eAAiB0C,IAC5B,MAAMtE,EAAQsE,EAAEs5B,cACZplB,OAAOihB,YAAY+jF,gBAAkBhlG,OAAOihB,YAAY2jF,kBAE1Dp9G,EAAMuE,iBAENvE,EAAMytC,YAAc/0C,KAAKU,EAAE,2CAK/B47D,EAAE9xD,SAASwwE,iBACR9xE,GAAG,gBAAkB/I,IACpBA,EAAI0L,kBACG,IK9ER,WACL,MAAMqlB,EAAU1mB,SAASgxD,iBAAiB,qCAE1C,IAAK,IAAIn/C,EAAI,EAAGA,EAAI6U,EAAQ3qB,OAAQ8V,IAAK,CACvC,IAAI6S,EAAUgC,EAAQ7U,GACtB,MAAM3Y,EAAOyC,OAAO+oB,GACd5hB,EAAM5J,EAAK+J,KAAK,cAChB85E,EAAU7jF,EAAK+J,KAAK,iBAE1B/J,EACGoH,KAAKy8E,GACLr+E,GAAG,SAAU,KACZ4W,OAAOgoB,SAASjjC,KAAOyI,EAAM,IAAM5J,EAAKqhH,eLqE5CC,GAIApD,EAA+BtlD,IAEK,IAAI,KAEtB7W,UMvFf,WAEL,IAAIw/D,EAAgBnlG,OAAOy2D,QAE3Bz2D,OAAOpV,iBAAiB,UAAU,WAEhC,IAAIw6G,EAAmBplG,OAAOy2D,QAAU,EAAI,EAAKz2D,OAAOy2D,SAElDpwE,OAAO,SAASmF,SAAS,sBAC3BnF,OAAO,aAAamF,SAAS,4BAC7Byb,KAAK2sE,IAAIwxB,EAAmBD,IATb,UAaGj6G,IAAlBi6G,QAAoDj6G,IAArBk6G,GAAmCD,EAAgBC,EAEpF/+G,OAAO,YAAY6D,YAAY,oBAE/B7D,OAAO,YAAY8D,SAAS,oBAE9Bg7G,EAAgBC,MNoEdC,GCjHC,WAEL,MAAM73G,EAAM,IAAI83G,IAAItlG,OAAOgoB,SAASjjC,MAC9B4gD,EAAWj7C,SAASwT,KAAKnO,UAAUlF,SAAS,mBAC5C06G,EAAyF,SAAjEl/G,OAAO,sCAAsCoD,KAAK,WAChF,IAAI+7G,EAAkBC,eAAeliD,QAAQ,KACzCmiD,GAAgB,GAIf//D,GAAY4/D,IAIX/3G,EAAIm4G,aAAazhH,IAAI,oBAAqD,IAA/B,cAAoBuC,SACjE++G,EAAkB,GAClBC,eAAeG,QAAQ,IAA0B,gBAGjDv/G,OAAO,iCAAiCuF,OAAM,WAC5C85G,GAAgB,EAChBpB,EAAY,iBAId55G,SAASE,iBAAiB,WAAW,SAAUpD,GAC3B,WAAdA,EAAMrG,KAAqBukH,IAC7BA,GAAgB,EAChBpB,EAAY,iBAEb,CAAEuB,MAAM,KAIW,iBAApBL,GACFlB,EAAY,eAIU,8BAApBkB,GAAmDh4G,EAAIm4G,aAAazhH,IAAI,2BAC1EogH,EAAY,QAIV92G,EAAIm4G,aAAazhH,IAAI,gCACnBmC,OAAO,uBAAuBI,OAAS,GACzC69G,EAAY,YAKQ,uBAApBkB,GACFlB,EAAY,cDkEdwB,GAOAhD,IAGA,IAAI,IAAQz8G,OAAO,oBAGnBA,OAAO,oCAAoCvC,MAAK,SAAUg8E,EAAYp1D,GACpE,YAAmBrkB,OAAOqkB,OOpIzB,WACLrkB,OAAO,iCAAiC+C,GAAG,UAAU,WACnD/C,OAAO,mCAAmCpF,OAAOoF,OAAO7G,MAAMylC,GAAG,gBAChEz7B,QAAQ,UAIXnD,OAAO,oCAAoCsS,QAAO,WAChD,IAAIotG,GAAevmH,KAAKwmH,QACtBC,EAASzmH,KAAKmG,MACdk/B,EAASx+B,OAAO,mDAChBggC,EAASxB,EAAO75B,KAAK,iBAAmBi7G,EAAS,MAG7B,IAAlB5/E,EAAO5/B,SAIX4/B,EAAOljB,KAAK,WAAY4iG,GACpBA,GAAe1/E,EAAOljB,KAAK,aAC7B0hB,EAAOzjC,IAAI,QAKf,IAAI8kH,EAAuB,SAAUrhF,GACnC,IAAIr6B,EAAOnE,OAAOw+B,GACdn9B,EAAY8C,EAAKf,KAAK,OAAS,GAC/B08G,EAAcz+G,EAAG2Y,QAAQ,YAAa,IACtC+lG,EAAU57G,EAAKpJ,MACfilH,EAAWhgH,OAAO,aAAa8/G,GAC/BnmF,EAASqmF,EAAS5/C,SAAS,+BAA+B94D,KAAK,UAEnE,MAAO,CAAEjG,GAAIA,EAAIy+G,YAAaA,EAAaC,QAASA,EAASC,SAAUA,EAAUrmF,OAAQA,IAS3F35B,OAAO,uBACJ0G,OAAM,WACL,IAAIY,EAAOu4G,EAAqB1mH,MAEhC6G,OAAO,IAAIsH,EAAKjG,MAAMiG,EAAKy4G,WAAWhlH,IAAIuM,EAAKqyB,OAAOW,cAEvDhoB,QAAO,WACN,IAAIhL,EAAOu4G,EAAqB1mH,MAE5B8mH,EAAcjgH,OAAO,IAAIsH,EAAKjG,MAAMiG,EAAKy4G,WAAWhlH,MAExDuM,EAAKqyB,OAAOS,QAAQ6lF,GACpB34G,EAAK04G,SAAS58G,KAAK,OAAQ,YAAYkE,EAAKw4G,gBAAgBx4G,EAAKy4G,eAIrE//G,OAAO,yBAAyB0T,QAAO,WAQrC,OANI1T,OAAO,8BAA8B4+B,GAAG,aAAe5+B,OAAO,wBAAwB4+B,GAAG,aAC3F5+B,OAAO,0BACJjF,KAAI,IAAIotB,MAAOpP,eACf+D,KAAK,YAAY,IAGf,KAIT9c,OAAO,iCAAiC+C,GAAG,UAAU,WACnD,MAAMm9G,EAAkBlgH,OAAO7G,MAAM4B,MACrCiF,OAAO,mCAAmCsG,OAC1CtG,OAAO,0BAA4BkgH,GAAiBhmH,UACnDiJ,QAAQ,UAEXnD,OAAO,iCAAiC+C,GAAG,UAAU,WACnD,IAAIo9G,EAAgC,SAAvBngH,OAAO7G,MAAM4B,MAC1BiF,OAAO,oDACJG,QAAQ,gBACRvF,QAAQulH,MAIbngH,OAAO,2CAA2CsS,QAAO,WACvD,IAAI8tG,EAAajnH,KAAKwmH,QACT3/G,OAAO7G,MAAMgH,QAAQ,YAG/BwE,KAAK,gBACLD,OAAO,yBACPA,OAAO,uBACP27G,WAAW,YACXvjG,KAAK,WAAYsjG,MAItBpgH,OAAO,uCAAuCsS,QAAO,WACnD,IAAIhC,EAAmBtQ,OAAO7G,MAAM4B,MACpCiF,OAAO,qCAAqCpF,OAA4B,WAArB0V,MAOqC,IAAtFtQ,OAAO,oEAAoEI,QAC7EJ,OAAO,4DAA4D8c,KAAK,WAAW,GAErF9c,OAAO,mCAAmC0T,QAAO,WAC/C,IAAIq+C,EAAsB/xD,OAAO,4DACRA,OAAO,oEACTI,SAAW2xD,EAAoB3xD,QACpD2xD,EAAoBj1C,KAAK,WAAW,MPuBtCwjG,GQ1GFtgH,OAAO,mBAAmBvC,MAAK,WAC7B,IACI4gC,EACAkiF,EAFAxlD,EAAU/6D,OAAO7G,MAGjB+G,EAAS66D,EAAQzzD,KAAK,UAGxB+2B,EADEn+B,EACMF,OAAOE,GAEP66D,EAAQx5D,KAAK,SAGF,IAAjB88B,EAAMj+B,SAIVmgH,EAAO,WACL,IAAIC,EAAe,GAEfniF,EAAMtjC,OAASsjC,EAAMtjC,MAAMqF,OAAS,EACtCogH,EAAeniF,EAAMtjC,MACZsjC,EAAMj7B,KAAK,gBACpBi7B,EAAMj7B,KAAK,eAAehD,OAAS,IACnCogH,EAAeniF,EAAMj7B,KAAK,gBAG5B23D,EAAQ71D,IAAI,mBAAoBs7G,IAGlCniF,EAAMoiF,MAAMF,GAAMjuG,OAAOiuG,GAAM75G,MAAM65G,GACrCA,QJjCE9B,EAAyBz+G,OAAO,8BAChC0+G,EAAgB1+G,OAAO,gCAAgC+Q,OAE3D0tG,EAAuB95G,KAAK,SAAS5B,GAAG,SAAS,WAC/C,IAAI29G,EAAcjC,EAAuB95G,KAAK,SAAS5J,MACnD2jH,EAAc9gF,gBAAkB8iF,EAAY9iF,cAC9C6gF,EAAuB95G,KAAK,UAAUmY,KAAK,YAAY,GAEvD2hG,EAAuB95G,KAAK,UAAUmY,KAAK,YAAY,MJ8GzDggG,O,4BSpHG,MAAM6D,EACJ,SAAS/1F,EAAc+0F,GAC5B3/G,OAAO,IAAM4qB,EAAW,mBAAmB3nB,IAAI,aAAaxF,MAAK,WAC/DtE,KAAKwmH,QAAUA,KAIZ,2BAA2B/0F,GAChC,MAAMg2F,EAAQ5gH,OAAO4qB,GACrB,IAAIi2F,GAAc,EAClB,IAAK,IAAI3qG,EAAI,EAAGA,EAAI0qG,EAAMxgH,OAAQ8V,KAAgC,IAArB0qG,EAAM1qG,GAAGypG,UAAqBkB,GAAc,GACzF,IAAK,IAAI3qG,EAAI,EAAGA,EAAI0qG,EAAMxgH,OAAQ8V,IAAO0qG,EAAM1qG,GAAGypG,SAAWkB,GC4DjElnG,OAAOihB,YAAc,IArEd,MAAP,cAES,KAAAD,cAAqD,cAErD,KAAAmmF,QAAU,IAAIH,EAGd,KAAAhC,eAAwB,EAGxB,KAAAJ,iBAA0B,EAQ1B,mBACL,OAAOplH,KAAKwhC,cACTthC,UACAC,KAAK,OAAAi3C,EAAA,GAAK,IACVvqB,YAGL,cACE,OAAOhmB,OAAO,4BAA4BoD,KAAK,YAAc,GAG/D,kBACE,OAAOpD,OAAO,sCAAsCsH,KAAK,eAG3D,cACE,OAAOtH,OAAO,sCAAsCsH,KAAK,WAG3D,wBACE,MAAwB,aAAjBnO,KAAK4nH,QAGd,mBACE,MAAwB,QAAjB5nH,KAAK4nH,QAaP,oBAAoBjmH,EAAY6wC,GACrC,IACE,QAAiB9mC,IAAb8mC,EAEG,CACL,MAAMrsC,EAAQqa,OAAOqnG,aAAa9jD,QAAQpiE,GAC1C,OAAiB,OAAVwE,OAAiBuF,EAAYvF,EAHpCqa,OAAOqnG,aAAazB,QAAQzkH,EAAK6wC,GAKnC,MAAOlmC,GACPsR,QAAQoB,MAAM,sF,6CCnGpB,8DAGO,MAAM8oG,EAEX,YAAuCpsC,GAAA,KAAAA,kBAOvC,eACE,OAAO17E,KAAK+nH,aAAa,mBAM3B,aACE,OAAO/nH,KAAK+nH,aAAa,iBAGnB,aAAathH,GACnB,OAAOzG,KAAK07E,gBAAgBh9D,KAAKnO,UAAUlF,SAAS5E,I,sCArB3CqhH,GAAe,KAEL,O,yBAFVA,EAAe,QAAfA,EAAe,qBADF,U,kCCH1B,0H,uCCAA,0BACe,sEACoB,O,uBAApB,2BDUR,MAAME,EAcX,YAAqBj/G,EACArI,EACAuC,EACA8vC,EACAC,GAJA,KAAAjqC,WACA,KAAArI,OACA,KAAAuC,iBACA,KAAA8vC,mBACA,KAAAC,gBAhBd,KAAAhkC,QAAwC,GACxC,KAAA6H,eAAwB,EAExB,KAAAe,KAAO,CACZqwG,aAAcjoH,KAAKU,KAAKU,EAAE,oBAC1B8mH,gBAAiBloH,KAAKU,KAAKU,EAAE,mCAC7B+mH,iBAAkBnoH,KAAKU,KAAKU,EAAE,6CAE9BgnH,sBAAuBpoH,KAAKU,KAAKU,EAAE,qCACnCinH,0BAA2BroH,KAAKU,KAAKU,EAAE,2CAUzC,WACEpB,KAAK6W,cAAgB7W,KAAKgzC,cAAcn8B,cACxC7W,KAAKiD,eACFmpD,UACA38C,KAAK,IAAMzP,KAAKgP,QAAUhP,KAAKiD,eAAehD,SAEjDD,KAAKiD,eAAewpB,WAAWpsB,UAAU2O,IACvChP,KAAKgP,QAAUhP,KAAKiD,eAAehD,UAIhC,SACDD,KAAKgP,SACPhP,KAAKiD,eAAeqlH,kBAAkBtoH,KAAKgP,U,sCAlCpCg5G,GAA8B,oD,uBAA9BA,EAA8B,uKCZ3C,gC,KAAe,0B,kMCyCR,MAAM,EAGX,YAAoBvkH,GAAA,KAAAA,eAFZ,KAAA8kH,UAAY,cAWb,QAAQtlG,EAAkB+xC,GAG7B,OAFAh1D,KAAKggC,OAEE,IAAIzwB,QAAoC,CAACC,EAASquB,KACvD79B,KAAKuoH,UACF3uE,gBACAnqC,KAAK,IAAMD,EAAQxP,KAAKwL,KAAKyX,EAAW+xC,OAQ1C,YAAY9sD,GAGjB,OAFAlI,KAAKggC,OAEEhgC,KACJuoH,UACAroH,UACAC,KACC,OAAAi3C,EAAA,GAAK,IAENvqB,YACApd,KAAK,KACJ,MAAMtJ,EAAQnG,KAAKuoH,UAAU90G,WAAW,IACxC,OAAOpP,EAAEmH,KAAKrF,EAAOypB,GAAWA,EAAQ1nB,GAAGma,aAAena,KAIxD,OACNlI,KAAKuoH,UAAU/jD,yBAAyB,IACtCxkE,KAAKyD,aACFoyD,WACAnxD,MACAmoB,YACApd,KAAM0oE,GAAmDA,EAAU3zE,WAKlE,KAAKye,EAAkB+xC,GAC7B,MAAM7uD,EAAQnG,KAAKuoH,UAAU90G,WAAW,IACxC,OAAOpP,EAAEmH,KAAKrF,EAAQypB,GAAYA,EAAQolC,QAAUA,GAASplC,EAAQ3M,YAAcA,I,sCAvD1E,GAAyB,Y,yBAAzB,EAAyB,QAAzB,EAAyB,qBADZ,S,iHCZpB,eAIE,qBACA,kBACF,Q,oBAJG,iCAA0B,qBAGA,yCCM5B,MAAM,UAA+B,IAe1C,YAA+CnR,EAC1BpR,EACAb,EACAW,GACnBV,MAAMgS,EAAQjS,EAAOW,GAJwB,KAAAsR,SAC1B,KAAApR,OACA,KAAAb,QACA,KAAAW,aAfd,KAAAymD,eAAgB,EAGhB,KAAAE,qBAAsB,EAEpB,KAAAvvC,KAAO,CACd,KAAQ5X,KAAKU,KAAKU,EAAE,kBACpB,MAASpB,KAAKU,KAAKU,EAAE,oBAGhB,KAAAonH,SAA4BxoH,KAAK8R,OAAO02G,SAS/C,WACE1oH,MAAMqkB,WAGNnkB,KACGwoH,SACA98E,YACAoiC,QACAr+D,KAAK,IAAMzP,KAAKH,MAAMS,iBAG3B,mBACE,OAAIN,KAAKwoH,SAASC,SACTzoH,KAAKwoH,SAASC,SAASvqE,MAAM34C,KAG/B,I,sCAtCE,GAAsB,KAeb,KAAkB,gC,uBAf3B,EAAsB,8wBDvCnC,gBAEE,gBACE,gBACE,aACE,iBACA,iBACF,OAEA,cACE,cAEE,2CAAmB,EAAA+hD,QAAA,MAErB,OACF,OACF,OAEA,gBAKA,wBAIA,iBACE,sBAOF,OACF,OACF,Q,MA/B+B,wDAOrB,mCAOD,wDAGQ,oCAMR,2C,wHE7BT,mCAAwB,kEAItB,oBACA,QACF,O,uBAHwB,yEADA,yCAGtB,0CCqCK,MAAMohE,EAA4B,sBAOlC,MAAM,EAkBX,YAAsBloH,EACAmoH,EACA9uE,EACAh6C,EACAkJ,EACArI,GALA,KAAAF,aACA,KAAAmoH,qBACA,KAAA9uE,iBACA,KAAAh6C,QACA,KAAAkJ,WACA,KAAArI,OAbf,KAAAkoH,QAAiB,EAEf,KAAAhxG,KAAO,CACdixG,YAAa7oH,KAAKU,KAAKU,EAAE,4BACzB,KAAQpB,KAAKU,KAAKU,EAAE,kBACpB,MAASpB,KAAKU,KAAKU,EAAE,oBAWvB,WACE,MAAMwuB,EAAsB5vB,KAAKQ,WAAWsG,cAE5C9G,KAAK8oH,WAAa9oH,KAAK8oH,YAAcl5F,EAAQnf,QAAQq4G,WACrD9oH,KAAKijB,UAAYjjB,KAAKijB,WAAa2M,EAAQnf,QAAQwS,UACnDjjB,KAAK+oH,eAAiB/oH,KAAK+oH,gBAAkBn5F,EAAQnf,QAAQs4G,eAC7D/oH,KAAKgpH,gBAAkBhpH,KAAKgpH,iBAAmBp5F,EAAQnf,QAAQu4G,gBAE3DhpH,KAAK8oH,WACP9oH,KAAK4oH,QAAS,EAGd5oH,KAAKggC,OAAOvwB,KAAM8N,IAChBvd,KAAK4oH,SAAWrrG,EAChBvd,KAAKH,MAAMS,gBACJid,IAKN,cACLvd,KAAKggC,OAAOvwB,KAAM8N,IAChBvd,KAAK65C,eAAe94C,KAAK,EAAwBf,KAAK+I,SAAU,CAAEy/G,SAAUjrG,MAIxE,OACN,OAAIvd,KAAK8oH,WACA9oH,KAAK2oH,mBAAmBM,YAAYjpH,KAAK8oH,YAEzC9oH,KAAK2oH,mBAAmBl4F,QAAQzwB,KAAKijB,UAAWjjB,KAAK+oH,iB,sCAxDrD,GAA0B,4D,uBAA1B,EAA0B,iVDjDvC,yC,KACwB,uB,gGE4BxB,0H,uCCxBM,cAEG,oEAEH,O,uBADG,8C,uCAKD,cACE,eAAG,sDAAgB,KACjB,qBACF,OACA,eAAG,sDAAgB,KACjB,qBACF,OACA,iBACF,O,wBAP2B,8BAGC,+BAGpB,0C,uCAIJ,2CAGI,yEAA+B,kEAEnC,O,4BAHI,kB,yBAHN,gBACE,iDAMF,Q,qBALM,gC,kEAbV,cACE,sBASA,gBACE,sBAQF,OACF,Q,oBAnBO,qCASA,2DACmC,8C,qBAU1C,c,wBAGI,e,yBAA+B,uB,yBAFnC,cACE,gBACE,sBACF,OACF,Q,oBAFQ,gC,uCAKZ,oCACwB,6DAGxB,O,uBAFwB,sCDFnB,MAAMG,EAWX,YAAqBxoH,EACAd,GADA,KAAAc,OACA,KAAAd,uBATd,KAAAgY,KAAO,CACZivC,YAAa7mD,KAAKU,KAAKU,EAAE,yBAIpB,KAAA+nH,YAAc,EACd,KAAApoH,MAAO,EAMd,WACEf,KAAK8S,KAAO9S,KAAKuwE,aAAaz9D,KAGhC,WACE,OAAO9S,KAAKuwE,aAAapiE,KAGpB,cACL,OAAOnO,KAAKmO,MAAQnO,KAAKmO,KAAKlH,OAAS,EAGlC,YACL,MAAkC,WAA3BjH,KAAKuwE,aAAaz9D,KAGpB,SACL9S,KAAKJ,qBAAqB6yB,OAAOzyB,KAAKuwE,cAOjC,gBACDvwE,KAAKuwE,aAAahqC,OACpBvmC,KAAKuwE,aAAahqC,KAAKx/B,SACvB/G,KAAKyyB,UAIF,cAAc+nB,GACnBx6C,KAAKyyB,SAGA,kBACLzyB,KAAKmpH,aAAe,EAGtB,iBACE,OAAOnpH,KAAKU,KAAKU,EAAE,0BACjB,CAAEm8E,KAAMv9E,KAAKmpH,YAAal1F,MAAOj0B,KAAKmO,KAAKlH,U,sCAxDpCiiH,GAAqB,sB,uBAArBA,EAAqB,u6BCzClC,gBACE,gBACE,YACE,iBACA,iBACA,oBAKF,OACA,gBACE,sBAqBA,sBACA,sBAKF,OACF,OACA,0CAKF,Q,MA9CK,qCAGO,mDACA,gCAEH,yCAKA,gCACE,sCAqBA,uCACA,qCAOe,qC,uGCzC1Bn5G,EAAOC,QAAUg7E,OAAa,KAAI,EAAQ,S,oCCG1C,sGAAO,MAAMpC,EAAmB,kBACnBwgC,EAAmB,WAKzB,MAAMC,EAEX,YAA4B5xG,EACAijC,GADA,KAAAjjC,SACA,KAAAijC,UAGrB,cAAcx2B,EAAsB5B,EAAcue,GACvD,OAAO7gC,KAAK62B,MAAM3S,EAVa,sBAUuB5B,EAAOue,GAGxD,WAAW3c,EAAsB5B,EAAcue,GACpD,OAAO7gC,KAAK62B,MAAM3S,EAbU,mBAauB5B,EAAOue,GAGpD,MAAM3c,EAAsBpT,EAAcwR,EAAcue,GAC9D,IAAI3d,EAAIhY,SAASoF,cAAc,KAU/B,OARA4S,EAAE3d,KAAOvF,KAAKyX,OAAOlS,KAAMvF,KAAK06C,QAAgB5pC,GAAQ,CAACoT,cAAeA,IACxEhB,EAAE3S,UAAUC,IAAIo4E,GAChB1lE,EAAEzS,QAAuB,cAAIyT,EAC7BhB,EAAEzS,QAAiB,QAAIK,EAEvBoS,EAAE5R,aAAa,QAASgR,GACxBY,EAAE3R,YAAcsvB,EAET3d,K,mBClCX,SAASomG,EAAyBl6G,GAGjC,OAAOG,QAAQC,UAAUC,MAAK,WAC7B,IAAInD,EAAI,IAAIoD,MAAM,uBAAyBN,EAAM,KAEjD,MADA9C,EAAEqD,KAAO,mBACHrD,KAGRg9G,EAAyBz5G,KAAO,WAAa,MAAO,IACpDy5G,EAAyB95G,QAAU85G,EACnCv5G,EAAOC,QAAUs5G,EACjBA,EAAyBphH,GAAK,Q,oCCgB9B,0EAoBO,MAAM82C,EAKX,YAAqB+6B,GAAA,KAAAA,uBAFb,KAAAh6E,MAAQ,YAAuB,IAGrC8G,OAAO2Z,QACJ5W,GAjB4B,uBAkB3B,CAAC5B,EAA6BuoE,KAC5BvwE,KAAKwQ,IAAI+/D,KAOjB,cACE,OAAOvwE,KAAKD,MAGP,IAAIwwE,EAA4Bg5C,EAAe,KAiBpD,OAnDF1iH,OAAO,iBAAiB4rB,SAsCtBzyB,KAAKD,MAAM6vE,SAAU3vE,IACnB,IAAIupH,EAAY,CAACj5C,GAAclnD,OAAOppB,GAItC,OAHAoE,EAAEouB,OAAO+2F,EAAW,CAACr1D,EAAGp3C,IACtBA,EAAI,IAAiB,YAAXo3C,EAAErhD,MAAiC,UAAXqhD,EAAErhD,OAE/B02G,IAIiB,YAAtBj5C,EAAaz9D,MAAsB9S,KAAK+5E,qBAAqB0vC,kBAC/Dn8G,WAAW,IAAMtN,KAAKyyB,OAAO89C,GAAeg5C,GAGvCh5C,EAGF,SAAS/1B,EAA8Bvd,EAAsB,IAC7D/f,MAAM2c,QAAQoD,KACjBA,EAAS,CAACA,IAGZ,IAAIszC,EAA6BvwE,KAAK0pH,mBAAmBlvE,EAAS,SAGlE,OAFA+1B,EAAapiE,KAAO8uB,EAEbj9B,KAAKwQ,IAAI+/D,GAGX,WAAW/1B,GAChB,OAAOx6C,KAAKwQ,IAAIxQ,KAAK0pH,mBAAmBlvE,EAAS,YAG5C,WAAWA,GAChB,OAAOx6C,KAAKwQ,IAAIxQ,KAAK0pH,mBAAmBlvE,EAAS,YAG5C,UAAUA,GACf,OAAOx6C,KAAKwQ,IAAIxQ,KAAK0pH,mBAAmBlvE,EAAS,SAG5C,oBAAoBA,EAA8B41B,GACvD,OAAOpwE,KAAKwQ,IAAIxQ,KAAK2pH,mCAAmCnvE,EAAS41B,IAG5D,OAAOG,GACZvwE,KAAKD,MAAM6vE,SAAU3vE,IACnBoE,EAAEouB,OAAOxyB,EAASk0D,GAAKA,IAAMoc,GACtBtwE,IAIJ,QACLD,KAAKD,MAAMiE,SAAS,IAGd,mBAAmBw2C,EAA8B1nC,GACvD,MAAuB,iBAAZ0nC,EACF,CAAEA,QAASA,EAAS1nC,KAAMA,IAEjC0nC,EAAQ1nC,KAAOA,EAGV0nC,GAGD,mCAAmCA,EAA8B41B,GACvE,IAAKA,EAAQnpE,OACX,MAAM,IAAIyI,MAAM,yDAGlB,IAAI6gE,EAAevwE,KAAK0pH,mBAAmBlvE,EAAS,UAGpD,OAFA+1B,EAAapiE,KAAOiiE,EAEbG,G,sCAhGEvxB,GAAoB,Y,yBAApBA,EAAoB,QAApBA,EAAoB,qBADP,U,kCCnB1B,kDAOO,MAAM4qE,UAA4B,IAIvC,SACE,OAAO5pH,KAAKmtB,QAAQjlB,IAAMlI,KAAKsb,WAGjC,OAAcmhD,GACZz8D,KAAKmtB,QAAQjlB,GAAKu0D,K,kCCjBtB,gJAaO,MAAMotD,UAA2B,IAEtC,YAAqBlnH,EACAuZ,GACnBpc,MAAM6C,EAAO8B,SAFM,KAAA9B,SACA,KAAAuZ,qBAId,MAAMhU,GACX,OAAOpI,MAAMgR,MAAM9Q,KAAK8pH,SAAS5hH,IAUnC,GAAGqV,GACD,IAAI/a,EAASxC,KAAK8Q,MAAMyM,GAAUpX,MAElC,IAAK3D,EACH,KAAM,uBAAuB+a,yCAG/B,MAAuB,gBAAnBA,EAASpV,MACJ,IAAuB5F,OAAOC,EAAQ+a,GAEtC,IAAYhb,OAAOC,EAAQ+a,GAI/B,cAAcA,G,MACnB,IAAIhY,EAA6B,QAAzB,EAAGgY,EAAS9X,OAAOjD,cAAM,eAAE+C,KAEnC,IAAKA,EACH,MAAM,IAAImK,MAAM,YAAY6N,4BAG9B,OAAOhY,EAQT,aAAagY,GACX,IAAIhY,EAAOgY,aAAoB,IAAcvd,KAAK+pH,cAAcxsG,GAAYA,EAE5E,OAAOvd,KACJ8lB,iBAAiBvgB,GACjBpF,KACC,YAAK,IAEN0sB,YAYE,iBAAiBtnB,EAAa2rD,GAAgB,GASnD,OAPIlxD,KAAKmxD,MAAM5rD,IAAS2rD,IACtBlxD,KAAKsxD,aACH/rD,EACAvF,KAAKggC,KAAKz6B,IAIPvF,KAAK8Q,MAAMvL,GAAMrF,UAMhB,KAAKqF,GACb,OAAOvF,KACJkc,mBACAxX,IAAoBa,GACpBpF,KACC,YAAK,IAID,QAAQ6pH,GAChB,OAAOz6G,QAAQu0B,IAAIkmF,EAAM96G,IAAI3J,GAAQvF,KAAKggC,KAAKz6B,KAQjD,OAAOgY,EAAsB/a,GAC3BxC,KAAK4zD,WAAWlvD,IAAI1E,KAAK8pH,SAASvsG,IAAWvZ,SAASxB,GAGhD,SAAS0F,GACf,OAAIA,aAAc,IACTlI,KAAK+pH,cAAc7hH,GAEnBA,G,sCA5GA2hH,GAAkB,sB,yBAAlBA,EAAkB,QAAlBA,EAAkB,a,oCCxC/B,8DAMO,MAAMI,EACX,YAAoBl2C,GAAA,KAAAA,eAIpB,cACE,OAAO/zE,KAAK+zE,aAAam2C,WAG3B,iBACE,OAAOlqH,KAAKC,QAAQoY,MAbI,OAgBnB,aAAalS,GAClB,IAAIya,EAAQ5gB,KAAKmqH,WACjBvpG,EAAM,GAAKza,EAEXnG,KAAK+zE,aAAaq2C,SAASxpG,EAAMkC,KApBT,S,sCAGfmnG,GAAc,Y,yBAAdA,EAAc,QAAdA,EAAc,qBADD,U,gOCuCnB,MAAMI,EAAgC,4BAChCC,EAAuB,qBAE7B,MAAeC,EAoBpB,YAA6BxhH,GAAA,KAAAA,WAXtB,KAAAqmC,aAAuD,GAGvD,KAAAo7E,mBAAqD,GAMrD,KAAAj0E,UAAmB,EAuBhB,QAAQjqB,IASX,kBACL,OAAQjoB,EAAEiT,QAAQtX,KAAKovC,cAUzB,aACE,OAAOpvC,KAAK4V,WAAWE,UAAU9V,KAAKud,UAQjC,SAASnW,EAAkBu2B,GAAqB,GACrD,OAAO39B,KAAK49B,gBAAgBx2B,EAAWu2B,GACpCluB,KAAMjN,GACAA,EAAO8W,UAAaqkB,EAKlB39B,KAAKyqH,YAAYrjH,EAAW5E,IAJjCxC,KAAKoqC,gBAAgBsgF,wBAAwBloH,EAAOiE,MAAQW,GACrDmI,QAAQsuB,WAWhB,mBAAmBz2B,GAExB,OADoBpH,KAAKovC,aAAahoC,GAE7BmI,QAAQC,UAGVxP,KAAK2qH,eAAevjH,GAAWqI,KAAK,IAClCzP,KAAKsH,SAASF,GAAW,IAO7B,wBACLpH,KAAKmZ,OAAOpD,UAAUtG,KAAMrL,IAC1BC,EAAEC,KAAKF,EAAK+9C,iBAAkB,CAACvgD,EAASD,KAC1B,OAARA,GAGJ3B,KAAK4qH,mBAAmBjpH,OASjB,S,mDACX,GAAI3B,KAAKmZ,OAAO7B,YAActX,KAAKud,SAASpb,MAE1C,OADAnC,KAAKg3C,kBACEznC,QAAQC,QAAQxP,KAAKud,UAI9Bvd,KAAKmZ,OAAOF,UAAW,EAGvBjZ,KAAKwqH,mBAAqB,GAG1B,MAAMK,EAAaxmH,EAAEwL,KAAK7P,KAAKovC,cAK/B,aAFM7/B,QAAQu0B,IAAIz/B,EAAE6K,IAAIlP,KAAKovC,aAAet2B,GAA6BA,EAAQ0wD,aAE1E,IAAIj6D,QAAW,CAACC,EAASquB,KAC9B79B,KAAK4V,WAAWwE,KAA8Bpa,KAAKmZ,QAChD1J,KAAK6vB,IAEJt/B,KAAKg3C,gBAAgB6zE,GAErBr7G,EAAQ8vB,EAAO/hB,UAEfvd,KAAKoqC,gBAAgBsD,SAASpO,EAAO/hB,SAAU+hB,EAAO/S,QACtDvsB,KAAKu2C,UAAW,EAChBv2C,KAAKiqF,QAAQ3qD,GACbt/B,KAAKmZ,OAAOF,UAAW,IAExBuB,MAAOwE,IACNhf,KAAKoqC,gBAAgByD,eAAe7uB,EAAOhf,KAAKud,UAE5CyB,aAAiB,MACnBhf,KAAK8qH,uBAAuB9rG,GAC5B6e,KAGF79B,KAAKmZ,OAAOF,UAAW,EAEhB1J,QAAQsuB,OAAO7e,UAWvB,gBAAgB7X,EAAwB,MAAO4jH,GAAsB,GAC3D,QAAX5jH,IACFA,EAAS9C,EAAEwL,KAAK7P,KAAKovC,eAGvBjoC,EAAOzB,QAASe,IACd,MAAMqS,EAAU9Y,KAAKovC,aAAa3oC,GAClCqS,GAAWA,EAAQY,YAAW,GAE1BqxG,GACF/qH,KAAKmZ,OAAOQ,MAAMlT,KAKd,uBAAuBuY,GAE/Bhf,KAAKgrH,0BAA0BhsG,GAGvB,0BAA0BA,GAElC,MAAMisG,EAAsBjsG,EAAMksG,wBAIlC,GADAlrH,KAAKwqH,mBAAqBxrG,EAAMmsG,0BACG,IAA/BF,EAAoBhkH,OAIxB,OAAOjH,KAAKorH,mBAAmBH,GAGzB,mBAAmBI,GAEzB,IAAIpN,EAA0BoN,EAAgBn8G,IAAK9H,GAC1CpH,KAAK2qH,eAAevjH,GAAWqI,KAAK,KACrCzP,KAAKovC,aAAahoC,IACpBpH,KAAKovC,aAAahoC,GAAW8hE,UAAUlpE,KAAKwqH,mBAAmBpjH,IAAc,IAGxEpH,KAAK4qH,mBAAmBxjH,MAInCmI,QAAQu0B,IAAIm6E,GACTxuG,KAAK,KACJnC,WAAW,IAAMtN,KAAKsrH,uBAEvB9wG,MAAM,KACLoD,QAAQoB,MAAM,8CASV,gBAAgB5X,EAAkBu2B,GAAqB,GAC/D,OAAO,IAAIpuB,QAAQ,CAACC,EAASquB,KAC3B79B,KAAKurH,iBAAiBnkH,EAAWu2B,GACjC,MAAMk7B,EAA2B74D,KAAKmZ,OAAO3W,OAAOi5C,WAAWr0C,GAE/D,IAAKyxD,EACH,MAAM,IAAInpD,MAGZF,EAAQqpD,KASJ,iBAAiBzxD,EAAkBu2B,GAAqB,GAE9D39B,KAAKmZ,OACFpD,UACAtG,KAAK,KAEJ,MAAMopD,EAAc74D,KAAKmZ,OAAO3W,OAAOi5C,WAAWr0C,GAC7CyxD,EAAYv/C,UAAaqkB,IAC5B39B,KAAKoqC,gBAAgBsgF,wBAAwB7xD,EAAYpyD,MAAQW,GACjEpH,KAAKg3C,gBAAgB,CAAC5vC,OAGzBoT,MAAOwE,IACNpB,QAAQoB,MAAM,iCAAkCA,GAChDhf,KAAKoqC,gBAAgByD,eAAe7uB,EAAOhf,KAAKud,UAChDvd,KAAKg3C,gBAAgB,CAAC5vC,MAIpB,YAAYA,EAAkB5E,GAMpC,OAL0CxC,KAAKwrH,cAAcxrH,KAC3DwC,EACA4E,EACApH,KAAKwqH,mBAAmBpjH,IAAc,IAGrCqI,KAAM8iB,IACLvyB,KAAKovC,aAAahoC,GAAamrB,EACxBA,IAER/X,MAAOwE,IACNpB,QAAQoB,MAAM,+BAAiCA,GAC/Chf,KAAKoqC,gBAAgByD,eAAe7uB,MAjR3B,aAAd,c,0BAAqB,M,6BACP,aAAd,c,0BAAyB,M,iCACX,aAAd,c,0BAA8B,M,sCAChB,aAAd,c,0BAAwB,M,wDCrD3B,MAiBYu2C,IAaVv1D,UAVmD,KAAjD,cAA2B,OAUvB,SAASgrF,GACf,aAGA,IAAItqF,EAAOsqF,GAAUA,EAAOtqF,MAAQ,GAGhCgkB,EAAQxH,MAAMuuG,UAAU/mG,MAGxBgnG,EAAU,SAASC,GACrB,OAAQ,IAAMA,EAAOtpG,YAAYuiG,QAAQ,IAKvCgH,EAAU,SAASD,EAAQE,GAC7B,OAAOC,EAAc,QAASH,GAASE,GAAWD,QAAQC,IAKxDvuC,EAAW,SAASH,GACtB,IAAIrqE,SAAcqqE,EAClB,MAAgB,aAATrqE,GAAgC,WAATA,GAG5Bi5G,EAAa,SAAS3E,GAExB,MAAgB,mBADEA,GAKhB4E,EAAQ,SAAS7lH,GACnB,OAAO,MAAM,GAKX0zB,EAAU,SAASj4B,GACrB,OAAIsb,MAAM2c,QACD3c,MAAM2c,QAAQj4B,GAEwB,mBAAxCkO,OAAO27G,UAAUppG,SAAS4K,KAAKrrB,IAGpCqqH,EAAW,SAASrqH,GACtB,MAAuB,iBAATuE,OAA6D,oBAAxC2J,OAAO27G,UAAUppG,SAAS4K,KAAKrrB,IAGhEsqH,EAAW,SAAStqH,GACtB,MAAqB,iBAAPA,GAA2D,oBAAxCkO,OAAO27G,UAAUppG,SAAS4K,KAAKrrB,IAG9DuqH,EAAY,SAASvqH,GACvB,OAAe,IAARA,IAAwB,IAARA,GAGrBkqH,EAAgB,SAASh5G,EAAM3M,EAAOimH,GAExC,YAAmB,IAARA,GAAgC,IAARA,EAC1B3kG,KAAK3U,GAAM3M,IAEpBA,GAASA,EACTimH,GAAOA,EAEH3jD,MAAMtiE,IAA2B,iBAARimH,GAAoBA,EAAM,GAAM,EACpDC,KAGTlmH,EAAQA,EAAMkc,WAAWhK,MAAM,QAG/BlS,GAFAA,EAAQshB,KAAK3U,KAAQ3M,EAAM,GAAK,KAAOA,EAAM,IAAOA,EAAM,GAAKimH,GAAQA,MAEzD/pG,WAAWhK,MAAM,MAChB,GAAK,KAAOlS,EAAM,IAAOA,EAAM,GAAKimH,EAAOA,OAGxDE,EAAe,SAAS9xE,EAASwa,GACnC,OAAI+2D,EAAWvxE,GACNA,EAAQwa,GAERxa,GAIPtsB,EAAQ,SAAUq+F,EAAMpvC,GAC1B,IAAIx7E,EAAKwE,EACT,IAAKxE,KAAOw7E,EAASA,EAAIthC,eAAel6C,KACtCwE,EAAQg3E,EAAIx7E,GACRsqH,EAAS9lH,IAAU+lH,EAAS/lH,IAAUgmH,EAAUhmH,IAAU0zB,EAAQ1zB,GACpEomH,EAAK5qH,GAAOwE,GAEK,MAAbomH,EAAK5qH,KAAc4qH,EAAK5qH,GAAO,IACnCusB,EAAMq+F,EAAK5qH,GAAMwE,KAGrB,OAAOomH,GAILC,EAAO,CACPC,UAAW,CAAC,SAAU,SAAU,UAAW,YAAa,WAAY,SAAU,YAC9EC,eAAgB,CAAC,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,OAC3DC,YAAa,CAAC,KAAM,UAAW,WAAY,QAAS,QAAS,MAAO,OAAQ,OAAQ,SAAU,YAAa,UAAW,WAAY,YAClIC,iBAAkB,CAAC,KAAM,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,OACtGC,SAAU,CAAC,KAAM,OAIjBC,EAAgB,CAChBjB,UAAW,EACXv+B,UAAW,IACXy/B,UAAW,IACXC,2BAA2B,GAI3BC,EAAkB,CAClBhlG,KAAM,IACN4jG,UAAW,EACX3wG,OAAQ,OACRgyG,YAAY,EACZH,UAAW,IACXz/B,UAAW,KAIX6/B,EAAoB,CACpBllG,KAAM,IACN4jG,UAAW,EACX3wG,OAAQ,OACRoyE,UAAW,IACXy/B,UAAW,IAIXK,EAAa,CAAC,KAAM,KAAM,KAAM,KAAM,MAGtCC,EAAkB,CAGlBC,cAAe,KAEf7kE,OAAQ,KAER8kE,iBAAkB,IAElB/9F,YAAa,+BAGbg+F,WAAW,EAEXC,aAAc,GAGdC,iBAAkB,UAIlBC,yBAA0B,IA22B9B,OAt2BAjtH,EAAKiZ,MAAQ,WACX,IAAIhY,EACJ,IAAKA,KAAO0rH,EACVrtH,KAAK2B,GAAO0rH,EAAgB1rH,IAKhCjB,EAAKktH,kBAAoB,WACvB,IAAIjsH,EACJ,IAAKA,KAAO0rH,EAAsBrB,EAAMhsH,KAAK2B,MAC3C3B,KAAK2B,GAAO0rH,EAAgB1rH,KAGhCjB,EAAKktH,oBAiBLltH,EAAKmtH,QAAU,GAIfntH,EAAKmtH,QAAQnpH,IAAM,SAAS+jD,GAC1B,IAAInpB,EAASt/B,KAAKyoD,IAAWzoD,KAAKU,EAAK+nD,SAAWzoD,KAAc,QAUhE,OARI+rH,EAAWzsF,KACbA,EAASA,EAAOmpB,KAGM,IAApB5uB,EAAQyF,KACVA,EAAS,CAACA,IAGLA,GAIT5+B,EAAKmtH,QAAiB,QAAI,SAASplE,GACjC,IAAIolE,EAAU,GACVz6D,EAAO,GAyGX,OApGI3K,GACFolE,EAAQ3sH,KAAKunD,IAIVA,GAAU/nD,EAAK+nD,QAClBolE,EAAQ3sH,KAAKR,EAAK+nD,QAIhB/nD,EAAK8sH,WAAa9sH,EAAK4sH,eACzBO,EAAQ3sH,KAAKR,EAAK4sH,eA2CpBO,EAAQnoH,SAAQ,SAAS+iD,GACvB,IAAIqlE,EAAcrlE,EAAOpwC,MAAM,KAC3B01G,EAAgB,KAChBC,EAAiB,KACM,IAAvBF,EAAY7mH,QACd8mH,EAAgB,CACdD,EAAY,GACZA,EAAY,IACZhrG,KAAK,KACPkrG,EAAiBF,EAAY,IAEC,IAAvBA,EAAY7mH,SACnB8mH,EAAgBD,EAAY,KAGA,IAA1B16D,EAAKh2C,QAAQqrC,IACf2K,EAAKlyD,KAAKunD,GAGN/nD,EAAK8sH,WAIX,CACEO,EACAC,GACAtoH,SAAQ,SAASuoH,GAEb,MAAOA,GAMPA,IAA2BxlE,IACe,IAA1C2K,EAAKh2C,QAAQ6wG,IAEjB76D,EAAKlyD,KAAK+sH,SAKTJ,EAAQ5mH,QACX4mH,EAAQ3sH,KAAK,MAGRkyD,GAIT1yD,EAAKwtH,cAAgB,GAIrBxtH,EAAKwtH,cAAcxpH,IAAM,SAAS+jD,GAChC,OAAOzoD,KAAKyoD,IAAWzoD,KAAKU,EAAK+nD,SAAWzoD,KAAc,SAK5DU,EAAKwtH,cAAuB,QAAI,SAASj6F,GACvC,OAAQA,GACN,KAAK,EAAG,MAAO,CAAC,OAAQ,SACxB,KAAK,EAAG,MAAO,CAAC,OAChB,QAAS,MAAO,CAAC,WAMrBvzB,EAAKytH,cAAgB,WACnB,OAAOnuH,KAAKyoD,QAAUzoD,KAAKstH,eAI7B5sH,EAAKsrH,MAAQA,EAKbtrH,EAAKo8E,OAAS,SAAS9nB,EAAOllC,GAC5BA,EAAUA,GAAW,GAErB,IAEI24B,EACA2lE,EACAC,EACAZ,EALAI,EAAU7tH,KAAK6tH,QAAQnpH,IAAIorB,EAAQ24B,QAAQ/jC,QAU/C,IATsBmpG,EAAQ,GAO9BQ,EAAYruH,KAAKsuH,aAAat5D,EAAOllC,GAE9B+9F,EAAQ5mH,QAKb,GAJAwhD,EAASolE,EAAQpqC,QACjB2qC,EAASC,EAAUh2G,MAAMrY,KAAKutH,kBAC9BE,EAAeztH,KAAKytH,aAAahlE,GAEjC,CAGA,KAAO2lE,EAAOnnH,QAGRwmH,OAFJA,EAAeA,EAAaW,EAAO3qC,YAOrC,GAAIgqC,QACF,OAAOA,EAIX,GAAIzB,EAAMl8F,EAAQmoC,cAChB,OAAOq0D,EAAax8F,EAAQmoC,aAAcjD,IAK9Ct0D,EAAK6tH,mCAAqC,SAASt6F,EAAOw0B,EAAQglE,GAChE,IAEIe,EACAh0E,EAFAi0E,EADazuH,KAAKkuH,cAAcxpH,IAAI+jD,EACnBimE,CAAWz6F,GAIhC,GAAIqpD,EAASmwC,GACX,KAAOgB,EAAexnH,QAEpB,GADAunH,EAAgBC,EAAehrC,QAC3BuoC,EAAMyB,EAAae,IAAiB,CACtCh0E,EAAUizE,EAAae,GACvB,MAKN,OAAOh0E,GAIT95C,EAAKiuH,oBAAsB,SAAS16F,EAAO+gC,EAAOllC,GAChDA,EAAUA,GAAW,GACrB,IAEI24B,EACA2lE,EACAX,EACAjzE,EALAqzE,EAAU7tH,KAAK6tH,QAAQnpH,IAAIorB,EAAQ24B,QAAQ/jC,QAS/C,IARsBmpG,EAAQ,GAM9B74D,EAAQh1D,KAAKsuH,aAAat5D,EAAOllC,GAE1B+9F,EAAQ5mH,QAKb,GAJAwhD,EAASolE,EAAQpqC,QACjB2qC,EAASp5D,EAAM38C,MAAMrY,KAAKutH,kBAC1BE,EAAeztH,KAAKytH,aAAahlE,GAEjC,CAIA,KAAO2lE,EAAOnnH,SACZwmH,EAAeA,EAAaW,EAAO3qC,SAC9BnG,EAASmwC,KAGO,GAAjBW,EAAOnnH,SACTuzC,EAAUx6C,KAAKuuH,mCAAmCt6F,EAAOw0B,EAAQglE,IAGrE,GAAe,MAAXjzE,GAA8B9uC,MAAX8uC,EACrB,MAeJ,OAXe,MAAXA,GAA8B9uC,MAAX8uC,GACjBwxE,EAAMl8F,EAAQmoC,gBAEdzd,EADE8iC,EAASxtD,EAAQmoC,cACTj4D,KAAKuuH,mCAAmCt6F,EAAOnE,EAAQ24B,OAAQ34B,EAAQmoC,cAEvEnoC,EAAQmoC,aAEpBw1D,EAAe39F,EAAQmoC,cAIpB,CAAEzd,QAASA,EAASizE,aAAcA,IAQ3C/sH,EAAKmsH,SAAW,WACd,IAAI5xG,EAAOjb,KAAK88E,OAAO,QACnB7yD,EAAOjqB,KAAK88E,OAAO,QAEvB,OAAI7hE,GAAQA,EAAK2zG,IAAM3zG,EAAK4zG,GACnB,CAAC5zG,EAAK2zG,GAAI3zG,EAAK4zG,IACb5kG,GAAQA,EAAK4iG,SACf5iG,EAAK4iG,SAELL,EAAKK,UAUhBnsH,EAAKouH,eAAiB,WAMpB,IALA,IAEI1lD,EAFAg1B,EAAO15E,EAAMuI,KAAK8hG,WAClBj/F,EAAU,GAIPsuE,EAAKn3F,QAGV,GAAuB,iBAFvBmiE,EAAUg1B,EAAK3a,SAMf,IAAK,IAAIx5E,KAAQm/D,EACVA,EAAQvtB,eAAe5xC,KAIxB+hH,EAAMl8F,EAAQ7lB,MAIlB6lB,EAAQ7lB,GAAQm/D,EAAQn/D,KAI5B,OAAO6lB,GAMTpvB,EAAKsuH,yBAA2B,SAASh6D,EAAOllC,GAC9C,IAAIm/F,EAAqB,CAAC,CAACj6D,MAAOA,IAclC,OAVIg3D,EAAMl8F,EAAQxC,YAChB2hG,EAAqBA,EAAmB5lG,OAAOyG,EAAQxC,WAKrD0+F,EAAMl8F,EAAQmoC,eAChBg3D,EAAmB/tH,KAAK,CAAEs5C,QAAS1qB,EAAQmoC,eAGtCg3D,GAITvuH,EAAKwuH,UAAY,SAASl6D,EAAOllC,GAC/BA,EAAUA,GAAW,GAErB,IAEIq/F,EAFAF,EAAqBjvH,KAAKgvH,yBAAyBh6D,EAAOllC,GAI1Ds/F,EAAwBpvH,KAAK8uH,eAAeh/F,GAkBhD,cAjBOs/F,EAAsBn3D,aAK3Bg3D,EAAmBh6E,MAAK,SAASo6E,GAO/B,GANIrD,EAAMqD,EAAkBr6D,OAC1Bm6D,EAAcnvH,KAAK88E,OAAOuyC,EAAkBr6D,MAAOo6D,GAC1CpD,EAAMqD,EAAkB70E,WACjC20E,EAAc7C,EAAa+C,EAAkB70E,QAASwa,IAGpDm6D,QACF,OAAO,IAERnvH,OAMuB,iBAAlB,EACRmvH,EAAcnvH,KAAKsvH,YAAYH,EAAar/F,GACnCwtD,EAAS6xC,IAAgBnD,EAAMl8F,EAAQmE,SAChDk7F,EAAcnvH,KAAKuvH,UAAUz/F,EAAQmE,MAAO+gC,EAAOllC,IAG9Cq/F,GATEnvH,KAAKwvH,mBAAmBx6D,EAAOllC,IAa1CpvB,EAAK4uH,YAAc,SAAS90E,EAAS1qB,GACnCA,EAAUA,GAAW,GACrB,IACIN,EAEA/oB,EACAgpH,EAOAtpH,EAXAyrB,EAAU4oB,EAAQme,MAAM34D,KAAKwvB,aAOjC,IAAKoC,EACH,OAAO4oB,EAKT,KAAO5oB,EAAQ3qB,QAEbR,GADA+oB,EAAcoC,EAAQ6xD,SACH5iE,QAAQ7gB,KAAKwvB,YAAa,MAG3CrpB,EADE6lH,EAAMl8F,EAAQrpB,IACRqpB,EAAQrpB,GAAM4b,WAAWxB,QAAQ,OAAQ,SACxCpa,KAAQqpB,EACT9vB,KAAK0vH,gBAAgBlgG,EAAagrB,EAAS1qB,GAE3C9vB,KAAK2vH,mBAAmBngG,EAAagrB,EAAS1qB,GAGxD2/F,EAAQ,IAAIxgE,OAAOz/B,EAAY3O,QAAQ,OAAQ,OAAOA,QAAQ,OAAQ,QACtE25B,EAAUA,EAAQ35B,QAAQ4uG,EAAOtpH,GAGnC,OAAOq0C,EAAQ35B,QAAQ,UAAW,MAMpCngB,EAAK6uH,UAAY,SAASt7F,EAAO+gC,EAAOllC,GAEtC,IAAI4+F,EAAqBpvF,EAGzB,OAJAxP,EAAU9vB,KAAK8uH,eAAe,CAAC76F,MAAO5U,OAAO4U,IAASnE,GAI3BpkB,OAD3B4zB,EAASt/B,KAAK2uH,oBAAoB16F,EAAO+gC,EAAOllC,IACrC29F,cAAoD,MAAvBnuF,EAAOmuF,aACtCztH,KAAKwvH,mBAAmBx6D,EAAOllC,GAGlBpkB,MAAlB4zB,EAAOkb,SAA0C,MAAlBlb,EAAOkb,QACjCx6C,KAAKsvH,YAAYhwF,EAAOkb,QAAS1qB,IAGxC4+F,EAAa1uH,KAAKkuH,cAAcxpH,IAAIorB,EAAQ24B,QACrCzoD,KAAKwvH,mBAAmBx6D,EAAQ,IAAM05D,EAAWz6F,GAAO,GAAInE,KAKvEpvB,EAAK8uH,mBAAqB,SAASx6D,EAAOllC,GAExC,GAA4B,SAAzB9vB,KAAK0tH,iBAA4B,CAElC,IAAIkC,EAAI56D,EAAM38C,MAAM,KAAKqM,OAAO,GAAG,GAEnC,OAAQ1kB,KAAK2tH,yBAAyB1mH,OAAS,EAAIjH,KAAK2tH,yBAA2B,IAC/EiC,EAAE/uG,QAAQ,IAAI,KAAKA,QAAQ,mBAC3B,SAAS83C,EAAOk3D,EAAIC,GAAK,OAAOD,EAAK,IAAMC,EAAGrrF,iBAOpD,MAAO,aAFmB,CAFa,MAAX3U,GAAqC,MAAlBA,EAAQ24B,OAAkB34B,EAAQ24B,OAASzoD,KAAKmuH,gBACrEnuH,KAAKsuH,aAAat5D,EAAOllC,IACShN,KAAK9iB,KAAKutH,kBAE1B,kBAI9C7sH,EAAKivH,mBAAqB,SAASngG,EAAagrB,EAAS1qB,GACvD,MAAO,YAAcN,EAAc,WAGrC9uB,EAAKgvH,gBAAkB,WACrB,OAAOhvH,EAAKivH,mBAAmBxlD,MAAMzpE,EAAMquH,YAc7CruH,EAAKqvH,SAAW,SAASpE,EAAQ77F,GAC/BA,EAAU9vB,KAAK8uH,eACXh/F,EACA9vB,KAAK88E,OAAO,iBACZgwC,GAGJ,IAGIjB,EAEAmE,EALAC,EAAWtE,EAAS,EAEpB/qG,EADSgrG,EAAQnkG,KAAK2sE,IAAIu3B,GAAS77F,EAAQ+7F,WAAWxpG,WACvChK,MAAM,KAErB63G,EAAS,GAETh1G,EAAS4U,EAAQ5U,QAAU,KAC3Bi1G,EAAOF,EAAW,IAAM,GAM5B,IAHAtE,EAAS/qG,EAAM,GACfirG,EAAYjrG,EAAM,GAEX+qG,EAAO1kH,OAAS,GACrBipH,EAAOxhF,QAAQi9E,EAAO/G,OAAOn9F,KAAKyoD,IAAI,EAAGy7C,EAAO1kH,OAAS,GAAI,IAC7D0kH,EAASA,EAAO/G,OAAO,EAAG+G,EAAO1kH,OAAQ,GA0B3C,OAvBA+oH,EAAkBE,EAAOptG,KAAKgN,EAAQi9F,WAElCj9F,EAAQk9F,2BAA6BnB,IACvCA,EAAYA,EAAUhrG,QAAQ,MAAO,KAGnCiP,EAAQ+7F,UAAY,GAAKA,IAC3BmE,GAAmBlgG,EAAQw9D,UAAYu+B,GAUzCmE,GANE90G,EADE4U,EAAQo9F,WACD,KAAOhyG,EAGPA,EAAO2F,QAAQ,KAAM,SAI7BA,QAAQ,KAAMiP,EAAQ7H,MACtBpH,QAAQ,KAAMmvG,GACdnvG,QAAQ,KAAMsvG,IAqBnBzvH,EAAK0vH,WAAa,SAASzE,EAAQ77F,GAQjC,OAPAA,EAAU9vB,KAAK8uH,eACXh/F,EACA9vB,KAAK88E,OAAO,0BACZ98E,KAAK88E,OAAO,iBACZmwC,GAGGjtH,KAAK+vH,SAASpE,EAAQ77F,IAU/BpvB,EAAK2vH,SAAW,SAASr7D,EAAO7uD,EAAO2pB,GAGrC,OAFAA,IAAYA,EAAU,IAEdklC,GACN,IAAK,WACH,OAAOh1D,KAAKowH,WAAWjqH,GACzB,IAAK,SAEH,OADA6uD,EAAQh1D,KAAK88E,OAAO,iBACb98E,KAAK+vH,SAAS5pH,EAAO6uD,GAC9B,IAAK,aACH,OAAOh1D,KAAKswH,aAAanqH,GAC3B,QACE,IAAIoqH,EAQJ,OALEA,EADEv7D,EAAM2D,MAAM,gBACG34D,KAAKwwH,OAAOx7D,EAAO7uD,GAEnBA,EAAMkc,WAGlBriB,KAAKsvH,YAAYiB,EAAgBzgG,KAiB9CpvB,EAAK82C,UAAY,SAASvtB,GACxB,IAAI2H,EAAS6+F,EAAeC,EAE5B,GAAoB,iBAAV,EACR,OAAOzmG,EAKT,GAFA2H,EAAU3H,EAAK5H,WAAWs2C,MAAM,uFAEnB,CACX,IAAK,IAAI57C,EAAI,EAAGA,GAAK,EAAGA,IACtB6U,EAAQ7U,GAAKsgB,SAASzL,EAAQ7U,GAAI,KAAO,EAI3C6U,EAAQ,IAAM,EAEd8+F,EAAW9+F,EAAQ,GAAK,KAAQ,IAAMA,EAAQ,IAAM,KAGlD6+F,EADE7+F,EAAQ,GACM,IAAI5C,KAAKA,KAAK2hG,IAAI/+F,EAAQ,GAAIA,EAAQ,GAAIA,EAAQ,GAAIA,EAAQ,GAAIA,EAAQ,GAAIA,EAAQ,GAAI8+F,IAE1F,IAAI1hG,KAAK4C,EAAQ,GAAIA,EAAQ,GAAIA,EAAQ,GAAIA,EAAQ,GAAIA,EAAQ,GAAIA,EAAQ,GAAI8+F,OAE1E,iBAAV,GAEfD,EAAgB,IAAIzhG,MACN4hG,QAAQ3mG,GACbA,EAAK0uC,MAAM,wEAGpB83D,EAAgB,IAAIzhG,MACN4hG,QAAQ5hG,KAAK9P,MAAM,CAC/B+vC,OAAO4hE,GAAI5hE,OAAO6hE,GAAI7hE,OAAO8hE,GAAI9hE,OAAO+hE,GAAI/hE,OAAOgiE,GAAIhiE,OAAOiiE,IAC9DpuG,KAAK,QACEmH,EAAK0uC,MAAM,gCAEpB83D,EAAgB,IAAIzhG,MACN4hG,QAAQ5hG,KAAK9P,MAAM+K,KAOnC,OAAOwmG,GAiCT/vH,EAAKywH,SAAW,SAASlnG,EAAM/O,GAC7B,IAAI4U,EAAU9vB,KAAK88E,OAAO,QACtBs0C,EAAkB1wH,EAAKmsH,WAS3B,GANK/8F,IACHA,EAAU,IAGZA,EAAU9vB,KAAK8uH,eAAeh/F,EAAS08F,GAEnC/jD,MAAMx+C,EAAKonG,WACb,MAAM,IAAI3hH,MAAM,+EAGlB,IAAI4hH,EAAUrnG,EAAKsnG,SACf1hB,EAAM5lF,EAAKunG,UACXC,EAAOxnG,EAAKynG,cACZC,EAAQ1nG,EAAK2nG,WAAa,EAC1B/qG,EAAOoD,EAAK4nG,WACZC,EAASjrG,EACTgmG,EAAWhmG,EAAO,GAAK,EAAI,EAC3BkrG,EAAO9nG,EAAK+nG,aACZC,EAAOhoG,EAAKioG,aACZx5E,EAASzuB,EAAKkoG,oBACdC,EAAiB3qG,KAAKg9D,MAAMh9D,KAAK2sE,IAAI17C,EAAS,KAC9C25E,EAAmB5qG,KAAK2sE,IAAI17C,GAA4B,GAAjB05E,EACvCE,GAAkB55E,EAAS,EAAI,IAAM,MAClC05E,EAAe/vG,WAAWpb,OAAS,EAAI,IAAMmrH,EAAiBA,IAC9DC,EAAiBhwG,WAAWpb,OAAS,EAAI,IAAMorH,EAAmBA,GAiCzE,OA9BIP,EAAS,GACXA,GAAkB,GACE,IAAXA,IACTA,EAAS,IAyBX52G,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,GADAA,EAASA,EAAO2F,QAAQ,KAAMiP,EAAQ48F,eAAe4E,KACrCzwG,QAAQ,KAAMiP,EAAQ28F,UAAU6E,KAChCzwG,QAAQ,KAAMiP,EAAQ88F,iBAAiB+E,KACvC9wG,QAAQ,KAAMiP,EAAQ68F,YAAYgF,KAClC9wG,QAAQ,KAAM6qG,EAAQ7b,KACtBhvF,QAAQ,KAAMgvF,IACdhvF,QAAQ,MAAOgvF,IACfhvF,QAAQ,KAAM6qG,EAAQ7kG,KACtBhG,QAAQ,MAAOgG,IACfhG,QAAQ,KAAM6qG,EAAQoG,KACtBjxG,QAAQ,MAAOixG,IACfjxG,QAAQ,KAAM6qG,EAAQiG,KACtB9wG,QAAQ,MAAO8wG,IACf9wG,QAAQ,KAAM6qG,EAAQuG,KACtBpxG,QAAQ,MAAOoxG,IACfpxG,QAAQ,KAAMuwG,EAAgBvE,KAC9BhsG,QAAQ,KAAM6qG,EAAQqG,KACtBlxG,QAAQ,MAAOkxG,IACflxG,QAAQ,KAAMywG,IACdzwG,QAAQ,KAAM6qG,EAAQ+F,KACtB5wG,QAAQ,MAAO6qG,EAAQ+F,GAAM5wG,QAAQ,MAAO,MAC5CA,QAAQ,KAAM4wG,IACd5wG,QAAQ,KAAMyxG,IAMhC5xH,EAAK8vH,OAAS,SAASx7D,EAAOu9D,GAC5B,IAAItoG,EAAOjqB,KAAKw3C,UAAU+6E,GACtBr3G,EAASlb,KAAK88E,OAAO9nB,GAGzB,OAAI/qC,EAAK5H,WAAWs2C,MAAM,YACjB1uC,EAAK5H,WAGTnH,EAIElb,KAAKmxH,SAASlnG,EAAM/O,GAHlB+O,EAAK5H,YAOhB3hB,EAAK4vH,aAAe,SAAS3E,EAAQ77F,GAQnC,OAPAA,EAAU9vB,KAAK8uH,eACXh/F,EACA9vB,KAAK88E,OAAO,4BACZ98E,KAAK88E,OAAO,iBACZqwC,GAGGntH,KAAK+vH,SAASpE,EAAQ77F,IAI/BpvB,EAAK8xH,YAAc,SAAS7G,EAAQ77F,GAQlC,IAPA,IAGI7H,EACA4jG,EAJA4G,EAAK,KACL90G,EAAOguG,EACP+G,EAAa,EAKV/0G,GAAQ80G,GAAMC,EAAa,GAChC/0G,GAAc80G,EACdC,GAAc,EAgBhB,OAbmB,IAAfA,GACFzqG,EAAOjoB,KAAKoB,EAAE,wCAAyC,CAAC6yB,MAAOtW,IAC/DkuG,EAAY,IAEZ5jG,EAAOjoB,KAAKoB,EAAE,oCAAsCgsH,EAAWsF,IAC/D7G,EAAaluG,EAAO8J,KAAKg9D,MAAM9mE,IAAU,EAAK,EAAI,GAGpDmS,EAAU9vB,KAAK8uH,eACXh/F,EACA,CAAC7H,KAAMA,EAAM4jG,UAAWA,EAAW3wG,OAAQ,OAAQ6xG,UAAW,KAG3D/sH,KAAK+vH,SAASpyG,EAAMmS,IAG7BpvB,EAAK4tH,aAAe,SAASt5D,EAAOllC,GAgBlC,OAfAA,EAAUA,GAAW,GAGjB+J,EAAQm7B,KACVA,EAAQA,EAAMlyC,KAAK9iB,KAAKutH,mBAOtBz9F,EAAQklC,QACVA,EAAQ,CAACllC,EAAQklC,MAAOA,GAAOlyC,KAAK9iB,KAAKutH,mBAGpCv4D,GAYTt0D,EAAK8tD,OAAS,SAAWmkE,EAAMC,GAC7B,YAAqB,IAAX,QAA2C,IAAX,EACjC,GAEF1kG,EAAMykG,EAAMC,IAIrBlyH,EAAKU,EAAIV,EAAKwuH,UACdxuH,EAAKs5B,EAAIt5B,EAAK2vH,SACd3vH,EAAKmyH,EAAInyH,EAAK6uH,UAEP7uH,EArhC6BiyG,CAAQp9C,KAAO,+B,kCCQrD,kM,yBA+BI,gBAEE,uBAEF,Q,oBAFc,4CAA6B,wCAUxC,MAAMu9D,EAeX,YAAqBC,EACA/vH,EACAgwH,EACApwH,EACA/C,GAJA,KAAAkzH,mBACA,KAAA/vH,gBACA,KAAAgwH,SACA,KAAApwH,aACA,KAAA/C,QAjBL,KAAAozH,aAAsB,EACtB,KAAAC,aAAsB,GACtB,KAAAC,kBAA2B,GAEjC,KAAAp8B,iBAAmB,IAAI,IACvB,KAAAH,YAAc,IAAI,IAClB,KAAAjO,iBAAmB,IAAI,IAI1B,KAAAyqC,gBAAsC,aACtC,KAAAj8G,iBAAoC,OAS3C,WACEnX,KAAK6gD,SAAW7gD,KAAKu3B,cAAcC,mBACnCx3B,KAAK2gD,aAAe,IACX3gD,KAAKu3B,cAAcC,mBAG5Bx3B,KAAK+yH,iBACFxiF,WACApwC,KACC,YAAUH,KAAK4C,WAAWq6D,sBAC1B,eAED58D,UAAU,KACTL,KAAKmX,iBAAmBnX,KAAK+yH,iBAAiB9yH,QAAQ+W,KACtDhX,KAAKH,MAAMS,kBAKV,wBACL,IAAIuD,EAAQ7D,KAAK4C,WAAWiB,MAAMsC,MAC9BtC,GAAS7D,KAAKgD,cAAc41F,sBAAsB/0F,IACpD7D,KAAKgzH,OAAO54G,KAAKvW,I,sCA5CVivH,GAAyB,oD,uBAAzBA,EAAyB,sRALzB,CACT,IACA,OACD,yZAzBC,yBAMc,kCAAW,EAAAl6B,0BAAX,CAAmC,uCACf,EAAA7B,iBAAA,UADpB,CAAmC,kCAEpB,EAAAH,YAAA,UAFf,CAAmC,uCAGf,EAAAjO,iBAAA,WAIlC,OAEA,uB,MAfc,wCAAiC,sBAAjC,CAAiC,oBAAjC,CAAiC,sCAAjC,CAAiC,sBAAjC,CAAiC,gCAAjC,CAAiC,yBAAjC,CAAiC,oBAAjC,CAAiC,qBAe1C,qC,gGC/BT,sI,uCC5BA,mBACQ,+CAAS51C,iBAAA,sB,gBAGf,cACA,iBACF,O,uBAJQ,qCAGqB,gD,uCAMzB,0BAGe,kFAA6C,O,wBAF7C,0BAAmB,uB,yBAFpC,gBACE,gCAIF,Q,oBAJiB,kC,yCDwCZ,MAAMsgF,UAA4C,IASvD,YAAqBpwH,EACApD,EACAkzC,GACnBjzC,QAHmB,KAAAmD,iBACA,KAAApD,QACA,KAAAkzC,mBAVM,KAAA4+C,kBAA2B,EAC3B,KAAAC,iBAA0BlxF,KAAKU,EAAE,oBAC3C,KAAAyxC,eAAiB,IAAI,IAAqD,YAAmB7yC,OAGvG,KAAAgP,QAAUhP,KAAKiD,eAAehD,QAC9B,KAAA+9E,QAAS,EAMdh+E,KAAKszH,SAAWtzH,KAAK+yC,iBAAiB/6B,aAAa,YAAmBhY,OAGxE,WACEA,KAAKiD,eACF2+E,YACAzhF,KACCH,KAAKI,kBAENC,UAAU,KACTL,KAAKgP,QAAUhP,KAAKiD,eAAehD,QACnCD,KAAKg+E,QAAS,EACdh+E,KAAKH,MAAMS,kBAIV,kBAAkB0O,GACvB,IAAIsG,EAAYtG,EAAQzD,OAAO0G,GAAMjS,KAAKiD,eAAeswH,YAAYthH,IACrEjS,KAAKiD,eAAeqlH,kBAAkBhzG,GACtCtV,KAAK6yC,eAAerqC,KAAK8M,I,sCAhChB+9G,GAAmC,gC,uBAAnCA,EAAmC,ssBCnDhD,yBAQA,gBAEE,sB,gBAMF,Q,MAbQ,gCAMH,2CACkD,4C,4GCkBvD,8J,sBAcO,MAAMG,UAA8B,IAkBzC,YAA2BhzH,EACAyb,EACAtB,GACzB7a,QAHyB,KAAAU,aACA,KAAAyb,uBACA,KAAAtB,kBAnBV,KAAA4sD,SAAW,IAAI,IAA8B,YAAmBvnE,OAChE,KAAAka,SAAW,IAAI,IAEhB,KAAA8sF,YAAqB,GACrB,KAAAnhE,SAAwB36B,SAASwT,KACjC,KAAA+C,QAAiB,GACjB,KAAAvZ,GAAY,GACZ,KAAAzB,KAAc,GACd,KAAA8S,UAAmB,EACnB,KAAAoE,KAAc,GACd,KAAApQ,OAAgB,EAChB,KAAAoL,UAAmB,EAW5B3Y,KAAKkI,KACRlI,KAAKkI,GAAK,oBAAsBuf,KAAKg9D,MAAsB,IAAhBh9D,KAAK68D,UAAiBjiE,SAAS,IAI9E,kBACEriB,KAAKyzH,uBAGP,cACEzzH,KAAK0zH,oBAAsB1zH,KAAK0zH,mBAAmBx1F,UAGrD,cACOl+B,KAAK2Y,UACR3Y,KAAK0zH,mBAAmB3yH,OAI5B,cAAc2kC,GACR1lC,KAAKsX,UACPtX,KAAK0zH,mBAAmBruH,QACfrF,KAAK2zH,oBACd3zH,KAAKunE,SAAS/+D,KAAKxI,KAAKm3D,cAI5B,oBAAoBnvD,GACZA,EAAM4rH,eACV5zH,KAAK0zH,mBAAmBv5C,mBAAmB05C,kBAAkBxoH,SAASrD,EAAM4rH,gBAC5E5zH,KAAK0zH,mBAAmBvmH,OAIpB,UACN,MAAoC,KAA7BnN,KAAKm3D,aAAa/1B,OAG3B,mB,MACE,OAAwB,QAAjB,EAAAphC,KAAK8zH,oBAAY,eAAE3tH,QAAS,GAGrC,mBACE,OAAOnG,KAAK+zH,UAAUjtH,cAGhB,mBACN,OAAwD,OAAjD9G,KAAKm3D,aAAawB,MAAM,qBAGzB,uBACN,IAoBIq7D,EApBAlkG,EAAc,CAChBi1F,YAAY,EACZl/E,SAAU7lC,KAAK6lC,SACf0hC,SAAS,CAAC0sD,EAAsBC,KAC9B,IAAItyH,EAAasyH,EAEbl0H,KAAKsX,YAITtX,KAAK8zH,aAAa3tH,MAAQvE,EAC1B5B,KAAKunE,SAAS/+D,KAAK5G,KAErBuyH,UAAW,CAACF,EAAsBC,EAAgBzuD,EAAmBt3D,KAC/DA,EAAK4c,OAAS,IAASC,QACzBhrB,KAAKka,SAAS1R,SAOlBwrH,EADEh0H,KAAKsX,SAAWtX,KAAKgnG,YACRhnG,KAAK2a,gBAAgBy5G,aAAap0H,KAAKgnG,aAAaqtB,SAEpDr0H,KAAKm3D,aAGtBn3D,KAAK0zH,mBAAqB,IAAI,IAC5B,IAAM1zH,KAAKkI,GACX8rH,EACAlkG,I,sCAxGO0jG,GAAqB,gC,uBAArBA,EAAqB,uD,OAAA,K,6cC1ClC,oBASO,gCAAS,EAAAc,gBAAT,CAAuB,2BACf,EAAAntE,oBAAA,KADR,CAAuB,4BAEd,EAAAotE,cAAA,MAXhB,Q,KACO,gBAAS,cAAT,CAAS,sBAAT,CAAS,oBAAT,CAAS,cAAT,CAAS,sBAAT,CAAS,gBAAT,CAAS,wB,0EC2BhB,kDAGO,MAAMC,UAAuB,IAKlC,YACE,OAAOx0H,KAAK2C,OAAO6xD,SAAS9vD,IAAI1E,KAAKuF,S,kCCrCzC,kGAmBO,MAAMkvH,UAAwC,IAEnD,YAA4B7xH,EACAD,EACAlC,GAC1BX,MAAM8C,GAHoB,KAAAA,aACA,KAAAD,SACA,KAAAlC,gBAE1BT,KAAK2Z,QAGP,cACEqjE,UAAUjQ,OAAO,CAAC,YAAa,WAC/BiQ,UAAUjQ,OAAO,CAAC,YAAa,WAG1B,oBAAoB2nD,GACzB,IAAI5jH,EAAsC,CACxCy0B,SAAU,GACVovF,eAAgB,MAGlBD,EAAuBhvH,QAAQwC,GAAM4I,EAAMy0B,SAASr9B,IAAM,GAE1DlI,KAAKwT,aAAanO,QAClBrF,KAAK+xC,cAAc/tC,SAAS8M,GAGvB,WAAWoT,G,MAChB,SAAqB,QAAb,EAAClkB,KAAKC,eAAO,eAAEslC,SAASrhB,IAM3B,UAAU8a,GACf,MAAMluB,EAAsC9Q,KAAK40H,YAEjD51F,EAAKt5B,QAASmuB,IACRA,EAAI3P,gBACNpT,EAAMy0B,SAAS1R,EAAI3P,gBAAiB,KAIxClkB,KAAKwU,OAAO1D,GAMP,0BACL,IAAI+jH,EAAU70H,KAAK2C,OAAOkT,aAC1B,OAAO7V,KAAKg3F,4BAA4B9nF,IAAIhH,GAAM2sH,EAAQnwH,IAAIwD,GAAI/B,OAG7D,4B,MACL,IAAIo/B,EAAoB,GAQxB,OANAlhC,EAAEC,KAAiB,QAAb,EAACtE,KAAKC,eAAO,eAAEslC,SAAU,CAACiK,EAAoB1lB,KAC9C0lB,GACFjK,EAASrkC,KAAK4oB,KAIXyb,EAMF,QACLvlC,KAAKwU,OAAOxU,KAAK40H,aAGnB,cACE,OAA+B,IAAxB50H,KAAK80H,eAMd,qB,MACE,OAAOzwH,EAAEsZ,KAAiB,QAAb,EAAC3d,KAAKC,eAAO,eAAEslC,UAOvB,UAAUrhB,G,MACf,IAAIsrB,EAAyB,QAAf,EAAGxvC,KAAKC,eAAO,eAAEslC,SAASrhB,GACxClkB,KAAKohF,YAAYl9D,GAAgBsrB,GAQ5B,YAAYtrB,EAAsB3P,GACvC,IAAIzD,EAAQ9Q,KAAKC,SAAWD,KAAK40H,YACjC9jH,EAAMy0B,SAASrhB,GAAiB3P,EAChCvU,KAAKwU,OAAO1D,GAMP,aAAagZ,EAAaje,GAC/B,MAAM5L,EAAUD,KAAK40H,YACrB30H,EAAQslC,SAASzb,IAAQ,EACzB7pB,EAAQ00H,eAAiB9oH,EAEzB7L,KAAKwU,OAAOvU,GAQP,sBAAsB++B,EAA4BlV,EAAaje,GACpE,IAAIiF,EAAQ9Q,KAAKC,SAAWD,KAAK40H,YAGjC,GAA4B,IAAxB50H,KAAK80H,gBAAiD,OAAzBhkH,EAAM6jH,eACrC7jH,EAAMy0B,SAASzb,IAAQ,EACvBhZ,EAAM6jH,eAAiB9oH,MAClB,CACL,IAAIke,EAAQtC,KAAK0pE,IAAItlF,EAAUiF,EAAM6jH,gBACjCpsG,EAAMd,KAAKyoD,IAAIrkE,EAAUiF,EAAM6jH,gBAEnC31F,EAAKt5B,QAAQ,CAACmuB,EAAK9W,KACb8W,EAAI3P,gBACNpT,EAAMy0B,SAAS1R,EAAI3P,eAAiBnH,GAAKgN,GAAShN,GAAKwL,KAK7DvoB,KAAKwU,OAAO1D,GAGP,0BAA0BikH,GAE/B/3C,UAAUlwE,KAAK,CAAC,YAAa,UAAYR,IACvCtM,KAAKg1H,UAAUD,KACfzoH,EAAEC,iBAEFvM,KAAKS,cAAcsK,SACZ,IAIJ,8BAELiyE,UAAUlwE,KAAK,CAAC,YAAa,UAAYR,IACvCtM,KAAK2Z,QACLrN,EAAEC,iBAEFvM,KAAKS,cAAcsK,SACZ,IAIX,kBACE,MAAO,CACLw6B,SAAU,GACVovF,eAAgB,MAIpB,eAAe9wH,EAAqBC,K,sCAzKzB2wH,GAA+B,gC,yBAA/BA,EAA+B,QAA/BA,EAA+B,a,kCCS5C,kJAuBO,MAAMQ,UAA2B,IAgBtC,YAAqB/yF,EACD1hC,EACCiqB,EACAy7B,GACnBpmD,QAJmB,KAAAoiC,gBACD,KAAA1hC,aACC,KAAAiqB,eACA,KAAAy7B,kBAfZ,KAAAgvE,YAAkC,YAOnC,KAAAtqC,gBAAkB,IAEnB,KAAAuqC,QAAiB,EACjB,KAAAjC,aAAe,qDAStB,WAEElzH,KAAKo1H,gBAA+BlqH,SAASqtF,uBAAuBv4F,KAAKq1H,cAAc,GAGvF,IAAIC,EAAoBt1H,KAAKu1H,yBAC7Bv1H,KAAKyrF,aAAe6pC,IACCt1H,KAAKo1H,gBAAgBrpC,YAAc/rF,KAAK4qF,gBACvC5qF,KAAK4qF,gBACL5qF,KAAKo1H,gBAAgBrpC,aAIjB,IAAtB/rF,KAAKyrF,cAAsBzrF,KAAKo1H,gBAAgB7zE,gBAClDvhD,KAAKyrF,aAAezrF,KAAKo1H,gBAAgB7zE,cAAcwqC,YAAc,GAGvE/rF,KAAKo1H,gBAAgBpzG,MAAMhiB,KAAKk1H,aAAel1H,KAAKyrF,aAAe,KAGnEzrF,KAAK4vB,QAAU5vB,KAAKQ,WAAWsG,cAG/B9G,KAAKkiC,cAAcspD,YAChBrrF,KACC,cACAH,KAAKI,kBAENC,UAAUkrF,IACTvrF,KAAKw1H,4BAIT,YAAUh1G,OAAQ,SAAU,CAAE25E,SAAS,IACpCh6F,KACCH,KAAKI,iBACL,YAAa,MAEdC,UAAU,IAAML,KAAKw1H,2BAG1B,kBAEEx1H,KAAKy1H,QAAuBz1H,KAAKQ,WAAWsG,cAAcyxF,uBAAuBv4F,KAAKkzH,cAAc,GAEpGlzH,KAAK01H,kBAAkB11H,KAAKo1H,gBAAiBp1H,KAAKyrF,cAGpD,cACE3rF,MAAM4Y,cAEN1Y,KAAKo1H,gBAAgBpzG,MAAMhiB,KAAKk1H,aAAe,GAGjD,cAGE,IAAII,EAAoBt1H,KAAKu1H,yBACzBI,EAAqB31H,KAAKo1H,gBAAgBrpC,YAC1CupC,GAAqBA,EAAoBK,IAC3C31H,KAAKyrF,aAAekqC,GAIxB,YACE,IAAIL,EAAoBt1H,KAAKu1H,yBACzBD,IACFt1H,KAAKyrF,aAAe6pC,GAItB,MAAMttH,EAAQ,IAAIwkF,MAAMxsF,KAAK41H,aAC7Bp1G,OAAOq1G,cAAc7tH,GAErBhI,KAAK81H,kBAAiB,GAGxB,WAAWC,GAGT,IAAIvjF,EADJxyC,KAAKyrF,aAAezrF,KAAKyrF,aAAesqC,EAAOC,SAASvsF,EAIpDzpC,KAAKyrF,aAAezrF,KAAK4qF,iBAC3Bp4C,EAAWxyC,KAAK4qF,gBAGhB5qF,KAAK81H,kBAAiB,KAEtBtjF,EAAWxyC,KAAKyrF,aAEhBzrF,KAAK81H,kBAAiB,IAIxBt1G,OAAOihB,YAAYiqD,oBAAoB1rF,KAAK8qF,gBAAiB,GAAGt4C,GAGhExyC,KAAK01H,kBAAkB11H,KAAKo1H,gBAAiB5iF,GAG7CxyC,KAAKo1H,gBAAgBpzG,MAAMhiB,KAAKk1H,aAAe1iF,EAAW,KAGpD,yBACN,IAAI8iF,EAAoB90G,OAAOihB,YAAYiqD,oBAAoB1rF,KAAK8qF,iBAChE6gC,EAAStuF,SAASi4F,GAAqB,GAAI,IAE/C,GAAsB,iBAAX3J,GAAkCU,MAAXV,EAChC,OAAOA,EAMH,kBAAkB/7F,EAAqBqmG,GAEzCrmG,IAAY/oB,OAAO,yCAAyC,GAC9D7G,KAAKw1H,0BAILx1H,KAAKk2H,cAActmG,EAAS,KAIxB,cAAcA,EAAqBumG,EAAoB,KAEzDvmG,IAAY5vB,KAAKkmD,gBAAgBkzC,QACnCvyF,OAAO+oB,GAASmL,YAAY,oBAAqBnL,EAAQm8D,YAAcoqC,GAInE,0BACN,IAAIC,EAAqBvvH,OAAO,wCAAwC,GACxE7G,KAAKk2H,cAAcE,GAGb,iBAAiBC,GACnBA,IAAoBr2H,KAAKy1H,QAAQllH,UAAUlF,SAAS,gBACrDrL,KAAKy1H,QAAQllH,UAAUC,IAAI,gBAGzB6lH,GAAmBr2H,KAAKy1H,QAAQllH,UAAUlF,SAAS,gBACtDrL,KAAKy1H,QAAQllH,UAAUkiB,OAAO,gB,sCAvKvBwiG,GAAkB,0D,uBAAlBA,EAAkB,8SAX3B,oBAGS,8BAAO,EAAAqB,cAAP,CAAmB,2BACV,EAAAC,gBADT,CAAmB,2BAEX,EAAAC,WAAA,MACjB,Q,KANS,yBAAuB,gC,wFCZpC,kGASO,MAAMC,UAAsC,IAEjD,YAAqB1tH,EACUgc,EACA1P,GAC7BvV,MAAMiJ,GAHa,KAAAA,WACU,KAAAgc,8BACA,KAAA1P,cAOf,KAAA67B,wBAA0B,IAKnC,KAAA9a,aAAsB,WAmBtB,KAAAmqC,gBAA2C,KAiBlC,KAAAtwB,YAAc,CAC5BuwB,UAAWxgE,KAAKU,KAAKU,EAAE,0CACvBmB,OAAQvC,KAAKU,KAAKU,EAAE,sCAjCf,IAAIma,EAA0Bq1F,GACnC,OAAO5wG,KAAK+kB,4BAA4B2xG,mBAAmBn7G,EAAMq1F,GAM5D,OAAOr1F,EAA0B6X,GACtC,OAAOpzB,KAAK+kB,4BAA4By8B,YAAYpuB,GAQtD,aACE,SAAUpzB,KAAKugE,iBAAmBvgE,KAAK0gE,uBAAyB1gE,KAAK22H,aAGvE,mBACE,SAAU32H,KAAKugE,kBAAmBvgE,KAAK22H,aAGzC,kBACE,OAAO32H,KAAKwC,SAAWxC,KAAKwC,OAAO6Q,aAAerT,KAAKugE,gBAAiBl7C,aAW1E,aACE,OAAOrlB,KAAKugE,iBAAmBvgE,KAAKqV,YAAY/B,GAAGtT,KAAKugE,kB,sCA1D/Ck2D,GAA6B,gC,yBAA7BA,EAA6B,QAA7BA,EAA6B,a,kCCR1C,0HAaO,MAAMG,UAA2C,IAO/C,aAAa5oH,EAAY0P,EAA4Be,EAAgB,OAAQF,EAA6B,QAO/G,MAAO,CAACb,EANW,YAAK1d,KAAK62H,wBAAwB7oH,EAAK0P,IACvDvd,KACC,YAAUH,KAAK82H,iBAAiBp5G,EAAMe,EAAQF,IAC9C,gBAME,iBAAiBb,EAA4Be,EAAeF,GAClE,OAAO+gB,IACLA,EAAOl7B,KAAK+wB,OAAO,OAAQzX,EAAMA,EAAK4tB,YAAc5tB,EAAKjX,MAElDzG,KACJ2e,KACAC,QACCH,EACA6gB,EAAOtxB,IACP,CACE0Q,KAAM4gB,EAAOl7B,KAEbmtD,QAAS,SAGTjzC,iBAAiB,EACjBC,aAAcA,EAEdy/F,gBAAgB,IAGnB79G,KAAK,YAAUH,KAAK+2H,aAAaz3F,MAIhC,aAAaA,GACnB,OAAOt3B,GACDA,aAAiB,IACZhI,KACJ2e,KACAja,IACC46B,EAAOzgB,SAASsP,OAAO6oG,eAAezxH,KACtC,CACEgsD,QAAS,aAMV,YAAGvpD,GAIP,wBAAwBgG,EAAY0P,GACzC,MAAMmgG,EAAW,IAAIC,SACfC,EAAW,CACf/7G,YAAa0b,EAAK1b,YAClBipC,SAAUvtB,EAAK4tB,YAAc5tB,EAAKjX,KAClCwwH,SAAUv5G,EAAKC,KACfu5G,YAAax5G,EAAK5K,MAUpB+qG,EAAS1oF,OACP,WACA1P,KAAKC,UAAUq4F,IAyBjB,OAtBe/9G,KACZ2e,KACAC,QACC,OACA5Q,EACA,CACE0Q,KAAMm/F,EACNv/F,iBAAiB,EACjBC,aAAc,SAGjBsO,YACApd,KAAM+4D,IACL,IAAIpkE,EAAO,IAAI05G,SAMf,OAJAz5G,EAAEC,KAAKkkE,EAAIr6C,OAAO4hD,cAAconD,YAAa,CAAChxH,EAAOxE,KACnDyC,EAAK+wB,OAAOxzB,EAAKwE,KAGZ,CAAE6H,IAAKw6D,EAAIr6C,OAAO4hD,cAAcxqE,KAAMnB,KAAMA,EAAMya,SAAU2pD,M,oCApG9DouD,I,yBAAAA,EAAkC,QAAlCA,EAAkC,Y,aAAlCA,I,4JCnCN7yG,EAAwB,IAAuBA,sBAI/C,MAAMqzG,EAUX,YAAmBruH,EACCiG,EACAqoH,EAAoB,IAFrB,KAAAtuH,WACC,KAAAiG,UACA,KAAAqoH,WAPpB,KAAAC,SAAyF,CACvF,IAAKt3H,KAAKu3H,gBAAgBzqH,KAAK9M,MAC/B,KAAMA,KAAKw3H,UAAU1qH,KAAK9M,OASrB,yBAAyBmZ,GAC9B9U,EAAEC,KAAKtE,KAAKgP,QAASzD,IAEnB,IAA0C,IAAtCvL,KAAKq3H,SAASj6G,QAAQ7R,EAAOrD,IAC/B,OAIF,MAAMyd,EAAWpa,EAAOoa,SAASzd,GAC3B4Q,EAAU9Y,KAAKs3H,SAAS3xG,GAG9B7M,WAASmU,KAAKjtB,KAAMmZ,EAAQ5N,KAUxB,gBAAgB4N,EAA+C5N,GAGrE,GAAIvL,KAAKy3H,qBAAqBt+G,EAAQ5N,GACpC,OAIF,IAAIpF,EAAQoF,EAAOqa,OAAO,GAG1B,GAAIzf,EAAO,CACT,IAAIyoE,EAAgB5uE,KAAK03H,qBAAqBnsH,GAC9CvL,KAAK23H,YAAYx+G,EAAQy1D,EAAezoE,IAUpC,UAAUgT,EAA+C5N,GAC/D,IAAIqjE,EAAgB5uE,KAAK03H,qBAAqBnsH,GAE9CvL,KAAK6B,SAASsX,EAAQy1D,EAAc,CAAErpE,KAAM,OAGtC,YAAY4T,EAAoCjS,EAAcf,GACpE,IAAIqsC,EAAWxyC,KAAK43H,iBAAiBzxH,EAAOe,IAAUf,EAElDqsC,GACFxyC,KAAK6B,SAASsX,EAAQjS,EAAOsrC,GAIzB,SAASr5B,EAA+CjS,EAAcf,GACxEgT,aAAkB,IACpBA,EAAOtX,SAASqF,EAAOf,GAEvBgT,EAAOjS,GAASf,EASZ,iBAAiBA,EAA0Be,GACjD,MAAc,WAAVA,EACKf,EAGLA,aAAiB,KAA+B,qBAAhBA,EAAMxB,OAAgC3E,KAAKy3E,YAAYogD,WAClF73H,KAAKkc,mBAAmB47G,aAAa,iBAAiB93H,KAAKy3E,YAAY88B,aADhF,EAaM,qBAAqBp7F,EAA+C5N,GAE1E,GAAIA,EAAOqa,OAAO3e,QAAU,EAC1B,OAAO,EAGT,MAAMhH,EAAUkZ,aAAkB,IAAuBA,EAAO1W,kBAAkB8I,EAAOrD,IAAMiR,EAAO5N,EAAOrD,IAE7G,IAAK,IAAI6U,EAAI,EAAGA,EAAIxR,EAAOqa,OAAO3e,OAAQ8V,IACxC,GAAIgH,EAAsB9jB,EAASsL,EAAOqa,OAAO7I,IAC/C,OAAO,EAIX,OAAO,EAWD,qBAAqBxR,GAC3B,MAAkB,mBAAdA,EAAOrD,GACF,UAIFqD,EAAOrD,IAvID,aAAd,c,0BAA0B,M,kCACZ,aAAd,c,0BAAiC,M,4ECepC,8DAGO,MAAM6vH,EAIX,YAAwCr8C,GAAA,KAAAA,kBAFvB,KAAAs8C,UAAmB,EAGlCh4H,KAAKg4H,SAAWt8C,EAAgBh9D,KAAKnO,UAAUlF,SAAS,sBAG1D,oBACE,OAAOrL,KAAKg4H,SAGP,YAAYC,EAA4BC,GAC7Cl4H,KAAKg4H,SAAWh4H,KAAKm4H,UAAUF,GAAkBj4H,KAAKm4H,UAAUD,GAG1D,UAAU9Q,GAChBA,GAAQA,K,sCAjBC2Q,GAAc,KAIL,O,yBAJTA,EAAc,QAAdA,EAAc,qBADD,U,kCCH1B,0Q,qBC5BA,gB,uCAIA,qBAGU,qFAAgD,0EAG1D,O,uBALU,sDAA+C,yC,sFAQzD,gBAGE,oBAES,yFAAoD,0EAI7D,OACF,O,uBARK,oDACM,qDAAsC,0C,sBAUjD,gBAEE,8BACF,QDwCO,MAAMK,UAAqC,IAyBhD,YAAqB13H,EACAqI,EACA0O,EACAijC,EACA93C,EACAy1H,EACA1tC,EACA7oD,EACAl+B,EACA/D,EACAW,EACDozG,GAClB9zG,QAZmB,KAAAY,OACA,KAAAqI,WACA,KAAA0O,SACA,KAAAijC,UACA,KAAA93C,aACA,KAAAy1H,gBACA,KAAA1tC,gBACA,KAAA7oD,iBACA,KAAAl+B,0BACA,KAAA/D,QACA,KAAAW,aACD,KAAAozG,SAlCpB,KAAAh8F,KAAO,CACL,mBAAsB5X,KAAKU,KAAKU,EAAE,0CAClC,wBAA2BpB,KAAKU,KAAKU,EAAE,gDACvC,gBAAmBpB,KAAKU,KAAKU,EAAE,uBAIjC,KAAAk3H,eAAwB,EAGxB,KAAAC,wBAAyB,EAGzB,KAAAn2F,WAAoB,EAGpB,KAAAo2F,mBAAqBx4H,KAAKq4H,cAAcI,YAG/B,KAAAC,qBAA2D,CAClElhG,oBAAoB,GAkBtB,WAEEx3B,KAAK6+G,iCAEL7+G,KAAK4C,WAAWiB,MAAM3D,UAAUC,KAC9BH,KAAKI,kBACLC,UAAWwD,IAEX7D,KAAK24H,yBAAyB90H,GAC9B7D,KAAKoiC,UAAoC,IAAxBv+B,EAAMC,QAAQm2C,MAC/Bj6C,KAAKH,MAAMS,kBAUbN,KAAK4zG,OAAOc,kBAAkB,KAC5BpnG,WAAW,KACT,MAAMsrH,EAAc54H,KAAKQ,WAAWsG,cAAc+S,cAAc,2BAC1Dg/G,EAAe74H,KAAKQ,WAAWsG,cAAc+S,cAAc,qBAI7D++G,GAAeA,EAAYE,iBAC7BF,EAAYE,gBAAgB9xF,eAAe,CAACE,MAAO,UAGjD2xF,GACFA,EAAa7xF,eAAe,CAACE,MAAO,WAErC,KAIG,iCACRlnC,KACG4C,WACAqD,YACA/F,UACAC,KAAK,YAAK,IACVE,UAAU,KACTL,KAAKu4H,wBAAyB,EAC9Bv4H,KAAKH,MAAMS,kBAIV,wBACL,OAAO,EAGC,yBAAyBuD,GACjC7D,KAAKs4H,gBAAkBt4H,KAAK2qF,cAAcxkC,UACxCnmD,KAAK4D,wBAAwBm1H,eAAel1H,KAAW,KAG3D,yBAAyBmE,GACnBA,EAAMyyC,QACRz6C,KAAKg5H,eAAehxH,EAAMkc,eAI9B,cAAclc,GACZhI,KAAKyX,OAAOswB,GACT/nC,KAAK06C,QAAgB1yC,EAAM2yC,iBAAmB3yC,EAAM2yC,eACrD,CAAEz2B,cAAelc,EAAMkc,cAAe3W,OAAO,IAQjD,6BAA6BvF,GACvBhI,KAAK2qF,cAAcxkC,SACrBnmD,KAAKg5H,eAAehxH,EAAMkc,eAE1BlkB,KAAKi5H,yBAAyBjxH,GAI1B,eAAekc,GACrBlkB,KAAKyX,OAAOswB,GACV,qBACA,CAAE7jB,cAAeA,K,sCA/HVk0G,GAA4B,qI,uBAA5BA,EAA4B,yGAN5B,CACT,CAAEzyE,QAAS,IAAgCC,SAAU,KACrD,IACA,MACD,w0BCnEH,sB,gBAIA,2BASA,sBAaA,uB,MAzBK,6DAGK,+DASL,sCAcA,gD,uuECCL,gP,yBClBE,QACE,wBAIF,Q,oBAJe,qCDgCV,MAAMszE,EAAoC,8BAM1C,MAAMC,UAA2C,IA0BtD,YAAsB34H,EACAqO,EACAqN,EACAk9G,EACA14H,EACAiC,EACAsZ,GACpBnc,QAPoB,KAAAU,aACA,KAAAqO,aACA,KAAAqN,qBACA,KAAAk9G,gBACA,KAAA14H,OACA,KAAAiC,SACA,KAAAsZ,uBArBf,KAAAo7B,SAAkB,EAClB,KAAAp+B,UAAmB,EAYlB,KAAAogH,WAAY,EAYpB,WACEr5H,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eAGvC9G,KAAKs5H,iBAAmBt5H,KAAK4G,SAASqD,KAAK,qBAC3CjK,KAAKi9F,eAAiBj9F,KAAK4G,SAASqD,KAAK,mBACzCjK,KAAKqhC,OAA0C,UAAjCrhC,KAAK4G,SAASqD,KAAK,UACjCjK,KAAK28F,WAAa38F,KAAK4G,SAASqD,KAAK,gBAAkB,OAGvD,MAAMzC,EAASxH,KAAK4G,SAASuH,KAAK,YAClCnO,KAAKud,SAAW/V,EAASxH,KAAKkc,mBAAmBm8D,kBAAkB7wE,GAAQ,QAAQkE,EAEnF1L,KAAKu5H,YAAcv5H,KAAK4G,SAASI,QAAQ,QACzChH,KAAKw5H,gBAAkBx5H,KAAKu5H,YAAY/tH,KAAKxL,KAAKs5H,kBAClDt5H,KAAKw5H,gBACFtS,WAAW,YACX/5G,OACHnN,KAAKy5H,eAAiBz5H,KAAKw5H,gBAAgB53H,MAE3C5B,KAAK05H,oBAAsB15H,KAAKu5H,YAAY/tH,KAAK,uBACjDxL,KAAKovB,QAAU,CAAE7R,SAAUvd,KAAKud,SAAU0/E,eAAgBj9F,KAAKi9F,gBAC1Dj9F,KAAKqhC,SACRrhC,KAAKovB,QAAgB,OAAI,QAI7B,cACEtvB,MAAM4Y,cACN1Y,KAAKu5H,YAAYpvF,IAAI,mBAGhB,aACL3pB,OAAOihB,YAAY+jF,eAAgB,EAG9B,MAAMhlF,GA8BX,OA3BAxgC,KAAK4G,SAASuH,KAAK,SAAUqyB,GAEzBxgC,KAAKud,UAAYvd,KAAKud,SAASmuB,cACjC1rC,KAAK25H,6BAA6Bn5F,GAClCxgC,KAAK45H,6BAA6Bp5F,IAIpCxgC,KAAKu5H,YAAY3vH,GAAG,kCAAmC,KACrD,IACE5J,KAAKw5H,gBAAgB53H,IAAI5B,KAAK65H,iBAAiBC,cAC/C,MAAOxtH,GAKP,OAJAsR,QAAQoB,MAAM,6CAA6C1S,MAC3DtM,KAAKo5H,cAAcr/D,SAASztD,GAAKtM,KAAKU,KAAKU,EAAE,uBAGtC,EAMT,OAHApB,KAAK+5H,gCAGE,IAGT/5H,KAAKg6H,WAEEx5F,EAGD,6BAA6BA,GACnCA,EAAOy5F,MAAMrwH,GAAG,sBAAuB,KACrC5J,KAAK2C,OAAOopC,YAAY/rC,KAAKud,UAAYvZ,SAAShE,KAAKud,YAInD,6BAA6BijB,GACnCxgC,KAAK0rC,YAAcrnC,EAAE6iB,MAAMlnB,KAAKud,SAAUmuB,YAAYlnC,UAEtDxE,KAAK2C,OAAOopC,YAAY/rC,KAAKud,UAAYkP,WACtCtsB,KACC,YAAU,YAAmBH,OAC7B,YAAOud,KAAcA,IACrBld,UAAUkd,IACZ,IAII28G,EAJqB71H,EAAEw7D,aAAa7/D,KAAK0rC,YAC3CnuB,EAAUmuB,YAAYlnC,SACrB2mC,GAA2BA,EAAWjjC,IAEJgH,IAAIi8B,GAAcA,EAAWgvF,iBAAiBx1H,OAE/Eu1H,EAAYjzH,QACdu5B,EAAOy5F,MAAMG,KAAK,wBAAyBF,GAG7Cl6H,KAAK0rC,YAAcrnC,EAAE6iB,MAAM3J,EAAUmuB,YAAYlnC,YAI7C,WACN,IAAI61H,EAAar6H,KAAKs5H,iBAAiBgB,UAAU,GAC7Ch4F,EAAQz7B,OAAO,aAAawzH,MAE5BE,EAAYv6H,KAAK4G,SAAS4E,KAAK,eAEnC+uH,EAAUtwH,KAAK,aAAc,MAC7BswH,EAAUtwH,KAAK,kBAAmBowH,GAElC/3F,EAAMl2B,MAAM,KACVmuH,EAAUhtH,UAIN,+BACN,IAAKvN,KAAKud,WAAavd,KAAKud,SAASmuB,aAAe1rC,KAAKud,SAASrV,GAChE,OAGF,MAUMsyH,EAVWx6H,KAAK05H,oBAAoBluH,KAAK,sBAAwB0D,IAAI,CAAC+hB,EAAOiU,KACjF,IAAIyzB,GAASzzB,EAAMlC,aAAa,SAAW,IAAI21B,MAAM,uCAErD,OAAIA,EACKt7B,SAASs7B,EAAM,IAEf,IAIsB8hE,UAAUtgG,OAAOhR,OAAS,EAE3D,IAAIuxG,EAAmB16H,KAAKud,SAASmuB,YAAYlnC,UAAY,GAE7DqC,OAAOvC,KAAKo2H,EAAkB,CAACzpG,EAAcka,KAC3CnrC,KAAK05H,oBAAoBvkG,OAAO,0CAA0CqlG,EAAWvpG,EAAQ,kBAAkBka,EAAWjjC,W,sCAvKnHixH,GAAkC,wE,uBAAlCA,EAAkC,oE,OAAA,K,KAqBlC,KAAqB,G,0TCtElC,QACE,gBACE,wBAGa,yCAAiB,EAAAwB,MAAA,KAAjB,CAA+B,qCACZ,EAAAC,gBAChC,OACF,OAEA,+BAMF,Q,MAdiB,kCAAmB,2BAAnB,CAAmB,6BAQpB,0D,gICqBT,MAAM3hD,EADb,cAEU,KAAA/sD,MAAmC,GAEpC,SAAShkB,EAAW6E,GACpBA,IAIA/M,KAAKksB,MAAMhkB,KACdlI,KAAKksB,MAAMhkB,GAAM,IAGnBlI,KAAKksB,MAAMhkB,GAAIhH,KAAK6L,IAGf,KAAK7E,KAAcgW,GACxB,IAAIpa,EAAU,GAEd,GAAI9D,KAAKksB,MAAMhkB,GACb,IAAK,IAAIuhC,EAAI,EAAGA,EAAIzpC,KAAKksB,MAAMhkB,GAAIjB,OAAQwiC,IAAK,CAC9C,IAAInK,EAASt/B,KAAKksB,MAAMhkB,GAAIuhC,MAAMvrB,GAE9BohB,GACFx7B,EAAQ5C,KAAKo+B,GAKnB,OAAOx7B,G,sCA5BEm1E,I,yBAAAA,EAAW,QAAXA,EAAW,a,kCCCxB,8G,yBCXI,cAA2C,S,mCAAxC,0CAAwC,0B,yBAG3C,gBAAmE,QAAe,Q,mCAA7E,4BAA8D,sBDchE,MAAM4hD,UAA0C,K,oCAA1CA,I,uBAAAA,EAAiC,ieCtC9C,wBACW,sDAAmB,6BAcT,EAAAC,YAAA,KAdV,CAAmB,0BAeX,EAAAC,WAfR,CAAmB,2BAgBV,EAAAC,WAhBT,CAAmB,8BAiBR,EAAAC,WAAA,MAEpB,8BAGA,8BAGF,Q,KAzBW,wBAAmB,0BAAnB,CAAmB,oBAAnB,CAAmB,yBAAnB,CAAmB,mBAAnB,CAAmB,sBAAnB,CAAmB,wBAAnB,CAAmB,sBAAnB,CAAmB,wBAAnB,CAAmB,sBAAnB,CAAmB,sBAAnB,CAAmB,sBAAnB,CAAmB,8BAAnB,CAAmB,Y,4EDqCjBJ,I,kCETb,sI,wBC7BA,2B,oBAAgB,mC,yBAGhB,gBACE,gBACE,gBACE,eACF,OACF,OAEA,wCACF,Q,oBALgD,sCAIjB,2CD6BxB,MAAMK,UAAwC,IAKnD,YAA4Bx6H,EACA+W,EACAhU,GAC1B3D,QAH0B,KAAAY,OACA,KAAA+W,SACA,KAAAhU,eAJrB,KAAAmiE,QAAU5lE,KAAKU,KAAKU,EAAE,4BAO3BpB,KAAKkkB,cAAgBlkB,KAAKyX,OAAOyG,OAAOgG,cAExClkB,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKkkB,eACR4B,mBACA3lB,KACCH,KAAKI,kBAENC,UAAWsF,GAAO3F,KAAKgJ,YAAcrD,I,sCApB/Bu1H,GAA+B,2C,uBAA/BA,EAA+B,2UCvC5C,iCAGA,uB,MAFgB,2BAEc,qC,8EC0B9B,8DAGO,MAAeC,EAAtB,cAEY,KAAAC,uBAAyB,IAIzB,KAAAv1H,MAAgD,CACxDqC,GAAI,KACJ4I,MAAO,eAYF,QAAQ9H,EAAiCkoD,GAAgB,GAC9D,MAAMhpD,EAAKc,EAAYd,GACjB4I,EAAQ9Q,KAAK6F,MAAMiL,MAQzB,OALIogD,GAASlxD,KAAK6F,MAAMqC,KAAOA,IAC7B4I,EAAMzL,QAIJrF,KAAKq7H,SAASnzH,GACTqH,QAAQC,QAAQsB,EAAM3K,QAI/BnG,KAAK6F,MAAMqC,GAAKA,EAChBlI,KAAK6F,MAAMiL,MAAM0zD,yBAAyB,IAAMxkE,KAAKggC,KAAKh3B,IAEnDhJ,KAAK6F,MAAMiL,MACf5Q,UACAC,KAAK,YAAK,IACV0sB,aAGE,MAAM3I,GACPlkB,KAAK6F,MAAMqC,KAAOgc,GACpBlkB,KAAK6F,MAAMiL,MAAMzL,QASd,SAAS6e,GACd,MAAMpT,EAAQ9Q,KAAK6F,MAAMiL,MACzB,OAAO9Q,KAAK6F,MAAMqC,KAAOgc,GAAiBpT,EAAMxO,aAAewO,EAAMg2D,iBAA+C,IAA9B9mE,KAAKo7H,2B,kCCzF/F,0H,wBCiCgB,oB,mCACQ,mCAAgC,UAAhC,CAAgC,6B,wBA2BtC,oB,sDACQ,2BAA2B,aAA3B,CAA2B,gC,uCAd7C,iBACE,gBACE,mBAGE,QACF,OACA,gBACE,iBACE,oBAEE,wGAEA,0BAIF,OACF,OACF,OACF,OACF,O,sCAlBM,kDAEA,uCAKI,iDAGQ,+C,uCA5CtB,QACE,qBACE,mBAGA,eAEA,gBACE,gBACE,iBAEE,oBAGI,6EAEF,0BAIF,OACF,OACF,OACF,OACF,OAEA,qBACE,oBAGA,gBACA,wBAsBF,OACF,O,uBAnDY,8CAEL,oDAQO,2DAGM,8CAYR,gDAEL,sDACoB,2CDpCxB,MAAME,EAuCX,YAAqBvyH,EACArI,EACAE,EACAiC,GAHA,KAAAkG,WACA,KAAArI,OACA,KAAAE,kBACA,KAAAiC,iBAxCd,KAAAmnC,iBAA0B,EAU1B,KAAAuxF,oBAA0C,CAAC,UAAW,KAEtD,KAAA3jH,KAAO,CACZ0K,MAAOtiB,KAAKU,KAAKU,EAAE,4BACnBo6H,kBAAmBx7H,KAAKU,KAAKU,EAAE,gCAC/Bq6H,uBAAwBz7H,KAAKU,KAAKU,EAAE,2DACpCs6H,KAAM,CACJz7C,MAAOjgF,KAAKU,KAAKU,EAAE,uBACnBY,YAAahC,KAAKU,KAAKU,EAAE,iCACzBymB,KAAM7nB,KAAKU,KAAKU,EAAE,0BAClBu6H,MAAO37H,KAAKU,KAAKU,EAAE,2BACnB85E,OAAQl7E,KAAKU,KAAKU,EAAE,4BACpBw6H,SAAU57H,KAAKU,KAAKU,EAAE,8BACtBy6H,MAAO77H,KAAKU,KAAKU,EAAE,2BACnB06H,KAAM97H,KAAKU,KAAKU,EAAE,2BAEpBm+E,OAAQ,CACNj9D,MAAOtiB,KAAKU,KAAKU,EAAE,6BACnBY,YAAahC,KAAKU,KAAKU,EAAE,mCACzBq+F,IAAKz/F,KAAKU,KAAKU,EAAE,2BACjBqvF,KAAMzwF,KAAKU,KAAKU,EAAE,qCAClB01E,KAAM92E,KAAKU,KAAKU,EAAE,4BAClB21E,MAAO/2E,KAAKU,KAAKU,EAAE,6BACnBm/E,SAAUvgF,KAAKU,KAAKU,EAAE,kCAUnB,SACLpB,KAAKY,gBAAgB4T,OAAO,OAAD,wBACtBxU,KAAKY,gBAAgBX,SAAO,CAC/BskB,QAASvkB,KAAKgqC,gBACdu1C,OAAQv/E,KAAKu/E,OACbh5D,UAAWvmB,KAAKumB,aAIb,aAAa5kB,EAA0BwE,GAC9B,KAAVA,IACFA,EAAQ,MAGVnG,KAAKu/E,OAAO59E,GAAOwE,EAGrB,WACEnG,KAAKgqC,gBAAkBhqC,KAAKY,gBAAgBY,UAG5CxB,KAAKumB,UAAYvmB,KAAKY,gBAAgB2lB,UAGtC,MAAMg5D,EAASv/E,KAAKY,gBAAgB2+E,OACpCv/E,KAAKu/E,OAASl7E,EAAE6iB,MAAMq4D,GACtBv/E,KAAK+7H,gBAAkBjsH,OAAOD,KAAK7P,KAAKu/E,QAGxC,MAAMo6B,EAAmB35G,KAAK6C,eAC3Bm5H,mBACA7hG,KAAK,CAACjX,EAAeC,IAAkBD,EAAEzc,KAAKi+B,cAAcvhB,EAAE1c,OAEjEzG,KAAK44D,oBAAsB,CAAC,CAAE1wD,GAAI,GAAIzB,KAAMzG,KAAK4X,KAAK2nE,OAAOkR,OAAQpnE,OAAOswF,I,sCA9EnE2hB,GAAgC,0C,uBAAhCA,EAAgC,i0BCZ7C,cACE,iBACE,gBACE,kBAGA,gBACE,gBACE,kBACO,yEADP,OAKF,OACF,OACA,cACF,OACA,gCAuDF,OACF,Q,MArEa,qDAMI,0CAKyB,0DAExB,yC,8FCjBlB,kCAEO,MAAMW,EAAkC,IAF/C,UAEmD,GAAoB,oC,+aCArE,gBAEE,wBAIF,Q,oBAJe,qDAAsC,gCAAtC,CAAsC,yC,qBAsBnD,e,uCAhBF,QACE,2BAWgB,uFAA2B,sDACPtzC,iBAAA,WACpC,OAEA,qBAEF,O,qCAjBkB,8BAAkB,kCAAlB,CAAkB,sCAAlB,CAAkB,oCAAlB,CAAkB,sCAAlB,CAAkB,8BAAlB,CAAkB,4BAAlB,CAAkB,mCAClB,oCAA0C,4BAA1C,CAA0C,uDActD,uC,yBAKR,cACE,wBACF,Q,oBADc,6CAA8B,6CCmBrC,MAAMuzC,UAAqC,IAgDhD,YAAqBt5H,EACAD,EACAoG,EACA0O,EACA/W,EACAkvC,EACAC,EACAhD,EACA1gB,EACAxoB,EACA4xF,EACA11F,EACAgP,EACA0gC,EACA4sF,EACA77E,EACA87E,EACAzxC,GACnB7qF,QAlBmB,KAAA8C,aACA,KAAAD,SACA,KAAAoG,WACA,KAAA0O,SACA,KAAA/W,OACA,KAAAkvC,WACA,KAAAC,iBACA,KAAAhD,sBACA,KAAA1gB,YACA,KAAAxoB,uBACA,KAAA4xF,gBACA,KAAA11F,QACA,KAAAgP,aACA,KAAA0gC,mBACA,KAAA4sF,cACA,KAAA77E,WACA,KAAA87E,eACA,KAAAzxC,gBA5DL,KAAAtC,kBAA2B,EAC3B,KAAAD,gBAAyB,EACzB,KAAAI,YAAkC,WAElC,KAAA6zC,gBAAyB,EAEzB,KAAAC,qBAA8B,EAE9B,KAAA7zC,gBAAyB,EAKxB,KAAA3nC,QAAU,IAAI,IACrB,KAAAi2C,iBAAmB,IAAI,IACvB,KAAAH,YAAc,IAAI,IAClB,KAAAjO,iBAAmB,IAAI,IAE1B,KAAAllE,YAAc,IAAuBG,uBAAuB,eAE5D,KAAA24G,eAAwB,EAExB,KAAA3kH,KAAO,CACZkqC,WAAY9hD,KAAKU,KAAKU,EAAE,4BACxBo7H,WAAYx8H,KAAKU,KAAKU,EAAE,mBACxBghC,UAAW,CACT9f,MAAOtiB,KAAKU,KAAKU,EAAE,qCACnBY,YAAahC,KAAKU,KAAKU,EAAE,6CAKtB,KAAA2uC,QAAS,EACT,KAAAC,cAAe,EACf,KAAAysF,aAAc,EACd,KAAAtrF,eAAiBnxC,KAAK6vC,eAAeqB,wBAGrC,KAAAwrF,iBAAmB,CACxBxiH,SAAU,IAAMla,KAAK28H,kBAAiB,GACtCC,aAAej3H,GAA2B3F,KAAKo8H,aAAa96E,sBAAsB37C,EAAI,IAwBxF,WACE3F,KAAKmwC,2BAGLnwC,KAAK2D,qBACFqU,aAAa,YAAmBhY,OAChCK,UAAU,KACTL,KAAK+vC,OAAS/vC,KAAK6vC,eAAeE,OAClC/vC,KAAKgwC,aAAehwC,KAAK6vC,eAAeG,aACxChwC,KAAKH,MAAMS,kBAIfN,KAAKmsB,UACF+uC,YAAY,eACZ/6D,KACC,YAAIg7D,GAAUA,EAAO5vD,OAAOvD,GAA6B,YAApBA,EAAMwlC,YAC3C,YAAO2tB,IACL,MAAM7I,EAAiBtyD,KAAK6V,aAAa3G,IAAI+C,GAAMA,EAAG/J,GAAIma,YAC1D,QAAS84C,EAAO3vD,KAAKxD,IAAsC,IAA7BsqD,EAAMl1C,QAAQpV,EAAME,QAEpD7H,UAAU,KACZL,KAAK6V,aAAe7V,KAAKm8H,YAAYtmC,sBACrC71F,KAAKH,MAAMS,kBAGbN,KAAK4C,WAAWkB,QACb5D,UACAC,KACC,YAAeH,KAAK4C,WAAWiB,MAAM3D,WACrCF,KAAKI,kBACLC,UAAU,EAAEyD,EAASD,MACvB7D,KAAK6D,MAAQA,EACb7D,KAAK6V,aAAe7V,KAAKm8H,YAAYtmC,sBACrC71F,KAAKsgD,SAASu8E,0BAA0B78H,KAAK6V,cAC7C7V,KAAKu8H,cAA6C,IAA7Bv8H,KAAK6V,aAAa5O,OACvCjH,KAAKH,MAAMS,kBAIf,kBACEN,KAAKo8H,aAAa3mD,KAAKz1E,MAGlBA,KAAK2qF,cAAcxkC,UACtBnmD,KAAKo8H,aAAaU,sBAIpB,IAAIC,EAAW/8H,KAAK+I,SAASrE,IAAS,IAA6B,KAC/Dq4H,aAAoB,IACtBA,EAASnjC,SAAS55F,MAElB,IAAI+8H,EAAS/8H,KAAK+I,UAAU6wF,SAAS55F,MAEvCA,KAAKuvC,iBAAiBuoD,0BAA0B,IACvC93F,KAAKsgD,SAAS0yD,eAEvBhzG,KAAKuvC,iBAAiBwoD,8BAGxB,cACEj4F,MAAM4Y,cACN1Y,KAAKo8H,aAAal+F,UAGpB,mBACE,OAAOl+B,KAAKo8H,aAAavmH,aAG3B,iBAAwBA,GACtB7V,KAAKo8H,aAAavmH,aAAeA,EAG5B,iBAAiBmB,GACtBhX,KAAKy8H,YAAczlH,EACnBhX,KAAKH,MAAMS,gBAGN,aACLN,KAAKo8H,aAAaI,aAGb,WAAW72H,GAChB3F,KAAKo8H,aAAat6E,WAAWn8C,GAGzB,YAAYA,G,yDACV3F,KAAKo8H,aAAaY,YAAYr3H,MAG/B,UACL,IAAI8b,EAAU,sBAId,OAHAA,GAAW,IAAMzhB,KAAKwoF,YACtB/mE,GAAWzhB,KAAKyoF,eAAiB,WAAa,GAEvChnE,EAOD,2BACNzhB,KAAK4vC,SACFa,mBACAtwC,KACCH,KAAKI,kBAENC,UAAiBsF,GAA2B,4CAC3C3F,KAAKg9H,YAAYr3H,Q,sCAnLZu2H,GAA4B,iM,uBAA5BA,EAA4B,qD,OAAA,K,ooCDnDzC,kBAEE,sBAQA,gCAmBF,OAEA,uB,MA9BK,4BACE,mCAQS,uCAAoD,8BAqB/D,8D,y7CEHL,kDAEO,MAAMe,UAA4C,IAWhD,iBACL,OAAIj9H,KAAK2E,MACA3E,KAAK8tE,QAAQr+D,KAAMk0B,GAAoB3jC,KAAKwE,SAAWm/B,EAAWn/B,UAElE+K,QAAQC,a,kCChBrB,sR,wBrEzBM,yB,oBAEa,+C,yBAeT,gBAGE,yBAKF,Q,wCANI,mCACW,gDAA4C,4BAA5C,CAA4C,gCAA5C,CAA4C,gC,yBAJ7D,QACE,sBASF,Q,yBARM,wC,yBALR,gBAGE,gCAWF,Q,oBAXgB,mDqEyCf,MAAM0tH,UAAqC,IAdlD,c,oBAeE,KAAA7e,wBAA6D,CAC3D,CACE5vG,UAAW,IACX0uH,OAAQ,CACNC,WAAY,YAAG,sCACfnlH,QAAS,CAAC,qCAGd,CACExJ,UAAW,KAEb,CACEA,UAAW,IACXu5E,iBAAkB,qBAEpB,CACEv5E,UAAW,IACX1N,KAAM,OACMf,KAAK65D,eAAgB75D,KAAK65D,aAAa30D,UAGrD,CACEuJ,UAAW,IACXu5E,iBAAkB,qBAEpB,CACEv5E,UAAW,IACXu5E,iBAAkB,iCAEpB,CACEv5E,UAAW,IACXu5E,iBAAkB,qBAEpB,CACEv5E,UAAW,MAIf,WACE3O,MAAMqkB,WACNnkB,KAAK4X,KAAKylH,gBAAkBr9H,KAAKU,KAAKU,EAAE,sBAGhC,wBACR,OAAIpB,KAAKY,gBAAgBY,UAChBxB,KAAK4C,WAAWk6D,iBAAiB38D,KAAK,YAAK,IAAI0sB,YAE/C7sB,KAAK4C,WAAW0C,cAAcs0C,gBAI/B,wBACR,MAAoC,mCAA7B55C,KAAKyX,OAAOxX,QAAQwG,M,oCArDlBy2H,I,uBAAAA,EAA4B,4CAN5B,CAET,CAAEv3E,QAAS,IAAgCC,SAAU,KACrD,MACD,2hCrE3DH,gBAEE,gBACE,gBACE,8BAKA,mCAGwB,kCAAU,EAAAi6D,uBAAA,KAAV,CAAyC,mCACxB,EAAAV,gBAAgB,OAEzD,OAEA,qBAeF,OACF,OAEA,gBACE,wBAKF,OAEA,gBAEE,gBAMA,kBAEF,OACF,Q,MArDM,mCAGa,0CAKW,sCAAuB,6BAAvB,CAAuB,4CAAvB,CAAuB,kCAS3C,mCAkBO,0EAA2D,sDAA3D,CAA2D,wDAA3D,CAA2D,mC,63FqEyB/D+d,I,kCChCb,8MAiBO,MAAMI,EAUX,YAA+B5uH,EACwCmhC,EACjDpsC,EACAoN,EACAg8B,EACA1gB,EACAgsB,EACAv1C,EACSlC,GARA,KAAAgO,SACwC,KAAAmhC,iBACjD,KAAApsC,eACA,KAAAoN,cACA,KAAAg8B,sBACA,KAAA1gB,YACA,KAAAgsB,kBACA,KAAAv1C,aACS,KAAAlC,OAhBxB,KAAA6H,YAAa,EAEb,KAAAiqD,aAAexyD,KAAKu9H,oBAEpB,KAAA3lH,KAAO,CACZu1B,MAAOntC,KAAKU,KAAKU,EAAE,8BAcd,cACL,GAAIiD,EAAEilB,MAAMtpB,KAAKqtC,cACf,OAGF,MAAMmwF,EAAgBx9H,KAAKqtC,aAC3BrtC,KAAKuI,YAAa,EAElBvI,KAAK6vC,eAAer/B,IAAIxQ,KAAKgJ,YAAaw0H,GACvC/tH,KAAK,KACJzP,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKgJ,aACRw0B,UAEHx9B,KAAKmsB,UAAUjrB,KAAKlB,KAAKgJ,YAAa,CACpCwkC,UAAW,cACXC,mBAAoB+vF,EACpBpnG,aAAcp2B,KAAKo2B,eAGrBp2B,KAAKuI,YAAa,EAClBvI,KAAK6vC,eAAe4wB,+BAA+Br4D,KAAKo1H,GACxDx9H,KAAKqa,WAENG,MAAOozB,IACN5tC,KAAK6sC,oBAAoBgB,eAAeD,EAAK5tC,KAAKgJ,aAClDhJ,KAAKuI,YAAa,EAClBvI,KAAKqa,WAIJ,WAAWrR,GACZA,IACFhJ,KAAKqtC,aAAerkC,EAAYd,GAChClI,KAAKy9H,eAIT,mBACE,OAAOz9H,KAAK6vC,eAAezZ,aAG7B,kBACE,OAAOp2B,KAAK6vC,eAAe0wB,gBAGtB,SACLvgE,KAAK0O,OAAO4hC,WAGN,oBACN,MAAMzsC,EAAQ7D,KAAK4C,WAAWiB,MAAMsC,MAEpC,IAAKtC,EACH,MAAO,GAGT,MAAMopC,EAAgB,IAAiB8lC,gBAAe,GACtD,IAAI/jE,EAAUnL,EAAMmL,QAAQzD,OAAOA,IACjC,IAAIrD,EAAKlI,KAAKm4C,gBAAgBulF,6BAA6BnyH,GAC3D,OAAsC,IAA/B0hC,EAAc7vB,QAAQlV,KAG/B,OAAOlI,KAAKm4C,gBAAgBwlF,kBAAkB3uH,I,sCAtFrCsuH,GAAoC,eAW3B,KAA8B,wE,uBAXvCA,EAAoC,+iBC9CjD,gBAEE,gBACE,gBACE,sCAEI,sCAAc,EAAAjsD,WAAA,MAIlB,OACF,OACA,gBACE,mCAEI,kCAAW,EAAAh3D,YAEb,oBACF,OACF,OACF,OACF,Q,MAhBU,0CAA2B,mCAA3B,CAA2B,sCAYO,0C,gICerC,MAAMujH,EAUX,cALQ,KAAAjqH,OAAsC,CAC5C,KAAQ,OACR,QAAW,QAcN,KAA4BnP,EAAcsO,GAC/C,GAAwB,IAApBtO,EAASyC,OACX,OAAOzC,EAGT,MAAMq5H,EAAU/qH,GAAQtO,EAAS,GAAG2D,MACpC,IAAK01H,EACH,OAAOr5H,EAGT,MAAMwyB,EAAWh3B,KAAK89H,gBAAgBD,GACtC,OAAI7mG,EACK3yB,EAAEY,OAAUT,EAAUo5E,GAAKA,EAAE5mD,GAAUyN,eAEvCjgC,EAaJ,gBAAgBsO,GAMrB,OAJAA,EAAOA,EACJ2xB,cACA5jB,QAAQ,QAAS,IAEb7gB,KAAK2T,OAAOb,GAGd,mBAAmBA,GACxB,YAAsCpH,IAA/B1L,KAAK89H,gBAAgBhrH,I,sCA1DnB8qH,I,yBAAAA,EAAyB,QAAzBA,EAAyB,qBADZ,U,kCC1B1B,8DAaO,MAAMG,UAAe,IAA5B,c,oBACE,KAAAt3H,KAAO,YAGP,KAAAia,SAA4C,cAG5C,KAAA7K,aAAe,cAGf,KAAAmoH,MAAQ,cAGR,KAAAv5H,QAAU,cAGV,KAAA0Y,MAAQ,cAGR,KAAAq3C,SAAW,cAGX,KAAA3R,YAAiD,cAGjD,KAAAyR,SAAW,cAGX,KAAApzC,MAAQ,cAGR,KAAApc,QAAU,IAAIm5H,EAGd,KAAAn2F,QAAU,IAAIo2F,EAGd,KAAAjxE,WAAsD,GAEtD,QAAW7G,GACT,IAAIt1C,EAAS9Q,KAAaomD,IAAcpmD,KAAKitD,WAAW7G,GAMxD,OAJKt1C,IACHA,EAAQ9Q,KAAKitD,WAAW7G,GAAa,eAGhCt1C,EAGT,YAAiDyM,GAC/C,MAAM6oC,EAAY/hD,EAAE85H,UAAU5gH,EAASpV,OAAS,IAChD,IAAI2I,EAAQ9Q,KAAKm1D,QAAW/O,GAE5B,OAAOt1C,GAASA,EAAMpM,IAAI6Y,EAASrV,IAG9B,IAAIzB,EAAaqK,GACtB9Q,KAAKitD,WAAWxmD,GAAQqK,GAIrB,MAAMotH,EAAb,cAEE,KAAAp5H,QAAU,IAAI,KAGT,MAAMm5H,EAAb,cAEE,KAAAl5H,QAAU,cAGV,KAAAE,OAAS,cAGT,KAAAC,QAAU,cAGV,KAAA8J,QAAU,cAGV,KAAA7J,sBAAwB,iB,sHChGnB,MAAMi5H,EAAgC,mBAYtC,MAAMC,EACX,WACEnzH,SAASC,eAAe,qBAAsBgrB,QAAS,G,sCAF9CkoG,I,uBAAAA,EAAqB,4ze,sOCoG3B,MAAMC,UAAgC,IAA7C,c,oBAmBW,KAAAnyF,oBAAqB,EAK9B,kBAEE,OADmBnsC,KAAa8b,UACf5M,IAAK+C,GAA2BA,EAAG/J,IAM/C,gBAAgBq2H,EAAyB,IAI9C,MAAO,GAHMv+H,KAAK8S,KAAU9S,KAAK8S,KAAKrM,KAAb,KAAwB,KACjCzG,KAAKi5F,cAAcslC,KAQ9B,cAAcA,EAAyB,IAC5C,MAAMr2H,EAAKlI,KAAKmC,MAAQ,GAAK,MAAMnC,KAAKkI,MAGxC,MAAO,GAFS7D,EAAEm6H,SAASx+H,KAAKopE,QAAS,CAACniE,OAAQs3H,MAE9Br2H,IAGtB,aACE,IAAI+D,EAAWjM,KAAKyF,OAAOwG,SAC3B,QAASA,GAAYA,EAAShF,OAAS,GAGlC,cACL,OAAKjH,KAAKmC,MAGDrC,MAAM6pE,cAFN3pE,KAAKyD,aAAamC,cAAcsC,GAAGlI,KAAKkI,IAAKsT,KAMjD,iBAAiBpU,GACtB,MAAqB,gBAAdA,EAA8B,OAAS,cAGzC,WAAWq3H,G,MAChB,OAA8B,QAAvB,EAAAA,EAAiB/vH,cAAM,eAAEjJ,OAAOuF,KAAKkzC,MAAM34C,QAASvF,KAAKyF,OAAOuF,KAAKkzC,MAAM34C,KAU7E,yBAAyBm5H,GAC9B,MAAMvmD,EAAiD,GAEvDumD,EAAch5H,QAAQe,IACpB,MAAMk4H,EAAS3+H,KAAKyG,GACpB0xE,EAAU1xE,GAAQk4H,EAASA,EAAOriC,UAAY/sF,QAAQsuB,YAAOnyB,KAG/D,MAAMu5B,EAAU11B,QAAQu0B,IAAIz/B,EAAEuhB,OAAOuyD,IAKrC,OAJAlzC,EAAQx1B,KAAK,KACXzP,KAAK4+H,eAAe/sE,MAAM7xD,KAAKkI,MAG1B+8B,EAGF,YAAYz9B,GACjB1H,MAAM2H,YAAYD,GAElB,IAAIkkC,EAAkB1rC,KAAK0rC,aAAe,CAACve,QAAS,GAAI3oB,SAAU,IAClExE,KAAK0rC,YAAc,IAAI,IACrB1rC,KAAK+I,SAEL1E,EAAEK,IAAIgnC,EAAa,UAAWA,IAC9B,EACA1rC,KAAKoiD,eACL,eAOG,gBACL,OAAO/9C,EAAEy+C,QAAQhjD,MAAMijD,gBAAiB,UAM1C,YACE,OAAO/iD,KAAK2C,OAAOkT,aAAanR,IAAI1E,KAAKkI,IAMpC,KAAKsqC,GAQV,OAPAxyC,KAAKkwB,WAAW7qB,MAAMmtC,EAAStqC,IAG3BsqC,EAAS9jC,QACX1O,KAAKyD,aAAamC,cAAcsC,GAAGsqC,EAAS9jC,QAAQ8uB,UAG/Cx9B,KAAKyD,aAAamC,cAAcC,MAAMC,kBAAkB0sC,IA1HlD,aAAd,c,0BAAmB,M,2BACL,aAAd,c,0BAAqB,M,6BACP,aAAd,c,0BAAyB,M,iCACX,aAAd,c,0BAA2B,M,mCACb,aAAd,c,0BAAmC,M,2CACrB,aAAd,c,0BAA6C,M,qDAC/B,aAAd,c,0BAAyB,M,iCACX,aAAd,c,0BAA2B,M,mCAuHvB,MAAMqsF,EAAsB,YAAWP,I,kCC9N9C,kJ,+ECPI,gBACE,eACE,eACI,uDAAiB,UACnB,cAEF,OACA,eACI,uDAAiB,aACnB,cAEF,OACF,OACF,O,uBAXQ,iDAEU,uCAGV,oDAEU,2C,yBAOlB,cAA2C,S,mCAAxC,0CAAwC,0B,yBAG3C,iBAAmE,QAAe,Q,mCAA7E,4BAA8D,sBDShE,MAAMQ,UAAmD,IAG9D,YAAqBp+H,EACAb,EACA6X,EACA7I,GACnB/O,MAAMY,EAAMb,EAAO6X,EAAgB7I,GAJhB,KAAAnO,OACA,KAAAb,QACA,KAAA6X,iBACA,KAAA7I,aALX,KAAAkwH,WAAa,IAAI,IAYpB,KAAA58F,SAAkB,EAClB,KAAAnrB,KAA6C,MALlDhX,KAAK4X,KAAU,IAAI5X,KAAKU,KAAKU,EAAE,gBAC/BpB,KAAK4X,KAAa,OAAI5X,KAAKU,KAAKU,EAAE,mBAM7B,QAAQ+E,GACTA,IAAUnG,KAAKgX,MACjBhX,KAAK++H,WAAWv2H,KAAKrC,GAEvBnG,KAAKgX,KAAO7Q,G,sCApBH24H,GAA0C,0C,uBAA1CA,EAA0C,4nBCjDvD,wBACW,sDAAmB,6BAcT,EAAAhE,YAAA,KAdV,CAAmB,0BAeX,EAAAC,WAfR,CAAmB,2BAgBV,EAAAC,WAhBT,CAAmB,8BAiBR,EAAAC,WAAA,M,gBAEpB,8BAgBA,8BAGA,8BAGF,Q,KAzCW,wBAAmB,0BAAnB,CAAmB,oBAAnB,CAAmB,yBAAnB,CAAmB,mBAAnB,CAAmB,sBAAnB,CAAmB,wBAAnB,CAAmB,sBAAnB,CAAmB,wBAAnB,CAAmB,sBAAnB,CAAmB,sBAAnB,CAAmB,8BAAnB,CAAmB,uCAAnB,CAAmB,Y,sLCD9B,4MAeO,SAAS+D,EAAyBlzG,GACvC,OAAQ9M,GAAkB8M,EAAQ+hB,eAAe7uB,GAG5C,MAAMigH,EAuBX,YAAqBC,EACAC,EACAC,GAAwB,EACxBC,EAAa,KAHb,KAAAH,iBACA,KAAAC,eACA,KAAAC,gBACA,KAAAC,aAvBd,KAAAh3D,OAAS,IAAI,IAMb,KAAAi3D,SAAW,IAAI,IAGf,KAAAC,WAAiB,GAiBtBv/H,KAAKw/H,QAAU,YACb,YAAG,IACHx/H,KAAKqoE,OAAOloE,KACV,YAAOyB,IAAQw9H,GAAiB,MAACx9H,GACjC,cACA,YAAay9H,GACb,YAAKz9H,IACH5B,KAAKooE,mBAAqBxmE,EAC1B5B,KAAKu/H,WAAa,GAClBv/H,KAAKs/H,SAASl3H,MAAK,KAErB,YAAU4rD,GACRh0D,KAAKk/H,eAAelrE,GACjB7zD,KACC,YAAY6e,IACVhf,KAAKm/H,aAAangH,GACX,YAAG,MAEZ,YAAKlb,IACH9D,KAAKs/H,SAASl3H,MAAK,GACnBpI,KAAKu/H,WAAaz7H,MAI1B,YAAY,KAUX,QAAQ0uC,GACbxyC,KAAKqoE,OAAOjgE,KAAKoqC,GAMnB,iBACE,OAAOxyC,KAAKu/H,WAAWt4H,OAAS,EAM3B,QAAQw4H,GACb,OAAOz/H,KACJw/H,QACAr/H,KACC,YAAUs/H,O,kCC7FlB,oEAAO,MAAMC,EAIX,YAAsB3hH,EAA0BC,EAA0BT,GAApD,KAAAQ,WAA0B,KAAAC,UAA0B,KAAAT,WACxEvd,KAAKwb,KAAO,GAAGxb,KAAK+d,YAAYC,IAG3B,GAAG9V,GACR,OAAO,IAAKlI,KAAKud,UAAYoiH,GAAgB3/H,KAAKwb,KAAMtT,GAYnD,eAAeA,GACpB,OAAI7D,EAAEilB,MAAMphB,GACHlI,KAEAA,KAAKkI,GAAGA,GAIZ,WACL,OAAOlI,KAAKwb,KAGP,SACL,OAAOxb,KAAKwb,MAOT,MAAMmkH,EAGX,YAAqB5hH,EAA0BC,GAA1B,KAAAD,WAA0B,KAAAC,UAC7C,IAAIsvE,EAAYtvE,EAAQqE,WAAW1B,WAAW,KAAO,GAAK,IAC1D3gB,KAAKwb,KAAO,GAAGxb,KAAK+d,WAAWuvE,IAAYtvE,IAGtC,WACL,OAAOhe,KAAKwb,KAGP,SACL,OAAOxb,KAAKwb,Q,kCCjChB,8L,wBCvBI,4B,qBACiB,4BAAqB,4C,wBAGtC,+B,qBAAoB,6B,yBATxB,qBACE,mBACE,QACF,OACA,gBACE,kCAIA,qCAIF,OACF,Q,oBAZI,yCAGiB,4CAMG,uCDyBjB,MAAMokH,EAAsB,cAM5B,MAAMC,UAA6B,IAQxC,YAAsBr/H,EACAE,EACAiC,EACAuZ,GACpBpc,QAJoB,KAAAU,aACA,KAAAE,OACA,KAAAiC,SACA,KAAAuZ,qBAGpBlc,KAAK4X,KAAO,CACV8zB,YAAa1rC,KAAKU,KAAKU,EAAE,yBAI7B,WAGE,GAFApB,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,gBAElC9G,KAAKud,SAAU,CAElB,MAAM/V,EAASxH,KAAK4G,SAASuH,KAAK,YAClCnO,KAAKud,SAAWvd,KAAKkc,mBAAmBm8D,kBAAkB7wE,GAAQ,GAGpExH,KAAK8/H,eAAiB9/H,KAAK4G,SAASuH,KAAK,wBAESzC,IAA9C1L,KAAK4G,SAASuH,KAAK,uBACrBnO,KAAKqqC,mBAAqBrqC,KAAK4G,SAASuH,KAAK,uBAE7CnO,KAAKqqC,oBAAqB,EAG5BrqC,KAAK6rC,8BAGA,8BACL7rC,KAAK2C,OAAOopC,YAAY/rC,KAAKud,UAAWkP,WACrCtsB,KACCH,KAAKI,iBACL,YAAO4rC,KAAiBA,IAEzB3rC,UAAW2rC,IACVhsC,KAAKud,SAAWyuB,GAAehsC,KAAKud,WAMnC,kBACL,OAAOvd,KAAK8/H,gBAAkBz7H,EAAEK,IAAI1E,KAAKud,SAAU,oBAAqB,GAAK,G,sCArDpEsiH,GAAoB,0C,uBAApBA,EAAoB,oZC1CjC,2B,KAAiC,kC,8ECAjC,kJ,qECII,gBACE,iBAEA,cAAG,gFACwD,OAC7D,O,4BAHQ,oCDuBL,MAAME,UAAuC,IAyBlD,YAAqBr/H,EACAs/H,GACnBlgI,QAFmB,KAAAY,OACA,KAAAs/H,UArBZ,KAAApxC,WAAoB,EAGV,KAAAqxC,UAA8B,GAGvC,KAAA14D,SAAW,IAAI,IAGzB,KAAAyQ,iBAAqC,GAOrC,KAAApgE,KAAO,CACL4X,YAAaxvB,KAAKU,KAAKU,EAAE,yBAQ3B,WACEpB,KAAKkgI,yBAGLlgI,KAAKmgI,aAAengI,KAAKggI,QAAQI,YAAY,UAAW,IAGxDpgI,KAAKggI,QAAQK,KAAK,WACflgI,KAAKH,KAAKI,kBACVC,UAAU,IAAM,IAAW2hD,cAAc,OAAQ,cAGpD,YACEhiD,KAAKggI,QAAQM,KAAK,WAClBtgI,KAAKggI,QAAQ3lH,OAAO,YAEnBla,KAAKH,KAAKI,kBACVC,UAAU,IAAM,IAAW2hD,cAAc,SAG5C,MAAM/2B,EAAOjrB,KACbA,KAAKugI,WAAa,IAAI,IACpB,CACEr1H,SAASC,eAAe,oBAE1B,CACEkqE,OAAQ,GACRD,SAAU,GACVD,mBAAmB,EACnBG,WAAY,WACV,OAAOt1E,KAAKk1E,MAAQjqD,EAAKk1G,aAAaK,MAAMC,YAKpD,kBACMzgI,KAAK4uF,WACP5uF,KAAKo0C,kBAAkB7mC,QAI3B,cACEzN,MAAM4Y,cAEN1Y,KAAKggI,QAAQ9hG,QAAQ,WAGvB,OAAOpzB,GACAA,IAIL9K,KAAKulC,SAAW,IAAIvlC,KAAKulC,SAAUz6B,GAGnC9K,KAAKo0C,kBAAkBssF,cAGzB,OAAO51H,GACL9K,KAAKulC,SAAWvlC,KAAKulC,SAASh6B,OAAOg6B,GAAYA,EAASr9B,KAAO4C,EAAK5C,IAGxE,eACE,OAAOlI,KAAKigI,UAGd,aAAar+H,GACX5B,KAAKigI,UAAYr+H,EACjB5B,KAAKkgI,yBAELlgI,KAAKunE,SAAS/+D,KAAKxI,KAAKulC,UAG1B,SAGEj4B,WAAW,KACT,MAAMmB,EAAYzO,KAAKo0C,kBACnB3lC,GAAaA,EAAUymC,eACzBzmC,EAAUymC,cAAcC,mBAEzB,IAGG,yBACNn1C,KAAKg4E,iBAAmBh4E,KAAK8vB,QAC1BvkB,OAAOT,IAAS9K,KAAKulC,SAAS/5B,KAAK+5B,GAAYA,EAASr9B,KAAO4C,EAAK5C,M,sCApH9D63H,GAA8B,sB,uBAA9BA,EAA8B,gE,OAAA,K,4yBC7B3C,gBACE,gBAEK,8DACH,sBAMF,OAEA,wBAUW,+BAAQ,EAAAhF,WAAR,CAAiB,6BACP,EAAA11F,OAAA,MACrB,OACF,Q,MAtBO,wCACuC,mCASjC,yCAA0B,cAA1B,CAA0B,mBAA1B,CAA0B,iCAA1B,CAA0B,sBAA1B,CAA0B,sB,yoBCLhC,MAAM,EAOX,YAAoBx2B,GAAA,KAAAA,aAClB7O,KAAK2gI,UAAYngH,OAAO43C,IAAIwoE,WAQ9B,YAAYrjD,EAAesjD,GACzBtjD,EAAK,CAAE78D,SAAU1gB,KAAK2gI,UAAUjgH,WASlC,WAAWogH,EAAiBvjD,EAAesjD,GAazCtjD,EAZmB,CACjBr1E,GAAI44H,EAAY,GAAG54H,GACnBzB,KAAMq6H,EAAY,GAAGr6H,KACrBs6H,OAAQ/gI,KAAK2gI,UAAUI,OACvBC,cAAe,CACbC,aAAcjhI,KAAK2gI,UAAUO,cAE/BC,cAAe,CACbC,YAAY,KAclB,YAAYC,EAAmBC,EAAgB/jD,EAAev+D,GAC5D,MAAMuiH,EAAevhI,KAAK2gI,UAAUa,wBAAwBF,GAC5D1jH,QAAQyuD,IAAI,+BAA+Bk1D,GAC3CE,EAAA,EAAMC,SAAS1hI,KAAK6O,WAAW8yH,sBAAsBJ,GAAehkD,EAAMv+D,GAU5E,YAAYkzC,EAAkBovE,EAAgB/jD,EAAev+D,GAC3D,MAAMuiH,EAAevhI,KAAK2gI,UAAUiB,mBAAmBN,GACvD1jH,QAAQyuD,IAAI,+BAA+Bk1D,GAC3CE,EAAA,EAAMI,gBAAgB7hI,KAAK6O,WAAW8yH,sBAAsBJ,GAAehkD,EAAMv+D,I,oGCvC9E,MAAM,UAAyB,IASpC,YAAqBjW,GACnBjJ,MAAMiJ,GADa,KAAAA,WARd,KAAA+4H,kBAAmB,EACnB,KAAAC,eAAiB,IAAIC,EAAA,GAAyB,GAW9C,UAAUx9H,EAAyBkc,GACxC,kCAA8CjR,KAAMwyH,IAClD,IAAIC,EAAS,IAAI,EAAaliI,KAAK6O,YAC/BszH,EAAW,IAAIF,EAAmBG,UAAUF,EAAQ19H,GAExD29H,EAASv4H,GAAG,cAAgB5B,IAC1Bq6H,MAAM,eAAer6H,EAAMs6H,6BAA6Bt6H,EAAMu6H,2BAA2Bv6H,EAAMw6H,cAGjGL,EAASv4H,GAAG,cAAe,IAAM5J,KAAK+hI,eAAe35H,MAAK,IAE1D+5H,EAASM,YAAY/hH,EAAS,GAAO,IAErC1gB,KAAK0iI,OAASP,IAIX,UACLniI,KAAK+hI,eAAenoH,WAEf5Z,KAAK0iI,SAIV1iI,KAAK0iI,OAAOxkG,UACZl+B,KAAK0iI,YAASh3H,GAGhB,aACE,OAAO1L,KAAK2iI,QAGd,WAAkBD,GAChB1iI,KAAK2iI,QAAUD,EAGV,mBAAmB9gI,GACxB5B,KAAK0iI,OAAOE,mBAAmBhhI,GAG1B,gBACL,MAAMqN,EAAYjP,KAAK0iI,OAAOG,iBAAiB,CAAEC,eAAe,IAKhE,cAFO7zH,EAAU8zH,QAEV,OAAAzvH,EAAA,GAAGrE,GAGL,cAAcjG,EAAiCioB,GAGhDjxB,KAAKgjI,gBACHhjI,KAAK0iI,QACP1iI,KAAKijI,kBACEC,cAAcl6H,EAAaioB,GAC3B5wB,UAAU4O,GAAajP,KAAK0iI,OAAOS,iBAAiBl0H,EAAW,KAMxEuR,OAAOgoB,SAASjjC,KAAOvF,KAAK6O,WAAWu0H,eACrCp6H,EAAY0S,QAAQJ,WACpBtS,EAAYd,GACZ+oB,GAKC,gBACL,QAASjxB,KAAK0iI,Q,sCApFL,GAAgB,Y,yBAAhB,EAAgB,QAAhB,EAAgB,YAKZ,aAAd,c,0BAAyB,M,iCACX,aAAd,c,0BAAqB,M,6BACP,aAAd,c,0BAAgC,M,2ECZnC,sFAMO,MAAMW,EACX,YAAqBpnH,EACAvb,GADA,KAAAub,uBACA,KAAAvb,OACnBV,KAAKsjI,cAGA,cACL,SAAc5iI,KAAK+nD,QAOd,cAAc86E,EAAiBroH,GACpC,IAAI0X,EAAI,MAAW2wG,EAAUroH,GAO7B,OALIlb,KAAKic,qBAAqBunH,kBAC5B5wG,EAAE6wG,QACF7wG,EAAE8wG,GAAG1jI,KAAKic,qBAAqBosC,aAG1Bz1B,EAGF,UAAU3I,EAAkB/O,GACjC,OAAO,EAAO+O,EAAM/O,GAaf,mBAAmB+O,EAAa/O,GACrC,IAAIokB,EAUJ,OATApkB,EAASA,GAAUlb,KAAK2jI,iBAGtBrkG,EADEt/B,KAAKic,qBAAqBunH,gBACnB,KAAUv5G,EAAM/O,EAASlb,KAAKic,qBAAqBosC,YAEnD,EAAOp+B,EAAM/O,IAEjB0oH,MAEAtkG,EAWF,iBAAiBikG,GACtB,OAAOvjI,KAAK6a,cAAc0oH,EAAU,wBAG/B,aAAat5G,GAClB,OAAOjqB,KAAKw3C,UAAUvtB,EAAM,cAGvB,cAAcA,GAEnB,OADQjqB,KAAKw3C,UAAUvtB,GACd/O,OAAOlb,KAAK6jI,iBAOhB,UAAUtR,GACf,OAAOvyH,KAAKmiH,cAAcoQ,KAAgB,EAQrC,cAAcA,GACnB,MAAMtoG,EAAOjqB,KAAKw3C,UAAU+6E,GACtBuR,EAAQ,IAASx7G,QAAQ,OAE/B,OAAO2B,EAAKzC,KAAKs8G,EAAO,QAGnB,cAAcC,GACnB,OAAO/jI,KAAK6a,cAAckpH,GAAgB7oH,OAAOlb,KAAK2jI,iBAGjD,kBAAkBI,GACvB,IAAIz5D,EAAItqE,KAAKgkF,4BAA4B+/C,GACzC,OAAOz5D,EAAE,GAAK,IAAMA,EAAE,GAGjB,4BAA4By5D,GACjC,IAAInxG,EAAI5yB,KAAK6a,cAAckpH,GAC3B,MAAO,CACLnxG,EAAE1X,OAAOlb,KAAK6jI,iBACdjxG,EAAE1X,OAAOlb,KAAK2jI,kBAIX,QAAQK,GACb,OAAOzvD,OAAO,WAAgByvD,GAAgBC,UAAUrY,QAAQ,IAG3D,kBAAkBoY,GACvB,OAAOhkI,KAAKU,KAAKU,EAAE,gBAAiB,CAAE6yB,MAAOj0B,KAAKkkI,QAAQF,KAGrD,iBAAiB/5G,GACtB,OAAOjqB,KAAKw3C,UAAUvtB,GAAM/O,OAAO,cAG9B,qBAAqBqoH,GAC1B,OAAOA,EAASroH,SAGX,eAAe+O,GACpB,OAAOjqB,KAAKu3C,QAAQttB,EAAM,cAGrB,mBAAmBk6G,GACxB,OAAOnkI,KAAKu3C,QAAQ4sF,EAAU,wBAGzB,QAAQl6G,EAAa4wD,GAC1B,IAAI3/D,EAAS2/D,GAAc76E,KAAK6jI,gBAChC,OAAO,EAAO55G,EAAM,CAAC/O,IAAS,GAAMq8B,UAG/B,gBACL,OAAOv3C,KAAKic,qBAAqBmoH,oBAAsBpkI,KAAKic,qBAAqB4+D,aAAe,IAG3F,gBACL,OAAO76E,KAAKic,qBAAqBooH,oBAAsBrkI,KAAKic,qBAAqBqoH,aAAe,M,sCAjJvFjB,GAAe,sB,yBAAfA,EAAe,QAAfA,EAAe,qBADF,U,kCClC1B,8GAeO,MAAMkB,EAcX,YAAqB5hI,EACAC,EACAe,EACAjD,GAHA,KAAAiC,SACA,KAAAC,aACA,KAAAe,uBACA,KAAAjD,OAbJ,KAAA6mE,SAAW,IAAI,IAEzB,KAAA3vD,KAAO,CACZ4sH,WAAYxkI,KAAKU,KAAKU,EAAE,uBACxBqjI,iBAAkBzkI,KAAKU,KAAKU,EAAE,yBAE9BsjI,eAAgB1kI,KAAKU,KAAKU,EAAE,oCAC5BujI,qBAAsB3kI,KAAKU,KAAKU,EAAE,uCASpC,cACE,OAAOpB,KAAK4kI,QACV5kI,KAAK2D,qBAAqB2U,IAAI,QAAS,SACvCtY,KAAK2D,qBAAqB2U,IAAI,QAAS,UAG3C,iBACE,MAAMlU,EAAOpE,KAAK4C,WAAWiC,UAAUsB,MAEvC,OAAOnG,KAAK2D,qBAAqB2U,IAAI,QAAS,sBACzClU,EAAK5B,OAAO2hC,OAAO7qB,SAGnB,cAAc1X,GACnB5B,KAAKo9F,UAAYx7F,EACjB5B,KAAKq3C,UAGA,aAAaz1C,GAClB5B,KAAKq9F,SAAWz7F,EAChB5B,KAAKq3C,UAGA,UACLr3C,KAAKunE,SAAS/+D,KAAK,CAAE40F,YAAap9F,KAAKo9F,UAAWC,WAAYr9F,KAAKq9F,Y,sCA5C1DknC,GAAgB,0C,uBAAhBA,EAAgB,+lBCf7B,gBACE,gBACE,kBACE,gBACE,kBAIO,yCAAiB,EAAAM,aAAA,MAJxB,OAOF,OACA,QACF,OACA,gBACF,OACF,OAEA,gBACE,gBACE,kBACE,iBACE,mBAIO,yCAAiB,EAAAC,cAAA,MAJxB,OAOF,OACA,SACF,OACA,iBACF,OACF,Q,MA3Be,mCAAoB,0BAK7B,8CAE+C,wDAWtC,oCAAqB,uBAK9B,wCAE+C,oD,8ECJrD,8G,yFC3BE,gBACE,gBACE,YACE,mBACA,aACA,iBACF,OACF,OACF,Q,oBALc,8CAEF,qCDyCP,MAAMC,EA8CX,YAA6BvkI,EACA44H,EACA14H,EACAq5E,EACAirD,GAJA,KAAAxkI,aACA,KAAA44H,gBACA,KAAA14H,OACA,KAAAq5E,uBACA,KAAAirD,gBAjDpB,KAAAC,aAAoC,OAKnC,KAAAC,cAAgB,IAAI,IAGpB,KAAAC,gBAAkB,IAAI,IAGtB,KAAAC,uBAAyB,IAAI,IAQhC,KAAApmH,MAAoB,KACpB,KAAAqmH,iBAAkB,EAClB,KAAAC,YAAa,EAEb,KAAA1tH,KAAO,CACZ2tH,WAAYvlI,KAAKU,KAAKU,EAAE,0CAQlB,KAAAokI,iBAAmBnhI,EAAE2pF,SAC3B,KACEhuF,KAAKg9F,uBAAsB,GACxBvtF,KAAK7N,IACJ5B,KAAKmlI,gBAAgB38H,KAAK5G,MAGhC,IACA,CAAE6jI,SAAS,IAgBN,aACL,OAAIzlI,KAAKslI,WACAtlI,KAAK0lI,SAAW1lI,KAAKouF,mBAAoB3pB,WAEzCzkE,KAAK0lI,SAAW1lI,KAAK65H,iBAAkB14F,QAAQ,CAAEC,MAAM,IAQ3D,sBAAsBukG,GAAsB,GACjD,IAAK3lI,KAAKiG,YACR,KAAM,2DAGR,OAAO,IAAIsJ,QAAgB,CAACC,EAASquB,KACnC,IACEruB,EAAQxP,KAAK85H,cACb,MAAOxtH,GACPsR,QAAQoB,MAAM,oCAAoC1S,MAClD,IAAI0S,EAAQhf,KAAKU,KAAKU,EACpB,gCACA,CAAE4d,MAAO1S,GAAKtM,KAAKU,KAAKU,EAAE,uBAGxBukI,GACF3lI,KAAKo5H,cAAcr/D,SAAS/6C,GAG9B6e,EAAO7e,MAKb,YAAmB4mH,GACjB,IAAK5lI,KAAKiG,YACR,KAAM,2DAGRjG,KAAK0lI,SAAWE,EAChB5lI,KAAK65H,iBAAkB54F,QAAQ2kG,GAMjC,cACE,OAAO5lI,KAAK0lI,SAGd,kBACE,YAAiCh6H,IAA1B1L,KAAK65H,iBAGd,WACE,IACE75H,KAAK6lI,mBACL,MAAO7mH,GAIPpB,QAAQoB,MAAM,sCAAsCA,GACpDhf,KAAKgf,MAAQA,EACbhf,KAAKolI,uBAAuB58H,KAAKwW,IAI7B,mBACNhf,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eAEvC,MAAMg/H,EAAgB9lI,KAAKglI,cACxBziI,OACCvC,KAAKilI,aACLjlI,KAAK+lI,+BAA+Bj/H,cACpC9G,KAAKovB,QACLpvB,KAAK6gC,SAENrmB,MAAOwE,IACN,MAAK,IAENvP,KAAM+wB,IACLxgC,KAAK65H,iBAAmBr5F,EAGxBA,EAAOy5F,MAAM/uH,SAAStB,GAAG,SAAU5J,KAAKwlI,kBAGxChlG,EAAO52B,GAAG,yBAA0B,IAAM5J,KAAKgmI,oBAC/CxlG,EAAO52B,GAAG,0BAA2B,IAAM5J,KAAKimI,qBAEhDjmI,KAAKklI,cAAc18H,KAAKg4B,GACjBA,IAGXxgC,KAAK4G,SAASuH,KAAK,SAAU23H,GAOvB,oBACN,MAAM7lI,EAAUD,KAAK85H,aAGrB95H,KAAK65H,iBAAiB54F,QAAQhhC,GAC9BD,KAAKouF,mBAAqB,KAC1BpuF,KAAKslI,YAAa,EAMZ,mBACN,MAAMrlI,EAAUD,KAAK85H,aAGrBvqH,QACGu0B,IAAI,CACH,qCACA,UAAiD,kBAElDr0B,KAAM6+E,IACL,MAAMC,EAAaD,EAAS,GAAGpqD,QAC/BlkC,KAAKouF,mBAAqBG,EACxBvuF,KAAK4G,SAAS4E,KAAK,sBAAsB,GACzC,CACEkjF,aAAa,EACbC,aAAa,EACbxoF,MAAOlG,EACP+W,KAAM,KAIVhX,KAAKouF,mBAAmBxkF,GAAG,SAAU5J,KAAKwlI,kBAC1Cl4H,WAAW,IAAMtN,KAAKouF,mBAAmB5wD,UAAW,KACpDx9B,KAAKslI,YAAa,K,sCAnMbP,GAAmB,oD,uBAAnBA,EAAmB,oD,OAAA,M,6sBC/ChC,QACE,sBAUA,kBACE,gBACA,gBACE,gBAEF,OACF,OACF,Q,MAjBO,+B,+NC4BP,8GAQO,MAAMmB,EACX,YAA6BxlI,EACA+W,EACAqqB,EACApnB,EACAyrH,GAJA,KAAAzlI,OACA,KAAA+W,SACA,KAAAqqB,iBACA,KAAApnB,aACA,KAAAyrH,qBAGtB,KAAAvuH,KAAO,CACZwuH,SAAUpmI,KAAKU,KAAKU,EAAE,wCACtBia,OAAQrb,KAAKU,KAAKU,EAAE,sCACpBilI,WAAYrmI,KAAKU,KAAKU,EAAE,yCACxBklI,WAAYtmI,KAAKU,KAAKU,EAAE,yCACxBu6C,OAAQ37C,KAAKU,KAAKU,EAAE,sCACpBwE,cAAe5F,KAAKU,KAAKU,EAAE,gCAC3BmlI,MAAOvmI,KAAKU,KAAKU,EAAE,4BACnBolI,gBAAiBxmI,KAAKU,KAAKU,EAAE,oDAC7BqlI,cAAezmI,KAAKU,KAAKU,EAAE,kDAC3BslI,eAAgB1mI,KAAKU,KAAKU,EAAE,mDAC5BulI,iBAAkB3mI,KAAKU,KAAKU,EAAE,qDAC9BwlI,SAAU5mI,KAAKU,KAAKU,EAAE,6CACtBylI,QAAS7mI,KAAKU,KAAKU,EAAE,6CAMvB,UACE,IAAIJ,EAAQ,CACV,CACE8T,WAAY,WACZwtB,MAAOtiC,KAAK4X,KAAKgvH,SACjB/iG,YAAa,MAEf,CACE/uB,WAAY,kBACZwtB,MAAOtiC,KAAK4X,KAAK4uH,gBACjB3iG,YAAa,4IAEf,CACE/uB,WAAY,QACZwtB,MAAOtiC,KAAK4X,KAAK2uH,MACjB1iG,YAAa,4PAEf,CACE/uB,WAAY,mBACZwtB,MAAOtiC,KAAK4X,KAAK+uH,iBACjB9iG,YAAa,6IAIjB,MAAM/0B,EAAoB9O,KAAK8hC,eAAehtB,WAwB9C,OAvBIhG,GACF9N,EAAME,KAAK,CACT4T,WAAY,UACZwtB,MAAOtiC,KAAK4X,KAAKivH,QACjB3+F,YAAaloC,KAAK0a,WAAWmxD,wBAAwB/8D,GAAqB,YAI1E9O,KAAKmmI,mBAAmBtO,aAC1B72H,EAAQA,EAAMqoB,OAAO,CACnB,CACEvU,WAAY,gBACZwtB,MAAOtiC,KAAK4X,KAAK6uH,cACjB5iG,YAAa,qLAEf,CACE/uB,WAAY,iBACZwtB,MAAOtiC,KAAK4X,KAAK8uH,eACjB7iG,YAAa,+LAKZ7iC,EAGF,cAAc6C,GACnB,GAAI7D,KAAKyX,OAAOyG,OAAO2lB,YAAa,CAClC,IAAImU,EAAavyB,KAAKvG,MAAMlf,KAAKyX,OAAOyG,OAAO2lB,oBACxCmU,EAAW8uF,UACX9uF,EAAW+uF,GAClB,IAAIh2E,EAAmBtrC,KAAKC,UAAUsyB,GAEtC,MAAMgvF,EAAU3iI,EAAEmH,KAAKxL,KAAK8jC,IAAKh5B,GAC/BA,EAAK+4B,aAAe/4B,EAAK+4B,cAAgBktB,GAG3C,GAAIi2E,EACF,OAAOA,EAAQ1kG,MAKnB,OAA6B,IAAzBz+B,EAAMmL,QAAQ/H,QACQ,WAAxBpD,EAAMmL,QAAQ,GAAG9G,IACgB,MAAjCrE,EAAMmL,QAAQ,GAAG2W,SAASzd,GACnBlI,KAAK4X,KAAKgvH,SAIZ5mI,KAAK4X,KAAKhS,e,sCAtGRsgI,GAA+B,+D,yBAA/BA,EAA+B,QAA/BA,EAA+B,a,wNCiBrC,MAAMe,EAOX,YAAqBl+H,EACA4V,GADA,KAAA5V,WACA,KAAA4V,OAHb,KAAAhL,OAAiE,GASlE,QAA+B8K,EAA6BlZ,EAAa4I,EAAWgQ,EAA4B,IAIrH,GAAe,QAAXM,EACF,OAAOze,KAAK0E,IAAIa,EAAM4I,EAAMgQ,GAG9B,MAAMxK,EAA2B,CAC/B+K,KAAMvQ,GAAQ,GACdgQ,QAASA,EACTG,iBAAiB,EACjBC,aAAc,QAGhB,OAAOve,KAAKwe,SAASC,EAAQlZ,EAAMoO,GAG7B,SAAY8K,EAA6BlZ,EAAaoO,GAC5D,OAAO3T,KAAK2e,KAAKC,QAAWH,EAAQlZ,EAAMoO,GACvCxT,KACC,YAAK0e,GAAiB7e,KAAKq4E,kBAAkBx5D,IAC7C,YAAYG,IACV,YAAc,IAAMpB,QAAQoB,MAAM,aAAaP,KAAUlZ,MAASyZ,EAAMvY,SACxE,MAAM8W,EAAWvd,KAAKq4E,kBAAiCr5D,EAAMA,OAE7D,OADAzB,EAAS2pH,UAAYloH,EACd,YAAWzB,MAanB,IAA2BhY,EAAa2Y,EAA4BC,GACzE,MAAMxK,EAA2B,CAC/BwK,QAASA,EACTD,OAAQ,IAAI,IAAW,CAAEE,QAAS,IAAI,IAAoBC,WAAYH,IACtEI,iBAAiB,EACjBC,aAAc,QAGhB,OAAOve,KAAKwe,SAAS,MAAOjZ,EAAMoO,GAavB,gBAAyCpO,EAAa4hI,EAAiBjpH,EAAa,GAAIC,EAA4B,I,mDAE/H,IAAIipH,EAAY,EAEZ9tF,EAAO,EAEX,MAAM+tF,EAAe,GAIrB,IAFAnpH,EAAOq8B,SAAW4sF,EAEXC,EAAYD,GAAU,CAC3BjpH,EAAOw6B,OAASY,EAEhB,MAAMrU,EAAUjlC,KAAK4e,QAAQ,MAAOrZ,EAAMvF,KAAKsnI,SAASppH,GAASC,GAAS0O,YACpE/oB,QAAgBmhC,EAEtB,GAAsB,IAAlBnhC,EAAQmwB,MACV,KAAM,qDAGRozG,EAAWnmI,KAAK4C,GAEhBsjI,GAAatjI,EAAQmwB,MACrBqlB,GAAQ,EAGV,OAAO+tF,KAUF,IAA2B9hI,EAAa4I,EAAWgQ,GACxD,OAAOne,KAAK4e,QAAQ,MAAOrZ,EAAM4I,EAAMgQ,GAWlC,KAA4B5Y,EAAa4I,EAAWgQ,GACzD,OAAOne,KAAK4e,QAAQ,OAAQrZ,EAAM4I,EAAMgQ,GAWnC,MAA6B5Y,EAAa4I,EAAWgQ,GAC1D,OAAOne,KAAK4e,QAAQ,QAASrZ,EAAM4I,EAAMgQ,GAWpC,OAA8B5Y,EAAa4I,EAAWgQ,GAC3D,OAAOne,KAAK4e,QAAQ,SAAUrZ,EAAM4I,EAAMgQ,GAOrC,iBAAiBxc,EAAYogE,GAClC/hE,KAAK2T,OAAOhS,GAAOogE,EASrB,mBAEE,OADkC,IAa7B,kBAAuDv6D,EAAYw2E,GAAiB,GACrF35E,EAAEilB,MAAM9hB,KACVA,EAAS,IAAY+/H,oBAGvB,MAAMz0H,EAAOtL,EAAOW,OAAS,cAC7B,OAAOnI,KAAK8uB,wBAA2Bhc,EAAMtL,EAAQw2E,GAGhD,wBAA6DlrE,EAAatL,EAAYw2E,GAAiB,GAK5G,OAFe,IAF2Bh+E,KAAKwnI,uBAAuB10H,GAEvD,CAAkB9S,KAAK+I,SAAUvB,EAAQw2E,EADnC/B,GAAkB,YAAwBj8E,KAAMi8E,GACQnpE,GAWxE,yBAAgDmL,EAAmCzW,EAAYw2E,GAAiB,GACrH,MACMlrE,EAAOtL,EAAOW,OAAS,cAG7B,OAFe,IAAI8V,EAAcje,KAAK+I,SAAUvB,EAAQw2E,EAFnC/B,GAAkB,YAAwBj8E,KAAMi8E,GAEQnpE,GAWxE,SAASyzB,GACd,MAAMhpB,EAAW,IAAYgqH,iBAAiB,IAAQlpH,WAAWre,KAAMumC,IACvE,OAAOvmC,KAAKq4E,kBAAkB96D,GAAU,GAOnC,aAAahY,GAClB,MAAMiC,EAAS,CAAE2mB,OAAQ,CAAEnjB,KAAM,CAAEzF,KAAMA,KACzC,OAAOvF,KAAKq4E,kBAAkB7wE,GAMzB,qBAA0Dy0E,EAAe99B,EAAiB5X,GAC/F,MAAM/+B,EAAS,IAAY+/H,mBACrBE,EAAWxrD,EAAY9J,SACvBu1D,EAAS1nI,KAAK2nI,4BAA4BF,EAAUtpF,IAAa,cAIvE,OAFA32C,EAAO2mB,OAAOnjB,KAAOu7B,EAEdvmC,KAAK8uB,wBAAwB44G,EAAQlgI,GAAQ,GAS5C,uBAA8CsL,GACtD,MAAMa,EAAS3T,KAAK2T,OAAOb,GAC3B,OAAQa,GAAUA,EAAOuvC,IAAOvvC,EAAOuvC,IAAMljD,KAAK4nI,aAU1C,4BAAiE90H,EAAamQ,GACtF,MAAM4kH,EAAa7nI,KAAK2T,OAAOb,GAE/B,OADe+0H,GAAcA,EAAW1kF,WAAc,IACzClgC,GAGL,SAAS/E,GACjB,IAAI4pH,EAAW,UAAariH,KAAKC,UAAUxH,GAAS,CAAEkV,GAAI,WAG1D,MAAO,CAAE20G,OAFQC,KAAKF,K,sCA5Qbb,GAAkB,sB,yBAAlBA,EAAkB,QAAlBA,EAAkB,qBADL,U,oCCvB1B,4JAeO,MAAMgB,EAKX,YAAoB/rH,EACAzY,EACAykI,EACAh4G,EACA2c,EACAj3B,EACAuW,GANA,KAAAjQ,qBACA,KAAAzY,eACA,KAAAykI,uBACA,KAAAh4G,aACA,KAAA2c,sBACA,KAAAj3B,aACA,KAAAuW,YAGZ,cACNnsB,KAAKkc,mBAAmBxX,IAA0B1E,KAAK+gE,OAAOx7D,MAC3DsnB,YACApd,KAAMsxD,IACL/gE,KAAK+gE,OAASA,IAIb,SACL,IAAIh/D,EAAU,CACZ2iE,YAAa1kE,KAAKgJ,YAAY07D,YAC9Bv2C,OAAQ,CACNnlB,YAAa,CACXzD,KAAMvF,KAAKgJ,YAAYzD,QAK7BvF,KAAKkc,mBACFkR,KAA0BptB,KAAK+gE,OAAOx7D,KAAO,WAAYxD,GACzD1B,UACE8nI,IACCnoI,KAAK6sC,oBAAoBa,SAASy6F,GAAS,GAC3CnoI,KAAKgJ,YAAcm/H,EACnBnoI,KAAKkwB,WAAW7qB,MAAMrF,KAAKgJ,YAAYd,IAGvClI,KAAKyD,aAAamC,cAAcC,MAAMC,kBAAkBqiI,GAAS14H,KAAK,KACpEzP,KAAK4V,WAAWyX,YAAY86G,GAC5BnoI,KAAKmsB,UAAUjrB,KAAKinI,EAAS,CAAE36F,UAAW,eAG7CivC,GAAsBz8E,KAAK6sC,oBAAoBgB,eAAe4uC,EAAez8E,KAAKgJ,cAI7D,eAC1BhJ,KAAKooI,e,sCAnDIH,GAAuB,wE,uBAAvBA,EAAuB,iE,qCAAvB,qB,2LC7Cb,mBACI,gCAAS,EAAAzzH,YAGX,QACF,Q,MAFI,sEACF,uC,qDCwBF,kJ,mFvK5BA,gBAGE,sBAGW,gEACT,gBACE,gBACE,2BACF,OACA,eACE,eACE,iCACF,OACA,eACE,mBAIE,eACF,OACF,OACF,OACF,OAEA,6BAGA,kCAAqB,2EACrB,OACF,OACF,O,uBA7Ba,0CAA2B,0BAA3B,CAA2B,iBAMhB,6CAQN,6CASE,6CAA8B,0BuKW3C,MAAM6zH,UAAwC,IANrD,c,oBAOS,KAAAzqC,aAAsB,sB,oCADlByqC,I,uBAAAA,EAA+B,ouBvKrC5C,uB,KAEE,+B,0FuKmCWA,I,kCCTb,8DAIO,MAAeC,UAAyB,IAA/C,c,oBAyCS,KAAApvH,UAAY,IAAI,IAGb,KAAAqvH,kBAA+C,GAKlD,WACL,OAAOh5H,QAAQu0B,IAAI9jC,KAAKuoI,kBAAkBr5H,IAAKgyB,GAAOA,MAGjD,iBAAiBn0B,GACtB/M,KAAKuoI,kBAAkBrnI,KAAK6L,GAsDvB,eAAewQ,O,kCChHxB,8DAMO,MAAMirH,EAHb,cAIqC,KAAA51H,sBAA+B,EACvC,KAAAtR,QAAU,IAAI,IAIlC,YAAY0G,GACE,UAAfA,EAAM8K,MAAoB9K,EAAM+iB,QAAU,IAASqd,OAASpgC,EAAM+iB,QAAU,IAAS09G,QAEnFzoI,KAAK4S,uBACP5K,EAAMuE,iBACNvE,EAAM6E,mBAGR7M,KAAKsB,QAAQkH,KAAKR,K,sCAdXwgI,I,uBAAAA,EAAwB,sE,iCAAxB,mB,CAAmB,8BAAnB,qB,2JCLb,8DAEO,MAAME,EACY,EADZA,EAEY,EAiBlB,MAAMC,EAGX,YAAoBpxG,GAAA,KAAAA,gBAClBv3B,KAAK4oI,wBAGA,iBAAiBC,GACtB,MAAM1iI,EAAQnG,KAAK8oI,oBACbC,GAAgBF,aAAkB,EAAlBA,EAAoB5hI,SAAU,EAEpD,OAAc,OAAVd,GAAkBA,EAAQ,IAAwB,IAAlB4iI,IAA+D,KAAxCF,aAAkB,EAAlBA,EAAoBzrH,QAAQjX,KAC9EA,EAGL4iI,EAAgB,EACXF,EAAmB,GAGrB,GAGT,0BACE,MAAM1iI,EAAQqa,OAAOihB,YAAYiqD,oBAAoB,sBAErD,YAAchgF,IAAVvF,EACKk3B,SAASl3B,EAAO,IAEhB,KAIJ,uBACL,OAAOnG,KAAKgpI,kBAGd,qBACE,SAAUhpI,KAAK8oI,sBAAuB9oI,KAAKgpI,mBAGtC,aACL,OAAOhpI,KAAK8oI,qBAAuB9oI,KAAKgpI,kBAAkBzvF,QAGrD,2BACL,OAAOl1C,EAAEK,IAAI1E,KAAKgpI,kBAAmB,wBAAyBN,GAGzD,2BACL,OAAOrkI,EAAEK,IAAI1E,KAAKgpI,kBAAmB,wBAAyBN,GAGzD,WAAWnvF,GAChB/4B,OAAOihB,YAAYiqD,oBAAoB,qBAAsBnyC,EAAQl3B,YACrEriB,KAAKgpI,kBAAkBzvF,QAAUA,EAG5B,oBACL,OAAOv5C,KAAKgpI,kBAAkBC,eAGzB,kBAAkBA,GACvBjpI,KAAKgpI,kBAAkBC,eAAiBA,EAGnC,wBACL,OAAOjpI,KAAKu3B,cAActxB,YAAYwJ,KAAK,KACzCzP,KAAKgpI,kBAAoB,CACvBzvF,QAASv5C,KAAKq9G,iBAAiBr9G,KAAKu3B,cAAc0xG,gBAClDA,eAAgBjpI,KAAKu3B,cAAc0xG,eACnCC,sBAAuBR,EACvBS,sBAAuBT,GAGlB1oI,KAAKgpI,qB,sCA1ELL,GAAiB,Y,yBAAjBA,EAAiB,QAAjBA,EAAiB,a,kCCrB9B,0EAKO,MAAMS,EADb,cAEmB,KAAAt4H,MAAQ,aAAe,GAExC,cACE,OAAO9Q,KAAK8Q,MAAM2C,YAAW,GAG/B,YAAmB7R,GACjB5B,KAAK8Q,MAAM9M,SAASpC,GAGf,aAAam7B,GAClB,OAAO/8B,KAAK8Q,MAAM5Q,UAAUC,KAAK,YAAU48B,IAGtC,mBACL/8B,KAAK8Q,MAAM8+D,SAAU3vE,IAAaA,I,sCAhBzBmpI,I,yBAAAA,EAAyB,QAAzBA,EAAyB,a,oCCGtC,8DAGO,MAAMC,EACX,YAAsBntH,GAAA,KAAAA,qBAGf,aAAarY,EAAqBO,GACvCpE,KAAKspI,eAAezlI,EAAOO,EAAKrC,QAASqC,EAAK5B,QAC9CxC,KAAKupI,eAAe1lI,EAAOO,EAAKrC,QAASqC,EAAK5B,QAC9CxC,KAAKwpI,cAAc3lI,EAAOO,EAAKrC,QAASqC,EAAK5B,QAC7CxC,KAAKypI,eAAe5lI,EAAOO,EAAKrC,QAASqC,EAAK5B,QAC9CxC,KAAK0pI,uBAAuB7lI,EAAOO,EAAKrC,SAGlC,eAAe8B,EAAqB9B,EAAuB4nI,GACjE,IAAI36H,EAAU3K,EAAE6K,IAAKnN,EAAe,QAAGwJ,IACrC,IAAIq+H,EAAuBvlI,EAAEmH,KAAKm+H,EAAYplI,eAAeC,SAAWhC,GAC9DA,EAAO+I,OAAOvG,cAAwC,GAAGL,QAAU4G,EAAOA,OAAO5G,OAG3F,IAAKilI,EACH,OAAO,KAGT,IAAIC,EAAkBD,EAAqBtqE,YAEvC35C,EAAWthB,EAAEmH,KAAKo+H,EAAqBjkH,SAAS3gB,cAAe2gB,GAC1DA,EAAShhB,QAAU4G,EAAOoa,SAAShhB,OAU5C,OAPIghB,IACFkkH,EAAgBlkH,SAAWA,GAG7BkkH,EAAgBjkH,OAAO3e,OAAS,EAChC5C,EAAEC,KAAKiH,EAAOqa,OAAQzf,GAAS0jI,EAAgBjkH,OAAO1kB,KAAKiF,IAEpD0jI,IAGT76H,EAAU3K,EAAEwmE,QAAQ77D,GAGpBnL,EAAMmL,QAAQ/H,OAAS,EACvB5C,EAAEC,KAAK0K,EAASzD,GAAU1H,EAAMmL,QAAQ9N,KAAKqK,IAGvC,eAAe1H,EAAqBimI,EAAyBtnI,GACnE,IAAIuC,EAAUV,EAAE6K,IAAI46H,EAAU/kI,QAASqL,GAC9B/L,EAAEmH,KAAMhJ,EAAOuC,QAAQC,cAAiCotC,GACtDA,EAAUztC,QAAUyL,EAAOzL,QAItCI,EAAUV,EAAEwmE,QAAQ9lE,GAEpBlB,EAAMkB,QAAQkC,OAAS,EACvB5C,EAAEC,KAAKS,EAASqL,GAAUvM,EAAMkB,QAAQ7D,KAAKkP,IAGvC,cAAcvM,EAAqBimI,EAAyBtnI,GAClE,IAAIunI,EAAU1lI,EAAE6K,IAAK46H,EAAgB,OAAG7kI,GAC/BZ,EAAEmH,KAAMhJ,EAAOyC,OAAOD,cAAyCotC,GAC7DA,EAAUztC,QAAUM,EAAON,QAItColI,EAAU1lI,EAAEwmE,QAAQk/D,GAEpBlmI,EAAMoB,OAAOgC,OAAS,EACtB5C,EAAEC,KAAKylI,EAAS9kI,GAAUpB,EAAMoB,OAAO/D,KAAK+D,IAGtC,eAAepB,EAAqBimI,EAAyBtnI,GACnE,IAAI0C,EAAUb,EAAEmH,KAAMhJ,EAAO0C,QAAQF,cAA0CotC,GACtE03F,EAAU5kI,SAAW4kI,EAAU5kI,QAAQP,QAAUytC,EAAUztC,OAGpEd,EAAMqB,QAAUA,EAGV,uBAAuBrB,EAAqBimI,GAClDzlI,EAAEy+C,QAAQhzC,OAAOD,KAAKi6H,EAAU38G,SAAU,SAAU,WAAWznB,QAASsxB,IACtEnzB,EAAMmzB,GAAY8yG,EAAU9yG,KAG9B3yB,EAAEy+C,QAAQhzC,OAAOD,KAAKi6H,EAAU38G,QAAQgB,QAAS,UAAW,UAAW,UAAUzoB,QAASsxB,IACxFnzB,EAAMmzB,GAAY8yG,EAAU9yG,M,sCArFrBqyG,GAAmC,Y,yBAAnCA,EAAmC,QAAnCA,EAAmC,a,kCCZhD,4G,wBC5BA,6B,kCAEI,kCAA2B,aDqCxB,MAAMW,UAAiC,IAM5C,YAAqBvmI,EACA5D,GACnBC,QAFmB,KAAA2D,eACA,KAAA5D,QAHrB,KAAA05E,QAAiC,GAOjC,WACEv5E,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKgJ,YAAYd,IACpB4d,mBACA3lB,KACCH,KAAKI,kBAENC,UAAWsF,IACV3F,KAAKu5E,QAAU5zE,EAAGskI,cAAgB,IAAItkI,EAAGskI,eAAiB,GAC1DjqI,KAAKH,MAAMS,mB,sCAtBN0pI,GAAwB,sB,uBAAxBA,EAAwB,6PCvCrC,mC,KACI,2B,4FCGG,SAASE,KAAiBzoH,GAC/B,IAAIpgB,EAAO6J,SAASoF,cAAc,KAIlC,OAHAjP,EAAKiQ,aAAa,cAAe,QACjCjQ,EAAKkP,UAAUC,OAAOiR,GAEfpgB,EALT,mC,kCCHA,kG,qBCMM,e,wBAUI,qB,+BAA2B,0CAAAA,KAAA,K,wBAE3B,qB,+BAES,4DADA,wC,+EAZb,aACE,cAMG,uGAED,0BACA,iBACA,0BAGF,OACF,O,iCAdK,4BAAAklD,MAAA,IAEA,sCAAyC,+BACzC,6BAA6B,2BAA7B,CAA6B,sCAKrB,4BACH,uCACG,iC,yBAbf,QACE,qBACA,sBAgBF,Q,yBAjBM,+BACA,iC,wCDEH,MAAM4jF,EAIX,YAAqDr4H,GAAA,KAAAA,SACnD9R,KAAKgB,MAAQhB,KAAK8R,OAAO9Q,MAAMuK,OAAOT,KAASA,aAAI,EAAJA,EAAMqrB,SACrDn2B,KAAK8rB,QAAU9rB,KAAK8R,OAAOga,QAGtB,YAAYhhB,EAAwBygC,GACzC,OAAIzgC,EAAK6N,WAAY7N,EAAK02D,WAItB12D,EAAKxJ,QAASiqC,KAChBvrC,KAAK8R,OAAOga,QAAQ/gB,QACpBwgC,EAAOh/B,iBACPg/B,EAAO1+B,mBACA,K,sCAlBAs9H,GAAsB,KAIb,O,uBAJTA,EAAsB,wiBCVnC,gBAGE,eAGE,+BAmBF,OACF,Q,MA1BK,kCAKC,qDACY,kC,4KCGX,MAAeC,EAiBpB,YAAqBrhI,GAAA,KAAAA,WAJrB,sBACE,OAAO/I,KAAK8Q,MAAM8H,SAAS,0B,sCAdTwxH,GAAmB,Y,yBAAnBA,EAAmB,QAAnBA,EAAmB,YACxB,aAAd,c,0BAAoB,iB,+DCkBvB,0K,uCCdQ,gBAEE,eAAG,6FAIK,OACV,O,4BAFK,+B,yBANP,QACE,sBAQA,gBAA8B,iBAAC,OACjC,Q,qBATM,0C,yBAeF,aAA0C,QAAgB,Q,8BAAhB,iB,uCAC1C,eACE,kGAIK,O,iCADL,uB,mEARJ,gBAGE,qBACA,qBAMF,Q,mCATI,+CAEE,0CACD,2C,sBAQL,gBAA6D,iBAAC,Q,yBAbhE,QACE,sBAYA,sBACF,Q,qBAbM,sCAYA,+C,uCAIJ,gBACE,eAAG,6FAIK,OACV,O,4BAFK,+B,yBALP,QACE,sBAOF,Q,qBAPM,2C,wBAsBJ,kB,qBAIM,0C,yBAGR,gBAEE,qBACA,iBAGF,Q,qBAHQ,wC,uCAgBP,eACE,eAAG,uGAGK,OACV,O,iCAFK,+B,yBAIL,eAAkD,QAAmB,Q,8BAAnB,iB,yBAXnD,gBAIC,uBAOA,uBACD,Q,mCAXI,kDAGG,6CAOA,8C,yBAhBX,iBAEE,eACE,gBAEA,sBAaF,OACF,Q,qBAhBgE,sCAA9B,oCAE1B,0C,uCAtFV,gBACE,gBACE,eAEE,eACE,cAAG,8FAA8C,MAKzC,YAAK,OACf,OAEA,+BAYA,+BAgBA,+BAUA,eAEE,eAAG,8FAA8C,MAMzC,aAAK,OACf,OAEA,gBACE,kBACA,yBAKF,OAEA,uBAOF,OACF,OAEA,wBAoBF,O,uBAjGU,mEAGC,iDAMS,+CAYA,4CAgBA,8CAUV,sGAKC,6CAOG,2CACA,8CAQJ,gCAUH,6CDtCA,MAAMC,UAA4C,IAEvD,YAAsBjtB,EACAv9G,EACAyD,EACDV,EACAI,EACAtC,GACnBZ,MAAMs9G,EAAmBv9G,EAAOa,GANZ,KAAA08G,oBACA,KAAAv9G,QACA,KAAAyD,oBACD,KAAAV,aACA,KAAAI,gBACA,KAAAtC,OAKrB,WACEV,KAAKo9G,kBACFwrB,wBACAn5H,KAAMu5H,IACLhpI,KAAKipI,eAAiBD,EAAkBC,eACxCjpI,KAAKH,MAAMS,kBAGfN,KAAKsD,kBACFwlF,QACA3oF,KACCH,KAAKI,kBAENC,UAAWiqI,IACVtqI,KAAKw4C,WAAa8xF,EAAarqI,QAC/BD,KAAKwU,WAIT,YAAc,CACZxU,KAAK4C,WAAWiB,MAAM3D,UACtBF,KAAKgD,cAAc8lF,UAClB3oF,KACDH,KAAKI,kBACLC,UAAU,EAAEwD,EAAOs2B,MACnBn6B,KAAKuqI,YAAcvqI,KAAKwqI,oBAAsBxqI,KAAKmyC,oBACnDnyC,KAAKyqI,SAAWzqI,KAAK0qI,mBAAmB7mI,EAAMC,SAE9C9D,KAAKwU,WAIF,cAAc+kC,GACnBv5C,KAAKo9G,kBAAkButB,WAAWpxF,GAClCv5C,KAAKsD,kBAAkBg6G,iBAAiB,CAAEhkE,KAAM,EAAGC,QAASA,IAGvD,SAASqxF,GACd5qI,KAAKsD,kBAAkBg6G,iBAAiB,CAAEhkE,KAAMsxF,IAGlD,0BACE,OAAO5qI,KAAKgD,cAAcmvC,oBAGrB,mBAAmBvsC,GACxB,OAAI5F,KAAKmyC,qBAAwBvsC,EAAcquB,MAAQruB,EAAcq0C,MAC5Dv5C,KAAKU,EAAE,mCACZ,CAAE6yB,MAAOruB,EAAcquB,aAEzB,G,sCA9DOo2G,GAAmC,8D,uBAAnCA,EAAmC,sjDC5ChD,wB,KAAwB,4D,wGC4BxB,0H,sEAeM,oB,qBACA,oB,yBAFA,iBACA,0BACA,0BACF,Q,oBAFqC,6BACI,kCAKtC,MAAMQ,UAAgC,IAuB3C,YAA+BnqI,GAC7BZ,QAD6B,KAAAY,OArBd,KAAAu4C,QAAU,IAAI,IACd,KAAAxgC,UAAY,IAAI,IAQ1B,KAAAuG,OAAgB,EAChB,KAAA8rH,WAAY,EAEnB,UAAU3kI,GACRnG,KAAK+qI,YAAYjkI,cAAcX,MAAQA,EACvCnG,KAAKgrI,mBAAmBlkI,cAAcmkI,UAAe9kI,EAAH,IAEpC,MAAVA,IACFnG,KAAK+qI,YAAYjkI,cAAckb,MAAMsJ,QAAU,QAQnD,WACEtrB,KAAK0d,KAAO1d,KAAKw9G,OAAO,GACLx9G,KAAKw9G,OAAO,GAG5Br9G,KACCH,KAAKI,kBAENC,UACEQ,IACC,OAAQA,EAAIiS,MACV,KAAK,IAAco4H,KAEjB,OADAlrI,KAAKmG,MAAQ,EACN,YAAS,mBAAmBnG,KAAK0d,KAAKjX,iBAAiBzG,KAAK0d,KAAKC,SAE1E,KAAK,IAAcwtH,eACjB,OAAOnrI,KAAKorI,eAAevqI,GAE7B,KAAK,IAAcq9G,SAIjB,OAHA,YAAS,QAAQl+G,KAAKirC,gCACtBjrC,KAAKmG,MAAQ,IACbnG,KAAK8qI,WAAY,EACV9qI,KAAKyY,UAAUjQ,OAExB,QAEE,SAGLwW,GAA4Bhf,KAAKylD,YAAYzmC,IAIpD,eACE,OAAOhf,KAAK0d,MAAQ1d,KAAK0d,KAAKjX,KAGxB,eAAe5F,GACjBA,EAAIo5C,MACNj6C,KAAKmG,MAAQshB,KAAK6sD,MAAMzzE,EAAIm9E,OAASn9E,EAAIo5C,MAAQ,KAEjDj6C,KAAKmG,MAAQ,GAIT,YAAY6Y,GAClBhf,KAAKgf,OAAQ,EACbhf,KAAKi5C,QAAQzwC,KAAKwW,I,sCA1ET6rH,GAAuB,Y,uBAAvBA,EAAuB,sE,OAAA,M,4jBAXhC,aACE,iBACA,uBACA,mBAAuB,aAAE,OACzB,uBAIF,Q,MAPyB,uCAGQ,4C,0ECdrC,8M,yBCzBE,gBAEE,gBACE,gBACE,eAGF,OACF,OACF,Q,oBAJU,qD,uCAOV,cACE,+BAEoB,4EAG4B,OAClD,O,+CANsB,yBAAe,kDAAf,CAAe,eAAf,CAAe,0CAAf,CAAe,8B,wBAOrC,gC,oBACqB,mCDuBhB,MAAMQ,UAAsC,IAejD,YAAoB3qI,EACAmQ,EACAhR,EACA4D,GAClB3D,QAJkB,KAAAY,OACA,KAAAmQ,cACA,KAAAhR,QACA,KAAA4D,eAhBb,KAAA6nI,eAA0C,GAC1C,KAAAC,kBAA6B,GAC7B,KAAAC,kBAA2B,EAI3B,KAAA79E,wBAAyB,EAEzB,KAAA/1C,KAAO,CACZ6zH,iBAAkBzrI,KAAKU,KAAKU,EAAE,oCAEzB,KAAAsqI,iBAAyC,GAShD,WACE1rI,KAAKslB,iBAAmBtlB,KAAKgJ,YAAYuc,YAEzCvlB,KAAK6Q,YACFC,MAAM9Q,KAAKgJ,YAAYd,IACvBhI,UACAC,KACC,YAAU,YAAmBH,QAE9BK,UAAW0Q,IACV/Q,KAAK2rI,gBAAgB56H,KAGzB/Q,KAAK6Q,YAAY4f,QAAQzwB,KAAKgJ,YAAYd,IAG1ClI,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKgJ,aACR8c,mBACA3lB,KACC,YAAU,YAAmBH,QAE9BK,UAAWsF,IACV3F,KAAKgJ,YAAcrD,IAIjB,uBAAuB0tD,GAC7B,IAAIu4E,EAA2Dv4E,EAAenkD,IAAI4a,GAChF9pB,KACGyD,aACAmC,cACAsC,GAAG4hB,GACHplB,OAGL,OAAO,eAAOknI,GAGN,wBAAwBt3G,GAChC,MAAM85E,EAAW95E,EAAS1kB,IAC1B,OAAQ0kB,EAASlB,GAAG7tB,OAASvF,KAAKgJ,YAAYzD,KAAQ6oG,EAAS7yF,KAAO6yF,EAASh7E,GAG1E,gBACLpzB,KAAK2tD,wBAA0B3tD,KAAK2tD,uBACpC3tD,KAAK6rI,sBAGG,sBACJxnI,EAAEilB,MAAMtpB,KAAK0rI,oBAIjB1rI,KAAKsrI,eAA2CjnI,EAAEa,QAAQlF,KAAK0rI,iBAC5D/lI,IACC,GAAI3F,KAAK2tD,uBACP,OAAOhoD,EAAGmN,KAAKrM,KAEf,IAAIqlI,EAAkBnmI,EAAGomI,UAA+BD,eAAe9rI,KAAKgJ,aAC5E,OAAOhJ,KAAKU,KAAKU,EAAE,sBAAwB0qI,KAGjD9rI,KAAKurI,kBAAoBlnI,EAAEwL,KAAK7P,KAAKsrI,gBACrCtrI,KAAKwrI,iBAAmBnnI,EAAEsZ,KAAK3d,KAAKsrI,gBAAkB,EACtDtrI,KAAKH,MAAMS,iBAGH,gBAAgB0rI,GACxB,IAAIC,EAAwB,GACxBl7H,EAAkC,GAEtC,GAA4B,IAAxB1M,EAAEsZ,KAAKquH,GAET,OADAhsI,KAAK0rI,iBAAmB,GACjB1rI,KAAK6rI,sBAGdxnI,EAAEC,KAAK0nI,EAAc13G,IACnB,MAAM43G,EAAclsI,KAAKmsI,wBAAwB73G,GACjD23G,EAAa/qI,KAAKgrI,GAClBn7H,EAAUm7H,GAAe53G,IAG3Bt0B,KAAKosI,uBAAuBH,GACzB9rI,KACC,YAAK,IAENE,UAAWgsI,IACVrsI,KAAK0rI,iBAAmBW,EAAoBn9H,IAAKvJ,IAC/CA,EAAGomI,UAAYh7H,EAAUpL,EAAGuC,IACrBvC,IAGT3F,KAAK6rI,yB,sCArHAR,GAA6B,0C,uBAA7BA,EAA6B,glBC/C1C,gBAGE,sBAYA,sBAQA,sCAIA,mCACF,Q,MAxBO,yCAWA,4CAQgB,sCAIG,4C,wGCC1B,0HASO,MAAMiB,EAOb,YAAqB5rI,EACAkV,GADA,KAAAlV,OACA,KAAAkV,aALZ,KAAAgC,KAAO,CACZ20H,YAAavsI,KAAKU,KAAKU,EAAE,oB,sCAJhBkrI,GAAoC,sB,uBAApCA,EAAoC,4WCrCjD,gBACE,8BAIA,mBAKE,iBACA,oBACF,OACF,Q,MAZqB,0CAA2B,eAQtC,8DAHA,oBAIqB,iD,gHCoBxB,MAAME,EAEX,YAAmB7xH,EACA4V,EACAnM,EACA4M,EACAC,GAJA,KAAAtW,kBACA,KAAA4V,aACA,KAAAnM,aACA,KAAA4M,WACA,KAAAC,QAGZ,OAAOw7G,GAAuB,GACnC,OAAOzsI,KAAK0sI,aAAa1sI,KAAKixB,MAAOw7G,GAGvC,WACE,OAAOzsI,KAAK2sI,aAAa3sI,KAAKgxB,UAGhC,qBACE,GAAIhxB,KAAKixB,MAAQ,EACf,OAAOjxB,KAAK2sI,aAAa3sI,KAAKokB,WAAWpkB,KAAKixB,MAAQ,IAI1D,WACE,OAAOjxB,KAAKgxB,SAASzrB,KAGvB,iBACE,MAAO,GAAGvF,KAAKuF,QAAQvF,KAAKq0D,UAG9B,cACE,OAAOr0D,KAAKgxB,SAASqjC,QAGvB,iBACE,OAAOr0D,KAAKiqB,OAASjqB,KAAK4sI,eAGrB,UAAUH,GAAuB,GACtC,IAAI/6H,EAAa1R,KAAK2rH,OAAO8gB,GAE7B,GAAgD,IAA5CzsI,KAAKgxB,SAAS7oB,MAAMiV,QAAQ,YAC9B,OAAO,EAGT,GAAmB,IAAf1L,EACF,OAAO,EAGT,OAASA,EAAa,GAAG,CACvB,IAAI4uE,EAAMtgF,KAAK0sI,aAAah7H,EAAY+6H,GAAgB,EACpDz7G,EAAWhxB,KAAKokB,WAAWk8D,GAC/B,IAAKj8E,EAAEilB,MAAM0H,IAAoD,IAAvCA,EAAS7oB,MAAMiV,QAAQ,YAC/C,OAAO,EAIX,OAAO,EAGC,aAAa4T,GAErB,OAAOvR,OAAOuR,EAAS2+B,WAAWz0C,OAAO,MAGjC,aAAaxJ,EAAmB+6H,GAAuB,GAC/D,OAAIA,GAAgBzsI,KAAKuwB,WAChBvwB,KAAKokB,WAAWnd,OAASyK,EAG3BA,EAAa,G,oDChEjB,MAAM,UAAoC,IAE/C,YAAmBuK,EACEtB,GACnB7a,QAFiB,KAAAmc,uBACE,KAAAtB,kBAIrB,YACE,OAAO3a,KAAKuwB,WAAa,OAAS,MAGpC,iBACE,OAAOvwB,KAAKic,qBAAqB4wH,kCAQzB,KAAK7jI,GACb,IAAI8jI,EAAmB,GAAI7uB,EAA0B,GAEjDztG,EAAM,SAAUrC,GAClB2+H,EAAW5rI,KAAKiN,EAAK3J,WAQvB,OALAy5G,EAAS/8G,KAAK8H,EAAYob,WAAWk4E,UAAU7sF,KAAKe,IAEhDxH,EAAYyqD,WACdwqD,EAAS/8G,KAAK8H,EAAYyqD,UAAU6oC,UAAU7sF,KAAKe,IAE9CjB,QAAQu0B,IAAIm6E,GAAUxuG,KAAK,IACzBzP,KAAK+sI,mBAAmBD,IAIzB,mBAAmB1oH,EAA0Bna,EAAc,aACnE,IAAI+iI,EAAS3oI,EAAEY,OAAOZ,EAAEkgC,QAAQngB,GAAana,GAE7C,OAAIjK,KAAKuwB,WACAy8G,EAAOxoH,UAEPwoH,EAIJ,KAAK5oH,EAA0B4M,EAAsBC,GAC1D,OAAO,IAAIu7G,EAAkBxsI,KAAK2a,gBAAiB3a,KAAKuwB,WAAYnM,EAAY4M,EAAUC,I,sCAhDjF,GAA2B,sB,yBAA3B,EAA2B,QAA3B,EAA2B,a,kCCTxC,sI,uCRdQ,gBAEE,eAAG,6FAIK,OACV,O,4BAFK,+B,yBANP,QACE,sBAQA,gBAA8B,iBAAC,OACjC,Q,qBATM,0C,yBAeF,aAA0C,QAAgB,Q,8BAAhB,iB,uCAC1C,eACE,kGAIK,O,iCADL,uB,mEARJ,gBAGE,qBACA,qBAMF,Q,mCATI,+CAEE,0CACD,2C,sBAQL,gBAA6D,iBAAC,Q,yBAbhE,QACE,sBAYA,sBACF,Q,qBAbM,sCAYA,+C,uCAIJ,gBACE,eAAG,6FAIK,OACV,O,4BAFK,+B,yBALP,QACE,sBAOF,Q,qBAPM,2C,wBAsBJ,kB,qBAIM,0C,yBAGR,gBAEE,qBACA,iBAGF,Q,qBAHQ,wC,uCAgBP,eACE,eAAG,uGAGK,OACV,O,iCAFK,+B,yBAIL,eAAkD,QAAmB,Q,8BAAnB,iB,yBAXnD,gBAIC,uBAOA,uBACD,Q,mCAXI,kDAGG,6CAOA,8C,yBAhBX,iBAEE,eACE,gBAEA,sBAaF,OACF,Q,qBAhBgE,sCAA9B,oCAE1B,0C,uCAtFV,gBACE,gBACE,eAEE,eACE,cAAG,8FAA8C,MAKzC,YAAK,OACf,OAEA,+BAYA,+BAgBA,+BAUA,eAEE,eAAG,8FAA8C,MAMzC,aAAK,OACf,OAEA,gBACE,kBACA,yBAKF,OAEA,uBAOF,OACF,OAEA,wBAoBF,O,uBAjGU,mEAGC,iDAMS,+CAYA,4CAgBA,8CAUV,sGAKC,6CAOG,2CACA,8CAQJ,gCAUH,6CQlCA,MAAMg8G,UAAiC,IAsB5C,YAAsB7vB,EACAv9G,EACAa,GACpBZ,QAHoB,KAAAs9G,oBACA,KAAAv9G,QACA,KAAAa,OAtBb,KAAAwsI,0BAAmC,EACnC,KAAA3C,aAAsB,EACtB,KAAAC,oBAA6B,EAE5B,KAAA2C,cAAgB,IAAI,IAGvB,KAAAv1H,KAAO,CACZw1H,eAAgBptI,KAAKU,KAAKU,EAAE,gCAC5BisI,WAAYrtI,KAAKU,KAAKU,EAAE,4BACxBksI,SAAUttI,KAAKU,KAAKU,EAAE,qBACtBmsI,cAAevtI,KAAKU,KAAKU,EAAE,gCAGtB,KAAAosI,aAAsB,GACtB,KAAAC,YAAuB,GACvB,KAAAC,gBAA2B,GAC3B,KAAAC,eAA0B,GAC1B,KAAA1E,eAA0B,GAQjC,WACEjpI,KAAKo9G,kBACFwrB,wBACAn5H,KAAMu5H,IACLhpI,KAAKipI,eAAiBD,EAAkBC,eACxCjpI,KAAKw4C,WAAa,IAAI,IAAmB,EAAGnb,SAASr9B,KAAK4tI,cAAe5E,EAAkBzvF,SAC3Fv5C,KAAKH,MAAMS,kBAIV,SACLN,KAAK6tI,0BACL7tI,KAAK8tI,oBACL9tI,KAAKH,MAAMS,gBAGN,cAAci5C,GACnBv5C,KAAKw4C,WAAWe,QAAUA,EAC1Bv5C,KAAKo9G,kBAAkButB,WAAWpxF,GAClCv5C,KAAK+tI,SAAS,GAGT,SAASz0F,GACdt5C,KAAKw4C,WAAWc,KAAOA,EAEvBt5C,KAAK6tI,0BACL7tI,KAAK8tI,oBAEL9tI,KAAKguI,gBACLhuI,KAAKH,MAAMS,gBAGN,gBACLN,KAAKmtI,cAAc3kI,KAAKxI,KAAKw4C,YAG/B,gBACE,OAAQx4C,KAAKktI,0BAA6BltI,KAAKw4C,WAAWyB,MAAQj6C,KAAKw4C,WAAWe,QAQ7E,0BACL,GAAIv5C,KAAKw4C,WAAWyB,MAAO,CACzB,IAAIg0F,EAAajuI,KAAKw4C,WAAWyB,MAC7Bi0F,EAAaluI,KAAKw4C,WAAW21F,oBAC7BC,EAAapuI,KAAKw4C,WAAW61F,kBAAkBruI,KAAKw4C,WAAWyB,OAEnEj6C,KAAKwtI,aAAe,IAAMU,EAAa,YAAQE,EAAa,IAAMH,EAAa,SAE/EjuI,KAAKwtI,aAAe,YASjB,oBACL,IAAKxtI,KAAKwqI,mBAGR,OAFAxqI,KAAKytI,YAAc,QACnBztI,KAAK0tI,gBAAkB,IAIzB,IAAIY,EAAatuI,KAAKo9G,kBAAkBmxB,2BACpCC,EAAYxuI,KAAKo9G,kBAAkBqxB,2BAEnChB,EAAc,GAElB,MAAMl0F,EAAUv5C,KAAKw4C,WAAWe,QAC1Bm1F,EAAc1uI,KAAKw4C,WAAWc,KACpC,GAAIC,EAAS,CACX,IAAK,IAAIx8B,EAAI,EAAGA,GAAK0K,KAAKC,KAAK1nB,KAAKw4C,WAAWyB,MAAQV,GAAUx8B,IAC/D0wH,EAAYvsI,KAAK6b,GAInB,IAAI4xH,EAAeD,EAAc,EAAIF,EACjC,GAAKG,GAAgBA,GAAgB,EACvC3uI,KAAK0tI,gBAAkB1tI,KAAK4uI,iBAAiBnB,EAAaA,EAAYxmI,QAAUqnI,EAA0B,EAAZE,EAAgBF,EAAaE,EAAWf,EAAYxmI,OAAQ,IAE1JjH,KAAK2tI,eAAiB3tI,KAAK4uI,iBAAiBnB,EAAaiB,GAAeJ,EAAY,EAAG7mH,KAAK0pE,IAAIu9C,EAAcjnH,KAAKC,KAAK4mH,EAAa,GAAIb,EAAYxmI,OAASqnI,GAAaE,GAC3KxuI,KAAK0tI,gBAAkB1tI,KAAK4uI,iBAAiBnB,EAAaA,EAAYxmI,QAAUqnI,EAA0B,EAAZE,EAAgBF,EAAYb,EAAYxmI,OAAQ,IAIlJjH,KAAKytI,YAAcA,EAGd,qBACL,OAAOztI,KAAKuqI,aACVvqI,KAAKipI,eAAehiI,OAAS,GAC7BjH,KAAKw4C,WAAWyB,MAAQj6C,KAAKipI,eAAe,GAGxC,iBAAiBwE,EAAiBoB,EAAaC,EAAgBC,EAAkBC,GACvF,GAAIH,EAAS,CACX,IAAII,EAAiBjvI,KAAKo9G,kBAAkBqxB,2BACxCS,EAAgBzB,EAAYxkH,OAAO6lH,EAAYC,GAInD,OAHIG,EAAcjoI,QAA2B,EAAjBgoI,GAC1BC,EAAcjmH,OAAO+lH,EAAcE,EAAcjoI,OAASgoI,GAErDC,EAEP,MAAO,I,sCAzIAjC,GAAwB,gC,uBAAxBA,EAAwB,mR,uBAAA,kgDRhDrC,wB,KAAwB,4D,kRScjB,MAAMkC,EAOX,YAAqBpmI,GAAA,KAAAA,WAEd,qBAAqBC,EAAiCioB,GAC3D,MAAMm+G,EAAgBpmI,EAAYsgF,cAAcr4D,GAAO1rB,KAEvD,OAAOvF,KAAKqvI,OAAOnwH,MAAyBkwH,GAGvC,cAAcpmI,EAAiCioB,GAGpD,OAF0BjxB,KAAKsvI,qBAAqBtmI,EAAaioB,GAExCvsB,MAGpB,iBAAiBsE,EAAiCioB,GAGvD,OAF0BjxB,KAAKsvI,qBAAqBtmI,EAAaioB,GAGxDykB,SACAv1C,KAEC,YAAI,IAAMH,KAAKyD,aAAamC,cAAcsC,GAAGc,GAAa8c,kBAAiB,KAIhF,eAAe9c,EAAiCiG,GACrD,MAAMsgI,EAAcvmI,EAAY0S,QAAQJ,WAClCk0H,EAAaxvI,KAAKyvI,aAAazmI,GAE/B0mI,EAAazgI,EACC,YAAGA,GACHjP,KAAK2vI,aAAcC,gBAEvC,OAAO,YAAS,CACNC,UAAWL,EACXvgI,UAAWygI,IAEZvvI,KACC,YAAU2D,GACD9D,KAAKqvI,OACG3uH,SAASxY,GAAGqnI,GACZnvH,OAAOlY,GAAGpE,EAAQ+rI,WAClB7vH,WACAoN,KAAKtpB,EAAQmL,YAI9B,YAAKnL,GACH9D,KAAKyD,aAAamC,cAAcsC,GAAGc,GAAa8c,kBAAiB,KAIxE,aAAa9c,G,MAClB,GAAIhJ,KAAK6vI,UACP,OAAO,YAAG7vI,KAAK6vI,WACV,CACL,MAAMC,EAAgC,QAAvB,EAAG9mI,EAAY+mI,gBAAQ,eAAExqI,KAKxC,OAJmBuqI,EACC,YAAG9vI,KAAKqvI,OAAOnwH,MAAyB4wH,GAAY5nI,IACpDlI,KAAKgwI,gBAAgBhnI,IAEvB7I,KAAK,YAAI0vI,GAAa7vI,KAAK6vI,UAAYA,KAIrD,gBAAgB7mI,GACtB,MAAMumI,EAAcvmI,EAAY0S,QAAQJ,WAClC20H,EAAYjnI,EAAYknI,WAAWnuI,QAEzC,OAAO/B,KAAKqvI,OACG3uH,SAASxY,GAAGqnI,GACZnvH,OACAgN,KAAK6iH,GACL9vI,KACC,YAAKod,IACHvd,KAAK6vI,UAAYtyH,EAAS4yH,KACnBnwI,KAAK6vI,c,sCAnFrBV,GAAiB,Y,yBAAjBA,EAAiB,QAAjBA,EAAiB,YAGb,aAAd,c,0BAAqB,M,6BACP,aAAd,c,0BAA2B,M,mCACb,aAAd,c,0BAA2B,M,sECS9B,0K,yB3DPI,cAA2C,S,mCAAxC,0CAAwC,0B,yBAG3C,gBAAmE,QAAe,Q,mCAA7E,4BAA8D,sB2DiBhE,MAAMiB,UAAsC,IAIjD,YAAqB1vI,EACAgX,EACA7X,EACAgP,EACApL,EACA2mC,GACnBtqC,MAAMY,EAAMb,EAAO6X,EAAgB7I,GANhB,KAAAnO,OACA,KAAAgX,iBACA,KAAA7X,QACA,KAAAgP,aACA,KAAApL,eACA,KAAA2mC,kBARL,KAAAimG,cAAuB,EACtB,KAAAC,SAAW,IAAI,IAWhC,kBACExwI,MAAMs5C,kBAENp5C,KAAKuwI,6BAA6B9gI,KAAM7N,IAClCA,IACF5B,KAAKwwI,cAAiBtrG,GAAiBllC,KAAKywI,iBAAiBvrG,GAC7DllC,KAAKH,MAAMS,mBAUV,6BACL,OAAKN,KAAK0X,eAAexP,GAIlBlI,KACJyD,aACA6wD,SACAlC,mBACAw2D,OAAO5oH,KAAK0X,eAAexP,IAC3B2kB,YACArS,MAAM,KAAM,GATNjL,QAAQC,SAAQ,GAYjB,iBAAiB/I,GACzBzG,KACGyD,aACA6wD,SACAlnC,KAAKptB,KAAK0wI,kBAAkBjqI,IAC5BpG,UACCg0D,GAAWr0D,KAAKswI,SAAS9nI,KAAK6rD,GAC9Br1C,IACEhf,KAAK2wI,cACL3wI,KAAKoqC,gBAAgByD,eAAe7uB,KAIpC,kBAAkBvY,GACxB,IAAI1E,EAAc,GAQlB,OAPAA,EAAc,KAAI0E,EAClB1E,EAAgB,OAAI,CAClB6uI,gBAAiB,CACfrrI,KAAMvF,KAAKyD,aAAaid,SAASxY,GAAGlI,KAAK0X,eAAexP,IAAKsT,OAI1DzZ,G,sCAjEEquI,GAA6B,8D,uBAA7BA,EAA6B,yiB3DzC1C,wBACW,sDAAmB,6BAcT,EAAAtV,YAAA,KAdV,CAAmB,0BAeX,EAAAC,WAfR,CAAmB,2BAgBV,EAAAC,WAhBT,CAAmB,8BAiBR,EAAAC,WAAA,MAEpB,8BAGA,8BAGF,Q,KAzBW,wBAAmB,0BAAnB,CAAmB,oBAAnB,CAAmB,yBAAnB,CAAmB,mBAAnB,CAAmB,sBAAnB,CAAmB,wBAAnB,CAAmB,sBAAnB,CAAmB,wBAAnB,CAAmB,sBAAnB,CAAmB,sBAAnB,CAAmB,sBAAnB,CAAmB,8BAAnB,CAAmB,Y,kG4DA9B,oEAAO,MAAM4V,EAAoB,yBACpBC,EAAoB,c,kCC0BjC,kGAeO,MAAMC,UAAoD,IAC/D,YAAqBvwI,EACAC,EACAC,EACAswI,GACnBlxI,MAAMU,EAAYC,GAJC,KAAAD,aACA,KAAAC,gBACA,KAAAC,OACA,KAAAswI,wBAIX,KAAKnwI,GACbb,KAAKc,aACLd,KAAKS,cAAcM,KAAKf,KAAMa,GAGhC,aACE,MAAO,CACLG,MAAOhB,KAAKgB,MACZC,cAAe,8BAIX,aACNjB,KAAKgB,MAAQ,CACX,CACE2X,SAAU3Y,KAAKgxI,sBAAsBp9H,sBACrCzS,SAAUnB,KAAKU,KAAKU,EAAE,0BACtBC,KAAM,cACNC,QAAUT,IACRb,KAAKgxI,sBAAsBC,6BAA4B,IAEhD,IAGX,CACEt4H,SAAU3Y,KAAKgxI,sBAAsBn9H,qBACrC1S,SAAUnB,KAAKU,KAAKU,EAAE,wBACtBC,KAAM,YACNC,QAAUT,IACRb,KAAKgxI,sBAAsBC,6BAA4B,IAEhD,M,sCAvCJF,GAA2C,0C,uBAA3CA,EAA2C,+D,4LClCjD,MAAMG,UAA2C,IAItD,YAAsBlgF,EACDjzC,EACA7V,EACCwG,GACpB5O,MAAMie,EAAU7V,GAJI,KAAA8oD,UACD,KAAAjzC,WACA,KAAA7V,KACC,KAAAwG,SANb,KAAA3F,SAAW/I,KAAKgxD,QAAQjoD,SAgBvB,YAAuCiV,EAAgBklC,EAAqBiuF,GACpF,OAAO,IAAIjuF,EAAIljD,KAAKgxD,QAAShxD,KAAKwb,KAAMwC,EAAShe,OAhBpC,aAAd,c,0BAAiC,M,yCAqB7B,MAAMmxI,UAA+CD,EAInD,MACL,OAAOlxI,KACJkc,mBACAxX,IAAI1E,KAAKwb,OAIT,MAAM41H,UAAuE,IAIlF,YAAsBpgF,EACAjzC,EACVC,EACUT,GACpBzd,MAAMie,EAAUC,EAAST,GAJL,KAAAyzC,UACA,KAAAjzC,WAEA,KAAAR,WANb,KAAAxU,SAAW/I,KAAKgxD,QAAQjoD,SAe1B,GAAGm8B,GACR,IAAIh9B,EAOJ,OALEA,EADmB,iBAAVg9B,GAAuC,iBAAVA,EACjCA,EAAM7iB,WAEN6iB,EAAMh9B,GAGN,IAAKlI,KAAKud,UAAY4zH,GAAuBnxI,KAAKgxD,QAAShxD,KAAKwb,KAAMtT,EAAIlI,MAI5E,eAAekI,GACpB,OAAI7D,EAAEilB,MAAMphB,GACHlI,KAEAA,KAAKkI,GAAGA,GAOZ,WACL,OAAOlI,KAAKwb,KAMP,SACL,OAAOxb,KAAKwb,KAUP,SAAuCxM,EAA4BkP,EAAiC,GAAID,GAC7G,OAAOje,KAAKywD,YAAe,IAAMzhD,EAAQ8hD,SAAS5yC,GAASD,GAQnD,YAAoDD,EAAgBklC,EAAqBiuF,GACjG,OAAO,IAAIjuF,EAAIljD,KAAKgxD,QAAShxD,KAAKwb,KAAMwC,EAAShe,OAjEpC,aAAd,c,0BAAiC,M,8EC7CpC,8GAaO,MAAMqxI,EAOX,YAAoB/mH,EACCC,EACDC,EACAC,EACA1hB,GAJA,KAAAuhB,2BACC,KAAAC,cACD,KAAAC,SACA,KAAAC,eACA,KAAA1hB,WAMpB,qBACE,IAAK/I,KAAKsxI,mBAAoB,CAC5B,MAAM3mH,EAAc3qB,KAAKsxI,mBAAqBpmI,SAASoF,cAAc,OACrEqa,EAAYpa,UAAUC,IAAI,8CAC1BtF,SAASwT,KAAKrN,YAAYsZ,GAE1B3qB,KAAKuxI,gBAAkB,IAAI,IACzB5mH,EACA3qB,KAAKsqB,yBACLtqB,KAAKwqB,OACLxqB,KAAK+I,UAIT,OAAO/I,KAAKuxI,gBAMP,KAAKpjI,GACVnO,KAAK0rB,SAGL,MAAMP,EAAS,IAAI,IACjBnrB,KAAKwxI,sCACL,KACAxxI,KAAKorB,YAAYjd,IAEnBnO,KAAK6qB,eAAeQ,OAAOF,GAC3BnrB,KAAKsxI,mBAAmBtvH,MAAMsJ,QAAU,QAMnC,SAEDtrB,KAAK6qB,eAAe4mH,gBACtBzxI,KAAK6qB,eAAea,SACpB1rB,KAAKsxI,mBAAmBtvH,MAAMsJ,QAAU,QAUpC,YAAYnd,GAClB,MAAMyd,EAAiB,IAAIC,QAO3B,OAJA1d,EAAK2d,QAAU9rB,KAEf4rB,EAAeG,IAAI,IAAiC5d,GAE7C,IAAI,IAAenO,KAAK+I,SAAU6iB,GAG3C,sCACE,OAAO,K,sCA/EEylH,GAAiC,oE,yBAAjCA,EAAiC,QAAjCA,EAAiC,a,kCCc9C,oI,wBCnBE,yB,qBACa,kCAAgC,0B,wBAK7C,yB,qBACa,kCAAgC,yB,yBAK7C,kBACE,eAGF,Q,qBADK,uCAFA,6BAAsB,2B,wBAI3B,kB,qBAAuC,gC,yBAzBzC,gBAEE,gBACE,0BAGF,OAEA,8BAMA,8BAMA,uBAKA,uBACA,iBACA,iBACE,iBACF,OACF,Q,oBA3BmB,0CAA2B,2BAK/B,mDAMA,oDAMM,kCAKA,mCACiC,8CAE5B,0CDanB,MAAMK,EAkBX,YAAqBhxI,EACAia,EACA9a,EACA4D,GAHA,KAAA/C,OACA,KAAAia,kBACA,KAAA9a,QACA,KAAA4D,eAGrB,WACEzD,KAAK2xI,aAEL3xI,KAAK0b,QAAU1b,KAAKgJ,YAAY0S,QAChC1b,KAAK4xI,SAAW5xI,KAAKgxB,SAASlc,WAC9B9U,KAAKw6C,QAAUx6C,KAAKgxB,SAASwpB,QAAQspD,KAErC,MAAM+tC,EAAe7xI,KAAKgxB,SAAS8gH,aAAa5zF,MAAM34C,KAChDwsI,EAAoB/xI,KAAKgxB,SAASghH,oBAElCzrG,EAAOr7B,SAASoF,cAAc,KACpCi2B,EAAKhhC,KAAOssI,EACZtrG,EAAKjkB,MAAQtiB,KAAK4xI,SAClBrrG,EAAKh1B,YAAcvR,KAAKU,KAAKU,EAC3B,0BACA,CAAC6wI,oBAAqBF,IAGxB/xI,KAAKkyI,aAAelyI,KAAKU,KAAKU,EAAE,wBAC9B,CACE+wI,wBAAyB5rG,EAAKuE,UAC9B7gB,KAAMjqB,KAAK2a,gBAAgBy3H,kBAAkBpyI,KAAKgxB,SAAS2+B,aAIzD,kBACuBjkD,IAAzB1L,KAAKgxB,SAAS3V,OAChBrb,KAAKw0G,SAAWx0G,KAAKgxB,SAASqhH,WAE9BryI,KACGyD,aACAyd,MACAhZ,GAAGlI,KAAKgxB,SAAS3V,OAAOC,YACxB5W,MACArE,UAAWkG,IACVvG,KAAKu0G,OAAShuG,EAAK2B,GACnBlI,KAAKw0G,SAAWjuG,EAAKE,KACrBzG,KAAKsyI,WAAa/rI,EAAKiqC,SACvBxwC,KAAKy0G,WAAaluG,EAAK+a,OACvBthB,KAAKob,SAAW7U,EAAKgsI,SAAShtI,KAC9BvF,KAAKwyI,UAAYxyI,KAAKU,KAAKU,EAAE,kBAAmB,CAACmF,KAAMvG,KAAKw0G,WAC5Dx0G,KAAKH,MAAMS,mB,sCAjERoxI,GAAyB,0C,uBAAzBA,EAAyB,0oBCzCtC,uB,KACK,4B,+MCiCE,MAAM,UAA+B,IAH5C,c,oBAKS,KAAA3jG,YAA4B,YAAd/tC,KAAKyG,M,oCAFf,I,uBAAA,EAAsB,kNClCnC,kBAMO,sDAAmB,8BACR,EAAAqS,QAAA,uBADX,CAAmB,8BAEP,EAAAA,QAAA,gBARnB,Q,MAEO,4BAAqB,sBAArB,CAAqB,kBAArB,CAAqB,uBACrB,iCAA+B,yB,gED+BzB,GEUN,MAAM,UAAkC,IAd/C,c,oBAeS,KAAA2vC,OAAS/nD,KAAK+nD,Q,oCADV,I,uBAAA,EAAyB,4MAZlC,kBAMO,sDAAmB,8BACR,EAAA3vC,QAAA,uBADX,CAAmB,8BAEP,EAAAA,QAAA,gBARnB,Q,MAIO,4BAAqB,kBAArB,CAAqB,uBAFrB,iCAA+B,sBAA/B,CAA+B,mB,gEAU7B,G,oDCIN,MAAM,UAAmC,IAGvC,OAAO3S,GACZ,IAAKsiE,MAAMtiE,GAAQ,CACjB,IAAIssI,EAAaC,WAAWvsI,GAC5B,OAAO,WAAgBssI,EAAY,SAGrC,OAAOtsI,EAGF,UAAUA,GACf,OAAOouE,OAAO,WAAgBpuE,GAAO89H,UAAUrY,QAAQ,IAG/C,WAAWhqH,GACnB,GAAY,OAARA,EACF,OAAOA,EAGT,IAAI+wI,EAOJ,OALEA,EADE/wI,EAAI21C,UACQ31C,EAAIge,cAEJ,KAGT+yH,G,oCA5BE,I,uBAAA,EAA0B,+MAZnC,kBAKO,iDAAyB,EAAAl7F,OAAA,KAAzB,CAAwC,8BAE7B,EAAA3+B,QAAA,wBAPlB,Q,MAIO,qCAA4B,sBAA5B,CAA4B,uBAD5B,iCAA+B,yB,mDAUzB,aAAd,c,0BAA8B,M,mDADpB,G,4BCZN,MAAM85H,EADb,cAEU,KAAAC,QAA0C,GAE3C,SAASpkI,EAAewU,GAC7BjjB,KAAK6yI,QAAQ3xI,KAAK,CAAE+hB,UAAWA,EAAWxU,UAAWA,IAGhD,4BAA4BwU,GACjC,IAAI6vH,EAAazuI,EAAEmH,KAAKxL,KAAK6yI,QAAS3rI,GAASA,EAAM+b,YAAcA,GACnE,OAAO6vH,EAAaA,EAAWrkI,eAAY/C,G,sCATlCknI,I,yBAAAA,EAAkC,QAAlCA,EAAkC,qBADrB,S,sMCanB,MAAM,UAAiC,IAH9C,c,oBAUY,KAAAG,cAAe,EAIlB,KAAAltG,SAAe,KACd,KAAAurC,wBAA0B,+BAS3B,KAAAsrD,iBAA6C,CAClD4T,SAAW0C,GAA2BhzI,KAAKswI,SAAS0C,GACpDzrE,SAAWphE,GAAsBnG,KAAKunE,SAASphE,GAC/C8sI,UAAYjrI,GAAgChI,KAAK8Y,QAAQo6H,kBAAkBlrI,GAAO,GAClFwjB,OAAQ,IAAMxrB,KAAKwrB,SACnBG,QAAS,IAAM3rB,KAAK2rB,UACpBwnH,gBAAkB1kI,GAA2CzO,KAAKozI,wBAA0B3kI,GAGpF,aACRzO,KAAK4X,KAAO,CACVy7H,oBAAqBrzI,KAAKU,KAAKU,EAAE,6BACjCouB,YAAaxvB,KAAKU,KAAKU,EAAE,4BAG3BpB,KAAKszI,qBAAuBtzI,KAAKmZ,OAAOpD,UAAUtG,KAAK,IAC9CzP,KAAKuzI,uBAIN,sBAER,OADAvzI,KAAK+yI,cAAe,EACb/yI,KAAKwzI,aAAa3mH,YAGpB,yBACL,IAAI/Z,EAAO9S,KAAKwC,OAAOsQ,KACvB,OAAO9S,KAAKyzI,4BAA4BC,4BAA4B5gI,IAAS,IAGxE,WACLhT,MAAMqkB,WACNnkB,KAAK6lC,SAAW7lC,KAAK2zI,oBAErB3zI,KAAK8Y,QACFgnC,gBACA3/C,KACCH,KAAKI,kBAENC,UAAU,KACTL,KAAKszI,qBAAqB7jI,KAAK,KAC7BzP,KAAKozI,wBAAwB/C,cAAe,MAKpD,qBACE,MAAM9qI,EAAOvF,KAAKmG,MAAQnG,KAAKmG,MAAMxB,MAAQ,KAC7C,OAAON,EAAEmH,KAAKxL,KAAK4zI,aAActkI,GAAKA,EAAE3K,QAAUY,GAGpD,mBAA0B3D,GACxB,IAAIilC,EAASxiC,EAAEmH,KAAKxL,KAAKg4E,iBAAkB1oE,GAAKA,EAAE3K,QAAU/C,EAAI+C,OAI5DkiC,GAA2B,KAAjBA,EAAOliC,QACnBkiC,EAAOliC,MAAQ,MAGjB3E,KAAKmG,MAAQ0gC,EAGP,UAAUgtG,GAChB7zI,KAAKg4E,iBAAmBh4E,KAAK8zI,WAAWD,GACxC7zI,KAAK+zI,iBACL/zI,KAAK4zI,aAAe5zI,KAAKg4E,iBAAiB9oE,IAAI+C,GAAMjS,KAAKg0I,gBAAgB/hI,IAGjE,WAAWpO,GACnB,IAAImB,EAAgBhF,KAAKwC,OAAOwC,cAEhC,GAAIkY,MAAM2c,QAAQ70B,GAChBhF,KAAKs4E,UAAUtzE,GACfhF,KAAK+yI,cAAe,MACf,IAAI/tI,IAAkBhF,KAAK+yI,aAChC,OAAO/yI,KAAKi0I,sBAAsBpwI,GAElC7D,KAAKs4E,UAAU,IAGjB,OAAO,OAAA/8D,EAAA,GAAKhM,QAAQC,QAAQxP,KAAK4zI,eAGzB,sBAAsB/vI,GAC9B,OAAO,OAAA0X,EAAA,GACLvb,KAAK+3E,kBAAkBl0E,IACvB1D,KACA,OAAAyxD,EAAA,GAAIjuB,UAGuBj4B,IAArBi4B,EAAW1P,YAA4CvoB,IAArBi4B,EAAWsW,QAAyBp2C,GAAS8/B,EAAWsW,QAAUtW,EAAW1P,SACjHj0B,KAAK+yI,cAAe,KAGxB,OAAA7jI,EAAA,GAAIy0B,QACuBj4B,IAArBi4B,EAAW1P,YAA4CvoB,IAArBi4B,EAAWsW,QAAyBp2C,GAAS8/B,EAAWsW,QAAUtW,EAAW1P,QAAWj0B,KAAKmG,MAC1Hw9B,EAAWn/B,SAEXm/B,EAAWn/B,SAAS6kB,OAAO,CAACrpB,KAAKmG,SAG5C,OAAAyrD,EAAA,GAAIptD,GAAYxE,KAAKs4E,UAAU9zE,IAC/B,OAAA0K,EAAA,GAAI,IAAMlP,KAAK4zI,eAIT,kBAAkB/vI,GAE1B,IAAKA,EAAO,CACV,MAAMqwI,EAAWl0I,KAAKwC,OAAOwC,cAAck5C,MAAM34C,KACjD,OAAOvF,KAAKmZ,OAAOg7H,WAAWD,EAAUl0I,KAAKo0I,uBAAuBtnI,KAAK9M,OAG3E,OAAOA,KAAKo0I,uBAAuBvwI,GAG3B,uBAAuBA,GAC/B,OAAO7D,KAAKwC,OAAOwC,cAAck5C,MAAMkR,OAAOpvD,KAAKq0I,oBAAoBxwI,IAGjE,SAASjC,GACf5B,KAAKg4E,iBAAiB92E,KAAKU,GAC3B5B,KAAK4zI,aAAa1yI,KAAK,CAAEuF,KAAM7E,EAAI6E,KAAM9B,MAAO/C,EAAI+C,QAGtD,0BACE,SACG3E,KAAKmG,QAAU9B,EAAE4wC,KAAKj1C,KAAKg4E,iBAAmBnxC,GAAwBA,EAAOliC,QAAU3E,KAAKmG,MAAMxB,SAEjG3E,KAAKmG,OAASnG,KAAKwC,OAAO+W,UAIzB,SAASy5H,GACdhzI,KAAKs0I,SAAStB,GACdhzI,KAAKu0I,eAAiB,CAAE9tI,KAAMusI,EAAWvsI,KAAM9B,MAAOquI,EAAWruI,OACjE3E,KAAK8Y,QAAQuwD,mBAGR,SACLxiE,OAAO7G,KAAKoxE,yBAAyBW,IAAI,SAAU,KACjD/xE,KAAKozI,wBAAwBzC,gBAI1B,WAIA,SAASxqI,GACd,QAAcuF,IAAVvF,EAGF,OAFAnG,KAAKu0I,eAAiB,CAAE9tI,KAAMN,EAAMM,KAAM9B,MAAOwB,EAAMxB,YACvD3E,KAAK8Y,QAAQuwD,mBAIf,MAAMmrE,EAAcx0I,KAAKy0I,iBAErBD,IACFx0I,KAAKu0I,eAAiBC,EACtBx0I,KAAK8Y,QAAQuwD,oBAIT,iBAEN,GAAIrpE,KAAK00I,aACP,YAMkBhpI,IADA1L,KAAKy0I,kBAEvBz0I,KAAKg4E,iBAAiBtpC,QAAQ,CAC5BjoC,KAAMzG,KAAK4X,KAAK4X,YAChB7qB,MAAO,KAKH,aACR,OAAO3E,KAAKwC,OAAO+W,SAGX,WAAWs6H,GACnB,OAAO7zI,KAAKw3E,WAAWr9C,KAAK05G,GAGpB,gBAAgB1tI,GACxB,MAAO,CAAEM,KAAMN,EAAMM,KAAM9B,MAAOwB,EAAMxB,OAKhC,oBAAoBd,GAC5B,MAAO,GAGD,iBACN,OAAOQ,EAAEmH,KAAKxL,KAAKg4E,iBAAkB/lE,GAAMA,EAAGxL,OAASzG,KAAK4X,KAAK4X,c,oCA9NxD,I,uBAAA,EAAwB,mKChDrC,wB,KAAa,uDAAgD,6KAAhD,CAAgD,yC,uCDiD5C,aAAd,c,0BAA0CojH,I,kDAC5B,aAAd,c,0BAA8B,M,sCAChB,aAAd,c,0BAAyB,M,8CAHf,G,2FE1Bb,gCAEqB,gDAAU95H,QAAA,qBAAV,CAAqC,6CACzBA,QAAA,sBAGjC,O,uBANqB,+BAAwB,wBAAxB,CAAwB,8BCkBtC,MAAM,UAAsC,IAHnD,c,oBAOS,KAAAk/D,iBAAyB,GAEzB,KAAApgE,KAAO,CACZy7H,oBAAqBrzI,KAAKU,KAAKU,EAAE,6BACjCouB,YAAaxvB,KAAKU,KAAKU,EAAE,2BACzBgZ,KAAMpa,KAAKU,KAAKU,EAAE,yBAA0B,CAAE6hB,UAAWjjB,KAAKwC,OAAOiE,OACrE4T,OAAQra,KAAKU,KAAKU,EAAE,2BAA4B,CAAE6hB,UAAWjjB,KAAKwC,OAAOiE,QAGpE,KAAAo/B,SAAe,KACd,KAAAurC,wBAA0B,+BAE3B,KAAAujE,qBAA8B,EAK7B,KAAAC,cAAe,EAEvB,WACE50I,KAAK60I,WAAa,CAAEpuI,KAAMzG,KAAK4X,KAAK4X,YAAa7qB,MAAO,MAExD3E,KAAK8Y,QACFgnC,gBACA3/C,KACCH,KAAKI,kBAENC,UAAU,KACTL,KAAK40I,aAAgD,IAAjC50I,KAAKg4E,iBAAiB/wE,OAGrCjH,KAAK40I,cACR50I,KAAK80I,gCAIXh1I,MAAMqkB,WACNnkB,KAAK6lC,SAAW7lC,KAAK2zI,oBAGvB,YACE,MAAM/xI,EAAM5B,KAAKud,SAASvd,KAAKyG,MAC/B,OAAO7E,EAAMA,EAAI,GAAKA,EAQjB,sBACL,MAAMuE,EAAsBnG,KAAKud,SAASvd,KAAKyG,MAC/C,OAAON,EAAQA,EAAM+I,IAAItN,GAAO5B,KAAK+0I,gBAAgBnzI,IAAQ,GAG/D,qBACE,OAAO5B,KAAKg1I,gBAOd,mBAA0BpzI,GACxB5B,KAAKg1I,gBAAkBpzI,EACvB,IAAI29D,EAAU39D,IACZ,IAAIilC,EAASxiC,EAAEmH,KAAKxL,KAAKg4E,iBAAkB1oE,GAAKA,EAAE3K,QAAU/C,EAAI+C,QAAU3E,KAAK60I,WAQ/E,OAJIhuG,GAA2B,KAAjBA,EAAOliC,QACnBkiC,EAAOliC,MAAQ,MAGVkiC,GAGT7mC,KAAKud,SAASvd,KAAKyG,MAAQpC,EAAEwzE,UAAUj2E,GAAKsN,IAAI+C,GAAMstD,EAAOttD,IAGxD,SACLpL,OAAO7G,KAAKoxE,yBAAyBW,IAAI,SAAU,KACjD/xE,KAAKo0C,kBAAkBrpC,UAIpB,WAIA,qBACD/K,KAAKo0C,mBAAqBp0C,KAAKo0C,kBAAkBc,eACnD5nC,WAAW,IAAMtN,KAAKo0C,kBAAkBc,cAAc+/F,iBAAkB,GAIpE,8BAGN,IAAIhqH,EAAOjrB,KACXwgB,OAAOlT,YAAW,WAChB2d,EAAKmpB,kBAAkB/pC,SACtB,GAGG,gBAAgBw8B,GACtB,IAAIvH,EAMJ,OAJIuH,IACFvH,EAASj7B,EAAEmH,KAAKxL,KAAK4zI,aAAesB,GAAgBA,EAAYvwI,QAAUkiC,EAAOliC,QAG5E26B,GAAUt/B,KAAK60I,WAGhB,UAAUhB,EAAuBsB,GAA2B,GAC9DA,GACFtB,EAAgB15G,MAAK,SAAUjX,EAAOC,GACpC,IAAIiyH,EAAQlyH,EAAEzc,KAAKg+B,cACf4wG,EAAQlyH,EAAE1c,KAAKg+B,cACnB,OAAO2wG,EAAQC,GAAS,EAAID,EAAQC,EAAQ,EAAI,KAIpDr1I,KAAKg4E,iBAAmB67D,GAAmB,GAC3C7zI,KAAK4zI,aAAe5zI,KAAKg4E,iBAAiB9oE,IAAI+C,IACrC,CAAExL,KAAMwL,EAAGxL,KAAM9B,MAAOsN,EAAGtN,SAEpC3E,KAAKg1I,gBAAkBh1I,KAAKs1I,sBAC5Bt1I,KAAKu1I,4BAEDv1I,KAAKg4E,iBAAiB/wE,OAAS,GAAKjH,KAAK40I,eAC3C50I,KAAK80I,8BACL90I,KAAK40I,cAAe,GAId,aACR90I,MAAMkG,aACNhG,KAAKwzI,aAGC,aACN,IAAIxuI,EAAgBhF,KAAKwC,OAAOwC,cAChC,GAAIkY,MAAM2c,QAAQ70B,GAChBhF,KAAKs4E,UAAUtzE,OACV,IAAIhF,KAAKwC,OAAOwC,cACrB,OAAOhF,KAAKwC,OAAOwC,cAAc8oE,QAAQr+D,KAAMmW,IAEzCA,EAAOqO,MAAQ,GAA2C,YAArCrO,EAAOphB,SAAS,GAAW2D,MAClDnI,KAAKs4E,UAAU1yD,EAAOphB,UAAU,GAEhCxE,KAAKs4E,UAAU1yD,EAAOphB,YAI1BxE,KAAKs4E,UAAU,IAEjB,OAAO/oE,QAAQC,UAGT,4BACFxP,KAAKmG,MACPnG,KAAK20I,qBAGDtwI,EAAE4wC,KAAKj1C,KAAKmG,MAAQA,GACb9B,EAAE4wC,KAAKj1C,KAAKg4E,iBAAmBnxC,GAAYA,EAAOliC,QAAUwB,EAAMxB,QAK7E3E,KAAK20I,sBAAwB30I,KAAKwC,OAAO+W,U,oCAhLlC,I,uBAAA,EAA6B,qD,OAAA,K,KAC7B,KAAmB,G,2gBDzChC,sBAAW,+DAA4B,8BAUjB,EAAAT,QAAA,qBAAkC,KAV7C,CAA4B,0BAWpB,EAAA0S,WAXR,CAA4B,2BAYnB,EAAAG,YAZT,CAA4B,yBAarB,EAAA4sD,uBAbP,CAA4B,4BAclB,EAAAA,wBAMrB,OAEA,uC,MAtBW,iCAA4B,6CAA5B,CAA4B,sBAA5B,CAA4B,wBAA5B,CAA4B,sBAA5B,CAA4B,sBAA5B,CAA4B,uBAA5B,CAA4B,mBAA5B,CAA4B,sBAA5B,CAA4B,cAA5B,CAA4B,mBAA5B,CAA4B,sBAA5B,CAA4B,yBAA5B,CAA4B,mBAuBlB,6C,2DCmBJ,aAAd,c,0BAAmB,M,wCAFT,GCKN,MAAM,UAAgC,IAf7C,c,oBAgBS,KAAA9vB,OAAS/nD,KAAK+nD,Q,oCADV,I,uBAAA,EAAuB,yNAbhC,kBAMO,sDAAmB,8BACR,EAAA3vC,QAAA,uBADX,CAAmB,8BAEP,EAAAA,QAAA,gBARnB,Q,MAKO,4BAAqB,kBAArB,CAAqB,uBAFrB,iCAA+B,sBAA/B,CAA+B,mB,gEAU7B,GCDN,MAAM,UAAkC,IACtC,YAAY05B,GACjBxyC,KAAKmG,MAAQqsC,EACbxyC,KAAK8Y,QAAQuwD,oB,oCAHJ,I,uBAAA,EAAyB,yNAVlC,kBAIO,iCAAU,EAAA3zD,aAAA,WAAV,CAA8B,8BACnB,EAAAoD,QAAA,wBALlB,Q,MAGO,wBAAiB,sBAAjB,CAAiB,uBADjB,mC,+BAQE,G,6MCNN,MAAM,UAAsC,EAHnD,c,oBAKS,KAAA8uD,SAAW,IAAI,IACnBC,GAAsB7nE,KAAKwzI,WAAW3rE,GACvC,YAAyB7nE,KAAKoqC,kBAGtB,sBAKR,OAJApqC,KAAK+yI,cAAe,EAIb,IAAIxjI,QAAwBC,IACjCxP,KAAK4nE,SAAS43D,QAAQr/H,KAAK,OAAAi3C,EAAA,GAAK,IAAI/2C,UAAUyvB,IAC5CtgB,EAAQsgB,KAGV9vB,KAAK4nE,SAASS,OAAOjgE,KAAK,MAI9B,gBACE,OAAIpI,KAAK+yI,cAGA/yI,KAAK4nE,SAASS,OAIf,oBAAoBxkE,GAC5B,IAAI2xI,EAAe11I,MAAMu0I,oBAAoBxwI,GAE7C,GAAIA,EAAO,CACT,IAAImL,EAA6B,IAAI,IAErCA,EAAQwB,IAAI,cAAe,KAAM,CAAC3M,IAElC2xI,EAAe,CAAExmI,QAASA,EAAQmjD,UAGpC,OAAOqjF,EAGC,gBAAgBrvI,GACxB,GAAKA,EAA8B+B,GAAI,CAErC,IAAIutI,EAAUtvI,EAA8B2M,KAAW3M,EAA8B2M,KAAKrM,KAAvC,IAAiD,GAChGqlE,EAAU3lE,EAA8BijE,SAAWjjE,EAAMM,KAE7D,MAAO,CACLA,KAAM,GAAGgvI,KAAYtvI,EAA8B+B,MAAO4jE,IAC1DnnE,MAAOwB,EAAMxB,OAGf,OAAOwB,G,oCAtDA,I,uBAAA,EAA6B,oKCtC1C,wB,sBAAa,uDAAgD,6NAAhD,CAAgD,yC,gEDsChD,G,4BEWN,MAAM,UAA+B,IAI1C,WACErG,MAAMqkB,WAGD,gBAAgBhW,GACrBnO,KAAKmG,MAAQnG,KAAKy3C,OAAOtpC,GACzBnO,KAAK8Y,QAAQuwD,mBAGR,WACLrpE,KAAK8Y,QAAQ2wD,mBAGR,OAAOt7D,GACZ,OAAI,EAAOA,EAAM,cAAc,GAAMopC,UAC5BppC,EAEA,KAIJ,UAAUA,GACf,GAAI,EAAOA,EAAM,cAAc,GAAMopC,UAAW,CAC9C,IAAI3kB,EAAI5yB,KAAK2a,gBAAgB68B,UAAUrpC,GACvC,OAAOnO,KAAK2a,gBAAgBoY,iBAAiBH,GAE7C,OAAO,M,oCA9BA,I,uBAAA,EAAsB,oNAZ/B,2BAEI,oCAAY,EAAA8iH,gBAAA,KAAZ,CAAoC,8BACxB,EAAAx7H,cAMhB,Q,KALI,yCAAgC,sBAAhC,CAAgC,sBAAhC,CAAgC,wB,mCASvB,aAAd,c,0BAAuC,M,sCACzB,aAAd,c,0BAA6B,M,kDAFnB,G,yCC/CN,SAASy7H,GAA0BhmI,GAGxC,MAAO,KAFPA,EAAOimI,GAAkBjmI,IAEPkR,QAAQ,IAAK,KAG1B,SAASg1H,GAAkBlmI,EAA4BjP,GAG5D,OAFAiP,EAAOimI,GAAkBjmI,GAElBjP,EAAKU,EAAE,kCAAoCuO,EAAKkR,QAAQ,IAAK,MAGtE,SAAS+0H,GAAkBjmI,GACzB,OAAOA,GAAc,U,0BCHnB,iBACA,iBAA+D,QAAa,Q,oBADzC,6BACA,qCAA4B,sB,0BAG/D,iBACA,iBAA+D,QAAa,Q,oBADzC,6BACA,qCAA4B,sBCsB5D,MAAM,WAAwC,IAJrD,c,oBAQU,KAAAmmI,sBAAiC,CAAC,UAAW,YAAa,UAAW,YACtE,KAAAC,kBAA2B,UAE3B,KAAAC,kBAA0Bh2I,KAAK81I,sBAAsB5mI,IAAKS,IACxD,CACLA,KAAMA,EACNlJ,KAAMovI,GAAkBlmI,EAAM3P,KAAKU,MACnCikF,WAAYgxD,GAA0BhmI,MAInC,KAAAyhE,wBAA0B,mBAC1B,KAAAK,kBAAoB,OAE3B,WACEzxE,KAAK+1I,kBAAgD,OAA5B/1I,KAAKud,SAAiB,OAAa,UAAYvd,KAAKud,SAAiB,OAI9F,IAAI0N,EAAOjrB,KACXwgB,OAAOlT,YAAW,WAChB2d,EAAKmpB,kBAAkB/pC,SACtB,GAGE,WACLrK,KAAKud,SAAiB,OAA+B,YAA3Bvd,KAAK+1I,kBAAkC,KAAO/1I,KAAK+1I,kBAC7E/1I,KAAK8Y,QAAQuwD,mBAGR,SAGL/7D,WAAW,KACT,MAAMmB,EAAazO,KAAsB,kBACrCyO,GAAaA,EAAUymC,eACzBzmC,EAAUymC,cAAcC,kBAG1BtuC,OAAO7G,KAAKoxE,yBAAyBW,IAAI,+BAAgC,KACvE/xE,KAAKo0C,kBAAkBrpC,WAExB,IAGE,UACLlE,OAAO7G,KAAKoxE,yBAAyBjnC,IAAI,iC,sCAlDhC,K,wBAAA,GAA+B,qD,OAAA,K,KAC/B,KAAmB,G,+YDxChC,sBACW,kEAA+B,0BAIvB,EAAA3e,WAJR,CAA+B,2BAKtB,EAAAG,YALT,CAA+B,4BAMrB,EAAA47C,cAInB,+BAIA,+BAIF,Q,KAnBW,kCAA2B,8BAA3B,CAA2B,+BAA3B,CAA2B,kBAA3B,CAA2B,wB,mDCyCrB,aAAd,c,0BAAmB,M,0CAFT,ICLN,MAAM,WAA2C,IAHxD,c,oBAKS,KAAAx5B,aAAc,EAErB,YACE,IAAK/tC,KAAKwC,OACR,MAAO,GAET,MAAMotB,EAAU5vB,KAAKud,SAASvd,KAAKyG,MAEnC,OAAOmpB,GAAWA,EAAQvW,KAAO,GAGnC,UAAiBm5B,GACfxyC,KAAKud,SAASvd,KAAKyG,MAAQ,CAAE4S,IAAKm5B,I,sCAdzB,K,wBAAA,GAAkC,kNhBlC/C,kBAMO,sDAAmB,8BACR,EAAA15B,QAAA,uBADX,CAAmB,8BAEP,EAAAA,QAAA,gBARnB,Q,MAEO,4BAAqB,sBAArB,CAAqB,kBAArB,CAAqB,uBACrB,iCAA+B,yB,iEgB+BzB,I,iNCUN,MAAM,WAA+C,EAKhD,aACRhZ,MAAMkG,aAIFhG,KAAK08H,mBACP18H,KAAK08H,iBAA6B,WAAK1lH,IACrChX,KAAK+yI,cAAe,EACpB,IAAI17C,EAAYr3F,KAAK4nE,SAASQ,mBAI9BpoE,KAAK4nE,SAASS,OAAOjgE,KAAK,cAC1BpI,KAAK4nE,SAASS,OAAOjgE,KAAKivF,KAKzB,yBACL,OAAO,KAQC,aACR,OAAO,EAOC,kBAAkBxzF,GAC1B,OAAK7D,KAAKi2I,qBAeDj2I,KAAKo0I,uBAAuBvwI,GAd5B7D,KACJyD,aACAiyD,aACAtC,KAAK,CAAEpkD,QAAS,CAAC,CAAC,UAAW,IAAK,CAAC,QAAS/J,OAAQ,CAAC,CAAC,aAAc,SAAUs1C,SAlD9C,KAmDhC1tB,YACApd,KAAKk0B,IACJ3jC,KAAKi2I,qBAAuBtyG,EACzBn/B,SACA0K,IAAKgnI,GAAcA,EAAUltI,YAAYsS,YACzC/P,OAAO,CAACqyE,EAAG7gE,EAAGmG,IAAMA,EAAE9F,QAAQwgE,KAAO7gE,GAEjC/c,KAAKo0I,uBAAuBvwI,KAOjC,oBAAoBA,GAC5B,IAAImL,EAA6B,IAAI,IAUrC,MAR0F,WAArFhP,KAAKozI,wBAAuEp8H,MAC/EhI,EAAQwB,IAAI,KAAM,IAAKxQ,KAAKi2I,sBAG1BpyI,GACFmL,EAAQwB,IAAI,cAAe,KAAM,CAAC3M,IAG7B,CAAEmL,QAASA,EAAQmjD,UAGlB,WAAW0hF,GACnB,MAA0F,WAArF7zI,KAAKozI,wBAAuEp8H,KACxEhX,KAAKm2I,sBAAsBtC,GAE3B/zI,MAAMg0I,WAAWD,GAIlB,sBAAsBA,GAC9B,OAAOA,EACJ15G,KAAK,CAACjX,EAAGC,IACDnjB,KAAKi2I,qBAAqB74H,QAAQ8F,EAAEhb,IAAOlI,KAAKi2I,qBAAqB74H,QAAQ+F,EAAEjb,M,sCArFjF,K,wBAAA,GAAsC,oKN5CnD,wB,sBAAa,uDAAgD,8NAAhD,CAAgD,yC,mDM6C5C,aAAd,c,0BAA2B,O,kDADjB,I,iBCAN,MAAM,WAAuC,EAPpD,c,oBAWE,KAAAozE,MAAe,GACf,KAAA86D,mBAAqBp2I,KAAKU,KAAKU,EAAE,0BACjC,KAAAi1I,iBAAmBr2I,KAAKU,KAAKU,EAAE,wBAI/B,WACEtB,MAAMqkB,WAENnkB,KAAK8Y,QACFgnC,gBACA3/C,KACCH,KAAKI,kBAENC,UAAU,KACTL,KAAKs2I,wBAIX,c,MACEx2I,MAAM4Y,cACI,QAAV,EAAA1Y,KAAKy7D,aAAK,SAAEnU,UAGP,cACLtnD,KAAKs2I,sBAGC,sBACN,MAAM76E,EAAQz7D,KAAKy7D,MAAQz7D,KACxB65C,eACA94C,KAAK,KAAiBf,KAAK+I,SAAU,CAAE2jB,UAAW1sB,KAAKmZ,OAAQ/R,UAAWpH,KAAKyG,OAElF6G,WAAW,KACT,MAAMm9E,EAAe5jF,OAAO40D,EAAMj7D,WAAWsG,eAAe0E,KAAK,qBAC3DtE,EAAQL,OAAO7G,KAAKQ,WAAWsG,eACrC20D,EAAMlwC,WAAWk/D,EAAcvjF,KAGjCu0D,EACG3hB,cACAz5C,UAAWi7E,IACVt7E,KAAKs7E,MAAQA,EACbt7E,KAAKH,MAAMS,kBAGfm7D,EACGD,aACAr7D,KAAK,OAAAi3C,EAAA,GAAK,IACV/2C,UAAU,KACTL,KAAK8Y,QAAQuwD,qBAKT,aACRvpE,MAAMkG,aAINhG,KAAKs7E,MAAQ,GAAGt7E,KAAKu2I,sBAAsBv2I,KAAKw2I,iBAGlD,uBACE,OAAOx2I,KAAKud,SAASyM,WAAahqB,KAAKo2I,mBAGzC,qBACE,OAAOp2I,KAAKud,SAAS4M,SAAWnqB,KAAKq2I,kB,sCAxE5B,K,wBAAA,GAA8B,oIALvC,kBACO,gCAAS,EAAA5tI,iBADhB,Q,KAAO,uB,kBAMM,aAAd,c,0BAAuC,M,uCACzB,aAAd,c,0BAA6B,M,oDAFnB,I,iBCdN,MAAM,WAAyB,MCA/B,MAAM,WAA0B,KAErC,kBACE,OAAkB,MAAdzI,KAAKmG,MACA,GAGFnG,KAAKmG,MAAMswI,eAChBz2I,KAAKU,KAAK+nD,OACV,CAAEiuF,aAAa,EAAMC,sBAAuB,MCT3C,MAAM,WAA4B,KACvC,YACE,OAAOt5G,SAASr9B,KAAKud,SAASvd,KAAKyG,OAG9B,UACL,OAAOgiE,MAAMzoE,KAAKmG,QCNf,MAAM,WAA6B,KACxC,YACE,OAAInG,KAAKwC,OACAxC,KAAKijB,WAAajjB,KAAKijB,UAAUxc,KAGjC,M,kCCFN,MAAM,WAAgC,KAIpC,OAAOmpB,EAAqBC,EAAoBC,EAAc,IACnE,IAAIm+C,EAAM/iE,SAASoF,cAAc,OAEjC29D,EAAI19D,UAAUC,IACZ,mBACA,YACA,kBACA,mCACA,cAEEsf,EAAQyQ,KACV0tC,EAAI19D,UAAUC,IAAI,QAGpBy9D,EAAIl6C,UAAYlE,EAEhBD,EAAQmE,UAAY,GACpBnE,EAAQve,YAAY48D,GAGpB,KAAoB2oE,4BAA4B52I,KAAKwqB,OAAQyjD,GAG/D,oBACE,OAAO,EAGT,YACE,IAAKjuE,KAAKwC,OACR,OAAO,KAET,MAAMotB,EAAU5vB,KAAKud,SAASvd,KAAKyG,MACnC,OAAMmpB,GAAWA,EAAQk0E,KAIlB9jG,KAAK62I,SAASjnH,EAAQk0E,MAHpB,GAQD,SAASA,GACjB,OAAIA,ECpDD,MAIE,kCACL,MAAO,KAGF,gCACL,MAAO,0CAGF,cAAc5+D,GACnB,OAAOA,EAAMrkB,QAAQ,IAAIouC,OAAOjvD,KAAK82I,qBAAsB,KAAM92I,KAAK+2I,oBAGjE,gBAAgB7xG,GACrB,OAAOA,EAAMrkB,QAAQ,IAAIouC,OAAOjvD,KAAK+2I,mBAAoB,KAAM/2I,KAAK82I,wBDoCzCD,SAAS/yC,GAE3B,IA/CI,aAAd,c,0BAA8B,M,8BEJ1B,MAAM,WAA6B,KAA1C,c,oBAGU,KAAAkzC,YAAch3I,KAAKU,KAAKU,EAAE,wCAElC,kBACE,OAAOpB,KAAK2a,gBAAgBs8H,kBAAkBj3I,KAAKmG,OAMrD,0BACE,MAAO,UAAYnG,KAAKyG,KAAK+9E,OAAO,GAAG3hE,cAAgB7iB,KAAKyG,KAAKie,MAAM,GAGzE,mBACE,OAAO1kB,KAAKud,SAASvd,KAAKk3I,qBAG5B,yBACE,MAAM/wI,EAAQnG,KAAKm3I,aAEnB,OAAIhxI,EACKnG,KAAK2a,gBAAgBs8H,kBAAkB9wI,GAEvCnG,KAAKwvB,YAIT,OAAOI,EAAqBC,GACjC,GAAI7vB,KAAKsX,UAEP,YADAsY,EAAQre,YAAcvR,KAAKwvB,aAI7BI,EAAQrf,UAAUC,IAAI,oBACtB,IAAIrK,EAAQnG,KAAKmG,MACbixI,EAAiBjxI,GAASnG,KAAK2a,gBAAgBupH,QAAQ/9H,IAAW,EAEvD,IAAXixI,GACFp3I,KAAKq3I,aAAaznH,EAASC,GAG7B,IAAIynH,EAAUt3I,KAAKm3I,aACfG,GAAqD,IAA1Ct3I,KAAK2a,gBAAgBupH,QAAQoT,IAC1Ct3I,KAAKu3I,cAAc3nH,EAAS5vB,KAAKw3I,mBAA+B,IAAXJ,GAIlD,aAAaxnH,EAAqBC,GACvC,MAAMxO,EAAOnW,SAASoF,cAAc,QAEpC+Q,EAAK9P,YAAcse,EACnBxO,EAAKiB,MAAQtiB,KAAK2vB,YAClBtO,EAAK9Q,UAAUC,IAAI,iBAEnBof,EAAQve,YAAYgQ,GAGf,cAAcuO,EAAqBC,EAAoB4nH,GAC5D,MAAMp2H,EAAOnW,SAASoF,cAAc,QAEpC+Q,EAAK/P,aAAa,QAAStR,KAAKsvB,MAAMC,OACtClO,EAAK9P,YAAc,KAAOkmI,EAAgB,IAAM,IAAM5nH,EAAc,IACpExO,EAAKiB,MAAQ,GAAGtiB,KAAKw3I,sBAAsBx3I,KAAKg3I,cAChD31H,EAAK9Q,UAAUC,IAAI,kBAEfinI,GACFp2H,EAAK9Q,UAAUC,IAAI,sBAGrBof,EAAQve,YAAYgQ,GAGtB,YACE,OAAO,KAGF,UACL,MAAMlb,EAAQnG,KAAKmG,MACbmxI,EAAUt3I,KAAKm3I,aAEfO,GAAcvxI,GAAiD,IAAxCnG,KAAK2a,gBAAgBupH,QAAQ/9H,GACpDwxI,GAAgBL,GAAqD,IAA1Ct3I,KAAK2a,gBAAgBupH,QAAQoT,GAG9D,OAAOI,GAAcC,GAtFR,aAAd,c,0BAA8B,M,wDCD1B,MAAM,WAA6B,KAGxC,kBACE,OAAI33I,KAAKmG,MACAnG,KAAK2a,gBAAgBy3H,kBAAkBpyI,KAAKmG,OAG9C,IAPM,aAAd,c,0BAA8B,M,uCCH1B,MAAM,WAA4B,KAEvC,kBACE,OAAOnG,KAAK43I,kBAGd,kBACE,OAAO53I,KAAK43I,kBAGP,kBACL,OAAI53I,KAAKmG,MACAnG,KAAKU,KAAKU,EAAE,uBAEZpB,KAAKU,KAAKU,EAAE,sBAIhB,UAGL,OAAO,G,iBCrBJ,MAAM,WAAgC,KAA7C,c,oBAES,KAAAwW,KAAO,CACZ64E,KAAMzwF,KAAKU,KAAKU,EAAE,0BAGpB,YACE,OAAOpB,KAAKud,SAASvd,KAAKyG,MAG5B,YACE,OAAIzG,KAAKsX,UACAtX,KAAK4X,KAAK64E,KAEVzwF,KAAKmG,MAAMM,KAItB,WACE,OAAIzG,KAAKsX,UACA,KAGLtX,KAAKmG,MAAM+rE,QACNlyE,KAAKmG,MAAM+B,GAIblI,KAAKmG,MAAMZ,KAAKozD,MAAM,UAAU,GAGzC,kBAEE,MAAO,IAAK34D,KAAK8pB,QAAU9pB,KAAKsiB,QAG3B,UACL,OAAQtiB,KAAKmG,MAGf,uBACE,OAAO,G,2CClCJ,MAAM,WAAyC,GAAtD,c,oBACS,KAAAyR,KAAO,CACZigI,UAAW73I,KAAKU,KAAKU,EAAE,4CACvB02I,QAAS93I,KAAKU,KAAKU,EAAE,uBAOhB,OAAOwuB,EAAqBC,GACjC,IAAK7vB,KAAKmG,MACR,OAGF,MAAMogC,EAAOr7B,SAASoF,cAAc,KAKpC,GAJAi2B,EAAKh1B,YAAcse,EACnB0W,EAAKj1B,aAAa,QAAStR,KAAK4X,KAAKigI,WACrCtxG,EAAKj1B,aAAa,QAAS,uBAEvBtR,KAAKud,SAAS7B,QAAS,CACzB,MAAMq8H,EAAO/3I,KAAKud,SAASrV,GAAGma,WAC9BriB,KACGyD,aACAid,SACAxY,GAAGlI,KAAKud,SAAS7B,SACjBhX,MACArE,UAAWqb,IAEV,MAAMnW,EAAOotD,GAAI3yD,KAAK0a,WAAWs9H,uBAAuBt8H,EAAQ5G,aAC7DutB,OAAO,6EAA6E01G,kBACpF11H,WAEHkkB,EAAKhhC,KAAOA,IAIlBqqB,EAAQmE,UAAY,GACpBnE,EAAQve,YAAYk1B,GAEpBvmC,KAAKi4I,kBAAkBroH,GAGjB,kBAAkBA,GACxB,GAAI5vB,KAAKs5E,wBAA0Bt5E,KAAKud,SAASu6H,QAAS,CACxD,MAAMI,EAAiBhtI,SAASoF,cAAc,KAC9C4nI,EAAe5mI,aAAa,QAAS,kBACrC4mI,EAAe5mI,aAAa,OAAQ,IACpC4mI,EAAe5mI,aAAa,QAAStR,KAAK4X,KAAKkgI,SAE/CloH,EAAQve,YAAY6mI,GAEpBA,EAAe9sI,iBAAiB,QAASpL,KAAKm4I,kBAAkBrrI,KAAK9M,KAAMA,KAAKud,YAI5E,kBAAkB5X,GACxB3F,KAAKs5E,uBACF/2E,OAAOkd,OAAO,IAAIuP,MAASrpB,GAAI,GAC/B6U,MAAM,SArDI,aAAd,c,0BAAyB,O,kCACiB,aAA1C,YAAY,KAAwB,M,0BAA6B,O,8CACnD,aAAd,c,0BAA2B,O,oCCfvB,MAAM,WAAuB,KAApC,c,oBACS,KAAA5C,KAAO,CACZigI,UAAW73I,KAAKU,KAAKU,EAAE,2DAGzB,YACE,OAAIpB,KAAKud,SAASpb,MACT,KAGAnC,KAAKud,SAASvd,KAAKyG,MAIvB,OAAOmpB,EAAqBC,GAC5B7vB,KAAKmG,QAGVypB,EAAQre,YAAcse,GAGjB,UACL,OAAO,G,2CCpBJ,MAAM,WAAwC,KAE5C,OAAOD,EAAqBC,GACjC/vB,MAAMyhB,OAAOqO,EAASC,GAElB7vB,KAAKysC,iBACPzsC,KAAKo4I,aAAaxoH,GAItB,YACE,OAAI5vB,KAAKwC,OACAxC,KAAKijB,WAAajjB,KAAKijB,UAAUxc,KAGjC,KAIH,aAAampB,GACnB,GAAI5vB,KAAKijB,qBAAqB,KAAa,CACzC,MAAMo1H,EAAU,KAAa7xF,YAAYxmD,KAAKyG,KAAMzG,KAAKijB,UAAU/a,IACnE0nB,EAAQrf,UAAUC,IAAI6nI,KCxBrB,MAAM,WAAyB,GAEpC,sBACE,OAAO,G,iBCDJ,MAAM,WAAyB,KAGpC,YACE,OAAIr4I,KAAKwC,OACAxC,KAAKijB,WAAajjB,KAAKijB,UAAUxc,KAEjC,KAIJ,OAAOmpB,EAAqBC,GAC7B7vB,KAAKwvB,cAAgBK,EACvB7vB,KAAK+tE,YAAYn+C,GAEjB5vB,KAAKmuE,eAAe5sD,OAClBqO,EACA5vB,KAAKijB,YAhBI,aAAd,c,0BAA6B,O,sCCCzB,MAAM,WAAgC,KAGpC,OAAO2M,EAAqBC,GACjC,MAAMs8C,EAAQnsE,KAAKmG,MACnBypB,EAAQmE,UAAY,GACpBnE,EAAQte,aAAa,QAAS66D,EAAMrpD,KAAK,OAEpB,IAAjBqpD,EAAMllE,OACRjH,KAAK+tE,YAAYn+C,GAEjB5vB,KAAKguE,aAAahuE,KAAKijB,UAAW2M,GAQ5B,aAAahK,EAAuBgK,GAC5C,MAAMiR,EAAU31B,SAASwrB,yBACnB4hH,EAAeptI,SAASoF,cAAc,OAM5C,GALAgoI,EAAa/nI,UAAUC,IAAI,MAC3BqwB,EAAQxvB,YAAYinI,GAEpBt4I,KAAKu4I,qBAAqBD,EAAc1yH,GAEpCA,EAAO3e,OAAS,EAAG,CACrB,MAAMuxI,EAAOttI,SAASoF,cAAc,QACpCkoI,EAAKzkH,UAAY,OACjBukH,EAAajnI,YAAYmnI,GAEzB,MAAMrnI,EAAQnR,KAAKoiF,UAAUx8D,EAAO3e,OAAOob,WAAY,QAAS,cAChEwe,EAAQxvB,YAAYF,GAGtBye,EAAQve,YAAYwvB,GAIf,qBAAqBjR,EAAqBhK,GAC/C,MAAM08D,EAAkBj+E,EAAE+yC,KAAKxxB,EAAQ,GACvC5lB,KAAKmuE,eAAeC,eAAex+C,EAAS0yD,IAzC/B,aAAd,c,0BAA6B,O,iFCDzB,MAAM,WAAkC,GAA/C,c,oBAIU,KAAAm2D,eAAoC,IAAI,KAAmBz4I,KAAKyX,OAAQzX,KAAK06C,SAE9E,OAAO9qB,EAAqBC,GACjC,IAAK7vB,KAAKmG,MACR,OAEF,IAAIogC,EAAOvmC,KAAKy4I,eAAeC,WAC7B14I,KAAKmG,MACL0pB,EACA7vB,KAAKmG,OAGPypB,EAAQve,YAAYk1B,IAfP,aAAd,c,0BAAqB,kB,8BACP,aAAd,c,0BAAsB,O,+BCJlB,MAAM,WAAkC,KACtC,OAAO3W,EAAqBC,GACjC,MAAMlgB,EAAO3P,KAAKmG,MAEZwyI,EAAOztI,SAASoF,cAAc,QACpCqoI,EAAKpoI,UAAUC,IAAI,uBAAwBmlI,GAA0BhmI,IAErE,MAAMlJ,EAAOyE,SAASoF,cAAc,QAQpC,GAPA7J,EAAK8J,UAAUC,IAAI,uBAAyBmlI,GAA0BhmI,IACtElJ,EAAK8K,YAAcskI,GAAkBlmI,EAAM3P,KAAKU,MAEhDkvB,EAAQmE,UAAY,GACpBnE,EAAQve,YAAYsnI,GACpB/oH,EAAQve,YAAY5K,GAEhBzG,KAAKsZ,SAAU,CACjB,MAAMs/H,EAAW1tI,SAASoF,cAAc,QACxCsoI,EAASroI,UAAUC,IAAI,gCAAiC,OAAQ,iBAEhEof,EAAQve,YAAYunI,KCrBnB,MAAM,WAAqC,KAChD,YACE,IAAK54I,KAAKwC,OACR,OAAO,KAET,MAAMotB,EAAU5vB,KAAKud,SAASvd,KAAKyG,MAEnC,OAAOmpB,GAAWA,EAAQvW,KAAO,ICH9B,MAAM,WAAsC,GAAnD,c,oBAES,KAAAzB,KAAO,CACZigI,UAAW73I,KAAKU,KAAKU,EAAE,0DACvBqvF,KAAMzwF,KAAKU,KAAKU,EAAE,0BAMZ,KAAAq3I,eAAoC,IAAI,KAAmBz4I,KAAKyX,OAAQzX,KAAK06C,SAE9E,OAAO9qB,EAAqBC,GACjC,GAAI7vB,KAAKsX,UAEP,YADAsY,EAAQq7G,UAAYjrI,KAAKwvB,aAI3B,IAAI+W,EAAOvmC,KAAKy4I,eAAeC,WAC7B14I,KAAK8pB,KACL9pB,KAAK4X,KAAKigI,UACV73I,KAAK2vB,aAGHrN,EAAQpX,SAASoF,cAAc,QACnCgS,EAAM/Q,YAAc,IAAMlN,EAAEm6H,SAASx+H,KAAKsiB,MAAO,CAACrb,OAAQ,KAE1D2oB,EAAQmE,UAAY,GACpBnE,EAAQve,YAAYk1B,GACpB3W,EAAQve,YAAYiR,GAGtB,eACE,OAAO,EAGT,kBACE,MAAO,IAAMtiB,KAAK8pB,MA9BL,aAAd,c,0BAAqB,kB,8BACP,aAAd,c,0BAAsB,O,wGC4ElB,MAAM+uH,I,wBAAAA,K,qDAAAA,KAAuB,UA1CvB,CACT,CACElzF,QAAS,IACTG,WC9BC,SAAkCgzF,EAAmCC,GAC1E,MAAO,KACLD,EAAiBhxF,iBAAmB,OACpCgxF,EACG5wF,aAAa,EAAwB,OAAQ,CAAC,WAC9CA,aAAa,EAA2B,UAAW,CAAC,YACpDA,aAAa,EAA4B,WAAY,CAAC,aACtDA,aAAa,EAA0B,SAAU,CAAC,WACjD,SACA,OACA,OACA,UACA,sBACA,WACA,eACA,YACDA,aAAa,EAA+B,eAAgB,CAC3D,iBACA,WAEDA,aAAa,EAAyB,QAAS,CAAC,UAChDA,aAAa,EAA+B,cAAe,CAAC,gBAC5DA,aAAa,EAA2B,UAAW,CAAC,YACpDA,aAAa,EAAwB,OAAQ,CAAC,SAC9CA,aAAa,IAA+B,gBAAiB,CAAC,gBAC9DA,aAAa,GAAiC,iBAAkB,CAAC,kBACjEA,aAAa,IAAkC,WAAY,CAAC,YAE/D4wF,EACGE,qBAAqB,cAAe,GACf,OACA,CAAC,eAAgB,YAAa,UAAW,SAC9DA,qBAAqB,YAAa,GAAoC,UAAW,CAAC,YAClFA,qBAAqB,YAAa,GAAwC,cAAe,CAAC,gBAE7FD,EAAmCx5F,SAAS,KAA+B,WAC3Ew5F,EAAmCx5F,SAAS,KAAmC,iBDL7EyG,KAAM,CAAC,IAAkB4sF,GACzB/sF,OAAO,GAET,CACEF,QAAS,IACTG,WEhCC,SAAqCqpB,GAC1C,MAAO,KACLA,EAAoBrnB,iBAAmB,OACvCqnB,EACGjnB,aAAa,GAAkB,OAAQ,CAAC,WACxCA,aAAa,GAAmB,QAAS,CAAC,UAC1CA,aAAa,GAAqB,UAAW,CAAC,YAC9CA,aAAa,GAAiC,YAAa,CAC1D,SACA,aAEDA,aAAa,GAAkB,OAAQ,CAAC,SACxCA,aAAa,GAAsB,WAAY,CAC9C,UACA,sBACA,UACA,WACA,iBACDA,aAAa,KAAuB,YAAa,CAAC,mBAClDA,aAAa,GAAyB,QAAS,CAAC,WAChDA,aAAa,GAAyB,cAAe,CAAC,gBACtDA,aAAa,GAAsB,WAAY,CAAC,aAChDA,aAAa,KAAkB,OAAQ,CAAC,SACxCA,aAAa,GAAsB,WAAY,CAAC,aAChDA,aAAa,GAAqB,UAAW,CAAC,YAC9CA,aAAa,KAAsB,WAAY,CAAC,mBAChDA,aAAa,GAA+B,eAAgB,CAAC,gBAC7DA,aAAa,GAAgB,KAAM,CAAC,OACpCA,aAAa,GAA2B,iBAAkB,CAAC,kBAC3DA,aAAa,GAAkB,OAAQ,CAAC,SAE3CinB,EACK6pE,qBAAqB,cAAe,GAA2B,KAAM,CAAC,OACtEA,qBAAqB,cAAe,GAAkC,YAAa,CAAC,cACpFA,qBAAqB,cAAe,KAA0B,eAAgB,CAAC,iBAC/EA,qBAAqB,YAAa,GAA8B,UAAW,CAAC,YAC5EA,qBAAqB,YAAa,GAAyB,eAAgB,CAAC,kBFH/EhzF,KAAM,CAAC,KACPH,OAAO,IAEV,SA1BQ,CACP,KACA,KACA,KACA,U,kCGvCJ,8DAMO,MAAMozF,EAIX,YAAqB1uH,EACA/pB,GADA,KAAA+pB,cACA,KAAA/pB,aAHG,KAAA27C,SAAmB,EAM3C,kBACEn8C,KAAK4wC,cAGC,cACN,GAAI5wC,KAAKolF,UAAW,CAClB,MAAMx1D,EAAU/oB,OAAO7G,KAAKQ,WAAWsG,eACvC9G,KAAKuqB,YAAYkT,aAAa7N,EAAS5vB,KAAKm8C,Y,sCAfrC88F,GAAc,sB,uBAAdA,EAAc,8G,oCCN3B,kDAEO,MAAMC,UAAiC,IAIrC,SAAS/yI,GACd,OAAOnG,KAAK6iE,aAAa18D,M,oIC1BtB,MAAM,UAA6B,IAA1C,c,oBAEkB,KAAA2O,WAAa,sBACrB,KAAAqkI,eAAiB,IAAI,IAAmBn5I,KAAK+I,SAASrE,IAAI,gBAAe1E,KAAK+I,SAASrE,IAAI,MAC3F,KAAAkT,KAAO,CACblF,OAAQ1S,KAAKU,KAAKU,EAAE,2BAGf,eAEL,IAAIg4I,EAAcp5I,KAAKm5I,eAAeE,cACpCr5I,KAAKgJ,YAAYd,GACjBlI,KAAK4X,KAAKlF,OACV,IAMF,OAHA0mI,EAAY7oI,UAAUC,IAlBU,yBAkBgB,IAAmB,qBACnE4oI,EAAY/nI,YAAY,YAAc,OAAQ,eAEvC+nI,GCrBJ,MAAM,UAAiC,IAA9C,c,oBAEkB,KAAAtkI,WAAa,2BAErB,KAAA8C,KAAO,CACbigI,UAAW73I,KAAKU,KAAKU,EAAE,+BAGlB,eACL,IAAIk4I,EAAcpuI,SAASoF,cAAc,KAMzC,OALAgpI,EAAY/zI,KAAO,IACnB+zI,EAAY/oI,UAAUC,IAAI,IAA0B,KACpD8oI,EAAYh3H,MAAQtiB,KAAK4X,KAAKigI,UAC9ByB,EAAYjoI,YAAY,YAAc,OAAQ,8BAEvCioI,G,gBCbJ,MAAM,EAEX,YAA6BvwI,GAAA,KAAAA,WAMrB,KAAAwwE,QAAiC,CACvC,CAACxwE,EAAUC,IAAgB,IAAI,EAAqBD,EAAUC,GAC9D,CAACD,EAAUC,IAAgB,IAAI,EAAyBD,EAAUC,IAM7D,cAAcuwE,GACnBv5E,KAAKu5E,QAAUA,EAOV,OAAOvwE,GACZ,IAAIuwI,EAAQv5I,KAAKu5E,QAAQrqE,IAAKyjG,GAAYA,EAAQ3yG,KAAK+I,SAAUC,GAAawwI,gBAC9E,OAAOn1I,EAAEwmE,QAAQ0uE,I,sCA1BR,GAAqB,Y,yBAArB,EAAqB,QAArB,EAAqB,a,oFCuB3B,MAAME,EAIX,eAEA,cACE,OAAQz5I,KAAKyG,KAGR,WAAW2/C,EAA4BloC,GACvCle,KAAKsX,SAAY8uC,IAItBpmD,KAAKyG,KAAO2/C,EACZpmD,KAAKke,OAASA,I,sCAhBLu7H,I,yBAAAA,EAAiB,QAAjBA,EAAiB,a,kCCJ9B,sI,wBCjBI,iB,oBAAmD,mC,yCD6BhD,MAAMC,UAAyC,IAOpD,YAAqBh5I,EACCb,EACAkzC,EACA9vC,GACpBnD,MAAMY,GAJa,KAAAA,OACC,KAAAb,QACA,KAAAkzC,mBACA,KAAA9vC,iBARf,KAAAgD,aAAsB,EAEtB,KAAAs4C,SAAkB,qCAClB,KAAA2P,UAAmB,cAS1B,WACEluD,KAAK25I,gBAGP,eACE,MAAO,mBAGT,cACE,MAAO,oBAGT,YACE,OAAO35I,KAAKy1I,OAASz1I,KAAK4X,KAAK0qB,MAGjC,kBACE,OAAOtiC,KAAKi0B,MAGP,cAAcjsB,GACnBhI,KAAKs0C,mBAGA,mBACLt0C,KAAK+yC,iBAAiBuB,mBAGhB,gBACNt0C,KAAKiD,eACF6lF,QACA3oF,KACCH,KAAKI,kBAENC,UAAU,KACTL,KAAKi0B,MAAQj0B,KAAKiD,eAAe22I,wBAAwB3yI,OACzDjH,KAAKiG,aAAc,EACnBjG,KAAKH,MAAMS,kBAGfN,KAAK+yC,iBACF/6B,aAAa,YAAmBhY,OAChCK,UAAU,KACTL,KAAKwwC,SAAWxwC,KAAK+yC,iBAAiBxuB,QACtCvkB,KAAKH,MAAMS,mB,sCA1DNo5I,GAAgC,0C,uBAAhCA,EAAgC,wRCxC7C,mBAMQ,iCAAS,EAAA/qF,cAAA,MAEf,oBACA,iBACE,QACA,uBACF,OACF,Q,MARQ,4BAAqB,gCAJrB,sBAAoB,wBAApB,CAAoB,gBAApB,CAAoB,sBAOjB,4DAEP,mCAC+B,qC,gGCqBnC,8DAKO,MAAMkrF,EAEX,YAA0Bz8B,GAAA,KAAAA,oBAInB,iBAAiBl/F,GACtB,IAAKA,EACH,OAGF,IAAI0C,EAAiB,GAcrB,OAbAvc,EAAEC,KAAK4Z,EAAQ,CAAC/X,EAAOxE,KAChBwE,IACA+W,MAAM2c,QAAQ1zB,KAAQA,EAAQ,CAACA,IAEpC9B,EAAEC,KAAK6B,EAAQy3E,IACH,OAANA,GAA2B,iBAANA,IACvBA,EAAIn4D,KAAKC,UAAUk4D,IAErBh9D,EAAM1f,KAAKqyE,mBAAmB5xE,GAAO,IACnC4xE,mBAAmBqK,SAIlBh9D,EAAMkC,KAAK,KAGb,sBAAsBjf,EAAqBopD,EAAiB,IACjE,IAAI6sF,EAAiB,GAerB,OAbAA,EAAa95I,KAAK+5I,cAAcD,EAAYj2I,GAC5Ci2I,EAAa95I,KAAKg6I,WAAWF,EAAYj2I,GACzCi2I,EAAa95I,KAAKi6I,sBAAsBH,EAAYj2I,GACpDi2I,EAAa95I,KAAKk6I,uBAAuBJ,EAAYj2I,GACrDi2I,EAAa95I,KAAKm6I,4BAA4BL,EAAYj2I,GAC1Di2I,EAAWM,KAAOv2I,EAAMgiB,gBACxBi0H,EAAWO,EAAIh2I,EAAEK,IAAIb,EAAMqB,QAAS,KAAM,IAC1C40I,EAAa95I,KAAKs6I,aAAaR,EAAYj2I,GAC3Ci2I,EAAa95I,KAAKu6I,cAAcT,EAAYj2I,EAAMmL,SAClD8qI,EAAW/S,GAAK95E,EAAW3T,KAC3BwgG,EAAWhT,GAAK75E,EAAW1T,QAC3BugG,EAAWU,GAAK32I,EAAMsB,sBAEfsgB,KAAKC,UAAUo0H,GAGhB,cAAcA,EAAgBj2I,GAKpC,OAJAi2I,EAAWxvE,EAAIzmE,EAAMkB,QAAQmK,KAAI,SAAUkB,GACzC,OAAOA,EAAOlI,MAGT4xI,EAGD,WAAWA,EAAgBj2I,GAIjC,OAHMA,EAAMw2B,OACVy/G,EAAWlqB,EAAI/rH,EAAMw2B,MAEhBy/G,EAGD,uBAAuBA,EAAgBj2I,GAI7C,OAHIA,EAAMsT,mBAAqBtT,EAAM6uC,WAAwC,WAA3B7uC,EAAMsT,oBACtD2iI,EAAWW,GAAK52I,EAAMsT,kBAEjB2iI,EAGD,4BAA4BA,EAAgBj2I,GAMlD,MAL+B,WAA3BA,EAAMsT,kBACJ+F,MAAM2c,QAAQh2B,EAAMuT,wBAA0BvT,EAAMuT,sBAAsBnQ,OAAS,IACrF6yI,EAAWY,IAAM72I,EAAMuT,sBAAsBlI,IAAI+C,GAAMA,EAAG/J,KAGvD4xI,EAGD,aAAaA,EAAgBj2I,GASnC,OARIA,EAAMoB,SACR60I,EAAW14I,EAAIyC,EACZoB,OACAiK,KAAI,SAAUirB,GACb,OAAOA,EAAKjyB,GAAI2Y,QAAQ,IAAK,QAE9BiC,QAEEg3H,EAGF,cAAcA,EAAgB9qI,GAiBnC,OAhBIA,GAAWA,EAAQ/H,OAAS,EAC9B6yI,EAAWtlG,EAAIxlC,EACZE,IAAK3D,IAKG,CACL4oD,EALO5oD,EAAOrD,GAMdoH,EAJa/D,EAAOoa,SAASzd,GAK7B01E,EAAGv5E,EAAE6K,IAAI3D,EAAOqa,OAASg4D,GAAM59E,KAAK26I,wBAAwB/8D,OAIlEk8D,EAAWtlG,EAAI,GAEVslG,EAGD,sBAAsBA,EAAgBj2I,GAY5C,OAXMA,EAAMmmC,iBACV8vG,EAAWc,GAAK/2I,EAAMmmC,gBAEjB3lC,EAAEiT,QAAQzT,EAAM27E,kBACnBs6D,EAAWe,IAAMp1H,KAAKC,UAAU7hB,EAAM27E,iBAGxCs6D,EAAWgB,IAAMj3I,EAAMy7E,mBAEvBw6D,EAAWc,IAAK,EAEXd,EAIF,8BAA8BiB,GACnC,IAAI/nF,EAAgB,CAClBzY,SAAUv6C,KAAKo9G,kBAAkB49B,cAGnC,IAAKD,EACH,OAAO/nF,EAGT,IAAIyf,EAAahtD,KAAKvG,MAAM67H,GAwC5B,GAtCItoE,EAAWnI,IACbtX,EAAU,aAAeyf,EAAWnI,EAAEp7D,IAAKkB,GAAeA,IAEtDqiE,EAAWm9C,IACf58D,EAAUioF,SAAWxoE,EAAWm9C,GAGlC58D,EAAUhpB,gBAAkByoC,EAAWmoE,GAEjCnoE,EAAWmoE,KACTnoE,EAAWooE,MACf7nF,EAAUwsB,eAAiB/M,EAAWooE,KAGpCpoE,EAAWqoE,MACb9nF,EAAUssB,kBAAoB7M,EAAWqoE,MAIzCroE,EAAW+nE,KACbxnF,EAAU7tD,sBAAwBstE,EAAW+nE,IAG3C/nE,EAAWgoE,KACbznF,EAAU77C,iBAAmBs7D,EAAWgoE,IAGtChoE,EAAWioE,MACb1nF,EAAU,2BAA6Byf,EAAWioE,IAAIxrI,IAAKkB,GAAeA,KAGtD,IAAlBqiE,EAAW2nE,KAAkC,IAAlB3nE,EAAW2nE,KACxCpnF,EAAUntC,gBAAkB4sD,EAAW2nE,IAGzCpnF,EAAU9tD,QAAUb,EAAEK,IAAI+tE,EAAY,IAAK,IAGvCA,EAAWj+B,EAAG,CAChB,IAAIxlC,EAAUyjE,EAAWj+B,EAAEtlC,KAAI,SAAUgsI,GACvC,IAAIjzF,EAAa,CACftiC,SAAU68B,mBAAmB04F,EAAU5rI,IAEzC,GAAI4rI,EAAUt9D,EAAG,CAGf,IAAIu9D,EAAKj+H,MAAM2c,QAAQqhH,EAAUt9D,GAAKs9D,EAAUt9D,EAAI,CAACs9D,EAAUt9D,GAC/Dv5E,EAAEmqD,OAAOvG,EAAY,CAAEriC,OAAQu1H,IAEjC,MAAMC,EAAiB,GAGvB,OAFAA,EAAWF,EAAU/mF,GAAKlM,EAEnBmzF,KAGTpoF,EAAUhkD,QAAUyW,KAAKC,UAAU1W,GAgBrC,OAZIyjE,EAAWrxE,IACb4xD,EAAU/tD,OAASwgB,KAAKC,UAAU+sD,EAAWrxE,EAAEiX,MAAM,KAAKnJ,IAAKirB,GAAaA,EAAK9hB,MAAM,QAIrFo6D,EAAWs0D,KACb/zE,EAAUta,OAAS+5B,EAAWs0D,IAE5Bt0D,EAAWq0D,KACb9zE,EAAUzY,SAAWk4B,EAAWq0D,IAG3B9zE,EAGF,iCAAiCnvD,EAAqBqwD,EAAuB,GAAImnF,EAAiB,IACvG,IAAIroF,EAAgB,GAgCpB,OA9BAA,EAAU,aAAehzD,KAAKs7I,mCAAmCz3I,GACjEmvD,EAAUioF,SAAWp3I,EAAMw2B,KAC3B24B,EAAUhpB,kBAAoBnmC,EAAMmmC,gBAE9BnmC,EAAMmmC,kBACVgpB,EAAUssB,kBAAoBz7E,EAAMy7E,kBACpCtsB,EAAUwsB,eAAiB/5D,KAAKC,UAAU7hB,EAAM27E,iBAG9C37E,EAAMsT,mBACR67C,EAAU77C,iBAAmBtT,EAAMsT,kBAGjCtT,EAAMuT,uBAAoD,WAA3BvT,EAAMsT,mBACvC67C,EAAU,2BAA6BnvD,EAAMuT,sBAAsBlI,IAAI+C,GAAMA,EAAG1M,OAG9E1B,EAAMsB,wBACR6tD,EAAU7tD,sBAAwBtB,EAAMsB,uBAG1C6tD,EAAUntC,kBAAoBhiB,EAAMgiB,gBACpCmtC,EAAU9tD,QAAUb,EAAEK,IAAIb,EAAMqB,QAAS,KAAM,IAG/C8tD,EAAUhkD,QAAUhP,KAAKu7I,wBAAwB13I,EAAMmL,QAASqsI,GAGhEroF,EAAU/tD,OAASjF,KAAKw7I,0BAA0B33I,GAE3CQ,EAAEmqD,OAAO0F,EAAkBlB,GAG7B,wBAAwB7sD,GAC7B,MAAsB,kBAAZ,EACDA,EAAQ,IAAM,IAGlBA,EAEMA,EAAM+B,GACR/B,EAAM+B,GAAGma,WACPlc,EAAMxB,MACRwB,EAAMxB,MAAM0T,MAAM,KAAK8Q,MAAM9G,WAE7Blc,EAAMkc,WANN,GAUH,mCAAmCxe,GACzC,OAAIA,EAAMkB,QACDlB,EAAMkB,QAAQmK,IAAKkB,GAAeA,EAAOlI,IAAMkI,EAAOkL,YACpDzX,EAAMsqB,OAAOppB,QACflB,EAAMsqB,OAAOppB,QAAQmK,IAAKkB,IAC/B,IAAIlI,EAAKkI,EAAO7K,KAEhB,OAAOvF,KAAKy7I,WAAWvzI,UAJpB,EASF,kBAAkB8G,EAAuC0sI,EAAe,IAkB7E,OAjBiB1sI,EAAQE,IAAK3D,IAC5B,IAAIrD,EAAKlI,KAAK09H,6BAA6BnyH,GACvCoa,EAAW3lB,KAAK27I,+BAA+BpwI,GAC/Cqa,EAAS5lB,KAAK47I,2BAA2BrwI,GAAQ2D,IAAI/I,IACvD9B,EAAEC,KAAKo3I,EAAc,CAAC95I,EAAYD,KAChCwE,EAAQA,EAAM0a,QAAQ,IAAIlf,KAAQC,KAG7BuE,IAGT,MAAM01I,EAAyB,GAG/B,OAFAA,EAAW3zI,GAAM,CAAEyd,SAAUA,EAA4BC,OAAQA,GAE1Di2H,IAMJ,wBAAwBtwI,EAAsC8vI,EAAa,IAChF,OAAO51H,KAAKC,UAAU1lB,KAAK29H,kBAAkBpyH,EAAQ8vI,IAGhD,6BAA6B9vI,GAClC,IAAIhG,EAAOgG,EAAOA,OAASA,EAAOA,OAAO5G,MAAQ4G,EAAO4iB,OAAO5iB,OAAOhG,KAEtE,OAAOvF,KAAKy7I,WAAWl2I,GAGjB,+BAA+BgG,GACrC,GAAIA,EAAOoa,SACT,OAAOpa,EAAOoa,SAASzd,IAAMqD,EAAOoa,SAASrK,WACxC,CACL,IAAI/V,EAAOgG,EAAO4iB,OAAOxI,SAASpgB,KAElC,OAAOvF,KAAKy7I,WAAWl2I,IAInB,2BAA2BgG,GACjC,OAAIA,EAAOqa,OACFvhB,EAAE6K,IAAI3D,EAAOqa,OAASg4D,GAAU59E,KAAK26I,wBAAwB/8D,IAE7Dv5E,EAAE6K,IAAI3D,EAAO4iB,OAAOvI,OAASg4D,GAAU59E,KAAKy7I,WAAW79D,EAAEr4E,OAK5D,0BAA0B1B,GAChC,IACIi4I,GADUj4I,EAAMoB,OAASpB,EAAMoB,OAASpB,EAAMsqB,OAAOlpB,QACjCiK,IAAKirB,IAC3B,GAAIA,EAAKjyB,GACP,OAAOiyB,EAAKjyB,GACP,CACL,IAAI3C,EAAO40B,EAAK50B,KAIhB,OAFSvF,KAAKy7I,WAAWl2I,MAM7B,OAAOkgB,KAAKC,UAAUo2H,EAAU5sI,IAAKhH,GAAcA,EAAGmQ,MAAM,OAGtD,WAAW9S,GACjB,IAAI2C,EAAK3C,EAAK+0H,UAAU/0H,EAAKqd,YAAY,KAAO,EAAGrd,EAAK0B,QAExD,OAAOu7C,mBAAmBt6C,I,sCAzVjB2xI,GAAsB,Y,yBAAtBA,EAAsB,QAAtBA,EAAsB,qBADT,U,oICKnB,MAAMkC,EAMX,YAAqBhzI,GAAA,KAAAA,WAGb,eAAeizI,EAAc99H,GACnC,OAAOle,KAAKyX,OAAOswB,GAAGi0G,EAAO99H,GAGvB,qBAAqB+9H,EAA6BvuI,GACpDuuI,EACFj8I,KAAKk8I,eAAexuI,EAAW1N,KAAKm8I,UAAUj+H,QAE9Cle,KAAKk8I,eAAexuI,EAAY1N,KAAK06C,QAAQ0hG,uBAAwBp8I,KAAKm8I,UAAUj+H,QAIhF,0BACFle,KAAKm8I,UAAUztI,OACjB1O,KAAKk8I,eAAel8I,KAAKm8I,UAAU11I,KAAMzG,KAAKm8I,UAAUj+H,QAAQzO,KAAK,KAAQzP,KAAKyX,OAAOuwB,WAGzFhoC,KAAKk8I,eAAel8I,KAAKm8I,UAAU11I,KAAMzG,KAAKm8I,UAAUj+H,QAIpD,sBAAsB+9H,EAA6BvuI,GACrD1N,KAAK06C,QAAQ2hG,eAAer8I,KAAKm8I,UAAUztI,QAC7C1O,KAAKs8I,qBAAqBL,EAAqBvuI,GAE/C1N,KAAKu8I,0BAIF,OAAON,GAA8B,G,MAG1C,MAAMvuI,GAA0B,QAAd,EAAA1N,KAAKm8I,iBAAS,eAAEzuI,YAAa1N,KAAKyX,OAAOxX,QAAQkO,KAAKT,WAAa,kCAEhF1N,KAAKm8I,WAAazuI,EAAUkL,SAAS,QAAW5Y,KAAKyX,OAAOuwB,UAE1DhoC,KAAKm8I,WAAan8I,KAAKm8I,UAAU11I,KAAKmS,SAAS,OAClD5Y,KAAKyX,OAAOswB,GAAGr6B,EAAW1N,KAAKyX,OAAOyG,QAEtCle,KAAKw8I,sBAAsBP,EAAqBvuI,GAK/C,gBACL,MAAMA,EAAY1N,KAAKyX,OAAOxX,QAAQkO,KAAKT,WAAa,iCACxD1N,KAAKyX,OAAOswB,GAAGr6B,EAAW1N,KAAKyX,OAAOyG,QAGjC,KAAKvG,GACV,MAAMgjG,EAAYhjG,EAAW4D,OACvBm/F,EAAU/iG,EAAWyb,KAG3B,GAAIunF,EAAUl0G,MACZk0G,EAAUxsG,MACVusG,EAAQvsG,MACRwsG,EAAUxsG,KAAKO,SAAWgsG,EAAQvsG,KAAKO,OAAQ,CAC/C,MAAM+tI,EAAiB,OAAH,UAAQ9kI,EAAWuG,OAAO,SAC9Cle,KAAKm8I,UAAY,CAAE11I,KAAMk0G,EAAUl0G,KAChByX,OAAQu+H,EACR/tI,OAAQisG,EAAUxsG,KAAKO,OACvBhB,UAAWitG,EAAUxsG,KAAKT,YAIjD,cAAqBsuI,GACnBh8I,KAAK08I,WAAaV,EAGpB,gBACE,OAAOh8I,KAAK08I,Y,sCAhFHX,GAAkB,Y,yBAAlBA,EAAkB,QAAlBA,EAAkB,qBADL,SAET,aAAd,c,0BAA6B,iB,6BACf,aAAd,c,0BAA8B,M,mHCvC1B,MAAMY,EAOX,YAAqB/5I,EACAmG,GADA,KAAAnG,aACA,KAAAmG,WAOrB,cACE,OAAO,EAMF,WAAWi4C,IAMX,UAAUh4C,GACf,OAAO,EAWF,WAAWA,EAAiCiJ,GACjD,OAAO1C,QAAQC,aAAQ9D,GAQlB,oBAAoBkxI,EAA2BC,GAAwB,GAM5E,OALIA,EACFD,EAAcrsI,UAAUkiB,OAAO,YAE/BmqH,EAAcrsI,UAAUC,IAAI,aAEvB,G,wFC/CJ,MAAM,UAAmCmsI,EAM9C,cACE,OAAO38I,KAAKmD,mBAAmBy5B,UAM1B,UAAU5zB,GACf,QAASA,EAAYqc,aAGhB,WAAWrc,EAAiCiJ,GACjD,OAAOjS,KAAK88I,gBAAgB7qI,GAAIxC,KAAMsW,GAC7B/lB,KAAK+8I,yBAAyB13H,aAAarc,EAAa+c,IAQ3D,gBAAgB9T,GACtB,IAAIyf,EAAWzf,EAAG0f,uBACdvpB,EAAO6J,EAAG+qI,mBACVtuI,EAAS,KAEb,GAAiB,OAAbgjB,GAAqB1xB,KAAKi9I,iBAAiBhrI,EAAIyf,EAAUtpB,GAAO,CAKlE,GAFsBspB,EAAS3P,UAAU3E,QAAQ,gBAAuB,EAErD,CACjB,IAAI8/H,EAAel9I,KAAKm9I,oBAAoBzrH,GAC5C,GAAoB,MAAhBwrH,EACF,OAAO3tI,QAAQC,QAAQ,MAEzBkiB,EAAWwrH,EAGb,IAAIE,EAAgB1rH,EAAyBjhB,QAAQyT,cAErD,GAAIlkB,KAAKq9I,eAAe3rH,EAAU0rH,GAAe,CAG/C,GAFkC,YAAuBh1I,GAGvD,OAAOpI,KAAK88I,gBAAgBprH,GAG9BhjB,EAAS0uI,OAIT1uI,EAAS1O,KAAKs9I,eAAeF,GAIjC,OAAO7tI,QAAQC,QAAQd,GAGjB,oBAAoBuD,GAC1B,IAAIyf,EAAWzf,EAAG0f,uBAClB,KAAoB,OAAbD,GAAmB,CACxB,GAAIA,EAAS3P,UAAU3E,QAAQ,eAAsB,EACnD,OAAOsU,EAETA,EAAWA,EAASC,uBAGtB,OAAO,KAGD,iBAAiB/B,EAAiB8B,EAAkBtpB,GAC1D,MAAMm1I,EAAU7rH,EAAS3P,UAAU3E,QAAQ,YAAoB,MAAQ,EACjEogI,EAAS9rH,EAAS3P,UAAU3E,QAAQ,YAAmB,MAAQ,EACrE,IAAIqgI,EAEJ,GAAIF,GAAWC,EAAQ,CACrB,MAAME,EAAgBxgI,MAAM3B,KAAKqU,EAAQrf,WAAWhF,OAAOgmB,GAAaA,EAAU3Y,SAAS,wBAA0B,GAC/G+kI,EAAiBzgI,MAAM3B,KAAKmW,EAASnhB,WAAWhF,OAAOgmB,GAAaA,EAAU3Y,SAAS,wBAA0B,GACjHglI,EAAax1I,GAAQ8U,MAAM3B,KAAKnT,EAAKmI,WAAWhF,OAAOgmB,GAAaA,EAAU3Y,SAAS,wBAA0B,GACjHwkI,EAAgB1rH,EAAyBjhB,QAAQyT,cACjD25H,GAAwBD,EAAW3oG,KAAK7b,GAAaukH,EAAe/kI,SAASwgB,MAAgBwkH,EAAWhlI,SAAS,YAAoBwkI,IACrIU,EAA+BJ,EAAczoG,KAAK8oG,GAAgBJ,EAAe/kI,SAASmlI,KAC3DL,EAAc9kI,SAAS,YAAoBwkI,IAEhFK,EAAuBI,IAAyBC,EAGlD,OAAQL,GAAwBF,GAAWC,EAGrC,eAAe9rH,EAAkB0rH,GACvC,OAAO1rH,EAASnhB,UAAUlF,SAAS,YAAmB+xI,IAGhD,eAAetzH,GACrB,OAAO9pB,KACJyD,aACAmC,cACAsC,GAAG4hB,GACHplB,MACAmoB,YACApd,KAAM9J,I,MACL,OAAO4J,QAAQC,SAAiB,QAAT,EAAA7J,EAAG+I,cAAM,eAAExG,KAAM,SA3G/B,aAAd,c,0BAAyC,M,yCAC3B,aAAd,c,0BAA+C,M,+CACjC,aAAd,c,0BAAmC,M,2HCH/B,MAAM,UAAiCy0I,EAQ5C,cACE,OAAO38I,KAAK8C,eAAe85B,UAMtB,UAAU5zB,GACf,MAAMia,EAAYjjB,KAAKg+I,iBACvB,OAAqB,OAAd/6H,GAAsBjjB,KAAKqV,YAAY/B,GAAGtK,GAAa0yC,oBAAoBz4B,GAG7E,WAAWja,EAAiCiJ,GACjD,MAAMya,EAAY1sB,KAAK4V,WAAWE,UAAU9M,GACtCi1I,EAAej+I,KAAKk+I,iBAAiBjsI,GAG3C,OADAya,EAAUjqB,kBAAkBzC,KAAKg+I,kBAAqBC,EAC/Cj+I,KAAK4V,WACTwE,KAAKsS,GACLjd,KAAMk6E,GAAU3pF,KAAKmsB,UAAUjrB,KAAKyoF,EAAMpsE,SAAU,CAACiwB,UAAW,aAChEhzB,MAAMlO,GAAKtM,KAAKoqC,gBAAgByD,eAAevhC,EAAGtD,IAG/C,iBAAiBiJ,GACvB,MAAMksI,EAAc,YAA4BlsI,EAAI,IAAI,KAClD0mD,EAAQ34D,KAAK+F,OAAOyF,KAAKqJ,GAAS,YAAgBA,KAAWspI,EAAY1tI,QAAQ4D,iBAEvF,IAAKskD,EACH,OAAO,KAGT,GAAIA,EAAMxqC,QAAUwqC,EAAMxqC,OAAO4L,UAAW,CAC1C,MAAMnL,EAAQ+pC,EAAMxqC,OAAO4L,UAG3B,OAAwB,IAAjBnL,EAAM3nB,OAAe2nB,EAAM,GAAKA,EAEvC,OAAO+pC,EAAMxyD,MAOjB,uBACE,MAAMlG,EAAUD,KAAK8C,eAAe7C,QACpC,OAAOA,EAAUA,EAAQiI,GAAK,KAMhC,aACE,OAAOlI,KAAK4C,WAAWmD,OAAOI,OAAS,IA3D1B,aAAd,c,0BAA6B,M,qCACf,aAAd,c,0BAAyB,M,iCACX,aAAd,c,0BAAwB,M,gCACV,aAAd,c,0BAA8B,M,sCAChB,aAAd,c,0BAA0B,M,kDCRtB,MAAM,EADb,cAGU,KAAAo5C,SAAqC,CAC3C,EACA,GAGK,IAAIzzB,GACT9rB,KAAKu/C,SAASr+C,KAAK4qB,GAGd,IAAI/iB,GACT,MAAMnG,EAAamG,EAASrE,IAAI,KAMhC,OAJc1E,KAAKu/C,SAChBrwC,IAAIg0C,GAAO,IAAIA,EAAItgD,EAAYmG,IAC/ByC,KAAKi6D,GAAYA,EAAS24E,UAEb,IAAIzB,EAAuB/5I,EAAYmG,I,sCAlB9C,I,yBAAA,EAA+B,QAA/B,EAA+B,a,kCCXrC,IAAUs1I,EAAjB,2CAAiBA,GAcC,EAAAC,UAAhB,SAA0Bp8H,GACxB,OAAO,IAA0B,iBAAmBA,GAfxD,CAAiBm8H,MAAY,M,4LCUtB,MAAME,EAAc,oBACdC,EAAoB,2BAE1B,MAAMC,EAMX,YAAmB11I,GAAA,KAAAA,WAFZ,KAAAu2C,cAAgB,IAAI,IAAqBt/C,KAAK+I,SAAU,SAKxD,MAAMC,EAAiCoH,GAC5C,MAAMC,EAAKnF,SAASoF,cAAc,MAC5B2S,EAAY7S,EAAOlI,GACzBmI,EAAGE,UAAUC,IAAI+tI,EAAat7H,GAEZ,YAAdA,GACF5S,EAAGE,UAAUC,IAAI,QAGnB,MAAMhO,EAASxC,KAAKqV,YAAY/B,GAAGtK,GAAayyC,WAAWx4B,GACvDzgB,GAA0B,SAAhBA,EAAOsQ,MACnBzC,EAAGE,UAAUC,IAAI,oBAGnB,MAAMyQ,EAAY/V,SAASoF,cAAc,QACzC2Q,EAAU1Q,UAAUC,IAAIguI,EAAmB,IAAyBv7H,GACpE,MAAMy7H,EAAiB1+I,KAAKs/C,cAAc/9B,OAAOvY,EAAaia,EAAW,MAKzE,OAHAhC,EAAU5P,YAAYqtI,GACtBruI,EAAGgB,YAAY4P,GAER5Q,EAGF,QAAQ4Q,EAAuBjY,EAAiCia,GACrE,MAAMy7H,EAAiB1+I,KAAKs/C,cAAc/9B,OAAOvY,EAAaia,EAAW,MAEzEhC,EAAU8S,UAAY,GACtB9S,EAAU5P,YAAYqtI,IAnCS,aAAhC,YAAY,K,0BAAgC,M,uECc/C,sIAWO,MAAMC,UAAmC,IAS9C,YAAqBj+I,GACnBZ,QADmB,KAAAY,OARL,KAAAqtC,aAAsB,EAErB,KAAAC,cAAgB,IAAI,IAAmD,YAAmBhuC,OAElG,KAAA4X,KAAO,CACdgnI,WAAY5+I,KAAKU,KAAKU,EAAE,4CAO1B,YACE,OAAOpB,KAAKuL,OAAOqa,OAAO,GAG5B,UAAiBhkB,GACXA,EAAIqF,OACNjH,KAAKuL,OAAOqa,OAAO,GAAKhkB,EAExB5B,KAAKuL,OAAOqa,OAAO3e,OAAS,EAE9BjH,KAAKguC,cAAcxlC,KAAKxI,KAAKuL,S,sCAvBpBozI,GAA0B,Y,uBAA1BA,EAA0B,+WCxCvC,gBACE,kBAAO,sDAAP,OAOA,kBAIF,Q,MAZK,0CAKI,8CACA,0BAAAl4I,KAAA,KALA,wBAAmB,uBAOnB,+CACA,wC,kFCTT,sHAMO,SAASo4I,EAAc39G,GACvB,IAAYmsB,YACfnsB,IAQG,SAAS49G,EAAStkG,KAAmB4jD,GAC1CygD,EAAc,IAAMjhI,QAAQyuD,IAAI,WAAW7xB,KAAc4jD,IAGpD,SAAS2gD,EAAWC,EAAY99G,GACrC,GAAK,IAAYmsB,WAUf,OAAOnsB,IATP,IAAIxB,EAAKC,YAAY/Y,MAEjB9iB,EAAUo9B,IAEVrB,EAAKF,YAAY/Y,MAGrB,OAFAhJ,QAAQyuD,IAAI,KAAK2yE,kBAAqBn/G,EAAKH,kBAAqB,kBAEzD57B,I,kCCDX,0EAOO,MAAMm7I,UAAuC,IAElD,YAAqBl2I,EACAtF,GACnB3D,MAAMiJ,GAFa,KAAAA,WACA,KAAAtF,eAId,SAAS8Z,EAA8B4+D,GAAmB,GAC/D,IAAI3hC,EAAc,CAChBA,QAASx6C,KAAKU,KAAKU,EAAE,yBAA2B+6E,EAAW,SAAW,YAGxEn8E,KAAKk/I,6BAA6B1kG,EAASj9B,GAE3Cvd,KAAKg/C,qBAAqBkM,WAAW1Q,GAG7B,gBAAgBiiC,EAAmBl/D,GAC3C,MAAsC,qDAAlCk/D,EAAcp6B,iBAChBriD,KAAKg/C,qBAAqB+a,SAAS,CACjCvf,QAASiiC,EAAcjiC,QACvB1nC,KAAM,QACNyzB,KAAM,CACJ3uB,KAAM5X,KAAKU,KAAKU,EAAE,wCAClB2F,OAAQ,IAAM/G,KAAKyD,aAAamC,cAAcsC,GAAGqV,GAAUigB,cAIxD,GAGF19B,MAAM68E,gBAAgBF,EAAel/D,GAGtC,6BAA6Bi9B,EAAuBj9B,GAErDvd,KAAKyX,OAAOmB,SAAS,wBACxB4hC,EAAQjU,KAAO,CACbx/B,OAAQ,IAAM/G,KAAKyX,OAAOswB,GAAG,8BAA+B,CAAC7jB,cAAe3G,EAASrV,KACrF0P,KAAM5X,KAAKU,KAAKU,EAAE,6D,sCAvCb69I,GAA8B,sB,yBAA9BA,EAA8B,QAA9BA,EAA8B,a,kCCN3C,oFAEO,MAAME,EAAoB,oDACpBC,EAAqB,qDAOO,IASC,K,kCCpB1C,0H,yBC5BA,gBAEE,gBACE,yBACF,OACF,Q,oBAFkB,2CDoCX,MAAMC,UAAyC,IAIpD,YAA4B3+I,EACAuvB,EACAxsB,GAC1B3D,QAH0B,KAAAY,OACA,KAAAuvB,cACA,KAAAxsB,eAI5B,WACE,MAAMqmB,EAAO9pB,KAAKkkB,eAAiBlkB,KAAKiwB,YAAY/R,OAAO,MAAMgG,cACjElkB,KACGyD,aACAmC,cACAsC,GAAG4hB,GACHhE,mBACA3lB,KACCH,KAAKI,kBAENC,UAAWsF,IACV3F,KAAKkkB,cAAgBve,EAAGuC,GACxBlI,KAAKgJ,YAAcrD,K,sCAtBd05I,GAAgC,yC,uBAAhCA,EAAgC,0YCvC7C,sB,KACK,4B,oSCmBE,MAAMC,UAAmC,IAuB9C,YAAmBv2I,EACGmb,EACAtd,EACAmvF,EAA6B,GAC7BlT,GAAkC,GACtD/iF,MAAMiJ,EAASrE,IAAI,MALF,KAAAqE,WACG,KAAAmb,gBACA,KAAAtd,WACA,KAAAmvF,yBACA,KAAAlT,0BAjBZ,KAAA75E,YAAchJ,KAAK2C,OAAOkT,aAAanR,IAAI1E,KAAKkkB,eAAe/d,MAC/D,KAAAo5I,qBAAuBv/I,KAAKw/I,0BAC5B,KAAApmE,iBAAmBp5E,KAAKy/I,6BAA6BpmE,oBAC7Dr5E,KAAKu/I,qBACL,IACAv/I,KAAK6iF,yBAIG,KAAAn1E,UAAY1N,KAAKyX,OAAOxX,QAAQkO,KAAKT,WAAa1N,KAAKyX,OAAOxX,QAAQwG,KAEtE,KAAAzF,MAAQhB,KAAKc,aAUvB,aACE,MAAO,CAAEG,cAAe,4BAA6BD,MAAOhB,KAAKgB,OAG5D,aAAaH,GAClB,IAAIgL,EAAW/L,MAAMmW,aAAapV,GAGlC,OAFAwD,EAAE6R,OAAOrK,EAAU7L,KAAK+1F,wBAEjBlqF,EAGF,yBAAyBk1D,GAC9B,MAAMx6B,EAAOw6B,EAAOx6B,KAEpB,OAAQw6B,EAAOp/D,KACb,IAAK,SACH3B,KAAK0/I,6BACL,MAEF,IAAK,OACH1/I,KAAK2/I,yBAAyBp5G,GAC9B,MAEF,IAAK,OACHvmC,KAAK4/I,yBAAyBr5G,GAC9B,MAEF,IAAK,qBACHvmC,KAAK+kB,4BAA4B86H,cAAc7/I,KAAK0N,UAAW1N,KAAKgJ,aACpE,MAEF,IAAK,WACHhJ,KAAK8/I,gCACL,MAEF,QACEt/H,OAAOgoB,SAASjjC,KAAOghC,GAKrB,6BACN,IAAIhB,EAAWvlC,KAAKw/I,0BACpBx/I,KAAK65C,eAAe94C,KAAK,IAAgBf,KAAK+I,SAAU,CAAE8M,aAAc0vB,IAGlE,yBAAyBgB,GAChBvmC,KAAKw/I,0BAEPv4I,OAAS,IACpBuZ,OAAOgoB,SAASjjC,KAAOghC,GAKnB,yBAAyBA,GAC/B,IAAIhB,EAAWvlC,KAAKw/I,0BAEpB,GAAIj6G,EAASt+B,OAAS,EAEpB,YADAuZ,OAAOgoB,SAASjjC,KAAOghC,GAIzB,IAAIroB,EAAS,CACX21D,wBAAyBtuC,EAAS,GAAGr9B,IAGvClI,KAAKyX,OAAOswB,GAAG/nC,KAAK0N,UAAY,QAASwQ,GAGnC,gCACNle,KAAKs5E,uBACF/2E,OAAOkd,OAAO,IAAIuP,MAAShvB,KAAKgJ,aAChCwR,MAAM,QAKH,0BACN,IAAI+kI,EAAuBv/I,KAAKuvC,iBAAiBiwG,0BAEjD,OAAoC,IAAhCD,EAAqBt4I,OAChB,CAACjH,KAAKgJ,eAGyC,IAApDu2I,EAAqBniI,QAAQpd,KAAKgJ,cACpCu2I,EAAqBr+I,KAAKlB,KAAKgJ,aAG1Bu2I,GAGC,aACR,IAAIv+I,EAAQhB,KAAKo5E,iBAAiBlqE,IAAK6xD,IAC9B,CACLxa,WAAO76C,EACPiN,UAAU,EACVxX,SAAU4/D,EAAOnpD,KACjBrS,KAAMw7D,EAAOx7D,KACblE,KAAqB,MAAf0/D,EAAO1/D,KAAe0/D,EAAO1/D,KAAO,QAAQ0/D,EAAOp/D,IACzDL,QAAUiqC,KACJw1B,EAAOx7D,OAAQ,IAAa6M,sBAAsBm5B,MAItDvrC,KAAK25E,yBAAyB5Y,IACvB,MAkDb,OA5CK/gE,KAAKgJ,YAAY7G,QACpBnB,EAAM0tC,QAAQ,CACZ/1B,UAAU,EACVtX,KAAM,uBACNklD,MAAO,qBACPhhD,KAAMvF,KAAKyX,OAAOlS,KAAK,qBAAsB,CAAE2e,cAAelkB,KAAKkkB,gBACnE/iB,SAAUT,KAAKU,EAAE,6BACjBE,QAAUiqC,IACJ,IAAan5B,sBAAsBm5B,KAIvCvrC,KAAKyX,OAAOswB,GACV,qBACA,CAAE7jB,cAAelkB,KAAKkkB,iBAEjB,KAIPlkB,KAAK6iF,yBACP7hF,EAAM0tC,QAAQ,CACZ/1B,UAAU,EACVtX,KAAM,kBACNklD,MAAO,sBACPhhD,KAAMvF,KAAKyX,OAAOlS,KAChB,YAAevF,KAAKyX,QAAU,YAC9B,CAAEyM,cAAelkB,KAAKkkB,gBACxB/iB,SAAUT,KAAKU,EAAE,0BACjBE,QAAUiqC,IACJ,IAAan5B,sBAAsBm5B,KAIvCvrC,KAAKyX,OAAOswB,GACV,YAAe/nC,KAAKyX,QAAU,YAC9B,CAAEyM,cAAelkB,KAAKkkB,iBAEjB,MAMRljB,GAzLM,aAAd,c,0BAA+B,M,6BACjB,aAAd,c,0BAAoD,M,kDACtC,aAAd,c,0BAAuC,M,qCACzB,aAAd,c,0BAA+B,iB,6BACjB,aAAd,c,0BAAyC,M,uCAC3B,aAAd,c,0BAAqD,M,mDACvC,aAAd,c,0BAA+C,M,gFCAlD,4J,yCAOM++I,EAAwB,EACjBC,EAA2B,yBAOjC,MAAMC,UAA+B,IAU1C,YAAqBv/I,EACAb,GACnBC,MAAMY,GAFa,KAAAA,OACA,KAAAb,QAVd,KAAA0+C,SAAkB,uCAClB,KAAAD,YAAqB,eACrB,KAAA4P,UAAmB,gBAWxBluD,KAAKmuD,cAAgBztD,EAAKU,EAAE,+BAC5BpB,KAAKouD,gBAAkB1tD,EAAKU,EAAE,iCAC9B,IAAI4J,EAAOhL,KAGP+/I,EAAWG,SACbH,EAAWI,UAAS,WAGbJ,EAAWK,cACdp1I,EAAKq1I,uBAMb,YACE,OAAIrgJ,KAAKwwC,SACAxwC,KAAKouD,gBAELpuD,KAAKmuD,cAIT,WACL,OAAO,EAGD,oBACNnuD,KAAKwwC,SAAWyvG,EAAuBK,WAAY,EACnDz5I,OAAO,QAAQ6D,YAAY,YAC3B1K,KAAK2Y,UAAW,EACZonI,EAAWG,SAAWH,EAAWK,cACnCL,EAAWQ,OAEbvgJ,KAAKH,MAAMS,gBAGL,kBACNN,KAAKwwC,SAAWyvG,EAAuBK,WAAY,EACnDz5I,OAAO,QAAQ8D,SAAS,YACpBo1I,EAAWG,SACbH,EAAWnhI,UAEb5e,KAAKH,MAAMS,gBAGN,cAAcO,GAQnB,OAPIo/I,EAAuBK,UACzBtgJ,KAAKqgJ,oBAELrgJ,KAAKwgJ,kBAGP3/I,EAAI0L,kBACG,GAhEF,EAAA+zI,WAAoB,E,sCALhBL,GAAsB,sB,uBAAtBA,EAAsB,2Lne3CnC,mBAOQ,2CAAmB,EAAAtxF,cAAA,MACzB,oBACF,Q,MATQ,iCAEA,qCAAmC,kDAEnC,sBAAoB,gBAApB,CAAoB,yBAIjB,8D,gGoeRX,4DAQO,SAAS8xF,EAAYp8B,EAAYpsD,EAAmB,MACzD,MAAO,CAAClxD,EAAwBiwB,YAClBjwB,EAAeiwB,IACzBlnB,OAAO4tE,eAAe32E,EAAQiwB,EAAU,CACtCtyB,IAAK,WACH,GAAI2/G,EACF,OAAOrkH,KAAK+I,SAASrE,IAAS2/G,EAAOpsD,GAChC,CACL,MAAMnlD,EAAO4tI,QAAQC,YAAY,cAAe55I,EAAQiwB,GACxD,OAAOh3B,KAAK+I,SAASrE,IAASoO,KAGlCiZ,IAAK,SAA+B60H,GAClC,YAAS,sCAAwC5pH,S,kCCrB3D,sI,wBCcA,8B,oBAEmB,8CAAuC,6CDJnD,MAAM6pH,EAoBX,YAAqB93I,EACArI,EACAmC,EACAoZ,EACA+2B,GAJA,KAAAjqC,WACA,KAAArI,OACA,KAAAmC,iBACA,KAAAoZ,uBACA,KAAA+2B,gBAvBd,KAAA8tG,wBAA0B9gJ,KAAK6C,eAAeihC,IAAI50B,IAAIo7D,GAAKtqE,KAAK+gJ,YAAYz2E,IAE5E,KAAAqvC,iBAAmB35G,KAAK6C,eAAeihC,IACvC,KAAAk9G,oBAAkD38I,EAAE48I,MAAMjhJ,KAAK25G,iBAAkBrvC,GAAKA,EAAEpiE,IACxF,KAAAggH,gBAAoCloH,KAAK6C,eAAe4rC,aAAav/B,IAAIo7D,GAAKtqE,KAAK+gJ,YAAYz2E,IAE/F,KAAA42E,kBAA4C,GAC5C,KAAArqI,eAAwB,EACxB,KAAAe,KAAO,CAEZupI,YAAanhJ,KAAKU,KAAKU,EAAE,0DACzB6mH,aAAcjoH,KAAKU,KAAKU,EAAE,oBAC1B8mH,gBAAiBloH,KAAKU,KAAKU,EAAE,mCAC7B+mH,iBAAkBnoH,KAAKU,KAAKU,EAAE,6CAE9BgnH,sBAAuBpoH,KAAKU,KAAKU,EAAE,gEACnCggJ,mBAAoBphJ,KAAKU,KAAKU,EAAE,+DAU3B,SACLpB,KAAK6C,eAAew+I,eAAerhJ,KAAKkoH,gBAAgBh5G,IAAIo7D,GAAKA,EAAEpiE,KAGrE,WACElI,KAAK6W,cAAgB7W,KAAKgzC,cAAcn8B,cACxC7W,KAAKkoH,gBAAgBxiH,QAAS4kE,IAC5BtqE,KAAKkhJ,kBAAkB52E,EAAEpiE,KAAM,IAI3B,YAAYoiE,GAClB,MAAO,CAAEpiE,GAAIoiE,EAAEpiE,GAAIzB,KAAM6jE,EAAE7jE,MAG7B,eAAe8+B,GACbvlC,KAAKkoH,gBAAkB3iF,G,sCA3Cds7G,GAA8B,oD,uBAA9BA,EAA8B,2cCZ3C,gBACE,kBAKA,oCAEyB,oCAAY,EAAAS,eAAA,MACrC,OAEA,cACF,OAEA,qC,MAZI,mDAIuB,kDAAmC,8BAKvB,+CAIpB,uC,8ECcnB,0T,yBCLU,gBACE,+BAGF,Q,qBAHqB,0CAA2B,gB,sEA4C5C,gBAIE,eACA,+BACF,Q,qBAJI,4CAES,iDACQ,uC,iGA1EnC,gBAKI,0BAEA,gBACE,gBACE,gBAEE,wBAEA,gBACE,qBACF,OACF,OACA,eACE,eACE,+BAIF,OACA,uBAKA,gBACE,kCAEF,OACA,iBACE,qBAIE,sBACF,OACF,OACF,OACF,OACF,OAEA,kBACE,kBACE,kBACE,4BACF,OACF,OACA,kBACE,kBACE,mBACA,kBACE,iBAGE,iBAGE,gBACF,OACA,iBAGE,gBACA,iCACF,OACA,uBAOF,OACF,OACA,kBAEF,OAEA,kBACE,yBAEF,OACF,OACF,OACJ,Q,oBAvFK,+BAIc,0CAeL,mCAA0D,2BAIrC,0CAaf,8DAFA,2CAaM,0CAKqC,+CAM7C,qDAES,iDAGT,qDAES,kDACS,sCAElB,oDAcI,oEAAuD,oDDrCtE,MAAMC,UAAsC,IAQjD,YAAmBx4I,EACAwmC,EACE93B,GACnB3X,MAAMiJ,EAAU0O,EAAOyG,OAAsB,eAH5B,KAAAnV,WACA,KAAAwmC,mBACE,KAAA93B,SAJrB,KAAA2lH,WAAa,YAAG,qBAQhB,WACEp9H,KAAKghF,qBAGG,kBACRlhF,MAAMyhF,kBAENvhF,KAAK4X,KAAK4pI,UAAY,CACpBjV,YAAavsI,KAAKU,KAAKU,EAAE,mBAInB,OACRtB,MAAM21E,OAGNz1E,KAAK8vC,aAAac,YAAY5wC,KAAKgJ,YAAYd,IAE/ClI,KAAKyhJ,8BAA8BzhJ,KAAKgJ,aAGlC,8BAA8BrD,GACpC3F,KAAK+9C,UAAYp4C,EAAGk2C,eAAe,WACnC77C,KAAK0hJ,mBAAqB/7I,EAAGk2C,eAAe,YAAcl2C,EAAGk2C,eAAe,SAGxEl2C,EAAGmkD,WACL9pD,KAAK8pD,SAAYnkD,EAAGmkD,SAAiBtlD,W,sCAzC9B+8I,GAA6B,2C,uBAA7BA,EAA6B,8FAJ7B,CACT,CAAE57F,QAAS,IAAgCugB,YAAa,OACzD,wjDC5CH,wB,KAEK,4B,4XC2CE,MAAMy7E,UAAkC,IAwB7C,YAAmB54I,EAA6Bmb,GAC9CpkB,QADiB,KAAAiJ,WAA6B,KAAAmb,gBATzC,KAAAtM,KAAW,GAWhB5X,KAAKuhF,kBAOG,qBAERvhF,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKkkB,eACR4B,mBACA3lB,KACCH,KAAKI,kBAENC,UAAWsF,IACR3F,KAAKgJ,YAAcrD,EACnB3F,KAAKy1E,OACLz1E,KAAKH,MAAMS,iBAEZ0e,GAAUhf,KAAK6sC,oBAAoBgB,eAAe7uB,IAO/C,kBACRhf,KAAK4X,KAAKgqI,KAAO,GACjB,CAAC,WAAY,WAAY,YAAa,YAAYl8I,QAAQ8/D,IACxDxlE,KAAK4X,KAAKgqI,KAAKp8E,GAAOxlE,KAAKU,KAAKU,EAAE,yBAA2BokE,KAOvD,OAERxlE,KACGyD,aACAid,SACAxY,GAAGlI,KAAKgJ,YAAY0S,SACpBoK,mBACAzlB,UAAU,KACTL,KAAK8O,kBAAoB9O,KAAKgJ,YAAY0S,QAAQ5G,WAClD9U,KAAKH,MAAMS,kBAIfN,KAAK2D,qBAAqB6B,cAAc,eAAgBxF,KAAKgJ,YAAYvD,QAGzEzF,KAAK+zE,aAAaC,aAAah0E,KAAKgJ,YAAY64I,gBAAgB,KAGhE7hJ,KAAK8hJ,mBAAqB9hJ,KAAK0a,WAAWyK,gBAAgBnlB,KAAKkkB,eAG/DlkB,KAAK06C,QAAQ0W,WACVjxD,KACCH,KAAKI,kBAENC,UAAWuhJ,IACV5hJ,KAAK+hJ,uBAAuBH,EAAK7oI,UAOhC,uBAAuB6sD,GAC5B,MAAMo8E,EAAWhiJ,KAAKU,KAAKU,EAAE,6CAA8C,CACzEokE,IAAKxlE,KAAKU,KAAKU,EAAE,yBAA2BwkE,GAC5C9yD,KAAM9S,KAAKgJ,YAAY8J,KAAKrM,KAC5B2iE,QAASppE,KAAKgJ,YAAYogE,UAG5B,OAAOppE,KAAKiiJ,iBAAmBD,EAG1B,6BACL,SAAUhiJ,KAAKgJ,cAAehJ,KAAKgJ,YAAY8gD,WA5GlC,aAAd,c,0BAAqB,M,6BACP,aAAd,c,0BAAmB,M,2BACL,aAAd,c,0BAAsB,M,8BACR,aAAd,c,0BAAyB,M,iCACX,aAAd,c,0BAAyB,M,iCACX,aAAd,c,0BAA2B,M,mCACb,aAAd,c,0BAAkC,M,0CACpB,aAAd,c,0BAAmC,M,2CACrB,aAAd,c,0BAAoB,M,4BACN,aAAd,c,0BAAoC,M,mCACtB,aAAd,c,0BAAoC,M,wECzDvC,gS,gECYc,kB,qBACM,8C,wBACN,kB,qBACM,oD,uCATR,kBACM,wFAKJ,wBAEA,wBAEA,kBACF,O,wBALQ,8CAEA,+CAE2B,mD,wBAUrC,oB,yBACQ,4BAAkC,c,uCAT9C,iBAEE,oBACQ,mFAAkC,iEAAlC,CAAkC,0FAKxC,0BAGF,OACF,O,wBATU,+CAKE,kD,sEAOd,iBAEE,eAMF,Q,qBALK,2DAAqD,oDAGrD,sF,yBAKH,uBACE,sCACF,Q,qBAFsC,sCACV,+C,uCAc5B,oCACwB,0FAKtB,qBACF,O,wBAJwB,0CAAmC,iCAGM,gD,qFAOnE,iBAEK,oFAGL,O,wBAJK,kDAAoD,uE,uCAKzD,iBAEM,yBAKI,4EAAsC,oFACG,OACjD,iCACqB,sEAA4B,yEAIjD,OACF,O,wBAPU,qDACa,kDAAmC,wBAAnC,CAAmC,8B,yBAjB5D,iBAEE,uBAMA,uBAgBF,Q,qBAnBO,2DAIA,2D,iFA/ET,gBAGE,gBAEE,gBACQ,uBAYN,sBAaF,OAEA,sBAUA,gBACE,4BAGF,OAEA,gBAEE,oCAIwB,yHACtB,sBAEF,OACA,2CAQF,OACF,OAEA,wBAyBF,O,uBA9FK,8DAQa,yDAUP,wDAeF,0CAUQ,0CAOa,uDAAwC,qCAAxC,CAAwC,4CAQxC,uCAYvB,oDDvDA,MAAMo4F,UAAwC,IAyCnD,YAAsBz+I,EACAopC,EACAh8B,EACAsb,EACAzrB,EACAb,EACA6a,GACpB5a,QAPoB,KAAA2D,eACA,KAAAopC,sBACA,KAAAh8B,cACA,KAAAsb,YACA,KAAAzrB,OACA,KAAAb,QACA,KAAA6a,aAvCf,KAAAynI,kBAA2B,EAC3B,KAAAn9H,cAAuB,EAIvB,KAAAo9H,WAAa,CAClBC,gBAAiB,GACjBC,yBAAyB,EACzBC,uBAAuB,EACvBJ,kBAAkB,GAIb,KAAAK,gBAAkB,CACvB1pI,QAAS,CACPC,QAAQ,GAEVQ,UAAU,GAIL,KAAA3B,KAAO,CACZyC,OAAQra,KAAKU,KAAKU,EAAE,oBACpBgZ,KAAMpa,KAAKU,KAAKU,EAAE,kBAClBqhJ,aAAcziJ,KAAKU,KAAKU,EAAE,8BAC1BshJ,kBAAmB1iJ,KAAKU,KAAKU,EAAE,0CAC/BuhJ,kBAAmB3iJ,KAAKU,KAAKU,EAAE,0CAC/BwhJ,eAAgB5iJ,KAAKU,KAAKU,EAAE,uCAC5BouB,YAAa,CACXxtB,YAAahC,KAAKU,KAAKU,EAAE,0CAc7B,WACEpB,KAAKs0B,SAAWt0B,KAAKytC,mBAAmBs+F,UAExC/rI,KAAKoiJ,WAAWC,gBAAkBriJ,KAAKs0B,SAAStyB,aAAe,GAC/DhC,KAAK6iJ,uBAAyB,IAAiB31G,0BAAyB,GACxEltC,KAAK+sC,qBAAuB1oC,EAAEmH,KAAKxL,KAAK6iJ,uBACtC,CAAE,KAAQ7iJ,KAAKs0B,SAASw3G,eAAe9rI,KAAKgJ,eAE9ChJ,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKytC,oBACR3nB,mBACA3lB,KACCH,KAAKI,kBACLC,UAAWsF,IACb3F,KAAKytC,mBAAqB9nC,IAQ9B,6BACE,IAAImN,EAAO9S,KAAKs0B,SAASw3G,eAAe9rI,KAAKgJ,aAC7C,OAAOhJ,KAAKU,KAAKU,EAAE,sBAAwB0R,GAG7C,oBACE,OAAO9S,KAAKytC,oBAAsBztC,KAAKytC,mBAAmBykC,QAGrD,uBACLlyE,KAAKoiJ,WAAWE,yBAA0B,EAC1Ch1I,WAAW,KACT,MAAMw1I,EAAWj8I,OAAO7G,KAAK+iJ,4BAA4Bj8I,eACnDk8I,EAAWF,EAASlhJ,MAAiBqF,OAE3C67I,EAASv1I,QAETu1I,EAASn/H,KAAK,iBAAkBq/H,GAChCF,EAASn/H,KAAK,eAAgBq/H,KAI3B,qBAAqBz3G,GACL,KAAjBA,EAAOxgB,OACT/qB,KAAKijJ,wBAIF,wBACLjjJ,KAAKoiJ,WAAWE,yBAA0B,EAC1CtiJ,KAAKoiJ,WAAWC,gBAAkBriJ,KAAKs0B,SAAStyB,aAAe,GAG1D,kBACLhC,KAAK6Q,YAAY+xI,eACf5iJ,KAAKs0B,SACL,CAAEtyB,YAAahC,KAAKoiJ,WAAWC,kBAC9B5yI,KAAMyzI,IACLljJ,KAAKs0B,SAAW4uH,EAChBljJ,KAAKytC,mBAAmBs+F,UAAYmX,EACpCljJ,KAAKoiJ,WAAWE,yBAA0B,EAC1CtiJ,KAAK6sC,oBAAoBa,SAAS1tC,KAAKytC,oBACvCztC,KAAKH,MAAMS,kBAIjB,0BACE,OAAON,KAAKoiJ,WAAWD,kBAAoBniJ,KAAKs0B,SAAStyB,YAGpD,2BACDhC,KAAK2tD,yBACP3tD,KAAKoiJ,WAAWG,uBAAwB,GAIrC,+BAA+B1hJ,GACpCb,KAAKoiJ,WAAWG,uBAAwB,EAGnC,mBACLviJ,KAAK6Q,YAAYsyI,mBACfnjJ,KAAKgJ,YACLhJ,KAAKytC,mBACLztC,KAAKs0B,SACLt0B,KAAK+sC,qBAAqBtmC,MACzBgJ,KAAMyzI,IACLljJ,KAAK6sC,oBAAoBa,SAAS1tC,KAAKytC,oBACvCztC,KAAKytC,mBAAmBs+F,UAAYmX,EACpCljJ,KAAKs0B,SAAW4uH,EAEhBljJ,KAAKoiJ,WAAWG,uBAAwB,EACxCviJ,KAAKH,MAAMS,kBAEZka,MAAOwE,GAAchf,KAAK6sC,oBAAoBgB,eAAe7uB,EAAOhf,KAAKgJ,cAGvE,4BACLhJ,KAAKoiJ,WAAWE,yBAA2BtiJ,KAAKoiJ,WAAWE,wBAGtD,iBACLtiJ,KAAK6Q,YAAY4pG,eAAez6G,KAAKs0B,UAClC7kB,KAAK,KACJzP,KAAKmsB,UAAUjrB,KAAKlB,KAAKgJ,YAAa,CACpCwkC,UAAW,cACXC,mBAAoB,KACpBrX,aAAcp2B,KAAKs0B,SAASw3G,eAAe9rI,KAAKgJ,eAGlDhJ,KACGyD,aACAmC,cACAC,MACAC,kBAAkB9F,KAAKytC,oBAE1BztC,KAAK6sC,oBAAoBa,SAAS1tC,KAAKytC,sBAExCjzB,MAAOozB,GAAY5tC,KAAK6sC,oBAAoBgB,eAAeD,EAC1D5tC,KAAKytC,sB,sCA9KAy0G,GAA+B,wE,uBAA/BA,EAA+B,wD,OAAA,K,2mFChB5C,wB,KAAK,kD,gTCaE,MAAMkB,EAIX,YAA6BthH,EACAjzB,EACApL,EACAyY,EACA8hD,EACAt9D,GALA,KAAAohC,iBACA,KAAAjzB,aACA,KAAApL,eACA,KAAAyY,qBACA,KAAA8hD,gBACA,KAAAt9D,OAPrB,KAAAypD,GAAKnqD,KAAK6O,WAAWq7C,IAAIC,GAWzB,OAAOjsC,EAAelP,GAC5B,IAAIq0I,EAAa59H,KAAKC,UAAU1W,GAEhC,OAAOhP,KACJyD,aACAqB,QACAV,KACA81D,eACC,CACE3f,SAAU,EACVvrC,QAASq0I,QAEX33I,EACA1L,KAAK8hC,eAAehtB,WACpB9U,KAAKsjJ,kBAAkBplI,IAExB2O,YACApd,KAAK,EAAErL,EAAMP,MAGZ,GAAIO,EAAK5B,OAAe,OAAE8W,SACxB,OAAOtZ,KACJyD,aACAqB,QACAsoB,KAAKvpB,EAAOO,GACZyoB,YAEH,MAAM,IAAInd,MAAM1P,KAAKU,KAAKU,EAAE,yCAQ7B,aAAayzD,EAAawE,GAC/B,MAAM9tD,EAASvL,KAAKujJ,uBACpB,OAAOvjJ,KAAKwjJ,SAAS3uF,EAAOwE,EAAa,CAAC9tD,IAQ/B,SAASspD,EAAawE,EAAoBrqD,G,mDACrD,MAAMilB,EAAQ4gC,EAAM/vD,QAAQmC,OAC5B,IAGE,IAAIO,EAAS,CACXW,MAAO,aACP2M,WAAY,qBACZinE,SAAU,EACVD,OAAQ,EACRlsB,YAAa37B,EAAQ,EACrB+nD,UAAW/nD,EAAQ,EACnBnE,QAAS,CACPioB,eAVgB/3C,KAAKuC,OAAO82D,EAAarqD,IAU1B9G,GACf8G,QAASA,IAITuO,EAAWvd,KAAKkc,mBAAmBsgE,yBAAyB,IAAoBh1E,GACpFqtD,EAAM2uF,SAASjmI,GACf,MAAOjR,GACPtM,KAAKg+D,cAAcjE,SAASztD,GAC5BsR,QAAQoB,MAAM1S,GAEhB,OAAOuoD,KAGD,kBAAkB32C,GACxB,OAAO,OAAP,QACEiY,QAAQ,EACRgO,QAAQ,EACR,OAAU,CACR,OAAU,CACR,CAAE,KAAQnkC,KAAKmqD,GAAGC,UAAY,uCAC9B,CAAE,KAAQpqD,KAAKmqD,GAAGC,UAAY,+BAG/BlsC,GAIC,uBACN,MAAO,CAAEulI,WAAY,CAAE99H,SAAU,KAAMC,OAAQ,M,sCApGtCw9H,GAAiB,8D,yBAAjBA,EAAiB,QAAjBA,EAAiB,qBADJ,U,kCCgB1B,gG,MAGaM,EAA+B,uBAUrC,MAAMC,EASX,YAAqBnjJ,GAAA,KAAAA,aANd,KAAA+2B,cAAoD,CACzDoX,sBAAsB,EACtBC,mBAAmB,EACnB0iD,oBAAoB,GAMtB,WACE,MAAM1hE,EAAU5vB,KAAKQ,WAAWsG,cAChC9G,KAAKg4C,WAAavyB,KAAKvG,MAAM0Q,EAAQnf,QAAQunC,a,sCAdpC2rG,GAA4B,Y,uBAA5BA,EAA4B,+C,2BAAA,qFALrC,oC,KAAyB,gCAAyB,kC,sECPtD,0EAIO,MAAMC,EAGX,YAAoBlpI,EACAjX,GADA,KAAAiX,aACA,KAAAjX,eAClBzD,KAAK6jJ,SAGP,uBACE,YAAwBn4I,IAAjB1L,KAAKC,QAGd,WACE,OAAID,KAAKC,QACAD,KAAK0a,WAAW3L,YAAY/O,KAAKC,QAAQ6U,YAG3C,KAGT,gBACE,OAAI9U,KAAKC,QACAD,KAAKyD,aAAaid,SAASxY,GAAGlI,KAAKC,QAAQiI,IAAIma,WAGjD,KAGT,SACE,OAAOriB,KAAK8jJ,WAAW,MAGzB,WACE,OAAO9jJ,KAAK8jJ,WAAW,QAGzB,iBACE,OAAO9jJ,KAAK8jJ,WAAW,cAGjB,WAAWniJ,GACjB,OAAI3B,KAAKC,SAAWD,KAAKC,QAAQ0B,GACxB3B,KAAKC,QAAQ0B,GAAK0gB,WAGpB,KAMF,SACL,MAAMuN,EAA+B1kB,SAAS2O,cAAc,8BACxD+V,IACF5vB,KAAKC,QAAU,CACbiI,GAAI0nB,EAAQnf,QAAQyhD,UACpBzrD,KAAMmpB,EAAQnf,QAAQszI,YACtBjvI,WAAY8a,EAAQnf,QAAQ3B,qB,sCAzDvB80I,GAAqB,sB,yBAArBA,EAAqB,QAArBA,EAAqB,qBADR,U,kCChC1B,8DASO,MAAMI,UAA4B,IAEvC,YAAmBj7I,EACAC,EACS8L,EACRwN,EACC06B,EACA17C,GACnBxB,MAAMiJ,EAAUC,GANC,KAAAD,WACA,KAAAC,cACS,KAAA8L,aACR,KAAAwN,QACC,KAAA06B,aACA,KAAA17C,UAYd,kBAAkBwT,EACAwN,EACAhhB,EACA07C,EAA0D,MAAM,IACvF,MAAO,CAACj0C,EAAmBC,IAClB,IAAIg7I,EAAoBj7I,EAC7BC,EACA8L,EACAwN,EACA06B,EACA17C,GAIC,eACL,IAAKtB,KAAKg9C,WAAWh9C,KAAKgJ,aACxB,OAAO,KAGT,IAAI4mB,EAAU1kB,SAASoF,cAAc,KAWrC,OAVAsf,EAAQtN,MAAQtiB,KAAKsiB,MACrBsN,EAAQrqB,KAAO,IACfqqB,EAAQrf,UAAUC,IAAI,IAAmB,2BACzCof,EAAQnf,QAAQyT,cAAgBlkB,KAAKgJ,YAAYd,GACjD0nB,EAAQve,YAAY,YAAc,OAAQ,eAC1CxK,OAAO+oB,GAASxjB,MAAOpE,IACrBA,EAAMuE,iBACNvM,KAAKsB,QAAQtB,KAAKgJ,eAGb4mB,K,kCC1DX,4P,kDCiBM,Q,yBADF,QACE,gCACF,Q,oBADgB,0DAA8D,yC,iIAM1E,gBAEE,eAKG,wFAEH,OATF,O,sCACI,0FAGC,2EAAsE,uBACtE,yC,yBART,iBAEE,gBACE,sBAUF,OACF,Q,oBAXQ,yCDaL,MAAMq0H,EAAwC,IAAI,IAAmC,6CAKrF,MAAMC,UAA2C,IAoCtD,YAA+CpyI,EAC+BqyI,EACzDzjJ,EACAqI,EACAyhB,EACAF,EACAyX,EACAn/B,EACAs1C,EACAz0C,EACAopC,EACAhqC,EACAhD,EACAoc,EACAzb,GACnBV,MAAMgS,EAAQjS,EAAOW,GAfwB,KAAAsR,SAC+B,KAAAqyI,wBACzD,KAAAzjJ,OACA,KAAAqI,WACA,KAAAyhB,SACA,KAAAF,2BACA,KAAAyX,mBACA,KAAAn/B,aACA,KAAAs1C,yBACA,KAAAz0C,eACA,KAAAopC,sBACA,KAAAhqC,iBACA,KAAAhD,QACA,KAAAoc,uBACA,KAAAzb,aA/Cd,KAAAymD,eAAgB,EAGhB,KAAAE,qBAAsB,EAItB,KAAAvvC,KAAO,CACZ0K,MAAOtiB,KAAKU,KAAKU,EAAE,oDACnB68D,WAAYj+D,KAAKU,KAAKU,EAAE,wBAExB6mH,aAAcjoH,KAAKU,KAAKU,EAAE,oBAC1B8mH,gBAAiBloH,KAAKU,KAAKU,EAAE,mCAC7B+mH,iBAAkBnoH,KAAKU,KAAKU,EAAE,6CAC9BgjJ,YAAapkJ,KAAKU,KAAKU,EAAE,0BACzBsuC,aAAc1vC,KAAKU,KAAKU,EAAE,2BAE1BgnH,sBAAuBpoH,KAAKU,KAAKU,EAAE,qCACnCinH,0BAA2BroH,KAAKU,KAAKU,EAAE,2CAGlC,KAAA04C,cAAgB,IAAI,IACpB,KAAAonG,kBAA4C,GAQ3C,KAAAmD,4BACNrkJ,KAAK+I,SAASrE,IAAI,IAA6B,IAAI,IAA4B1E,KAAKU,OAoBtF,WACEV,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eAEvC9G,KAAKskJ,cAAgB,IAAI,IACvBtkJ,KAAKqkJ,4BAA4BzC,KACjC5hJ,KAAKukJ,iBAAiBz9I,cACtB9G,KAAKsqB,yBACLtqB,KAAKwqB,OACLxqB,KAAK+I,UAGP/I,KAAK+hC,iBAAiB9wB,UAAU,SAASg0B,QAAUjlC,KAAKg6C,WACrDvqC,KAAK,KACJ,MAAMyxD,EAAalhE,KAAK8R,OAAmB,YAAK9R,KAAKolE,cAAc,GAAG3+D,KACtEzG,KAAKmgH,SAASj/C,KAIpB,cACElhE,KAAK85C,cAAclgC,WACnB5Z,KAAKskJ,cAAcx+E,UAGrB,oBACE,OAAO9lE,KAAKskJ,cAAcl/E,cAG5B,iBACE,OAAOplE,KAAKskJ,cAAc/+E,WAGrB,SAAS9+D,GACdzG,KAAKskJ,cAAcnkC,SAAS15G,GAGvB,cACLzG,KAAKskJ,cAAcE,iBAAiB9+I,QAAS+I,IAC3CA,EAAUwL,WAGZja,KAAK85C,cAActxC,OACnBxI,KAAK8rB,QAAQ/gB,QAQR,UAEL,OADA/K,KAAK6oD,aAAat7C,SACX,EAGT,mBACE,OAAOvN,KAAK4G,SAGJ,WACR,MAAM/C,EAAQ7D,KAAK4C,WAAWiB,MAAMsC,MACpC,OAAOnG,KACJyD,aACAqB,QACAV,KACA47B,KAAKn8B,GACLgpB,YACApd,KAAK,EAAErL,EAAMC,MACVrE,KAAKk4C,uBAAuBoC,qBAAqBz2C,EAAOO,GAEjDA,IAEVoW,MAAOwE,GAAUhf,KAAK6sC,oBAAoBgB,eAAe7uB,K,sCA7HnDklI,GAAkC,KAoCzB,KAAkB,KACND,EAAqC,uI,uBArC1DC,EAAkC,qD,OAAA,K,y1BCzC/C,gBACE,gBAGE,gBACE,eAEA,cACE,cAEI,iCAAS,EAAA58F,QAAA,MAEb,OACF,OACF,OAEA,+BAIA,sBAgBA,kBACA,kBACE,qBAEQ,gCAAS,EAAAm9F,iBACjB,OACA,qBAEQ,iCAAS,EAAAn9F,QAAA,MACjB,OACF,OACF,OACF,Q,MA3CU,yCAME,wCAKM,+CAIT,uCAmBK,+CAIA,kD,wFCdd,sO,yB7P5BE,gBACE,gBACE,eAEF,OACF,Q,qBAFQ,0C,mPAJV,QACE,sBAOA,gCACmB,gFAYnB,OACF,O,uBArBO,6BASc,2CAAiC,0BAAjC,CAAiC,8BAAjC,CAAiC,6D6P0C/C,MAAMo9F,UAA0C,IAmBrD,YAAsB3/H,EACArK,EACAm1B,EACA1jB,EACA1oB,EACAgjF,EACD/lF,GACnBZ,MAAM2mF,GAPc,KAAA1hE,8BACA,KAAArK,aACA,KAAAm1B,iBACA,KAAA1jB,YACA,KAAA1oB,eACA,KAAAgjF,uBACD,KAAA/lF,OAnBL,KAAAikJ,yBAAkC,EAE3C,KAAA5rG,aAAsC,CAC3C,IAAoBw3D,WAClB,sBACAvwG,KAAKU,KAAKU,EAAE,oCACXw6B,IACC57B,KAAK0mF,cAAc3kD,iBAAmB/hC,KAAK+kB,4BAA4By8B,YAAY5lB,IAEpFA,KAAgCA,EAAMvW,eAc3C,WAEErlB,KAAK6vC,eAAe0wB,gBAAkBvgE,KAAKgJ,YAG3ChJ,KAAKg4C,WAAah4C,KAAK2wG,kBAGvB3wG,KAAK6vC,eAAegB,4BACjB1wC,KACCH,KAAKI,kBAENC,UAAWuwG,IACV5wG,KAAKmsB,UAAUjrB,KAAKlB,KAAKgJ,YAAa,CACpCwkC,UAAW,cACXC,mBAAoBmjE,EACpBx6E,aAAc,YAKpBp2B,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKgJ,aACRuoD,UACApxD,KACC,YAAO,IAAMH,KAAK0mF,eAAiB1mF,KAAK0mF,cAAcC,eACtD3mF,KAAKI,kBAENC,UAAU,IAAML,KAAKywG,iB,sCA3Dfi0C,GAAiC,wE,uBAAjCA,EAAiC,kKAJjC,CACT,CAAE/+F,QAAS,IAAgCC,SAAU,OACtD,8V7PlDH,+B,KAAc,wB,0E8P4Bd,0KAkBO,MAAMg/F,UAA2C,IAGtD,YAAqBpkJ,EACAC,EACAgX,EACC0vE,EACAvxE,EACAi3B,EACAnsC,EACAyrB,GAEpBrsB,MAAMU,EAAYC,GATC,KAAAD,aACA,KAAAC,gBACA,KAAAgX,SACC,KAAA0vE,iCACA,KAAAvxE,aACA,KAAAi3B,sBACA,KAAAnsC,OACA,KAAAyrB,YAKZ,KAAKtrB,GACb,MAAMsY,EAASnZ,KAAK4V,WAAWE,UAAU9V,KAAKgJ,aAE9CmQ,EAAOpD,UAAUtG,KAAMrL,IACrB,MAAMowD,EAAWpwD,EAAK5B,OAAOm5C,OAAO32C,cACpChF,KAAKc,WAAW0zD,GAECr7C,EAAO3W,OAAOm5C,OAAOriC,SAIpCtZ,KAAKS,cAAcM,KAAKf,KAAMa,GAF9Bb,KAAK6sC,oBAAoBktB,SAAS/5D,KAAKU,KAAKU,EAAE,2DAOpD,aACE,MAAO,CACLJ,MAAOhB,KAAKgB,MACZC,cAAe,0BAIX,aAAa06C,GACnB,MAAMxiC,EAASnZ,KAAK4V,WAAWE,UAAU9V,KAAKgJ,aAC9CmQ,EAAO1W,kBAAkBk5C,OAASA,EAE7B37C,KAAKgJ,YAAY7G,OACpBnC,KAAK4V,WACFwE,KAAKjB,GACL1J,KAAK,KACJzP,KAAKmnF,+BAA+Bz5C,SAAS1tC,KAAKgJ,eAKlD,WAAWwrD,GACjBx0D,KAAKgB,MAAQwzD,EAAStlD,IAAKysC,IAClB,CACLhjC,UAAU,EACVxX,SAAUw6C,EAAOl1C,KACjBo+I,SAAUlpG,EAAOJ,WAAa,cAAgB,KAC9CupG,cAAe9kJ,KAAKU,KAAKU,EAAE,mDAC3BmlD,MAAO,IAAaC,YAAY,SAAU7K,EAAOzzC,IACjD5G,QAAS,KACPtB,KAAK+kJ,aAAappG,IACX,O,sCA7DJipG,GAAkC,6F,uBAAlCA,EAAkC,8H,kCClB/C,sI,uDtJPI,cAA2C,S,mCAAxC,0CAAwC,0B,yBAG3C,gBAAmE,QAAe,Q,mCAA7E,4BAA8D,sBsJsBhE,MAAMI,EA6BX,YAAqBtkJ,EACAb,EACA6X,EACA7I,GAHA,KAAAnO,OACA,KAAAb,QACA,KAAA6X,iBACA,KAAA7I,aA5BL,KAAA0K,UAAmB,EACnB,KAAAZ,UAAmB,EACnB,KAAAssI,iBAA0B,EAC1B,KAAA/8I,GAAY,GACZ,KAAAuZ,QAAiB,GAEjB,KAAAyjI,cAAuB,EAEtB,KAAA39E,SAAW,IAAI,IACf,KAAA0rE,UAAY,IAAI,IAChB,KAAAznH,OAAS,IAAI,IACb,KAAAG,QAAU,IAAI,IACd,KAAAwnH,gBAAkB,IAAI,IAKhC,KAAAv7H,KAA+B,CACpCutI,eAAgBnlJ,KAAKU,KAAKU,EAAE,oBAGvB,KAAAovI,eAAiC,EAEhC,KAAA4U,eAAwB,EAQhC,kBACEplJ,KAAKmzI,gBAAgB3qI,KAAKxI,MAGrB,aACDA,KAAKo0C,oBACPp0C,KAAKo0C,kBAAkB/pC,OAOzBrK,KAAKqwI,cAAe,GAGf,cACLrwI,KAAKo0C,mBAAqBp0C,KAAKo0C,kBAAkBrpC,QAG5C,YAAY6kB,GACjB5vB,KAAKunE,SAAS/+D,KAAKonB,GAGd,SAGLtiB,WAAW,KACT,MAAMmB,EAAYzO,KAAKo0C,kBACnB3lC,GAAaA,EAAUymC,eACzBzmC,EAAUymC,cAAcC,mBAEzB,IAEHn1C,KAAKwrB,OAAOhjB,OAGP,SACLxI,KAAKqwI,cAAe,EACpBrwI,KAAK2rB,QAAQnjB,OAGR,WAAWR,GAChBhI,KAAKizI,UAAUzqI,KAAKR,GAGtB,mBACE,OAAOhI,KAAKolJ,cAGd,iBAAwBxjJ,GACtB5B,KAAKolJ,cAAgBxjJ,EACjBA,GACF5B,KAAKqlJ,aAIF,kBACLrlJ,KAAKo0C,mBAAqBp0C,KAAKo0C,kBAAkB7mC,S,sCA7FxCy3I,GAA4B,0C,uBAA5BA,EAA4B,6D,OAAA,K,60BtJ9CzC,wBACW,sDAAmB,6BAcT,EAAAlqB,YAAA,KAdV,CAAmB,0BAeX,EAAAC,WAfR,CAAmB,2BAgBV,EAAAC,WAhBT,CAAmB,8BAiBR,EAAAC,WAAA,MAEpB,8BAGA,8BAGF,Q,KAzBW,wBAAmB,0BAAnB,CAAmB,oBAAnB,CAAmB,yBAAnB,CAAmB,mBAAnB,CAAmB,sBAAnB,CAAmB,wBAAnB,CAAmB,sBAAnB,CAAmB,wBAAnB,CAAmB,sBAAnB,CAAmB,sBAAnB,CAAmB,sBAAnB,CAAmB,8BAAnB,CAAmB,Y,kGuJA9B,sIAUO,MAAMqqB,EAmCX,YAAqB5kJ,GAAA,KAAAA,OAjCX,KAAAsR,MAAuB,CAC/B,CACEvL,KAAM,UACN6b,MAAOtiB,KAAKU,KAAKU,EAAE,oBACnB85C,eAAgB,KAElB,CACEz0C,KAAM,UACN6b,MAAOtiB,KAAKU,KAAKU,EAAE,kCACnB85C,eAAgB,KAElB,CACEz0C,KAAM,UACN6b,MAAOtiB,KAAKU,KAAKU,EAAE,oBACnB85C,eAAgB,KAElB,CACEz0C,KAAM,mBACN6b,MAAOtiB,KAAKU,KAAKU,EAAE,yDACnB85C,eAAgB,KAElB,CACEz0C,KAAM,eACN6b,MAAOtiB,KAAKU,KAAKU,EAAE,qDACnB85C,eAAgB,KAElB,CACEz0C,KAAM,YACN6b,MAAOtiB,KAAKU,KAAKU,EAAE,4BACnB85C,eAAgB,MAOpB,WACE,OAAOl7C,KAAKgS,O,sCAvCHszI,GAA2B,Y,yBAA3BA,EAA2B,QAA3BA,EAA2B,a,kCCiBxC,sFAUO,MAAMC,UAA6B,IAGxC,YAAqB/kJ,GACnBV,QADmB,KAAAU,aAKrB,WACE,IAAIovB,EAAU/oB,OAAO7G,KAAKQ,WAAWsG,eACjC0+I,EAAoB,IAAI,KAAgB,GAE5CA,EACGrlJ,KACCH,KAAKI,iBACL,YAAU,KAEXC,UAAU0zG,IACTnkF,EAAQmL,YAAY,SAAUg5E,KAOlCnkF,EAAQ,GAAGxkB,iBAAiB,SAHR,WAClBo6I,EAAkBp9I,MAAK,MAE2B,GAKpDwnB,EAAQ,GAAGxkB,iBAAiB,QAHT,WACjBo6I,EAAkBp9I,MAAK,MAEyB,GAElDkF,WAAW,KACTsiB,EAAQjlB,SAAS,yBACjBilB,EAAQpkB,KAAKxL,KAAKyxB,UAAU9mB,SAAS,4BACpC,I,sCAnCM46I,GAAoB,Y,uBAApBA,EAAoB,mF,oICP1B,MAAME,EAcX,YAAsCv6I,EACjBnC,GADiB,KAAAmC,WACjB,KAAAnC,WAbd,KAAAy3H,MAA2B,KAE3B,KAAAxf,QAAuB,GAItB,KAAA0kC,eAAkB7kJ,IACpBb,KAAKwgI,OAAqB,WAAZ3/H,EAAIc,KACpB3B,KAAKwgI,MAAMnmH,QAAO,IAMpBra,KAAKkL,SAASwwE,gBAAgBtwE,iBAAiB,UAAWpL,KAAK0lJ,gBAGjE,cACE1lJ,KAAKkL,SAASwwE,gBAAgBL,oBAAoB,UAAWr7E,KAAK0lJ,gBAClE1lJ,KAAKugI,YAAcvgI,KAAKugI,WAAWriG,UACnCl+B,KAAKwgI,OAASxgI,KAAKwgI,MAAMtiG,UAGpB,OAAOjd,GACRjhB,KAAKiG,cACP5B,EAAEouB,OAAOzyB,KAAKwgI,MAAOmlB,WAAa1zI,GAAOA,IAAOgP,GAChD5c,EAAEouB,OAAOzyB,KAAKghH,QAAU/uG,GAAOA,EAAGsuC,gBAAkBt/B,IAIjD,OAAOA,GACZ,OAAO5c,EAAEmH,KAAKxL,KAAKghH,QAAS/uG,GAAMA,EAAGsuC,gBAAkBt/B,GAGzD,kBACE,OAAsB,OAAfjhB,KAAKwgI,MAGP,SAASolB,GACd5lJ,KAAKghH,QAAQ9/G,KAAK0kJ,GAClB,MAAMplG,EAAmBolG,EAAOplG,iBAE5BxgD,KAAKugI,WACPvgI,KAAKugI,WAAW/vH,IAAIgwC,GAEpBxgD,KAAK6lJ,gBAAgBrlG,GAGvB,MAAMD,EAAgBqlG,EAAOrlG,cACV,OAAfvgD,KAAKwgI,MACPxgI,KAAK8lJ,gBAAgB,CAACvlG,IAEtBvgD,KAAKwgI,MAAMmlB,WAAWzkJ,KAAKq/C,GAIxB,mBAAmBtuC,GACpBjS,KAAKugI,WACPvgI,KAAKugI,WAAW/vH,IAAIyB,GAEpBjS,KAAK6lJ,gBAAgB,CAAC5zI,IAExBjS,KAAKugI,WAAWwlB,wBAAwB9zI,GAGhC,gBAAgB0zI,GAExB3lJ,KAAKugI,WAAa,IAAI,IACpBolB,EACA,CACEtwE,OAAQ,IACRD,SAAU,GACVD,mBAAmB,EACnBG,WAAY,IAAMt1E,KAAKwgI,OAASxgI,KAAKwgI,MAAMC,WAQvC,UAAUx/G,GAClB,OAAOjhB,KAAKghH,QAAQx1G,KAAKo6I,GAAUA,EAAOrlG,gBAAkBt/B,GAGpD,gBAAgB0kI,GACxB3lJ,KAAKwgI,MAAQR,QAAQ2lB,EAAY,CAC/BllG,MAAO,CAACxuC,EAAQgP,EAAe0W,EAAYwgE,KACzC,MAAMytD,EAAS5lJ,KAAKgmJ,UAAU/kI,GAC9B,QAAO2kI,GAASA,EAAOnlG,MAAMxuC,EAAIgP,EAAW0W,EAAQwgE,IAEtDv3C,QAAS,CAAC3uC,EAAQgP,KAChB,MAAM2kI,EAAS5lJ,KAAKgmJ,UAAU/kI,GAC9B,OAAQ2kI,IAAUA,EAAOhlG,SAAWglG,EAAOhlG,QAAQ3uC,EAAIgP,IAEzDglI,QAAS,KAAM,EACf1zG,UAAW,WACX2zG,MAAM,EACNC,eAAe,EACfC,eAAe,EACfC,gBAAiBn7I,SAASwT,KAC1B4nI,0BAA0B,IAG5BtmJ,KAAKwgI,MAAM52H,GAAG,OAAQ,CAACqI,EAAgBzK,KACrCyK,EAAGxB,QAAQqoF,YAAc,IAAmBh6D,UAAU7sB,GAAIoQ,aAG5DriB,KAAKwgI,MAAM52H,GAAG,OAAQ,CAACqI,EAAgBgP,KACrC,MAAM65E,EAAO75E,EAAUja,QAAQ,cAC3B8zF,GACFA,EAAKvqF,UAAUC,IAAI,mBAIvBxQ,KAAKwgI,MAAM52H,GAAG,MAAO,CAACqI,EAAgBgP,KACpC,MAAM65E,EAAO75E,EAAUja,QAAQ,cAC3B8zF,GACFA,EAAKvqF,UAAUkiB,OAAO,mBAI1BzyB,KAAKwgI,MAAM52H,GAAG,SAAU,CAACsd,EAAmB8xE,KAC1C,MAAM4sD,EAAS5lJ,KAAK4lJ,OAAO5sD,EAASz3C,eAChCqkG,GAAUA,EAAO7sD,UACnB6sD,EAAO7sD,SAAS7xE,EAAO8xE,KAI3Bh5F,KAAKwgI,MAAM52H,GAAG,OAAQ,CAAOqI,EAAgBlL,EAAoBS,EAAoB2wF,IAAwB,4CAC3G,UACQn4F,KAAK04F,WAAWzmF,EAAIlL,EAAQS,EAAQ2wF,GAC1C,MAAO7rF,GACPsR,QAAQoB,MAAM,kCAAmC/M,EAAI3F,QAIzDtM,KAAKwgI,MAAM52H,GAAG,SAAU,CAACgzI,EAA2B37H,KAClD,MAAM2kI,EAAS5lJ,KAAK4lJ,OAAO3kI,GACvB2kI,GAAUA,EAAOzsD,kBACnBysD,EAAOzsD,iBAAiByjD,KAI5B58I,KAAKwgI,MAAM52H,GAAG,SAAU,CAACqI,EAAgBgP,EAAuBzZ,KAC9D,MAAMo+I,EAAS5lJ,KAAK4lJ,OAAO3kI,GACvB2kI,GAAUA,EAAO1rI,UACnB0rI,EAAO1rI,SAASjI,KAKR,WAAWA,EAAgBlL,EAAoBS,EAAoB2wF,G,mDAC/E,MAAM/kE,EAAKpzB,KAAK4lJ,OAAO7+I,GACjBwU,EAAOvb,KAAK4lJ,OAAOp+I,GAEzB,IAAM4rB,IAAM7X,EACV,OAGF,GAAI6X,IAAO7X,EACT,OAAO6X,EAAG0tB,QAAQ7uC,EAAIlL,EAAQS,EAAQ2wF,UAGnB/kE,EAAGiuB,QAAQpvC,EAAIlL,EAAQS,EAAQ2wF,IAGlD58E,EAAK6lC,UAAUnvC,EAAIlL,EAAQS,EAAQ2wF,GAGnC,IAAmBlvC,SAASh3C,EAAIA,EAAGxB,QAAQqoF,cAAgB,EAAGtxF,O,sCA5KvDi+I,GAAkB,KAcT,KAAQ,Y,yBAdjBA,EAAkB,QAAlBA,EAAkB,a,oCCH/B,8JAgBO,MAAMc,UAA0B,IAiBrC,YAAqB/lJ,EAC0BsR,EAC1BpR,EACAiC,EACAC,EACA/C,EACA84C,EACAvO,EACAxqC,GACnBE,MAAMgS,EAAQjS,EAAOW,GATF,KAAAA,aAC0B,KAAAsR,SAC1B,KAAApR,OACA,KAAAiC,SACA,KAAAC,aACA,KAAA/C,QACA,KAAA84C,gBACA,KAAAvO,kBACA,KAAAxqC,uBAvBd,KAAAw9F,WAAY,EACZ,KAAAC,UAAW,EACX,KAAA3zC,QAAS,EAET,KAAA9xC,KAAO,CACZ0K,MAAOtiB,KAAKU,KAAKU,EAAE,+BACnBwW,KAAM5X,KAAKU,KAAKU,EAAE,8BAClBk8F,QAASt9F,KAAKU,KAAKU,EAAE,oBACrBm8F,WAAYv9F,KAAKU,KAAKU,EAAE,wBACxB4wF,0BAA2BhyF,KAAKU,KAAKU,EAAE,gCACvCusF,YAAa3tF,KAAKU,KAAKU,EAAE,yBACzBwlD,cAAe5mD,KAAKU,KAAKU,EAAE,oBAC3BylD,YAAa7mD,KAAKU,KAAKU,EAAE,yBAe3B,WACEtB,MAAMqkB,WAENnkB,KAAK6D,MAAQ7D,KAAK4C,WAAWiB,MAAMsC,MAEnCnG,KAAKo9F,UAAYp9F,KAAK6D,MAAMogC,QAC5BjkC,KAAKq9F,SAAWr9F,KAAK6D,MAAMsgC,OAItB,UAAUhrB,GACfnZ,KAAKo9F,UAAYjkF,EAAOikF,UACxBp9F,KAAKq9F,SAAWlkF,EAAOkkF,SAGzB,mBACE,OAAOx2F,OAAO,kCAGT,UAAU0kC,GACf,GAAIvrC,KAAK0pD,OACP,OAGF1pD,KAAK0pD,QAAS,EACd,IAAIu0D,EAAW,GAEXj+G,KAAK6D,MAAMsgC,SAAWnkC,KAAKq9F,WAC7Br9F,KAAK6D,MAAMsgC,OAASnkC,KAAKq9F,SAEzB4gB,EAAS/8G,KAAKlB,KAAK24C,cAAcv+B,KAAKpa,KAAK6D,SAGzC7D,KAAK6D,MAAMogC,UAAYjkC,KAAKo9F,WAC9B6gB,EAAS/8G,KAAKlB,KAAK24C,cAAcqhB,cAAch6D,KAAK6D,QAGtD0L,QACGu0B,IAAIm6E,GACJxuG,KAAK,KACJzP,KAAKsnD,QAAQ/b,GACbvrC,KAAK0pD,QAAS,IAEflvC,MAAM,KACLxa,KAAKJ,qBAAqBm6D,SAAS/5D,KAAKU,KAAKU,EAAE,2BAC/CpB,KAAK0pD,QAAS,K,sCA1ET68F,GAAiB,eAkBR,KAAkB,wE,uBAlB3BA,EAAiB,8kBC5C9B,gBACE,gBAGE,gBACE,eAEA,cACE,cAEI,iCAAS,EAAAj/F,QAAA,MAEb,OACF,OACF,OAEA,+BAEI,oCAAY,EAAAgxB,UAAA,MAGhB,OAEA,gBACE,mBACQ,iCAAS,EAAAkuE,UAAA,MAEjB,OACA,mBAGQ,iCAAS,EAAAl/F,QAAA,MACjB,OACF,OACF,OACF,Q,MA9BU,6DAME,yCAMJ,0BAAgB,wBAAhB,CAAgB,uBASV,+CAGA,iDAAkC,uB,sECDhD,sRAsPO,MAAMm/F,EACX,YAAY19I,IA5LP,SAAyBA,GAE9B,MAAM2O,EAAiB3O,EAASrE,IAAI,KAC9B+yE,EAAc1uE,EAASrE,IAAI,KAC3BgiJ,EAAc39I,EAASrE,IAAI,gBAEjC8b,OAAO8kC,cAAcqhG,WAAY3xF,IAC3ByiB,EAAYogD,YACd7iE,EAAM4xF,QAAQ,CAAEngJ,KAAMgxE,EAAYhxE,KAAMyB,GAAIuvE,EAAY88B,OAAQsyC,MAAOpvE,EAAYqvE,OAGjFpvI,EAAeipG,kBACjB3rD,EAAM+xF,OAAO,UAAWrvI,EAAe5C,YAGzCkgD,EAAMgyF,SAAS,eAAgBN,EAAYzmJ,QAAQwG,QAGjCsC,EAASrE,IAAI,KACrB66C,SAAS,8BAA+B,IAC3C,CACL,MAwKF0nG,CAAgBl+I,I,uBAFP09I,I,oDAAAA,GAAuB,qBAhKzB,CAEP,iBAEA,IAEA,IAEA,IACA,IACA,IAEA,IACA,IACA,IAEA,IAAcS,eAAe,CAC3B,IACA,IACA,IACA,OAKF,iBACA,IACA,IACA,IACA,IACA,IACA,IACA,IA4CA,Q,kCClKJ,sHAKO,MAAMC,EAAqB,cAO3B,MAAMC,EAIX,YAAsB5mJ,EACA2tE,EACAt/D,GAFA,KAAArO,aACA,KAAA2tE,iBACA,KAAAt/D,aAGf,kBACL,MAAM+gB,EAAU5vB,KAAKQ,WAAWsG,cAChC,IAAIP,EAAOvG,KAAKuG,MAAQ,CAAEE,KAAMmpB,EAAQnf,QAAQ+jG,SAAWtsG,GAAI0nB,EAAQnf,QAAQ8jG,QAC/Ev0G,KAAKmuE,eAAe5sD,OAAOqO,EAASrpB,GAAM,EAAOqpB,EAAQnf,QAAQF,Y,sCAZxD62I,GAAmB,gC,uBAAnBA,EAAmB,8H,kCCZhC,0EAMO,MAAMC,UAAsB,IAS1B,sBAAsB9pI,EAA6B/a,EAA6B,MACrF,GAAI+a,aAAoB,KAAe/a,EAAQ,CAC7C,IAAI8sD,EAAO/xC,EACPxb,EAAU,IAAiB+vD,yBAAyBxC,EAAM9sD,GAkB9D,OAdIT,EAAQ2tD,UACV3tD,EAAQ2tD,QAAUJ,EAAKI,QAAQxgD,IAAK+2B,IAC3B,CACL/9B,GAAI+9B,EAAO/9B,GACX6zE,SAAU91C,EAAO81C,SACjBD,OAAQ71C,EAAO61C,OACflsB,YAAa3pB,EAAO2pB,YACpBosB,UAAW/1C,EAAO+1C,UAClBlnE,WAAYmxB,EAAOnxB,WACnBgb,QAASmW,EAAOnW,YAKf/tB,EAGT,OAAOwb,GAAY,GASd,eAAeqB,EAA4Bpc,EAA6B,MAC7E,OAAO6kJ,EAAc32F,eAAe9xC,EAASpc,M,oCC3EjD,sIAYO,MAAM8kJ,UAA2B,IAKtC,cACExnJ,QALF,KAAA2G,KAAO,eAEP,KAAAsK,UAAiD,cAI/C/Q,KAAKypF,qBAKF,MAAM89D,UAAoC,IAE/C,YAAoB7sI,EACAjX,EACAw4E,GAClBn8E,OAAM,IAAIwnJ,GAAqBv2I,WAHb,KAAA2J,aACA,KAAAjX,eACA,KAAAw4E,cAab,QAAQ/zE,EAAWgpD,GAAgB,GACxC,OAAOlxD,KACJ8lB,iBAAiB5d,EAAIgpD,GACrB/wD,KACC,YAAK,IAEN0sB,YAYE,iBAAiB3kB,EAAWgpD,GAAgB,GASjD,OAPIlxD,KAAKmxD,MAAMjpD,IAAOgpD,IACpBlxD,KAAKsxD,aACHppD,EACAlI,KAAKggC,KAAK93B,IAIPlI,KAAK8Q,MAAM5I,GAAIhI,UAOd,KAAKgI,GACb,OAAOlI,KACJyD,aACAmC,cACAsC,GAAGA,GACH6I,UACArM,MACAvE,KACC,YAAIwjC,GAAc3jC,KAAKwnJ,oBAAoBt/I,EAAIy7B,EAAWn/B,YAIzD,WAAWoL,GAChB,OAAO,IAAIL,QAAmB,CAACC,EAASquB,KACtC79B,KACGyD,aACAsN,UACA02I,aAAa73I,GACbid,YACApd,KAAMjL,IACLxE,KAAK0tB,aAAa9d,GAClB5P,KAAK0nJ,gCAAgC93I,EAAKpL,GAC1CgL,MAEDgL,MAAMqjB,KAON,KAAKtiB,EAA0B6X,EAAwBtgB,GAC5D,MAAM/B,EAA0C/Q,KAAK8Q,MAAMyK,EAAKrT,IAAK/B,MAErE,GAAK4K,EAIL,OAAO1M,EAAEmH,KAAKuF,EAAYujB,IACxB,MAAMC,EAAeD,EAASC,aAAahZ,GAI3C,OAAOgZ,EAAaxtB,OAAOmB,KAAOkrB,EAAGlrB,IACnCqsB,EAAa6B,eAAiBtjB,IAO7B,eAAewhB,GACpB,OAAOA,EAASohB,SAASjmC,KAAK,KAC5BzP,KAAK2nJ,iBAAiBrzH,KAOnB,mBAAmB/Y,EAA0B6X,EAAwBkB,EAA2BxhB,GACrG,MAAMoL,EAAS,CACbiQ,OAAQ,CACN5S,KAAM,CAAEhW,KAAMgW,EAAKhW,MACnB6tB,GAAI,CAAE7tB,KAAM6tB,EAAG7tB,OAEjBuN,KAAMA,GAGR,OAAO9S,KAAK4iJ,eAAetuH,EAAUpW,GAGhC,eAAeoW,EAA2BpW,GAC/C,OAAOoW,EAASrF,kBAAkB/Q,GAC/BzO,KAAMyzI,IACLljJ,KAAK4nJ,iBAAiB1E,GACfA,IAIN,kBAAkBztH,EACAW,EACA81G,GACvB,MAAMhuH,EAAS,CACbiQ,OAAQ,CACN5S,KAAM,CAAEhW,KAAMvF,KAAKyD,aAAamC,cAAcsC,GAAGutB,GAAQpT,YACzD+Q,GAAI,CAAE7tB,KAAMvF,KAAKyD,aAAamC,cAAcsC,GAAGgkI,GAAa7pH,aAE9DvP,KAAMsjB,GAGF5a,EAAOxb,KAAKyD,aAAamC,cAAcsC,GAAGutB,GAAQ1kB,UAAUsR,WAClE,OAAOriB,KAAKi8E,YACT7uD,KAAuB5R,EAAM0C,GAC7B2O,YACApd,KAAM6kB,IACLt0B,KAAK4nJ,iBAAiBtzH,GACfA,IAQL,iBAAiBA,GACvBjwB,EAAEuhB,OAAO0O,EAAS1kB,KAAKlK,QAAQokB,IAC7B9pB,KAAK4zD,WAAWlvD,IAAIolB,GAAM8lD,SAAUzpE,IAClCA,EAAMmuB,EAASpsB,IAAOosB,EACfnuB,GACN,KACD,IAAIA,EAA4B,GAEhC,OADAA,EAAMmuB,EAASpsB,IAAOosB,EACfnuB,MASL,iBAAiBmuB,GACvBjwB,EAAEuhB,OAAO0O,EAAS1kB,KAAKlK,QAAQokB,IAC7B9pB,KAAK4zD,WAAWlvD,IAAIolB,GAAM8lD,SAAUzpE,WAC3BA,EAAMmuB,EAASpsB,IACf/B,GACN,KACM,OAYL,oBAAoB2jB,EAAa/Y,GACvC,OAAO1M,EAAE48I,MAAMlwI,EAAW0/D,GAAKA,EAAEvoE,IAU3B,gCAAgCkmG,EAAmBr9F,GACzDq9F,EAAS1oG,QAAQokB,IACf,MAAM+9H,EAAW92I,EAAUxF,OAAOklE,GAAKA,EAAEq3E,WAAWh+H,IAC9C3jB,EAAQnG,KAAKwnJ,oBAAoB19H,EAAM+9H,GAE7C7nJ,KAAK0V,YAAYoU,EAAM3jB,M,sCA/MhBohJ,GAA2B,gC,yBAA3BA,EAA2B,QAA3BA,EAA2B,a,wHCYjC,MAAMQ,UAAyB,IAAtC,c,oBA0BW,KAAA57G,oBAAqB,EAnBvB,YAAY3kC,GACjB1H,MAAM2H,YAAYD,GAElBxH,KAAK0vD,QAAU1vD,KACZ0vD,QACAxgD,IAAK+2B,IACJ,IAAI+hH,EAAiB,IAAI,IAAoBhoJ,KAAK+I,SACLk9B,GACA,EACAjmC,KAAKoiD,eACL,cAK7C,OAFA4lG,EAAe14F,KAAOtvD,KAEfgoJ,IAMA,oB,mDACX,OAAOhoJ,KAAK0rC,YAAY4wD,UAAU7sF,KAAK,KACrCzP,KAAK2C,OAAOopC,YAAY/rC,MAAOgE,SAAShE,MACjCA,KAAK0rC,kBAMX,MAAMu8G,EAAe,YAAWF,I,kCC/CvC,8G,uCCzBE,aACE,mBAIQ,mEACN,oBACF,OACF,O,uBALU,mDACA,+B,uCAMV,aACE,mBAIQ,mEAA6B,MACnC,oBACF,OACF,O,uBAJU,sCADA,8B,uCAOV,aACE,mBAIQ,oEAA6B,MACnC,oBACF,OACF,O,uBAJU,sCADA,6BDoBL,MAAMG,UAA2C,IAiBtD,YAAqBxnJ,EACAb,EACFe,GACjBd,MAAMY,GAHa,KAAAA,OACA,KAAAb,QACF,KAAAe,kBAlBZ,KAAA29C,SAAkB,uCAClB,KAAA2P,UAAmB,qBAOnB,KAAAi6F,aAAiC,OACjC,KAAAC,aAAiC,QAEjC,KAAAz/C,YAAa,EAEb,KAAA0/C,YAAqB,EACrB,KAAAC,YAAqB,EAO1BtoJ,KAAKmuD,cAAgBztD,EAAKU,EAAE,gCAC5BpB,KAAKouD,gBAAkB1tD,EAAKU,EAAE,kCAE9BpB,KAAK4X,KAAK2wI,OAAS7nJ,EAAKU,EAAE,wBAC1BpB,KAAK4X,KAAK4wI,QAAU9nJ,EAAKU,EAAE,yBAC3BpB,KAAK4X,KAAK6wI,SAAW/nJ,EAAKU,EAAE,0BAG9B,WACEpB,KAAKY,gBACFkoF,QACA3oF,KACCH,KAAKI,kBAENC,UAAU,KACTL,KAAK2oG,WAAa3oG,KAAKY,gBAAgB+nG,aACvC3oG,KAAKwwC,SAAWxwC,KAAKY,gBAAgBY,UACrCxB,KAAKH,MAAMS,kBAGfN,KAAKY,gBACFw+E,kBACAl/E,UACAC,KACCH,KAAKI,kBAENC,UAAWJ,IACVD,KAAKqoJ,WAAapoJ,IAAYD,KAAKooJ,aACnCpoJ,KAAKsoJ,WAAaroJ,IAAYD,KAAKmoJ,aACnCnoJ,KAAKH,MAAMS,kBAIjB,YACE,OAAIN,KAAKwwC,SACAxwC,KAAKouD,gBAELpuD,KAAKmuD,cAIT,WACL,OAAO,EAGF,oBAAoBnlB,GACzBhpC,KAAKY,gBAAgB8nJ,oBAAoB1/G,GAGpC,cAAchhC,GACnBhI,KAAK2oJ,iBAGA,iBACL3oJ,KAAKY,gBAAgBa,SAGhB,iBACLzB,KAAKY,gBAAgBgoJ,iBAGhB,yBACL,OAAO5oJ,KAAK2oG,WAAa,YAAc,I,sCApF9Bu/C,GAAkC,gC,uBAAlCA,EAAkC,yrBC9C/C,eAGE,qBAUA,qBAUA,qBASF,Q,MA7BM,gCAUA,gCAUA,kC,0LCvBN,8D,6HCEI,aAGE,eAAqB,qFAAoD,OAC3E,O,qCAHI,uCACA,oBACC,iCAAiB,uBDOnB,MAAMW,EAJb,cAUS,KAAAC,aAAsB,GACtB,KAAAlH,KAAa,GACb,KAAAngI,QAAmB,CAAC,mBACpB,KAAAsnI,gBAAyB,EACzB,KAAAC,iBAA0B,EAKjC,kBACEhpJ,KAAKihB,UAAYjhB,KAAKq+B,gBAAgBv3B,cACtC9G,KAAKipJ,KAAOjpJ,KAAKkpJ,WAAWpiJ,cAE5B9G,KAAKmpJ,kCACLnpJ,KAAKopJ,sBAAsBppJ,KAAK8oJ,cAG3B,SAAStjF,GACdxlE,KAAK8oJ,aAAetjF,EAGf,SAASx9D,GACdhI,KAAKmpJ,kCAGC,kCACNnpJ,KAAK+oJ,eAAkB/oJ,KAAKipJ,KAAKr/G,YAAc,EAC/C5pC,KAAKgpJ,gBAAmBhpJ,KAAKipJ,KAAKhgD,YAAcjpG,KAAKipJ,KAAKr/G,YAAc5pC,KAAKihB,UAAU26D,YAGlF,cACL57E,KAAKipJ,KAAKr/G,YAAc5pC,KAAKihB,UAAU26D,YAGlC,aACL57E,KAAKipJ,KAAKr/G,YAAc5pC,KAAKihB,UAAU26D,YAGjC,sBAAsBytE,GAC5B,MAAM7jF,EAAsB3+D,OAAO7G,KAAKipJ,MAAMz9I,KAAK,WAAW69I,MAGxDC,EAF6B9jF,EAAI35D,WAEEirE,KAAOvC,OAAO/O,EAAI+jF,cAEvDvpJ,KAAKipJ,KAAKr/G,WAAa5pC,KAAKihB,UAAU26D,YAAc0tE,IACtDtpJ,KAAKipJ,KAAKr/G,WAAa0/G,EAAmBtpJ,KAAKihB,UAAU26D,YAAc,K,sCAnDhEitE,I,uBAAAA,EAAuB,qD,OAAA,M,onBCZpC,kBACE,iBAA+B,kCAAU,EAAAW,SAAA,MACvC,qBAKF,OACA,kBAEoB,gCAAS,EAAA5/G,gBAC3B,iBACF,OACA,kBAEqB,gCAAS,EAAA6/G,iBAC5B,mBACF,OACF,Q,MAlBsB,0BAEd,+BAMc,wCAKC,2C,4ECbvB,0E,wBCAA,gB,oBAAK,gCDwBE,MAAMC,EAJb,cAaU,KAAAC,UAAW,EAET,KAAAphI,IAAgC,IAAI,IACpC,KAAAwB,MAAkC,IAAI,IACtC,KAAAk3B,KAAiC,IAAI,IAEtC,KAAA2oG,eAAgB,EAChB,KAAAC,YAAc,cACd,KAAA32B,aAAe,UAExB,cACElzH,KAAKq7E,sBAKA,YAAYrzE,GACjBA,EAAMuE,iBACNvE,EAAM6E,kBAGgB,IAAlB7E,EAAM8hJ,SAAiC,IAAhB9hJ,EAAM+iB,OAA+B,IAAhB/iB,EAAM+iB,QAEpD/qB,KAAK+pJ,KAAO/pJ,KAAKivG,OAASjnG,EAAMo7D,SAAWp7D,EAAMgiJ,OAAShiJ,EAAMiiJ,QAAQ,GAAG7mF,QAC3EpjE,KAAKkqJ,KAAOlqJ,KAAKmqJ,OAASniJ,EAAMq7D,SAAWr7D,EAAMoiJ,OAASpiJ,EAAMiiJ,QAAQ,GAAG5mF,QAE3ErjE,KAAKqqJ,KAAOriJ,EAAMo7D,SAAWp7D,EAAMgiJ,OAAShiJ,EAAMiiJ,QAAQ,GAAG7mF,QAC7DpjE,KAAKsqJ,KAAOtiJ,EAAMq7D,SAAWr7D,EAAMoiJ,OAASpiJ,EAAMiiJ,QAAQ,GAAG5mF,QAE7DrjE,KAAK2pJ,UAAW,EAEhB3pJ,KAAKuqJ,kBACLvqJ,KAAKwqJ,kBAAkBxiJ,GAEvBhI,KAAK+pB,MAAMvhB,KAAKxI,KAAKy1F,WAAWztF,KAI5B,UAAUA,GAChBhI,KAAKyqJ,gBACLzqJ,KAAKq7E,sBAELr7E,KAAKuoB,IAAI/f,KAAKxI,KAAKy1F,WAAWztF,IAGxB,YAAYA,GAClBA,EAAMuE,iBACNvE,EAAM6E,kBAEN7M,KAAK+pJ,KAAO/pJ,KAAKqqJ,KACjBrqJ,KAAKkqJ,KAAOlqJ,KAAKsqJ,KAEjBtqJ,KAAKqqJ,KAAOriJ,EAAMo7D,SAAWp7D,EAAMgiJ,OAAShiJ,EAAMiiJ,QAAQ,GAAG7mF,QAC7DpjE,KAAKsqJ,KAAOtiJ,EAAMq7D,SAAWr7D,EAAMoiJ,OAASpiJ,EAAMiiJ,QAAQ,GAAG7mF,QAE7DpjE,KAAKihD,KAAKz4C,KAAKxI,KAAKy1F,WAAWztF,IAIzB,kBAAkBA,GACxBhI,KAAK0qJ,iBAAmB1qJ,KAAK2qJ,YAAY79I,KAAK9M,MAC9CA,KAAK4qJ,eAAiB5qJ,KAAK6qJ,UAAU/9I,KAAK9M,MAE1CwgB,OAAOpV,iBAAiB,YAAapL,KAAK0qJ,kBAC1ClqI,OAAOpV,iBAAiB,YAAapL,KAAK0qJ,kBAC1ClqI,OAAOpV,iBAAiB,UAAWpL,KAAK4qJ,gBACxCpqI,OAAOpV,iBAAiB,WAAYpL,KAAK4qJ,gBAGnC,sBACNpqI,OAAO66D,oBAAoB,YAAar7E,KAAK0qJ,kBAC7ClqI,OAAO66D,oBAAoB,YAAar7E,KAAK0qJ,kBAC7ClqI,OAAO66D,oBAAoB,UAAWr7E,KAAK4qJ,gBAC3CpqI,OAAO66D,oBAAoB,WAAYr7E,KAAK4qJ,gBAGtC,kBACN,IAAW5oG,cAAchiD,KAAK6pJ,YAAa,aAGrC,gBACN,IAAW7nG,cAAc,QAGnB,WAAWh6C,GACjB,MAAO,CACL8iJ,OAAQ9iJ,EACR+iJ,SAAU,CACRthH,EAAGzpC,KAAKqqJ,KAAOrqJ,KAAKivG,OACpBvlE,EAAG1pC,KAAKsqJ,KAAOtqJ,KAAKmqJ,QAEtBn0B,SAAU,CACRvsF,EAAGzpC,KAAKqqJ,KAAOrqJ,KAAK+pJ,KACpBrgH,EAAG1pC,KAAKsqJ,KAAOtqJ,KAAK+pJ,Q,sCAtGfL,I,uBAAAA,EAAgB,wD,qCAAhB,mB,CAAmB,iCAAnB,qB,qQCxBb,sBAGA,S,KAFK,+B,4HC8BE,MAAMvjB,EACX,iBACE,OAAOnmI,KAAKgrJ,SAAS/jJ,OAAS,EAGhC,aACE,OAAOjH,KAAKgrJ,SAAS78I,KAAK,MAG5B,WACE,MAAO,iBAAiBnO,KAAKu0G,OAG/B,WACE,OAAOv0G,KAAKgrJ,SAAS78I,KAAK,QAG5B,WACE,OAAOnO,KAAKgrJ,SAAS78I,KAAK,QAG5B,eACE,OAAOzN,KAAK+nD,QAAU,KAGxB,eACE,OAAO5hD,OAAO,4B,sCA1BLs/H,I,yBAAAA,EAAkB,QAAlBA,EAAkB,qBADL,U,kCCQ1B,kCAAO,MAAM8kB,EACX,YAAsBzoJ,EACA+a,GADA,KAAA/a,SACA,KAAA+a,WAGtB,cAAc/a,EAAuB+a,GACnC,OAAO,IAAI4mD,MACT3hE,EACA,IAAIxC,KAAKwC,EAAQ+a,IAIrB,IAAI/a,EAAuBw0B,EAAsBskB,GAC/C,OAAQtkB,GACN,IAAK,aACH,OAAOh3B,KAAKkrJ,YAAYlrJ,KAAKy7C,YAE/B,IAAK,sBACH,OAAOz7C,KAAKkrJ,YAAYlrJ,KAAK07C,qBAE/B,IAAK,aACH,OAAO17C,KAAKkrJ,YAAYlrJ,KAAKyvE,YAE/B,IAAK,aACH,OAAOzvE,KAAKy/C,WAEd,QACE,OAAOihG,QAAQh8I,IAAIlC,EAAQw0B,EAAUskB,IAepC,WAAWtkB,GAChB,IAAIwkB,EAAiBx7C,KAAKwC,OAAOxC,KAAKyvE,WAAWz4C,IAEjD,OAAIwkB,EACK1rC,OAAOoG,OAAO,GAAIslC,EAAgB,CAAEliC,SAAUtZ,KAAKy/C,YAAcjE,GAAkBA,EAAeliC,WAElG,KAYJ,oBAAoB0d,GACzB,IAAIwkB,EAAiBx7C,KAAKy7C,WAAWzkB,GAErC,QAASwkB,GAAkBA,EAAeliC,SAS5C,iBACE,OAAOtZ,KAAKud,SAASpb,SAAWnC,KAAKud,SAAS9X,OAAO+O,OAGhD,WAAWwiB,GAChB,OAAOA,EAGD,YAAYvY,GAClB,MAAMzT,EAAOhL,KAIb,OAAO,IAAImkE,MAAM1lD,EAAQ,CACvB0rD,MAAO,SAAU9lE,EAAG8mJ,EAAIC,GACtB,OAAO3sI,EAAO0rD,MAAMn/D,EAAM,CAACogJ,EAAc,W,yUC1H7C,U,oBAAiC,qC,wBAM7B,8B,qBACkB,6BAAsB,uBAAtB,CAAsB,+B,uCAIxC,iBACK,kFAEH,oCAKE,gEAEA,kBACE,kBACF,OAEA,kBACE,qBACF,OACF,OACF,O,wBAXI,+CAIQ,+CAI4B,6C,yBAxB5C,kBAGE,gBACE,mCAKA,sBAmBF,OACJ,Q,oBAzBwB,8BAKb,gC,wBAsBT,U,oBAAgC,qCCuB7B,MAAMC,UAAoC,IAkB/C,YAAsB7qJ,EACAuI,EACA4qG,EACAD,EACAz3F,EACA8lB,EACAt+B,EACA0jF,EACAnoC,EACAn/C,EACAa,GACpBZ,MAAMU,EAAYuI,GAXE,KAAAvI,aACA,KAAAuI,WACA,KAAA4qG,iBACA,KAAAD,qBACA,KAAAz3F,uBACA,KAAA8lB,mBACA,KAAAt+B,eACA,KAAA0jF,iCACA,KAAAnoC,uBACA,KAAAn/C,QACA,KAAAa,OAtBf,KAAAkX,KAAO,CACZ0zI,UAAWtrJ,KAAKU,KAAKU,EAAE,8BACvBkmF,WAAYtnF,KAAKU,KAAKU,EAAE,wBACxBmqJ,YAAavrJ,KAAKU,KAAKU,EAAE,2BACzBouB,YAAaxvB,KAAKU,KAAKU,EAAE,+BAEpB,KAAAoqJ,WAAoBxrJ,KAAK4X,KAAK0zI,UAE9B,KAAAryI,UAAW,EAkBX,WACLnZ,MAAMqkB,WAENnkB,KAAKyrJ,gBAAkBzrJ,KAAKgJ,YAAYs+E,WACxCtnF,KAAK0rJ,UAAY1rJ,KAAKic,qBAAqB4wH,kCAE3C7sI,KAAK2zG,eAAevsB,YACjBjnF,KACCH,KAAKI,kBAENC,UAAWsrJ,IACV3rJ,KAAKsH,SAASqkJ,GACd3rJ,KAAK4rJ,iBAAiB9kJ,cAAckgC,mBAKnC,wBAAwBh/B,GAC7B,QAAIhI,KAAK+Y,SAIT/Y,KAAKsH,WAELU,EAAMuE,kBACC,GAGT,aACE,MAAO,mBAGF,SAAS6M,GACdtZ,MAAMwH,SAAS8R,GAEVpZ,KAAK0rJ,WACR1rJ,KAAK6rJ,iBAGP7rJ,KAAKH,MAAMS,gBAGN,WAAWiN,GAChBA,GAASvN,KAAKuN,QACdvN,KAAK+Y,QAAS,EACd/Y,KAAKH,MAAMS,gBAGA,mB,mDACX,GAAIN,KAAKiZ,WAAajZ,KAAK40G,WACzB,OAAOrlG,QAAQC,UAMjB,OAHAxP,KAAKiZ,UAAW,QACVjZ,KAAKwpE,WACKxpE,KAAK+hC,iBAAiB+pH,UACrB7mH,QAAUjlC,KAAK2zG,eAAeo4C,cAAc/rJ,KAAKgJ,YAAahJ,KAAKyZ,cACjFhK,KAAK,KACJzP,KAAK+Y,QAAS,EACd/Y,KAAKg/C,qBAAqBkM,WAAWlrD,KAAKU,KAAKU,EAAE,mCAEjDpB,KAAK0zG,mBAAmBjjF,QAAQzwB,KAAKgJ,aAAa,GAClDhJ,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKgJ,YAAYd,IACpBs1B,UAEHx9B,KAAKiZ,UAAW,EAChBjZ,KAAK0Z,YAAW,KAEjBc,MAAOwE,IACNhf,KAAKiZ,UAAW,EACZ+F,aAAiB,IACnBhf,KAAKmnF,+BAA+BvoB,UAAU5/C,EAAOhf,KAAKgJ,aAE1DhJ,KAAKg/C,qBAAqB+a,SAAS/5D,KAAKU,KAAKU,EAAE,8CAKvD,iBACE,MAAM4qJ,EAAsBnlJ,OAAO7G,KAAKQ,WAAWsG,eAAegrB,eAAe,GAC7Ek6H,GACF1+I,WAAW,KACT0+I,EAAoBh6H,UAAYg6H,EAAoBC,cACnD,KAIP,UAAU3iF,K,sCA1HC+hF,GAA2B,gH,uBAA3BA,EAA2B,oE,OAAA,K,OAGxB,KAAW,G,6sCD9D3B,gBACE,gBAEE,+BAEA,sBA+BA,+BACF,OACF,Q,MAnCkB,kCAIT,qCA6BS,mC,8OEJX,MAAM,UAAiC,IAGrC,OAAOz7H,EAAqBC,GACjC,MAAM7P,EAAahgB,KAAKud,SAAS+rE,cACjC,GAAItpE,GAAcA,EAAW/Y,OAAS,EAAG,CACvC,MAAMgI,EAAY+Q,EAAW,GAC7B4P,EAAQmE,UAAY,uBACN/zB,KAAKksJ,cAAcC,aAAal9I,sCAG9C2gB,EAAQmE,UAAY,IAVT,aAAd,c,0BAA4B,M,4EC7BxB,MAAMq4H,EACX,YAAuC1wE,GAAA,KAAAA,kBAOvC,qBACE,OAAO17E,KAAK+nH,aAAa,iBAGnB,aAAathH,GACnB,OAAOzG,KAAK07E,gBAAgBh9D,KAAKnO,UAAUlF,SAAS5E,I,sCAb3C2lJ,GAAkB,KACR,O,yBADVA,EAAkB,QAAlBA,EAAkB,Y,4KCMxB,MAAM,EAKX,YAAqB/c,GAAA,KAAAA,SAFX,KAAAgd,iBAAmB,cAetB,YAAYv9I,EAA0Bw9I,EAA+BvrF,GAC1E,MAAMjwD,EAAQ9Q,KAAKqsJ,iBAAiB3nJ,IAAIoK,GAUxC,OARAgC,EAAM0zD,yBAAyB,IAC7BxkE,KAAKqvI,OACF3uH,SAASxY,GAAG4G,GACZuR,WACA3b,MACAmoB,aAGE/b,EACJ5Q,UACAC,KACC,OAAA+O,EAAA,GACEqO,GAAYA,EAAS+uI,IAAc/uI,EAAS+uI,GAAW1zI,SAASmoD,KAYjE,YAAYjyD,EAA0Bw9I,EAA+BvrF,GAC1E,OAAO/gE,KACJusJ,YAAYz9I,EAAmBw9I,EAAWvrF,GAC1C5gE,KACC,OAAAi3C,EAAA,GAAK,IAENvqB,YACArS,MAAM,KAAM,I,sCApDN,GAAuB,Y,yBAAvB,EAAuB,QAAvB,EAAuB,qBADV,S,mECAtB,gBACE,wBAEa,yEAAmC,8EAAnC,CAAmC,wEAAnC,CAAmC,2EAIhD,OACF,O,wBAPe,yCAA0B,2B,uCASzC,cAGG,0FACD,qBACA,kBAA4B,QAAmB,OACjD,O,wBALG,mCAI2B,wC,yBAxBlC,QACE,gBACE,gBACE,gBACE,eAEF,OACF,OAEA,sBAUA,oBAOF,OACF,Q,oBAtBY,uCAIqB,8CAU1B,uDCYA,MAAM,UAAqC,IAiFhD,YAAqB1J,EACA07I,EACA7c,EACAlsI,EACAmsC,EACAouB,EACAn+D,EACAa,EACAuiI,GACnBnjI,QATmB,KAAAgR,QACA,KAAA07I,mBACA,KAAA7c,eACA,KAAAlsI,eACA,KAAAmsC,WACA,KAAAouB,gBACA,KAAAn+D,QACA,KAAAa,OACA,KAAAuiI,oBArFrB,KAAArrH,KAAO,CACL60I,IAAKzsJ,KAAKU,KAAKU,EAAE,oBACjB6N,UAAWjP,KAAKU,KAAKU,EAAE,oBACvBsrJ,cAAe1sJ,KAAKU,KAAKU,EAAE,wBAC3BurJ,eAAgB3sJ,KAAKU,KAAKU,EAAE,yBAC5BwrJ,iBAAkB5sJ,KAAKU,KAAKU,EAAE,2BAC9ByrJ,kBAAmB7sJ,KAAKU,KAAKU,EAAE,wBAC/B0rJ,yBAA0B9sJ,KAAKU,KAAKU,EAAE,+BACtC2rJ,yBAA0B/sJ,KAAKU,KAAKU,EAAE,gCAGxC,KAAA4rJ,eAAqC,CACnC,CACE5vH,MAAO,OACPlL,OAAQ,QAGRtN,WAAY,EAIZ1C,OAAO,EACP+qI,kBAAmB,EAEnBC,oBAAoB,EAEpBC,cAAe,UACfC,eAAgB,GAChBC,kBAAkB,EAClBC,mBAAmB,EACnBC,2BAA2B,EAC3BC,UAAW,UACXC,qBAAqB,EAErBC,iBAAkB,EAClBC,gBAAiB,EACjBC,iBAAiB,EACjBC,qBAAqB,EACrBC,cAAe,mBACfC,cAAe,oBACfC,UAAW,aACXC,aAAc,gBACdC,iBAAkBluJ,KAAKu5E,UACvBA,QAASv5E,KAAKu5E,WAGhB,CACE40E,WAAY,IACZ/wH,MAAO,OACPlL,OAAQ,QACRk8H,aAAc,GACdC,kBAAmB,GACnBX,iBAAkB,EAClBC,gBAAiB,GAGnB,CACEQ,WAAY,IACZj8H,OAAQ,QACR+6H,kBAAmB,EACnBS,iBAAkB,EAClBC,gBAAiB,IAIrB,KAAA3tI,WAAgC,GAEhC,KAAAsuI,cAAsB,GAGtB,KAAAC,aAAsB,EAEtB,KAAA/d,eAAwB,EAExB,KAAAge,eAAgB,EAehB,kBAEExuJ,KAAKyuJ,iBAGP,WACEzuJ,KAAK2vI,aAAa5N,eAAe1hI,UAAWkkB,IAExCvkB,KAAKwuJ,gBADHjqI,EAKJvkB,KAAKH,MAAMS,kBAIL,iBACRN,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKgJ,aACR8c,mBACA3lB,KAAKH,KAAKI,kBACVC,UAAgBsF,GAAM,4CACrB3F,KAAKgJ,YAAcrD,EAEd3F,KAAKkyD,kBACFlyD,KAAKgG,WAAWhG,KAAKgJ,cAGzBrD,EAAG2jF,eACLtpF,KAAK0uJ,kBAAkB/oJ,EAAG2jF,mBAK5B,WAAWtgF,G,mDACfhJ,KAAKkyD,UAAYlpD,EAAY0S,QAAQJ,WACrCtb,KAAKuuJ,kBAAoBvuJ,KAAKwsJ,iBAAiBmC,YAAY3uJ,KAAKkyD,UAAW,kBAAmB,aAC9FlyD,KAAKwwI,oBAAsBxwI,KAAKwsJ,iBAAiBmC,YAAY3uJ,KAAKkyD,UAAW,gBAAiB,mBAE9FlyD,KAAK4uJ,uBAAuB5lJ,GAC5BhJ,KAAKH,MAAMS,mBAGb,kBAAkB0f,GAChBhgB,KAAKggB,WAAaA,EAAW9Q,IAAK+C,IAAe,CAAG1M,KAAM0M,EAAG1M,KAAMspJ,YAAgB58I,EAAG1M,KAAN,eAEhFvF,KAAK8uJ,uBAAuB9uJ,KAAKggB,YAGzB,cAAchX,EAAiCioB,GACvDjxB,KAAK2vI,aAAaof,cAAc/lJ,EAAaioB,GAGrC,gBAAgBjoB,EAAiCioB,GACpDzQ,OAAOgrB,QAAQxrC,KAAK4X,KAAKi1I,oBAI9B7sJ,KAAKijI,kBACF+rB,iBAAiBhmJ,EAAaioB,GAC9B5wB,UAAU8N,IACTnO,KAAKg+D,cAAc9S,WAAWlrD,KAAK4X,KAAKm1I,0BACxC/sJ,KAAKivJ,QAAQrtF,QAAQ72D,UAIpB,cAAc/B,GACnBhJ,KAAKijI,kBACFisB,eAAelmJ,GACf3I,UAAU4O,IACTjP,KAAKg+D,cAAc9S,WAAWlrD,KAAK4X,KAAKk1I,0BACxC9sJ,KAAKmvJ,UAAYnvJ,KAAKggB,WAAW/Y,SAI7B,uBAAuB+B,GAC/B,GAA6C,iBAAjChJ,KAAK8Q,MAAMoN,OAAgB,UAAgB,CACrD,MAAM+S,EAAQjxB,KAAK8Q,MAAMoN,OAAOjP,UAChCjP,KAAK+uJ,cAAc/lJ,EAAaioB,GAChCjxB,KAAKmvJ,UAAYl+H,EACjBjxB,KAAKovJ,2BACLpvJ,KAAK8Q,MAAMi3B,GAAG,IAAK,OAAF,wBAAO/nC,KAAK8Q,MAAMoN,QAAM,CAAEjP,eAAWvD,IAAa,CAAEs8B,QAAQ,KAI1E,kBACL,OAAOhoC,KAAKuuJ,cACTvuJ,KAAKggB,WAAW/Y,OAAS,GACvBjH,KAAKwwI,eAAiBxwI,KAAKwuJ,eAIxB,UACR,MAAO,CACL,CACEntJ,KAAM,kBACNC,QAAS,CAACT,EAASowB,KACjBjxB,KAAK+uJ,cAAc/uJ,KAAKgJ,YAAaioB,GACrCjxB,KAAKivJ,QAAQrtF,QAAQ72D,SAEvBskJ,UAAWrvJ,KAAK4X,KAAK+0I,gBAEvB,CACEtrJ,KAAM,cACNC,QAAS,CAACT,EAASowB,IAAiBjxB,KAAKsvJ,gBAAgBtvJ,KAAKgJ,YAAaioB,GAC3Eo+H,UAAWrvJ,KAAK4X,KAAKg1I,mBAKpB,qBACL/lJ,OAAO,aAAa8D,SAAS,eAGxB,sBACL9D,OAAO,aAAa6D,YAAY,eAG3B,2BACL4C,WAAW,KAAK,aAAa,QAAb,EAACtN,KAAKivJ,eAAO,eAAEluJ,KAAKf,KAAKmvJ,YAAY,KAGhD,iBAAiBnnJ,GACtBhI,KAAKmvJ,UAAYnnJ,EAAMipB,MAGzB,cAAwB9qB,GACtB,MAAM2pB,EAAU,IAAI9vB,KAAKgtJ,gBACzBl9H,EAAQ,GAAGlL,WAAaze,EACxBnG,KAAKgtJ,eAAiBl9H,EAGxB,gBACE,OAAO9vB,KAAKgtJ,eAAe,GAAGpoI,WAGtB,uBAAuB5E,GAC/B,MAAM/Y,EAAS+Y,EAAW/Y,OAE1BjH,KAAKuvJ,uBAAuBtoJ,GAExBjH,KAAKmvJ,UAAY,GAAKloJ,EAAS,EACjCjH,KAAKmvJ,UAAY,EACRnvJ,KAAKmvJ,WAAaloJ,IAC3BjH,KAAKmvJ,UAAYloJ,EAAS,GAG5BjH,KAAKsuJ,cAAgBtuI,EAAW9Q,IAAID,IAC3B,CACLugJ,MAAOvgJ,EAAU4/I,YACjBY,OAAQxgJ,EAAU4/I,YAClBa,IAAKzgJ,EAAU4/I,eAGnB7uJ,KAAKH,MAAMS,gBAGH,uBAAuBqvJ,GAC/B,MAAM7/H,EAAU,IAAI9vB,KAAKgtJ,gBAEzBl9H,EAAQ,GAAGm9H,kBAAoB0C,EAAiB,EAAIA,EAAiB,EACrE7/H,EAAQ,GAAGm9H,kBAAoB0C,EAAiB,EAAIA,EAAiB,EACrE7/H,EAAQ,GAAGm9H,kBAAoB0C,EAAiB,EAAIA,EAAiB,EAErE7/H,EAAQ,GAAGoC,OAAYlyB,KAAK4vJ,uBAAuBD,GAA/B,KACpB7/H,EAAQ,GAAGoC,OAAYlyB,KAAK4vJ,uBAAuBD,GAA/B,KACpB7/H,EAAQ,GAAGoC,OAAYlyB,KAAK4vJ,uBAAuBD,GAA/B,KAEpB3vJ,KAAKgtJ,eAAiBl9H,EAGd,uBAAuB6/H,GAC/B,OAAOloI,KAAKyoD,IAAIzoD,KAAK6sD,MAAM,IAAMq7E,GAAiB,M,sCA3QzC,GAA4B,qG,uBAA5B,EAA4B,qD,OAAA,K,KAE5B,KAAmB,G,+FAJnB,CAAC,MAAkB,2fD7BhC,+B,KAAc,kC,w1CASV,gBACE,wBAEa,yEAAmC,8EAAnC,CAAmC,wEAAnC,CAAmC,2EAIhD,OACF,O,wBAPe,yCAA0B,2B,uCASzC,cAGG,0FACD,qBACA,kBAA4B,QAAmB,OACjD,O,wBALG,mCAI2B,wC,yBAxBlC,QACE,gBACE,gBACE,gBACE,eAEF,OACF,OAEA,sBAUA,oBAOF,OACF,Q,oBAtBY,uCAIqB,8CAU1B,uDELA,MAAM,UAAwC,EALrD,c,oBAME,KAAAE,kBAAuC,GAEvC,kBACM7vJ,KAAKwuJ,gBACP1uJ,MAAMs5C,kBAGFp5C,KAAKgJ,YAAY7G,OACnBnC,KAAK8vJ,mBASH,kBACN9vJ,KAAK4vC,SACEa,mBACAtwC,KACCH,KAAKI,iBACL,OAAAg3C,EAAA,GAAK,GACL,OAAAoa,EAAA,GAAW7rD,GAA2B3F,KAAKijI,kBAAkBwM,aAAa9pI,GAAMA,GAAOA,GACvF,OAAA6rD,EAAA,GAAW7rD,IACT3F,KAAKgJ,YAAcrD,EACnB,MAAMoqJ,EAAc/vJ,KAAK6vJ,kBACEtkJ,OAAOykJ,IAAkBA,EAAczqJ,MAAQyqJ,EAAc/gJ,WAC7DC,IAAI8gJ,GAAiBhwJ,KAAKijI,kBAAkBisB,eAAelvJ,KAAKgJ,YAAagnJ,EAAc/gJ,YAEtH,OAAO,OAAAghJ,EAAA,GAASF,MAGnB1vJ,UAAW2f,IACVhgB,KAAKmvJ,UAAYnvJ,KAAK6vJ,kBAAkB5oJ,OAAS,IAK3D,cAAc+B,EAAiCioB,IAI/C,gBAAgBjoB,EAAiCioB,GAC/CjxB,KAAK6vJ,kBAAoB7vJ,KAAK6vJ,kBAAkBtkJ,OAAO,CAAClH,EAAG0Y,IAAMA,IAAMkU,GAEvEjxB,KAAK8uJ,uBAAuB9uJ,KAAK6vJ,mBAKnC,gBACE7vJ,KAAK2vI,aACEC,gBACAvvI,UAAU4O,IACT,MAAMihJ,EAAe,CACjBrB,YAAa5/I,EAAUkhJ,SAASC,cAChCnhJ,UAAWA,GAGfjP,KAAK6vJ,kBAAoB,IACpB7vJ,KAAK6vJ,kBACRK,GAGFlwJ,KAAK8uJ,uBAAuB9uJ,KAAK6vJ,mBAGjC7vJ,KAAKmvJ,UAAYnvJ,KAAK6vJ,kBAAkB5oJ,OAAS,EACjDjH,KAAKovJ,6BAIf,kBACE,OAAOpvJ,KAAKwwI,eAAiBxwI,KAAKwuJ,cAE1B,UAER,OAAO1uJ,MACJy5E,UACAhuE,OAAO0G,GAAkB,gBAAZA,EAAG5Q,O,oCAjFV,I,uBAAA,EAA+B,kiBFd5C,+B,KAAc,kC,kyCEcD,G,gECGN,MAAM,UAA2B,IAUtC,YAAqB0H,GACnBjJ,MAAMiJ,GADa,KAAAA,WATd,KAAA+4H,kBAAmB,EACnB,KAAAC,eAAiB,IAAIC,EAAA,GAAyB,GAC7C,KAAAquB,2BAA6B,IAAIpnF,EAAA,EACjC,KAAAqnF,iBAAmB,EAI3B,KAAAC,sBAAwBvwJ,KAAKqwJ,2BAA2BxoJ,eAKlD2Y,OAAOgwI,YACTxwJ,KAAKywJ,sBAELjwI,OAAOpV,iBAAiB,qBAAsB,KAC5CpL,KAAKywJ,uBACJ,CAAEpqC,MAAM,IAIR,gBACL,OAAOrmH,KAAK+hI,eAAet9D,WAGtB,gBACL,MAAMisF,EAAa1wJ,KAAK2wJ,gBAIxB,OAFA3wJ,KAAK4wJ,mBAAmB,6BAA8BF,EAAY,IAE3D1wJ,KAAKuwJ,sBACGpwJ,KACC,OAAAq5C,EAAA,KACA,OAAAjuC,EAAA,GAAOivC,GAAmC,kBAAxBA,EAAQq2G,aAAmCr2G,EAAQk2G,aAAeA,GACpF,OAAA3mJ,EAAA,MAED5J,KACC,OAAA+O,EAAA,GAAKsrC,IACH,IAAIs2G,EAAgBt2G,EAAQu2G,eAO5B,OALAD,EAAcX,SAAW,CACvBa,cAAe,MACfZ,cAAeU,EAAcX,UAGxBW,KAKpB,cAAc9nJ,EAAiCioB,GACnDjxB,KAAKijI,kBACKC,cAAcl6H,EAAaioB,GAC3B5wB,UAAW4O,GAAqCjP,KAAK4wJ,mBAAmB,gBAAiB5wJ,KAAK2wJ,gBAAiBlrI,KAAKC,UAAUzW,KAG3I,mBAAmB4hJ,EAAoBH,EAAmBK,GACxD,IAAK/wJ,KAAKwuJ,gBACR,OAGF,MAAMyC,EAAgC,MAAlBF,EAAyBtrI,KAAKC,UAAUqrI,GAAkB,KAC9EvwI,OAAOgwI,YAAYI,mBAAmBC,EAAaH,EAAYO,GAGzD,sBACNzwI,OAAOgwI,YAAYU,yBAA4BC,IAC7C,MAAM32G,EAAU/0B,KAAKvG,MAAMiyI,GACrBN,EAAcr2G,EAAQq2G,YACtBH,EAAal2G,EAAQk2G,WACrBK,EAAiBtrI,KAAKvG,MAAMs7B,EAAQu2G,gBAE1C/wJ,KAAKqwJ,2BAA2BjoJ,KAAK,CACnCyoJ,YAAaA,EACbH,WAAYA,EACZK,eAAgBA,KAGpB/wJ,KAAK+hI,eAAe35H,MAAK,GAG3B,gBAEE,OADApI,KAAKswJ,iBAAmBtwJ,KAAKswJ,iBAAmB,EACzCjxI,OAAOrf,KAAKswJ,mB,sCApFV,GAAkB,Y,yBAAlB,EAAkB,QAAlB,EAAkB,YAMd,aAAd,c,0BAAgC,M,wCCkE5B,MAAM,EAGX,YAAYvnJ,GACV,EAAqBozD,UAAUpzD,GAM1B,iBAAiBA,GACtB,GAAI/I,KAAKoxJ,gBACP,OAGFpxJ,KAAKoxJ,iBAAkB,EAEKroJ,EAASrE,IAAI,KAEtCwjD,aAAa,EAA0B,eAAgB,CACtD,kBAIgBn/C,EAASrE,IAAI,KACrB66C,SAAS,2BAA6Bv2C,IAChD,GAAKwX,OAAOihB,YAAY4vH,aAIxB,OAAIroJ,EAAY7G,MACP,EAEA,KAhCN,EAAAivJ,iBAAkB,E,uBADd,I,oDAAA,GAAoB,sBAtBpB,CACT,CAAEzrG,QAAS,IAAmBC,SAAU,IAA8BC,OAAO,GAC7E,CACEF,QAAS,IACTG,WAjBqC/8C,GACrCyX,OAAO8wI,UAAUC,UAAUlvH,OAAO,UAAY,EACzC,IAAI,EAAmBt5B,GAEvBA,EAASrE,IAAI,IAAkB,IAAI,IAAiBqE,IAczDi9C,KAAM,CAAC,MAETomG,EACA,IACA,KACD,SAdQ,CACP,IACA,S,kCCrCJ,oI,wBCtBa,mB,yBACQ,4BAA8B,c,uCAKjD,iBACE,2BAAgB,qEAKhB,OACF,O,uBALkB,wCAA2B,0BAA3B,CAA2B,6BDkBxC,MAAMoF,EAAgC,2BAMtC,MAAMC,EAgBX,YAAoBjxJ,EACAX,EACD2qB,EACC9pB,GAHA,KAAAF,aACA,KAAAX,QACD,KAAA2qB,SACC,KAAA9pB,OAlBb,KAAAgxJ,cAAe,EAMd,KAAAC,MAAQ,KACR,KAAAC,WAAa,UACb,KAAAC,kBAAoB,iBAErB,KAAAC,UAAY,CACjB,CAACnwJ,IAAK3B,KAAK2xJ,MAAOrvH,MAAOtiC,KAAKU,KAAKU,EAAE,oCACrC,CAACO,IAAK3B,KAAK4xJ,WAAYtvH,MAAOtiC,KAAKU,KAAKU,EAAE,yCAUrC,WACL,MAAMwuB,EAAU5vB,KAAKQ,WAAWsG,cAChC9G,KAAKoH,UAAYwoB,EAAQnf,QAAQrJ,UACjCpH,KAAK+xJ,WAAaniI,EAAQnf,QAAQshJ,WAE9B/xJ,KAAK+xJ,aAAe/xJ,KAAK6xJ,kBAC3B7xJ,KAAKgyJ,iBAAmBhyJ,KAAK8xJ,UAAU,IAEvC9xJ,KAAKgyJ,iBAAmBhyJ,KAAK8xJ,UAAU,GACvC9xJ,KAAKiyJ,aAAejyJ,KAAK+xJ,YAG3B/xJ,KAAKkyJ,wBAGA,wBACLlyJ,KAAK0xJ,aAAe1xJ,KAAKgyJ,iBAAiBrwJ,MAAQ3B,KAAK2xJ,MACnD3xJ,KAAK+xJ,aAAe/xJ,KAAK6xJ,oBAC3B7xJ,KAAK+xJ,WAAa,IAGpB/xJ,KAAKmyJ,gBAGC,gBACFnyJ,KAAKgyJ,iBAAiBrwJ,MAAQ3B,KAAK4xJ,aACrC5xJ,KAAK+xJ,WAAa/xJ,KAAK6xJ,mBAI3B,cAGE,OAAO7xJ,KAAKoH,UACAyZ,QAAQ,SAAU,KAClBA,QAAQ,KAAM,KACdA,QAAQ,KAAM,IAG5B,YAAYjf,GACV5B,KAAK+xJ,WAAanwJ,EAClB5B,KAAKH,MAAMS,iB,sCAhEFmxJ,GAA8B,0C,uBAA9BA,EAA8B,meCtC3C,gBACE,iBACI,mBAEQ,iEAA8B,4BACpB,EAAAS,2BACX,yBAIP,OACJ,OACA,uBAQA,kBAGF,Q,MAnBc,2CADA,qBAGO,oCAM4B,oCASxC,iCAAkB,wB,oJCyBpB,MAAME,EADb,cAEU,KAAAC,MAAoB7xI,OAAe9f,KAcpC,KAAAqvH,SAAW/vH,KAAKqyJ,MAAMtiC,SAASjjH,KAAK9M,KAAKqyJ,OACzC,KAAA/hC,aAAetwH,KAAKqyJ,MAAM/hC,aAAaxjH,KAAK9M,KAAKqyJ,OACjD,KAAAjiC,WAAapwH,KAAKqyJ,MAAMjiC,WAAWtjH,KAAK9M,KAAKqyJ,OAC7C,KAAAlhC,SAAWnxH,KAAKqyJ,MAAMlhC,SAASrkH,KAAK9M,KAAKqyJ,OACzC,KAAA7/B,YAAcxyH,KAAKqyJ,MAAM7/B,YAAY1lH,KAAK9M,KAAKqyJ,OAhBtD,aACE,OAAOryJ,KAAKqyJ,MAAM5pG,OAGb,EAAE6pG,EAAoBC,GAC3B,OAAOvyJ,KAAKqyJ,MAAMjxJ,EAAEkxJ,EAAaC,GAG5B,OAAOD,GACZ,OAAOtyJ,KAAKqyJ,MAAMv1E,OAAOw1E,I,sCAZhBF,I,yBAAAA,EAAW,QAAXA,EAAW,qBADE,U,oFCjBnB,MAAMI,EAKX,YAAYjuI,GAJL,KAAA/iB,WAAoB,EACpB,KAAAg3B,KAAmB,KACnB,KAAA1E,UAA6C,GAGlD9zB,KAAKwB,UAAY+iB,G,gBC5Bd,MAAM,UAA0C,IAE9C,eAAe1gB,GACpB,MAAMsC,EAAS,IAAIqsJ,EAA2B3uJ,EAAMgiB,iBAC9C5lB,EAAUD,KAAKC,QAQrB,OAJIA,IACFkG,EAAM2tB,UAAY7zB,EAAQ6zB,WAGrB3tB,EAGF,WAAWtC,GAChB,OAAOA,EAAMgiB,kBAAoB7lB,KAAK48B,UAGjC,aAAa/4B,GAIlB,OAHAA,EAAMgiB,gBAAkB7lB,KAAK48B,UAGtB58B,KAAK48B,UAMd,gBACE,SAAU58B,KAAKC,UAAWD,KAAKC,QAAQuB,WAGlC,WAAWuX,GAAiB,GACjC,MAAMjI,EAAQ,OAAH,wBAAQ9Q,KAAKC,SAAO,CAAEuB,UAAWuX,EAAQyf,KAAM,OAC1Dx4B,KAAKwU,OAAO1D,GAMP,cAEL,OADA9Q,KAAK0zF,YAAY1zF,KAAK48B,WACf58B,KAAK48B,UAMP,UAAU9S,GACf,OAAO9pB,KAAKC,QAAQ6zB,UAAUhK,GAMzB,SAASA,GACd9pB,KAAKyyJ,SAAS3oI,GAAM,GAMf,OAAOA,GACZ9pB,KAAKyyJ,SAAS3oI,GAAM,GAMf,OAAOA,GACZ9pB,KAAKyyJ,SAAS3oI,GAAO9pB,KAAK8zB,UAAUhK,IAM9B,SAASA,EAAa0tE,GAC5B,MAAM1mF,EAAQ,OAAH,wBAAQ9Q,KAAKC,SAAO,CAAEu4B,KAAM1O,IACvChZ,EAAMgjB,UAAUhK,GAAQ0tE,EACxBx3F,KAAKwU,OAAO1D,GAMd,cACE,MAAMA,EAAQ9Q,KAAK+W,iBAAiB5Q,MAEpC,YAAcuF,IAAVoF,EACK9Q,KAAK0yJ,cAGT5hJ,EAAMgjB,YACThjB,EAAMgjB,UAAY,IAGbhjB,GAGT,mBACE,OAAO,IAAI0hJ,GAA2B,I,oCArG7B,I,yBAAA,EAAiC,QAAjC,EAAiC,Y,aAAjC,I,oFCIN,MAAMG,EADb,cAGU,KAAAp9D,cAAyB,GAE1B,SAAS1xF,GACd,OAAO7D,KAAKu1F,cAAc38E,SAAS5Y,KAAKm0I,WAAWtwI,IAG9C,IAAIA,GACL7D,KAAKu1F,cAActuF,OAAS,KAC9BjH,KAAKu1F,cAActsE,OAAO,EAAG,IAG/BjpB,KAAKu1F,cAAcr0F,KAAKlB,KAAKm0I,WAAWtwI,IAGlC,WAAWA,GACjB,OAAOA,EAAM6xF,UAAY7xF,EAAMc,O,sCAjBtBguJ,I,yBAAAA,EAAoB,QAApBA,EAAoB,a,kCCTjC,sF,8CAmBO,MAAMC,EAUX,YAAsBlyJ,GAAA,KAAAA,OATN,KAAAmyJ,YAAqB,EAK9B,KAAAj7I,KAAW,CAChBk7I,kBAAmB9yJ,KAAKU,KAAKU,EAAE,sBAM1B,SACL,OAAIpB,KAAK+yJ,WACA,IAAuB,gBAAkB/yJ,KAAK+yJ,WAE9C,K,sCAjBAH,GAAyB,Y,uBAAzBA,EAAyB,4WAZhC,gBAEE,gBACE,cACA,cACA,cAGF,OACF,Q,MARK,uCAEgB,qDACd,0CACA,qCAAiB,+B,uQCgB9B,kDASO,MAAeI,UAA2C,IAU/D,YAAmBtyJ,GACjBZ,QADiB,KAAAY,OAJZ,KAAA8vC,UAAmB,EAOxBxwC,KAAK4X,KAAO,CACVtQ,SAAUtH,KAAKU,KAAKU,EAAE,qBACtBsY,WAAY1Z,KAAKU,KAAKU,EAAE,uBACxBkhC,MAAOtiC,KAAKizJ,SAAWjzJ,KAAKU,KAAKU,EAAEpB,KAAKizJ,UAAY,GACpD50G,WAAYr+C,KAAKkzJ,QAAUlzJ,KAAKU,KAAKU,EAAEpB,KAAKkzJ,SAAW,IAI3D,YACE,OAAOlzJ,KAAK4X,KAAK0qB,MAGnB,iBACE,OAAOtiC,KAAK4X,KAAKymC,WAGnB,eACE,MAAO,GAGT,cACE,MAAO,GAGT,uBACE,OAAQr+C,KAAKwwC,SAAsC,GAA3BxwC,KAAK4X,KAAKtQ,SAAW,IAG/C,yBACE,OAAOtH,KAAKwwC,SAAWxwC,KAAK4X,KAAK8B,WAAa,IAAM,GAGtD,aACE,OAAO1Z,KAAKmzJ,kBAAoBnzJ,KAAKozJ,mBAGhC,WACL,OAAO,K,uOChEL,oBAEQ,8DAGN,qBACA,kBAGF,O,uBALQ,gCADA,yBAIA,wC,uCAIR,oBAEQ,8DAEN,qBACA,kBAGF,O,uBALQ,4BAGA,2C,uCAIR,oBAEQ,4DAEN,qBACA,kBAGF,O,uBALQ,4BAGA,2CCrCP,MAAM,UAA6B,IAGxC,oBACE,OAAO,EAGF,iBAAiB7nH,GACtBvrC,KAAKqzJ,aAAe9nH,EAAOuL,cAC3B92C,KAAKszJ,4BAGP,eACE,OAAOtzJ,KAAK63D,KAAKz2D,EAAE,oB,oCAbV,I,uBAAA,EAAoB,4CAJpB,CACT,MACD,s3BDZH,gBACE,gBAGE,gBACE,cACE,cAEE,iCAAS,EAAAkmD,QAAA,MAEX,OACF,OACA,eACF,OAEA,gBACE,sBAGS,yCAAiB,EAAAisG,iBAAA,MAC1B,OACF,OAEA,gBACE,2BAWA,2BAUA,2BASF,OACF,OACF,Q,MA/CU,mCAGmC,yCAK9B,sCAAuB,+CAQxB,mCAWA,mCAUA,uC,0MChCD,G,4BCEN,MAAM,EAEX,YAAqB15G,EACV9wC,EACAkzE,EACAx4E,EACA4R,EACCO,EACDiiD,GANU,KAAAhe,iBACV,KAAA9wC,WACA,KAAAkzE,cACA,KAAAx4E,eACA,KAAA4R,cACC,KAAAO,aACD,KAAAiiD,OAGJ,OAAO5tC,EAAatkB,EAAyBg3G,GAA+B,GACjF,OAAO,IAAIptG,QAAsD,CAACC,EAASquB,KACzE79B,KACGwzJ,mBAAmBvpI,EAAMtkB,GACzB8J,KAAKid,IACJ,MAAM+uC,EAAQz7D,KAAK65C,eAAe94C,KAAK,EAAsBf,KAAK+I,SAAU,CAAE2jB,UAAWA,EAAWiwF,qBAAsBA,IAE1HlhD,EACGD,aACAr7D,KAAK,OAAAi3C,EAAA,GAAK,IACV/2C,UAAU,KACLo7D,EAAM43F,aACR7jJ,EAAQ,CAAEuyD,MAAOtG,EAAM43F,aAActyF,OAAQ,WAE7CljC,UAOP,mBAAmB5T,EAAatkB,GACrC,IAAI5D,EAAc,CAChB86G,QAAS5yF,EAAK/O,OAAO,eAWvB,OARIvV,IACF5D,EAAgB,OAAI,CAClBiH,YAAa,CACXzD,KAAMI,EAAGJ,QAKRvF,KACJyD,aACAiyD,aACAtxD,KACAgpB,KAAKrrB,GACL8qB,YACApd,KAAKrL,GACCpE,KAAK8sB,eAAe1oB,IAIxB,eAAeA,GACpB,IAAI29D,EAAQ/hE,KAAK+sB,sBAAsB3oB,GAEvC,OAAOpE,KAAK4V,WAAWoX,KAA8D+0C,EAAO39D,GAGtF,sBAAsBA,GAC5B,IAAI29D,EAAQ/hE,KAAKi8E,YAAYntD,wBAA2C,YAAa1qB,EAAKrC,QAAQ8sB,UAyBlG,OAvBAkzC,EAAMt8D,OAAe,OAAI,CAAEF,KAAM,OAEjCw8D,EAAa,MAAI,YACjBA,EAAU,GAAI,MACdA,EAAa,MAAI,OAGjBA,EAAc,OAAIA,EAAMt8D,OAAe,OAAIrB,EAAKqB,OAAOuF,KAEvD+2D,EAAyB,kBAAIA,EAAMt8D,OAA0B,kBAAK1D,GACzD/B,KACJyD,aACAiyD,aACAtoC,KAAKrrB,GACL8qB,YAGLk1C,EAAMjxD,MAAM9M,SAAS+9D,GAIrB/hE,KAAKqV,YAAYb,OAAOutD,EAAO39D,EAAK5B,QAE7Bu/D,G,sCAxFE,GAAsB,wE,yBAAtB,EAAsB,QAAtB,EAAsB,a,kCCcnC,8DAsBO,MAAM0xF,G,uBAAAA,I,oDAAAA,IAA4B,SAf9B,CACP,S,sNCzBG,MAAMC,EAA0B,uBAE1BC,EAAkC,oCAIxC,MAAMC,UAAkC,IAe7C,YAA4B7qJ,EACNuqB,GAEpBxzB,MAAMiJ,EAAUuqB,GAHU,KAAAvqB,WACN,KAAAuqB,mBAIpBtzB,KAAK4X,KAAO,CACVi8I,KAAO5zE,GAAiBjgF,KAAKU,KAAKU,EAAE,kCAAmC,CAAC6+E,MAAOA,IAC/EvvE,SAAWuvE,GAAiBjgF,KAAKU,KAAKU,EAAE,+CACtC,CAAC6+E,MAAOA,IACVnsD,UAAYmsD,GAAiBjgF,KAAKU,KAAKU,EAAE,gDACvC,CAAC6+E,MAAOA,KAQP,WAAWj3E,EAAiC6rB,GAEjD,MAAMyB,EAASx2B,MAAMy2B,WAAWvtB,EAAa6rB,GAI7C,OAHAyB,EAAO9qB,KAAK,6BAA6BinB,SACzCzyB,KAAK8zJ,yBAAyB9qJ,EAAastB,GAEpCA,EAMF,WAAWttB,GAChB,IAAK4mB,EAASvrB,GAAKvE,MAAMi5B,WAAW/vB,IAC/ByY,EAAS0U,GAAUn2B,KAAK08B,gBAAgB1zB,GAI7C,OAHA4mB,EAAQrf,UAAUC,OAAOiR,GAEzBzhB,KAAK8zJ,yBAAyB9qJ,EAAanC,OAAO+oB,IAC3C,CAACA,EAASuG,GAOZ,gBAAgBntB,GACrB,MAAM8H,EAAQ9Q,KAAKmD,mBAAmBlD,QAChCupD,EAAsB,GAC5B,IAAIrzB,GAAS,EAkBb,OAhBIn2B,KAAKk7B,2BAA2BlyB,EAAYd,KAC9CshD,EAAWtoD,KAAK,YAAmB8H,EAAYd,KAG7C7D,EAAEw1B,QAAQ7wB,EAAY8S,YACxB9S,EAAY8S,UAAUpW,QAAS01B,IAC7BouB,EAAWtoD,KAAK,YAAoBk6B,EAASlzB,KAEzC4I,EAAMgjB,UAAUsH,EAASlzB,MAC3BiuB,GAAS,EACTqzB,EAAWtoD,KAAK,YAAoBk6B,EAASlzB,QAM5C,CAACshD,EAAYrzB,GAMf,iBAAiBiF,EACAY,EACA/K,GAEtB,MAAMjoB,EAAchJ,KAAK2C,OAAOkT,aAAanR,IAAI02B,EAASlzB,IAAK/B,OACxDuuB,EAAIyB,GAAUn2B,KAAK+4B,WAAW/vB,GAErC,OADA0rB,EAAGnkB,UAAUC,IAAImjJ,GACV,CAACj/H,EAAIyB,GASN,yBAAyBntB,EAAiC6rB,EAAaorD,GAC7E,MAAM8zE,OAA2BroJ,IAAVu0E,EAA8Bj3E,EAAY8S,UAAU7U,OAASg5E,EAC9E+zE,EAAmBh0J,KAAKi0J,wBAAwBjrJ,EAAa6rB,EAAMk/H,GAEzEl/H,EAAKrpB,KAAK,cACPb,SAAS,mBACTwkC,QAAQ6kH,GAGXn/H,EAAKrpB,KAAK,cAAcO,IAAI,WAAY,IAjHR,GAiHsCgoJ,EAAkB,MACxFl/H,EAAKrpB,KAAK,wCACPO,IAAI,QAAS,sBAnHgB,GAmH8DgoJ,EAAkB,OAM1G,wBAAwB/qJ,EAAiC6rB,EAAkBorD,GACjF,MAAMi0E,EAAqBhpJ,SAASoF,cAAc,QAC5CwjB,EAAY9zB,KAAKmD,mBAAmB2wB,UAAU9qB,EAAYd,IAC1DisJ,EA3H8B,GADJ,GA4H0Cl0E,EAAS,KAKnF,GAJAi0E,EAAmB3jJ,UAAUC,IA/HK,4BAgIlC0jJ,EAAmBlyI,MAAMob,MAAQ+2H,EACjCD,EAAmBzjJ,QAAQ2jJ,YAAcD,EAErCn0J,KAAKk7B,2BAA2BlyB,EAAYd,IAAM,CACpD,MAAM6Z,EAAY+R,EAAY4/H,EAA0B,GACxDQ,EAAmBngI,UAAY,yFACiDhS,yLAEE/hB,KAAK4X,KAAKlH,SAC1FuvE,qGACiFjgF,KAAK4X,KAAKkc,UAC3FmsD,6CAIFi0E,EAAmBngI,UAAY,sHAEY/zB,KAAK4X,KAAKi8I,KAAK5zE,2CAK5D,OAAOi0E,GA/IM,aAAd,c,0BAAwC,M,yCAC1B,aAAd,c,0BAA4B,M,gECO/B,kGAeO,MAAMG,EAMX,YAAqB3zJ,EACAgX,EACAw0I,GAFA,KAAAxrJ,OACA,KAAAgX,iBACA,KAAAw0I,gBAPd,KAAAt0I,KAAO,CACZ08I,OAAQt0J,KAAKU,KAAKU,EAAE,iBACpBmzJ,aAAcv0J,KAAKU,KAAKU,EAAE,+BAQrB,cACL,IAAI0N,EAAoB9O,KAAK0X,eAAe5C,WAC5C,GAAIhG,EAAmB,CACrB,IAAId,EAAMhO,KAAKksJ,cAAcsI,uBAAuB1lJ,GACpD0R,OAAOgoB,SAASjjC,KAAOyI,I,sCAfhBqmJ,GAAwB,gC,uBAAxBA,EAAwB,yMATjC,cACE,gCAAS,EAAA5rJ,iBAET,oBACA,iBAA4B,QAAgB,OAC9C,Q,MALG,kCAI2B,sC,iOC5B3B,MAAegsJ,UAA2B,IAiB/C,YAAqBj0J,EAC4BsR,EAC5BjS,EACAg4D,EACA9uD,GACnBjJ,MAAMgS,EAAQjS,EAAOW,GALF,KAAAA,aAC4B,KAAAsR,SAC5B,KAAAjS,QACA,KAAAg4D,OACA,KAAA9uD,WAlBd,KAAA6O,KAA+B,CACpC0K,MAAOtiB,KAAK63D,KAAKz2D,EAAE,uBACnBiZ,OAAQra,KAAK63D,KAAKz2D,EAAE,oBACpB2J,MAAO/K,KAAK63D,KAAKz2D,EAAE,mBACnBs0C,OAAQ11C,KAAK63D,KAAKz2D,EAAE,oBACpBszJ,WAAY10J,KAAK63D,KAAKz2D,EAAE,yBAGnB,KAAA6lD,eAAgB,EAChB,KAAAE,qBAAsB,EAe7B,gBACE,OAAOnnD,KAAK8R,OAAO4a,UAGrB,YACE,OAAO1sB,KAAK0sB,UAAUjqB,kBAGxB,2BACE,YAA4CiJ,IAArC1L,KAAK8R,OAAO6qG,sBAAqC38G,KAAK8R,OAAO6qG,qBAG/D,YACL38G,KAAK20J,cAAe,EAEpB30J,KAAKga,SAASI,OACX3K,KAAK,IAAMzP,KAAKszJ,6BAChB94I,MAAM,KACLxa,KAAK20J,cAAe,EACpB30J,KAAKH,MAAMS,kBAIjB,eACE,OAAON,KAAK63D,KAAKz2D,EAAE,kBAGrB,kBACE,OAAO,EAGT,oBACE,OAAO,EAGC,4BAEJpB,KAAK+hE,MAAM/4D,aACbhJ,KACGyD,aACAmC,cACAsC,GAAGlI,KAAK+hE,MAAM/4D,aACdw0B,UAELx9B,KAAK8rB,QAAQ/gB,QACb/K,KAAK20J,cAAe,EACpB30J,KAAKH,MAAMS,iB,sCAzEOm0J,GAAkB,eAkBlB,KAAkB,gC,uBAlBlBA,EAAkB,wB,OAAA,K,2EAevB,aAAd,c,0BAA2B,M,sECE9B,kDAGO,MAAMG,UAAqB,IAiBzB,kCACL,MAAO,CAAC,SAAU,cAGpB,YACE,OAAO50J,KAAK2C,OAAOue,MAAMxc,IAAI1E,KAAKuF,MAGpC,mBACE,OAAOvF,KAAKuyI,SAAWvyI,KAAKuyI,SAASr0F,MAAM34C,KAAO,KAGpD,eACE,OAAOqvJ,EAAaC,qBAAqBz3I,QAAQpd,KAAK27C,SAAW,K,kCC3DrE,gM,sLCAI,aACE,cAOF,Q,mCAPK,mCAA0B,sBAA1B,CAA0B,qDAA1B,CAA0B,+C,yBAHnC,cACE,eACE,sBASF,OACF,Q,6BAVQ,0BAA8C,6BDS/C,MAAMm5G,EAAqB,cAO3B,MAAMC,UAA4B,IAyBvC,YAA6BC,EACAvxJ,EACAiU,EACAuqB,GAC3BniC,QAJ2B,KAAAk1J,eACA,KAAAvxJ,eACA,KAAAiU,iBACA,KAAAuqB,kBA3B7B,KAAAgzH,UAAY,IAAuBjyI,mBAAmB,MAEtD,KAAAkyI,yBAA2Bl1J,KAAK0X,eAAe5C,WAIxC,KAAAqgJ,QAA8Bn1J,KAClCyD,aACAsyD,OACAhE,aACA5xD,KACC,YAAK41D,GACIA,EAAO57B,MAAK,SAAUjX,EAAGC,GAC9B,OAAID,EAAEzc,KAAO0c,EAAE1c,MACL,EAENyc,EAAEzc,KAAO0c,EAAE1c,KACN,EAEF,OAYf,WAGEzG,KAAKiiC,gBACFgB,WAAW,cACX5iC,UAAU,KACTL,KAAKo1J,iBACLp1J,KAAKg1J,aAAaK,kBAGtBr1J,KACGg1J,aACAn+C,cACA12G,KACCH,KAAKI,kBAENC,UAAW6H,IACVlI,KAAKs1J,gBAAkBptJ,GAAU,KAI/B,iBACgBrB,OAAO,+DACb0G,S,sCAvDPwnJ,GAAmB,0C,uBAAnBA,EAAmB,kUClBhC,sB,sBAAK,kC,oQCkCE,MAAMQ,EAQJ,WAAWtrI,GAChB,MAAgB,KAATA,EAAc,KAAOA,EAGvB,UAAUA,GACf,OAAIA,aAAgB+E,KACX,IAAIA,KAAK/E,EAAKurI,SAAS,EAAE,EAAE,EAAE,IAClB,KAATvrI,EACF,GAEA,IAAI+E,KAAK,IAAIA,KAAK/E,GAAMurI,SAAS,EAAE,EAAE,EAAE,IAI3C,UAAUvrI,GACf,OAAQA,aAAgB+E,MACZ,KAAT/E,KACC,IAAI+E,KAAK/E,GAAMw6E,UAGd,UAAUnpB,GACf,OAAOA,EAAMnhD,MAAK,SAASjX,EAAQC,GACjC,OAAOD,EAAEmuG,UAAYluG,EAAEkuG,aAIpB,cAAcokC,EAAuBC,GAC1C,IAAIC,EAAc31J,KAAKw3C,UAAUi+G,GAC7BG,EAAc51J,KAAKw3C,UAAUk+G,GAEjC,MAA6B,iBAAlB,GAAwD,iBAAlB,GAGxCC,EAAYtkC,YAAcukC,EAAYvkC,UAI1C,yBAAyBzvH,GAC9B5B,KAAK61J,4BAA8Bj0J,EAG9B,4BAA4B05E,EAAoCw6E,GACrE91J,KAAK61J,4BAAmE,UAArC71J,KAAK61J,4BAA0C,MAAQ,QAC1F71J,KAAK+1J,0BAA0Bz6E,EAAOw6E,GAGjC,+BAA+Bl0J,GACpC,OAAO5B,KAAK61J,8BAAgCj0J,EAGvC,SAAS05E,EAA+Bw6E,EAAuBE,GACpE,IAAIC,EAAeH,EAAW37E,mBAAmB87E,aAC7CC,EAAcJ,EAAW37E,mBAAmB+7E,YAChDJ,EAAWK,SAAS76E,GAEhB06E,GACFF,EAAW37E,mBAAmB87E,aAAeD,EAAYpkC,WACzDkkC,EAAW37E,mBAAmB+7E,YAAcF,EAAYtkC,gBAGxDokC,EAAW37E,mBAAmB87E,aAAeA,EAC7CH,EAAW37E,mBAAmB+7E,YAAcA,GAG9CJ,EAAW37E,mBAAmBi8E,SAGzB,0BAA0B96E,EAAoCw6E,GACnE,IAAKx6E,EAAMvxD,QAAUuxD,EAAM/yD,IACzB,OAGF,IAAI8tI,EAA4BpsI,IACvB,EAGLjqB,KAAKs2J,+BAA+B,UAAYh7E,EAAM/yD,IACxD8tI,EAAmBpsI,GACVA,EAAKonG,UAAY,IAAIriG,KAAKssD,EAAM/yD,KAAKitI,SAAS,EAAE,EAAE,EAAE,GAEpDx1J,KAAKs2J,+BAA+B,QAAUh7E,EAAMvxD,QAC7DssI,EAAmBpsI,GACVA,EAAKonG,UAAY,IAAIriG,KAAKssD,EAAMvxD,OAAOyrI,SAAS,EAAE,EAAE,EAAE,IAIjEM,EAAW37E,mBAAmBpuD,IAAI,UAAW,CAACsqI,IAGzC,gBAAgB/6E,GACrB,GAAKA,EAAMvxD,OAAUuxD,EAAM/yD,KAAQ+yD,EAAMvxD,QAAUuxD,EAAM/yD,IAAzD,CAIA,IAAIguI,EAAiBrrJ,SAASqtF,uBAAuB,gBAErD,IAAK,IAAIx7E,EAAI,EAAGA,EAAIw5I,EAAetvJ,OAAQ8V,IACzC/c,KAAKw2J,4BAA4BD,EAAex5I,GAAIu+D,IAIhD,4BAA4Br6D,EAAmBq6D,GACrD,IAAIm7E,EAAmB5vJ,OAAOoa,GAAWzV,KAAK,2BAC9C,GAAgC,IAA5BirJ,EAAiBxvJ,OAEnBwvJ,EAAiB,GAAGlmJ,UAAUC,IAAI,cAClCimJ,EAAiB,GAAGlmJ,UAAUC,IAAI,YAElCxQ,KAAK02J,qBAAqBD,EAAiB,GAAIA,EAAiB,SAC3D,GAAgC,IAA5BA,EAAiBxvJ,QAE1B,GAAIjH,KAAK22J,oBAAoBr7E,EAAMvxD,MAAO0sI,EAAiB,IACzDA,EAAiB,GAAGlmJ,UAAUC,IAAI,cAClCxQ,KAAK02J,qBAAqBD,EAAiB,GAAI,SAC1C,GAAIz2J,KAAK22J,oBAAoBr7E,EAAM/yD,IAAKkuI,EAAiB,IAAK,CACnE,IAAIG,EAAW/vJ,OAAOoa,GAAWzV,KAAK,kBAAkB,GAExDirJ,EAAiB,GAAGlmJ,UAAUC,IAAI,YAClComJ,EAASrmJ,UAAUC,IAAI,WAEvBxQ,KAAK02J,qBAAqBE,EAAUH,EAAiB,UAE9Cz2J,KAAK62J,wBAAwB51I,EAAWq6D,IAEjDz0E,OAAOoa,GAAWzV,KAAK,kBAAkBb,SAAS,WAI9C,oBAAoBsf,EAAa6sI,GACvC,OAAO,IAAI9nI,KAAK8nI,EAAgB9zH,aAAa,eAAgB+zH,iBAAmB,IAAI/nI,KAAK/E,GAAM8sI,eAGzF,wBAAwB91I,EAAmBq6D,GACjD,IAAI07E,EAAyBnwJ,OAAOoa,GAAWzV,KAAK,+BAA+B,GAC/EyrJ,EAAkB,IAAIjoI,KAAKgoI,EAAuBh0H,aAAa,eAEnE,OAAOi0H,GAAmB,IAAIjoI,KAAKssD,EAAM/yD,MAClC0uI,GAAmB,IAAIjoI,KAAKssD,EAAMvxD,OAGnC,qBAAqBxO,EAAckkH,GACzC54H,OAAO0U,GAAM27I,UAAUz3B,GAAO90H,SAAS,Y,sCArJ9B4qJ,I,yBAAAA,EAAqB,QAArBA,EAAqB,qBADR,S,0JCxBhB,QACE,iBACE,mBAGA,gBACE,iBACE,mBAKO,mEAA4B,OAAQhqH,KAApC,CAA4C,0CACnC4rH,iBAAA,yBAA0C,WAN1D,OAOF,OACA,eAEG,qDAAe,WAChB,kBACF,OACF,OACA,iBACE,eAAG,wDAAkB,WAErB,OACF,OACF,OACF,O,uBAxBW,wCAOI,4FAAkF,wBAMxF,mCAOA,0C,uCAsBH,eAGG,sDAAe,YAChB,kBACF,O,wBAHG,4B,uCAMH,eACG,yDAAkB,YAErB,O,wBADG,kC,uCAmBH,eAGG,sDAAe,UAChB,kBACF,O,wBAHG,4B,uCAMH,eACG,yDAAkB,UAErB,O,wBADG,kC,uCAvDT,QACE,iBACE,mBAGA,gBACE,iBACE,mBAKO,mEAA4B,QAAS5rH,KAArC,CAA6C,mEAEX,YAPzC,OAQF,OACA,qBAMF,OACA,iBACE,qBAIF,OACF,OACA,iBACE,oBAGA,iBACE,kBACE,oBAKO,mEAA4B,MAAOA,KAAnC,CAA2C,mEAET,UAPzC,OAQF,OACA,sBAMF,OACA,kBACE,sBAIF,OACF,OACF,O,uBAxDW,6CAOI,8FAAmF,wBAAnF,CAAmF,6BAOzF,qCAOA,8CAQE,2CAOI,4FAAiF,sBAAjF,CAAiF,6BAOvF,qCAOA,6C,yBA2BP,QACE,eACF,Q,qBADK,6C,yBAEL,QACE,eACF,Q,qBADK,oE,yBAPX,QACE,iBACE,iBACE,+BAGA,+BAGF,OACF,OACF,Q,oBARoB,gCAGA,qE,sBAMpB,QACE,mBAEF,QCtEC,MAAM,UAAwB,IAwCnC,YAAqBxiC,EAC0B+I,EAC1BjS,EACAW,EACAu5E,GACnBj6E,MAAMgS,EAAQjS,EAAOW,GALF,KAAAuI,WAC0B,KAAA+I,SAC1B,KAAAjS,QACA,KAAAW,aACA,KAAAu5E,uBAnCrB,KAAAniE,KAAO,CACLwC,KAAMpa,KAAKU,KAAKU,EAAE,kBAClBiZ,OAAQra,KAAKU,KAAKU,EAAE,oBACpBiE,MAAOrF,KAAKU,KAAKU,EAAE,iCACnBg2J,iBAAkBp3J,KAAKU,KAAKU,EAAE,wBAC9B6oB,KAAMjqB,KAAKU,KAAKU,EAAE,oCAClB4oB,UAAWhqB,KAAKU,KAAKU,EAAE,yCACvBi2J,QAASr3J,KAAKU,KAAKU,EAAE,uCACrBouB,YAAaxvB,KAAKU,KAAKU,EAAE,2BACzB0iI,MAAO9jI,KAAKU,KAAKU,EAAE,kBACnBk2J,SAAUt3J,KAAKU,KAAKU,EAAE,yCACtBm2J,gCAAiCv3J,KAAKU,KAAKU,EAAE,qEAExC,KAAA04C,cAAgB,IAAI,IAEpB,KAAA09G,YAAa,EAEb,KAAA57G,kBAAmB,EAEnB,KAAA67G,OAAgB,GAEhB,KAAAn8E,MAAqC,CAC1CrxD,KAAM,GACNF,MAAO,GACPxB,IAAK,IAaLvoB,KAAK0sB,UAAY5a,EAAO4a,UACxB1sB,KAAKy3J,OAAS,iBAAiB3lJ,EAAO1K,UAEtCpH,KAAKw3J,WAAax3J,KAAK0sB,UAAUgrI,WAAW,QAC5C13J,KAAK47C,iBAAmB57C,KAAK0sB,UAAUvmB,MAAM,oBAEzCnG,KAAKw3J,YACPx3J,KAAKs7E,MAAMrxD,KAAOjqB,KAAK0sB,UAAUvmB,MAAM,QACvCnG,KAAKm3J,iBAAiBQ,yBAAyB,UAE/C33J,KAAKs7E,MAAMvxD,MAAQ/pB,KAAK0sB,UAAUvmB,MAAM,aACxCnG,KAAKs7E,MAAM/yD,IAAMvoB,KAAK0sB,UAAUvmB,MAAM,WACtCnG,KAAKm3J,iBAAiBQ,yBAAyB33J,KAAK43J,0BAIxD,kBACM53J,KAAK63J,eACP73J,KAAK83J,oBAGP93J,KAAK+3J,eAGP,uBACE/3J,KAAK47C,kBAAoB57C,KAAK47C,iBAC9B57C,KAAKH,MAAMS,gBAEPN,KAAK47C,iBACP57C,KAAK83J,oBACI93J,KAAKs3J,UACdt3J,KAAKg4J,sBAIT,OACOh4J,KAAKi4J,YAKVj4J,KAAK0sB,UAAU7qB,SAAS,mBAAoB7B,KAAK47C,kBAG7C57C,KAAK63J,gBACH73J,KAAKw3J,WACPx3J,KAAK0sB,UAAU7qB,SAAS,OAAQ7B,KAAKm3J,iBAAiBe,WAAWl4J,KAAKs7E,MAAMrxD,QAE5EjqB,KAAK0sB,UAAU7qB,SAAS,YAAa7B,KAAKm3J,iBAAiBe,WAAWl4J,KAAKs7E,MAAMvxD,QACjF/pB,KAAK0sB,UAAU7qB,SAAS,UAAW7B,KAAKm3J,iBAAiBe,WAAWl4J,KAAKs7E,MAAM/yD,QAInFvoB,KAAKsnD,WAGP,SACEtnD,KAAKsnD,UAGP,MAAM3lD,GACJ3B,KAAKs7E,MAAM35E,GAAO,GAClB3B,KAAKm4J,mCAGP,WAAWx2J,EAAcC,IAEnBA,EAAIqF,QAAU,GAAoB,IAAfrF,EAAIqF,UACzBjH,KAAKs7E,MAAM35E,GAAOC,EACd5B,KAAKm3J,iBAAiBiB,UAAUx2J,IAAQ5B,KAAK0zH,oBAC/C1zH,KAAKm4J,kCAAiC,IAK5C,SAASx2J,GACP,IAAImiI,EAAQ9jI,KAAKm3J,iBAAiB3/G,UAAU,IAAIxoB,MAChDhvB,KAAKs7E,MAAM35E,GAAO3B,KAAK2a,gBAAgBoY,iBAAiB+wG,GAEvDA,aAAiB90G,KAAQhvB,KAAKm4J,kCAAiC,EAAMr0B,GAAS9jI,KAAKm4J,mCAGtF,WAAWvoI,EAA6B7oB,GACtC6oB,EAAQ/jB,SAAS,CACfsK,GAAI,WACJC,GAAI,cACJ9C,GAAIvM,EACJgiD,UAAW,YAIf,yBAAyBpnD,GACvB3B,KAAKm3J,iBAAiBQ,yBAAyBh2J,GAC/C3B,KAAKm3J,iBAAiBpB,0BAA0B/1J,KAAKs7E,MAAOt7E,KAAK0zH,oBACjE1zH,KAAKm3J,iBAAiBkB,gBAAgBr4J,KAAKs7E,OAG7C,cAAc35E,GACZ,QAAK3B,KAAK63J,gBAIE,UAARl2J,EACK3B,KAAKm3J,iBAAiB3/G,UAAU,IAAIxoB,OAAWhvB,KAAKm3J,iBAAiB3/G,UAAUx3C,KAAKs7E,MAAM/yD,KAE1FvoB,KAAKm3J,iBAAiB3/G,UAAU,IAAIxoB,OAAWhvB,KAAKm3J,iBAAiB3/G,UAAUx3C,KAAKs7E,MAAMvxD,QAWrG,oBACE,OAAO/pB,KAAK47C,mBAAsB57C,KAAKs3J,WAAat3J,KAAKu3J,gCAG3D,gBACE,OAAOv3J,KAAK63J,eAAiB73J,KAAKu3J,gCAOpC,eACE,OAAOv3J,KAAK0sB,UAAUjqB,kBAAkBgD,OAAOwG,UAAYjM,KAAK0sB,UAAUjqB,kBAAkBgD,OAAOwG,SAAShF,OAAS,EAGvH,sCACE,OAAQjH,KAAK47C,kBAAoB57C,KAAK0sB,UAAUvmB,MAAM,oBAGhD,oBACNnG,KAAKyzH,uBACLzzH,KAAKm3J,iBAAiBpB,0BAA0B/1J,KAAKs7E,MAAOt7E,KAAK0zH,oBACjE1zH,KAAKm3J,iBAAiBkB,gBAAgBr4J,KAAKs7E,OAGrC,sBACNt7E,KAAK0zH,mBAAmBx1F,UAGlB,uB,MACiB,QAAvB,EAAAl+B,KAAK0zH,0BAAkB,SAAEx1F,UACzBl+B,KAAK0zH,mBAAqB,IAAI,IAC5B,mBACA1zH,KAAKw3J,WAAax3J,KAAKs7E,MAAMrxD,KAAO,CAACjqB,KAAKs7E,MAAMvxD,MAAO/pB,KAAKs7E,MAAM/yD,KAClE,CACEvR,KAAMhX,KAAKw3J,WAAa,SAAW,WACnCc,WAAYt4J,KAAKkmD,gBAAgBC,SAAW,EAAI,EAChDoyG,QAAQ,EACRhxF,SAAW+T,IACTt7E,KAAKw4J,uBAAuBl9E,GAE5Bt7E,KAAK+3J,gBAEPU,cAAe,KAAQz4J,KAAKm3J,iBAAiBkB,gBAAgBr4J,KAAKs7E,QAClEo9E,aAAc,KAAQ14J,KAAKm3J,iBAAiBkB,gBAAgBr4J,KAAKs7E,cAEnE5vE,EACA1L,KAAK+5E,sBAID,iCAAiC4+E,GAAsB,EAAM3C,GACnE,GAAIh2J,KAAKw3J,WAAY,CACnB,IAAIvtI,EAAOjqB,KAAKm3J,iBAAiB3/G,UAAUx3C,KAAKs7E,MAAMrxD,MACtDjqB,KAAKm3J,iBAAiBhB,SAASlsI,EAAMjqB,KAAK0zH,mBAAoBsiC,OACzD,CACL,IAAI16E,EAAQ,CAACt7E,KAAKm3J,iBAAiB3/G,UAAUx3C,KAAKs7E,MAAMvxD,OAAQ/pB,KAAKm3J,iBAAiB3/G,UAAUx3C,KAAKs7E,MAAM/yD,MAC3GvoB,KAAKm3J,iBAAiBhB,SAAS76E,EAAOt7E,KAAK0zH,mBAAoBsiC,GAE/Dh2J,KAAK44J,oCAAoCD,IAIrC,uBAAuBr9E,GAC7B,OAAQA,EAAMr0E,QACZ,KAAK,GAECjH,KAAKs7E,MAAMvxD,OAAS/pB,KAAKs7E,MAAM/yD,MACjCvoB,KAAK64J,4BAA4B74J,KAAKs7E,MAAMvxD,OAAS/pB,KAAKs7E,MAAM/yD,KAGlE,MAEF,KAAK,EACH,GAAIvoB,KAAKw3J,WACPx3J,KAAKs7E,MAAMrxD,KAAOjqB,KAAK2a,gBAAgBoY,iBAAiBuoD,EAAM,SAG9D,GAAIt7E,KAAKs7E,MAAMvxD,OAAS/pB,KAAKs7E,MAAM/yD,IAAK,CAEtC,GAAIvoB,KAAKs7E,MAAMvxD,QAAU/pB,KAAKs7E,MAAM/yD,IAClC,OAKF,GAAKvoB,KAAKm3J,iBAAiBb,+BAA+B,UAAYt2J,KAAKm3J,iBAAiB2B,cAAc94J,KAAKs7E,MAAMvxD,MAAOuxD,EAAM,KAC7Ht7E,KAAKm3J,iBAAiBb,+BAA+B,QAAUt2J,KAAKm3J,iBAAiB2B,cAAc94J,KAAKs7E,MAAM/yD,IAAK+yD,EAAM,IAAM,CAElI,IAAIy9E,EAA0B/4J,KAAKm3J,iBAAiBb,+BAA+B,SAAW,MAAQ,QACtGt2J,KAAK64J,4BAA4B74J,KAAKs7E,MAAMy9E,SAI5C/4J,KAAKm4J,kCAAiC,QAIxCn4J,KAAK64J,4BAA4B74J,KAAK2a,gBAAgBoY,iBAAiBuoD,EAAM,KAAK,GAItF,MAEF,KAAK,EACH,IAAMt7E,KAAKs7E,MAAM/yD,KAAOvoB,KAAKm3J,iBAAiBb,+BAA+B,WACvEt2J,KAAKs7E,MAAMvxD,OAAS/pB,KAAKm3J,iBAAiBb,+BAA+B,OAE7Et2J,KAAKg5J,gCAAgC,CAAC19E,EAAM,SACvC,CAEDA,EAAM,GAAKA,EAAM,KACnBA,EAAQt7E,KAAKm3J,iBAAiB8B,UAAU39E,GACxCt7E,KAAKm3J,iBAAiBhB,SAAS76E,EAAOt7E,KAAK0zH,qBAG7C,IAAIziG,EAAQjxB,KAAKm3J,iBAAiBb,+BAA+B,SAAW,EAAI,EAChFt2J,KAAKs7E,MAAMt7E,KAAKm3J,iBAAiBtB,6BAA+B71J,KAAK2a,gBAAgBoY,iBAAiBuoD,EAAMrqD,IAE5GjxB,KAAK44J,sCAGP,MAEF,QAEM54J,KAAKm3J,iBAAiBb,+BAA+B,SACvDt2J,KAAKg5J,gCAAgC,CAAC19E,EAAM,GAAIA,EAAM,KAEtDt7E,KAAKg5J,gCAAgC,CAAC19E,EAAM,GAAIA,EAAM,KAO5Dt7E,KAAKH,MAAMS,gBAGL,gCAAgCg7E,GACtCt7E,KAAKm3J,iBAAiBhB,SAAS76E,EAAOt7E,KAAK0zH,oBAC3C1zH,KAAKw4J,uBAAuBl9E,GAGtB,4BAA4B49E,EAAgBC,GAAgC,GAClFn5J,KAAKs7E,MAAMt7E,KAAKm3J,iBAAiBtB,6BAA+BqD,EAC5DC,GACFn5J,KAAKm3J,iBAAiBhB,SAAS,CAACn2J,KAAKm3J,iBAAiB3/G,UAAU0hH,IAAWl5J,KAAK0zH,oBAElF1zH,KAAKm3J,iBAAiBiC,4BAA4Bp5J,KAAKs7E,MAAOt7E,KAAK0zH,oBAG7D,oCAAoCilC,GAAsB,GAC5DA,GACF34J,KAAKm3J,iBAAiBiC,4BAA4Bp5J,KAAKs7E,MAAOt7E,KAAK0zH,oBAErE1zH,KAAKm3J,iBAAiBkB,gBAAgBr4J,KAAKs7E,OAGrC,eACN,IAAIrxD,EAAOjqB,KAAKs7E,MAAMrxD,MAAQ,GAC1BF,EAAQ/pB,KAAKs7E,MAAMvxD,OAAS,GAC5BxB,EAAMvoB,KAAKs7E,MAAM/yD,KAAO,GAExB8wI,EAASr5J,KAAKw3J,WAAavtI,EAAOF,EAAQ,MAAQxB,EACtDvoB,KAAK85C,cAActxC,KAAK6wJ,GAGlB,wBACN,MAAiC,YAA1Br5J,KAAK8R,OAAO1K,WAA4BpH,KAAKs7E,MAAMvxD,QAAU/pB,KAAKs7E,MAAM/yD,IAAO,MAAQ,S,sCA5UrF,GAAe,eAyCN,KAAkB,gC,uBAzC3B,EAAe,qD,OAAA,K,qoDD5D5B,gBACE,kBAKE,gBACE,iBACE,gBACE,gCA6BA,iCA4DA,gBACE,gBACE,mBACE,kBACE,oBAIO,wCAAiB,EAAA+wI,0BAJxB,OAKF,OACA,SACF,OACF,OACF,OACF,OACF,OAEA,gCAYA,gCAKA,kBACE,qBAAQ,gCAAS,EAAAj/I,YAGjB,OACA,qBAAQ,gCAAS,EAAAD,UAIjB,OACF,OACF,OACF,OACF,Q,MA9IO,4BAMiB,kCA6BA,mCAmEC,2CAGT,8CAOI,sCAYA,qCAQT,0CAKA,wCAFA,wC,kuDC7EM,aAAd,c,0BAAmB,M,2BACL,aAAd,c,0BAA8B,M,sCAChB,aAAd,c,0BAAyB,M,iCACX,aAAd,c,0BAA+Bm7I,I,uCACjB,aAAd,c,0BAA8B,M,yECjEjC,8J,6FCCE,+B,oBAEmB,8CAAuC,mDDWrD,MAAMgE,EAgCX,YAAqBxwJ,EACArI,EACAiC,EACAC,EACA+T,EACAo8G,GALA,KAAAhqH,WACA,KAAArI,OACA,KAAAiC,SACA,KAAAC,aACA,KAAA+T,UACA,KAAAo8G,mBAlCd,KAAA57G,iBAAoC,SACpC,KAAAqiJ,eAAwB,EACxB,KAAAC,uBAA0C,SAC1C,KAAA5iJ,eAAwB,EAExB,KAAA6iJ,qCAAqD,GACrD,KAAA5iJ,mBAA2B,GAE3B,KAAA6iJ,kCAA4E,GAK5E,KAAA/hJ,KAAO,CACZ0K,MAAOtiB,KAAKU,KAAKU,EAAE,qDACnBw4J,kBAAmB,CACjB53J,YAAahC,KAAKU,KAAKU,EAAE,sEACzBqvF,KAAMzwF,KAAKU,KAAKU,EAAE,+DAClBm3J,OAAQv4J,KAAKU,KAAKU,EAAE,iEACpBy4J,sBAAuB75J,KAAKU,KAAKU,EAAE,qEACnCu6C,OAAQ37C,KAAKU,KAAKU,EAAE,iEACpB0R,KAAM9S,KAAKU,KAAKU,EAAE,oCAClB+6C,SAAUn8C,KAAKU,KAAKU,EAAE,mEACtB04J,cAAe95J,KAAKU,KAAKU,EAAE,yEAE7B24J,4BAA6B/5J,KAAKU,KAAKU,EAAE,sEACzCggJ,mBAAoBphJ,KAAKU,KAAKU,EAAE,+DAWlC,WACEpB,KAAK05J,qCAAuC15J,KAAKg6J,+BACjDh6J,KAAK25J,kCAAoC,CACvC,CAAClzJ,KAAMzG,KAAK4X,KAAKgiJ,kBAAkBj+G,OAAQx1C,MAAO,UAClD,CAACM,KAAMzG,KAAK4X,KAAKgiJ,kBAAkBz9G,SAAUh2C,MAAO,aAGtDnG,KAAKi6J,oBAELj6J,KAAK6W,cAAgB7W,KAAK2W,QAAQE,cAClC7W,KAAKk6J,WAAWl6J,KAAK+yH,iBAAiB9yH,QAAQ+W,MAE1ChX,KAAK6W,eACP7W,KAAKk6J,WAAW,QAIb,SACL,IAAIljJ,EAAOhX,KAAKmX,iBAChBnX,KAAK+yH,iBAAiBv+G,OAAO,CAAEwC,KAAMA,EAAMF,mBAAoB9W,KAAK8W,qBAG/D,WAAWE,GAEdhX,KAAKmX,iBADM,eAATH,EACsBhX,KAAKy5J,uBAELziJ,GAGqC,IAA3D,CAAC,SAAU,YAAYoG,QAAQpd,KAAKmX,mBACtCnX,KAAKy5J,uBAAyBz5J,KAAKmX,iBACnCnX,KAAKw5J,eAAgB,GAErBx5J,KAAKw5J,eAAgB,EAIlB,6BAA6Bv/B,GAClCj6H,KAAK8W,mBAAqBmjH,EAGrB,cAAc9zH,GACnB,OAAOA,EAAQ,WAAa,KAG9B,qCAEE,OADenG,KAAK4C,WAAWiC,UAAUsB,MAAO3D,OAClC4U,sBAAsBpS,cAG/B,OAAOyJ,GACZnB,WAAW,KACLmB,EAAUymC,eACZzmC,EAAUymC,cAAcC,mBAEzB,IAGG,oBACN,MAAMglH,EAAgBn6J,KAAK+yH,iBAAiB9yH,QAAQ6W,mBAElD9W,KAAK8W,wBADepL,IAAlByuJ,EACwBn6J,KAAK05J,qCAELS,G,sCAvGnBZ,GAAmC,8D,uBAAnCA,EAAmC,qD,OAAA,M,62CCdhD,cACE,oCAMA,eACE,cACA,gBACE,kBACE,kBAEO,iEAA8B,6BACpB,EAAAW,WAAA,mBAHjB,OAMA,iBAA2D,gBAC7D,OAEA,gBACE,iBACE,yBAEW,mEAAgC,mDAKxB,EAAA1uI,OAAA,KALR,CAAgC,6BAMtB,EAAA4uI,6BAAA,MAKrB,OACF,OACF,OACF,OAEA,iBACE,mBACE,mBAEO,8DAA2B,4BACjB,EAAAF,WAAW,iBAH5B,OAMA,kBACF,OAEA,iBACE,iBACE,2BAEW,uEAAoC,mDAG5B,EAAA1uI,OAAA,KAHR,CAAoC,6BAI1B,EAAA0uI,WAAA,YAOrB,OACF,OACF,OACF,OAEA,iBACE,mBACE,oBAEO,iEAA8B,6BACpB,EAAAA,WAAA,mBAHjB,OAMA,kBACF,OACF,OACF,OACF,O,MAjFqB,qCAMd,iEAKQ,2CADA,kDAKD,4DAMO,6DAA8C,+BAA9C,CAA8C,cAA9C,CAA8C,yCAA9C,CAA8C,eAA9C,CAA8C,oBAqBpD,wCAA2B,YAD3B,kDAKD,mEAMO,0DAA2C,mCAA3C,CAA2C,4CAA3C,CAA2C,gBAqBjD,2CADA,kDAKD,4D,0GCnDd,8J,yBC3BE,gBAEE,gBACE,eACF,OACF,Q,oBAFO,iD,wBAOH,8B,yBAEY,mB,4CDiCX,MAAMG,UAAwC,IAsBnD,YAA4B35J,EACAF,EACAo9C,EACA3tB,EACA4c,EACA9K,EACAliC,EACAgP,EACApL,GAC1B3D,QAT0B,KAAAY,OACA,KAAAF,aACA,KAAAo9C,oBACA,KAAA3tB,cACA,KAAA4c,sBACA,KAAA9K,mBACA,KAAAliC,QACA,KAAAgP,aACA,KAAApL,eA3BrB,KAAAggB,YAAc,IAAuBA,YAErC,KAAAzE,OAAQ,EACR,KAAAojB,WAAoB,EACpB,KAAAk4H,eAAgB,EAChB,KAAAC,cAAe,EACf,KAAAC,iBAAkB,EAIlB,KAAAC,SAAiB,GACjB,KAAA7iJ,KAAO,CACZuqB,QAASniC,KAAKU,KAAKU,EAAE,6BACrBs5J,aAAc16J,KAAKU,KAAKU,EAAE,mCAC1B8kC,aAAc,CACZ1W,YAAaxvB,KAAKU,KAAKU,EAAE,uCAgBtB,WACLpB,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eAEvC9G,KAAKkkB,cAAgBlkB,KAAKiwB,YAAY/R,OAAO,MAAMgG,cACnDlkB,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKkkB,eACR4B,mBACA3lB,KACCH,KAAKI,kBAENC,UAAWsF,IACV3F,KAAKgJ,YAAcrD,EACnB3F,KAAK26J,wBAGT36J,KAAK46J,sBAAwB56J,KAAKyD,aAAamC,cAAcsC,GAAGlI,KAAKkkB,eAAewvC,mBAAmBl4C,KAGlG,sBACLxb,KAAKgf,OAAQ,EACbhf,KAAKs6J,gBAAkBt6J,KAAKgJ,YAAY8gD,SACxC9pD,KAAKu6J,eAAiBv6J,KAAKgJ,YAAY6xJ,WACvC76J,KAAKw6J,kBAAoBx6J,KAAKgJ,YAAYonG,cAErCpwG,KAAKs6J,cAKVt6J,KAAK49C,kBAAkBntB,QAAQzwB,KAAKgJ,aACjCyG,KAAMq6C,IACL9pD,KAAKy6J,SAAW3wG,EAChB9pD,KAAKH,MAAMS,kBAEZka,MAAOwE,IACNhf,KAAK6sC,oBAAoB+xB,UAAU5/C,EAAOhf,KAAKgJ,eAVjDhJ,KAAKgf,OAAQ,EAcjB,mBAA0BimB,GACxBjlC,KAAK+hC,iBAAiB+pH,UAAU7mH,QAAUA,EAIrC,WAAW1+B,GAChBvG,KAAK2kC,eAAiB3kC,KAAKgJ,YAAY6xJ,WAAW38G,MAAMkR,OAAO,CAAE7oD,KAAM,CAAEhB,KAAMgB,EAAKhB,QACjFkK,KAAK,KAGJzP,KAAK49C,kBAAkBntB,QAAQzwB,KAAKgJ,aAAa,GACjDhJ,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKgJ,aACRw0B,UAEHx9B,KAAKH,MAAMS,kBAEZka,MAAOwE,GAAchf,KAAK6sC,oBAAoB+xB,UAAU5/C,EAAOhf,KAAKgJ,cAGlE,cAAcmnG,GACnBnwG,KAAKgJ,YAAYonG,cAAclyD,MAAM48G,SAAS,CAAEC,QAAS5qD,EAAQjoG,IAAjElI,GACGyP,KAAK,KACJpL,EAAEouB,OAAOzyB,KAAKy6J,SAAWroF,GAChBA,EAAM7sE,OAAS4qG,EAAQ5qG,MAKhCvF,KAAK49C,kBAAkBntB,QAAQzwB,KAAKgJ,aAAa,GACjDhJ,KACGyD,aACAmC,cACAsC,GAAGlI,KAAKgJ,aACRw0B,UACHx9B,KAAKH,MAAMS,kBAEZka,MAAOwE,GAAchf,KAAK6sC,oBAAoB+xB,UAAU5/C,EAAOhf,KAAKgJ,e,sCAlH9DqxJ,GAA+B,qG,uBAA/BA,EAA+B,skBC9C5C,gBACE,sBAMA,gBACE,gBAGE,mCAIF,OACA,gBAEE,iBACE,+BACoB,oCAAY,EAAAQ,WAAA,MAGhC,OACF,OACF,OACF,OACF,Q,MAzBO,6BAKA,+BAEE,qDAGS,mCAAqD,8BAK9D,uCAEmB,uCAA4B,iC,uECSxD,kPAuBO,MAAMG,UAAmC,IAoB9C,YAA4BjyJ,EACGknB,EACAxY,EACA/W,EACAqzE,EACAlnC,EACAlqC,EACAitC,EACAqrH,EACAh4J,EACA4L,EACApL,EACA5D,GAC7BC,QAb0B,KAAAiJ,WACG,KAAAknB,cACA,KAAAxY,SACA,KAAA/W,OACA,KAAAqzE,eACA,KAAAlnC,sBACA,KAAAlqC,SACA,KAAAitC,WACA,KAAAqrH,cACA,KAAAh4J,iBACA,KAAA4L,aACA,KAAApL,eACA,KAAA5D,QA/BxB,KAAA+9F,aAAsB,YAAe59F,KAAKyX,QAC1C,KAAAyjJ,YAAqBl7J,KAAKyX,OAAOxX,QAAQkO,KAAKT,UAM9C,KAAAgmE,SAAU,EAEV,KAAAE,YAAc5zE,KAAKiwB,YAAY/R,OAAO,MACtC,KAAAtG,KAAO,CACZylH,gBAAiBr9H,KAAKU,KAAKU,EAAE,uBAMrB,KAAAg+C,WAAY,EAkBf,WACLp/C,KAAKm7J,uCAELn7J,KAAKo7J,WAGA,cACLt7J,MAAM4Y,cAGD,qBACL1Y,KAAKyX,OAAOswB,GAAG,oBAAqB/nC,KAAKyX,OAAOyG,QAG3C,QAAQA,G,MACb,IAAI,cAAE44B,EAAa,UAAEC,GAAc74B,EAEtB,QAAb,EAAAle,KAAKga,gBAAQ,SAAEK,QAAO,GAElBra,KAAK49F,cACP59F,KAAKyX,OAAOswB,GAAG/nC,KAAK49F,aAAc,CAAE15E,cAAe4yB,EAAc5uC,KAC9DuH,KAAK,KACJzP,KAAKi7J,YAAYrqH,YAAYkG,EAAc5uC,IAC3ClI,KAAK6sC,oBAAoBa,SAASoJ,EAAeC,KAK/C,WACR/2C,KACGq7J,qBACA5rJ,KAAMid,IACL1sB,KAAKmZ,OAASuT,EACd1sB,KAAKs7J,eAAiB5uI,EAAUxqB,iBAChClC,KAAKH,MAAMS,gBAEXN,KAAKoqH,WAEDpqH,KAAK4zE,YAAuB,WAC9BlnD,EAAU7qB,SACR,SACA,CAAE0D,KAAMvF,KAAKyD,aAAamC,cAAcsC,GAAGlI,KAAK4zE,YAAuB,WAAGp4D,OAK1Exb,KAAK4zE,YAAuB,WAC9B5zE,KACGyD,aACAmC,cACAsC,GAAGlI,KAAK4zE,YAAuB,WAC/BlvE,MACAvE,KACCH,KAAKI,kBAENC,UAAUqO,IACT1O,KAAKu+F,kBAAoB7vF,EACzB1O,KAAKH,MAAMS,oBAIlBka,MAAOwE,IACwB,wDAA1BA,EAAMqjC,kBACRriD,KAAKyD,aAAa8xD,KAAK7wD,MAAMrE,UAAWk1D,IACtC,IAAKA,EAAKhvD,KAAM,CAEd,IAAIyH,EAAM,EAAIhO,KAAK6O,WAAW0sJ,aAC9BvtJ,EAAIq0B,OAAO,CAAEm5H,SAAUxtJ,IACvBwS,OAAOgoB,SAASjjC,KAAOyI,EAAIqU,cAG/BriB,KAAK6sC,oBAAoBgB,eAAe7uB,MAKtC,WACRhf,KAAK+zE,aAAaC,aAAah0E,KAAKU,KAAKU,EAAE,kCAGtC,sBACLpB,KAAK4vC,SAASkB,iBACd9wC,KAAKyX,OAAOswB,GAAG/nC,KAAKk7J,YAAal7J,KAAKyX,OAAOyG,QAGrC,qBACR,IAAIoP,EAAqB,CACvBa,OAAQ,IAGV,MAAMrb,EAAO9S,KAAK4zE,YAAY9gE,KAAOuqB,SAASr9B,KAAK4zE,YAAY9gE,WAAQpH,EACjEgD,EAAS1O,KAAK4zE,YAAYyqB,UAAYhhE,SAASr9B,KAAK4zE,YAAYyqB,gBAAa3yF,EAC7EgQ,EAAU1b,KAAK4zE,YAAY7kE,YASjC,OAPI+D,IACFwa,EAASa,OAAa,KAAI,CAAE5oB,KAAMvF,KAAKyD,aAAa0Z,MAAMjV,GAAG4K,GAAM0I,OAEjE9M,IACF4e,EAASa,OAAe,OAAI,CAAE5oB,KAAMvF,KAAKyD,aAAamC,cAAcsC,GAAGwG,GAAQ8M,OAG1Exb,KAAK4vC,SAASwB,4BAA4B11B,EAAS5I,EAAMwa,GAG1D,uCACNttB,KAAK4vC,SACFa,mBACAtwC,KACC,YAAU,KAAOH,KAAKq/C,qBAEvBh/C,UAAWsF,IACV3F,KAAKiqF,QAAQ,CAAEnzC,cAAenxC,EAAIoxC,WAAW,O,sCAnJxCikH,GAA0B,wJ,uBAA1BA,EAA0B,wB,OAAA,K,KAe1B,KAAmB,G,mGCtChC,0KAwBO,MAAMS,UAAiC,IAQ5C,YAAqB/6J,EACAgX,EACAw0I,EACAtpJ,EACA6jF,EACA5sC,EACA9wC,EACA+H,GACnBhR,QARmB,KAAAY,OACA,KAAAgX,iBACA,KAAAw0I,gBACA,KAAAtpJ,aACA,KAAA6jF,uBACA,KAAA5sC,iBACA,KAAA9wC,WACA,KAAA+H,QAdd,KAAA8G,KAAO,CACZ8jJ,OAAQ17J,KAAKU,KAAKU,EAAE,iBACpBu6J,aAAc37J,KAAKU,KAAKU,EAAE,+BAgB5B,WACEpB,KAAK4C,WAAWiB,MACb3D,UACAC,KACCH,KAAKI,kBAENC,UAAWwD,IACV7D,KAAK6D,MAAQA,EAEb,IAAIiL,EAAoB9O,KAAK0X,eAAe5C,WACxC9F,EAAUhP,KAAKymF,qBAAqBk3C,kBAAkB39H,KAAK6D,MAAMmL,SACrEhP,KAAK47J,WAAa57J,KAAKksJ,cAAc2P,wBACnC/sJ,EACA2W,KAAKC,UAAU1W,MAKhB,kBAAkBhH,GACvBhI,KAAK65C,eAAe94C,KAAK,IAAoBf,KAAK+I,SAAU,CAAEw9B,KAAMvmC,KAAK47J,aACzE5zJ,EAAMuE,kB,sCAvCGkvJ,GAAwB,6F,uBAAxBA,EAAwB,yNAVjC,cAGG,iCAAS,EAAAK,kBAAA,MACV,oBACA,iBAA4B,QAAgB,OAC9C,Q,MANG,kCAEA,+BAG2B,sC,uXCb3B,MAAM,UAAkC,IAH/C,c,oBAKS,KAAAl5C,sBAAoC,KAIpC,WACL9iH,MAAMqkB,WAENnkB,KAAK4X,KAAK0K,MAAQ5hB,KAAKU,EAAE,kCACzBpB,KAAK4X,KAAKmkJ,kBAAoBr7J,KAAKU,EAAE,8CACrCpB,KAAK4X,KAAKokJ,eAAiBt7J,KAAKU,EAAE,qBAClCpB,KAAK4X,KAAKqkJ,SAAWv7J,KAAKU,EAAE,qBAE5BpB,KAAKinD,eAAgB,EACrBjnD,KAAKmnD,qBAAsB,EAC3BnnD,KAAKqnD,WAAY,EAGZ,gBAAgBxmD,GACjBb,KAAKk8J,wBACPp8J,MAAMynD,gBAAgB1mD,GAInB,OAAO4pF,GACZ3qF,MAAM0rB,OAAOi/D,GACbzqF,KAAKm8J,0BAA0Br1J,cAAcyG,QAGxC,uBACL,OAAsC,OAA/BvN,KAAK4iH,uBAAkC5iH,KAAK4iH,sBAAsB37G,OAAS,G,oCA/BzE,I,uBAAA,EAAyB,qD,OAAA,K,shCClCtC,gBACE,gBAGE,gBACE,eACF,OAEA,gBACE,iBAA4D,kCAAU,EAAAsgD,gBAAA,MACpE,gBACE,kBAKA,gBACE,gBACE,uBAEO,sEAFP,OAMF,OACF,OACA,kBACF,OACF,OACF,OAEA,kBACE,qBACQ,iCAAS,EAAAA,gBAAA,MAIT,gDACR,OACF,OACF,OACF,Q,MApC2C,yCAS1B,4CADA,4CAOI,gDAM2B,qDASlC,kDAAmC,sCADnC,sC,oEDAD,G,4BEGN,MAAM,UAA4B,IAMvC,YAAqB/mD,EAC0BsR,EAC1BjS,EACAa,GAEnBZ,MAAMgS,EAAQjS,EAAOW,GALF,KAAAA,aAC0B,KAAAsR,SAC1B,KAAAjS,QACA,KAAAa,OALd,KAAAymD,qBAA8B,EAWrC,WACErnD,MAAMqkB,WAGNnkB,KAAK4G,SACF4E,KAAK,mCACLb,SAAS3K,KAAK8R,OAAOsqJ,gBACrBjnI,OAAOn1B,KAAK8R,OAAOuqJ,WAGtBx1J,OAAOqE,SAASwT,MACb9U,GAAG,uBACF,uCACC/I,IACDb,KAAKsnD,QAAQzmD,KAInB,cACEgG,OAAOqE,SAASwT,MAAMyrB,IAAI,wBAC1BrqC,MAAM4Y,e,sCAnCG,GAAmB,eAOV,KAAkB,sB,uBAP3B,EAAmB,qQCrChC,gBACE,gBAIF,S,0GC2BO,MAAM,EACX,YAA4B4jJ,GAAA,KAAAA,YAErB,SAASC,GACd,OAAOv8J,KAAKs8J,UAAUE,SAAS,IAAgBC,KAAMF,IAAW,I,sCAJvD,GAAmB,Y,yBAAnB,EAAmB,QAAnB,EAAmB,qBADN,S,wFCDnB,MAAM,EA+CX,YAA4BxzJ,GAAA,KAAAA,WA7CpB,KAAA2zJ,gBAAkB,CACxB,8BACA,+BACA,gCAIc,KAAAl6C,SAAW,CACzBlX,cAAetrG,KAAK+I,SAASrE,IAA0B,KACvDi4J,2BAA4B38J,KAAK+I,SAASrE,IAAuC,KACjFk4J,mCAAoC58J,KAAK+I,SAASrE,IAA+C,KACjGu3E,YAAaj8E,KAAK+I,SAASrE,IAAwB,KACnDwnB,MAAOlsB,KAAK+I,SAASrE,IAAiB,KACtCmzD,KAAM73D,KAAK+I,SAASrE,IAAiB,KACrCs5D,cAAeh+D,KAAK+I,SAASrE,IAA0B,KACvDm1C,eAAgB75C,KAAK+I,SAASrE,IAAoB,KAClDosE,aAAc9wE,KAAK+I,SAASrE,IAAkC,KAC9D+8G,aAAczhH,KAAK+I,SAASrE,IAAyB,KACrDm2C,UAAW76C,KAAK+I,SAASrE,IAAsB,KAC/C28B,OAAQrhC,KAAK+I,SAASrE,IAAyB,KAC/Cm4J,oBAAqB78J,KAAK+I,SAASrE,IAAyB,GAC5Do4J,gBAAiB98J,KAAK+I,SAASrE,IAA4B,KAC3Dq4J,kBAAmB/8J,KAAK+I,SAASrE,IAAuB,KACxD/B,OAAQ3C,KAAK+I,SAASrE,IAAY,KAClCjB,aAAczD,KAAK+I,SAASrE,IAAkB,KAC9Cq1E,qBAAsB/5E,KAAK+I,SAASrE,IAA0B,MAIhD,KAAA+c,QAAU,CACxBihG,OAAQ,CACNC,qBAAsB,EACtBq6C,eAAgB,GAElB/qF,YAAa,IACb9iD,aAAc,KAIA,KAAAjD,MAAsD,GAOpElsB,KACG08J,gBACAh3J,QAASokF,IACR9pF,KAAKksB,MAAM49D,GAAS/8E,GAAsB/M,KAAKwiH,SAASt2F,MAAMqzB,SAASuqC,EAAM/8E,KAU5E,UAAUm0B,GACflhC,KAAK86F,KAAKmiE,IAAI/7H,GAOT,UAAUtR,GACf,IAAoBgnH,4BAClB52I,KAAK+I,SAASrE,IAAI,KAClBkrB,IA5BW,aAAd,c,0BAAmC,M,2BClC/B,MAAM,EACX,YAAY7mB,GACV,YAAS,0CACT,MAAMy4B,EAAgB,IAAI,EAAyBz4B,GACnDyX,OAAOihB,YAAYD,cAAcx9B,SAASw9B,I,uBAJjC,I,oDAAA,GAAwB,sBAJxB,CACT,O,4BCJJ,MAAM,UAA2B,KAI1B,MAAM07H,EAAiB,YAAW,GCNlC,MAAMC,EAEX,cACEt2J,OAAO,iBAAiBvC,KAAK,CAACyY,EAAG47C,KAC/B,IAAI1mD,EAAKpL,OAAO8xD,GAEhB,MAAM13C,EAAYhP,EAAGzG,KAAK,sBAEpB4xJ,EAAanrJ,EAAGzG,KAAK,yBAC3B4xJ,EAAW1xI,SACX,MAAM2xI,EAAWD,EAAW,GAAGtyH,UAC/B,IAAIstD,EAAW/6D,SAASprB,EAAGhI,KAAK,eAEhCgI,EAAGrI,GAAG,QAAS,yCAA2C/I,IACxDgG,OAAOhG,EAAIkG,QAAQC,QAAQ,gBAAgByrB,UACpC,IAITxgB,EAAGzG,KAAK,+CAA+CY,MAAOvL,IAC5DA,EAAI0L,iBACJ,IAAIsnB,EAAMhtB,OAAOw2J,EAASx8I,QAAQ,SAAUu3E,EAAS/1E,aAWrD,OAVAwR,EAAI9yB,OACJ8yB,EAAInpB,YAAY,wBAChBmpB,EAAIroB,KAAK,2BAA2BmY,KAAK,YAAY,GACrDkQ,EAAIroB,KAAK,8CAA8CmY,KAAK,YAAY,GAExE1C,EAAUkU,OAAOtB,GACjBukE,GAAY,EAEZn3E,EAAUzV,KAAK,uCAAuC+B,SAE/C,O,sCAhCF4vJ,I,yBAAAA,EAAyB,QAAzBA,EAAyB,YCH/B,MAAMG,EAcX,YAAmB12J,GAAA,KAAAA,WACjB5G,KAAKu9J,MAAQv9J,KAAK4G,SAASqD,KAAK,UAChCjK,KAAKw9J,QAAUx9J,KAAK4G,SAASqD,KAAK,YAClCjK,KAAKm9E,IAAMt2E,OAAO,IAAI7G,KAAKu9J,eAC3Bv9J,KAAKwvB,YAAcxvB,KAAK4G,SAASuH,KAAK,eAEtCnO,KAAKy9J,eAbP,gBACE52J,OAAOqE,UAAUtB,GAAG,QAAS,iCAAmC/I,IAC9D,MAAMuD,EAAOyC,OAAOhG,EAAIkG,QAAeC,QAAQ,qBAC/C,IAAIs2J,EAAwBl5J,KAazB,eACLpE,KAAK09J,iBAGC,iBACN19J,KAAKgtB,OAELnmB,OAAO,IAAM7G,KAAKu9J,MAAQ,eAAevzJ,QAAQ,SACjDnD,OAAO,IAAM7G,KAAKu9J,MAAQ,eAAevzJ,QAAQ,UAG3C,cACN,OAAOnD,OAAO,IAAM7G,KAAKu9J,MAAQ,aAAa37J,MAGxC,WACN,OAAOiF,OAAO,IAAM7G,KAAKu9J,MAAQ,eAAe37J,MAG1C,OACN5B,KAAKm9E,IAAIhwE,OAET,IAAIjF,EAAKlI,KAAKm9E,IAAI,GAAGj1E,GACjBy1J,EAAW39J,KAAK49J,cAChBz3J,EAAQnG,KAAKykE,WACbh+D,EAAOzG,KAAKw9J,QACZhuI,EAAcxvB,KAAKwvB,YAsBvB3oB,OApBe,8CACwBqB,uHAGpBA,iGACAA,6EACMA,0FAEEzB,qCACCN,2CACMqpB,0JAIWtnB,YAAay1J,qEAMzCE,YAAY79J,KAAKm9E,KAElC,IAAIlyD,EAAOjrB,KACX6G,OAAO,IAAMqB,EAAK,WAAW0B,GAAG,SAAS,WAGvC,OAFA/C,OAAO,IAAMqB,EAAK,YAAYuqB,SAC9BxH,EAAKkyD,IAAIp8E,QACF,M,8BCxEN,MAAM+8J,GAEX,YAAoB1zH,EACAzrB,GADA,KAAAyrB,kBACA,KAAAzrB,OAGpB,SACE9X,OAAO,wBAAwBvC,KAAK,CAACyY,EAAG47C,KACtC,IAAI1mD,EAAKpL,OAAO8xD,GAEhB,MAAM13C,EAAYhP,EAAGzG,KAAK,0BACpB4xJ,EAAanrJ,EAAGzG,KAAK,wBAC3B4xJ,EAAW1xI,SACX,MAAM2xI,EAAWD,EAAW,GAAGtyH,UAC/B,IAAIstD,EAAW/6D,SAASprB,EAAGhI,KAAK,eAGhCgI,EAAGrI,GAAG,SAAU,qBAAuB/I,IACrC,IAAIgzB,EAAMhtB,OAAOhG,EAAIkG,QAAQC,QAAQ,eACrChH,KAAKu2B,WAAWtkB,EAAI4hB,EAAI5pB,KAAK,SAG/BgI,EAAGrI,GAAG,QAAS,sBAAwB/I,IACrCA,EAAI0L,iBACJ1F,OAAOhG,EAAIkG,QAAQC,QAAQ,eAAeyrB,UACnC,IAITxgB,EAAGzG,KAAK,mBAAmBY,MAAOvL,IAChCA,EAAI0L,iBACJ,IAAIsnB,EAAMhtB,OAAOw2J,EAASx8I,QAAQ,SAAUu3E,EAAS/1E,aAKrD,OAJAwR,EAAI9yB,OACJ8yB,EAAInpB,YAAY,uBAChBuW,EAAUkU,OAAOtB,GACjBukE,GAAY,GACL,MAQN,WAAWnmF,EAAW8rJ,GAC3B,IAAIlqI,EAAM5hB,EAAGzG,KAAK,IAAMuyJ,GACpBn/I,EAAU5e,KAAKg+J,oBAAoBnqI,EAAKkqI,GAE5C/9J,KAAK2e,KACFyO,KACCnb,EAAGhI,KAAK,cACR2U,EACA,CACET,QAAS,CAAE,OAAU,oBACrBG,iBAAiB,IAEpBje,UACE8N,IACC9J,EAAEC,KAAK6J,EAAM,CAACvM,EAAY6vB,KACxB,IAAI7B,EAAU1kB,SAASC,eAAesmB,GAClC7B,aAAmBquI,iBACrBruI,EAAQzpB,MAAQvE,EACPguB,IACTA,EAAQre,YAAc3P,MAI3Bod,GAAchf,KAAKoqC,gBAAgByD,eAAe7uB,IAOjD,oBAAoB6U,EAAYkqI,GACtC,IAAIn/I,EAAc,CAChBs/I,WAAYH,EACZI,WAAYt3J,OAAO,sBAAsBjF,OAS3C,OALAiyB,EAAIroB,KAAK,sBAAsBlH,KAAK,CAAC2oE,EAAWh7D,KAC9C,IAAI/K,EAAQL,OAAOoL,GACnB2M,EAAQ1X,EAAMiH,KAAK,eAAiBjH,EAAMtF,OAAS,MAG9Cgd,G,uCAtFEk/I,IAA+B,wB,0BAA/BA,GAA+B,QAA/BA,GAA+B,YC6BrC,MAAM,GACX,YAAY/0J,IA7BP,SAA+BA,GACpCyX,OAAOihB,YAAY8gF,mBAAmB9yG,KAAM+xB,IAC1CA,EAAcghF,SAAS3nE,UAAUujH,gBAAgB,SAAU,CAAC,WAElC58H,EAAcghF,SAASf,aAC7B28C,gBAAgB,WAAY,CAAC,WAExB58H,EAAcghF,SAASvmC,YAC7Bl2B,iBAAiB,SAAU,CAAC7C,IAAKg6G,IAEvC17H,EAAcghF,SAAS7/G,OAC7B6N,IAAI,UAAW,eAGtB,IAAI2sJ,EACJG,EAAwBe,SAEFt1J,EAASrE,IAAIo5J,IACrBO,WAYdC,CAAsBv1J,I,wBAFb,K,qDAAA,IAAY,sBAJZ,CACT+0J,MCbG,MAAM,WAAgC,IAIlC,MAAMvgJ,EAAc/a,GACvB1C,MAAMqqE,MAAM5sD,EAAU/a,GACtBxC,KAAKu+J,kBAGC,kBACFv+J,KAAKmG,QAAgC,IAAvBnG,KAAKmG,MAAM+rE,SACzBlyE,KAAKmG,MAAM2nE,QAAQr+D,KAAK,KAEgB,gBAAhCzP,KAAKud,SAAS4P,QAAQhlB,OACxBnI,KACGyD,aACAmC,cACAC,MACAgsD,MAAM7xD,KAAKud,SAASrV,MAMrC,YACI,MAAO,GAGJ,OAAO0nB,EAAqBC,GAC3B7vB,KAAKsX,UACLsY,EAAQre,YAAcvR,KAAKwvB,YAI/BxvB,KAAKmG,MAAM3B,SAASkB,QAAQ,CAAC9D,EAAkBmb,KACzC/c,KAAKud,SAASihJ,UAChBx+J,KAAKy+J,iBAAiB78J,EAAKguB,EAAS7S,GAEpC/c,KAAK0+J,iBAAiB98J,EAAKguB,EAAS7S,KAKrC,UACH,OAAQ/c,KAAKmG,QACRnG,KAAKmG,MAAM3B,UACmB,IAA/BxE,KAAKmG,MAAM3B,SAASyC,OAOtB,iBAAiBrF,EAAkBguB,EAAqB7S,GAC9D,MAAMyhJ,EAAYx+J,KAAKud,SAASihJ,UAC1Bj4H,EAAOr7B,SAASoF,cAAc,KAEpCi2B,EAAKhhC,KAAOi5J,EAAUj5J,KAAO,SAAW3D,EAAI+8J,SAASz2J,GACrDq+B,EAAKj1B,aAAa,SAAU,UAC5Bi1B,EAAKh1B,YAAc3P,EAAIg9J,WAAa,IAAMh9J,EAAI+8J,SAASl4J,KACvDmpB,EAAQve,YAAYk1B,GAEpBvmC,KAAK6+J,aAAajvI,EAAS7S,GAMrB,iBAAiBnb,EAAkBguB,EAAqB7S,GAC9D,MAAMsE,EAAOnW,SAASoF,cAAc,QACpC+Q,EAAK9P,YAAc3P,EAAIg9J,WAAa,IAAMh9J,EAAI+8J,SAASl4J,KACvDmpB,EAAQve,YAAYgQ,GACpBrhB,KAAK6+J,aAAajvI,EAAS7S,GAGrB,aAAa6S,EAAqB7S,GACxC,GAAIA,EAAI/c,KAAKmG,MAAM3B,SAASyC,OAAS,EAAG,CACtC,MAAMua,EAAMtW,SAASoF,cAAc,QACnCkR,EAAIjQ,YAAc,KAElBqe,EAAQve,YAAYmQ,KA9EP,aAAd,c,0BAA2B,M,oCClBzB,MAAM,WAA6B,IAE/B,UACH,OAAQxhB,KAAKmG,QACRusI,WAAW1yI,KAAKmG,MAAMwyD,MAAM,QAAQ,KCoC1C,MAAM,GACX,YAAY5vD,GAvCZyX,OAAOihB,YAAY8gF,mBAAmB9yG,KAAM+xB,IAC1C,IAAI2tC,EAAsB3tC,EAAcghF,SAASf,aACjDtyC,EAAoBjnB,aAAa,GAAyB,QAAS,CAAC,gBACpEinB,EAAoBjnB,aAAa,GAAsB,WAAY,CAAC,aAAc,gBAAiB,iBAEnG1mB,EAActV,MAAM4yI,8BAA6B,SAAU5gJ,GACzD,MAAO,CACLvc,IAAK,YACLN,KAAM,gBACNq4E,QAAS,SAAUH,GACjB,IAAItoD,EAAQ5sB,EAAEy6B,UAAUy6C,EAAS,CAAC53E,IAAK,aACvC,OAAkB,IAAXsvB,EAAeA,EAAQ,EAAIsoD,EAAQtyE,QAE5CsW,SAAU,cACVgpB,KAAM,eAIV/E,EAActV,MAAM6yI,6BAA4B,SAAU7gJ,GACxD,MAAO,CACLvc,IAAK,YACLN,KAAM,gBACNklC,KAAM,WACNmzC,QAAS,SAAUH,GACjB,IAAItoD,EAAQ5sB,EAAEy6B,UAAUy6C,EAAS,CAAChzC,KAAM,YACxC,OAAkB,IAAXtV,EAAeA,EAAQ,EAAIsoD,EAAQtyE,QAE5C2Q,KAAMlX,KAAKU,EAAE,8B,wBAWR,K,qDAAA,IAAY,sBAHZ,K,ICjEIi9I,G,cAAjB,SAAiBA,GA2Bf,SAAgB2gB,EAAYC,EAAgB/8I,GAC1C,MAAMg9I,EAASh0J,SAASoF,cAAc,UAChC6uJ,EAAMD,EAAOE,WAAW,MAE9B,IAAIhiI,EAAQlb,EAAMkb,MACdlL,EAAShQ,EAAMgQ,OAEfkL,EAAQlL,EACNkL,EAAQ6hI,IACV/sI,GAAU+sI,EAAU7hI,EACpBA,EAAQ6hI,GAGN/sI,EAAS+sI,IACX7hI,GAAS6hI,EAAU/sI,EACnBA,EAAS+sI,GAIbC,EAAO9hI,MAAQA,EACf8hI,EAAOhtI,OAASA,EAChBitI,EAAIE,UAAUn9I,EAAO,EAAG,EAAGkb,EAAOlL,GAClC,IAAIotI,EAAUJ,EAAOK,UAAU,cAC/B,MAAO,CAACD,EAASE,EAAcF,IAGjC,SAASE,EAAcC,GACrB,MAAMC,EAAQD,EAAQpnJ,MAAM,KAAK,GAAG+E,QAAQ,WAAa,EACvDuiJ,KAAKF,EAAQpnJ,MAAM,KAAK,IACxBw+H,SAAS4oB,EAAQpnJ,MAAM,KAAK,IACxBunJ,EAAOH,EAAQpnJ,MAAM,KAAK,GAAGA,MAAM,KAAK,GAAGA,MAAM,KAAK,GACtD63D,EAAMwvF,EAAMz4J,OACZ44J,EAAK,IAAIC,WAAW5vF,GAC1B,IAAK,IAAInzD,EAAI,EAAGA,EAAImzD,EAAKnzD,IAAK8iJ,EAAG9iJ,GAAK2iJ,EAAM9+E,WAAW7jE,GACvD,OAAO,IAAIgjJ,KAAK,CAACF,GAAK,CAAC/sJ,KAAM8sJ,IArDf,EAAAI,WAAhB,SAA2Bf,EAAgBvhJ,GACzC,OAAO,IAAInO,QAAQ,CAACC,EAASnL,KAC3B,MAAM47J,EAAS,IAAIC,WACnBD,EAAOz9I,OAAU29I,IACf,MAAMj+I,EAAQ,IAAIC,MAClBD,EAAMM,OAAS,IAAMhT,EAAQwvJ,EAAYC,EAAS/8I,IAClDA,EAAME,IAAM+9I,EAAYp5J,OAAOu4B,QAEjC2gI,EAAOG,cAAc1iJ,MAWT,EAAAshJ,YAAW,EA3B7B,CAAiB3gB,QAAY,K,uDCejB,iB,oBAA0B,8C,0BAItC,sBACI,oBACA,iBACJ,Q,oBAFoC,2CAC3B,6C,yCCeF,MAAM,GAyBX,YAA6B39I,EACAF,EACAZ,EACAkxE,GAHA,KAAApwE,OACA,KAAAF,aACA,KAAAZ,uBACA,KAAAkxE,eAnBtB,KAAAghB,MAAe,EACf,KAAAuuE,aAAc,EAKd,KAAAzoJ,KAAO,CACZ0oJ,oBAAqBtgK,KAAKU,KAAKU,EAAE,kCACjCm/J,oBAAqBvgK,KAAKU,KAAKU,EAAE,uCACjCo/J,gBAAiBxgK,KAAKU,KAAKU,EAAE,oCAC7Bq/J,kBAAmBzgK,KAAKU,KAAKU,EAAE,gCAC/Bs/J,cAAe1gK,KAAKU,KAAKU,EAAE,oBAC3Bu/J,UAAW3gK,KAAKU,KAAKU,EAAE,+BACvBwgE,QAAS5hE,KAAKU,KAAKU,EAAE,qBAShB,WACL,MAAMwuB,EAAU5vB,KAAKQ,WAAWsG,cAChC9G,KAAK+G,OAAS6oB,EAAQoT,aAAa,UACnChjC,KAAKye,OAASmR,EAAQoT,aAAa,UAG9B,oBAAoB49H,GACzB,MAAM9jJ,EAAqBI,MAAM3B,KAAKvb,KAAK6gK,iBAAiB/5J,cAAcgW,OAC1E,GAAqB,IAAjBA,EAAM7V,OACR,OAGF,MAAMyW,EAAOZ,EAAM,IACkD,IAAjE,CAAC,aAAc,YAAa,aAAaM,QAAQM,EAAK5K,MAK1DurI,GAAa2hB,WAAW,IAAKtiJ,GAAMjO,KAAK,EAAEqxJ,EAASC,MAEjDA,EAAKt6J,KAAOiX,EAAKjX,KACjBzG,KAAKghK,WAAaD,EAClB/gK,KAAKihK,iBAAmBH,IARxB9gK,KAAKqgK,aAAc,EAYhB,aAAax/J,GAClBA,EAAI0L,iBACJvM,KAAK8xF,MAAO,EACZ,MAAM0rB,EAASx9G,KAAK8wE,aAAa6sC,aAAa39G,KAAK+G,OAAQ/G,KAAKghK,WAAYhhK,KAAKye,OAAQ,QACzFze,KAAKJ,qBAAqB4wE,oBAAoBxwE,KAAK4X,KAAK+oJ,UAAW,CAACnjD,IAEpEA,EAAO,GAAGn9G,UACPQ,IACC,OAAQA,EAAIiS,MACV,KAAK,EACH,OAEF,KAAK,EAIH,OAHA9S,KAAKghK,WAAWE,SAAW,IAC3BlhK,KAAK8xF,MAAO,OACZtxE,OAAOgoB,SAASR,SAGlB,QAEE,SAGLhpB,IACChf,KAAKJ,qBAAqBm6D,SAAS/6C,EAAMA,OACzChf,KAAK8xF,MAAO,K,uCAlFP,IAAyB,0C,wBAAzB,GAAyB,2D,OAAA,K,gsBDtCtC,gBACI,kBAKA,gBACI,oBAKO,kCAAU,EAAAqvE,oBAAA,MALjB,OAMJ,OACA,gBACI,iBACE,gBACE,wBACF,OACN,OACJ,OACA,4BAKA,qBACQ,iCAAS,EAAAC,aAAA,MAIjB,Q,MA7BW,iDAAsC,0CAanC,uDAEI,mCAIQ,wCAQlB,iDADA,iD,yCEWD,MAAM,GACX,YAAYr4J,GACUA,EAASrE,IAAI,KACrB66C,SAAS,8BAA+B,IAC3C,CACL,CAAE9tB,SAAU,qBAAsByxB,IAAK,O,wBALlC,K,qDAAA,IAAY,qBAPZ,CACP,SCON,MAAM,WAA6B,IAAnC,c,oBAGY,KAAA/W,oBAAqB,GAG1B,MAAMk1H,GAAmB,YAAW,ICGpC,MAAM,GACX,cAbA7gJ,OAAOihB,YAAY8gF,mBAChB9yG,KAAM+xB,IACoBA,EAAcghF,SAASvmC,YAC7Bl2B,iBAAiB,WAAY,CAAC7C,IAAKm+G,KAEzC7/H,EAAcghF,SAAS7/G,OAC7B6N,IAAI,YAAa,kB,wBAMjB,K,qDAAA,OCJN,MAAM8wJ,I,wBAAAA,K,qDAAAA,KAAmB,SAPnB,CACL,GACA,GACA,GACA,O,+FC1CD,MAAMC,GAOX,YAAYxlF,EAAiBD,EAAelsB,EAAoBosB,GAC9Dh8E,KAAK+7E,SAAWA,EAChB/7E,KAAK87E,OAASA,EACd97E,KAAK4vD,YAAcA,EACnB5vD,KAAKg8E,UAAYA,EAGnB,mBACE,OAAuB,EAAhBh8E,KAAK+7E,SAGd,iBACE,OAAqB,EAAd/7E,KAAK87E,OAAa,EAG3B,sBACE,OAA0B,EAAnB97E,KAAK4vD,YAGd,oBACE,OAAwB,EAAjB5vD,KAAKg8E,UAAgB,EAG9B,WAKE,OAJKh8E,KAAKwhK,aACRxhK,KAAKwhK,WAAaxhK,KAAKyhK,WAGlBzhK,KAAKwhK,WAGN,UACN,SAASE,IACP,OAAOj6I,KAAKg9D,MAA4B,OAArB,EAAIh9D,KAAK68D,WACzBjiE,SAAS,IACTi4G,UAAU,GAEf,OAAOonC,IAAOA,IAAO,IAAMA,IAAO,IAAMA,IAAO,IAAMA,IAAO,IAAMA,IAAOA,IAAOA,KCzC7E,MAAM,WAAuBH,GAGlC,YAAYt7H,GACVnmC,MAAMmmC,EAAO81C,SACX91C,EAAO61C,OACP71C,EAAO2pB,YACP3pB,EAAO+1C,WAETh8E,KAAKimC,OAASA,EAGT,QACLjmC,KAAK+7E,SAAW/7E,KAAKimC,OAAO81C,SAC5B/7E,KAAK87E,OAAS97E,KAAKimC,OAAO61C,OAC1B97E,KAAK4vD,YAAc5vD,KAAKimC,OAAO2pB,YAC/B5vD,KAAKg8E,UAAYh8E,KAAKimC,OAAO+1C,UAGxB,YACLh8E,KAAK4vD,cACL5vD,KAAKg8E,YAGA,WACLh8E,KAAK4vD,cACL5vD,KAAKg8E,YAGA,aACLh8E,KAAKg8E,YAGA,SAAS2lF,GACd,OAAO3hK,KAAK4hK,YAAYD,IACjB3hK,KAAK6hK,eAAeF,GAGtB,YAAYA,GACjB,OAAO3hK,KAAK+7E,SAAW4lF,EAAU7lF,QAC1B97E,KAAK87E,QAAU6lF,EAAU7lF,QACzB97E,KAAK+7E,UAAY4lF,EAAU5lF,UAC3B/7E,KAAK87E,OAAS6lF,EAAU5lF,UACxB/7E,KAAK+7E,SAAW4lF,EAAU5lF,UAC1B/7E,KAAK87E,OAAS6lF,EAAU7lF,OAG1B,eAAe6lF,GACpB,OAAO3hK,KAAK4vD,YAAc+xG,EAAU3lF,WAC7Bh8E,KAAKg8E,WAAa2lF,EAAU3lF,WAC5Bh8E,KAAK4vD,aAAe+xG,EAAU/xG,aAC9B5vD,KAAKg8E,UAAY2lF,EAAU/xG,aAC3B5vD,KAAK4vD,YAAc+xG,EAAU/xG,aAC7B5vD,KAAKg8E,UAAY2lF,EAAU3lF,UAG7B,oBAAoB2lF,GACzB,OAAO3hK,KAAK4vD,YAAc+xG,EAAU/xG,aAC7B5vD,KAAKg8E,UAAY2lF,EAAU/xG,aAC3B5vD,KAAK4hK,YAAYD,GAG1B,oBACE,OAAO3hK,KAAK4vD,cAAgB5vD,KAAKimC,OAAO2pB,aACjC5vD,KAAKg8E,YAAch8E,KAAKimC,OAAO+1C,WAC/Bh8E,KAAK+7E,WAAa/7E,KAAKimC,OAAO81C,UAC9B/7E,KAAK87E,SAAW97E,KAAKimC,OAAO61C,OAG9B,0BACL97E,KAAKimC,OAAO81C,SAAW/7E,KAAK+7E,SAC5B/7E,KAAKimC,OAAO61C,OAAS97E,KAAK87E,OAC1B97E,KAAKimC,OAAO2pB,YAAc5vD,KAAK4vD,YAC/B5vD,KAAKimC,OAAO+1C,UAAYh8E,KAAKg8E,UAGxB,iBAAiB8lF,GACtBA,EAAK/lF,SAAW/7E,KAAK+7E,SACrB+lF,EAAKlyG,YAAc5vD,KAAK4vD,YACxBkyG,EAAKhmF,OAAS97E,KAAK87E,OACnBgmF,EAAK9lF,UAAYh8E,KAAKg8E,WCjFnB,MAAM,WAAgBulF,GAG3B,YAAYxlF,EAAiBD,EAAelsB,EAAoBosB,EAAkBlpE,GAChFhT,MAAMi8E,EAAUD,EAAQlsB,EAAaosB,GAErCh8E,KAAK8S,KAAOA,EAGd,mBACE,OAAI9S,KAAK+hK,MACgB,EAAhB/hK,KAAK+7E,SAAe,EAEJ,EAAhB/7E,KAAK+7E,SAIhB,iBACE,OAAI/7E,KAAK+hK,MACc,EAAd/hK,KAAK87E,OAAa,EAEJ,EAAd97E,KAAK87E,OAAa,EAI7B,sBACE,OAAI97E,KAAK+hK,MACmB,EAAnB/hK,KAAK4vD,YAEc,EAAnB5vD,KAAK4vD,YAAkB,EAIlC,oBACE,OAAI5vD,KAAK+hK,MACiB,EAAjB/hK,KAAKg8E,UAAgB,EAEJ,EAAjBh8E,KAAKg8E,UAAgB,EAIhC,YACE,MAAqB,QAAdh8E,KAAK8S,KAGd,eACE,MAAqB,WAAd9S,KAAK8S,M,8BChCT,MAAM,GAeX,YAAqBrP,EACA8sE,EACA1Y,GAFA,KAAAp0D,eACA,KAAA8sE,eACA,KAAA1Y,OAZd,KAAAmqG,WAAoB,EACpB,KAAAC,QAAiB,EAKjB,KAAAC,eAA+B,KAC/B,KAAAC,gBAAkB,IAAIngC,GAAA,EAAgBhiI,KAAKkiK,gBAC3C,KAAAE,UAAW,EAMlB,iBAAwBj8J,GACtBnG,KAAKud,SAAWpX,EAChBnG,KAAK80D,cAEL90D,KAAKiiK,QAAUjiK,KAAKud,SAAS8kJ,SAC7BriK,KAAKgiK,WAAahiK,KAAKud,SAASgd,YAEhCv6B,KAAKsiK,YAAW,GAGlB,mBACE,OAAOtiK,KAAKud,SAGP,kBAAkBglJ,GACvBviK,KAAKkiK,eAAiBK,EAEtBviK,KAAKmiK,gBAAgB/5J,KAAKm6J,GAGrB,qBAEL,IAAIC,EAAan+J,EAAEm/D,MAAMxjE,KAAKiiK,QAAS,GAAI,GAE3CjiK,KAAKyiK,YAAY/8J,QAAQugC,IACvBu8H,EAAaA,EAAWj3J,OAAOT,GAAQA,IAASm7B,EAAO81C,YAGzDymF,EAAW98J,QAAQimH,IACb3rH,KAAKiiK,QAAU,GACjBjiK,KAAK0iK,UAAU/2C,KAInB,IAAIg3C,EAAgBt+J,EAAEm/D,MAAMxjE,KAAKgiK,WAAY,GAAI,GAEjDhiK,KAAKyiK,YAAY/8J,QAAQugC,IACvB08H,EAAgBA,EAAcp3J,OAAOT,GAAQA,IAASm7B,EAAO2pB,eAG/D+yG,EAAcj9J,QAAQimH,IAChB3rH,KAAKgiK,WAAa,GACpBhiK,KAAKisG,aAAa0f,KAKjB,WAAWj8D,GAAU,GAC1B1vD,KAAK4iK,UAAY5iK,KAAK6iK,iBACtB7iK,KAAK8iK,SAAW9iK,KAAK+iK,gBACrB/iK,KAAKgjK,YAAchjK,KAAKijK,mBACpBvzG,IACF1vD,KAAKyiK,YAAcziK,KAAKkjK,wBAIrB,oBACLljK,KAAKmjK,UACLnjK,KAAKsiK,YAAW,GAGX,UACLtiK,KAAKud,SAAS8kJ,SAAWriK,KAAKiiK,SAAWjiK,KAAKyiK,YAAYvzJ,IAAIqzJ,GAAQA,EAAKzmF,QAAQ3hD,KAAK,CAACjX,EAAGC,IAAMD,EAAIC,GAAGgG,OAAS,GAAK,EACvHnpB,KAAKud,SAASgd,YAAcv6B,KAAKgiK,WAEjChiK,KAAKojK,4BAELpjK,KAAKqjK,SAASrjK,KAAKud,SAAUvd,KAAKwC,QAG7B,oBAAoBkqB,GACzB,IAAI3qB,EAAc,KAAc2uD,eAAe1wD,KAAKud,SAAUvd,KAAKwC,QAE/D8gK,EAAgBvhK,EAAQ2tD,QAAQlkD,KAAM+3J,GAAUA,EAAEr7J,KAAOwkB,EAAUxqB,iBAAiBgG,IACxF4H,OAAOoG,OAAOotJ,EAAe52I,EAAUob,SAGvC/lC,EAAY,GAAI/B,KAAKud,SAASrV,GAE9BlI,KAAKqjK,SAASthK,GAGT,MAAMwgK,GACX,OAAOA,aAAgB,GAGzB,mBACE,OAAwB,IAAjBviK,KAAKiiK,SAAqC,IAApBjiK,KAAKgiK,YAAoD,IAAhChiK,KAAKwjK,gBAAgBv8J,OAG7E,iBACE,OAAOjH,KAAKoiK,UAAYpiK,KAAKyjK,aAGxB,iBACLzjK,KAAKoiK,UAAYpiK,KAAKoiK,SAOjB,4BACL,IAAI5yI,EAAc3oB,OAAO,4BAEpB2oB,EAAY,GAAWk0I,wBAC1Bp2J,WAAW,IAAOkiB,EAAY,GAAWk0I,0BAIrC,SAASnmJ,EAAiC/a,GAChDxC,KACGyD,aACAixD,MACAxsD,GAAGqV,GACHozC,MAAMpzC,EAAU/a,GAChBnC,UAAUsjK,IACT3jK,KAAK4jK,kBAAkBD,GACvB3jK,KAAKuwE,aAAarlB,WAAWlrD,KAAK63D,KAAKz2D,EAAE,kCAIvC,kBAAkByiK,GACxB7jK,KAAKud,SAASmyC,QAAUm0G,EAAQn0G,QAEhC,IAAIo0G,EAAW9jK,KAAKyiK,YAAYvzJ,IAAIgU,GAAKA,EAAE+iB,OAAO/9B,IAClDlI,KAAKyiK,YAAY/8J,QAAQ68J,IACvB,IAAIwB,EAMFA,EADExB,EAAKt8H,OAAO/9B,GACF27J,EAAQn0G,QAAQlkD,KAAKy6B,GAAUA,EAAO/9B,KAAOq6J,EAAKt8H,OAAO/9B,IAEzD27J,EAAQn0G,QAAQlkD,KAAKy6B,IAAW69H,EAASlrJ,SAASqtB,EAAO/9B,KAAO+9B,EAAOnxB,aAAeytJ,EAAKt8H,OAAOnxB,YAAcmxB,EAAO81C,WAAawmF,EAAKt8H,OAAO81C,UAAY91C,EAAO2pB,cAAgB2yG,EAAKt8H,OAAO2pB,aAG7M2yG,EAAKt8H,OAAS89H,IAIV,iBACN,IAAIh1H,EAAmB,GAGvB,IAAK,IAAIlb,EAAM,EAAGA,GAAO7zB,KAAKiiK,QAAU,EAAGpuI,IACzCkb,EAAM7tC,QAAQlB,KAAKgkK,kBAAkBnwI,IAGvC,OAAOkb,EAGD,gBACN,IAAIA,EAAmB,GAGvB,GAAI/uC,KAAKyjK,aACP,OAAO10H,EAGT,IAAK,IAAIlb,EAAM,EAAGA,GAAO7zB,KAAKiiK,QAAU,EAAGpuI,IACzCkb,EAAM7tC,QAAQlB,KAAKikK,gBAAgBpwI,IAGrC,OAAOkb,EAGD,kBAAkBlb,GACxB,IAAIkb,EAAmB,GAEvB,IAAK,IAAI3+B,EAAS,EAAGA,GAAUpQ,KAAKgiK,WAAY5xJ,IAAU,CACxD,IAAIglB,EAAO,IAAImsI,GAAS1tI,EACtBA,EAAM,EACNzjB,EACAA,EAAS,GAEX2+B,EAAM7tC,KAAKk0B,GAGb,OAAO2Z,EAGD,gBAAgBlb,GACtB,IAAIkb,EAAkB,GAEtB,IAAK,IAAI3+B,EAAS,EAAGA,GAAUpQ,KAAKgiK,WAAY5xJ,IAC9C2+B,EAAM7tC,KAAK,IAAI,GAAQ2yB,EACKA,EAAM,EACXzjB,EACKA,EAAS,EACT,QAG9B,GAAIyjB,GAAO7zB,KAAKiiK,QACd,IAAK,IAAI7xJ,EAAS,EAAGA,GAAUpQ,KAAKgiK,WAAa,EAAG5xJ,IAClD2+B,EAAM7tC,KAAK,IAAI,GAAQ2yB,EACrBA,EAAM,EACNzjB,EACAA,EAAS,EACT,WAIN,OAAO2+B,EAGD,uBACN,OAAO/uC,KAAKwjK,gBAAgBt0J,IAAK+2B,GACxB,IAAI,GAAeA,IAMvB,4BACLjmC,KAAKyiK,YAAY/8J,QAAS68J,IACxBA,EAAK2B,4BAIF,UAAU9zJ,EAAe+zJ,GAC9BnkK,KAAKgiK,aAEL,IAAIoC,EAAgC,GAEpC,IAAK,IAAIvwI,EAAM,EAAGA,GAAO7zB,KAAKiiK,QAASpuI,IAAO,CAC5C,GAAIA,IAAQswI,EACV,SAGF,IAAIl+H,EAASjmC,KACCqkK,WAAWxwI,GACXsG,KAAK,CAACjX,EAAGC,IAAMD,EAAE0sC,YAAczsC,EAAEysC,aACjCpkD,KAAKy6B,KAAYA,EAAO81C,SAAWooF,GAAcl+H,EAAO61C,OAASqoF,KAC/Dl+H,EAAO2pB,cAAgBx/C,EAAS,GAChC61B,EAAO+1C,YAAc5rE,EAAS,GAC9B61B,EAAO2pB,aAAex/C,GAAU61B,EAAO+1C,UAAY5rE,IAE/D61B,IACFm+H,EAAaljK,KAAK+kC,GAClBA,EAAO+1C,aAIXh8E,KAAKskK,yBAAyBtkK,KAAKyiK,YAAYl3J,OAAO06B,IAAWm+H,EAAaxrJ,SAASqtB,IACzD71B,GAGzB,OAAOyjB,EAAY0wI,GACxBvkK,KAAKiiK,UAEL,IAAImC,EAAgC,GAEpC,IAAK,IAAIh0J,EAAS,EAAGA,GAAUpQ,KAAKgiK,WAAY5xJ,IAAU,CACxD,GAAIA,IAAWm0J,EACb,SAGF,IAAIt+H,EAASjmC,KACCwkK,cAAcp0J,GACd+pB,KAAK,CAACjX,EAAGC,IAAMD,EAAE64D,SAAW54D,EAAE44D,UAC9BvwE,KAAKy6B,KAAYA,EAAO2pB,YAAc20G,GAAiBt+H,EAAO+1C,UAAYuoF,KACxEt+H,EAAO81C,WAAaloD,EAAM,GACzBoS,EAAO61C,SAAWjoD,EAAM,GACxBoS,EAAO81C,UAAYloD,GAAOoS,EAAO61C,OAASjoD,IAEvDoS,IACFm+H,EAAaljK,KAAK+kC,GAClBA,EAAO61C,UAIX97E,KAAKykK,4BAA4BzkK,KAAKyiK,YAAYl3J,OAAO06B,IAAWm+H,EAAaxrJ,SAASqtB,IACzDpS,GAG5B,aAAazjB,GAClBpQ,KAAKgiK,aAGLhiK,KAAKyiK,YAAY/8J,QAASugC,IACpBA,EAAO2pB,aAAex/C,GAAU61B,EAAO+1C,WAAa5rE,EAAS,GAE/D61B,EAAO+1C,cAMXh8E,KAAKyiK,YAAYl3J,OAAQ06B,GAChBA,EAAO2pB,YAAcx/C,GAC3B1K,QAASugC,IACVA,EAAO2pB,cACP3pB,EAAO+1C,cAIJ,UAAUnoD,GACf7zB,KAAKiiK,UAGLjiK,KAAKyiK,YAAY/8J,QAASugC,IACpBA,EAAO81C,UAAYloD,GAAOoS,EAAO61C,QAAUjoD,EAAM,GAEnDoS,EAAO61C,WAMX97E,KAAKyiK,YAAYl3J,OAAQ06B,GAChBA,EAAO81C,SAAWloD,GACxBnuB,QAASugC,IACVA,EAAO81C,WACP91C,EAAO61C,WAIJ,WAAW4oF,EAAkC,MAClD1kK,KAAKyiK,YAAYl3J,OAAQg3J,IACfmC,GAAenC,EAAKpyB,OAASu0B,EAAYv0B,MAChDzqI,QAAQ68J,GAAQA,EAAK5oJ,SAExB3Z,KAAKiiK,QAAUjiK,KAAKud,SAAS8kJ,SAC7BriK,KAAKgiK,WAAahiK,KAAKud,SAASgd,YAGlC,iBACE,YAA+C7uB,IAAxC1L,KAAK2kK,aAAa11I,kBAGnB,mBACN,OAAOjvB,KACJ4iK,UACAr3J,OAAOg3J,IAASviK,KAAK4kK,MAAMrC,IAC3BrzJ,IAAKqzJ,GAASA,EAAKpyB,MAGhB,cACNnwI,KACGyD,aACAixD,MACAxsD,GAAGlI,KAAKud,UACRnZ,KACAgpB,KAAK,IACL/sB,UAAU+D,GAAQpE,KAAKwC,OAAS4B,EAAK5B,QAGnC,aAAaqiK,GAClB,IAAI5zI,EAAQjxB,KAAKud,SAASmyC,QAAQ5wB,UAAWmH,GAAWA,EAAO/9B,KAAO28J,EAAc38J,IACpFlI,KAAKud,SAASmyC,QAAQzmC,OAAOgI,EAAO,GAEpCA,EAAQjxB,KAAKyiK,YAAY3jI,UAAWyjI,GAASA,EAAKt8H,OAAO/9B,KAAO28J,EAAc38J,IAC9ElI,KAAKyiK,YAAYx5I,OAAOgI,EAAO,GAC/BjxB,KAAK8kK,qBAEL9kK,KAAK+kK,oBAGP,sBACE,OAAQ/kK,KAAKud,UAAYvd,KAAKud,SAASmyC,SAAY,GAG7C,WAAW77B,GACjB,OAAO7zB,KAAKyiK,YAAYl3J,OAAO06B,GAAUA,EAAO81C,WAAaloD,GAGvD,yBAAyBwwI,EAA6Bj0J,GAC5Di0J,EAAW3+J,QAAQs/J,IACbA,EAAiBp1G,YAAcx/C,IACjC40J,EAAiBp1G,cACjBo1G,EAAiBhpF,eAKf,cAAc5rE,GACpB,OAAOpQ,KAAKyiK,YAAYl3J,OAAO06B,GAAUA,EAAO2pB,cAAgBx/C,GAG1D,4BAA4Bo0J,EAAgC3wI,GAClE2wI,EAAc9+J,QAAQs/J,IAChBA,EAAiBjpF,SAAWloD,IAC9BmxI,EAAiBjpF,WACjBipF,EAAiBlpF,a,uCApZZ,IAAe,gC,0BAAf,GAAe,QAAf,GAAe,Y,+GCqBrB,MAAM,GAKX,YAAqBmpF,GAAA,KAAAA,SAHZ,KAAA9uG,UAAmB,EAClB,KAAA+uG,UAAY,IAAI,IAMnB,QAAQz+J,GACbzG,KAAKklK,UAAU18J,KAAK/B,GAGtB,mBACE,OAAOzG,KAAKm2D,UAAYn2D,KAAKilK,OAAOxlH,Y,uCAd3B,IAAqB,W,wBAArB,GAAqB,0H,iCAAA,uJ,SCrClC,eAGE,QAEA,mCACwB,kCAAU,EAAA0lH,QAAA,MAGlC,OAEA,UACF,Q,MAXI,0CAIsB,6BAAc,6B,8LCCjC,MAAMC,GAEX,YAAqBH,GAAA,KAAAA,SAGd,KAAK1C,GACVviK,KAAKimC,OAAOs8H,EAAKt8H,QAGZ,OAAOA,GACZjmC,KAAKilK,OAAOI,aAAap/H,I,uCAVhBm/H,IAAuB,W,0BAAvBA,GAAuB,QAAvBA,GAAuB,YC8B7B,MAAe,GAKpB,YAAqBvtG,EACUplC,EACAwyI,GAFV,KAAAptG,OACU,KAAAplC,SACA,KAAAwyI,SAJrB,KAAAK,aAAmC,CAACtlK,KAAKulK,YAOnD,gBACE,MAAO,IAAY,4CACjB,OAAOvlK,KAAKslK,gBAIhB,iBACE,MAAO,CACLnkK,SAAUnB,KAAK63D,KAAKz2D,EAAE,kBACtBE,QAAS,KACPtB,KAAKyyB,OAAOwT,OAAOjmC,KAAKud,WACjB,IAKb,cACE,OAAOvd,KAAKilK,OAAOxlH,Y,uCA3BD,IAA2B,8B,wBAA3B,GAA2B,+B,0CCpCjD,wC,oBAEI,gCCkCG,MAAM,WAA4B,I,sCAA5B,K,wBAAA,GAAmB,2IDpChC,+C,KACI,wB,sFCmCS,I,wPChCT,4B,oBAEe,mC,yBAEf,gB,oBAEI,0CCiCD,MAAM,WAAuC,KA+ClD,YAAqB98C,EACA8U,EACAxU,EACA01C,EACA/1C,EACAc,EACA2R,EACA0+D,EACDnkD,EACCioC,EACAj4D,EACD08J,EACA/kI,GAClBz3B,QAbmB,KAAA6C,SACA,KAAA8U,SACA,KAAAxU,iBACA,KAAA01C,gBACA,KAAA/1C,aACA,KAAAc,wBACA,KAAA2R,cACA,KAAA0+D,eACD,KAAAnkD,UACC,KAAAioC,OACA,KAAAj4D,uBACD,KAAA08J,YACA,KAAA/kI,gBAzDZ,KAAAiuI,cAAgB,IAAIv8F,GAAA,EAoCnB,KAAAw8F,QAAiB,EAKlB,KAAAC,eAAgB,EAvCxB,cACc9nF,GAGPA,IAIL59E,KAAK2lK,WAAa/nF,EAKlB59E,KAAK2lK,WAAWC,SAAS72E,UAAU,gBAAkB/mF,IACnDhI,KAAK6lK,WAAW79J,KAElBhI,KAAK2lK,WAAWC,SAAS72E,UAAU,aAAe/mF,IAChDhI,KAAK8lK,aAAa99J,MAGtB,sBACsB41E,GACfA,IAIA59E,KAAK+lK,iBACR/lK,KAAK+lK,eAAiB,IAAIC,eAAe,IAAMhmK,KAAKwlK,cAAcp9J,SAGpEpI,KAAK+lK,eAAex0G,QAAQqsB,EAAE92E,gBA6BhC,WACE9G,KAAKwlK,cACFrlK,KAAK,OAAA6+F,GAAA,GAAa,KAClB3+F,UAAU,KACTL,KAAK2lK,WAAWC,SAASK,eAI7BjmK,KAAK4C,WAAWq6D,qBAAqB70D,OAErCpI,KAAKkmK,4BACLlmK,KAAKmmK,qBAGA,uBAAuBC,EACAC,EACAC,GAC5B,GAAItmK,KAAK0lK,cAAe,CACtB1lK,KAAK0lK,eAAgB,EACrB,IAAIvqG,EAASn7D,KAAKmtI,cAAcntI,KAAK4C,WAAWkB,QAAQqC,OACxDkgK,EAAgBlrG,QAEhBn7D,KAAK4C,WAAWkB,QAAQ5D,UAAUC,KAChC,OAAAi3C,GAAA,GAAK,IACL/2C,UAAWsjC,IACX,IAAIw3B,EAASn7D,KAAKmtI,cAAc,GAChCk5B,EAAgBlrG,KAKpBn7D,KAAKumK,gBAAgBH,GAGf,qBACNpmK,KAAKu3B,cAActxB,YAChBwJ,KAAK,KACJzP,KAAKwmK,gBAAkB,CACrBrwG,UAAU,EACV1N,OAAQzoD,KAAK63D,KAAKpP,OAClBg+G,gBAAgB,EAChB7P,SAAU52J,KAAKu3B,cAAcgjD,cAC7Bpf,OAAQn7D,KAAK0mK,uBAAuB55J,KAAK9M,MACzC2mK,QAAS,CAAC,MACVC,YAAa,KACP5mK,KAAKylK,OACA,mBAEP,EAJS,GAObvzI,OAAQlyB,KAAK6mK,iBACbC,cAAe9mK,KAAK+mK,iBAKrB,gBAAgBX,GACrB,IAAIY,EAAehnK,KAAKiD,eAAeqU,QAEvC,GAAI0vJ,GAAgBhnK,KAAK4C,WAAWiB,MAAMsC,MAExC,OAGF,IAAI6jB,EAAY,GAAOo8I,EAAUr8I,OAAO7O,OAAO,cAC3Cm8I,EAAU,GAAO+O,EAAU79I,KAAKrN,OAAO,cAE3C,GAAI8rJ,EAAc,CAChB,IAAIhvH,EAAah4C,KAAKinK,kBAAkBj9I,EAAWqtI,GAE/Cr3J,KAAKyX,OAAOyG,OAAO2lB,cACrBmU,EAAawK,mBAAmBxiD,KAAKyX,OAAOyG,OAAO2lB,aAAe,KAGpE7jC,KAAK24C,cAAcghB,gBAAgB,CAAE91B,YAAamU,GAAch4C,KAAK8O,mBAAmB+d,gBACnF,CACQ7sB,KAAKyX,OAAOyG,OAEzBle,KAAKiD,eAAe88E,OAAO,gBAAkBmnF,IAC3CA,EAAoBthJ,OAAO,GAAKoE,EAChCk9I,EAAoBthJ,OAAO,GAAKyxI,KAK/B,WAAWrvJ,GAChBnB,OAAOmB,EAAMiK,IAAIk1J,QAAQ,CACvBtmI,QAAS7gC,KAAKonK,qBAAqBp/J,EAAMA,MAAMq/J,cAAcr+J,aAC7DhI,MAAO,YACP+J,MAAO,WACLlE,OAAO,gCAAgC4rB,UAEzC60I,OAAO,IAIJ,aAAat/J,GAClB,IAAIgB,EAAchB,EAAMA,MAAMq/J,cAAcr+J,YAExChB,EAAMiK,IAERjS,KAAKunK,cAAcv/J,EAAMiK,IAI3BjS,KAAK0D,sBAAsB2B,QAG3Bmb,OAAOgnJ,QAAQC,UAAU,GAAIznK,KAAK+zE,aAAa9zE,QAASugB,OAAOgoB,SAASjjC,MAExEvF,KAAKyX,OAAOswB,GACV,qBACA,CAAE7jB,cAAelb,EAAYd,IAC7B,CAAEw/J,SAAS,IAEf,sBACE,OAAO7gK,OAAO7G,KAAK4vB,QAAQ9oB,eAAe0E,KAAK,2BAGzC,iBACN,GAAIxL,KAAKylK,OAAQ,CACf,IAAIkC,EAAgB9gK,OAAO7G,KAAK4vB,QAAQ9oB,eAExC,MAAQ6gK,EAAcz1I,UAAYy1I,EAAcj5J,UAC9Ci5J,EAAgBA,EAAcj5J,SAGhC,IAAIk5J,EAAgB/gK,OAAO7G,KAAK4vB,QAAQ9oB,eAAe+E,WAAWC,IAC9D+7J,EAAqBF,EAAc97J,WAAWC,IAElD,OAAO67J,EAAcz1I,UAAa01I,EAAgBC,GAGlD,OAAOhhK,OAAO2Z,QAAQ0R,SAAYlyB,KAAK8nK,gBAAgBpvH,SAAU5sC,IAAM,GAIpE,cACL,OAAI9L,KAAKylK,QAGA,CACL1uF,MAAO,2BACPksB,OAAQ,QACRnsB,KAAM,mBAKJ,mBACN,MAAMjzE,EAAQ7D,KAAK4C,WAAWiB,MAAMsC,MACpC,IAAKtC,EACH,OAGF,IAAIqjK,EAAsB7iK,EAAEmH,KAAK3H,EAAMmL,SAAW,GAAI,CAAE,GAAM,kBAE1D+4J,EAAmB,KACnBC,EAAe,eAEnB,GAAId,EAAqB,CACvB,IAAIe,EAAQ,GAAOf,EAAoBthJ,OAAO,IAE1C4B,EADQ,GAAO0/I,EAAoBthJ,OAAO,IAC7B4B,KAAKygJ,EAAO,QAE7BF,EAAeE,EAAMz3J,IAAIgX,EAAO,EAAG,QAEtB,IAATA,IACFwgJ,EAAe,eAIfD,EACF/nK,KAAK2lK,WAAWC,SAASsC,WAAWF,EAAcD,EAAa1zC,UAE/Dr0H,KAAK2lK,WAAWC,SAASsC,WAAWF,GAIhC,4BACNhoK,KAAK4C,WAAWkB,QAAQ5D,UAAUC,KAChCH,KAAKI,kBACLC,UAAWsjC,IACX3jC,KAAK0lK,eAAgB,EACrB1lK,KAAKmoK,mBAELnoK,KAAK2lK,WAAWC,SAASwC,kBAIrB,cAAczkI,GAGpB,OAFA3jC,KAAKqoK,qBAAqB1kI,GAEnB3jC,KAAKsoK,oBAAoB3kI,EAAWn/B,UAGrC,oBAAoBqR,GAiB1B,OAhBaA,EAAa3G,IAAKlG,IAC7B,IAAIghB,EAAYhqB,KAAKuoK,UAAUv/J,EAAa,SACxCquJ,EAAUr3J,KAAKuoK,UAAUv/J,EAAa,OAEtCw/J,EAAe,GAAOnR,GAAS7mJ,IAAI,EAAG,QAAQ0K,OAAO,cAEzD,MAAO,CACLoH,MAAOtZ,EAAYogE,QACnBr/C,MAAOC,EACPzB,IAAKigJ,EACLC,QAAQ,EACR1mJ,UAAW,wBAAwB/Y,EAAY8J,KAAK5K,GACpDc,YAAaA,KAOX,qBAAqB26B,GACvBA,EAAW1P,MAAQ0P,EAAWsW,MAChCj6C,KAAK0oK,mBAAqB1oK,KAAK63D,KAAKz2D,EAAE,uBACpC,CACE6yB,MAAO0P,EAAWsW,MAClBi2B,IAAK,GAA+By4F,gBAGxC3oK,KAAK0oK,mBAAqB,KAGxB1oK,KAAK0oK,qBAAuB1oK,KAAKylK,QACnCzlK,KAAKJ,qBAAqB6d,UAAUzd,KAAK0oK,oBAIrC,kBAAkB1+I,EAAkBqtI,GAC1C,IAAIuR,EAAQ,CACV,EAAK,CAAC,MACN,EACE,SACF,EAAK,CAAC,CAAE,EAAK,SAAU,EAAK,IAAK,EAAK,IACpC,CAAE,EAAK,gBAAiB,EAAK,MAAO,EAAK,CAAC5+I,EAAWqtI,KACvD,GAAM,GAA+BsR,eAGvC,OAAOljJ,KAAKC,UAAUkjJ,GAGhB,UAAU5/J,EAAiC8J,GACjD,OAAI9S,KAAKqV,YAAY/B,GAAGtK,GAAaqK,YAC5BrK,EAAYihB,KAEZjhB,EAAe8J,EAAH,QAIf,qBAAqB9J,GAC3B,MAAO,aACDhJ,KAAK6oK,eAAe7/J,EAAa,YAAYA,EAAYd,OAAOlI,KAAK6oK,eAAe7/J,EAAa,UAAW,oIAGxEhJ,KAAK63D,KAAKz2D,EAAE,qGACVpB,KAAK6oK,eAAe7/J,EAAa,8HAGnChJ,KAAK63D,KAAKz2D,EAAE,gGACVpB,KAAK6oK,eAAe7/J,EAAa,6HAGnChJ,KAAK63D,KAAKz2D,EAAE,mGACVpB,KAAKuoK,UAAUv/J,EAAa,4HAG9BhJ,KAAK63D,KAAKz2D,EAAE,iGACVpB,KAAKuoK,UAAUv/J,EAAa,0HAG9BhJ,KAAK63D,KAAKz2D,EAAE,kGACVpB,KAAK6oK,eAAe7/J,EAAa,+HAGnChJ,KAAK63D,KAAKz2D,EAAE,kGACVpB,KAAK6oK,eAAe7/J,EAAa,+DAMvE,eAAeA,EAAiCia,EAAkB6lJ,EAA6B,QACrG,IAAI3iK,EAAQ6C,EAAYia,GAIxB,OAHA9c,EAAQ2iK,GAAkB3iK,EAAQA,EAAM2iK,GAAkB3iK,EAC1DA,EAAQA,GAASnG,KAAK63D,KAAKz2D,EAAE,2BAEtBpB,KAAKs8J,UAAUE,SAAS,IAAgBC,KAAMt2J,GAG/C,cAAcypB,GAEpB/oB,OAAO+oB,GAASu3I,QAAQ,CACtBp8J,MAAO,WACLlE,OAAO,gCAAgC4rB,UAEzC9Z,UAAU,KApUP,GAAAgwJ,cAAgB,I,uCAvCZ,IAA8B,sJ,wBAA9B,GAA8B,oD,OAAA,M,KAI9B,MAAqB,G,WAoBC,M,0dDlEnC,gBAGI,iCAIA,uBAIJ,Q,MAVK,oCAGc,uCAIX,gC,kLE2BD,MAAM,WAAkC,KAC7C,YAA+B9wG,EACA9uD,EACA2O,GAC7B5X,MAAM+3D,EAAM9uD,GAHiB,KAAA8uD,OACA,KAAA9uD,WACA,KAAA2O,iBAI/B,wBACE,OAAO1X,KAAK0X,eAAe5C,Y,uCARlB,IAAyB,iC,wBAAzB,GAAyB,sNCpCtC,0BAEI,qCAAa,EAAAi0J,aAAA,MAEf,wBAIF,OAEA,UACE,wBAGF,Q,MAbI,0BAKE,oCAMA,0BAAe,2C,gICGjB,iBACE,mBACA,kBACE,kBACE,mBAAiF,qFAAjF,OACF,OACF,OACF,O,+CAN6B,8BAAmB,oBAGnB,4BAAqB,sBCe/C,MAAM,WAA0D,IA2BrE,YAA+Cj3J,EAC1BpR,EACAqI,EACAyhB,EACAuX,EACA8K,EACAhtC,EACA03B,EACA/2B,GACnBV,MAAMgS,EAAQjS,EAAOW,GATwB,KAAAsR,SAC1B,KAAApR,OACA,KAAAqI,WACA,KAAAyhB,SACA,KAAAuX,mBACA,KAAA8K,sBACA,KAAAhtC,QACA,KAAA03B,gBACA,KAAA/2B,aAhCd,KAAAymD,eAAgB,EAGhB,KAAAE,qBAAsB,EAItB,KAAAvvC,KAAO,CACZoxJ,cAAehpK,KAAKU,KAAKU,EAAE,4DAC3B68D,WAAYj+D,KAAKU,KAAKU,EAAE,wBAExBgjJ,YAAapkJ,KAAKU,KAAKU,EAAE,0BACzBsuC,aAAc1vC,KAAKU,KAAKU,EAAE,2BAE1B25E,SAAUt7D,OAAOs7D,YAIZ,KAAAkuF,eAAiBjpK,KAAKu3B,cAAcgjD,cAkB3C,WACEv6E,KAAK6nB,KAAO7nB,KAAK8R,OAAOge,QAAQjI,MAAQ3K,MAAM3B,KAAK,CAAEtU,OAAQ,GAAK,KAAM,GAExE,IAAIiiK,EAAuB,EAAIzpJ,OAAO0pJ,aAAazgH,iBAAmB,EACtE1oD,KAAK4X,KAAKmjE,SAAWt7D,OAAO0pJ,aAAapuF,WAAWr2D,MAAMwkJ,GAAsB7/I,OAAO5J,OAAO0pJ,aAAapuF,WAAWr2D,MAAM,EAAGwkJ,IAG1H,cACLlpK,KAAK8vB,QAAU,CAAEjI,KAAM7nB,KAAK6nB,MAC5B7nB,KAAK8rB,QAAQ/gB,S,yBPlFjB,wC,oBAEI,gC,uCOgCS,IAAiD,KA2BxC,KAAkB,oF,wBA3B3B,GAAiD,stBDlC9D,gBACE,gBAGE,gBACE,cACE,cAEE,iCAAS,EAAAu8C,QAAA,MAEX,OACF,OACA,eACF,OAEA,uBASA,gBACA,gBACE,mBAEQ,gCAAS,EAAAm9F,iBACjB,OACA,qBAEQ,iCAAS,EAAAn9F,QAAA,MACjB,OACF,OACF,OACF,Q,MA3BU,wCAGA,iDAGmC,wCAY/B,+CAIA,kD,gDEYP,MAAM,WAAkD,GAS7D,YAA6Bv+C,EACA8wC,EACRge,EACUplC,EACVwyI,GACnBnlK,MAAM+3D,EACJplC,EACAwyI,GAPyB,KAAAl8J,WACA,KAAA8wC,iBACR,KAAAge,OACU,KAAAplC,SACV,KAAAwyI,SAXrB,KAAAmE,aAAiC,IAAI,IAE3B,KAAA9D,aAAe,CACvBtlK,KAAKulK,WACLvlK,KAAKqpK,eAaP,oBACE,MAAO,CACLloK,SAAUnB,KAAK63D,KAAKz2D,EAAE,qBACtBE,QAAS,KACPtB,KAAK65C,eAAe94C,KAAK,GAAmDf,KAAK+I,SAAU/I,KAAK8R,QAC7F0pD,aAAan7D,UAAWo7D,IACnBA,EAAM3rC,SACR9vB,KAAKopK,aAAa5gK,KAAKizD,EAAM3rC,YAG5B,IAKb,aACE,MAAO,CAAEA,QAAS9vB,KAAKud,SAASuS,U,uCAnCvB,IAAyC,kD,wBAAzC,GAAyC,2MR3CtD,+C,KACI,wB,mKjDuBE,oBAEQ,8DAGN,qBACA,kBAGF,O,uBALQ,gCADA,yBAIA,wC,wCAIR,oBAEQ,8DAEN,qBACA,kBAGF,O,uBALQ,4BAGA,2C,wCAIR,oBAEQ,4DAEN,qBACA,kBAGF,O,uBALQ,4BAGA,2C0DrCP,MAAM,WAA2B,KAI/B,iBAAiByb,GACtBvrC,KAAK48G,cAAgBrxE,EAAOuL,cAC5B92C,KAAKszJ,4BAGP,kBACE,QAAStzJ,KAAK+hE,MAAMvtD,OAGtB,oBACE,QAASxU,KAAK+hE,MAAMrsB,OAGf,UACAl1B,OAAOgrB,QAAQxrC,KAAK4X,KAAK88I,cAI9B10J,KAAKspK,eAAiBtpK,KAAK+hE,MAC3B/hE,KAAK8rB,QAAQ/gB,U,sCAvBJ,K,wBAAA,GAAkB,4CAJlB,CACT,OACD,s3B1DZH,gBACE,gBAGE,gBACE,cACE,cAEE,iCAAS,EAAAu8C,QAAA,MAEX,OACF,OACA,eACF,OAEA,gBACE,sBAGS,yCAAiB,EAAAisG,iBAAA,MAC1B,OACF,OAEA,gBACE,4BAWA,4BAUA,4BASF,OACF,OACF,Q,MA/CU,mCAGmC,yCAK9B,sCAAuB,+CAQxB,mCAWA,mCAUA,uC,8M0DhCD,ICFN,MAAM,GAEX,YAAqB15G,EACA9wC,EACAtF,EACAw4E,EACCrmE,EACDiiD,GALA,KAAAhe,iBACA,KAAA9wC,WACA,KAAAtF,eACA,KAAAw4E,cACC,KAAArmE,aACD,KAAAiiD,OAGd,KAAKkK,GACV,OAAO,IAAIxyD,QAA8D,CAACC,EAASquB,KACjF79B,KACGupK,gBAAgBxnG,GAChBtyD,KAAKid,IACJ,MAAM+uC,EAAQz7D,KAAK65C,eAAe94C,KAAK,GAAoBf,KAAK+I,SAAU,CAAE2jB,UAAWA,IAEvF+uC,EACGD,aACAr7D,KAAK,OAAAi3C,GAAA,GAAK,IACV/2C,UAAU,KACLo7D,EAAM6tG,eACR7tG,EAAM6tG,eAAe5zH,SAASjmC,KAAK,KACjCD,EAAQ,CAACuyD,MAAOtG,EAAM6tG,eAAgBvoG,OAAQ,cAEvCtF,EAAMmhD,cACfptG,EAAQ,CAAEuyD,MAAOtG,EAAMmhD,cAAe77C,OAAQ,WAE9CljC,UAOP,gBAAgBkkC,GACrB,OAAO/hE,KACJyD,aACAiyD,aACAxtD,GAAG65D,GACH39D,KACAgpB,KAAK20C,GACLl1C,YACApd,KAAKrL,GACCpE,KAAK4V,WAAWoX,KAA8D+0C,EAAO39D,K,uCA5CrF,IAAoB,+D,0BAApB,GAAoB,QAApB,GAAoB,Y,mFCP/B,mBAGQ,kEACN,oBACA,iBAGF,O,uBANQ,kCAIA,4CC0CV,MAAMolK,GAAwB,0BAExBC,GAAuB,yBAEvBC,GAAkC,cAcjC,MAAM,GAmDX,YAAqB/mK,EACAc,EACAgU,EACDmY,EACCioC,EACA9uD,EACAi1D,EACDs+F,EACA/kI,EACA8wB,EACAshH,EACAC,EACAv0J,EACA2L,EACAklC,GAdC,KAAAvjD,SACA,KAAAc,eACA,KAAAgU,SACD,KAAAmY,UACC,KAAAioC,OACA,KAAA9uD,WACA,KAAAi1D,gBACD,KAAAs+F,YACA,KAAA/kI,gBACA,KAAA8wB,WACA,KAAAshH,gBACA,KAAAC,kBACA,KAAAv0J,cACA,KAAA2L,SACA,KAAAklC,kBA9DX,KAAAu/G,QAAiB,EAMhB,KAAAxoD,QAAU,IAAI,IAGjB,KAAA4sD,QAAU,EACV,KAAAC,QAAU,GACV,KAAAC,mBAAqB,EACrB,KAAAC,WAAa,EAIb,KAAAC,uBAAgC,EAChC,KAAAC,WAAsB,GAEtB,KAAAtyJ,KAAO,CACZkgI,QAAS93I,KAAK63D,KAAKz2D,EAAE,uBAGvB,KAAAolK,gBAAkC,CAChCrwG,UAAU,EACV1N,OAAQzoD,KAAK63D,KAAKpP,OAClBg+G,gBAAgB,EAChBK,cAAe,CACb/vF,MAAO,GACPksB,OAAQ,QACRnsB,KAAM,mBAER8vF,YAAa,eACbhQ,SAAU52J,KAAKu3B,cAAcgjD,cAC7B2vF,WAAY,GACZC,cAAe,IACfC,kBAAkB,EAClBC,kBAAsBrqK,KAAK+pK,mBAAR,SACnBO,gBAAkB3lJ,KAAe3kB,KAAK8pK,QAAUnlJ,EAAKsF,KAAKpD,MAAQ7mB,KAAKgqK,YAAY3nJ,WACnFkoJ,YAAY,EACZC,kBAAkB,EAClBC,YAAgBzqK,KAAK6pK,QAAU,EAAlB,SACba,YAAgB1qK,KAAK8pK,QAAR,SACb3uG,OAAQn7D,KAAK0mK,uBAAuB55J,KAAK9M,MACzC2qK,aAAeC,IAAoBA,EAAWrzE,WAAW3+E,SAAS4wJ,IAClE7C,QAAS,CAAC,KAAU,OA3CtB,kBAA2B9+I,GACzB7nB,KAAK6qK,cAAchjJ,GA8DrB,kBAIE7nB,KAAK2lK,WAAWC,SAAS72E,UAAU,gBAAkB/mF,IACnDhI,KAAK8qK,gBAAgB9iK,KAEvBhI,KAAK2lK,WAAWC,SAAS72E,UAAU,mBAAqB/mF,IACtDhI,KAAK+qK,kBAAkB/iK,KAEzBhI,KAAK2lK,WAAWC,SAAS72E,UAAU,aAAe/mF,IAChDhI,KAAKgrK,mBAAmBhjK,KAE1BhI,KAAK2lK,WAAWC,SAAS72E,UAAU,YAAc/mF,IAC/ChI,KAAKirK,UAAUjjK,KAIZ,uBAAuBo+J,EACAC,EACAC,GAE5BtmK,KAAKkrK,iBAAiB9E,EAAUr8I,MAAOq8I,EAAU79I,KAC9C9Y,KAAMk0B,IACL3jC,KAAKi9G,QAAQz0G,KAAKm7B,GAElB0iI,EAAgBrmK,KAAKmrK,aAAaxnI,EAAWn/B,SAAU4hK,MAInD,iBAAiBr8I,EAAYxB,GACrC,IAAKvoB,KAAKorK,qBACRprK,KAAKorK,oBAAoBrhJ,MAAMsnG,YAActnG,EAAMsnG,WACnDrxH,KAAKorK,oBAAoB7iJ,IAAI8oG,YAAc9oG,EAAI8oG,UAAW,CAC1D,IAAIpsF,EAAUjlC,KACXyD,aACAiyD,aACAtC,KAAK,CAAEpkD,QAAShP,KAAKqrK,UAAUthJ,EAAOxB,GAAMgyB,SAAU,MACtD1tB,YACApd,KAAKk0B,IACJ3jC,KAAKiqK,wBAA0BtmI,EAAW2nI,gBAEnC3nI,IAGX3jC,KAAKorK,oBAAsB,CAAErhJ,MAAOA,EAAOxB,IAAKA,EAAK00F,QAASh4E,GAGhE,OAAOjlC,KAAKorK,oBAAoBnuD,QAG1B,aAAaA,EAA6BmpD,GAGhD,OAFApmK,KAAKurK,SAAStuD,GAEPj9G,KAAKwrK,sBAAsBvuD,GAC/B5zF,OAAOrpB,KAAKyrK,gBAAgBxuD,EAASmpD,IAGlC,SAASnpD,GACf,IAAIyuD,EAAW1rK,KAAK2rK,kBAAkB1uD,GAElC2uD,EAAWnkJ,KAAKyoD,OAAOpgE,OAAO8V,OAAO8lJ,GAAW,GAEhDG,EAAW7rK,KAAKgqK,WAEhB4B,EAAW5rK,KAAK8pK,QAAU9pK,KAAK6pK,QACjC7pK,KAAKgqK,WAAahqK,KAAK8rK,sBAAsB9rK,KAAK8pK,QAAU9pK,KAAK6pK,SAAW+B,GAE5E5rK,KAAKgqK,WAAa,EAGhB6B,IAAa7rK,KAAKgqK,YAKpBhqK,KAAK2lK,WAAWC,SAAS72E,UAAU,kBAAoBpqE,KAC1C3kB,KAAK8pK,QAAUnlJ,EAAKsF,KAAKpD,MAAQ7mB,KAAKgqK,YACtC3nJ,YAKT,sBAAsB46F,GAC5B,IAAI8uD,EAA4C,GAEhD,OAAO9uD,EAAQ/tG,IAAK6yD,IAClB,IAAIh4C,EACAxB,EACA2K,EAAQlzB,KAAKqoD,SAAS67E,QAAQniE,EAAM7uC,OAASlzB,KAAKgqK,WAElD+B,EAAkBhqG,EAAM86C,UAC1B9yF,EAAQgiJ,EAAkBhqG,EAAM86C,SAAS31F,QAAQyiF,SAASz2E,EAAO,KACjE3K,EAAMwjJ,EAAkBhqG,EAAM86C,SAAS31F,UAEvC6C,EAAQ,GAAOg4C,EAAM86C,SAASrsG,IAAIxQ,KAAK8pK,QAAU52I,EAAO,KACxD3K,EAAM,GAAOw5C,EAAM86C,SAASrsG,IAAIxQ,KAAK8pK,QAAS,MAGhDiC,EAAkBhqG,EAAM86C,SAAW9yF,EAErB/pB,KAAKghB,OAAOa,MAAM7hB,KAAKgsK,UAAUjqG,IAE/C,OAAO/hE,KAAKk2I,UAAUn0E,EAAO7uC,EAAOnJ,EAAOxB,KAIvC,gBAAgB00F,EAA6BmpD,GACnD,IAAIsF,EAAW1rK,KAAK2rK,kBAAkB1uD,GAElCgvD,EAA+B,GAEnC,IAAK,IAAIC,EAAI,GAAO9F,EAAUr8I,OAAQmiJ,EAAE1kJ,KAAK4+I,EAAU79I,IAAK,SAAW,EAAG2jJ,EAAE17J,IAAI,EAAG,QAAS,CAC1F,IAAIg1F,EAAWkmE,EAASQ,EAAEhxJ,OAAO,gBAAkB,EAEnD+wJ,EAAgB/qK,KAAKlB,KAAKmsK,SAASD,EAAG1mE,IAElCxlG,KAAKiqK,uBACPgC,EAAgB/qK,KAAKlB,KAAKosK,SAASF,EAAG1mE,IAI1C,OAAOymE,EAGD,kBAAkBhvD,GACxB,IAAIyuD,EAAmC,GAYvC,OAVAzuD,EAAQv3G,QAASq8D,IACf,IAAI7uC,EAAQlzB,KAAKqoD,SAAS67E,QAAQniE,EAAM7uC,OAEpCw4I,EAAS3pG,EAAM86C,SACjB6uD,EAAS3pG,EAAM86C,UAAY3pF,EAE3Bw4I,EAAS3pG,EAAM86C,SAAW3pF,IAIvBw4I,EAGC,UAAU3pG,EAAyB7uC,EAAcnJ,EAAcxB,GACvE,MAAMilF,EAAQxtG,KAAKghB,OAAOa,MAAM7hB,KAAKgsK,UAAUjqG,IAE/C,IAAIw1B,EAAa,CAACiyE,IAEdnoJ,EAAOkH,EAAIf,KAAKuC,EAAO,KAM3B,OAJI1I,EAAO,IACTk2E,EAAWr2F,KAAK,eAGX,CACLohB,MAAOjB,EAAO,GAAK,GAAKrhB,KAAKgsK,UAAUjqG,GACvCsqG,gBAAiBtqG,EAAMvtD,OACvBuV,MAAOA,EAAM7O,SACbqN,IAAKA,EAAIrN,SACToxJ,gBAAiB9+D,EACjB++D,YAAa/+D,EACbjW,WAAYA,EACZx1B,MAAOA,GAID,SAAS93C,EAAau7E,GAC9B,MAAO,CACLz7E,MAAOE,EAAK/C,QAAQ1W,IAAIxQ,KAAK8pK,QAAUriJ,KAAK0pE,IAAIqU,EAAWxlG,KAAKgqK,WAAYhqK,KAAK8pK,QAAU,IAAO,GAAK,KAAK5uJ,SAC5GqN,IAAK0B,EAAK/C,QAAQ1W,IAAIxQ,KAAK8pK,QAAUriJ,KAAK0pE,KAAMqU,EAAW,KAAQxlG,KAAKgqK,WAAahqK,KAAK8pK,QAAU,IAAM,KAAK5uJ,SAC/Gq8E,WA7PqB,uBA8PrBi1E,UAAW,aACXH,eAAe,EACf5tE,IAAKz+F,KAAK63D,KAAKz2D,EAAE,gBAAiB,CAAE6yB,MAAOj0B,KAAKysK,aAAajnE,MAIvD,SAASv7E,EAAau7E,GAC9B,IAAIjO,EAAa,CAACkyE,IAMlB,OAJIjkE,GAAY,IACdjO,EAAWr2F,KAAKwoK,IAGX,CACL3/I,MAAOE,EAAK/C,QAAQhM,SACpBqN,IAAK0B,EAAK/C,QAAQ1W,IAAIxQ,KAAK8pK,QAAUriJ,KAAK0pE,IAAIqU,EAAWxlG,KAAKgqK,WAAYhqK,KAAK8pK,QAAU,GAAK,GAAK,KAAK5uJ,SACxGsxJ,UAAW,aACXj1E,WAAYA,GAIN,UAAUxtE,EAAYxB,GAG9B,MAAO,CAAC,CAAC,UAAW,MAAO,CAFX,GAAOwB,GAAO7O,OAAO,cACvB,GAAOqN,GAAKohF,SAAS,EAAG,KAAKzuF,OAAO,gBAEhD,CAAC,UAAW,IAAK,CAAC,QAGd,mBAAmBlT,GACrBA,EAAMA,MAAMq/J,cAActlG,MAC5B/hE,KAAK0sK,UAAU1kK,EAAMA,MAAMq/J,cAActlG,OAChC/5D,EAAMiK,GAAG1B,UAAUlF,SAASo+J,MAA0BzhK,EAAMiK,GAAG1B,UAAUlF,SAASq+J,KAC3F1pK,KAAK2sK,SAAS,GAAO3kK,EAAMA,MAAM+hB,QAI7B,UAAUg4C,GAChB/hE,KACG2pK,cACA38I,KAAK+0C,GACLtyD,KAAKm9J,IACJ5sK,KAAK6sK,eAAeD,EAAmB7qG,MAAO6qG,EAAmB7rG,UAElEvmD,MAAM,QAKH,UAAUxS,GAChB,IAAI+5D,EAAQ/5D,EAAMA,MAAMq/J,cAActlG,MAItCA,EAAM86C,QAAU,GAAO70G,EAAMA,MAAMugB,KAAMrN,OAAO,cAEhDlb,KACGqV,YACA28C,aAAa+P,GACbtyD,KAAKjN,IACJxC,KACGyD,aACAiyD,aACAxtD,GAAG65D,GACHpR,MAAMoR,EAAOv/D,GACbnC,UACC2H,GAAShI,KAAK6sK,eAAe7kK,EAAO,UACpCsE,IACEtM,KAAKg+D,cAAcnwB,eAAevhC,GAClCtE,EAAM8kK,aAMX,gBACL9sK,KAAK2sK,SAAS,GAAO,IAAI39I,OAGnB,SAAS/E,GACVjqB,KAAKiqK,uBAIVjqK,KACG4pK,gBACArnK,OAAO0nB,GACPxa,KAAKm9J,IACJ5sK,KAAK6sK,eAAeD,EAAmB7qG,MAAO6qG,EAAmB7rG,UAElEvmD,MAAM,QAKH,eAAexS,EAAyB+4D,GAC9C/gE,KAAKorK,oBAAoBnuD,QAAQxtG,KAAKk0B,IACpC,IAAIopI,EAAappI,EAAWn/B,SAASs6B,UAAU2K,GAAKA,EAAEvhC,KAAOF,EAAME,IAEnE,OAAQ64D,GACN,IAAK,SACHp9B,EAAWn/B,SAASuoK,GAAc/kK,EAClC,MACF,IAAK,UACH27B,EAAWn/B,SAASykB,OAAO8jJ,EAAY,GACvC,MACF,IAAK,SACH/sK,KACGyD,aACAiyD,aACA7vD,MACA6rD,UAAU1pD,GAEb27B,EAAWn/B,SAAStD,KAAK8G,GAI7BhI,KAAK2lK,WAAWC,SAASwC,kBAIrB,gBAAgBpgK,GACtBhI,KAAKgtK,cAAchlK,GACnBhI,KAAKitK,UAAUjlK,GAEVA,EAAMA,MAAMq/J,cAActlG,QAI/B/hE,KAAK6lK,WAAW79J,GAChBhI,KAAKktK,gBAAgBllK,GACrBhI,KAAKmtK,cAAcnlK,IAGb,cAAcA,GACpB,IAAKA,EAAMiK,GAAG1B,UAAUlF,SAASo+J,IAC/B,OAGF,IAAI2D,EAAUliK,SAASoF,cAAc,OACrC88J,EAAQ78J,UAAUC,IAvYM,yBAwYxB48J,EAAQniC,UAAY,IACpBjjI,EAAMiK,GAAGkjB,OAAOi4I,GAGV,UAAUplK,GACZA,EAAMA,MAAMq/J,cAAc5oE,MAC5Bz2F,EAAMiK,GAAG8hB,UAAY/rB,EAAMA,MAAMq/J,cAAc5oE,KAI3C,WAAWz2F,GACbhI,KAAKkmD,gBAAgBC,UAIzBt/C,OAAOmB,EAAMiK,IAAIk1J,QAAQ,CACvBtmI,QAAS7gC,KAAKonK,qBAAqBp/J,EAAMA,MAAMq/J,cAActlG,OAC7D/gE,MAAO,YACP+J,MAAO,WACLlE,OAAO,gCAAgC4rB,UAEzC60I,OAAO,IAIH,cAAct/J,GACpBnB,OAAOmB,EAAMiK,IAAIk1J,QAAQ,WAGnB,gBAAgBn/J,GACtB,IAAIkuI,EAAYluI,EAAMA,MAAMq/J,cAActlG,MAE1C,GAAI/hE,KAAKqoD,SAAS67E,QAAQgS,EAAUhjH,OAAS,GAC3C,OAGF,IAAI+jH,EAAoBj3I,KAAKqoD,SAAS4uF,kBAAkBf,EAAUhjH,OAElErsB,OAAOmB,EAAMiK,IACVzG,KAAK,mBACL2jC,QAAQ,4BAA4B8nG,WAYjC,cAAcjvI,GACpB,IAAIkuI,EAAYluI,EAAMA,MAAMq/J,cAActlG,MAE1C,GAAI/hE,KAAKqoD,SAAS67E,QAAQgS,EAAUhjH,OAAS,GAC3C,OAGF,IAAItsB,EAAWC,OAAOmB,EAAMiK,IACxBo7J,EAAUxmK,OAAO,kCAEjBymK,EAAYttK,KAAKghB,OAAOusJ,OAAOvtK,KAAKgsK,UAAU91B,GAAY,GAC1Ds3B,EAAUxtK,KAAKghB,OAAOusJ,OAAOvtK,KAAKgsK,UAAU91B,GAAY,KAE5Dm3B,EAAQthK,IAAI,aAAc,2BAA2BuhK,SAAiBE,UAEtE,CAAC,uBAAwB,qBAAsB,kBAAmB,uBAAuB9nK,QAASsc,IAChGqrJ,EAAQthK,IAAI,mBAAoB,GAAGiW,KAASsrJ,SAAiBE,YAG/D5mK,EACGuuB,OAAOk4I,GAGJ,kBAAkBrlK,GACnBA,EAAMA,MAAMq/J,cAActlG,OAI/B/hE,KAAKunK,cAAcv/J,GAGb,UAAU+5D,GAChB,IAAIt7D,EAAOs7D,EAAMrmD,QAAQjV,KAKzB,OAJIs7D,EAAM/4D,cACRvC,GAAQ,MAAMzG,KAAKytK,gBAAgB1rG,IAG9Bt7D,GAAQ,IAGT,gBAAgBs7D,GACtB,MAAO,IAAIA,EAAM/4D,YAAYsS,eAAeymD,EAAM/4D,YAAYvC,OAGxD,qBAAqBs7D,GAC3B,MAAO,+HAGmC/hE,KAAK63D,KAAKz2D,EAAE,mFACVpB,KAAK6oK,eAAe9mG,EAAMrmD,QAAQjV,yHAGpCzG,KAAK63D,KAAKz2D,EAAE,wFACV2gE,EAAM/4D,YAAchJ,KAAK6oK,eAAe7oK,KAAKytK,gBAAgB1rG,IAAU/hE,KAAK63D,KAAKz2D,EAAE,8IAGrFpB,KAAK63D,KAAKz2D,EAAE,oFACVpB,KAAK6oK,eAAe9mG,EAAM/wC,SAASvqB,yHAGrCzG,KAAK63D,KAAKz2D,EAAE,iFACVpB,KAAKqoD,SAAS4uF,kBAAkBl1E,EAAM7uC,0HAGxClzB,KAAK63D,KAAKz2D,EAAE,mFACV2gE,EAAMslB,QAAQhuE,KAAOrZ,KAAK63D,KAAKz2D,EAAE,+DAKvE,eAAe+E,GACrB,OAAOnG,KAAKs8J,UAAUE,SAAS,IAAgBC,KAAMt2J,GAG7C,aAAaA,GACrB,OAAOnG,KAAK63D,KAAKk4D,SAAS5pH,EAAO,CAAE0lH,UAAW,IAGxC,qBAAqB1lH,GAC3B,IAAK,IAAIunK,EAAU1tK,KAAK+pK,mBAAqB,EAAG2D,EAAU,IAAKA,IAAW,CACxE,IAAIt7H,EAAYpyC,KAAK+pK,mBAAqB2D,EAE1C,GAAIvnK,GAASisC,EACX,OAAOA,EAIX,OAAO,EAGC,cAAc42H,GACtB,IAAIkB,EAAsBhtJ,MACvB3B,KAAKytJ,EAAe,CAAC7iK,EAAO8qB,IACtB9qB,EAGI,MAFC8qB,EAAQ,GAAK,GAKxB1lB,OAAQpF,GAAoB,OAAVA,GAErBnG,KAAKwmK,gBAAkB,OAAH,wBAAQxmK,KAAKwmK,iBAAe,CAAE0D,gB,uCAlhBzC,IAA0B,yK,wBAA1B,GAA0B,oD,OAAA,K,KAC1B,MAAqB,G,wLAPrB,CACT,GACA,KACA,QACD,mYDpEH,gBAIE,0BAUA,4BAGF,Q,MAhBK,oCAGK,6CAWO,4C,81EEHV,MAAM,WAA8C,KAIzD,YAA+BnhK,EACVs/C,EACAwP,EACAhpD,EACU8+J,GAC7B7tK,MAAM+3D,EAAM9uD,GALiB,KAAAA,WACV,KAAAs/C,WACA,KAAAwP,OACA,KAAAhpD,aACU,KAAA8+J,MAPxB,KAAA1wD,QAA8B,GAW9B,WACLj9G,KAAKgpK,cAAgBhpK,KAAKud,SAASuS,QAAQjI,KAGtC,cAAco1F,GACnBj9G,KAAKi9G,QAAUA,EAAQz4G,SAEvBxE,KAAK2tK,IAAIrtK,gBAGX,YACE,IAAIklG,EAAWxlG,KAAKi9G,QAAQtoG,OAAO,CAAC1U,EAAS8hE,IACpC9hE,EAAUD,KAAKqoD,SAAS67E,QAAQniE,EAAM7uC,OAC5C,GAEH,OAAIsyE,EAAW,EACNxlG,KAAK63D,KAAKz2D,EAAE,gBAAiB,CAAE6yB,MAAOj0B,KAAKysK,aAAajnE,KAExDxlG,KAAK63D,KAAKz2D,EAAE,2BAIvB,iBACE,OAAO,EAGF,oBAAoB0uB,GACzB9vB,KAAK83D,gBAAgBtvD,KAAKxI,KAAKk4D,oBAAoBpoC,IAEnD9vB,KAAKgpK,cAAgB,IAAIl5I,EAAQjI,MAGzB,aAAa1hB,GACrB,OAAOnG,KAAK63D,KAAKk4D,SAAS5pH,EAAO,CAAE0lH,UAAW,K,uCA7CrC,IAAqC,qD,wBAArC,GAAqC,sOCblD,0BAIE,kDAGE,wCAAgB,EAAA+hD,oBAAA,MAClB,OACF,OAEA,wBACE,mCAAW,EAAAC,cAAA,MAEZ,OAED,QACE,gBACE,YAAG,kBAAO,iBAAmC,OAC/C,OACF,Q,MAnBE,0BAAmB,yBAKjB,oCAOF,8CAKkB,sC,0DCbb,MAAMC,GACX,YAAoBC,GAAA,KAAAA,OAEpB,iBACE,IAAIC,EAAyC,GAM7C,OAJA3pK,EAAEC,KAAKtE,KAAK+tK,KAAK9gJ,KAAK,eAAiBghJ,IACrCD,EAAoBA,EAAkB3kJ,OAAO4kJ,KAGxCD,G,uCAVEF,IAAkB,Y,0BAAlBA,GAAkB,QAAlBA,GAAkB,Y,wDC+BxB,MAAM,WAA2C,KAGtD,qBAA+B7oI,GAC7BjlC,KAAK84C,wBAAwB7nC,UAAU,kBAAkBg0B,QAAUA,EAG9D,QAAQu6E,EAAiBjnE,GAC9B,OAAOv4C,KAAK+hC,iBACV/hC,KAAK24C,cAAcinE,2BAA2B5/G,KAAK8O,oB,sCAT5C,K,wBAAA,GAAkC,qD,OAAA,K,KAClC,IAAgC,G,0ZCrC7C,gBAEI,gBACI,gBACI,gBACI,aACG,QACH,OACJ,OAEA,eACI,eACI,2BAEJ,OACA,eACI,kCAEJ,OACJ,OACJ,OACJ,OAEA,4BAEA,yBACJ,Q,MApBmB,oDAmBF,wD,+DDWJ,I,iBEoBN,MAAMo/J,I,wBAAAA,K,qDAAAA,KAA4B,UAV5B,CACT,IACD,SATQ,CAEP,IAGA,QCLJ,MAEaC,GAAwC,CACnD,CACE1nK,KAAM,yBACNuH,IAAK,YACLS,UAAW,GACXP,gBAAgB,EAChBC,KAAM,CACJC,YAAa,iCACbC,SAVgB,qBAWhBK,OAAQ,mBAoCP,MAAM0/J,I,wBAAAA,K,qDAAAA,KAAyB,SA9B3B,CAEP,IAGA,kBAAeC,SAAS,CAAE1rK,OAAQwrK,KAGlC,KAGAD,GAGA,IAGA,S,0CC9DF,uB,oBACY,gC,0BAEZ,QACE,eACE,cAGF,OACA,cACE,eACF,OAEA,iBAGF,Q,kCAXO,4CAA+B,uBAK9B,iDAID,yDCTF,MAAM,WAAiC,KAQ5C,YAAqBjyF,EACAptE,EACApL,EACAo0D,EACAxP,EACAimH,EACUvlK,EACV2O,EACAi2J,GACnB7tK,MAAM+3D,EAAM9uD,GATO,KAAAkzE,cACA,KAAAptE,aACA,KAAApL,eACA,KAAAo0D,OACA,KAAAxP,WACA,KAAAimH,eACU,KAAAvlK,WACV,KAAA2O,iBACA,KAAAi2J,MAfd,KAAA/1J,KAAO,CACZwqB,UAAWpiC,KAAK63D,KAAKz2D,EAAE,yCAGlB,KAAA67G,QAA6B,GAC5B,KAAAsxD,eAAgB,EAcxB,WACEvuK,KAAKi8E,YACFv3E,IAAwB1E,KAAKwuK,cAC7B3hJ,YACApd,KAAMk0B,IACL3jC,KAAKi9G,QAAUt5E,EAAWn/B,SAC1BxE,KAAKuuK,eAAgB,EAErBvuK,KAAK2tK,IAAIrtK,kBAIf,iBACE,OAAO,EAGF,aAAa4K,GAClB,MAAO,GAAGlL,KAAK6O,WAAW0R,yBAAyBrV,EAAShD,KAGvD,gBAAgBgD,GACrB,OAAOlL,KAAKqoD,SAAS+pF,kBAAkBlnI,EAASykD,WAG3C,oBAAoBzkD,GACzB,OAAOlL,KAAKsuK,aAAa9R,SAAS,IAAgBC,KAAMvxJ,EAASlJ,YAAY8hG,MAG/E,gBACE,OAAQ9jG,KAAKi9G,QAAQh2G,QAAUjH,KAAKuuK,cAGtC,mBACE,IAAIE,EAAShpJ,KAAKC,UAAU,CAAC,CAAC,aAAc,UAExC1X,EAAMhO,KAAKyD,aAAa6xD,UAAUx1C,SAAW,WAAW2uJ,gBAE5D,GAAIzuK,KAAK0X,eAAexP,GAAI,CAG1B8F,EAAMA,EAAM,YAFEyX,KAAKC,UAAU,CAAC,CAACgpJ,WAAY,CAAE/oJ,SAAU,IAAKC,OAAQ,CAAC5lB,KAAK0X,eAAexP,GAAGma,gBAK9F,OAAOrU,G,uCA/DE,IAAwB,8F,wBAAxB,GAAwB,yaDhBrC,0BAIE,wBAIF,OAEA,gBACE,8BAGA,gCAcF,Q,MA3BI,0BAAmB,yBAKjB,oCAKQ,iCAGE,oC,gHEJd,uB,oBACY,gC,yBAMN,yB,8BACa,uB,0BAWb,iBAEE,kBACF,Q,uCADQ,kD,yBAGN,e,8BACG,+B,0BArBT,eAEE,gBACE,+BAIA,cACE,eAEI,aACJ,eAGF,OACA,wBAIA,cACE,sBAGF,OACF,OACF,Q,kCAtBiB,8BAKR,+CAA8B,oCAG9B,wCAAuB,uBAIvB,8BAKA,gCCpBN,MAAM,WAA4B,KAWvC,YAEWa,EACAgpD,EACU9uD,EACVs/C,EACA3wC,EACAjU,EACAkqK,GAET7tK,MAAM+3D,EAAM9uD,GARH,KAAA8F,aACA,KAAAgpD,OACU,KAAA9uD,WACV,KAAAs/C,WACA,KAAA3wC,iBACA,KAAAjU,eACA,KAAAkqK,MAlBJ,KAAA/1J,KAAO,CACZxB,GAAIpW,KAAK63D,KAAKz2D,EAAE,2BAChBghC,UAAWpiC,KAAK63D,KAAKz2D,EAAE,mCACvButK,QAAU/4G,GAAsB51D,KAAK63D,KAAKz2D,EAAE,yBAC1C,CAAEia,OAAQrb,KAAK4uK,eAAeh5G,GAAOi5G,IAAK7uK,KAAK8uK,YAAYl5G,GAAOm5G,WAAY/uK,KAAKgvK,eAAep5G,MAG/F,KAAAqnD,QAAyB,GACxB,KAAAsxD,eAAgB,EAexB,WACEvuK,KACGyD,aACAmyD,KACAxC,KAAKpzD,KAAKivK,cACV5uK,UAAUsjC,GAAc3jC,KAAKkvK,UAAUvrI,EAAWn/B,WAGhD,UAAUoxD,GAEf51D,KAAKi9G,QAAUrnD,EACf51D,KAAKuuK,eAAgB,EACrBvuK,KAAK2tK,IAAIrtK,gBAGX,iBACE,OAAO,EAGF,SAASs1D,GAEd,OAAO51D,KAAK6O,WAAWsgK,SAASv5G,EAAK1tD,IAGhC,gBAAgB0tD,G,MACrB,OAAO51D,KAAK6O,WAAWE,YAAwB,QAAb,EAAC6mD,EAAKl6C,eAAO,eAAEJ,YAG5C,gBAAgBs6C,G,MACrB,OAAmB,QAAnB,EAAOA,EAAKl6C,eAAO,eAAEjV,KAGhB,eAAemvD,G,MACpB,OAAkB,QAAlB,EAAOA,EAAKv6C,cAAM,eAAE5U,KAGf,eAAemvD,G,MACpB,OAAO51D,KAAK6O,WAAWuM,SAAoB,QAAZ,EAACw6C,EAAKv6C,cAAM,eAAEnT,IAIxC,YAAY0tD,GACjB,OAAO51D,KAAKqoD,SAAS+pF,kBAAkBx8E,EAAKjG,WAG9C,gBACE,OAAQ3vD,KAAKi9G,QAAQh2G,QAAUjH,KAAKuuK,cAGtC,mBACE,IAAIrwJ,EAA6B,CAC/BjZ,OAAQ,CAAC,CAAC,aAAc,SACxBs1C,SAAU,GAOZ,OAJIv6C,KAAK0X,eAAexP,KACtBgW,EAAgB,QAAI,CAAC,CAAC,aAAc,IAAK,CAACle,KAAK0X,eAAexP,OAGzDgW,G,uCAnFE,IAAmB,0E,wBAAnB,GAAmB,gtBDdhC,0BAGE,wBAKF,OACA,gBACE,8BAGA,eACE,uBA0BF,OACF,Q,MAzCe,0BAAmB,yBAK9B,oCAKU,iCAKN,oC,4FERD,MAAM,GACX,YAAqBza,EACAyY,GADA,KAAAzY,eACA,KAAAyY,qBAOd,WAAWV,GAChB,OAAOxb,KACJyD,aACAixD,MACAtB,KAAK,CAAEpkD,QAAS,CAAC,CAAC,QAAS,IAAK,CAACwM,OACjCqR,YACApd,KAAKk0B,GACqB,IAArBA,EAAWsW,MACNj6C,KAAKovK,WAAW5zJ,GAEfmoB,EAAWn/B,SAAS,IAK5B,WAAWgX,GACjB,IAAIzZ,EAAU,CACZ,OAAU,CACR,MAAS,CACP,KAAQyZ,KAKd,OAAOxb,KACJyD,aACAixD,MACAtwD,KACAgpB,KAAKrrB,GACL5B,KACC,OAAAqxD,GAAA,GAAUptD,IACR,IAAIoD,EAASpD,EAAKrC,QAAQorB,QACtB5P,EAAWvd,KAAKkc,mBAAmBm8D,kBAAkB7wE,GAOzD,OALgC,IAA5B+V,EAASmyC,QAAQzoD,SACnBsW,EAAS8kJ,SAAW,EACpB9kJ,EAASgd,YAAc,GAGlBv6B,KACJyD,aACAixD,MACAtnC,KAAK7P,EAAUnZ,EAAK5B,WAG1BqqB,a,uCAtDM,IAAyB,sB,0BAAzB,GAAyB,QAAzB,GAAyB,Y,sBCD/B,MAAMwiJ,GAIJ,SACLrvK,KAAKsvK,SAASr1J,U,uCALLo1J,K,wBAAAA,GAA+B,qD,OAAA,K,8JCN5C,UACE,oCACF,S,wCCIO,MAAME,GAIJ,SACLvvK,KAAKsvK,SAASr1J,U,uCALLs1J,K,wBAAAA,GAA8B,qD,OAAA,K,8JCN3C,UACE,mCACF,S,kBCeO,MAAMC,GAGX,YAAmBn2G,EACAo2G,EACAp0D,GAFA,KAAAhiD,cACA,KAAAo2G,eACA,KAAAp0D,YAJZ,KAAAv2G,QAA0B,GAK/B9E,KAAKq7G,UAAYr7G,KAAKq7G,WAAa,gBAG9B,2BAA2BxjD,EAAkB63G,GAClD,MAAO,CACLv5I,QAAQ,EACRgO,OAAQurI,EACRjpK,KAAMoxD,EAAKz2D,EAAE,6CACbykB,iBAAiB,EACjBsI,OAAQ,CACNjpB,QAAS,CACPK,KAAM,uCCjBT,MAAM,GAMX,YAAqB7E,EACA25C,EACAxN,EACAn1B,GAHA,KAAAhX,OACA,KAAA25C,eACA,KAAAxN,sBACA,KAAAn1B,iBANb,KAAAi4J,OAAyC,GAS1C,mBACL,OAAO,IAAIpgK,QAAQ,CAACC,EAASquB,KAC3B79B,KAAK4vK,iBAAiBngK,KAAK,KACzBzP,KAAK6vK,gBAAgBpgK,KAAK,IAAMD,SAK/B,iBACL,IAAIyuG,EAAWj+G,KAAK8E,QAAQoK,IAAIrL,GACvB7D,KAAKwmJ,UAAU3iJ,IAGxB,OAAO0L,QAAQu0B,IAAIm6E,GAGrB,eACE,OAAOj+G,KAAK8E,QAAQoK,IAAIrL,IACf,CACLkC,OAAQlC,EAAMC,QAAQiC,OACtBiyC,WAAY,GACZ1V,MAAOz+B,EAAM4C,QAKZ,gBAGL,OAFAzG,KAAKu3B,cAAczyB,QAAQmC,OAAS,EAE7BjH,KAAK0jC,cAGP,qBACL,OAAgC,IAA5B1jC,KAAKq5D,YAAYpyD,OACZjH,KAAK8vK,gBACTrgK,KAAM5L,IACL7D,KAAKq5D,YAAYn4D,KAAK,CAACgH,GAAIrE,EAAMqE,KAE1BlI,KAAK0jC,gBAGT1jC,KAAK0jC,cAIR,gBACN,OAAO1jC,KACJq6C,aACAv1C,QACAV,KACA81D,eACC,CAAC3f,SAAU,QACX7uC,EACA1L,KAAK0X,eAAe5C,WACpB06J,GAAqBO,oBAAoB/vK,KAAKU,OAAQV,KAAK0X,eAAe5C,aAE3E+X,YACApd,KAAK,EAAErL,EAAMP,KACL7D,KACJq6C,aACAv1C,QACAsoB,KAAKvpB,EAAOO,GACZyoB,aAID,cACN,IAAImjJ,EAAgBhwK,KAAKq5D,YAAYnqD,IAAI+gK,GAChCjwK,KAAKyoC,UAAUwnI,IAGxB,OAAO1gK,QAAQu0B,IAAIksI,GAGb,UAAU9xJ,GAChB,OAAOle,KACJq6C,aACAv1C,QACA0G,KACCsE,OAAOoG,OAAO,CAACqkC,SAAU,GAAIr8B,EAAO0qJ,OACpC1qJ,EAAOhW,GACPlI,KAAK0X,eAAe5C,YAErB+X,YACApd,KAAK5L,IACAqa,EAAOzX,OACT5C,EAAM4C,KAAOyX,EAAOzX,MAEtBzG,KAAKu3B,cAAczyB,QAAQ5D,KAAK2C,KAIxB,UAAUA,G,mDACtB,OAAO7D,KAAKkwK,QAAQrsK,GACjB4L,KAAKrL,GACGpE,KACJq6C,aACAv1C,QACAoD,GAAGrE,GACH8sD,MAAM9sD,EAAOO,GACbyoB,gBAIT,oBACE,OAAO7sB,KAAKmwK,eAGd,kBAAyBx8J,GACvB3T,KAAKmwK,eAAiBx8J,EACtB3T,KAAKowK,cAAgB,KAGV,QAAQvsK,G,mDACnB,OAAO7D,KACJqwK,YACA5gK,KAAK,IACGzP,KAAK2vK,OAAO9rK,EAAMqE,QAI/B,WACE,IAAI05I,EAAsB,CACxB,CACEn7I,KAAM,iBACN6b,MAAOtiB,KAAKU,KAAKU,EAAE,gCACnB85C,eAAgBm0H,KAIhBiB,EAAYtwK,KAAKu3B,cAAczyB,QAAQoK,IAAKrL,IACvC,CACL4C,KAAM5C,EAAMqE,GACZoa,MAAOtiB,KAAKU,KAAKU,EAAE,kCACnB85C,eAAgBq0H,MAIpB,OAAO3tB,EAAKv4H,OAAOinJ,GAGd,YACL,IAAKtwK,KAAKowK,cAAe,CACvB,IAAIG,EAAevwK,KAAKu3B,cAAczyB,QAAQoK,IAAKrL,GAC1C7D,KACJq6C,aACAv1C,QACAV,KACA47B,KAAKn8B,GACLgpB,YACApd,KAAK,EAAErL,EAAMC,MACZrE,KAAK2vK,OAAO9rK,EAAMqE,IAAgB9D,IAEnCoW,MAAOwE,GAAUhf,KAAK6sC,oBAAoBgB,eAAe7uB,KAG9Dhf,KAAKowK,cAAgB7gK,QAAQu0B,IAAIysI,GAGnC,OAAOvwK,KAAKowK,cAGd,gBACE,OAAOpwK,KAAKmwK,eAAe90D,UAG7B,cAAqBvoG,GACnB9S,KAAKmwK,eAAe90D,UAAYvoG,EAGlC,cACE,OAAO9S,KAAKmwK,eAAerrK,QAG7B,mBACE,OAAO9E,KAAKmwK,eAAeV,aAG7B,kBACE,OAAOzvK,KAAKmwK,eAAe92G,a,uCA/LlB,IAA2B,4C,0BAA3B,GAA2B,QAA3B,GAA2B,Y,qEvHAlC,Q,0BADF,QACE,iCACF,Q,oBADgB,0DAA8D,yC,oIAM1E,gBAEE,eAKG,wFAEH,OATF,O,sCACI,2FAGC,4EAAsE,uBACtE,yC,0BART,iBAEE,gBACE,uBAUF,OACF,Q,oBAXQ,yCwHQL,MAAM4qF,GAAwC,IAAI,IAAmC,6CAKrF,MAAM,WAA2C,IAyBtD,YAA+CnyI,EAC+BqyI,EACzDzjJ,EACAqI,EACAyhB,EACAF,EACAyX,EACA8K,EACAhtC,EACAoc,EACAzb,EACAgwK,GACnB1wK,MAAMgS,EAAQjS,EAAOW,GAZwB,KAAAsR,SAC+B,KAAAqyI,wBACzD,KAAAzjJ,OACA,KAAAqI,WACA,KAAAyhB,SACA,KAAAF,2BACA,KAAAyX,mBACA,KAAA8K,sBACA,KAAAhtC,QACA,KAAAoc,uBACA,KAAAzb,aACA,KAAAgwK,qBAjCd,KAAAvpH,eAAgB,EAGhB,KAAAE,qBAAsB,EAItB,KAAAvvC,KAAO,CACZ0K,MAAOtiB,KAAKU,KAAKU,EAAE,wBACnB68D,WAAYj+D,KAAKU,KAAKU,EAAE,wBAExBgjJ,YAAapkJ,KAAKU,KAAKU,EAAE,0BACzBsuC,aAAc1vC,KAAKU,KAAKU,EAAE,4BAyB5B,WACEpB,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eAEvC9G,KAAK+hC,iBAAiB9wB,UAAU,SAASg0B,QAAUjlC,KAAKwwK,mBAAmBH,YACxE5gK,KAAK,KACJzP,KAAKskJ,cAAgB,IAAI,KACvBtkJ,KAAKwwK,mBAAmB5uB,KACxB5hJ,KAAKukJ,iBAAiBz9I,cACtB9G,KAAKsqB,yBACLtqB,KAAKwqB,OACLxqB,KAAK+I,UAGP,MAAMm4D,EAAalhE,KAAK8R,OAAmB,YAAK9R,KAAKolE,cAAc,GAAG3+D,KACtEzG,KAAKmgH,SAASj/C,KAIpB,cACElhE,KAAKskJ,cAAcx+E,UAGrB,oBACE,OAAO9lE,KAAKskJ,cAAcl/E,cAG5B,iBACE,OAAOplE,KAAKskJ,cAAc/+E,WAGrB,SAAS9+D,GACdzG,KAAKskJ,cAAcnkC,SAAS15G,GAGvB,cACLzG,KAAKskJ,cAAcE,iBAAiB9+I,QAAS+I,IAC3CA,EAAUwL,WAGZja,KAAKu3B,cAAgBv3B,KAAKwwK,mBAAmBj5I,cAE7Cv3B,KAAK8rB,QAAQ/gB,QAQR,UAEL,OADA/K,KAAK6oD,aAAat7C,SACX,EAGT,mBACE,OAAOvN,KAAK4G,U,uCA/FH,IAAkC,KAyBzB,KAAkB,KACNq9I,GAAqC,0G,wBA1B1D,GAAkC,qD,OAAA,K,01BxHpC/C,gBACE,gBAGE,gBACE,eAEA,cACE,cAEI,iCAAS,EAAA38F,QAAA,MAEb,OACF,OACF,OAEA,gCAIA,uBAgBA,kBACA,kBACE,qBAEQ,gCAAS,EAAAm9F,iBACjB,OACA,qBAEQ,iCAAS,EAAAn9F,QAAA,MACjB,OACF,OACF,OACF,Q,MA3CU,yCAME,wCAKM,+CAIT,uCAmBK,+CAIA,kD,wDyHJP,MAAe,WAAiC,GAWrD,YAA6Bv+C,EACA8wC,EACRge,EACUplC,EACVwyI,GACrBnlK,MAAM+3D,EACAplC,EACAwyI,GAPuB,KAAAl8J,WACA,KAAA8wC,iBACR,KAAAge,OACU,KAAAplC,SACV,KAAAwyI,SAXrB,KAAAmE,aAAiC,IAAI,IAE3B,KAAA9D,aAAe,CACvBtlK,KAAKulK,WACLvlK,KAAKqpK,eAaP,oBACE,MAAO,CACLloK,SAAUnB,KAAK63D,KAAKz2D,EAAE,sCACtBE,QAAS,KACPtB,KAAK65C,eAAe94C,KAAKf,KAAKywK,uBAAwBzwK,KAAK+I,SAAU/I,KAAK8R,QACvE0pD,aAAan7D,UAAWo7D,IACvBz7D,KAAKopK,aAAa5gK,KAAKizD,EAAMlkC,kBAE1B,IAKb,aACE,MAAO,I,yBhC1EX,wC,oBAEI,gC,uCgCqCkB,IAAwB,kD,wBAAxB,GAAwB,wDCHvC,MAAM,WAAmC,GAJhD,c,oBAKY,KAAAk5I,uBAAyB,I,sCADxB,K,wBAAA,GAA0B,oJjCpCvC,+C,KACI,wB,uDiCmCS,I,0CCnCX,mB,oBACQ,6BAAsB,uBAAtB,CAAsB,wBAAtB,CAAsB,2B,yBAM9B,uB,oBACY,gC,uCCaP,MAAMC,GAkBX,YAAqB74G,GAAA,KAAAA,OAfD,KAAAwjD,UAAsB,gBAGnC,KAAAr8F,MAAoB,KAEpB,KAAA2xJ,YAAc,OACd,KAAAC,YAAuB,GACvB,KAAAC,UAA2B,GAE3B,KAAA5qK,aAAc,EAEd,KAAA2R,KAAO,CACZwqB,UAAWpiC,KAAK63D,KAAKz2D,EAAE,sCAKzB,YAAY0mC,GACNA,EAAQgpI,UACV9wK,KAAK+wK,kBACL/wK,KAAKgxK,kBAGAlpI,EAAQgpI,SAAS15G,cACpBp3D,KAAKiG,aAAc,IAEZ6hC,EAAQuzE,WACjBr7G,KAAK+wK,kBAID,kBACN,IAAIE,EAAa5sK,EAAEu9C,KAAK5hD,KAAK8wK,SAASn8J,OAAO,CAACu8J,EAAOzgK,KACnD,IAAI1K,GAAU0K,EAAQ1K,QAAU,IAAImJ,IAAK2F,GAAUA,EAAM1O,OACzD,OAAO+qK,EAAM7nJ,OAAOtjB,IACnB,KAECorK,EAAiBnxK,KAAK8wK,SAAS5hK,IAAKuB,IACtC,IAAI2gK,GAAY3gK,EAAQ1K,QAAU,IAAI4O,OAAO,CAACgsE,EAAM9rE,KAClD8rE,EAAK9rE,EAAM1O,OAAS0O,EAAMof,MACnB0sD,GACN,IAEH,MAAO,CACLr+C,MAAO7xB,EAAQ6xB,MACfn0B,KAAM8iK,EAAW/hK,IAAKozB,GAAmB8uI,EAAS9uI,IAAU,MAIhE2uI,EAAaA,EAAW/hK,IAAKozB,GACtBA,GACItiC,KAAK63D,KAAKz2D,EAAE,4BAMvBpB,KAAKqxK,YAGLrxK,KAAK4wK,YAAY3pK,OAAS,EAC1BjH,KAAK4wK,YAAY1vK,QAAQ+vK,GACzBjxK,KAAK6wK,UAAU5pK,OAAS,EACxBjH,KAAK6wK,UAAU3vK,QAAQiwK,GAGf,kBACR,IAAI7jJ,EAAW,CACbgkJ,YAAY,EACZC,qBAAqB,EACrBxuD,OAAQ,CAENz3F,QAAStrB,KAAK8wK,SAAS7pK,OAAS,GAElC0/J,QAAS,CACP6K,WAAY,CACVC,MAA0B,QAAnBzxK,KAAKq7G,UAAsB,MAAQ,YAK5Cq2D,EAAiC,CAACC,OAAO,IACtB,kBAAnB3xK,KAAKq7G,WAAoD,QAAnBr7G,KAAKq7G,WAC9Cr7G,KAAK4xK,mBAAmBF,GAGzB1xK,KAAKyvK,aAAe3/J,OAAOoG,OAAO,GAAIoX,EAAUokJ,EAAmB1xK,KAAK6xK,mBAG1E,uBACE,OAAO7xK,KAAK6wK,UAAU5pK,OAAS,GAAKjH,KAAK6wK,UAAU57H,KAAKlpB,GAAOA,EAAI5d,KAAKlH,OAAS,GAG3E,YACN,GAAuB,kBAAnBjH,KAAKq7G,WAAiCr7G,KAAK8wK,UAAY9wK,KAAK8wK,SAAS,GAAI,CAC3E,IAAIvxF,EAAkB,GACtBv/E,KAAK8wK,SAASprK,QAAQktB,GAAKA,EAAE7sB,OAAQL,QAAQ20I,IACtC96D,EAAO3mE,SAASyhI,EAAEl0I,QACrBo5E,EAAOr+E,KAAKm5I,EAAEl0I,UAGlB,IAAI+rB,EAAyB,GAAhBqtD,EAAOt4E,OAEhBjH,KAAK8wK,SAAS7pK,OAAS,IAEzBirB,GAAU,IAIZA,GAAU,GAEVlyB,KAAK2wK,YAAiBz+I,EAAH,UAEnBlyB,KAAK2wK,YAAc,OAKf,mBAAmBlB,GAEzB,IAAIqC,EAAuB,CAAC,CAC1BC,SAAS,EACTC,MAAO,CACLjlK,SAAW5G,GACLshB,KAAKg9D,MAAMt+E,KAAWA,EACjBA,EAEA,QAMX8rK,EAAqB,CAAC,CACxBF,SAAS,IAGPtC,EAAakC,SACQ,QAAnB3xK,KAAKq7G,WACPo0D,EAAakC,OAAOO,MAAQJ,EAC5BrC,EAAakC,OAAOQ,MAAQF,GACC,kBAAnBjyK,KAAKq7G,YACfo0D,EAAakC,OAAOQ,MAAQL,EAC5BrC,EAAakC,OAAOO,MAAQD,K,uCAlJvBvB,IAAiC,Y,wBAAjCA,GAAiC,keDtB9C,kBACE,0BAOA,8BAGF,Q,MAXgG,yCAMtF,wCAEI,0D,yJEOP,MAAM,WAA+B,KAG1C,YAAsB74G,EACA9uD,EACA4kK,EACS6C,GAC7B1wK,MAAM+3D,EAAM9uD,GAJQ,KAAA8uD,OACA,KAAA9uD,WACA,KAAA4kK,MACS,KAAA6C,qBALxB,KAAAM,SAA6C,GASpD,WACE9wK,KAAKoyK,0BACLpyK,KAAKqyK,uBAGP,cAAqBv/J,GACnB9S,KAAKud,SAASuS,QAAQurF,UAAYvoG,EAG7B,YAAYa,GACjB3T,KAAKwwK,mBAAmB8B,mBACrB7iK,KAAK,KAGJ,GAFAzP,KAAKuyK,UAEDvyK,KAAKud,SAASuS,QAAQurF,YAAcr7G,KAAKwwK,mBAAmBn1D,UAAW,CACzE,IAAI3uF,EAAY1sB,KAAKk4D,oBAAoB,CAAEmjD,UAAWr7G,KAAKwwK,mBAAmBn1D,YAE9Er7G,KAAK83D,gBAAgBtvD,KAAKkkB,MAKxB,UACR1sB,KAAK8wK,SAAW9wK,KAAKwwK,mBAAmBM,SACxC9wK,KAAK2tK,IAAIrtK,gBAGD,0BACR,IAAIsP,EAAM,GACN5P,KAAKud,SAASuS,QAAQioB,SACxBnoC,EAAI1O,KAAK,CAAEgH,GAAIlI,KAAKud,SAASuS,QAAQioB,UAGvC/3C,KAAKwwK,mBAAmBj5I,cAAgB,IAAIi4I,GAAqB5/J,EAC/D5P,KAAKud,SAASuS,QAAQ2/I,aACtBzvK,KAAKud,SAASuS,QAAQurF,WAGhB,uBACRr7G,KAAKwwK,mBAAmBgC,qBACrB/iK,KAAK,KACJ,IAAKzP,KAAKud,SAASuS,QAAQioB,QAAS,CAClC,IAAIrrB,EAAY1sB,KAAKk4D,oBAAoB,CAAEngB,QAAS/3C,KAAKwwK,mBAAmBn3G,YAAY,GAAGnxD,KAE3FlI,KAAK83D,gBAAgBtvD,KAAKkkB,GAE5B1sB,KAAKuyK,YAIX,mBACE,OAAOvyK,KAAKwwK,mBAAmBf,aAGjC,gBACE,OAAOzvK,KAAKwwK,mBAAmBn1D,W,uCAjEtB,IAAsB,yC,wBAAtB,GAAsB,+CAFtB,CAAC,KAA4B,iMCb1C,0BAEI,qCAAa,EAAA0tD,aAAA,MAEf,iCAGI,wCAAgB,EAAA0J,YAAA,MACpB,OACF,OAEA,+B,MAVI,0BAKE,oCAMa,oCAAqB,2B,6KrCZxC,wC,oBAEI,gCsCkCG,MAAM,WAAmC,GAJhD,c,oBAKY,KAAAhC,uBAAyB,M,sCADxB,K,wBAAA,GAA0B,oJtCpCvC,+C,KACI,wB,uDsCmCS,I,0CC3Bb,8B,oBAAmB,0BAAmB,kCCU/B,MAAM,WAA+B,KAa1C,YAAsB54G,EACS9uD,EACTovC,EACSrnC,EACAlO,EACAa,GAC7B3D,MAAM+3D,EAAM9uD,GANQ,KAAA8uD,OACS,KAAA9uD,WACT,KAAAovC,kBACS,KAAArnC,QACA,KAAAlO,aACA,KAAAa,eAfxB,KAAAwV,UAAW,EAGX,KAAAse,cAAuD,CAC5DoX,sBAAsB,EACtBC,mBAAmB,EACnB4iD,wBAAwB,EACxBF,oBAAoB,GAYtB,WACOtxF,KAAKud,SAASuS,QAAQioB,QAUzB/3C,KAAK+3C,QAAU/3C,KAAKud,SAASuS,QAAQioB,QATrC/3C,KAAK8vK,gBACFrgK,KAAM5L,IACL,IAAI6oB,EAAY1sB,KAAKk4D,oBAAoB,CAAEngB,QAASl0C,EAAMqE,KAE1DlI,KAAK83D,gBAAgBtvD,KAAKkkB,GAE1B1sB,KAAK+3C,QAAUl0C,EAAMqE,KAM3BlI,KAAK0yK,OAAS1yK,KACX4C,WACAiB,MACA3D,UAEHF,KAAK0yK,OACFvyK,KAEC,OAAAwyK,GAAA,GAAK,GACL3yK,KAAKI,kBACLC,UAAWwD,IACb7D,KAAK4yK,uBAAuB/uK,KAIhC,iBACE,OAAO7D,KAAKud,SAASuS,QAAQrpB,KAGxB,wBACL,MAAO,sBAGD,uBAAuB5C,GACzB7D,KAAK6E,UACP7E,KAAKwmJ,UAAU3iJ,EAAO7D,KAAK6E,WAE3B7E,KACGyD,aACAqB,QACAV,KACA47B,KAAKn8B,GACLxD,UAAU,EAAE+D,EAAMC,MACjBrE,KAAK6E,UAAYT,EACjBpE,KAAKwmJ,UAAU3iJ,EAAOO,KAKtB,UAAUP,EAAqBO,GACrCpE,KAAKiZ,UAAW,EAEhBjZ,KACGyD,aACAqB,QACAoD,GAAGrE,GACH8sD,MAAM9sD,EAAO7D,KAAK6E,WAClBxE,UACC,IAAML,KAAKiZ,UAAW,EACtB,IAAMjZ,KAAKiZ,UAAW,GAIpB,gBACN,MAAMnK,EAAoB9O,KAAK8Q,MAAMoN,OAAoB,YACzD,IAAI20J,EAAsB7yK,KAAKud,SAASuS,QAAQkoB,WAC5CA,EAAaloC,OAAOoG,OAAO,CAAEqkC,SAAU,GAAKs4H,GAEhD,OAAO7yK,KACJyD,aACAqB,QACAV,KACA81D,eACCliB,OACAtsC,EACAoD,EACA9O,KAAK+vK,uBAENljJ,YACApd,KAAK,EAAErL,EAAMP,KACL7D,KACJyD,aACAqB,QACAsoB,KAAKvpB,EAAOO,GACZyoB,YACApd,KAAM5L,WACE7D,KAAKud,SAASuS,QAAQkoB,WAEtBn0C,KAKP,sBAMR,MAAO,CACLsyB,QAAQ,EACRgO,SAJwBnkC,KAAK8Q,MAAMoN,OAAoB,c,uCA3HhD,IAAsB,4E,wBAAtB,GAAsB,8NDnBnC,0BAEE,qCAAa,EAAA6qJ,aAAA,MACb,iCAIF,OAEA,sC,MARE,0BAIE,oCAMe,iC,gHEHZ,MAAM,WAAyC,KAC7C,kBAAkBr8I,GACvB1sB,KAAK83D,gBAAgBtvD,KAAKkkB,I,sCAFjB,K,wBAAA,GAAgC,kKCR7C,UACE,4BACiB,2CAAmB,EAAAomJ,kBAAA,MAA4B,OAClE,Q,MAFmB,sC,mIDON,I,8BEHN,MAAeC,GACpB,YAAqBryK,EACAw3C,EACA86H,GAFA,KAAAtyK,OACA,KAAAw3C,yBACA,KAAA86H,uBAGX,uBACR,OAAOhzK,KACGgzK,qBACA9C,QAAQlwK,KAAK6D,OACb4L,KAAKrL,IACJpE,KAAKk4C,uBAAuBlyC,WAAWhG,KAAK6D,MAAO7D,KAAK6D,MAAMC,SAC9D9D,KAAKk4C,uBAAuBoC,qBAAqBt6C,KAAK6D,MAAOO,M,yDCjB5E,0BACe,sEACoB,O,uBAApB,2BCYR,MAAM,WAA4C2uK,GAOvD,YAAqBryK,EACAuC,EACA8vC,EACAmF,EACA86H,GACnBlzK,MAAMY,EAAMw3C,EAAwB86H,GALjB,KAAAtyK,OACA,KAAAuC,iBACA,KAAA8vC,mBACA,KAAAmF,yBACA,KAAA86H,uBAVd,KAAAhkK,QAAwC,GAExC,KAAA4I,KAAO,CACZuwG,iBAAkBnoH,KAAKU,KAAKU,EAAE,8CAWhC,WACEpB,KAAKizK,uBACFxjK,KAAK,KACJzP,KAAKiD,eACFmpD,UACA38C,KAAK,KACJzP,KAAKgP,QAAUhP,KAAKiD,eAAehD,YAKtC,SACDD,KAAKgP,UACPhP,KAAKiD,eAAeqlH,kBAAkBtoH,KAAKgP,SAC3ChP,KAAKiD,eAAemD,aAAapG,KAAKgzK,qBAAqBluK,QAAQ,KAIvE,YACE,OAAO9E,KAAKgzK,qBAAqBluK,QAAQ,I,uCAlChC,IAAmC,sD,wBAAnC,GAAmC,6KDdhD,iC,KAAe,0B,mFEUH,mB,yBACQ,kBAAiB,uB,yBAczB,mB,yBACQ,kBAAgB,wB,2CCN7B,MAAM,WAA6CiuK,GAWxD,YAAqBryK,EACAoC,EACAo1C,EACA86H,GACnBlzK,MAAMY,EAAMw3C,EAAwB86H,GAJjB,KAAAtyK,OACA,KAAAoC,iBACA,KAAAo1C,yBACA,KAAA86H,uBAZd,KAAA//E,gBAAyC,GAIzC,KAAAr7E,KAAO,CACZs7J,SAAUlzK,KAAKU,KAAKU,EAAE,0BACtB+xK,WAAYnzK,KAAKU,KAAKU,EAAE,kBAUnB,SACLpB,KAAKgzK,qBAAqB33D,UAAYr7G,KAAKozK,iBAAiBt+J,WAC5D9U,KAAKgzK,qBAAqBluK,QAAQY,QAAS7B,IACzC7D,KAAK8C,eAAesD,aAAavC,KAIrC,mBACE,OAAO7D,KAAK8C,eAAe7C,QAG7B,iBAAwBkG,GACtBnG,KAAK8C,eAAe0R,OAAOrO,GAG7B,WACEnG,KACGizK,uBACAxjK,KAAK,KACJzP,KAAK8C,eACFspD,UACA38C,KAAK,KACJzP,KAAKqzK,4BACLrzK,KAAKszK,mCAKP,4BACN,IAAIh+J,EAAYtV,KAAK8C,eAAewS,UAGhCrV,EAAUD,KAAK8C,eAAe7C,QAE9BA,IACFqV,EAAYA,EAAU/J,OAAOsJ,GAASA,EAAM3M,KAAOjI,EAASiI,IAC5DoN,EAAYA,EAAU+T,OAAOppB,IAG/BD,KAAKizF,gBAAkB5uF,EAAEY,OAAOqQ,EAAW,QAGrC,+BACNtV,KAAKuzK,oBAAsBlvK,EAAEY,OAAO,CAClC,CAAC6P,WAAY,gBAA8BwtB,MAAOtiC,KAAKU,KAAKU,EAAE,kCAC9D,CAAC0T,WAAY,MAAoBwtB,MAAOtiC,KAAKU,KAAKU,EAAE,uBACpD,CAAC0T,WAAY,OAAqBwtB,MAAOtiC,KAAKU,KAAKU,EAAE,wBACrD,CAAC0T,WAAY,MAAoBwtB,MAAOtiC,KAAKU,KAAKU,EAAE,uBACpD,CAAC0T,WAAY,WAAyBwtB,MAAOtiC,KAAKU,KAAKU,EAAE,4BACzD,CAAC0T,WAAY,QAAsBwtB,MAAOtiC,KAAKU,KAAKU,EAAE,yBACtD,CAAC0T,WAAY,YAA0BwtB,MAAOtiC,KAAKU,KAAKU,EAAE,+BACzD,SAEHpB,KAAKozK,iBAAmBpzK,KAAKuzK,oBAAoB/nK,KAAKsH,GAAQA,EAAKgC,aAAe9U,KAAKgzK,qBAAqBz7I,cAAc8jF,YAAcr7G,KAAKuzK,oBAAoB,GAGnK,YACE,OAAOvzK,KAAKgzK,qBAAqBluK,QAAQ,I,uCA3EhC,IAAoC,2C,wBAApC,GAAoC,mjBDpBjD,cACE,iBACE,gBACE,kBACA,gBACE,gBACE,mBAAQ,6DAIN,0BAGF,OACF,OACF,OACF,OAEA,gBACE,kBACA,iBACE,iBACE,oBAAQ,iEAGN,2BAGF,OACF,OACF,OACF,OACF,OACF,Q,MA9BiC,4CAGf,uCAA0B,6BAIxB,0CASa,8CAGf,2CAA8B,6BAG5B,gD,6JEvBhB,mBAAuE,QAAgB,Q,yBAA/E,sBAA+D,uB,0BAG3E,gBAEI,gBAGJ,Q,oBAFS,qC,yBAIT,gC,oBACiB,4BAAqB,gC,yBAKtC,gC,oBACiB,4BAAqB,gCCM/B,MAAM,GAWX,YAAqBtE,EACAE,EACA8yK,EACU7F,GAHV,KAAAntK,aACA,KAAAE,OACA,KAAA8yK,4BACU,KAAA7F,MAVtB,KAAAzoK,QAAiB,SACjB,KAAAuqK,aAA4B,CAAE8B,qBAAqB,GACrD,KAAAT,SAA6C,GAC7C,KAAA2C,mBAAoB,EAEpB,KAAAz0J,MAAoB,KAOzBhf,KAAK0zK,iBAAmB,CAAC,CAACpxI,MAAO5hC,EAAKU,EAAE,wCAAyCO,IAAK,YAC7D,CAAC2gC,MAAO5hC,EAAKU,EAAE,oCAAqCO,IAAK,QACzD,CAAC2gC,MAAO5hC,EAAKU,EAAE,sCAAuCO,IAAK,UAC3D,CAAC2gC,MAAO5hC,EAAKU,EAAE,wCAAyCO,IAAK,YAC7D,CAAC2gC,MAAO5hC,EAAKU,EAAE,sCAAuCO,IAAK,UAC3D,CAAC2gC,MAAO5hC,EAAKU,EAAE,wCAAyCO,IAAK,aAGxF,WACE,MAAMiuB,EAAU5vB,KAAKQ,WAAWsG,cAChC9G,KAAK2zK,iBAAmBluJ,KAAKvG,MAAM0Q,EAAQoT,aAAa,sBAExDhjC,KAAK4zK,gBAGA,gBACL5zK,KAAK8wK,SAAW,GAEhB,IAAI5yJ,EAASle,KAAK6zK,YAElB7zK,KAAKwzK,0BAA0Bj8I,cAAgB,IAAIi4I,GAAqBtxJ,EAAQ,GAAI,iBAGpFle,KACGwzK,0BACA3D,gBACApgK,KAAK,KACJzP,KAAK8wK,SAAW9wK,KAAK8zK,eAAe9zK,KAAKwzK,0BAA0B1C,SAAU5yJ,GAE7Ele,KAAK2tK,IAAIrtK,kBAEVka,MAAM,KACLxa,KAAKgf,MAAQhf,KAAKU,KAAKU,EAAE,kCAEzBpB,KAAK2tK,IAAIrtK,kBAIf,kBACE,IAAI4d,EAAS,GAab,MAXqB,WAAjBle,KAAKkF,SACPlF,KAAKyzK,mBAAoB,EAEzBv1J,EAAOhd,KAAK,CAAEuF,KAAMzG,KAAKU,KAAKU,EAAE,gBAAiBwnK,MAAO5oK,KAAK+zK,cAE7D/zK,KAAKyzK,mBAAoB,EAEzBv1J,EAAOhd,KAAK,CAAEuF,KAAMzG,KAAKU,KAAKU,EAAE,+BAAgCwnK,MAAO5oK,KAAKg0K,YAC5E91J,EAAOhd,KAAK,CAAEuF,KAAMzG,KAAKU,KAAKU,EAAE,iCAAkCwnK,MAAO5oK,KAAKi0K,eAGzE/1J,EAGF,eAAe4yJ,EAA4C5yJ,GAChE,IAAIg2J,EAAeh2J,EAAOhP,IAAKu6B,GAAMA,EAAEhjC,MAEvC,OAAOqqK,EAASpsJ,QAAQyV,KAAK,CAACjX,EAAGC,IACxB+wJ,EAAa92J,QAAQ8F,EAAEof,OAAS4xI,EAAa92J,QAAQ+F,EAAEmf,QAKlE,gBACE,OAAOtiC,KAAKm0K,YAGd,gBACE,OAAOn0K,KAAKm0K,UAAU,CAACx4H,OAAQ,CAAEh2B,SAAU,IAAKC,OAAQ,MAG1D,kBACE,OAAO5lB,KAAKm0K,UAAU,CAACx4H,OAAQ,CAAEh2B,SAAU,IAAKC,OAAQ,MAGlD,UAAUra,GAChB,IAAIyD,EAAU,CAAC,CAAColK,aAAc,CAACzuJ,SAAU,IAAKC,OAAQ,MAUtD,OARIra,GACFyD,EAAQ9N,KAAKqK,GAGXvL,KAAK2zK,kBACP3kK,EAAQ9N,KAAKlB,KAAK2zK,kBAGb,CACL,YAAa,GACb3kK,QAASyW,KAAKC,UAAU1W,GACxBkkK,SAAUlzK,KAAKkF,QACfq1C,SAAU,GAId,oBACE,OAAOv6C,KAAKyzK,kBAGd,mBACE,OAAQzzK,KAAKyzK,kBAGf,mBACE,OAAIzzK,KAAKq0K,cACAr0K,KAAKs0K,oBAELt0K,KAAKu0K,oB,uCA3HL,IAAiC,yC,wBAAjC,GAAiC,0D,OAAA,M,2OALjC,CACT,MACD,8XDtBH,mBAAQ,wDAAqB,mCACJ,EAAAX,mBACrB,0BACJ,OAEA,uBAOA,qCAMA,sC,MAlBQ,0BAE2B,2CAG9B,6BAUY,oCAMA,uC,+wBEoDV,MAAM,GACX,gB,wBADW,K,qDAAA,KAAkC,SA/BpC,CAEP,IAEA,KAEA,S,KAKArE,GAA8B,moBAD9B,GACAA,GACA,GACAF,GACA,GAGAqB,GAEA,IAAiC,oE,KANjCrB,GAA+B,moBAH/B,GACAE,GACA,GACAF,GACA,GAGAqB,GAEA,IAAiC,oE,kFC9CnC,sBAEE,qCAGF,Q,oBAJW,mBACiB,4BC2BvB,MAAM,WAA0C,KAGrD,YAA+B74G,EACA9uD,EACAtF,EACAiU,EACA7X,GAC7BC,MAAM+3D,EAAM9uD,GALiB,KAAA8uD,OACA,KAAA9uD,WACA,KAAAtF,eACA,KAAAiU,iBACA,KAAA7X,QAI/B,WACEG,KAAKw0K,SAAWx0K,KACbyD,aACAid,SACAxY,GAAGlI,KAAK0X,eAAexP,IACvBxD,MAEH1E,KAAKH,MAAMS,gBAGb,iBACE,OAAO,G,uCAtBE,IAAiC,qD,wBAAjC,GAAiC,4CAJjC,CACT,OACD,iTD1CH,0BAIE,gCAIA,wBAIF,OAEA,gBACE,6B,gBAMF,Q,MApBE,0BAAmB,yBAKE,yCAIjB,oCAKO,4C,wFEoBN,MAAM,WAAkC,M,sCAAlC,K,wBAAA,GAAyB,4MCnCtC,0BAEI,qCAAa,EAAAyoK,aAAA,MAEf,wBAIF,OAEA,+B,MATI,0BAKA,oCAMA,iC,wEDuBS,I,8BEvBN,MAAM,WAAmC,KAU9C,YAAsBvoK,EACAuI,EACAkzE,EACA5mE,GACpBvV,QAJoB,KAAAU,aACA,KAAAuI,WACA,KAAAkzE,cACA,KAAA5mE,cAZf,KAAAjO,UAAY,OACZ,KAAAqtK,QAAS,EACT,KAAAz7J,YAAa,EACb,KAAAC,UAAW,EAelB,cAIO,WAAW9S,GAChBnG,KAAK00K,oBAAoBvuK,GACzBnG,KAAK20K,cAAgB,IAAI3yC,GAAA,EAAgB77H,EAAM2pB,QAAc,MAGxD,aAAa3pB,GAClBnG,KAAK00K,oBAAoBvuK,GAMpB,mBACL,OAAOnG,KAAKwU,SAGP,MAAM4E,EAAkB,IACzBA,EAASnS,OAAS,IACpBmS,GAAY,MAGdpZ,KAAK0sB,UAAU7qB,SAAS7B,KAAKoH,UAAW,CAAEiS,IAAKD,IAGjD,aACE,MAAO,CACL3S,KAAM/F,KAAKU,EAAE,qCACbkY,UAAU,EACVC,UAAU,EACVzG,KAAM,cACN0G,YAAY,GAIF,S,mDACZ,OAAOxZ,KACJwpE,WACA/5D,KAAK,KACJzP,KAAK20K,cAAcvsK,KAAKpI,KAAK40K,SAC7B50K,KAAK0Z,kBAIX,cACE,OAAOrV,EAAEK,IAAI1E,KAAK60K,UAAW,MAAO,IAGtC,eACE,OAAOxwK,EAAEK,IAAI1E,KAAK60K,UAAW,OAAQ,IAGvC,gBACE,OAAO70K,KAAK0sB,UAAUvmB,MAAMnG,KAAKoH,WAG5B,mBACLpH,KAAK0Z,aAGP,aACE,OAAO1Z,KAAKy0K,OAGP,SAASr7J,GACdpZ,KAAKy0K,QAAS,EAGhB,aACEz0K,KAAK0sB,UAAUrnB,QACfrF,KAAKy0K,QAAS,EAGhB,QACE,MAAMzqK,EAAUhK,KAAKQ,WAAWsG,cAAc+S,cAAc,uCAC5D7P,GAAWA,EAAQuD,QAGrB,UAAU+7D,IAIV,kBAAkBthE,EAA6B8R,IAI/C,YACE,OAAQ9Z,KAAK0sB,UAAUpV,UAGzB,gBAAgBzW,GACd,OAAO,EAOD,oBAAoBsF,GAC1B,IAAIw7G,EAAa,oBACbmzD,EAAiB,CACEl9J,KAAMzR,EAAM2pB,QAAQlY,KACpBglF,iBAAkB,IAAM,OACxBm4E,kBAAmB5uK,EAAMmpD,KAAKylH,kBAC9Bv3J,kBAAoBV,GAAuB3W,EAAMmpD,KAAK9xC,kBAAkBV,GACxEqR,OAAQ,CACN3rB,OAAQ,CACN+C,KAAMo8G,KAK7BpkG,EAAWvd,KAAKi8E,YAAY5D,kBAAkBy8F,GAAgB,GAE9DE,EAAe,CACjBp9J,KAAM5X,KAAKwC,OACX2rB,OAAQ,CACNnjB,KAAM,CAAEzF,KAAMo8G,KAIdn/G,EAASxC,KAAKi8E,YAAY5D,kBAAkB28F,GAAc,GAE9Dh1K,KAAKqV,YAAYb,OAAO+I,EAAU/a,GAElCxC,KAAK0sB,UAAY,IAAI,KAAkBnP,I,uCAnJ9B,IAA0B,2C,0BAA1B,GAA0B,QAA1B,GAA0B,Y,kGCCnC,iB,qBAEI,qC,yBACJ,iB,qBAEI,0C,0BAPN,mBAEE,wBAGA,wBAGF,Q,oBALM,kCAGA,kC,yBAOJ,8B,oBACkB,6BAAsB,0BAAtB,CAAsB,+B,yBAIxC,yB,oBACa,kC,sBAYT,Q,wCALF,iBACK,0EAIH,iCACF,O,kCAJK,oCAAkC,gCAGvB,oC,sBAId,Q,0BADF,QACE,iCACF,Q,6BADgB,oC,mFAZlB,iBAGE,wBAQA,iCAGF,Q,oBAZK,4CACE,sCAQS,wCChBb,MAAM,WAAkC,KAM7C,YAAsBs6C,EACA9uD,EACH+P,EACG60J,EACAl6D,EACAjpF,EACAy6I,GACpBnlK,MAAM+3D,EAAM9uD,GAPQ,KAAA8uD,OACA,KAAA9uD,WACH,KAAA+P,UACG,KAAA60J,MACA,KAAAl6D,eACA,KAAAjpF,SACA,KAAAy6I,SAItB,WACEjlK,KAAKi1K,gBAAe,GAEpBj1K,KACG8Y,QACA67J,cACAx0K,KACCH,KAAKI,iBACL,OAAAmL,GAAA,GAAOpF,GAASA,IAAUnG,KAAKud,SAASuS,QAAc,OACtDzvB,UAAU60K,IACZ,IAAIxoJ,EAAY1sB,KAAKk4D,oBAAoB,CAAEtgD,KAAM,CAAEyB,IAAK67J,KACxDl1K,KAAK83D,gBAAgBtvD,KAAKkkB,KAI9B,YAAYob,GACNA,EAAQvqB,SAAS45C,aAAarnC,QAAQlY,KAAKyB,MAAQrZ,KAAKm1K,iBAC1Dn1K,KAAKi1K,iBAELj1K,KAAK2tK,IAAIrtK,iBAIN,SAAS0H,GAEVhI,KAAKo1K,2CAA2CptK,IAMpDhI,KAAKud,SAAS+xC,KAAK1jB,oBAAoBn8B,KAAK,KAC1CzP,KAAK8Y,QAAQxR,aAIjB,sBACE,OAAOtH,KAAK63D,KAAKz2D,EAAE,sDAGrB,yBACE,IAAIqgB,EAAU,kEAMd,OAJIzhB,KAAKq1K,YACP5zJ,GAAW,iBAGNA,EAGT,aACE,OAAOzhB,KAAK8Y,QAAQtW,OAGtB,gBACE,OAAOxC,KAAK8Y,QAAQ4T,UAGtB,aACE,OAAO1sB,KAAK8Y,QAAQC,OAGtB,gBACE,OAAQ/Y,KAAKm1K,eAAeluK,OAG9B,qBACE,OAAOjH,KAAKilK,OAAOxlH,WAGb,eAAe61H,GAAU,GAC/Bt1K,KAAKu1K,kBACDD,EACFt1K,KAAK8Y,QAAQ9S,WAAWhG,KAAKud,UAE7Bvd,KAAK8Y,QAAQ08J,aAAax1K,KAAKud,UAEjCvd,KAAKy1K,qBAGC,kBACNz1K,KAAKm1K,eAAkBn1K,KAAKud,SAASuS,QAAQlY,KAAqByB,IAG5D,qBACNrZ,KAAK01K,WAAa11K,KAAKyzG,aAAa4B,wBAAwBr1G,KAAK8Y,QAAQ68J,UAGzEroK,WAAW,KACT,IAAoBspI,4BAA4B52I,KAAKwqB,OAAQxqB,KAAK2/C,iBAAiB74C,gBAClF,KAGG,2CAA2CkB,GACjD,OAAOhI,KAAK2/C,iBAAiB74C,cAAcuE,SAASrD,EAAMjB,OAAOC,QAAQ,a,uCA9GhE,IAAyB,sE,wBAAzB,GAAyB,qD,OAAA,K,iFAJzB,CACT,KACD,26BD3BH,0BAEI,qCAAa,EAAA+hK,aAAA,MAEf,wBAIF,OAEA,yCAYA,gBACE,gBACE,oCAKA,+BAKA,uBAeF,OACF,Q,MAjDI,0BAKE,oCAkBgB,8BAKL,8BAKR,iC,6IEpBH,QACE,gBACE,QACA,gCAEF,OACA,gBACE,sCAGF,OACF,Q,uCATI,8BACqB,gCAAoB,4BAIf,2BAAoB,oB,0BAVtD,sBAEE,gBACE,gCAYF,OACF,Q,6BAfW,mBAEO,wCCuCb,MAAM,WAAsC,KAMjD,YAA+BlxG,EACA9uD,EACAtF,EACAiU,EACA7X,GAC7BC,MAAM+3D,EAAM9uD,GALiB,KAAA8uD,OACA,KAAA9uD,WACA,KAAAtF,eACA,KAAAiU,iBACA,KAAA7X,QAPxB,KAAA2W,aAA4C,GAWnD,WACExW,KAAK41K,gBACL51K,KAAKw0K,SAAWx0K,KACbyD,aACAid,SACAxY,GAAGlI,KAAK0X,eAAexP,IACvB4d,mBAGL,iBACE,OAAO,EAGD,gBACNvW,QAAQu0B,IAAI,CACR9jC,KAAK61K,sBAENpmK,KAAK,EAAEjN,MACNxC,KAAKg9G,gBAAgBx6G,KAInB,oBACN,OAAOxC,KACJyD,aACAid,SACAle,OACAkC,MACAmoB,YAGG,gBAAgBrqB,GACtBsN,OAAOmtG,QAAQz6G,GAAQkD,QAAQ,EAAE/D,EAAKu7G,MAChCv7G,EAAIg3D,MAAM,mBACZ34D,KAAKwW,aAAatV,KAAK,CAACS,IAAKA,EAAK2gC,MAAO46E,EAAUz2G,SAIvDzG,KAAKH,MAAMS,iB,uCApDF,IAA6B,qD,wBAA7B,GAA6B,qD,OAAA,K,iFAJ7B,CACT,OACD,6UDnDH,0BAIE,wBAIF,OAEA,gBACE,6B,gBAiBF,Q,MA3BI,0BAAmB,yBAKjB,oCAKO,4C,6FEEN,MAAe,WAAuC,KAqB3D,YAAqByI,EACAs/C,EACAwP,EACAhpD,EACAy8F,EACUqiE,GAC7B7tK,MAAM+3D,EAAM9uD,GANO,KAAAA,WACA,KAAAs/C,WACA,KAAAwP,OACA,KAAAhpD,aACA,KAAAy8F,gBACU,KAAAqiE,MAzBxB,KAAA/1J,KAAO,CACZoZ,SAAUhxB,KAAK63D,KAAKz2D,EAAE,0BACtBimF,QAASrnF,KAAK63D,KAAKz2D,EAAE,yBACrBylB,KAAM7mB,KAAK63D,KAAKz2D,EAAE,uBAClB4H,YAAahJ,KAAK63D,KAAKz2D,EAAE,yBACzB4rB,KAAMhtB,KAAK63D,KAAKz2D,EAAE,kBAClBs0C,OAAQ11C,KAAK63D,KAAKz2D,EAAE,oBACpBmqG,cAAe,CACb3zF,KAAM5X,KAAK63D,KAAKz2D,EAAE,qCAClBkhB,MAAOtiB,KAAK63D,KAAKz2D,EAAE,uCAErBghC,UAAWpiC,KAAK63D,KAAKz2D,EAAE,iDAElB,KAAA67G,QAA8B,GAC7B,KAAAsxD,eAAgB,EACjB,KAAAvvI,KAA+D,GActE,WACEh/B,KACGyD,aACAiyD,aACAtC,KAAK,CAAEpkD,QAAShP,KAAKqrK,YAAa9wH,SAAU,MAC5Cl6C,UAAWsjC,IACV3jC,KAAKmrK,aAAaxnI,EAAWn/B,UAC7BxE,KAAKuuK,eAAgB,EAErBvuK,KAAK2tK,IAAIrtK,kBAIf,YACE,IAAIklG,EAAWxlG,KAAKi9G,QAAQtoG,OAAO,CAAC1U,EAAS8hE,IACpC9hE,EAAUD,KAAKqoD,SAAS67E,QAAQniE,EAAM7uC,OAC5C,GAEH,OAAOlzB,KAAK63D,KAAKz2D,EAAE,gBAAiB,CAAE6yB,MAAOj0B,KAAKysK,aAAajnE,KAGjE,iBACE,QAASxlG,KAAKi9G,QAAQh2G,OAGjB,aAAa86D,GAClB,OAAOA,EAAM/wC,SAASvqB,KAGjB,YAAYs7D,GACjB,OAAOA,EAAMrmD,QAAQjV,KAGhB,gBAAgBs7D,GACrB,MAAO,IAAIA,EAAM/4D,YAAYd,OAAO65D,EAAM/4D,YAAYvC,OAGjD,cAAcs7D,GACnB,OAAOA,EAAM/4D,YAAYd,GAGpB,QAAQ65D,GACb,OAAOA,EAAMslB,SAAWtlB,EAAMslB,QAAQhuE,IAGjC,MAAM0oD,GACX,OAAO/hE,KAAKysK,aAAazsK,KAAKqoD,SAAS67E,QAAQniE,EAAM7uC,QAGhD,gBAAgB6uC,GACrB,OAAO/hE,KAAK6O,WAAWsW,gBAAgB48C,EAAM/4D,YAAYsS,YAG3D,iBACE,OAAO,EAGF,cAAcymD,GACnB/hE,KACGyD,aACAiyD,aACAxtD,GAAG65D,EAAM75D,IACTxD,MACArE,UAAWy1K,IACZ91K,KAAK+1K,qBACF/oJ,KAAK8oJ,GACLrmK,KAAMumK,IACL,IAAIC,EAAuBj2K,KAAKi9G,QAAQn+E,UAAU7sB,GAAMA,EAAG/J,KAAO8tK,EAAaj0G,MAAM75D,IACjFguK,EAAal2K,KAAKi9G,QACtBi5D,EAAWD,GAAiBD,EAAaj0G,MAEzC/hE,KAAKmrK,aAAa+K,KAEnB17J,MAAM,UAMN,kBAAkBxS,EAAa+5D,G,UACpC/5D,EAAMuE,iBACNvM,KAAKsrG,cAAc9/D,QAAQ,CACzB5zB,KAAM5X,KAAK4X,KAAK2zF,cAChBrkD,eAAe,EACfG,WAAW,EACXD,iBAAiB,EACjBJ,WAAW,CACT,KAAuB,QAApB,EAAG+a,EAAM/4D,mBAAW,eAAEsS,YAAa,KAAuB,QAApB,EAAGymD,EAAM/4D,mBAAW,eAAEvC,MAC/DzG,KAAK63D,KAAKz2D,EACR,gBACA,CAAE6yB,MAAOj0B,KAAKqoD,SAAS67E,QAAQniE,EAAM7uC,SAAY,MAAqB,QAAjB,EAAG6uC,EAAM/wC,gBAAQ,eAAEvqB,MAAO,KAEnFqgD,oBAAoB,IACnBr3C,KAAK,KACNsyD,EAAMrsB,SAASjmC,KAAK,KAClB,IAAIymK,EAAal2K,KAAKi9G,QAAQ1xG,OAAQ4qK,GAC7Bp0G,EAAM75D,KAAOiuK,EAAQjuK,IAG9BlI,KAAKmrK,aAAa+K,OAGnB17J,MAAM,QAOH,aAAayiG,GACnBj9G,KAAKi9G,QAAUA,EACf,IAAIm5D,EAAwC,GAE5Cn5D,EAAQv3G,QAASq8D,IACf,IAAI93C,EAAO83C,EAAM86C,QAEZu5D,EAAgBnsJ,KACnBmsJ,EAAgBnsJ,GAAQ,GAG1BmsJ,EAAgBnsJ,GAAQmsJ,EAAgBnsJ,GAAQjqB,KAAKqoD,SAAS67E,QAAQniE,EAAM7uC,SAG9E,IAAImjJ,EAAgBp5D,EAAQ9iF,KAAK,CAACjX,EAAGC,IAC5BA,EAAE05F,QAAQn4E,cAAcxhB,EAAE25F,UAGnC78G,KAAKg/B,KAAO,GACZ,IAAIs3I,EAA0B,KAC9BD,EAAc3wK,QAASq8D,IACjBA,EAAM86C,UAAYy5D,IACpBA,EAAcv0G,EAAM86C,QACpB78G,KAAKg/B,KAAK99B,KAAK,CAAC+oB,KAAMjqB,KAAKqoD,SAASolC,cAAc6oF,GAAe73E,IAAKz+F,KAAKysK,aAAa2J,EAAgBE,OAG1Gt2K,KAAKg/B,KAAK99B,KAAK,CAAC+oB,KAAMqsJ,EAAcv0G,MAAOA,MAKrC,aAAa57D,GACrB,OAAOnG,KAAK63D,KAAKk4D,SAAS5pH,EAAO,CAAE0lH,UAAW,IAGhD,gBACE,OAAQ7rH,KAAKi9G,QAAQh2G,QAAUjH,KAAKuuK,e,yBClLxC,uB,oBACY,gC,yBAoDF,gB,wCAEI,6C,0BAEJ,gBAEE,mBACF,Q,8BADU,oC,0BAEV,gBAEI,QAA8B,eAClC,Q,wCADI,+CAAiC,qDAAoC,2C,yBAEzE,gB,wCAEI,4C,yBAEJ,gB,wCAEI,wC,yBAEJ,gB,wCAEI,sC,0BAEJ,gBAEE,eACF,Q,8BADM,mC,wCAGJ,eACG,mGAED,qBACF,O,wBAFG,2B,wCAGH,eACG,0GAED,qBACF,O,wBAFG,6B,0BArCP,gBACE,uBAIA,uBAIA,uBAIA,uBAIA,uBAIA,uBAIA,uBAIA,gBACE,sBAKA,uBAKF,OACF,Q,yBAvCM,6BAIA,2BAIA,kDAIA,mDAIA,6BAIA,6BAIA,2BAIC,wDAKA,8C,0BA9Eb,gBACE,kBACE,mBACE,iBACA,iBACA,iBACA,iBACA,cACF,OACA,mBACE,aACE,cACE,kBACE,kBACE,kBACF,OACF,OACF,OACA,cACE,kBACE,kBACE,kBACF,OACF,OACF,OACA,cACE,kBACE,kBACE,kBACF,OACF,OACF,OACA,cACE,kBACE,kBACE,kBACF,OACF,OACF,OACA,cAAI,kBAA+C,OACrD,OACF,OACA,iBACE,yBA0CF,OACF,OACF,Q,qBAzEoB,6CAOA,+CAOA,2CAOA,wCAQS,gC,0BAhD/B,QACE,gBACE,YAAG,kBAAO,iBAAmC,OAC/C,OAEA,wBAwFF,Q,oBA3FoB,oCAG4B,mC,uCDN1B,IAA8B,+D,wBAA9B,GAA8B,kBAkBnC,aAAd,c,0BAAmD,K,4CACrC,aAAd,c,0BAA2C,M,oCEpBvC,MAAM,WAA0C,GACrD,YAAqBxlK,EACAs/C,EACAwP,EACAhpD,EACAy8F,EACUqiE,EACAj2J,GAC7B5X,MAAMiJ,EAAUs/C,EAAUwP,EAAMhpD,EAAYy8F,EAAeqiE,GAPxC,KAAA5kK,WACA,KAAAs/C,WACA,KAAAwP,OACA,KAAAhpD,aACA,KAAAy8F,gBACU,KAAAqiE,MACA,KAAAj2J,iBAGrB,YACR,MAAO,CAAC,CAAC,UAAW,MAAO,CAAC,MACpB,CAAC,aAAc,IAAK,CAAC1X,KAAK0X,eAAexP,O,yBCbnD,uB,oBACY,gC,uBAMV,eAAoB,aAAE,Q,0BAJxB,eACE,cAGA,wBACF,Q,2CAJK,2CAA6B,gCAG1B,yB,uCDNG,IAAiC,0E,wBAAjC,GAAiC,moCDZ9C,0BAIE,wBAIF,OAEA,8BAIA,iC,MAbI,0BAAmB,yBAKjB,oCAIM,iCAIE,oC,8DGCP,MAAM,WAAmC,KAO9C,YAAqB+zE,EACAptE,EACAgpD,EACU9uD,EACVs/C,EACA5kD,EACAiU,EACAi2J,GACnB7tK,MAAM+3D,EAAM9uD,GARO,KAAAkzE,cACA,KAAAptE,aACA,KAAAgpD,OACU,KAAA9uD,WACV,KAAAs/C,WACA,KAAA5kD,eACA,KAAAiU,iBACA,KAAAi2J,MAbd,KAAA/1J,KAAO,CACZwqB,UAAWpiC,KAAK63D,KAAKz2D,EAAE,2CAgBzB,WACEpB,KACGyD,aACAid,SACA0yC,KAAKpzD,KAAKu2K,mBACVl2K,UAAWsjC,IACV3jC,KAAK0gB,SAAWijB,EAAWn/B,SAE3BxE,KAAK2tK,IAAIrtK,kBAIf,iBACE,OAAO,EAGF,YAAYob,GACjB,OAAO1b,KAAK6O,WAAWE,YAAY2M,EAAQ5G,YAGtC,YAAY4G,GACjB,OAAOA,EAAQjV,KAGjB,gBACE,OAAOzG,KAAK0gB,WAAa1gB,KAAK0gB,SAASzZ,OAGzC,wBACE,MAAO,CAAEhC,OAAQ,CAAC,CAAC,OAAQ,QAClB+J,QAAS,CAAC,CAAC,YAAa,IAAK,CAAChP,KAAK0X,eAAexP,Q,yBCpD7D,wB,oBACY,gC,0BAWF,QACE,kBACF,Q,wCADQ,2C,0BAER,QACE,yBAGA,eAGF,Q,wCANe,uBAGV,wCAA4B,8B,uBAKjC,QAA4B,aAAE,Q,0BAdhC,eAEE,iCAGA,iCASA,iCACF,Q,4CAbgB,kCAGA,mCASA,yB,0BApBtB,QACE,iBACE,QACF,OAEA,iBACI,wBAgBJ,OACF,Q,yBArBI,kCAIQ,iC,0BAmBd,iBAEE,QACF,Q,oBADE,yC,0BAKF,eAGE,eACA,kBAGF,Q,oBANG,oEAIK,wC,0BAIR,eAGE,eACA,kBAGF,Q,oBANG,2CAIK,4C,uCD9CG,IAA0B,oF,wBAA1B,GAA0B,2QDfvC,0BAIE,wBAIF,OAEA,gBACE,8BAGA,wBAMF,Q,MAnBI,0BAAmB,yBAKjB,oCAKQ,iCAGN,qC,sEGID,MAAM,WAA+B,KAY1C,YAAqB2G,EACApL,EACAo0D,EACU9uD,EACV2O,EACAi2J,GACnB7tK,MAAM+3D,EAAM9uD,GANO,KAAA8F,aACA,KAAApL,eACA,KAAAo0D,OACU,KAAA9uD,WACV,KAAA2O,iBACA,KAAAi2J,MAhBd,KAAA/1J,KAAO,CACZpH,IAAKxQ,KAAK63D,KAAKz2D,EAAE,+BACjBghC,UAAWpiC,KAAK63D,KAAKz2D,EAAE,sCACvBo1K,QAASx2K,KAAK63D,KAAKz2D,EAAE,6CAIhB,KAAAq1K,eAA6E,GAC5E,KAAAlI,eAAgB,EACjB,KAAAmI,gBAAyB,EAWhC,WACE12K,KACGyD,aACAkyD,YACAvC,KAAKpzD,KAAK22K,mBACVt2K,UAAUsjC,IACT3jC,KAAK42K,uBAAuBjzI,EAAWn/B,UACvCxE,KAAK62K,kBACL72K,KAAK82K,aAAenzI,EAAWsW,MAE/Bj6C,KAAKuuK,eAAgB,EACrBvuK,KAAK2tK,IAAIrtK,kBAGbN,KAAKyD,aACFkyD,YACAvD,mBACAgB,KAAKpzD,KAAK+2K,6BACV12K,UAAUsjC,IACT3jC,KAAK02K,eAAiB/yI,EAAWsW,MAAQ,IAI/C,iBACE,OAAO,EAGF,SAAS1zC,GACd,OAAOvG,KAAK6O,WAAWuM,SAAS7U,EAAK2B,IAGhC,SAAS3B,GACd,OAAOA,EAAKE,KAGd,gBACE,OAAOzG,KAAKuuK,gBAAkBz+J,OAAOD,KAAK7P,KAAKy2K,gBAAgBxvK,OAGjE,kBACE,OAAOjH,KAAKuuK,eAAiBvuK,KAAK82K,aApEN,IAuE9B,sBACE,OAAOp2K,KAAKU,EACR,mCACA,CAAE6yB,MA1EsB,IA0EUgmB,MAAOj6C,KAAK82K,eAIpD,6BACE,OAAO92K,KAAK6O,WAAWmoK,uBAAuBh3K,KAAK0X,eAAe5C,YAGpE,kBACE,OAAOhF,OAAO8V,OAAO5lB,KAAKy2K,gBAGrB,QAAQQ,GACb,OAAOj3K,KAAKyD,aAAasC,OAAOmC,GAAG+uK,EAAU/uK,IAAKma,aAAe40J,EAAU1xK,KAGrE,uBAAuBowD,GAC7BA,EAAYjwD,QAAQwxK,IAClBA,EAAWC,MAAMzxK,QAAS0xK,IACnBp3K,KAAKy2K,eAAeW,EAAKlvK,MAC5BlI,KAAKy2K,eAAeW,EAAKlvK,IAAO,CAAEkvK,KAAMA,EAAMl2J,MAAO,KAGvDlhB,KAAKy2K,eAAeW,EAAKlvK,IAAKgZ,MAAMhgB,KAAKg2K,EAAWD,eAKlD,kBACNnnK,OAAO8V,OAAO5lB,KAAKy2K,gBAAgB/wK,QAAQq8D,IACzCA,EAAM7gD,MAAMiZ,KAAK,CAACjX,EAAGC,IACZnjB,KAAKw0G,SAAStxF,GAAGwhB,cAAc1kC,KAAKw0G,SAASrxF,OAK1D,wBACE,IAAIjF,EAA6B,CAAEjZ,OAAQ,CAAC,CAAC,aAAc,SAAUs1C,SA/GzC,KAqH5B,OAJIv6C,KAAK0X,eAAexP,KACtBgW,EAAgB,QAAI,CAAC,CAAC,aAAc,IAAK,CAACle,KAAK0X,eAAexP,OAGzDgW,EAGT,kCAGE,IAAIA,EAA6B,GAMjC,OAJIle,KAAK0X,eAAexP,KACtBgW,EAAgB,QAAI,CAAC,CAAC,KAAM,IAAK,CAACle,KAAK0X,eAAexP,OAGjDgW,G,uCA1HE,IAAsB,+D,wBAAtB,GAAsB,62BDlBnC,0BAIE,wBAIF,OAEA,gBACE,8BAGA,gBACE,gCAwBF,OACA,uBAIF,OAEA,gBACE,qBASA,qBAQF,Q,MA/DI,0BAAmB,yBAKjB,oCAKQ,iCAII,sCAyBX,mCAOF,sCASA,oC,+bEzCH,sBACE,gBACE,qCAIF,OACA,gBACE,qCAGF,OACF,Q,oBAZiD,mBAEnB,2BAMA,4BCiCzB,MAAM,WAAqC,KAQhD,YAA+B25C,EACA9uD,EACAtF,EACAiU,EACA7X,GAC7BC,MAAM+3D,EAAM9uD,GALiB,KAAA8uD,OACA,KAAA9uD,WACA,KAAAtF,eACA,KAAAiU,iBACA,KAAA7X,QARxB,KAAAk2I,kBAA2B,UAC3B,KAAAh+H,YAAqB,GAW5B,WACE/X,KAAKw0K,SAAWx0K,KACbyD,aACAid,SACAxY,GAAGlI,KAAK0X,eAAexP,IACvBxD,MAEH1E,KAAKH,MAAMS,gBAGb,iBACE,OAAO,G,uCA3BE,IAA4B,qD,wBAA5B,GAA4B,qD,OAAA,K,iFAN5B,CACT,KACA,KACA,OACD,mdDtDH,0BAIE,gCAIA,wBAIF,OAEA,gBACE,6B,gBAaF,Q,MA3BE,0BAAmB,yBAKE,yCAInB,oCAKS,4C,wFE+HN,MAAM+2K,GACX,YAAYtuK,IAKP,SAAyBA,GAC9B,MAAMkoG,EAAcloG,EAASrE,IAAI,KAC3BmzD,EAAO9uD,EAASrE,IAAI,KAE1BusG,EAAY1xD,SAAS,cAAe,KAElC,IAAI+3H,EAAiB,CAAC,KAAM,UAAW,OAAQ,WAE3CC,EAAkB,IAAI,KAC1BA,EAAgB/mK,IAAI,WAAY,IAAK,CAAC,OACtC+mK,EAAgB/mK,IAAI,SAAU,IAAK,IAEnC,IAAIgnK,EAAgB,CAClB,YAAaF,EACb,QAAWC,EAAgBplH,UAGzBslH,EAAqB,IAAI,KAC7BA,EAAmBjnK,IAAI,cAAe,IAAK,CAAC,OAC5CinK,EAAmBjnK,IAAI,SAAU,IAAK,IAEtC,IAAIknK,EAAmB,CACrB,YAAaJ,EACb,QAAWG,EAAmBtlH,UAG5BwlH,EAAiB,IAAI,KACzBA,EAAennK,IAAI,SAAU,IAAK,CAAC,OACnCmnK,EAAennK,IAAI,SAAU,IAAK,IAElC,IAAIonK,EAAe,CACjB,YAAaN,EACb,QAAWK,EAAexlH,UAGxB0lH,EAAiB,IAAI,KACzBA,EAAernK,IAAI,UAAW,IAAK,CAAC,OACpCqnK,EAAernK,IAAI,SAAU,IAAK,IAElC,IAAIsnK,EAAe,CACjB,YAAaR,EACb,QAAWO,EAAe1lH,UAG5B,MAAO,CACL,CACEr9C,WAAY,yBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,gDACdqxE,WAAY,CACVz6B,WAAYw/H,EACZ/wK,KAAMoxD,EAAKz2D,EAAE,kDAGjB,CACE0T,WAAY,4BACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,mDACdqxE,WAAY,CACVz6B,WAAY0/H,EACZjxK,KAAMoxD,EAAKz2D,EAAE,qDAGjB,CACE0T,WAAY,wBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,+CACdqxE,WAAY,CACVz6B,WAAY4/H,EACZnxK,KAAMoxD,EAAKz2D,EAAE,iDAGjB,CACE0T,WAAY,wBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,+CACdqxE,WAAY,CACVz6B,WAAY8/H,EACZrxK,KAAMoxD,EAAKz2D,EAAE,iDAGjB,CACE0T,WAAY,sBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,6CACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,+CAGjB,CACE0T,WAAY,sBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,6CACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,+CAGjB,CACE0T,WAAY,yBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,gDACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,kDAGjB,CACE0T,WAAY,yBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,gDACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,kDAGjB,CACE0T,WAAY,4BACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,mDACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,mDACbymB,KAAM,EAAC,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,KAG/C,CACE/S,WAAY,uBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,2CACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,6CAGjB,CACE0T,WAAY,YACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,mCACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,qCAGjB,CACE0T,WAAY,UACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,iCACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,mCAGjB,CACE0T,WAAY,OACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,8BACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,gCAGjB,CACE0T,WAAY,sBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,6CACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,+CAGjB,CACE0T,WAAY,cACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,qCACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,qCACbwW,KAAM,CACJyB,IAAK,MAIX,CACEvE,WAAY,kBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,yCACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,2CAGjB,CACE0T,WAAY,iBACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,wCACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,0CAGjB,CACE0T,WAAY,cACZrG,UAAW,GACX6T,MAAOu1C,EAAKz2D,EAAE,qCACdqxE,WAAY,CACVhsE,KAAMoxD,EAAKz2D,EAAE,0CAtMnB22K,CAAgBhvK,I,wBAFPsuK,K,qDAAAA,IAAsB,sBAvCtB,CACTvJ,GACA,IACD,SApCQ,CACP,IACA,IACA,KAEA,IACA,KACA,GACAM,GACAF,GAEA,KAEA,KAAchnB,eAAe,CAC3B,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,KAGF,Q,iBCtEG,MAAM8wB,GAAkB,mBAUxB,MAAMC,I,uCAAAA,K,wBAAAA,GAAwB,sHALjC,gBACE,kBACF,S,0DCAG,MAAMC,GAA2C,CACtD,CACEzxK,KAAM,OACNuH,IAAK,4BACLS,UAAWwpK,GACXE,UAAU,EACVj6J,OAAQ,CAGNnP,YAAa,CAAE+D,KAAM,OAAQ3M,MAAO,KAAMiyK,QAAQ,GAClD13J,SAAU,CAAE5N,KAAM,OAAQ3M,MAAO,KAAMiyK,QAAQ,GAG/CC,cAAe,CAAEC,SAAS,EAAMnyK,MAAO,KAAMuhK,SAAS,KAG1D,CACEjhK,KAAM,YACNiI,OAAQ,OACRV,IAAK,UACLuqK,aAAc,IAAM,kCAA8C9oK,KAAKy8J,GAAKA,EAAEsM,0BAEhF,CACE/xK,KAAM,SACNiI,OAAQ,OACRV,IAAK,OACLuqK,aAAc,IAAM,kCAA0D9oK,KAAKy8J,GAAKA,EAAEuM,6BAE5F,CACEhyK,KAAM,cACNiI,OAAQ,OACRV,IAAK,YACLuqK,aAAc,IAAM,kCAAkD9oK,KAAKy8J,GAAKA,EAAEwM,4BAEpF,CACEjyK,KAAM,qBACNiI,OAAQ,OACRV,IAAK,WACLuqK,aAAc,IAAM,kCAAkD9oK,KAAKy8J,GAAKA,EAAEwM,4BAEpF,CACEjyK,KAAM,eACNiI,OAAQ,OACRV,IAAK,gBACLuqK,aAAc,IAAM,kCAAoD9oK,KAAKy8J,GAAKA,EAAEyM,6BAEtF,CACElyK,KAAM,kBACNiI,OAAQ,OACRV,IAAK,gBACLuqK,aAAc,IAAM,kCAAsD9oK,KAAKy8J,GAAKA,EAAE0M,8BAUnF,SAASC,GAAU92J,EAA0Cg/C,EAAwB,OACtFh/C,IACE7E,MAAM2c,QAAQ9X,GAChBA,EAAUrc,QAASozK,IACjB5tK,SAASwT,KAAKnO,UAAUwwD,GAAQ+3G,KAGlC5tK,SAASwT,KAAKnO,UAAUwwD,GAAQh/C,IAK/B,SAASg3J,GAAeprK,EAAgCozD,EAAwB,OACrF,IAAKpzD,EACH,OAGF,IAAIU,EAAWxH,OAAO,eAAiB8G,GAAe,GAEtD,IAAKU,EACH,OAIFA,EAASkC,UAAUwwD,GAAQ,YAG3B,IAAIi4G,GAAiB3qK,EAAS20B,aAAa,UAAY,IAAI3qB,MAAM,KAAKqM,OAAO,GAAG,GACjE,QAAXq8C,IACFi4G,EAAgBt4K,KAAKU,EAAE,mCAAqC43K,GAG9D3qK,EAASiD,aAAa,QAAS0nK,GC5E1B,MAAM,GACX,YAAYjwK,IDiGP,SAAqCA,GAC1C,MAAM0hB,EAAiC1hB,EAASrE,IAAI,sBAC9Cu0K,EAAelwK,EAASrE,IAAI,iBAC5B9E,EAA4CmJ,EAASrE,IAAI,KACzDgT,EAAuC3O,EAASrE,IAAI,MACpDo8E,EAA+B/3E,EAASrE,IAAI,MAC5C4zD,EAAwCvvD,EAASrE,IAAI,MAI3D,IAAIw0K,EAAShuK,SAAS2O,cAAcm+J,IAWpCvtJ,EAAa0uJ,QAAQ,IAAI,SAAUxhK,EAAuB7G,GAExD+nK,GAAUx0K,EAAEK,IAAIoM,EAAO,oBAAqB,OACxC6G,EAAW4D,OAAOpN,MAAQ9J,EAAEK,IAAIoM,EAAO,mBAAqB6G,EAAW4D,OAAOpN,KAAKE,UACrF0qK,GAAe10K,EAAEK,IAAIoM,EAAO,iBAAkB,OAIhD0P,OAAO42D,SAAS,EAAG,MAGrB3sD,EAAa2uJ,OAAO,IAAI,SAAUzhK,EAAuB7G,GAEvD+nK,GAAUx0K,EAAEK,IAAIoM,EAAO,oBAAqB,UACxC6G,EAAWyb,KAAKjlB,MAAQ9J,EAAEK,IAAIoM,EAAO,mBAAqB6G,EAAWyb,KAAKjlB,KAAKE,UACjF0qK,GAAe10K,EAAEK,IAAIoM,EAAO,iBAAkB,aAIlD2Z,EAAaK,QAAQ,IAAI,SAAUnT,GACjC,MAAMF,EAASE,EAAW0hK,OAAOJ,aAC3BnoH,EAAWn5C,EAAWuG,OAAO,MAE7Bw8F,GADY/iG,EAAW4D,OACb5D,EAAWyb,MAG3B,GAAI09B,EAASwoH,uBAA0C,mCAAjB5+D,EAAQj0G,KAA2C,CACvF,MAAM8yK,EAAazpK,OAAOoG,OAAO,GAAIyB,EAAWuG,UAEhD,OADAq7J,EAAWD,2BAAwB5tK,EAC5B+L,EAAO1Q,OAAO4Q,EAAWyb,KAAMmmJ,GAIxCjhH,EAAmBkhH,KAAK7hK,GAGxB,MAAM8hK,EAAgBj5J,OAAek5J,aACrCD,GAAYA,EAASE,iBAErB,MAAM7qK,EAAoBgiD,EAAS/hD,aAAe2I,EAAe5C,WACjE,IAAKg8C,EAASpwC,UAAY5R,EAAmB,CAC3C,MAAM26F,EAAYplG,EAAE6iB,MAAM4pC,GAE1B,OADAzsD,EAAE6R,OAAOuzF,EAAW,CAAE16F,YAAaD,EAAmB4R,SAAU,aACzDjJ,EAAO1Q,OAAO2zG,EAASjR,EAAW,CAAEjhE,SAAU,YAWvD,GAAe,OAAX0wI,EAAiB,CAGnB,MAAM19J,EAAOgF,OAAOgoB,SAASoxI,SACvBC,EAAiBr+J,EAAOgF,OAAOgoB,SAASnG,OACxCt7B,EAASkyK,EAAa1zK,KAAKm1G,EAAS5pD,GAE1C,GAAI/pD,GAAUyU,IAASzU,GAAU8yK,IAAmB9yK,EAElD,OADAyZ,OAAOgoB,SAASjjC,KAAOwB,GAChB,EAuBX,OAjBA8xK,GAAUx0K,EAAEK,IAAIg2G,EAAS,oBAAqB,OAK9C55B,EAAWg5F,WAAWp/D,EAAQj0G,KAAMqqD,GAGhCn5C,EAAWyb,KAAK3sB,OAASkR,EAAW4D,OAAO9U,MAC7C7G,EAAqByF,QAInByrD,EAASunH,eACXz4K,EAAqB4Q,IAAIsgD,EAASunH,gBAG7B,KC3MP0B,CAA4BhxK,I,wBAFnB,K,qDAAA,IAAuB,sBAPvB,CACT,MACD,SATQ,CACP,kBAAeixK,QAAQ,CACrBr3K,OAAQu1K,GACR+B,SAAS,EACTtmK,ODyFC,SAA+BumK,EAAmBnxK,EAAmBgH,GAE1EmqK,EAASC,WAAWxmK,OAAOymK,YAAW,GAItCF,EAASC,WAAWxmK,OAAOb,KACzB,gBACA,CACEunK,OAAQ9mG,mBACR+mG,OAAQ93H,mBACRnpC,KAAK,EACLi/J,SAAS,EACT7yI,GAAK7jC,GAAiC,iBAAV,EAC5B24K,OAAQ,CAACr3J,EAAOC,IAAU9e,EAAEgT,QAAQ6L,EAAGC,Y,sIEzGtC,MAAM,GAAgB,0BAEhBq3J,GAA6C,CACxD,CACE/zK,KAAM,gBACNiI,OAAQ,OACRD,UAAW,KACXT,IAAK,4DACLC,WAAY,iCACZE,KAAM,CACJC,YAAa,6BACbC,SAAU,IAEZ6P,OAAQ,CACNopB,SAAU,CAAEx0B,KAAM,QAASwlK,SAAS,GAEpCz0I,YAAa,CAAE/wB,KAAM,iBAErBwmK,sBAAuB,CAAExmK,KAAM,QAASslK,QAAQ,EAAMjyK,WAAOuF,KAGjE,CACEjF,KAAM,oBACNuH,IAAK,sBACLS,UAAW,KACXP,gBAAgB,EAChBC,KAAM,CACJT,UAAW,gBACXiB,uBAAuB,EACvBP,YAAa,oCACbC,SAAU,KAGd,CACE5H,KAAM,qBACNuH,IAAK,yCACLS,UAAW,KACXP,gBAAgB,EAChBC,KAAM,CACJT,UAAW,gBACXiB,uBAAuB,EACvBP,YAAa,oCACbC,SAAU,KAGd,CACE5H,KAAM,qBACNuH,IAAK,0BAELC,WAAY,8BACZQ,UAAW,KACXN,KAAM,CACJT,UAAW,gBACXU,YAAa,kCACbE,SAAU,oBACVD,SAAU,KAGd,CACE5H,KAAM,8BACNuH,IAAK,YACLS,UAAW,KACXN,KAAM,CACJO,OAAQ,qBACRL,SAAU,KAGd,CACE5H,KAAM,sCACNuH,IAAK,sCACLS,UAAW,KACXN,KAAM,CACJO,OAAQ,qBACRL,SAAU,KAGd,CACE5H,KAAM,+BACNuH,IAAK,aACLS,UAAW,KACXN,KAAM,CACJO,OAAQ,qBACRL,SAAU,KAGd,CACE5H,KAAM,8BACNuH,IAAK,YACLS,UAAW,KACXN,KAAM,CACJO,OAAQ,qBACRL,SAAU,KAGd,CACE5H,KAAM,4BACNgI,UAAW,KACXT,IAAK,GACLG,KAAM,CAEJC,YAAa,KAGjB,CACE3H,KAAM,iCACNuH,IAAK,GACLE,gBAAgB,EAChBM,MAAO,CACL,eAAgB,CAAEC,UAAW,OAE/BN,KAAM,CACJC,YAAa,+CACbC,SAAU,GACVE,UAAW,kBAGZ,aACD,iCACA,GACA,OC/GG,MAAMksK,I,wBAAAA,K,qDAAAA,KAAkC,SARpC,CAEP,KAGA,kBAAepM,SAAS,CAAE1rK,OAAQ63K,SCV/B,MAAM,GAoBX,YAAsB95K,EACAqI,EACA2R,EACAggK,GAHA,KAAAh6K,OACA,KAAAqI,WACA,KAAA2R,aACA,KAAAggK,wBAtBd,KAAAC,YAAc,IAAI34C,GAAA,EAAwB,IAC3C,KAAA44C,YAAc56K,KAAK26K,YAAY9yK,eAI9B,KAAAgzK,YAAc,IAAI74C,GAAA,EAAqB,OACxC,KAAA84C,YAAc96K,KAAK66K,YAAYhzK,eAG9B,KAAAkzK,cAAgB,IAAI/4C,GAAA,EAAqB,IAC1C,KAAAg5C,cAAgBh7K,KAAK+6K,cAAclzK,eAElC,KAAAmK,MAAQ,IAAIgwH,GAAA,EAAqB,IAClC,KAAAi5C,MAAQj7K,KAAKgS,MAAMnK,eAGlB,KAAAqzK,eAAiB,IAAIl5C,GAAA,GAAqB,GAC3C,KAAAm5C,eAAiBn7K,KAAKk7K,eAAerzK,eAM1C7H,KAAKgG,aAGC,aACN,IAAI+5B,EAAc//B,KAAKo7K,cACnBr7I,IACEA,EAAYs7I,wBACdr7K,KAAKgS,MAAM5J,KAAK23B,EAAYs7I,wBAE1Bt7I,EAAYu7I,aACdt7K,KAAK26K,YAAYvyK,KAAK23B,EAAYu7I,aAEhCv7I,EAAYw7I,aACdv7K,KAAK66K,YAAYzyK,KAAK23B,EAAYw7I,aAGhCx7I,EAAYy7I,cACdx7K,KAAK+6K,cAAc3yK,KAAK23B,EAAYy7I,eAC1Bx7K,KAAK06K,sBAAsBl/J,MACrCxb,KAAK+6K,cAAc3yK,KAAK,QAKtB,cAIN,IACE,OAAQoY,OAAe43C,IAAIqjH,cAC3B,MAAOnvK,GACP,OAAO,MAIJ,eACLkU,OAAOgoB,SAASjjC,KAAOvF,KAAK07K,aAGvB,aACL,IAAIA,EAAoB17K,KAAK0a,WAAW6wD,WAKxC,OAJIvrE,KAAK06K,sBAAsBl/J,MAA8B,QAAtBxb,KAAK27K,eAC1CD,EAAa17K,KAAK06K,sBAAsBl/J,MAE1CkgK,EAAaA,EAAa,WAAW17K,KAAK47K,oBACnCF,EAGT,eAAsB7zG,GACpB7nE,KAAK26K,YAAYvyK,KAAKy/D,GAGxB,iBACE,OAAO7nE,KAAK26K,YAAYx0K,MAG1B,WACE,OAAOnG,KAAKgS,MAAM7L,MAGpB,iBACE,OAAOnG,KAAK66K,YAAY10K,MAG1B,eAAsBq/D,GACpBxlE,KAAK66K,YAAYzyK,KAAKo9D,GAGxB,mBACE,OAAOxlE,KAAK+6K,cAAc50K,MAG5B,iBAAwBA,GACtBnG,KAAK+6K,cAAc3yK,KAAKjC,GAG1B,oBACE,OAAOnG,KAAKk7K,eAAe/0K,MAG7B,kBAAyBA,GACvBnG,KAAKk7K,eAAe9yK,KAAKjC,GAGnB,oBACN,IAAI+X,EAWJ,OATAA,EAAS,KAAKq1D,mBAAmBvzE,KAAK6nE,YAElC7nE,KAAKulE,WAAWt+D,OAAS,GAAyB,QAApBjH,KAAKulE,YAA2C,kBAApBvlE,KAAKulE,aACjErnD,EAAS,GAAGA,KAAUle,KAAKulE,gBAEzBvlE,KAAK27K,aAAa10K,OAAS,IAC7BiX,EAAS,GAAGA,WAAgBle,KAAK27K,gBAG5Bz9J,EAGF,gBACL,OAAQrX,OAAO,0BAA0BI,OAAS,G,uCA5HzC,IAAmB,2C,0BAAnB,GAAmB,QAAnB,GAAmB,YCkBzB,MAAM40K,I,wBAAAA,K,qDAAAA,KAA6B,UAX7B,CACT,IACD,SANQ,CACP,IACA,S,8BClCG,MAAM,WAA0B,KAErC,YAAwCngG,EACpB4vB,EACA5qG,GAClBZ,MAAM47E,GAHgC,KAAAA,kBACpB,KAAA4vB,gBACA,KAAA5qG,OAIpB,iBACEV,KAAKsrG,cAAc9/D,QAAQ,CACzB5zB,KAAM,CACJ0K,MAAOtiB,KAAKU,KAAKU,EAAE,2CACnBwW,KAAM5X,KAAKU,KAAKU,EAAE,gDAClBulD,gBAAiB3mD,KAAKU,KAAKU,EAAE,8CAC7BwlD,cAAe5mD,KAAKU,KAAKU,EAAE,0CAE5BqO,KAAK,KACN+Q,OAAOgoB,SAASjjC,KAAO,qI,uCAjBhB,IAAiB,KAER,MAAQ,sB,0BAFjB,GAAiB,QAAjB,GAAiB,Y,gGCiCtB,uCAC2B,qFAA+C,2FAG1E,O,iCAD2B,iB,wCAE3B,mCACuB,4FAA8B,2FAGrD,O,iCADuB,iB,0BATzB,QACE,8CAKA,0CAKF,Q,yBAV6B,0CAKJ,uC,yBAsBnB,kB,qBAEM,yC,0BARV,iBAGE,kBACA,kBACI,QACF,yBAIF,OACF,Q,yBATK,uBAGC,oCACI,8BCpCX,MACMu2K,GAAiB,UASvB,MAAM,WAAuC,KA0BlD,YAAoBt7K,EACAE,EACAq7K,EACA/7C,EACA10B,EACA1rG,EACAo8K,GAClBl8K,QAPkB,KAAAU,aACA,KAAAE,OACA,KAAAq7K,MACA,KAAA/7C,UACA,KAAA10B,gBACA,KAAA1rG,uBACA,KAAAo8K,wBA9Bb,KAAApkK,KAAO,CACZqkK,iBAAkBj8K,KAAKU,KAAKU,EAAE,uCAC9BuY,MAAO3Z,KAAKU,KAAKU,EAAE,wCACnB86K,YAAal8K,KAAKU,KAAKU,EAAE,kBACzB+6K,UAAWn8K,KAAKU,KAAKU,EAAE,gCACvBg7K,eAAgBp8K,KAAKU,KAAKU,EAAE,+BAC5Bi7K,aAAcr8K,KAAKU,KAAKU,EAAE,mCAC1Bk7K,UAAWt8K,KAAKU,KAAKU,EAAE,gCACvBm7K,UAAWv8K,KAAKU,KAAKU,EAAE,iCAQlB,KAAA2E,OAAqB,GACrB,KAAAy2K,UAAgC,GAiBvC,WAEEx8K,KAAK4vB,QAAU5vB,KAAKQ,WAAWsG,cAC/B9G,KAAKy8K,gBAAkBz8K,KAAK4vB,QAAQnf,QAAQisK,cAC5C18K,KAAKoE,KAAOyC,OAAO7G,KAAK4vB,SAAS5oB,QAAQ,QACzChH,KAAKua,OAASva,KAAKoE,KAAKoH,KAAK,6BAK7B,IAAImxK,GAAY,EAEhB38K,KAAKoE,KAAKwF,GAAG,SAAW5B,IACtB20K,GAAY,IAId38K,KAAKua,OAAO3Q,GAAG,YAAc5B,IAC3BsF,WAAW,KACJqvK,GACH38K,KAAKoE,KAAK4F,QAAQ,WAEnB,KACI,IAIThK,KAAKoE,KAAKwF,GAAG,yBAA0B,KACrC5J,KAAK48K,sBACE,IAIT58K,KAAK68K,YAAc78K,KAChBggI,QACAI,YAAY,SAAU,CACrB3/E,MAAO,CAACxuC,EAAIzK,EAAQmwB,IAAuBA,EAAOpnB,UAAUlF,SAAS,kBAEtEm1H,MAGHxgI,KAAK88K,eAAiB98K,KACnBggI,QACAI,YAAY,aAAc,CACzB3/E,MAAO,CAACxuC,EAAIzK,EAAQmwB,IAAuBA,EAAOpnB,UAAUlF,SAAS,sBAEtEm1H,MAGHxgI,KAAK+F,OAAS0f,KACXvG,MAAMlf,KAAK4vB,QAAQnf,QAAQssK,cAC3BxxK,OAAQsJ,IAAoBA,aAAK,EAALA,EAAOlT,OAAQm6K,IAC9C97K,KAAKw8K,UAAY/2J,KAAKvG,MAAMlf,KAAK4vB,QAAQnf,QAAQusK,oBAGjD,MAAM/xJ,EAAOjrB,KACbA,KAAKugI,WAAa,IAAI,KACpB,CACEr1H,SAASC,eAAe,oBAE1B,CACEkqE,OAAQ,GACRD,SAAU,GACVD,mBAAmB,EACnBG,WAAY,WACV,MAAMvvE,EAASklB,EAAK4xJ,aAAe5xJ,EAAK4xJ,YAAYp8C,SAC9Cx4E,EAAah9B,EAAK6xJ,gBAAkB7xJ,EAAK6xJ,eAAer8C,SAE9D,OAAO16H,GAAUkiD,KAKzB,kBACE,MAAM/8B,EAAOrkB,OAAO7G,KAAKQ,WAAWsG,eAAe0E,KAAK,kBACxD,aAAmB0f,GAGd,oBAAoBjI,GACzBjjB,KAAKi9K,gBAAgBj9K,KAAKw8K,UAAUnzJ,OAAOpG,IAGtC,uBACL,IAAIi6J,EAAWl9K,KAAKogI,YAAY,SAChCpgI,KAAKm9K,UAAUD,GAGV,UAAUroK,GAEf,MAAM9C,EAAe,CACnB,mBAAoBrR,KAAKU,EAAE,8DAC3B,UAAaV,KAAKU,EAAE,+DAGtBpB,KAAKg8K,sBAAsBj7K,KAAK,CAC9B84D,aAAcp0C,KAAKvG,MAAMrK,EAAMhR,OAC/BkJ,SAAWirC,GAAmBnjC,EAAMhR,MAAQ4hB,KAAKC,UAAUsyB,GAC3DjmC,iBAIG,YAAY8C,GAOjB,MANmB,cAAfA,EAAM/B,MACR9S,KAAKi9K,gBAAgBj9K,KAAKw8K,UAAUnzJ,OAAOxU,EAAMozC,aAGnDjoD,KAAK+F,OAAS/F,KAAK+F,OAAOwF,OAAO0G,GAAMA,IAAO4C,GAEvCA,EAGF,YAAY/B,EAAoB65E,EAAmB,IACxD,IAAI93E,EAAkB,CACpB/B,KAAMA,EACNrM,KAAM,GACN9E,IAAK,KACLkC,MAAO7D,KAAKy8K,gBACZx0H,WAAY,IAId,OADAjoD,KAAK+F,OAAO2oC,QAAQ75B,GACbA,EAGF,eAAe02B,GAkBpB,OAjBAvrC,KAAKsrG,cACF9/D,QAAQ,CACP5zB,KAAM,CACJ0K,MAAOtiB,KAAKU,KAAKU,EAAE,yCACnBwW,KAAM5X,KAAKU,KAAKU,EAAE,2CAClBulD,gBAAiB3mD,KAAKU,KAAKU,EAAE,qBAGhCqO,KAAK,KACJzP,KAAKoE,KAAKoH,KAAK,+BAA+B5J,IAAI6jB,KAAKC,UAAU,KAGjE1lB,KAAKoE,KAAK+lC,IAAI,0BACdnqC,KAAKoE,KAAK4F,QAAQ,YAGtBuhC,EAAOh/B,kBACA,EAGD,gBAAgBimC,GACtBxyC,KAAKw8K,UAAY,IAAIhqI,GAAUrY,KAAK,CAACjX,EAAGC,IAAMD,EAAEisG,YAAYzqF,cAAcvhB,EAAEgsG,cAO9E,iBACE,MAAO,CAAEr8G,KAAM,YAAanR,IAAKm6K,GAAgBr1K,KAAM,QAASwhD,WAAY,IAGtE,qBACN,MAAMm1H,EAAcp9K,KAAKoE,KAAKoH,KAAK,kCACR,IAAvBxL,KAAK+F,OAAOkB,OAGdm2K,EAAYx7K,IAAI6jB,KAAKC,UAAU,CAAC1lB,KAAKq9K,cAErCD,EAAYx7K,IAAI6jB,KAAKC,UAAU1lB,KAAK+F,U,wCCjP1C,gBACM,iEAGN,O,uBAFM,4B,wCAGN,oBAMI,wEAAwB,2DAAxB,CAAwB,6DAAxB,CAAwB,qEAN5B,O,uBAMI,6BACA,mC,uCD6BS,IAA8B,0E,wBAA9B,GAA8B,6DAJ9B,CACT,KACD,s4CDvCH,gBACE,gBACE,eACE,eACE,mBAEQ,iCAAS,EAAAu3K,eAAA,MACf,oBACA,iBACF,OACF,OACA,eACE,cACE,oBACA,kBACA,sBACF,OACA,iBACE,cACE,gBAEG,0CAAmB,EAAAl9C,YAAY,YAAa,OAC/C,OACF,OACA,cACE,gBAEG,0CAAmB,EAAAm9C,0BACtB,OACF,OACF,OACF,OACF,OACF,OACF,OAEA,kBACE,kBACE,kBAA4C,4DAC1C,kCAYF,OACF,OACA,kBACE,kBACE,kBACE,mBACA,aACA,mBACF,OACA,kBAA6C,+DAC3C,yBAYF,OACF,OACF,OACF,Q,MApEqC,yCAMA,+CAMtB,6CAMA,6CAYiC,sCAC5B,iCAiBa,kDAEJ,oDAEsB,yCACtC,sC,kBGjBN,MAAM,GAUX,YAAoBvqI,EACWnzC,GADX,KAAAmzC,gBACW,KAAAnzC,QAVf,KAAA2vB,YAAqB,GAGpB,KAAAguJ,cAAgB,IAAI,IAE9B,KAAA3+I,SAAU,EAQjB,WACE7+B,KAAKy9K,WAAaz9K,KAAKyG,KAElBzG,KAAKyG,MAA6B,IAArBzG,KAAKyG,KAAKQ,QAE1BjH,KAAK4xC,eAIT,eACE5xC,KAAKgzC,cAAcz7B,YACjB,IAAMvX,KAAKgzC,cAAc0qI,iBACzB,KACE19K,KAAK6+B,SAAU,IAKrB,YAAY72B,GAaV,OAZAhI,KAAK29K,mBACL39K,KAAKyG,KAAOzG,KAAKy9K,WAAWr8I,OAE5BphC,KAAKH,MAAMS,gBAEO,KAAdN,KAAKyG,MACPzG,KAAKw9K,cAAch1K,KAAKxI,KAAKyG,MAI/BuB,EAAMuE,iBACNvE,EAAM6E,mBACC,EAGT,QACE7M,KAAK6+B,SAAU,EACf7+B,KAAKy9K,WAAaz9K,KAAKyG,KAGzB,mBAEyB,MAAnBzG,KAAKy9K,YAAsBz9K,KAAKy9K,WAAWr8I,OAAOn6B,OAAS,IAC7DjH,KAAK6+B,SAAU,I,yBCnFb,kB,qBAEM,yC,wCARV,gBAGE,iBACA,iBACE,QACA,yBAIF,OACA,kBAAqD,yFAAqC,OAC5F,O,4BAVK,uBAGD,oCAEM,8B,uCD0BD,IAAyB,qB,wBAAzB,GAAyB,qkBD5CtC,uBAKA,0B,MALK,wBAOD,iC,uEGEG,MAAM,GAUX,YAAoBn+B,EACAb,GADA,KAAAa,OACA,KAAAb,QARH,KAAA+9K,YAAc,IAAI,IAClB,KAAAC,gBAAkB,IAAI,IAEvC,KAAAjmK,KAAO,CACLykK,aAAcr8K,KAAKU,KAAKU,EAAE,oCAO5B,OAAOoxC,GACLxyC,KAAK6U,MAAMpO,KAAO+rC,SACXxyC,KAAK6U,MAAMlT,IAClB3B,KAAKH,MAAMS,gBAGb,gBAAgB2iB,GACdjjB,KAAK6U,MAAMozC,WAAajoD,KAAK6U,MAAMozC,WAAW18C,OAAO2X,GAAKA,IAAMD,GAChEjjB,KAAK69K,gBAAgBr1K,KAAKya,I,uCAtBjB,IAA+B,sB,wBAA/B,GAA+B,gvBDT5C,gBACE,gBACE,iBACA,gCAEI,yCAAiB,EAAA66J,OAAA,MAErB,OACA,iBAAiD,gCAAS,EAAAF,YAAA,UAAoB,OAChF,OACA,gBAA6C,sEAC3C,uBAaF,OACF,Q,MArBQ,kCAMuC,gDACtC,6C,mEEHF,MAAM,GAUX,YAAoBl9K,EACAb,GADA,KAAAa,OACA,KAAAb,QATpB,KAAA+X,KAAO,CACLmmK,WAAY/9K,KAAKU,KAAKU,EAAE,kCAIT,KAAA+7K,UAAY,IAAI,IAChB,KAAAS,YAAc,IAAI,IAMnC,OAAOprI,GACLxyC,KAAK6U,MAAMpO,KAAO+rC,EAClBxyC,KAAKH,MAAMS,iB,uCAhBF,IAA2B,sB,wBAA3B,GAA2B,0eCRxC,gBACI,gBACI,iBACA,gCAEQ,yCAAiB,EAAAw9K,OAAA,MAEzB,OACA,iBAAiD,gCAAS,EAAAF,YAAA,UAAoB,OAClF,OACA,gBACI,iBAAiD,gCAAS,EAAAT,UAAA,UACxD,oBACE,QACJ,OACJ,OACJ,Q,MAZgB,kCASJ,0C,0ECDL,MAAMa,GAWX,YAAoBx9K,EACAE,EACAb,EACAs4C,EACA8lI,GAJA,KAAAz9K,aACA,KAAAE,OACA,KAAAb,QACA,KAAAs4C,kBACA,KAAA8lI,gBAZpB,KAAA9yH,WAAoB,EAIpB,KAAAvzC,KAAO,CACLmmK,WAAY/9K,KAAKU,KAAKU,EAAE,kCAU1B,WACE,MAAMwuB,EAAU5vB,KAAKQ,WAAWsG,cAChC9G,KAAKkI,GAAK0nB,EAAQnf,QAAQvI,GAC1BlI,KAAKyG,KAAOmpB,EAAQnf,QAAQhK,KAC5BzG,KAAKmrD,UAA0C,SAA9Bv7B,EAAQnf,QAAQ06C,UAEjCnrD,KAAKg4C,WAAapoB,EAAQnf,QAAQ5M,MAG7B,YACL,IAAIm0C,EAAiBh4C,KAAKg4C,WAE1B,IAAKh4C,KAAKmrD,UACR,IACEnT,EAAavyB,KAAKvG,MAAMlf,KAAKg4C,YAC7B,MAAO1rC,GACPsR,QAAQoB,MAAM,oCAAoChf,KAAKg4C,eAAe1rC,KACtE0rC,EAAa,GAIjBh4C,KAAKi+K,cAAcl9K,KAAK,CACtB84D,aAAc7hB,EACdmT,UAAWnrD,KAAKmrD,UAChBp+C,SAAWirC,IACTh4C,KAAKg4C,WAAah4C,KAAKmrD,UAAYnT,EAAavyB,KAAKC,UAAUsyB,GAC/Dh4C,KAAKH,MAAMS,oB,uCA5CN09K,IAA2B,qD,wBAA3BA,GAA2B,sMCZxC,kBAIA,cAEE,0CAAmB,EAAAb,eAEa,Q,MAL3B,2BAFA,4BAA+B,mBAMpC,4CAAiC,mC,sDC+C5B,MAAMe,I,wCCtCP,gBACK,mFAIL,O,4BAHK,wBAAwB,wB,yBAK7B,+B,oBACmB,uCAAgC,mC,wBD8B5CA,K,qDAAAA,KAAsB,UAVtB,GACV,SANQ,CACP,KAAclE,UACd,IACA,S,KAOA,GAA8B,4fAF9B,GACA,GACA,GACA,GACAgE,IAA2B,oEEvCxB,MAAM,WAA2B,IAYtC,YAAqBx9K,EAC4BsR,EAC5BjS,EACAs+K,EACAtmH,EACA7kB,GACnBlzC,MAAMgS,EAAQjS,EAAOW,GANF,KAAAA,aAC4B,KAAAsR,SAC5B,KAAAjS,QACA,KAAAs+K,iBACA,KAAAtmH,OACA,KAAA7kB,gBAfrB,KAAAp7B,KAAO,CACL0K,MAAOtiB,KAAK63D,KAAKz2D,EAAE,sBACnBylD,YAAa7mD,KAAK63D,KAAKz2D,EAAE,mBACzBoyC,YAAaxzC,KAAK63D,KAAKz2D,EAAE,uBACzBg9K,YAAap+K,KAAK63D,KAAKz2D,EAAE,wBAIpB,KAAAyV,eAAgB,EAWvB,WACE/W,MAAMqkB,WACNnkB,KAAK6W,cAAgB7W,KAAKgzC,cAAcn8B,cAG1C,iBACE,OAAO7W,KAAKq+K,gBAAgBlkJ,KAAK,CAACjX,EAAGC,IAC5BD,EAAEZ,MAAMoiB,cAAcvhB,EAAEb,QAI5B,OAAOipB,EAAYtF,GACxBjmC,KAAKs+K,aAAer4I,EACpBjmC,KAAKsnD,QAAQ/b,GAGR,cAActF,GACnB,OAAOA,EAAOnxB,WAGhB,sBACE,IAAIypK,EAA0Bv+K,KAAK8R,OAAOtP,OAAOktD,QAAQ1qD,cAAckK,IAAK+2B,GACnEA,EAAOnxB,YAGhB,OAAO9U,KAAKm+K,eAAeK,WAAWjzK,OAAQ06B,GACrCs4I,EAAwB3lK,SAASqtB,EAAOnxB,c,uCA/CxC,IAAkB,eAaT,KAAkB,0C,wBAb3B,GAAkB,2yBDZ/B,gBACE,gBAGE,gBACE,cACE,cAEI,iCAAS,EAAAwyC,QAAA,MAEb,OACF,OACA,eACF,OAEA,gBACE,uBAOA,qCAMF,OACF,OACF,Q,MAtBY,yCAGkC,yCAInC,qCAAwD,gCAO1C,uC,8CEjBlB,MAAMm3H,GACX,YAAoBxZ,GAAA,KAAAA,SAEb,KAAKyZ,EAA+BC,GACzC,IAAIC,EAA8B,GAC9BC,EAAkC7+K,KAAKilK,OAAOxC,YAAY/9I,MAAM,GAYpE,IAVIi6J,IACFE,EAAiBA,EAAetzK,OAAQg3J,GAC/BA,EAAKpyB,OAASwuC,EAAWxuC,OAIpC0uC,EAAe1kJ,KAAK,CAACjX,EAAGC,IACfA,EAAE44D,SAAW74D,EAAE64D,UAGH,OAAd2iG,GACLE,EAAW19K,KAAKw9K,GAEhBG,EAAiBA,EAAetzK,OAAQg3J,GAC/BA,EAAKpyB,OAASuuC,EAAWvuC,MAGlCuuC,EAAY1+K,KAAK8+K,YAAYF,EAAYC,GAIrC,YAAYE,EAA8BC,GAChD,IAAIC,EAAoBj/K,KAAKk/K,gBAAgBH,EAAaC,GAE1D,GAAIC,EAAmB,CACrB,IAAIE,EAAaF,EAAkB,GAC/BG,EAAaH,EAAkB,GAE/BI,EAAaF,EAAWl5I,OAAO/T,OASnC,OAPAitJ,EAAWpjG,SAAWqjG,EAAWtjG,OACjCqjG,EAAWrjG,OAASqjG,EAAWpjG,SAAWsjG,EAEtCr/K,KAAKilK,OAAOhD,QAAUkd,EAAWrjG,OAAS,IAC5C97E,KAAKilK,OAAOhD,QAAUkd,EAAWrjG,OAAS,GAGrCqjG,EAEP,OAAO,KAeH,gBAAgBJ,EAA8BC,GACpD,IAAIM,EAAsC,KACtCH,EAAiC,KAgBrC,GAdAH,EAAat5K,QAAS65K,IACpBR,EAAYr5K,QAAS05K,IACnB,GAAIA,EAAWI,SAASD,GAGtB,OAFAD,EAAkBF,OAClBD,EAAaI,OAUA,OAAfJ,EAAqB,CACvB,IAAIM,EAAgBH,EAQpB,OANAP,EAAYr5K,QAAS05K,IACfA,EAAWtjG,OAAS2jG,EAAc3jG,QAAUqjG,EAAYtd,eAAeud,KACzEK,EAAgBL,KAIb,CAACD,EAAYM,GAEpB,OAAO,M,uCA1FAhB,IAAe,W,0BAAfA,GAAe,QAAfA,GAAe,Y,8BCGrB,MAAM,GAMX,YAAqBxZ,EACAhkH,GADA,KAAAgkH,SACA,KAAAhkH,OAEnBjhD,KAAK0/K,kCAGP,cACE1/K,KAAK2/K,uBAAuB5iJ,cAGtB,kCACN/8B,KAAK2/K,uBAAyB3/K,KAC3BilK,OACA9C,gBACAhiK,KAEC,OAAAy/K,GAAA,GAAa,IACb,OAAApmI,GAAA,KACA,OAAAjuC,GAAA,GAAQg3J,GAASviK,KAAK6/K,qBAAuBtd,IAASviK,KAAKilK,OAAOL,MAAMrC,KAAUviK,KAAK8/K,gBAAiB/jG,WAAawmF,EAAKxmF,UAAY/7E,KAAK8/K,gBAAiBlwH,cAAgB2yG,EAAK3yG,eACjLvvD,UAAUkiK,IACVviK,KAAK+/K,WAAWxd,GAEhBviK,KAAKilK,OAAO+a,8BAIV,WAAWzd,GACjBviK,KAAKilK,OAAOgb,WAAWjgL,KAAKkgL,aAC5BlgL,KAAKmgL,oBAAoB5d,GAGnB,oBAAoB6d,GAC1B,IAAKpgL,KAAK8/K,gBACR,OAEF,IAAIO,EAAargL,KAAKkgL,YAOtBlgL,KAAKsgL,wBAAwBF,EAAUpgL,KAAK8/K,iBAE5C9/K,KAAKihD,KAAKi0B,KAAKl1E,KAAK8/K,gBAAiBO,GAGvC,wBACE,QAASrgL,KAAKkgL,YAGT,eAAe3d,GACpB,OAAQviK,KAAK6/K,mBAAqBtd,EAAKzmF,SAAW97E,KAAKilK,OAAOhD,QAAU,EAGnE,UAAUM,GACf,OAAOviK,KAAK6/K,mBAAqB7/K,KAAKkgL,YAAa/vC,OAASoyB,EAAKpyB,KAG5D,UAAUoyB,GACf,OAAOviK,KAAK6/K,oBAAsB7/K,KAAKugL,UAAUhe,GAGnD,kBACE,OAAOviK,KAAKilK,OAAOxlH,WAGd,MAAM8iH,GACXviK,KAAK8/K,gBAAkB,IAAI,GAAevd,EAAKt8H,QAE/CjmC,KAAKwgL,cAAiBt1K,SAAiBC,eAAeo3J,EAAKpyB,MAAMswC,aAAe,EAChFzgL,KAAKkgL,YAAc3d,EAGd,QACLr3J,SAAS2qH,cAAc,IAAIrpC,MAAM,YACjCxsF,KAAKkgL,YAAc,KACnBlgL,KAAK8/K,gBAAkB,KACvB9/K,KAAKilK,OAAOgb,aAGP,OACAjgL,KAAKkgL,cAIVlgL,KAAK8/K,gBAAiBY,iBAAiB1gL,KAAKkgL,aAEvClgL,KAAKkgL,YAAaS,gBACrB3gL,KAAKilK,OAAO7B,4BACZpjK,KAAKilK,OAAOH,qBACZ9kK,KAAKilK,OAAOF,qBAGd/kK,KAAKkgL,YAAc,KACnBlgL,KAAK8/K,gBAAkB,MAGjB,wBAAwBt4K,EAAiBs6J,GAC/CA,EAAK/lF,SAAWv0E,EAAOu0E,SAInBv0E,EAAOu0E,WAAa/7E,KAAKilK,OAAOhD,QAAU,EAC5CH,EAAKhmF,OAAS97E,KAAKilK,OAAOhD,QAAU,EAC3Bz6J,EAAOu0E,SAAW+lF,EAAK77H,OAAO/T,OAASlyB,KAAKilK,OAAOhD,QAAU,EACtEH,EAAKhmF,OAAS97E,KAAKilK,OAAOhD,QAAU,EAEpCH,EAAKhmF,OAASt0E,EAAOu0E,SAAW+lF,EAAK77H,OAAO/T,OAG9C4vI,EAAKlyG,YAAcpoD,EAAOooD,YACtBpoD,EAAOooD,YAAckyG,EAAK77H,OAAO7I,MAAQp9B,KAAKilK,OAAOjD,WAAa,EACpEF,EAAK9lF,UAAYh8E,KAAKilK,OAAOjD,WAAa,EAE1CF,EAAK9lF,UAAYx0E,EAAOooD,YAAckyG,EAAK77H,OAAO7I,O,uCAzH3C,IAAsB,oB,0BAAtB,GAAsB,QAAtB,GAAsB,YCA5B,MAAMwjJ,GAIX,YAAqB3b,EACAhkH,EACAo/E,GAFA,KAAA4kC,SACA,KAAAhkH,OACA,KAAAo/E,OAEd,IAAIkiC,GACJviK,KAAK6gL,cAIV7gL,KAAK6gL,YAAc,KAGfte,EAAKoe,gBAIT3gL,KAAKilK,OAAO7B,4BACZpjK,KAAKilK,OAAOH,qBAEZ9kK,KAAKilK,OAAOF,sBAGP,QACD/kK,KAAK6gL,cACP7gL,KAAKilK,OAAOgb,aACZjgL,KAAK6gL,YAAc,MAIhB,MAAMA,GACX7gL,KAAK6gL,YAAcA,EAEnB,IAAIC,EAAgB9gL,KAAKilK,OAAOrC,UAAUr3J,OAAQg3J,IAEhD,IAAIwe,EAAUxe,EAAKxmF,WAAa/7E,KAAK6gL,YAAa9kG,UACnCwmF,EAAK3yG,aAAe5vD,KAAK6gL,YAAajxH,YAKjDoxH,EAAYze,EAAKxmF,SAAW/7E,KAAK6gL,YAAa9kG,UAClCwmF,EAAK3yG,aAAe5vD,KAAK6gL,YAAajxH,aACtC5vD,KAAKilK,OAAOxC,YAAYxtH,KAAMgsI,GACrBA,EAAUllG,WAAawmF,EAAKxmF,WAElCklG,EAAUjlG,WAAah8E,KAAK6gL,YAAajxH,aAExCqxH,EAAUrxH,aAAe2yG,EAAKvmF,YAEjD,OAAO+kG,GAAWC,IAGrBhhL,KAAKkhL,UAAYJ,EACC5xK,IAAIqzJ,GAAQA,EAAKpyB,MAG9B,OAAOpa,GACP/1H,KAAK6gL,aACP7gL,KAAKilK,OAAO/C,gBACZliK,KAAKkhL,UAAUtoK,SAAS5Y,KAAKilK,OAAO/C,eAAe/xB,QAItDnwI,KAAKilK,OAAOgb,aAEZjgL,KAAK6gL,YAAY/kG,OAAS97E,KAAKilK,OAAO/C,eAAepmF,OACrD97E,KAAK6gL,YAAY7kG,UAAYh8E,KAAKilK,OAAO/C,eAAelmF,UAExDh8E,KAAKihD,KAAKi0B,KAAKl1E,KAAK6gL,YAAa7gL,KAAK6gL,cAGjC,SAASte,GACd,IAAI4e,EAAS5e,EAAKpyB,KAElB,OAAOnwI,KAAK6gL,aAAe7gL,KAAKkhL,UAAUtoK,SAASuoK,GAG9C,UAAU5e,GACf,OAAOviK,KAAK6gL,aAAe7gL,KAAK6gL,YAAY1wC,OAASoyB,EAAKpyB,KAGrD,UAAUoyB,GACf,OAAOviK,KAAKohL,oBAAsBphL,KAAKqhL,UAAU9e,GAGnD,wBACE,QAASviK,KAAK6gL,YAGhB,kBACE,OAAQ7gL,KAAKqgI,KAAKw/C,mBAAqB7/K,KAAKshL,UAG9C,gBACE,OAAOthL,KAAKilK,OAAON,aAAa11I,mB,uCAlGvB2xJ,IAAiB,6B,0BAAjBA,GAAiB,QAAjBA,GAAiB,YCMvB,MAAM,GAIX,YAAqB/mI,EACA9wC,EACAkzE,EACAgpF,EACA5kC,EACAp/E,EACAsgI,EACA1pH,GAPA,KAAAhe,iBACA,KAAA9wC,WACA,KAAAkzE,cACA,KAAAgpF,SACA,KAAA5kC,OACA,KAAAp/E,OACA,KAAAsgI,SACA,KAAA1pH,OATrB,KAAAjgD,KAAO,CAAEpH,IAAKxQ,KAAK63D,KAAKz2D,EAAE,uBAYnB,UAAUmhK,GACf,OAAQviK,KAAKqgI,KAAKw/C,oBACf7/K,KAAKuhL,OAAOH,oBACZphL,KAAKilK,OAAO/C,iBAAmBK,GAAQviK,KAAKilK,OAAOxB,cAAgBzjK,KAAKilK,OAAOuc,aAChFxhL,KAAKshL,UAGF,OAAO/e,GACZviK,KACGqlC,OAAOk9H,GACP9yJ,KAAMu4I,IAEDhoJ,KAAKilK,OAAOL,MAAMrC,IACpBviK,KAAKyhL,QAAQlf,GAGf,IAAImf,EAAU,IAAI,GAAe15B,GAEjChoJ,KAAK2hL,YAAYD,GAEjB1hL,KAAKmjK,QAAQue,KAEdlnK,MAAM,QAKX,cACE,OAAOxa,KAAK4X,KAAKpH,IAGX,OAAO+xJ,GACb,OAAO,IAAIhzJ,QAA4B,CAACC,EAASquB,KACjC79B,KAAK65C,eAAe94C,KAAK,GAAoBf,KAAK+I,SAAU,CAAEvG,OAAQxC,KAAKilK,OAAOziK,SAC1Fg5D,aAAan7D,UAAWo7D,IAC5B,IAAI+iH,EAAa/iH,EAAM6iH,aAEvB,IAAKE,EAEH,YADA3gJ,IAIF,IAAIr2B,EAAS,CACXW,MAAO,aACP2M,WAAY0pK,EAAW1pK,WACvBinE,SAAUwmF,EAAKxmF,SACfD,OAAQymF,EAAKzmF,OACblsB,YAAa2yG,EAAK3yG,YAClBosB,UAAWumF,EAAKvmF,UAChBlsD,QAAS0uJ,EAAW/rG,YAAc,IAGhCl1D,EAAWvd,KAAKi8E,YAAY5D,kBAAkB7wE,GAElD+V,EAAS+xC,KAAOtvD,KAAKilK,OAAON,aAE5Bn1J,EAAQ+N,OAKN,QAAQglJ,GACVA,EAAKR,MAEP/hK,KAAKilK,OAAO2c,OAAOrf,EAAKxmF,SAAW,EAAGwmF,EAAK3yG,aAClC2yG,EAAKsf,UAEd7hL,KAAKilK,OAAOvnI,UAAU6kI,EAAK3yG,YAAc,EAAG2yG,EAAKxmF,UAM7C,YAAYwmF,GAClBA,EAAKvmF,UAAYh8E,KAAKilK,OAAOjD,WAAa,EAE1ChiK,KAAKilK,OAAOxC,YAAY/8J,QAASo8K,IAC3Bvf,EAAKwf,oBAAoBD,KAC3Bvf,EAAKvmF,UAAY8lG,EAAalyH,eAK5B,QAAQ2yG,GACdA,EAAK2B,0BACLlkK,KAAKilK,OAAOxC,YAAYvhK,KAAKqhK,GAC7BviK,KAAKilK,OAAOzB,gBAAgBtiK,KAAKqhK,EAAKt8H,QACtCjmC,KAAKilK,OAAOF,oBAGd,gBACE,OAAO/kK,KAAKilK,OAAON,cAAgB3kK,KAAKilK,OAAON,aAAa11I,mB,uCAzGnD,IAAoB,8E,0BAApB,GAAoB,QAApB,GAAoB,YCJ1B,MAAe+yJ,GAIpB,YAAqBC,EAEApzK,EACA6I,EACAmgD,EACAh4D,EACAyiB,EACA4/J,EACAxiF,EACAyiF,GATA,KAAAF,qBAEA,KAAApzK,aACA,KAAA6I,iBACA,KAAAmgD,OACA,KAAAh4D,QACA,KAAAyiB,QACA,KAAA4/J,YACA,KAAAxiF,WACA,KAAAyiF,QAZd,KAAAvqK,KAAO,CAAE0K,MAAOtiB,KAAK63D,KAAKz2D,EAAE,MAAMpB,KAAKoiL,yBAC9BC,WAAYriL,KAAK63D,KAAKz2D,EAAE,MAAMpB,KAAKoiL,0BAenD,WACEpiL,KAAK0/F,SAAS/0F,SAASO,SAASwT,KAAM,sBACtC1e,KACGiiL,mBACAj8K,WAAWhG,KAAKsiL,iBAChB7yK,KAAM6/C,IACLtvD,KAAKsvD,KAAOA,EACZtvD,KAAKH,MAAMS,kBAGfN,KAAKuiL,eAGP,cACEviL,KAAK0/F,SAASh1F,YAAYQ,SAASwT,KAAM,sBAGnC,eACN1e,KAAKsiB,MAAM8nG,SAASpqH,KAAK4X,KAAKyqK,a,uCAnCZL,IAAiB,0F,wBAAjBA,K,mCCahB,kB,qBAKM,iC,wCAQR,qBAES,sEAAOT,OAAA,SAAP,CAAwB,mEACfA,OAAA,WADT,CAAwB,2CAEhBA,OAAA,aACf,iBACE,eAGF,OACF,O,KATS,yB,kHAjCX,gBAaE,gBAEK,4EAAkBlhD,KAAA,WAAlB,CAAmC,mDACjBA,KAAA,UAGrB,wBAQA,wBAIF,OACA,2BAWF,O,qCAtCK,sCAA0C,4BAA1C,CAA0C,sCAA1C,CAA0C,mCAH1C,iHAEmD,YAFnD,CAEmD,oBAFnD,CAEmD,+CAajD,sEAEG,wCAQO,yDAA6C,6CAA7C,CAA6C,gDAKnD,2C,wCA8BT,iBAGK,wEAAS7vH,IAAA,aACd,O,wBAFK,6B,6JAlBP,iBAaK,uEAAay0J,OAAA,wBAGhB,wBAKF,O,qCAdK,sCAA0C,4BAA1C,CAA0C,sCAA1C,CAA0C,mCAL1C,0IAI+C,YAJ/C,CAI+C,oBAJ/C,CAI+C,+CAW7C,sC,wCAkBL,iBAGK,wEAASz0J,IAAA,aACd,O,wBAFK,6B,6HAdP,iBAWK,uEAAay0J,OAAA,wBAChB,wBAKF,O,qCAXK,sCAAyC,4BAAzC,CAAyC,sCAAzC,CAAyC,mCAJzC,sFAGuC,aAQrC,sC,0BAOP,iBAOE,iBAEF,Q,oBAPK,2DAA0D,iDAA1D,CAA0D,2DAA1D,CAA0D,uDAA1D,CAA0D,yCCpE1D,MAAMud,GAAiB,CAC5B,GACA/D,GACA,GACAmC,GACA,GACAxb,IAOK,MAAM,GASX,YAAoB3xD,EACA0qE,EACD99C,EACAkhD,EACAtc,EACAz0J,EACAiiB,EACEyzB,GAPD,KAAAutD,eACA,KAAA0qE,iBACD,KAAA99C,OACA,KAAAkhD,SACA,KAAAtc,SACA,KAAAz0J,MACA,KAAAiiB,SACE,KAAAyzB,kBAfd,KAAAu8H,UAAgC,GAChC,KAAAC,iBAAmB,OACnB,KAAAC,mBAAqB,OAErB,KAAAl0K,UAAY,GAcnB,WACEzO,KAAKilK,OAAON,aAAe3kK,KAAKsvD,KAGlC,cACEtvD,KAAKyiL,UAAU/8K,QAASugC,GAAWA,EAAO/H,WAI5C,oBAAoBl2B,GACA,WAAdA,EAAMrG,MAEC3B,KAAKqgI,KAAKw/C,kBACnB7/K,KAAKqgI,KAAKlzF,QACDntC,KAAKuhL,OAAOH,mBACrBphL,KAAKuhL,OAAOp0I,SAIT,gBAAgBo1H,GACrB,IAAIt8H,EAASs8H,EAAKt8H,OAElB,IAAKA,EACH,OAAO,KAGT,IAAIgoI,EAAejuK,KAAKm+K,eAAeK,WAAWhzK,KAAMo3K,GAAQA,EAAI9tK,aAAemxB,EAAOnxB,YAE1F,OAAKm5J,EAKIA,EAAax/J,UAFb,KAMJ,qBAAqB8zJ,GAC1B,MAAO,CAAEhlJ,SAAUglJ,EAAKt8H,QAGnB,sBAAsBs8H,GAC3B,MAAO,CAAEzqG,gBAAiB93D,KAAKilK,OAAO4d,oBAAoB/1K,KAAK9M,KAAKilK,SAGtE,sBACE,OAAOjlK,KAAK8iL,UAAU9iL,KAAKilK,OAAOjD,WACZ,gBAAgBhiK,KAAK2iL,wBAAwB3iL,KAAKilK,OAAOjD,WAAa,QAAQhiK,KAAKilK,OAAOjD,eAGlH,mBACE,OAAOhiK,KAAK8iL,UAAU9iL,KAAKilK,OAAOhD,QACbjiK,KAAK0iL,kBAGrB,iBAAiBzxJ,EAAcsxI,GACpC,OAAOA,EAAKpyB,KAGd,yBACE,OAAOnwI,KAAKilK,OAAOxlH,WAGrB,qBACE,OAAOz/C,KAAKkmD,gBAAgBC,SAGtB,UAAUgxB,EAAe4rG,GAC/B,IAAI/gK,EAAQ,GACZ,IAAK,IAAIjF,EAAI,EAAGA,EAAIo6D,EAAQp6D,IAC1BiF,GAAS,GAAGhiB,KAAK2iL,sBAAsBI,KAKzC,OAFA/gK,GAAS,GAAGhiB,KAAK2iL,mBAEV3iL,KAAKyzG,aAAauvE,yBAAyBhhK,I,uCA9FzC,IAAa,6E,wBAAb,GAAa,qD,iCAAb,4BAA2B,S,whEDzCxC,gBAKE,wBA8CA,wBAuBA,wBAoBA,wBAUF,Q,MAvGK,gDAA+C,qCAI7C,6CAAmE,mCA8CnE,2CAAiE,mCAuBjE,0CAA+D,mCAoB/D,8C,8JEnFC,mBAGQ,+CAASmgK,MAAA,oBAEf,qBAEF,O,uBALQ,kCAA2B,0C,yBAW3C,kB,oBAAmB,qBCdZ,MAAM,WAA2BH,GAC5B,gBACR,MAAO,aAGC,gBACR,OAAOhiL,KAAK6O,WAAWo0K,sBAAsBjjL,KAAK0X,eAAe5C,a,sCANxD,K,wBAAA,GAAkB,yCAFlB0tK,IAAc,qZDR3B,gBACE,gBACE,gBACE,eACF,OAEA,eACE,eACE,iCACF,OACA,eACE,0BAQF,OACF,OACF,OACF,OAEA,yB,MArBU,yCASM,2CAYV,8B,+VCdO,IC0BAU,GAA0C,CACrD,CACEz8K,KAAM,aACNiI,OAAQ,OAGRV,IAAK,eACLG,KAAM,CACJC,YAAa,CAAC,+BAAgC,sBAC9CC,SAXgB,wBAalBI,UAAW,KAgCR,MAAM00K,I,wCC/Eb,gBACC,2BAEgB,+EAChB,OACD,O,uBAJiB,2C,wBD8EJA,K,qDAAAA,KAA2B,UAN3B,GACV,SAZQ,CACP,IAEA9L,GAGA,kBAAehJ,SAAS,CACtB1rK,OAAQugL,GACRvvK,OAnBC,SAAyCumK,GAG9CA,EAASC,WAAWiJ,MACjBC,KACC,IAAIp0H,OAAO,+BACX0J,GAAS,aAAaA,EAAM,yBEd3B,MAAM,WAAuB,IAOlC,YAAqBn4D,EAC4BsR,EAC5BjS,EACAg4D,EACAp0D,EACAo2C,EACApiC,GACnB3X,MAAMgS,EAAQjS,EAAOW,GAPF,KAAAA,aAC4B,KAAAsR,SAC5B,KAAAjS,QACA,KAAAg4D,OACA,KAAAp0D,eACA,KAAAo2C,iBACA,KAAApiC,SAVd,KAAAG,KAAO,CACZ0rK,WAAYtjL,KAAK63D,KAAKz2D,EAAE,wBAa1B,WACEtB,MAAMqkB,WACN,MAAMo/J,EAAkBvjL,KAAK8R,OAAOyxK,gBAC9Br/J,EAAgB,IAAY5I,WAAWioK,GAE7CvjL,KACGyD,aACAmC,cACAsC,GAAGgc,GACH4B,mBACAzlB,UAAW2I,IACVhJ,KAAKgJ,YAAcA,EACnBhJ,KAAKH,MAAMS,gBAEX,MAAMm7D,EAAQ50D,OAAO7G,KAAKQ,WAAWsG,eAAe0E,KAAK,6BACzDxL,KAAKurB,WAAWkwC,EAAOz7D,KAAK8R,OAAO9J,MAAMjB,UAIxC,WAAW6oB,EAA6B7oB,GAC7C6oB,EAAQ/jB,SAAS,CACfsK,GAAI,YACJC,GAAI,eACJ9C,GAAIvM,EACJgiD,UAAW,YAIR,cAAc/gD,GACnB,MAAMkW,EAAS,CAAEgG,cAAelc,EAAMkc,eAEtClkB,KAAKyX,OAAOswB,GAAG//B,EAAM2yC,eAAgBz8B,I,uCAhD5B,IAAc,eAQL,KAAkB,gE,wBAR3B,GAAc,wSD3C3B,uB,KAA8D,4B,6SEkCvD,MAAM,GAIX,YAAqB27B,EACA9wC,GADA,KAAA8wC,iBACA,KAAA9wC,WAGrB,gBACElC,OAAOqE,SAASwT,MAAM9U,GAAG,aAAc,mBAAqB0C,IAC1DA,EAAEC,iBACFD,EAAEO,kBACF,MAAMoF,EAAKpL,OAAOyF,EAAEvF,QACdxB,EAAO0M,EAAGhI,KAAK,QAEhB1E,IAILvF,KAAKwjL,aAAexjL,KAAK65C,eAAe94C,KAAK,GAAgBf,KAAK+I,SAAU,CAAEw6K,gBAAiBh+K,EAAMyC,MAAOsE,IAC5GtM,KAAKyqF,aAAezqF,KAAKwjL,aAAahjL,WAAWsG,cACjD9G,KAAKwjL,aAAaj4J,WAAW1kB,OAAO7G,KAAKyqF,cAAex4E,GAExDpL,OAAO7G,KAAKyqF,cAAc9/E,SAAS,2BAGrC9D,OAAOqE,SAASwT,MAAM9U,GAAG,aAAc,mBAAqB0C,IAC1DA,EAAEC,iBACFD,EAAEO,kBAEE7M,KAAKyjL,mBAAmBn3K,GAC1BzF,OAAO7G,KAAKyqF,cAAc7gF,GAAG,aAAe,KAC1C5J,KAAK65C,eAAe9uC,UAGtB/K,KAAK65C,eAAe9uC,UAKlB,mBAAmBuB,GACzB,IAAKtM,KAAKyqF,aACR,OAAO,EAGT,MAAM7/C,EAAiB/jC,OAAO7G,KAAKyqF,aAAax+E,SAAS,IACzD,GAAI2+B,GAAkBA,EAAe8N,SAAU,CAC7C,IAAIgrI,EAAkBp3K,EAAE09I,OAASviI,KAAKg9D,MAAM75C,EAAe8N,SAAUo+B,OAC/CxqE,EAAE09I,MAAQp/G,EAAe8N,SAAUo+B,KAAOlsC,EAAexN,QAC3EumJ,EAAgBr3K,EAAE89I,OAAS3iI,KAAKg9D,MAAM75C,EAAe8N,SAAU5sC,MAC/CQ,EAAE89I,MAAQx/G,EAAe8N,SAAU5sC,IAAM8+B,EAAe1Y,SAC5E,OAAOwxJ,GAAmBC,EAE5B,OAAO,G,uCArDE,IAAqB,sB,0BAArB,GAAqB,QAArB,GAAqB,qBADR,S,kFLtBlB,mBAGQ,+CAASxB,MAAA,oBAEf,qBAEF,O,uBALQ,kCAA2B,0C,yBAW3C,kB,oBAAmB,qBMdZ,MAAM,WAA0BH,GAC3B,gBACR,MAAO,YAGC,gBACR,OAAOhiL,KAAK6O,WAAWE,YAAY/O,KAAK0X,eAAe5C,a,sCAN9C,K,wBAAA,GAAiB,wCAFjB0tK,IAAc,qZNR3B,gBACE,gBACE,gBACE,eACF,OAEA,eACE,eACE,iCACF,OACA,eACE,0BAQF,OACF,OACF,OACF,OAEA,yB,MArBU,yCASM,2CAYV,8B,+VMdO,IC0BAoB,GAAwC,CACnD,CACEn9K,KAAM,WACNiI,OAAQ,OAGRV,IAAK,IACLG,KAAM,CACJE,SAVgB,sBAYlBI,UAAW,KA+BR,MAAMo1K,I,wBAAAA,K,qDAAAA,KAAyB,UANzB,GACV,SAXQ,CACP,IAEAxM,GAEA,kBAAehJ,SAAS,CACtB1rK,OAAQihL,GACRjwK,OAlBC,SAAuCumK,GAG5CA,EAASC,WAAWiJ,MACjBC,KACC,IAAIp0H,OAAO,gCACX0J,GAAS,aAAaA,EAAM,c,kFP7C1B,mBAGQ,+CAASwpH,MAAA,oBAEf,qBAEF,O,uBALQ,kCAA2B,0C,yBAW3C,kB,oBAAmB,qBQfZ,MAAM,WAAwBH,GACzB,gBACR,MAAO,UAGC,gBACR,OAAOhiL,KAAK6O,WAAWi1K,c,sCANd,K,wBAAA,GAAe,4CAFftB,IAAc,qZRP3B,gBACE,gBACE,gBACE,eACF,OAEA,eACE,eACE,iCACF,OACA,eACE,0BAQF,OACF,OACF,OACF,OAEA,yB,MArBU,yCASM,2CAYV,8B,+VQfO,ICyBAuB,GAAuC,CAClD,CACEt9K,KAAM,UACNuH,IAAK,WACLS,UAAW,GACXN,KAAM,CACJC,YAAa,CAAC,gCAAiC,sBAC/CM,OAAQ,mBAkBP,MAAMs1K,I,wBAAAA,K,qDAAAA,KAAuB,SAZzB,CACP,IAEA3M,GAGA,kBAAehJ,SAAS,CAAE1rK,OAAQohL,S,8BCpBtC,MAAME,GAAa,CACjBriH,QAAS,EACT05F,eAAgB,EAChBtuI,KAAM,EACNk3J,YAAa,EACbC,cAAe,EACfC,KAAM,EACNC,SAAU,EACVznG,QAAS,GAWJ,MAAM0nG,GAyBX,YAA6B5pK,EACA6P,EACA7S,GAFA,KAAAgD,aACA,KAAA6P,cACA,KAAA7S,iBAxBrB,KAAA6sK,UAAgB,CACtB,IAAK,IAAMvkL,KAAKwkL,gBAChB,MAAOxkL,KAAKykL,aAAa,cACzB,MAAOzkL,KAAK0kL,cAAc,eAC1B,QAAS1kL,KAAK0kL,cAAc,2BAC5B,QAAS1kL,KAAK0kL,cAAc,mBAC5B,MAAO1kL,KAAK0kL,cAAc,uBAC1B,MAAO1kL,KAAK0kL,cAAc,uBAC1B,MAAO1kL,KAAK0kL,cAAc,mBAC1B,QAAS1kL,KAAK0kL,cAAc,6BAE5B,MAAO1kL,KAAK+tD,UAAU,QACtB,MAAO/tD,KAAK+tD,UAAU,WACtB,QAAS/tD,KAAK+tD,UAAU,WACxB,EAAK/tD,KAAK+tD,UAAU,YACpB,EAAK/tD,KAAK+tD,UAAU,iBACpB,EAAK/tD,KAAK+tD,UAAU,eACpB,EAAK,IAAM/tD,KAAK2kL,gBAChB,EAAK,IAAM3kL,KAAK4kL,iBAOhB5kL,KAAKu/C,WAMA,WACLl7C,EAAEC,KAAKtE,KAAKukL,UAAW,CAACxjH,EAAmBp/D,IAAeq7E,UAAUlwE,KAAKnL,EAAKo/D,IAGzE,UAAU8jH,GACf,IAAIljL,EAAMsiL,GAAWY,GACrB,MAAO,KACL,IAAI5lF,EAAOp4F,OAAO,cAAgBlF,EAAM,WACpCs9F,EAAKx5D,GAAG,UAAgC,wBAApBw5D,EAAKh1F,KAAK,MAGhCqD,WAAW,IAAMtN,KAAKuqB,YAAYhd,MAAM0xF,GAAO,KACtCA,EAAKx5D,GAAG,UACjBzlC,KAAK8kL,UAAU7lF,EAAK,IAEpBA,EAAK,GAAG7yF,SAKP,aAAa20D,GAClB,MAAO,KACL,IAAI/yD,EAAOhO,KAAK0a,WAAWqmD,KAC3BvgD,OAAOgoB,SAASjjC,KAAOyI,GAIpB,cAAc+yD,GACnB,MAAO,KACL,IAAIjyD,EAAoB9O,KAAK0X,eAAe5C,WAC5C,GAAIhG,EAAmB,CACrB,IAAId,EAAOhO,KAAK0a,WAAWqmD,GAAgBjyD,GAC3C0R,OAAOgoB,SAASjjC,KAAOyI,IAK7B,UAAUu4B,GACR,IAAIo7D,GAAY,EAEhB,GAAMz2F,SAAS65K,YAAa,CAC1B,IAAI/8K,EAAQ,IAAIg9K,WAAW,QAAS,CAClCjkJ,KAAMvgB,OACNykK,SAAS,EACTC,YAAY,IAEdvjF,GAAap7D,EAAKsvF,cAAc7tH,QACvBu+B,EAAK4+I,YACdxjF,GAAap7D,EAAK4+I,UAAU,YAGzBxjF,IACHnhF,OAAOgoB,SAASjjC,KAAOghC,EAAKhhC,MAIhC,gBACEib,OAAOnW,KAAKrK,KAAK0a,WAAW0qK,6BAG9B,iBACE,MAAMC,EAAWx+K,OAtGU,kCAuGrBy+K,EAAoB,GAO1B,OANAD,EAAS75K,KAAK,YAAYlH,MAAK,SAAU2sB,EAAOyD,GAC9C,IAAI6wJ,EAAY1+K,OAAO6tB,GAAIlpB,KAAK,qBAAqB,QACnCE,IAAd65K,GACFD,EAAcpkL,KAAKqkL,MAGhBD,EAGT,gBAAgB5sI,GACd,MAAM0a,EAAOpzD,KAAKwlL,iBAClB,IAAIv0J,EAEJ,GAAa,OAATmiC,EACF,OAGFniC,EAAQmiC,EAAKh2C,QACXvW,OAAOqE,SAASglD,eACblpD,QA1HqB,2CA2HrBwE,KAAK,qBAAqB,IAGhB3E,OAAOusD,GAAMniC,EAAQynB,EAAS0a,EAAKnsD,QAAUmsD,EAAKnsD,SAC1DsG,QAIT,gBACEvN,KAAKylL,gBAAgB,GAGvB,gBACEzlL,KAAKylL,iBAAiB,I,uCAlIbnB,IAAuB,kC,0BAAvBA,GAAuB,QAAvBA,GAAuB,qBAFtB,S,wDCLN,iBAAuC,QAAa,Q,6BAA9C,oCAAiC,sB,0BAGvC,iBAAuC,QAAa,Q,6BAA9C,oCAAiC,sBAMxC,MAAM,GAOX,YAAsB9jL,EACSE,GADT,KAAAF,aACS,KAAAE,OALvB,KAAAglL,qBAA8B,EAQtC,WACE1lL,KAAK2lL,kBAEL3lL,KAAKgoE,iBAAmB98D,SAAS+8D,kBAAkBjoE,KAAKQ,WAAWsG,cAAc2J,QAAQm1K,aAAa,GACtG5lL,KAAK0lL,oBAAuBjgK,KAAKvG,MAAMlf,KAAKQ,WAAWsG,cAAc2J,QAAQi1K,qBAGxE,cAAcl4E,GACfA,GAASxtG,KAAKgoE,mBAChBhoE,KAAKgoE,iBAAiB7hE,MAAQqnG,EAAMrnG,OAIhC,kBACNnG,KAAK8vB,QAAUrK,KAAKvG,MAAMlf,KAAKQ,WAAWsG,cAAc2J,QAAQuQ,QAChEhhB,KAAK8vB,QAAQ4e,QAAQ,CAACjoC,KAAMzG,KAAKU,KAAKU,EAAE,qBAAsB+E,MAAO,KAErEnG,KAAKu0I,eAAiBv0I,KAAK8vB,QAAQtkB,KAAMV,IAA2B,IAAlBA,EAAKy6B,UAEnDvlC,KAAKu0I,eACPv0I,KAAKu0I,eAAiBv0I,KAAKu0I,eAAepuI,OAG1CnG,KAAK6lL,gBAAkB7lL,KAAKQ,WAAWsG,cAAc2J,QAAQq1K,cAC7D9lL,KAAKu0I,eAAiBv0I,KAAK6lL,gBAAkB7lL,KAAK6lL,gBAAkB,IAIhE,eAAe/6K,GACrB,GAAmB,KAAfA,EAAK3E,MAAgB,OAEzB,IAAI4/K,EAMJ,OAJEA,EADE/lL,KAAK0lL,oBACa,qBAEA,gBAEfK,EAAoB,KAAaphG,WAAW3kF,KAAK0lL,oBAAqB56K,EAAK3E,Q,uCAhDzE,IAAmB,sB,wBAAnB,GAAmB,qRAlB5B,sBAIW,+DAA4B,6BAClB,EAAAwiE,cAAA,MAGnB,+BAGA,+BAGF,Q,KAdW,wBAAiB,mBAAjB,CAAiB,2BAAjB,CAAiB,iB,qGCW5B,8B,oBACmB,gCAAyB,uCAMzC,MAAM,WAA0C,KAcrD,YAAqBp+C,EACA/pB,EACAk/F,EACAh/F,EACAwb,EACA8pK,EACA/iL,EACAL,EACAqjL,EACApmL,EACDirD,GAClBhrD,QAXmB,KAAAyqB,cACA,KAAA/pB,aACA,KAAAk/F,WACA,KAAAh/F,OACA,KAAAwb,qBACA,KAAA8pK,sBACA,KAAA/iL,iBACA,KAAAL,aACA,KAAAqjL,YACA,KAAApmL,QACD,KAAAirD,kBAtBb,KAAAo7H,eAAgB,EAEhB,KAAAC,mBAAyD,CAC9Dx3I,sBAAsB,EACtBC,mBAAmB,EACnB0iD,oBAAoB,EACpBC,qBAAqB,EACrBx3C,aAAa,EACb43C,kBAAkB,EAClBC,iBAAkB5xF,KAAKU,KAAKU,EAAE,8BAiBhC,kBACE,OAAA+5F,GAAA,GAAc,CACZn7F,KAAKgmL,oBAAoBpL,YACzB56K,KAAKgmL,oBAAoBhL,gBAExB76K,KACC,OAAAwyK,GAAA,GAAK,GACL,OAAAn5H,GAAA,KACA,OAAAwlD,GAAA,GAAa,IACbh/F,KAAKI,kBAENC,UAAU,EAAE+lL,EAAeC,MAC1BrmL,KAAKimL,UAAU1hK,SAAU,EACzBvkB,KAAK4zK,kBAGT5zK,KAAKgmL,oBACF7K,eACAh7K,KACCH,KAAKI,kBAENC,UAAW6lL,GAA0BlmL,KAAKkmL,cAAgBA,GAG/D,WACElmL,KAAK4zK,gBAGC,gBACN,IAAI5kK,EAAgB,GAChBjK,EAAU,CAAC,KAAM,UAAW,UAAW,OAAQ,SAAU,aAEzD/E,KAAKgmL,oBAAoBn+G,WAAW5gE,OAAS,GAC/C+H,EAAQ9N,KAAK,CACXmhC,OAAQ,CACN1c,SAAU,KACVC,OAAQ,CAAC5lB,KAAKgmL,oBAAoBn+G,eAKM,oBAA1C7nE,KAAKgmL,oBAAoBrK,eAC3B3sK,EAAQ9N,KAAK,CACXkzK,aAAc,CACZzuJ,SAAU,KACVC,OAAQ,MAGZ7gB,EAAU,CAAC,KAAM,UAAW,OAAQ,SAAU,cAGF,KAA1C/E,KAAKgmL,oBAAoBrK,cAC3B3sK,EAAQ9N,KAAK,CACXkzK,aAAc,CACZzuJ,SAAU,IACVC,OAAQ,MAKd5lB,KAAKg4C,WAAa,CAChB,YAAajzC,EACbiK,QAASyW,KAAKC,UAAU1W,GACxB/J,OAAQwgB,KAAKC,UAAU,CAAC,CAAC,YAAa,UACtCG,iBAAiB,I,uCA5FV,IAAiC,oH,wBAAjC,GAAiC,2LAP1C,qC,KAAmB,+B,0DCahB,MAAM,GASX,YACWgyC,EACAy2G,GADA,KAAAz2G,OACA,KAAAy2G,eATX,KAAAgY,mBAAqB,KAAahoC,UAAU,oBACrC,KAAA1mI,KAAO,CACZ2uK,YAAavmL,KAAK63D,KAAKz2D,EAAE,yBACzBolL,uBAAwBxmL,KAAK63D,KAAKz2D,EAAE,uDACpCqlL,WAAYzmL,KAAK63D,KAAKz2D,EAAE,kDAuBlB,KAAAslL,SAAkB,qCAhBxB1mL,KAAK2mL,kBAAoBnmK,OAAOihB,YAAYklJ,kBAG9C,uBACE,IAAI34K,EAAMhO,KAAK4mL,WAAW,oBAC1B,OAAO5mL,KAAKsuK,aAAauY,+BAA+B74K,GAG1D,4BACE,OAAOhO,KAAK4mL,WAAW,4BAGjB,WAAWjlL,GACjB,OAAO3B,KAAK63D,KAAKz2D,EAAEpB,KAAK0mL,SAAW1mL,KAAK8mL,WAAa,IAAMnlL,EAAK,CAAEolL,mBAAoB,0BAA2BC,aCtF3F,6ED2FxB,iBACE,OAAOhnL,KAAK2mL,kBAAoB,WAAa,O,uCAhCpC,IAAmC,sB,wBAAnC,GAAmC,yPArB5C,cACE,QACF,OACA,gBACE,cACA,gBACA,cACF,OAEA,cAA6C,QAAqB,Q,MARhE,oDAGG,uDACE,8CAIJ,6CAA0C,kC,wREJ1C,MAAMM,I,uCAAAA,K,wBAAAA,GAAsC,sIAL/C,UACE,sCACF,S,wDCLG,MAAMC,GAYX,YAAoB1mL,GAAA,KAAAA,aANZ,KAAA2mL,UAAmB,EAS3B,WACEnnL,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eACvC9G,KAAKonL,oBAAsBpnL,KAAKqnL,wBAEhCrnL,KAAK8U,WAAc9U,KAAK4G,SAASuH,KAAK,cACtCnO,KAAKmnL,SAAuE,SAA5D3mK,OAAOihB,YAAYiqD,oBAAoB1rF,KAAK8U,YAG5D9U,KAAKonL,oBAAoBzjK,KAAK,WAAY3jB,KAAKmnL,UAG/CnnL,KAAK4G,SACF8H,SACAlD,KAAK,qCACL5B,GAAG,QAAS,IAAM5J,KAAKyB,QAAQzB,KAAKmnL,WAGvCnnL,KAAKonL,oBACF57K,KAAK,4BACL5B,GAAG,QAAS,IAAM5J,KAAKyB,QAAO,IAI3B,wBACN,OAAOzB,KAAK4G,SACT8H,SACAlD,KAAK,oCAGF,OAAO87K,GACbtnL,KAAKmnL,SAAWG,EAChB9mK,OAAOihB,YAAYiqD,oBAAoB1rF,KAAK8U,cAAewyK,GAAajlK,YAEpEilK,EACFtnL,KAAKonL,oBAAoBx6K,QAAQ,IAAK,KAEpC5M,KAAKonL,oBAAoBzjK,KAAK,UAAU,MAG1C3jB,KAAKonL,oBAAoBp6K,UAAU,KACnChN,KAAKonL,oBAAoBzjK,KAAK,UAAU,K,uCAvDjCujK,IAAyB,Y,wBAAzBA,GAAyB,4FCE/B,MAAM,GAIX,YAAYnL,GAHL,KAAAwL,UAAY,cACZ,KAAAzjJ,IAA8B,GAGnC,MAAM0jJ,EAAezL,EAAIr3K,IAAI,gBAC7B1E,KAAK8jC,IAAM0jJ,EAAS1jJ,IACpB9jC,KAAKunL,UAAUvjL,SAASwjL,EAASzuK,OAAO7J,IAAK+C,IAC3CjS,KAAKs0C,iBAAiBriC,EAAGtQ,KAAK,GACvBsQ,EAAGtQ,OAGZ3B,KAAKynL,uBAGP,QAAQ9lL,GACN,OAAOuJ,SAAS2O,cAAc,2CAA2ClY,OAG3E,KAAKA,GACH3B,KAAKunL,UAAU33G,SAAS23G,GAAaA,EAAUh8K,OAAO0G,GAAMA,IAAOtQ,IACnE3B,KAAKs0C,iBAAiB3yC,GAAK,GAG7B,KAAKA,GACH3B,KAAKunL,UAAU33G,SAAS23G,GAAa,IAAIA,EAAW5lL,IACpD3B,KAAKs0C,iBAAiB3yC,GAAK,GAGrB,iBAAiBA,EAAY4iB,GACnC,MAAMmjK,EAAU1nL,KAAK0nL,QAAQ/lL,GAEzB+lL,IACFA,EAAQvxJ,QAAU5R,GAId,uBACN1d,OAAOqE,SAASwT,MACb9U,GAAG,SAAU,QAAQ,SAAS/I,GAC7B,MAAMuD,EAAOyC,OAAO7G,MACdwnL,EAAWpjL,EAAKoH,KAAK,+BAE3B,SAAIpH,EAAK+J,KAAK,uBAA6C,IAApBq5K,EAASvgL,UAIhD7C,EAAK+J,KAAK,sBAAsB,GAChCq5K,EAAS/0J,SACTruB,EAAK4F,QAAQ,UACbnJ,EAAI0L,kBACG,O,uCAnDF,IAAkB,a,0BAAlB,GAAkB,QAAlB,GAAkB,qBADL,SCAnB,MAAMo7K,GAKX,YAAsBnnL,EACAonL,GADA,KAAApnL,aACA,KAAAonL,qBALtB,KAAAL,WAAoB,EAOpB,WACEvnL,KAAK6nL,YAAc7nL,KAAKQ,WAAWsG,cAAc2J,QAAQo3K,YAG3D,cAEE,OADA7nL,KAAK4nL,mBAAmBz6K,KAAKnN,KAAK6nL,cAC3B,G,uCAdEF,IAAwB,qB,wBAAxBA,GAAwB,kNCrCrC,mCACI,kCAAW,EAAAG,iBAGb,oBACF,S,yCCgCO,MAAMC,GAIX,YAAoBC,EACAxnL,GADA,KAAAwnL,qBACA,KAAAxnL,aAGpB,WACE,MAAMovB,EAAU/oB,OAAO7G,KAAKQ,WAAWsG,eACvC9G,KAAKioL,SAAWr4J,EAAQzhB,KAAK,YAC7BnO,KAAKkoL,gBAAkBt4J,EAAQzhB,KAAK,mBAErBtH,OAAO7G,KAAKQ,WAAWsG,eAAeqhL,OAC9Cv+K,GAAG,SAAU5B,IACGnB,OAAO,kBAAmBmB,EAAMjB,QAElCnF,QAAU5B,KAAKioL,SAChCjoL,KAAKgoL,mBAAmB76K,KAAKnN,KAAKkoL,iBAElCloL,KAAKgoL,mBAAmBjnL,KAAKf,KAAKkoL,oB,uCApB7BH,IAA4B,qB,wBAA5BA,GAA4B,gG,sECjCvC,mB,yBAAqD,oBAAmB,wBCoCnE,MAAM,WAAoC,KAW/C,YAAsBH,EACApnL,EACAE,GACpBZ,QAHoB,KAAA8nL,qBACA,KAAApnL,aACA,KAAAE,OAVtB,KAAA0nL,WAAa,KAAuB1kK,gBAAgB,OAEpD,KAAA2kK,WAAqC,GACrC,KAAAtvK,OAAkB,GAGX,KAAAyW,YAAcxvB,KAAKU,KAAKU,EAAE,6BAQjC,WACEpB,KAAKy3J,OAASz3J,KAAKQ,WAAWsG,cAAc2J,QAAQgnJ,OAEpDz3J,KAAK4nL,mBACFL,UACArnL,UACAC,KACCH,KAAKI,kBACLC,UAAUknL,IACZvnL,KAAKqoL,WAAaroL,KAAK4nL,mBAAmB9jJ,IACvCv4B,OAAO0G,IAAqC,IAA/Bs1K,EAAUnqK,QAAQnL,EAAGtQ,MAClCw4B,KAAK,CAACjX,EAAGC,IAAMD,EAAEof,MAAMoC,cAAcvhB,EAAEmf,QAEzCtiC,KAAK6mC,OAAO//B,cAAoCy+B,UAAW,IAIhE,KAAKp/B,GACHnG,KAAK4nL,mBAAmB7mL,KAAKoF,I,yBC5BzB,Q,oBAAA,uB,uCDPK,IAA2B,+B,wBAA3B,GAA2B,6D,OAAA,K,yUDxCxC,mBAEQ,kCAAU,EAAApF,KAAA,mBAChB,qBACA,0BACF,Q,MALQ,oBAG2B,0CACzB,uC,4CEiDH,MAAMunL,GAiBX,YAAsB9nL,GAAA,KAAAA,aAXf,KAAA+nL,aAAsB,EAc7B,WACE,MAAM34J,EAAU5vB,KAAKQ,WAAWsG,cAGhC9G,KAAKuoL,YAA8C,SAAhC34J,EAAQnf,QAAQ83K,YACnCvoL,KAAKwoL,WAAa54J,EAAQnf,QAAQw3E,QAGlCjoF,KAAKyoL,mBAAqB74J,EAAQnf,QAAQq3E,UAEtC9nF,KAAKuoL,cACPvoL,KAAKyoL,oBAAsB,MAK7B,MAAMt6K,EAAoBsX,KAAKvG,MAAM0Q,EAAQnf,QAAQqf,SAGrD9vB,KAAKkoE,oBAAoB/5D,GAEpBnO,KAAKuoL,cACRvoL,KAAKulC,SAAYvlC,KAAKulC,SAA0B,IAGlDvlC,KAAK8vB,QAAU3hB,EAGfyhB,EAAQ2xB,cAAcprB,QAAS,EAGjC,oBAAoBhoB,GAClBnO,KAAK0oL,gBAAgBv6K,EAAK5C,OAAOqkB,GAAWA,EAAQ2V,WAGtD,gBAAgBvkC,GACdhB,KAAKulC,SAAWvkC,EAChBA,EAAQqD,EAAEwzE,UAAU72E,GAEpBhB,KAAK2oL,4BACL3nL,EAAM0E,QAASuM,IACbjS,KAAK4oL,kBAAkB32K,EAAG9L,SAI9B,kBAAkBA,GACAU,OAAO7G,KAAKQ,WAAWsG,eAEpC4H,SACAymB,OAAO,8BAA8Bn1B,KAAKyoL,oBAAsB,cAActiL,SAGnF,4BACkBU,OAAO7G,KAAKQ,WAAWsG,eAEpC4H,SACAlD,KAAK,eAAexL,KAAKyoL,wBACzBh2J,U,wCjMhIH,aAGE,eAAqB,qFAAoD,OAC3E,O,qCAHI,uCACA,oBACC,iCAAiB,uB,uCiMgDb61J,IAAqC,Y,wBAArCA,GAAqC,uE,OAAA,K,KACrC,MAAiB,G,mRAjB1B,sBAQW,yCAAiB,EAAAI,gBAAA,MAC1B,+BAGF,Q,KAZW,wBAAiB,0BAAjB,CAAiB,yBAAjB,CAAiB,mBAAjB,CAAiB,uB,iDCiBzB,MAAM,WAA6B,KAMxC,YAAqBloL,EACAiX,EACA2gD,EACA13D,GACnBZ,QAJmB,KAAAU,aACA,KAAAiX,SACA,KAAA2gD,MACA,KAAA13D,OALd,KAAA+gB,QAAmB,CAAC,gBAAiB,mBAQ1CzhB,KAAK6oL,QAAUpjK,KAAKvG,MAAOlf,KAAKo4D,IAAI1zD,IAAI,eAAuBk9I,MAC/D5hJ,KAAKulE,WAAa9/C,KAAKvG,MAAOlf,KAAKo4D,IAAI1zD,IAAI,eAAuB6gC,UAGlEvlC,KAAK4hJ,KAAO5hJ,KAAK6oL,QAAQ35K,IAAKs2D,IACrB,CACLt9D,GAAIs9D,EAAI/+D,KACRA,KAAMzG,KAAKU,KAAKU,EAAE,MAAQokE,EAAIljC,MAAO,CAAE21B,aAAcuN,EAAIljC,QACzD9mB,KAAMgqD,EAAIhqD,QAKdxb,KAAK8oJ,aAAe9oJ,KAAKulE,WAAW9+D,M,uCAzB3B,IAAoB,uD,wBAApB,GAAoB,mclMtDjC,kBACE,iBAA+B,kCAAU,EAAA+iJ,SAAA,MACvC,sBAKF,OACA,kBAEoB,gCAAS,EAAA5/G,gBAC3B,iBACF,OACA,kBAEqB,gCAAS,EAAA6/G,iBAC5B,mBACF,OACF,Q,MAlBsB,0BAEd,+BAMc,wCAKC,2C,2DmM2BhB,MAAMq/B,GAKX,YAAqB9pI,EACAx+C,EACAE,EACAub,GAHA,KAAA+iC,uBACA,KAAAx+C,aACA,KAAAE,OACA,KAAAub,uBAGrB,WACE,MAAM2T,EAAU5vB,KAAKQ,WAAWsG,cAEhC9G,KAAK+oL,YAAcn5J,EAAQoT,aAAa,gBACxChjC,KAAKgpL,gBAAkBp5J,EAAQoT,aAAa,oBAE5Cn8B,OAAO7G,KAAK+oL,aAAan/K,GAAG,QAAU/I,GAA8Bb,KAAKsB,QAAQT,IAEjF+uB,EAAQrf,UAAUC,IAAI,qBACtBxQ,KAAK+G,OAASF,OAAO7G,KAAKgpL,gBAAkBhpL,KAAKgpL,gBAAkBp5J,GAGrE,gBAAgB9c,EAA8B0nC,GAC5C,IAAI+1B,EAAevwE,KAAKg/C,qBAAqBlsC,GAAM0nC,GAGnDltC,WAAW,IAAMtN,KAAKg/C,qBAAqBvsB,OAAO89C,GAAe,KAGnE,QAAQhlC,GACN,IAAI09I,EAAa/9K,SAASg+K,uBAAyBh+K,SAASg+K,sBAAsB,QAOlF,GANA39I,EAAOh/B,iBAIPvM,KAAK+G,OAAOs+B,SAAS93B,QAEjB07K,EACF,IAEE,GAAI/9K,SAASi+K,YAAY,QAEvB,YADAnpL,KAAKopL,gBAAgB,aAAcppL,KAAKU,KAAKU,EAAE,mCAGjD,MAAOkL,GACPsR,QAAQyuD,IACN,wEAA0E//D,GAKhFtM,KAAKopL,gBAAgB,WAAYppL,KAAKU,KAAKU,EAAE,gC,uCApDpC0nL,IAAwB,0C,wBAAxBA,GAAwB,4FCF9B,MAAMO,GAYX,YAAqBz5J,EACA07E,EACA5qG,GAFA,KAAAkvB,UACA,KAAA07E,gBACA,KAAA5qG,OAXd,KAAAgmD,WAAY,EACZ,KAAA9uC,KAAO,CACZ0K,MAAOtiB,KAAKU,KAAKU,EAAE,+BACnBwW,KAAM5X,KAAKU,KAAKU,EAAE,+BAWpB,WACEpB,KAAK4G,SAAWC,OAAoB7G,KAAK4vB,QAAQ9oB,eAE7C9G,KAAK4G,SAAS6+B,GAAG,QACnBzlC,KAAKspL,MAAQtpL,KAAK4G,SAElB5G,KAAKspL,MAAQtpL,KAAK4G,SAASI,QAAQ,QAGrChH,KAAKspL,MAAM1/K,GAAG,SAAW/I,KAClBb,KAAK0mD,YACR7lD,EAAI0L,iBACJvM,KAAKupL,0BACE,IAON,yBACLvpL,KAAKsrG,cAAc9/D,QAAQ,CACzB5zB,KAAM5X,KAAK4X,KACXsvC,eAAe,EACfG,WAAW,EACXD,iBAAiB,IAChB33C,KAAK,KACJzP,KAAK0mD,WAAY,EACjB1mD,KAAKspL,MAAMt/K,QAAQ,YAEpBwQ,MAAM,IAAMxa,KAAK0mD,WAAY,I,uCA/CvB2iI,IAA2B,gC,wBAA3BA,GAA2B,8F,sDCoBjC,MAAM,WAAiC,KAU5C,YAAqBnnJ,EACAriC,EACAW,GACnBV,QAHmB,KAAAoiC,gBACA,KAAAriC,QACA,KAAAW,aANb,KAAA2qF,SAAWtkF,OAAO,cAAc,GAEjC,KAAAsuH,QAAiB,EAQxB,WACEn1H,KAAKkiC,cAAcopD,WAChBnrF,KACC,OAAAq5C,GAAA,KACAx5C,KAAKI,kBAENC,UAAUgsF,IACTrsF,KAAKysF,YAAcJ,EACnBrsF,KAAKH,MAAMS,kBAGfN,KAAK41H,YAAc,mBACnB51H,KAAK8qF,gBAAkB,4BAGlB,cACL9qF,KAAKyrF,aAAezrF,KAAKmrF,SAASvP,YAG7B,WAAWm6C,GAChB/1H,KAAKkiC,cAAc4pD,UAAU9rF,KAAKyrF,aAAesqC,EAAOg1B,SAASthH,GAG5D,YACL,MAAMzhC,EAAQ,IAAIwkF,MAAMxsF,KAAK41H,aAC7Bp1G,OAAOq1G,cAAc7tH,I,uCAzCZ,IAAwB,iC,wBAAxB,GAAwB,6UAnBjC,oBAGS,8BAAO,EAAAsuH,cAAP,CAAmB,2BACV,EAAAC,gBADT,CAAmB,2BAEX,EAAAC,WAAA,MACf,gBACE,cAGI,2CAAmB,EAAAt0F,cAAA,uBAAwC,OAE/D,cAEF,OACF,Q,MAdS,yBAAsB,4BAQvB,kEAFD,8B,sMC7CP,cACG,uEAID,cACF,O,uBAFG,mC,wCA0BG,cACE,iBAAgD,oFAC9C,iBACE,kBAA0C,QAAiB,OAC3D,kBAA0E,QAAgB,OAC5F,OACF,OACF,O,qCAJgD,qCACC,qCAA+B,qC,wCAK9E,eAGG,4FAED,iBACE,yBAKA,kBACA,QACA,OAEA,iBACE,kBAIA,eAEA,QACA,OACA,kBAKF,OACF,OACF,O,qCA7BG,iCAKC,8BAKA,gCAIQ,sCAKJ,2CACF,4BAEM,qCAA2B,6C,0BAjCzC,wBAQA,4C,8BARK,mBAA8C,e,wECmDtD,MAAM,GAoCX,YAAqB1hC,EACAE,EACA+C,EACA2nE,EACAlvD,EACA8pK,EACAtL,EACA/vF,EACA9qF,EACAuqC,GATA,KAAA5pC,aACA,KAAAE,OACA,KAAA+C,eACA,KAAA2nE,oBACA,KAAAlvD,qBACA,KAAA8pK,sBACA,KAAAtL,wBACA,KAAA/vF,gBACA,KAAA9qF,QACA,KAAAuqC,kBAzCd,KAAA15B,UAAmB,EACnB,KAAA84K,UAAW,EAGX,KAAA5hH,SAAW,IAAI,KACnBC,GAAsB7nE,KAAK4xE,yBAAyB/J,GAAY1nE,KAC/D,OAAAyxD,GAAA,GAAI,KACFtkD,WAAW,IAAMtN,KAAKypL,kBAAmB,OAG7C,aAAyBzpL,KAAKoqC,kBAIzB,KAAA+sB,aAAsB,GAStB,KAAAv/C,KAA+B,CACpC8xK,aAAc1pL,KAAKU,KAAKU,EAAE,iCAC1BuoL,gBAAiB3pL,KAAKU,KAAKU,EAAE,oCAC7BwoL,oCAAqC5pL,KAAKU,KAAKU,EAAE,wDACjDihC,OAAQriC,KAAKU,KAAKU,EAAE,2BACpByoL,YAAa7pL,KAAKU,KAAKU,EAAE,2BAA6B,OACtD0oL,aAAc9pL,KAAKU,KAAKU,EAAE,kCAe5B,WAEEpB,KAAKo0C,kBAAkByzB,WAAa7nE,KAAKm3D,aAAen3D,KAAKgmL,oBAAoBn+G,WACjF7nE,KAAK0Q,SAAY1Q,KAAKo0C,kBAAkByzB,WAAW5gE,OAAS,EAC5DjH,KAAK+pL,qBAGP,cACE/pL,KAAKgqL,aAKA,YAAYhiL,GACjBA,EAAM6E,kBACN7E,EAAMuE,iBAGF,KAAewjD,aAAa/vD,KAAKiqL,IAAInjL,cAAekB,EAAMjB,UACxD/G,KAAK2qF,cAAcxkC,UACrBnmD,KAAKkqL,qBAELrjL,OAAO,mBAAmB0G,SAC4B,IAA7CvN,KAAKo0C,kBAAkByzB,WAAW5gE,OAC3CjH,KAAKo0C,kBAAkB7mC,QAEvBvN,KAAKmqL,wBAMJ,qBACLnqL,KAAK0Q,UAAY1Q,KAAK0Q,SACtB1Q,KAAK+pL,qBAGA,aAAa7hL,EAAWF,GAE7B,OADAA,EAAMugC,6BACF,KAAan2B,sBAAsBpK,KAIvCwY,OAAOgoB,SAASjjC,KAAOvF,KAAKoqL,OAAOliL,GACnCF,EAAMuE,kBACC,GAGF,OAAOrE,GACZ,OAAOlI,KAAKorE,kBAAkBjmD,gBAAgBjd,GAGzC,OAAOqjC,GACZvrC,KAAKm3D,aAAen3D,KAAKo0C,kBAAkByzB,WAC3C7nE,KAAKqqL,cAAc9+I,EAAOyoB,MAIrB,cAAcs2H,GACnBtqL,KAAKo0C,kBAAkBjqC,OAAUmgL,EAAalpJ,OAAOn6B,OAAS,EAGzD,UACLjH,KAAK0Q,UAAW,EAChB1Q,KAAK+pL,qBACL/pL,KAAKqqL,cAAcrqL,KAAKm3D,cAGnB,aACAn3D,KAAK2qF,cAAcxkC,WACtBnmD,KAAK0Q,SAAY1Q,KAAKo0C,kBAAkByzB,WAAW5gE,OAAS,EAC5DjH,KAAKo0C,kBAAkBjqC,QAAS,EAChCnK,KAAK+pL,sBAIF,cACL/pL,KAAKm3D,aAAen3D,KAAKo0C,kBAAkByzB,WAAa,GACxD7nE,KAAKqqL,cAAcrqL,KAAKm3D,cAMnB,6BACLn3D,KAAK4nE,SAAS03D,SAASn/H,KACnB,OAAAoL,GAAA,GAAOpF,IAAmB,IAAVA,GAChB,OAAAixC,GAAA,GAAK,IAEN/2C,UAAU,KACLL,KAAKuqL,aACPvqL,KAAKwqL,qBAELxqL,KAAKyqL,cAAczqL,KAAK0qL,gBAKzB,mBAAmBC,GACxB,OAAO,KAAankI,YAAY,SAAUmkI,GAG5C,kBACE,OAAO3qL,KAAKuqL,cAAgBvqL,KAAKuqL,aAAa1uI,eAAe,MAGxD,WAAW/wC,GACZA,EAAK+wC,eAAe,MACtBr7B,OAAOgoB,SAASjjC,KAAOvF,KAAKoqL,OAAQt/K,EAA0B5C,KAG9DlI,KAAKgmL,oBAAoBn+G,WAAa7nE,KAAKm3D,aAC3Cn3D,KAAKyqL,cAAe3/K,EAA0B6wK,eAI3C,qBACD37K,KAAKuqL,cACPvqL,KAAK4qL,WAAW5qL,KAAKuqL,cAKlB,eAAev2H,EAAalpD,GACjC,YAAmBY,IAAZZ,EAAK5C,KAAgF,IAA5D4C,EAAKs+D,QAAQ3kC,cAAcrnB,QAAQ42C,EAAKvvB,eAGlE,yBAAyB5gC,GAC/B,IAAKA,EACH,OAAO,OAAAyP,GAAA,GAAG,IAKZtT,KAAKuqL,aAAe,KAEpBvqL,KAAKwpL,UAAW,EAGhB,IAAIqB,EAAgB7qL,KAAK8qL,iBAAiBjnL,GAE1C,OAAO7D,KACJ+qL,mBAAmBF,EAAeA,IAAkBhnL,GACpDa,MACAvE,KACC,OAAA+O,GAAA,GAAKy0B,GACI3jC,KAAKgrL,uBAAuBrnJ,EAAWn/B,SAAUqmL,KAMxD,iBAAiBhnL,GACvB,OAAIA,EAAM80D,MAAM,WACP90D,EAAM+gH,OAAO,GAEb/gH,EAIH,mBAAmBA,EAAcowD,GACvC,OAAOj0D,KACJyD,aACAmC,cACAqlL,oBAAoBpnL,EAAOowD,GAGxB,uBAAuBnwD,EAA+BD,GAC5D,IAAIqnL,EAAcpnL,EAAQoL,IAAKvJ,IAC7B,IAAImF,EAAQ,CACV5C,GAAIvC,EAAGuC,GACPkhE,QAASzjE,EAAGyjE,QACZztB,OAAQh2C,EAAGg2C,OAAOl1C,KAClBkkL,SAAUhlL,EAAGg2C,OAAOrgC,WACpB3W,MAAOgB,EAAGhB,MACV+W,QAAS/V,EAAG+V,QAAQjV,KACpB4U,OAAQ1V,EAAG0V,QAQb,OAJIxX,IAAU8B,EAAGuC,GAAIma,aACnBriB,KAAKuqL,aAAez/K,GAGfA,IAGLqgL,EAAgBnrL,KAAKorL,wBAMzB,OAJKprL,KAAKuqL,eACRvqL,KAAKuqL,aAAeY,EAAc,IAG5BA,EAAwD9hK,OAAO6hK,GAIjE,wBACN,IAAIC,EAAgB,GAYpB,OATInrL,KAAK06K,sBAAsBl/J,OAC7B2vK,EAAcjqL,KAAK,uCACnBiqL,EAAcjqL,KAAK,oBAEyB,oBAA1ClB,KAAKgmL,oBAAoBrK,cAC3BwP,EAAc3mK,UAEhB2mK,EAAcjqL,KAAK,gBAEZiqL,EAAcj8K,IAAKm8K,IACjB,CAAE1P,aAAc0P,EAAYzzK,KAAM5X,KAAK4X,KAAKyzK,MA8B/C,kBACNrrL,KAAKwpL,UAAW,EAChBxpL,KAAKo0C,kBAAkBk3I,UAAUC,SAASvrL,KAAKo0C,kBAAkBk3I,UAAUE,cAAc,IAEzFxrL,KAAKH,MAAMS,gBAGL,cAAc00D,GACpB,OAAQA,GACN,IAAK,eAAgB,CACnB,IAAIy2H,GAAgB,EAC0B,QAA1CzrL,KAAKgmL,oBAAoBrK,eAC3B8P,GAAgB,EAChBzrL,KAAKgmL,oBAAoBE,eAAgB,GAE3ClmL,KAAKgmL,oBAAoBrK,aAAe,MACxC37K,KAAKmqL,qBAAqBsB,GAC1B,MAEF,IAAK,kBACHzrL,KAAKgmL,oBAAoBrK,aAAe,kBACxC37K,KAAKmqL,uBACL,MAEF,IAAK,sCACHnqL,KAAKgmL,oBAAoBrK,aAAe,GACxC37K,KAAKmqL,wBAMJ,qBAAqBsB,GAAwB,GAElD,GADAzrL,KAAKgmL,oBAAoBn+G,WAAa7nE,KAAKm3D,aACvCn3D,KAAKm3D,aAAalwD,OAAS,EAAG,CAGhC,GAFAjH,KAAKo0C,kBAAkBrpC,SAElB0gL,GACHzrL,KAAKgmL,oBAAoB0F,iBACe,kBAAxC1rL,KAAKgmL,oBAAoBzgH,WAMzB,YALA/kD,OAAOgnJ,QACJmkB,aAAa,GACZ,GAAGjrL,KAAKU,EAAE,4BAA4BpB,KAAKo0C,kBAAkByzB,aAC7D7nE,KAAKgmL,oBAAoBtK,cAI/B17K,KAAKgmL,oBAAoB4F,gBAItB,OACL5rL,KAAKo0C,kBAAkByzB,WAAa,GACjB38D,SAASglD,cAAe7iD,OAG7C,mBACE,IAAIw+K,EAAe7rL,KAAKgmL,oBAAoBrK,aAC5C,MAAyB,KAAjBkQ,EAAuB,sCAAwCA,EAGjE,aACF7rL,KAAK8rL,2BACP9rL,KAAK8rL,2BACL9rL,KAAK8rL,8BAA2BpgL,GAI5B,qBACN7E,OAAO,aAAak0B,YAAY,0BAA2B/6B,KAAK0Q,W,uCAtWvD,IAA0B,wG,wBAA1B,GAA0B,4D,OAAA,M,iBAE1B,MAAmB,I,wJAFnB,qB,i2CDlFb,gBACI,qBAOA,wBAOU,6DAA0B,2BAMjB,EAAAg4D,YANT,CAA0B,0BAOlB,EAAAqjH,eAPR,CAA0B,6BAQhB,EAAA1pJ,OAAA,KARV,CAA0B,0BASlB,EAAAgoJ,cAAA,kBATR,CAA0B,uEAA1B,CAA0B,4BAWhB,EAAAG,uBAXV,CAA0B,mCAYT,EAAAwB,+BAZjB,CAA0B,oCAaR,EAAA3+K,SAblB,CAA0B,2BAcjB,EAAA4+K,iB,gCACf,+BA4CJ,OACA,gBAOG,2CAAmB,EAAAxjL,YAAA,MACnB,oBACH,OACJ,O,MApFO,gCAeO,qCAJA,uCAHA,4CAAkC,iCAAlC,CAAkC,yBAAlC,CAAkC,iBAAlC,CAAkC,4BAAlC,CAAkC,8BAAlC,CAAkC,0CAwEzC,0CAHA,8B,mlMEzCA,MAAMyjL,GAMX,YAAmB1rL,GAAA,KAAAA,aALZ,KAAAkQ,UAAmB,EAQ1B,WACE,MAAMkf,EAAsB5vB,KAAKQ,WAAWsG,cAE5C9G,KAAKmsL,aAAev8J,EAAQoT,aAAa,iBACU,SAA/CpT,EAAQoT,aAAa,wBACvBhjC,KAAK0Q,UAAW,GAGlB,MAAM3J,EAAqB6oB,EAAQotH,mBACnCh9I,KAAKosL,YAAYtlL,cAAcuK,YAAYtK,GAC3CA,EAAO82K,gBAAgB,UAGlB,SACL79K,KAAK0Q,UAAY1Q,KAAK0Q,U,uCAvBbw7K,IAA2B,Y,wBAA3BA,GAA2B,oE,OAAA,K,wXCrCxC,oBAGE,mCAAwB,kCAAW,EAAAzqL,YAIjC,iBACF,OACA,kBAKF,Q,MAbS,sCAGiB,6CAGhB,2CAIH,qC,yCCIA,MAAM4qL,GAKX,YAAsB7rL,EACAq3D,GADA,KAAAr3D,aACA,KAAAq3D,OAGtB,WACE,IAAIjxD,EAAWC,OAAO7G,KAAKQ,WAAWsG,eAEtC9G,KAAKssL,YAAc1lL,EAASqD,KAAK,gBACjCjK,KAAKusL,YAAc3lL,EAASqD,KAAK,iBAAmBjK,KAAK63D,KAAKz2D,EAAE,8DAChEpB,KAAKwsL,SAAW5lL,EAASqD,KAAK,a,uCAdrBoiL,IAAkC,sB,wBAAlCA,GAAkC,6IAP3C,8B,KACE,kCAA2B,4BAA3B,CAA2B,0B,wCCgJhBI,G,cAAjB,SAAiBA,GAaC,EAAAltI,SAAhB,SAA4B94C,EAAakwC,GACvC9vC,OAAOo/B,OAAO,UAAUx/B,EAAQI,OAAOi6B,GAAGoF,aAAc,CACtDC,QAAS,WACPwQ,EAAK+3F,YAAc,EACnB1uI,KAAKomC,SACLpmC,KAAKimC,SAAS/a,KAAK,SAAU,QAAS,sBACtClrB,KAAKqmC,QAAQ,KAGfM,YAAa,SAAoBrB,EAAgBtkC,GAE/C6F,OAAOy+B,GAAIynC,OAAO,UAElB/sE,KAAK0sL,gBAAgBpnJ,EAAItkC,IAI3B,gBAA0BskC,EAAWtkC,EAA8Bs4C,EAAmB,MACpF,IAAIrT,EAASjmC,KACT06B,EAAkB15B,EAAMiG,OACxB0lL,EAAe3rL,EACfkvE,EAAMv5B,EAAKi2I,gBAaf,GAZa,OAATtzI,IACFqzI,EAAe3rL,EAAM0jB,MAAM40B,EAAO42B,EAAM52B,EAAO42B,EAAOA,GACtDx1C,EAAWjT,KAAK0pE,IAAInwF,EAAMiG,OAASqyC,EAAO42B,EAAOA,IAInDrpE,OAAOvC,KAAKqoL,GAAc,SAAU17J,EAAOnmB,GACzCm7B,EAAOc,gBAAgBzB,EAAIx6B,MAI7Bw6B,EAAGv5B,IAAI,SAAU,QACb2uB,EAAW15B,EAAMiG,OAAQ,CAC3B,MACM4lL,EAAyB,GAAXnyJ,EAEhBmyJ,EAH2C,IAA7B3hL,SAASwT,KAAK+hK,cAI9Bn7I,EAAGv5B,IAAI,SAAU8gL,EAAc,MAUrCC,OAAO9rL,GACEymB,KAAKC,KAAK1mB,EAAMiG,OAAS0vC,EAAKi2I,iBAGvCG,gBAAiB,SAAoB9rK,GACnC,MAAMglB,EAASjmC,KACTkrB,EAAO+a,EAAO/a,KAEpBA,EAAKsS,UAGLyI,EAAO+mJ,cAEP/rK,EAAUpV,SAAShF,OAAO2nD,OAAO,CAACl7C,GAAI2yB,EAAOrW,SAAUqW,EAAOnW,QAAQjkB,WAClEo6B,EAAOnW,QAAQgW,WACjB5a,EAAK9iB,KAAK,IAAIvB,OAAO2lF,MAAM,eAI/BwgG,YAAa,WACFhtL,KAAKkrB,KAAK0E,QAChB25H,WAAWvpJ,KAAK4vB,QAAQ25H,eAG7BjjH,YAAa,SAAoBhB,EAAWx6B,GAC1C,MAAMkpD,EAAOh0D,KAAK4vB,QAAQhuB,MACpB+W,EAA2B,aAAhB7N,EAAKyW,OAChB0sD,EAAMpnE,OAAO,SAAS8D,SAAS,wBAErCgsC,EAAKs2I,WAAWniL,EAAMmjE,GAEtB,MAAMr+C,EAAU/oB,OAAO,QACpBk0B,YAAY,oBAAqBpiB,GACjCoiB,YAAY,mBAAoBpiB,GAChCwc,OAAO84C,GACPpoC,SAASP,GAMZ,MAJa,KAAT0uB,GACDpkC,EAAgBs9J,KAAKl5H,EAAM,CAACjyC,UAAW,0BAGnC6N,GAGT88J,gBAAiB,SAAoBpnJ,EAAYtkC,GAC/C,MAAMilC,EAASjmC,KACTihB,EAAYpa,OAAOy+B,GACnB6nJ,EAAQntL,KAAK8sL,OAAO9rL,GAE1B,GAAImsL,GAAS,EACX,OAAOlnJ,EAAOmnJ,gBAAgB9nJ,EAAItkC,GAGpCilC,EAAOmnJ,gBAAgB9nJ,EAAItkC,EAAO,GAElCigB,EAAUosK,QAAO,WACf,GAhHR,SAA2BpsK,GACzB,IAAIiR,EAASjR,EAAUqsK,cACnBrhC,EAAehrI,EAAU,GAAGgrI,aAEhC,OADgBhrI,EAAU+Q,aACLi6H,EAAe/5H,EA4G1Bq7J,CAAkBtsK,GAAY,CAChC,KAAM01B,EAAK+3F,aAAey+C,EACxB,OAIFlnJ,EAAOmnJ,gBAAgB9nJ,EAAItkC,EAAO21C,EAAK+3F,aAGvCzoG,EAAO8mJ,gBAAgBznJ,WA/HnC,CAAiBmnJ,QAAuB,K,iBChGjC,MAAM,WDjDN,MAUL,YAA0Be,GAAA,KAAAA,aACxBf,GAAwBltI,SAASiuI,EAAYxtL,MA6BxC,WAAW8K,EAA2BmjE,GAC3CA,EAAIr2D,KAAK9M,EAAKw3B,OAMR,YAAYthC,EAA8BgzD,GAChD,GAAa,KAATA,EACF,OAAOhzD,EACF,GAAIgzD,EAAK/sD,QAAU,EAAG,CAC3B,MAAMwmL,EAAiBztL,KAAK0tL,cAAc1sL,EAAOgzD,GAEjD,GAAIy5H,EAAexmL,OAAS,EAC1B,OAAOwmL,EAIX,OAAOztL,KAAK2tL,aAAatrJ,OAAO2xB,GAW1B,cAAchzD,EAA8BgzD,GAClD,MAAMlwD,EAAiC,GACjC8pL,EAAa55H,EAAKvvB,cAQxB,OANAzjC,EAAM0E,QAAQ4G,KACgC,IAAxCA,EAAEg2B,MAAMmC,cAAcrnB,QAAQwwK,IAChC9pL,EAAQ5C,KAAKoL,KAIVxI,EASC,mBAAmB9C,EAA8BgmI,GAEzD,MAAMljI,EAAiC,GAUvC,OARAkjI,EAAQthI,QAAQuM,IACdnO,EAAQ5C,KAAK,CACXohC,MAAOrwB,EAAGqwB,MACVhU,OAAQrc,EAAGqc,OACX/M,OAAQ,YAILzd,EAGF,MAAMohC,EAAclkC,GACzBhB,KAAK0uI,YAAc,EACnB1uI,KAAKklC,MAAQA,EACbllC,KAAKklC,MAAMllC,KAAKwtL,YAAYvgK,KAAKjtB,KAAKklC,MAAOllC,KAAK6tL,YAAY7sL,IAY9DhB,KAAK2tL,aAAe,IAAI,GAAK3sL,EAXb,CACd8sL,YAAY,EACZC,UAAU,EACVC,UAAW,GACXxlJ,SAAU,EACVosD,SAAU,IACVq5F,iBAAkB,GAClBC,mBAAoB,EACpBr+K,KAAM,CAAC,WAMD,YAAYs+K,GACpB,MAAMx3I,EAAO32C,KAEb,MAAO,CACLolC,MAAO,GACP59B,OAAQ,SAAUoX,EAAaC,GAC7B,MAAMuvK,EAAez3I,EAAK03I,YAAYF,EAAoBvvK,EAAQo1C,MAClEn1C,EAAS83B,EAAK23I,mBAAmBH,EAAoBC,KAEvD/oJ,OAAQ,CAACC,EAAQC,KACc,UAAzBA,EAASz6B,KAAKyW,QAChBo1B,EAAK43I,eAAehpJ,EAASz6B,KAAKwjB,SAGtC/rB,OAAQ,IAAMo0C,EAAKzR,MAAM33B,QACzBsR,SAAU,CAAC7W,EAAkC84B,KAC3C6V,EAAK63I,iBAAiBxmL,EAAO84B,IAE/BgF,WAAW,EACXC,UAAW,KC1Ef,YAAsBrrB,EACAla,EACAme,EACA9e,EACAa,EACAgX,GACpB5X,MAAM,2BANc,KAAA4a,aACA,KAAAla,aACA,KAAAme,OACA,KAAA9e,QACA,KAAAa,OACA,KAAAgX,iBAXf,KAAA5T,QAAmC,KAElC,KAAAk6E,QAAS,EAYfh+E,KAAK4X,KAAO,CACV0qB,MAAO5hC,EAAKU,EAAE,mCACduhC,WAAYjiC,EAAKU,EAAE,iCACnB+gC,QAASzhC,EAAKU,EAAE,oBAIpB,WACEpB,KAAK4G,SAAWC,OAAO7G,KAAKQ,WAAWsG,eACvC9G,KAAKyuL,aAAezuL,KAAK4G,SAASkmE,QAAQ,gBAC1C9sE,KAAKklC,MAAQllC,KAAK4G,SAAS4E,KAAK,qCAChCxL,KAAKoiC,UAAYpiC,KAAK4G,SAAS4E,KAAK,0CAEpCxL,KAAKyuL,aAAa7kL,GAAG,SAAU,IAAM5J,KAAKqK,QAC1CrK,KAAKyuL,aAAa7kL,GAAG,SAAU,IAAM5J,KAAK+K,SAGrC,QACL,IACG/K,KAAKklC,MAAcwpJ,wBAAwB,WAC5C,MAAOpiL,GACPsR,QAAQC,KAAK,qCAAsCvR,GAErDtM,KAAK4G,SAAS4E,KAAK,2BAA2BO,IAAI,aAAc,UAG3D,OACL/L,KAAK4G,SAAS4E,KAAK,2BAA2BO,IAAI,aAAc,WAChE/L,KAAK2uL,eAAel/K,KAAM3L,IACxB,IAAIqqL,EAAqB9pL,EAAE6K,IAAIpL,EAAS4X,IAC/B,CAAE4mB,MAAO5mB,EAAQjV,KAAM8a,OAAQ,QAAS+M,OAAQ5S,KAGzD1b,KAAK26H,MAAM36H,KAAKklC,MAAOipJ,GACvBnuL,KAAK4uL,mBACL5uL,KAAKmjC,kBACLnjC,KAAKg+E,QAAS,EACdh+E,KAAKH,MAAMS,gBAEXN,KAAK6uL,iCAMT,sBACE,OAAO,IAGT,eAAenzK,GACb8E,OAAOgoB,SAASjjC,KAAOvF,KAAK8uL,YAAYpzK,EAAQ5G,YAGlD,iBAAiB9M,EAAkC84B,GAEjD9gC,KAAKoiC,UAAU3gC,OAA6B,IAAtBq/B,EAAGD,QAAQ55B,QAG5B,WAAW6D,EAA8BmjE,GAC9C,MAAM1nC,EAAO1/B,OAAO,OACjBoD,KAAK,OAAQjK,KAAK8uL,YAAYhkL,EAAKwjB,OAAOxZ,aAC1C8C,KAAK9M,EAAKw3B,OACVuD,SAASooC,GAGRnjE,EAAKwjB,OAAO2xD,MAAQ,GACtB15C,EACG3uB,KAAK,QAAK9M,EAAKw3B,OACfv2B,IAAI,eAAiB,EAAwB,GAApBjB,EAAKwjB,OAAO2xD,MAAc,MAIpDn1E,EAAKwjB,OAAOxZ,aAAe9U,KAAK0X,eAAe5C,YACjDm5D,EAAItjE,SAAS,YAIV,YAAYmK,GACjB,MAAMi6K,EAAkBloL,OAAO,kCAAkCoD,KAAK,WACtE,IAAI+D,EAAMhO,KAAK0a,WAAW3L,YAAY+F,GAMtC,OAJIi6K,IACF/gL,GAAO,SAAWulE,mBAAmBw7G,IAGhC/gL,EAGT,kBACE,OAAIhO,KAAKg+E,OACA,GAEAh+E,KAAK4X,KAAKuqB,QAIb,eACN,GAAqB,OAAjBniC,KAAK8D,QACP,OAAOyL,QAAQC,QAAQxP,KAAK8D,SAG9B,MAAMkK,EAAMhO,KAAK0a,WAAWs0K,uBAC5B,OAAOhvL,KAAK2e,KACTja,IAAIsJ,GACJ6e,YACApd,KAAM6vB,GACEt/B,KAAK8D,QAAU9D,KAAKivL,mBAAmB3vJ,EAAO5e,WAOpD,mBAAmBA,GACxB,MAAMosD,EAA8B,GACpC,IAAIoiH,GAAgB,EAEpB,OAAOxuK,EAASxR,IAAKwM,IACnB,KAAOwzK,GAAgBxzK,EAAQukE,OAC7BnT,EAAQ3jD,MACR+lK,IAOF,OAJApiH,EAAQ5rE,KAAKwa,GACbwzK,EAAexzK,EAAQukE,MACvBvkE,EAAQoxD,QAAUA,EAAQpoD,MAAM,GAAI,GAE7BhJ,IAQD,mBAAmB1a,EAAiCgmI,GAC5D,MAAMp1G,EAAUo1G,EAAQ93H,IAAI+C,GAAMA,EAAGqc,OAAOxZ,YACtCq6K,EAAiB9qL,EAAEkgC,QAAQyiG,EAAQ93H,IAAI+C,GAAMA,EAAGqc,OAAOw+C,UAEvDhpE,EAAoC,GAqB1C,OAnBA9C,EAAM0E,QAAQuM,IACZ,MAAM6C,EAAa7C,EAAGqc,OAAOxZ,WAC7B,IAAIohB,EAEJ,GAAItE,EAAQxU,QAAQtI,IAAe,EACjCohB,EAAa,YACR,KAAI7xB,EAAEmH,KAAK2jL,EAAgB7iL,GAAKA,EAAEwI,aAAeA,GAGtD,OAFAohB,EAAa,WAKfpyB,EAAQ5C,KAAK,CACXohC,MAAOrwB,EAAGqwB,MACVhU,OAAQrc,EAAGqc,OACX/M,OAAQ2U,MAILpyB,EAMC,mBACR9D,KAAKklC,MAAMiF,IAAI,QAEfnqC,KAAKklC,MAAMkqJ,QAASvuL,GACdA,EAAIkqB,QAAU,KAASC,SACzBhrB,KAAKklC,MAAMtjC,IAAI,IACd5B,KAAKklC,MAAcllC,KAAKwtL,YAAYvgK,KAAKjtB,KAAKklC,MAAO,SAAU,KACzD,IAYH,kBACR,IAAImqJ,GAAqB,EACzBrvL,KAAK4G,SACF4E,KAAK,uCACL5B,GAAG,QAAS,kBAAoB/I,IAC3B,KAAauR,sBAAsBvR,IACrCA,EAAI0nC,4BAGC,IAKR3+B,GAAG,WAAY,mBAAmB,SAAU/I,GACtCwuL,IACH7uK,OAAOgoB,SAASjjC,KAAQ1E,EAAIkG,OAA6BxB,SAE1DqE,GAAG,YAAa,mBAAmB,WACtCylL,GAAa,KACZzlL,GAAG,aAAc,mBAAmB,WACrCylL,GAAa,KAIP,YAAYlB,GACpB,MAAMjwK,EAAape,MAAM+tL,YAAYM,GAWrC,OARAjwK,EAAO2nB,SAAW,sCAClB3nB,EAAOuD,QAAU,CACf,kBAAmB,+CAErBvD,EAAOrS,SAAW,CAChByH,GAAI,+CAGC4K,EAGD,+BACN,IAAIxG,EAAkCxM,SAAS2O,cAAc,kCAG7D,IAAKnC,EACH,OAGF,IAAI43K,EAAuB53K,EAAe+oK,aACtCz0B,EAAsB9gJ,SAASqtF,uBAAuB,sCAAsC,GAI5Fg3F,EAAc73K,EAAe0a,UAC9B45H,EAAoCy0B,aAAe,EACpD6O,EAAuB,EAIzBtjC,EAAoBh6H,UAAau9J,EAAcD,GAAyB,EACtEC,EACAA,EAAeA,EAAcD,G,uCA/QtB,IAAgC,gE,wBAAhC,GAAgC,opBCzD7C,gBACE,gBACE,gBACE,kBACA,kBAKA,cACF,OACA,cACF,OACF,Q,MAV2E,yCAK9D,0CAG+C,gD,oCC2BrD,MAAM,GAEX,YAAoB9uL,EACAme,GADA,KAAAne,aACA,KAAAme,OASpB,WACE,MAAM/X,EAAWC,OAAO7G,KAAKQ,WAAWsG,eAClCwiL,EAAQ1iL,EAAS8H,SACvB1O,KAAKm9H,OAASmsD,EAAM99K,KAAK,wBACzBxL,KAAK+G,OAASuiL,EAAM99K,KAAK,yBAEzBxL,KAAKgO,IAAMpH,EAASuH,KAAK,OACzBnO,KAAKwvL,SAAqC,SAA1B5oL,EAASuH,KAAK,QAE9BnO,KAAKm9H,OAAOvzH,GAAG,eAAgBvF,EAAE2pF,SAAUhmF,IAOzC,IAAIynL,EAAgB,CAAC,KAASC,IAAK,KAAStnJ,MAAO,KAASunJ,QACzC,WAAf3nL,EAAM8K,MAAsB9K,EAAM+iB,QAAiD,IAAxC0kK,EAAcryK,QAAQpV,EAAM+iB,SACzE/qB,KAAK4vL,WAEN,MAGG,QAAQ1xK,GACd,MAAMC,EAAc,GASpB,OANIne,KAAKwvL,SACPrxK,EAAgB,OAAI,YAEpBA,EAAgB,OAAI,mBAGfne,KAAK2e,KACTja,IACC1E,KAAKgO,IACL,CACEkQ,OAAQA,EACRC,QAASA,EACTI,aAAeve,KAAKwvL,SAAW,OAAS,OACxClxK,iBAAiB,IAKjB,UACN,IAAIJ,EAAa,GAGjBle,KAAKm9H,OAAO74H,KAAK,CAACyY,EAAG9K,KACnBiM,EAAOjM,EAAGxB,QAAQo/K,gBAAmB59K,EAAG9L,QAG1CnG,KACG4e,QAAQV,GACR7d,UAAWwe,IACR7e,KAAKwvL,SAEPxvL,KAAK+G,OAAO+8F,KAAKjlF,GAEjBxa,EAAEC,KAAKua,EAAU,CAACjd,EAAY6vB,KAC5B,IAAI7B,EAAU1kB,SAASC,eAAesmB,GAElC7B,aAAmBquI,iBACrBruI,EAAQzpB,MAAQvE,EACPguB,IACTA,EAAQre,YAAc3P,Q,uCA9ErB,IAA2B,uB,wBAA3B,GAA2B,+F,iBCIjC,MAAM,WAAmC,KAe9C,YAAqBpB,EACAX,EACAmmL,EACAtlL,EACAqI,GACnBjJ,QALmB,KAAAU,aACA,KAAAX,QACA,KAAAmmL,sBACA,KAAAtlL,OACA,KAAAqI,WAXd,KAAA6O,KAA+B,CACpC8xK,aAAc1pL,KAAKU,KAAKU,EAAE,uCAC1B0uL,wBAAyB9vL,KAAKU,KAAKU,EAAE,kDACrC2uL,WAAY/vL,KAAKU,KAAKU,EAAE,qCACxB4uL,GAAIhwL,KAAKU,KAAKU,EAAE,gBAWlB,WAEE,OAAA+5F,GAAA,GAAc,CACZn7F,KAAKgmL,oBAAoBpL,YACzB56K,KAAKgmL,oBAAoBhL,gBAExB76K,KACC,OAAAq5C,GAAA,KACAx5C,KAAKI,kBAENC,UAAU,EAAE+lL,EAAeC,MAC1BrmL,KAAK6nE,WAAau+G,EAClBpmL,KAAK0b,QAAU1b,KAAKiwL,YAAY5J,GAChCrmL,KAAKkwL,YAAc,GAAGlwL,KAAK4X,KAAKm4K,cAAc/vL,KAAK6nE,cAA+B,KAAjB7nE,KAAK0b,QAAiB,GAAK1b,KAAK4X,KAAKo4K,MAAMhwL,KAAK0b,UAEjH1b,KAAKH,MAAMS,kBAIT,YAAY00D,GAClB,IAAIm7H,EAAqBnwL,KAAK06K,sBAAsBj0K,KAAOzG,KAAK06K,sBAAsBj0K,KAAO,GAE7F,OAAQuuD,GACN,IAAK,MACH,OAAOh1D,KAAK4X,KAAK8xK,aAEnB,IAAK,kBACH,OAAOyG,EAET,IAAK,GACH,OAAOA,EAAqB,IAAMnwL,KAAK4X,KAAKk4K,wBAE9C,QACE,MAAO,K,wC/MhGX,aAGE,eAAqB,qFAAoD,OAC3E,O,qCAHI,uCACA,oBACC,iCAAiB,uB,uC+MqCb,IAA0B,mD,wBAA1B,GAA0B,mSC1CvC,gBACE,gBACE,gBACE,aACE,QACA,YAAG,QAAkB,OACrB,QACA,YAAG,QAAa,OAClB,OACA,gBACF,OACF,OACF,Q,MATU,oCACF,wCACG,mCACH,kDACG,0B,kBDyCM,aAAd,c,0BAA4C,O,6CERxC,MAAM,WAAkC,KAM7C,YAAqB9J,GACnBlmL,QADmB,KAAAkmL,sBAFd,KAAAvkK,QAAmB,CAAC,sBAAuB,mBAMlD,WACEzhB,KAAKowL,cAAgBpwL,KAAKgmL,oBACvBlL,YACAz6K,UAAWklE,IACVvlE,KAAK8oJ,aAAevjF,IAGxBvlE,KAAKqwL,QAAUrwL,KAAKgmL,oBACjB/K,MACA56K,UAAWuhJ,IACV5hJ,KAAK4hJ,KAAOA,EACZ5hJ,KAAK4hJ,KAAK1yI,IAAKs2D,GAAQA,EAAIhqD,KAAO,OAIjC,SAASgqD,GACd1lE,MAAMwwL,SAAS9qH,GAEfxlE,KAAKgmL,oBAAoBzgH,WAAaC,EACtCxlE,KAAKgmL,oBAAoB4F,eAG3B,cACE5rL,KAAKowL,cAAcrzJ,cACnB/8B,KAAKqwL,QAAQtzJ,e,wCChCb,gBAGK,0DAAmBmF,cAAA,uBAEtB,cACE,cACF,OACF,O,uBANK,6B,uCDJI,IAAyB,W,wBAAzB,GAAyB,ycjNxCtC,kBACE,iBAA+B,kCAAU,EAAAsnH,SAAA,MACvC,sBAKF,OACA,kBAEoB,gCAAS,EAAA5/G,gBAC3B,iBACF,OACA,kBAEqB,gCAAS,EAAA6/G,iBAC5B,mBACF,OACF,Q,MAlBsB,0BAEd,+BAMc,wCAKC,2C,yCkNyChB,MAAM,WAAgC,KAI3C,YAAqBvnH,EACAriC,EACA8qF,EACA5hF,GACnBjJ,QAJmB,KAAAoiC,gBACA,KAAAriC,QACA,KAAA8qF,gBACA,KAAA5hF,WANrB,KAAA0jF,YAAqB,GAUrB,WACEzsF,KAAKkiC,cAAcquJ,iBAEnBvwL,KAAKkiC,cAAcopD,WAChBnrF,KACC,OAAAq5C,GAAA,KACAx5C,KAAKI,kBAENC,UAAUgsF,IACTrsF,KAAKysF,YAAcJ,EACnBrsF,KAAKH,MAAMS,mB,uCArBN,IAAuB,4C,wBAAvB,GAAuB,0VAZhC,uB,KAAK,mE,2DAcQ,aAAd,c,0BAA6B,O,gF9nB3C5B,wB,yBACa,gB,0BADb,+BAIA,S,oBAJa,uBAIb,8B+nBFG,MAAM,WAAsC,KAIvC,kBAAkB0N,EAAY65D,GACtC,OAAO7nE,KAAK2e,KACTja,IAAIsJ,EACH,CACEkQ,OAAQ,IAAI,KAAW,CAAEE,QAAS,IAAI,KAAoBC,WAAY,CAAE66C,EAAG2O,KAC3EtpD,aAAc,OACdJ,QAAS,CAAE,eAAgB,qCAG9Bhe,KACC,OAAA+O,GAAA,GAAKs5D,GACIA,EAAI1kE,QAAQ9C,MAAMkO,IAAK+C,IAC5B,MAAM1M,EAAO,QAAQguD,KAAKthD,EAAG/J,GAAGma,YAAcriB,KAAK6O,WAAWuM,SAASnJ,EAAG/J,IAAM,KAChF,MAAO,CAAEzB,KAAMwL,EAAGxL,KAAMyB,GAAI+J,EAAG/J,GAAI3C,KAAMA,Q,sCAjBxC,K,wBAAA,GAA6B,mX/nBf1C,sBAQW,gCAAS,EAAAmjE,YAAT,CAAmB,6BACT,EAAAC,cAAA,M,gCAGnB,+BAOF,Q,KAnBW,2CAAkC,6BAAlC,CAAkC,mBAAlC,CAAkC,0BAAlC,CAAkC,8BAAlC,CAAkC,yCAAlC,CAAkC,sBAAlC,CAAkC,wB,6E+nBgB5B,aAAd,c,0BAAmB,O,4BACL,aAAd,c,0BAAyB,M,gDAFf,ICKN,MAAM,GAsBX,YAAqBjoE,EACCie,EACD9P,EACCjP,GAHD,KAAAc,OACC,KAAAie,OACD,KAAA9P,aACC,KAAAjP,uBAvBtB,KAAA4wL,UAAY,cAQL,KAAAC,WAAY,EAEZ,KAAA9uF,WAAY,EAGZ,KAAA+uF,cAAuB,EACvB,KAAA94K,KAAO,CACZ+4K,cAAe3wL,KAAKU,KAAKU,EAAE,gDAC3BwvL,YAAa5wL,KAAKU,KAAKU,EAAE,8CACzByvL,aAAc7wL,KAAKU,KAAKU,EAAE,gDAO1B,IAAIg3D,EAAO53C,OAAe43C,IAC1Bp4D,KAAK8wL,aAAe14H,EAAI24H,UACxB/wL,KAAKgxL,aAAe54H,EAAI64H,cAEnBzwK,OAAe43C,IAAI84H,cACtBlxL,KAAKmxL,yBAMF,SAAS/sL,GACd,MAAMwa,EAAU,OAAH,wBAAQxa,EAAK+B,OAAK,CAAE8qL,cAAejxL,KAAKgxL,eACrDhxL,KAAK2e,KAAKyO,KAAKptB,KAAK8wL,aAAe,oBAAqBlyK,GACrDiO,YACApd,KAAM2hL,IACLpxL,KAAKwwL,UAAUxsL,SAASI,EAAK+B,OAC7BnG,KAAK2hG,WAAY,EAEjB3hG,KAAKqxL,UAAYD,EAAgBjjK,OAAOnjB,KAAKzF,KAC7CvF,KAAKsxL,aAAatxL,KAAKqxL,WAEvBrxL,KAAKuxL,sBAEN/2K,MAAOwE,IAEe,MAAjBA,EAAM28B,QAAmC,MAAjB38B,EAAM28B,OAChC37C,KAAKgf,MAAQA,EAEbhf,KAAKJ,qBAAqB4xL,WAAWxyK,EAAMA,MAAMhd,aAAetB,KAAKU,EAAE,wBAMxE,WAELpB,KAAK2e,KACFja,IAAS1E,KAAKqxL,WACdxkK,YACApd,KAAY+4D,GAAY,4CAEvBxoE,KAAK0mD,WAAY,EAIZ8hB,EAAIipH,wBACDzxL,KAAK0xL,UAAUlpH,EAAI67C,YAG5B7pG,MAAOwE,IAEe,MAAjBA,EAAM28B,QAA6C,mCAA3B38B,EAAMA,MAAMlK,YAEtC9U,KAAK2xL,WAAa3yK,EAAMA,MAAMmP,OAAOyjK,OAAOrsL,KAEvCvF,KAAK27C,SAAU37C,KAAK2hG,WACvB3hG,KAAKsxL,aAAatxL,KAAK2xL,YAGzB3xL,KAAKmxL,yBACLnxL,KAAK0mD,WAAY,GACwB,UAAhCriD,EAAEK,IAAIsa,EAAO,eACtBhf,KAAKJ,qBAAqBm6D,SAAS/6C,EAAMA,MAAMw7B,SAE/Cx6C,KAAKJ,qBAAqBm6D,SAAS/6C,EAAMA,OAASte,KAAKU,EAAE,wBAQzD,aAAaywL,GAEnB,IAAIC,EAAWD,EAAWx5K,MAAM,KAAK,GACrC,OAAOrY,KAAK2e,KAAKyO,KACfptB,KAAK6O,WAAW0R,YAAc,mCAC9B,CAAEwxK,UAAWD,GACb,CAAExzK,iBAAiB,IAElBuO,YACArS,MAAOlO,IACNtM,KAAKJ,qBAAqBm6D,SAASztD,EAAE0S,MAAMw7B,SAAWluC,EAAEkuC,SAAWluC,KAKjE,UAAU+3G,GAChB,OAAOrkH,KAAK2e,KAAKyO,KACfptB,KAAK6O,WAAW0R,YAAc,oBAC9B,CAAEyxK,iBAAkB,CAAEC,cAAe5tE,IACrC,CAAE/lG,iBAAiB,IAElBuO,YACApd,KAAK,KAECzP,KAAKywL,WACRnjL,WAAW,KACTkT,OAAOgoB,SAASR,UACf,OAGNxtB,MAAOwE,IAGNhf,KAAK2e,KACF+2B,OACD11C,KAAK6O,WAAWq7C,IAAIC,GAAGC,UAAY,qCACrC,CAAE9rC,iBAAiB,IAEhBuO,YAEH7sB,KAAKJ,qBAAqBm6D,SAAS/6C,EAAMA,MAAMhd,aAAetB,KAAKU,EAAE,wBAKpE,kBAAkBgkC,EAAe,IAAM8sJ,EAAiB,IACzDlyL,KAAK2hG,WAAa3hG,KAAK0mD,YAEJ,IAAZwrI,EACTlyL,KAAK2hG,WAAY,GAEjB3hG,KAAKmyL,WACL7kL,WAAW,KACTtN,KAAKuxL,kBAAkBnsJ,EAAO8sJ,EAAU,IACvC9sJ,KAIA,sBACLplC,KAAK27C,OAAS,aAGT,yBACL37C,KAAK27C,OAAS,gBAGhB,mBACE,MAAuB,eAAhB37C,KAAK27C,OAGd,oBACE,MAAuB,kBAAhB37C,KAAK27C,OAGd,kBACE,QAAO37C,KAAKgf,OAAwC,iBAAhChf,KAAKgf,MAAMA,MAAMlK,WAGvC,iBACE,QAAO9U,KAAKgf,OAAwC,+BAAhChf,KAAKgf,MAAMA,MAAMlK,WAGvC,iBACE,QAAI9U,KAAK0wL,gBAEE1wL,KAAKgf,OACPhf,KAAKoyL,WAMhB,eACE,IAAIpzK,EAAe,GASnB,OARIhf,KAAK0wL,aACP1xK,EAAQhf,KAAK4X,KAAK+4K,cACT3wL,KAAKqyL,YACdrzK,EAAQhf,KAAK4X,KAAKi5K,aACT7wL,KAAKoyL,aACdpzK,EAAQhf,KAAK4X,KAAKg5K,aAGb5xK,G,uCAzME,IAAsB,2C,0BAAtB,GAAsB,QAAtB,GAAsB,Y,ICpBlBszK,G,uCC6Cb,iBAA6F,QAA6B,Q,oBAA7B,yC,0BAc7F,iBAAyE,QAA6B,Q,oBAA7B,0CD3D7E,SAAiBA,GAaC,EAAAC,aAAhB,SAA6BrjL,GAG3B,OAAOA,EAFQxO,KAAK+nD,SAEEv5C,EAAIsjL,IAhB9B,CAAiBF,QAAW,K,yDE0CrB,MAAM,GAqCX,YAAqB9xL,EACAE,EACD+xL,EACCC,EACFC,GAJE,KAAAnyL,aACA,KAAAE,OACD,KAAA+xL,cACC,KAAAC,qBACF,KAAAC,iBAvCnB,KAAAC,SAAwC5yL,KAAK2yL,eAAenC,UAAU/8K,WAAW,IAEjF,KAAAo/K,UAAY7yL,KAAKyyL,YAAY59K,MAAM,CACjCi+K,QAAS,CAAC9yL,KAAK4yL,SAASE,QAAS,IAAWv5K,UAC5Cw5K,WAAY,CAAC/yL,KAAK4yL,SAASG,WAAY,IAAWx5K,UAClDy5K,UAAW,CAAChzL,KAAK4yL,SAASI,UAAW,IAAWz5K,UAChDstI,MAAO,CAAC,GAAI,CAAC,IAAWttI,SAAU,IAAWstI,QAC7CosC,OAAQ,CAACjzL,KAAK4yL,SAASK,QAAUzyK,OAAOgoB,SAAS0qJ,KAAM,IAAW35K,UAClE45K,gBAAiB,CAAC,KAAM,IAAW55K,UACnC65K,mBAAoB,KACpBxyJ,SAAU5gC,KAAK0yL,mBAAmB9xJ,WAG7B,KAAAhpB,KAAO,CACZu7K,gBAAiBnzL,KAAKU,KAAKU,EAAE,iDAAkD,CAC7EiyL,WAAYf,GAAYC,aAAa,CACnCC,GAAI,gDACJc,GAAI,wDAENC,aAAcjB,GAAYC,aAAa,CACrCC,GAAI,yDACJc,GAAI,kDAGRE,cAAexzL,KAAKU,KAAKU,EAAE,0CAC3BqyL,cAAezzL,KAAKU,KAAKU,EAAE,gDAC3BsyL,iBAAkB1zL,KAAKU,KAAKU,EAAE,mDAC9BuyL,gBAAiB3zL,KAAKU,KAAKU,EAAE,kDAC7BwyL,YAAa5zL,KAAKU,KAAKU,EAAE,8CACzByyL,aAAc7zL,KAAKU,KAAKU,EAAE,+CAC1B0yL,eAAgB9zL,KAAKU,KAAKU,EAAE,iDAC5B2yL,mBAAoB/zL,KAAKU,KAAKU,EAAE,oDAAqD,CAAEmlC,KAxCrE,4CAyClBytJ,iBAAkBh0L,KAAKU,KAAKU,EAAE,oDAazB,iBAC8B,KAA/BpB,KAAK6yL,UAAU1sL,MAAM0gJ,OAAgB7mJ,KAAK6yL,UAAUoB,SAASptC,MAAM5pH,OACrEj9B,KAAK2yL,eAAejC,cAAe,GAEnC1wL,KAAK2yL,eAAejC,cAAe,EACnC1wL,KAAK2yL,eAAe3zK,WAAQtT,I,uCApDrB,IAAoB,oD,wBAApB,GAAoB,4oDD1CjC,iBACE,gBACE,kBAAoD,QAAwB,OAC5E,gBACE,gBACE,kBAIF,OACF,OACF,OACA,gBACE,kBAAkD,QAA2B,OAC7E,iBACE,iBACE,mBAIF,OACF,OACF,OACA,iBACE,mBAAiD,SAA0B,OAC3E,iBACE,iBACE,mBAIF,OACF,OACF,OACA,iBACE,oBAA6C,SAAsB,OACnE,iBACE,kBAEE,oBAG+B,+BAAQ,EAAAwoL,oBAHvC,OAIF,OACF,OACA,yBACF,OACA,iBACE,oBAAmD,SAAuB,OAC1E,iBACE,kBAEE,oBAKF,OACF,OACA,yBACF,OACA,kBACE,iBACE,oBACE,kBACE,oBAKF,OACA,mBACF,OACF,OACF,OACA,kBACE,iBACE,oBACE,kBACE,oBAIF,OACA,mBACF,OACF,OACF,OACF,Q,MAxF8C,8BAEU,mCAWF,sCAWD,qCAWJ,iCAGtC,gEAOF,iDAG8C,kCAG5C,iEAQF,kDAYK,sDAaA,2D,gIErDP,MAAM,WAA0B,KAWrC,YAAqBxzL,GACnBZ,QADmB,KAAAY,OAVd,KAAAkX,KAAO,CACZg8K,YAAa5zL,KAAKU,KAAKU,EAAE,8CACzB+yL,iBAAkBn0L,KAAKU,KAAKU,EAAE,mDAC9BgzL,oBAAqBp0L,KAAKU,KAAKU,EAAE,sDACjCqyL,cAAezzL,KAAKU,KAAKU,EAAE,gDAC3ByyL,aAAc7zL,KAAKU,KAAKU,EAAE,+CAC1BizL,gBAAiBr0L,KAAKU,KAAKU,EAAE,kDAC7BkzL,iBAAkBt0L,KAAKU,KAAKU,EAAE,qD,yBCxB5B,gB,oBAAuD,0C,0BACvD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,uC,yBAGV,gB,oBAAsD,yC,0BACtD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,sC,yBAGV,gB,oBAAyD,gD,0BACzD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,yC,yBAGV,gB,oBAAwD,4C,0BACxD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,wC,yBAIV,gB,oBAAyD,6C,0BACzD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,yCCFT,MAAM,WAA+B,GAS1C,YAAqBZ,EACAX,EACAa,EACAie,EACAo9J,EACF4W,GACjB7yL,MAAMY,GANa,KAAAF,aACA,KAAAX,QACA,KAAAa,OACA,KAAAie,OACA,KAAAo9J,MACF,KAAA4W,iBAInB,WACO3yL,KAAKu0L,aACRv0L,KAAK2yL,eAAenC,UACjBtwL,UACAC,KACC,OAAAq5C,GAAA,KACAx5C,KAAKI,kBAENC,UAAUm0L,IACTx0L,KAAKy0L,eAAeD,GACpBx0L,KAAKH,MAAMS,kBAGfN,KAAKgG,cAID,aACN,IAAI0uL,EAAa10L,KAAK+7K,IAAIr3K,IAAI,gBAE1BgwL,IAAe10L,KAAK2yL,eAAenC,UAAUluL,aAE/CtC,KAAK2yL,eAAetB,UAAYrxL,KAAK2yL,eAAe7B,aAAe,qBAAuB4D,EAAWvuL,MACrGnG,KAAK20L,wBAMD,uBACN30L,KAAK2e,KACFja,IAAS1E,KAAK2yL,eAAetB,UAAY,YACzCxkK,YACApd,KAAM+kL,IACLx0L,KAAK2yL,eAAenC,UAAUxsL,SAASwwL,GACvCx0L,KAAK2yL,eAAepB,sBAErB/2K,MAAOwE,IAENhf,KAAK2yL,eAAeR,aAIlB,eAAeqC,GACrBx0L,KAAKu0L,WAAaC,EAASzB,WAAa,IAAMyB,EAASxB,UACvDhzL,KAAK6mJ,MAAQ2tC,EAAS3tC,MACtB7mJ,KAAK8yL,QAAU0B,EAAS1B,QACxB9yL,KAAKizL,OAASuB,EAASvB,Q,0BCjGvB,YAAoC,QAA0B,Q,qBAA1B,sC,wCAJtC,iBACE,QAEA,cAAoB,+DAAuB,QAAiB,OAC5D,qBACF,O,uBAJE,4CAE2C,4BACxC,iD,0BAIH,iBAA0C,QAA2B,Q,oBAA3B,8C,uCD4BjC,IAAsB,+D,wBAAtB,GAAsB,kdDzCnC,gBACE,gBACE,gBACE,gBACA,gBACE,gBACE,iBACF,OACF,OACA,gBACA,gBACE,gBACE,kBACF,OACF,OACA,wBACA,wBAKA,wBACA,wBAKA,wBACA,wBAKA,wBACA,wBAMA,wBACA,wBAKF,OACF,OACF,Q,MA7C6C,oDAG7B,yCAG6B,+CAG7B,oCAGL,+BACA,+BAKA,8BACA,8BAKA,iCACA,iCAKA,gCACA,gCAMA,iCACA,mC,2FGAJ,MAAM,GAkBX,YAAqBzyL,EACAE,EACCie,EACA/e,EACH+yL,EACEh4K,GALA,KAAAna,aACA,KAAAE,OACC,KAAAie,OACA,KAAA/e,uBACH,KAAA+yL,iBACE,KAAAh4K,kBAtBrB,KAAAi6K,QAAU50L,KAAK2a,gBAAgB8yE,eAAc,IAAIz+D,MAAO3M,YACxD,KAAAwkI,MAAe,GAER,KAAAjvI,KAAO,CACZi9K,kBAAmB,CAAC5qK,EAAa48H,IAAiB7mJ,KAAKU,KAAKU,EAAE,8CAA8C,CAC1G6oB,KAAMA,EACN48H,MAAOA,IAET+qC,OAAQ5xL,KAAKU,KAAKU,EAAE,yCACpB0zL,eAAgB90L,KAAKU,KAAKU,EAAE,4CAC5B2zL,eAAgB/0L,KAAKU,KAAKU,EAAE,4CAC5B4zL,gBAAiBh1L,KAAKU,KAAKU,EAAE,6CAC7B6zL,iBAAkBj1L,KAAKU,KAAKU,EAAE,8CAC9B8zL,aAAcl1L,KAAKU,KAAKU,EAAE,0CAC1B+zL,eAAgBn1L,KAAKU,KAAKU,EAAE,6CAW9B,WACE,IAAIszL,EAAcl0K,OAAe43C,IAAI84H,aACrC,GAAIwD,EAAY,CACd,IAAIU,EAAeV,EAAWE,QAAQv8K,MAAM,KAAK,GACjDrY,KAAK40L,QAAU50L,KAAK2a,gBAAgB8yE,cAAc2nG,GAGpDp1L,KAAK2yL,eAAenC,UACjBtwL,UACAC,KACC,OAAAq5C,GAAA,MAEDn5C,UAAUm0L,IACTx0L,KAAK6mJ,MAAQ2tC,EAAS3tC,QAKrB,aACL7mJ,KAAK2yL,eAAehxF,WAAY,EAChC3hG,KAAK2e,KAAKyO,KAAKptB,KAAK2yL,eAAehB,WAAY,IAC5C9kK,YACApd,KAAK,KACJzP,KAAKJ,qBAAqBsrD,WAAWlrD,KAAK4X,KAAKk9K,gBAC/C90L,KAAK2yL,eAAepB,sBAErB/2K,MAAM,KACDxa,KAAK2yL,eAAetB,UAEtBrxL,KAAK2yL,eAAeR,WAEpBnyL,KAAKJ,qBAAqBm6D,SAAS/5D,KAAK4X,KAAKm9K,mB,wCC5FjD,eACE,eAAsB,iEACtB,OACF,O,uBAFqD,0C,uBAOrD,cACE,gCACF,Q,uBAEA,cACE,mCACF,Q,0BAEA,cACE,iBACE,iBACE,eAAM,QAAyB,OACjC,OACA,iBACE,oBAMF,OACF,OACF,Q,oBAXY,oCAME,8C,wCASd,cACE,oBACQ,6DAKR,OACA,oBACQ,iEAGR,OACF,O,uBAVU,2DAA4C,mCAA5C,CAA4C,sEAE5C,mCAKA,iDACA,oC,wCAWR,oBAEQ,kEAGR,O,wBAFQ,2CACA,sC,wCAXR,oBACQ,yEAKR,OACA,2B,uBALQ,2CAAoC,uCAApC,CAAoC,wCACpC,qCAIA,oD,uCDrBH,IAAuB,+D,wBAAvB,GAAuB,kQ,GAAA,MDzCpC,kCAEA,YAAG,QAA4C,OAC/C,YACE,eAAM,QAAwB,OAC9B,wBAOA,yCAGF,Q,qBAbG,0DAEK,yCACA,iDAAuD,gB,0NGwCxD,MAAM,WAA6B,IAuBxC,YAAqBv0L,EAC0BsR,EAC1BjS,EACAa,EACA4tK,EACFqkB,GACjB7yL,MAAMgS,EAAQjS,EAAOW,GANF,KAAAA,aAC0B,KAAAsR,SAC1B,KAAAjS,QACA,KAAAa,OACA,KAAA4tK,eACF,KAAAqkB,iBArBZ,KAAAtrI,WAAY,EACZ,KAAAJ,eAAgB,EAChB,KAAAE,qBAAsB,EAGtB,KAAAvvC,KAAO,CACZy9K,cAAer1L,KAAKU,KAAKU,EAAE,2BAC3BwlD,cAAe5mD,KAAKU,KAAKU,EAAE,2BAC3BulD,gBAAiB3mD,KAAKU,KAAKU,EAAE,sBAC7BylD,YAAa7mD,KAAKU,KAAKU,EAAE,wBACzBk0L,qBAAsBt1L,KAAKU,KAAKU,EAAE,0CAClCm0L,mBAAoBv1L,KAAKU,KAAKU,EAAE,wCAChCo0L,gBAAiBx1L,KAAKU,KAAKU,EAAE,qCAC7Bq0L,eAAgBz1L,KAAKU,KAAKU,EAAE,6CAU5BpB,KAAK01L,kBAAoB11L,KAAK21L,WArCE,wDAwClC,kBACE31L,KAAK6yL,UAAY7yL,KAAK41L,cAAc/C,UAI/B,WACD7yL,KAAK6yL,UAAUgD,QACjB71L,KAAK6yL,UAAUiD,WAAW,QAAS,IAAI,IAAY,qBACnD91L,KAAK2yL,eAAeoD,SAAS/1L,KAAK6yL,YAI/B,uBAEL7yL,KAAK2yL,eAAeqD,sBAGf,aACL,OAAIh2L,KAAK2yL,eAAesD,cACfj2L,KAAK4X,KAAK09K,qBACRt1L,KAAK2yL,eAAeuD,aACtBl2L,KAAK4X,KAAK29K,mBAEVv1L,KAAK4X,KAAK49K,gBAId,WAAWxtL,GAChBhI,KAAKsnD,QAAQt/C,IAEThI,KAAK2yL,eAAeuD,cAAgBl2L,KAAK2yL,eAAejsI,YAC1DlmC,OAAOgoB,SAASR,SAElBhoC,KAAK2yL,eAAelC,WAAY,EAG3B,WAAWziL,GAChB,OAAOhO,KAAKsuK,aAAauY,+BAA+B74K,GAGnD,aACL,OAAKhO,KAAK2yL,eAAeh3I,QAAU37C,KAAK2yL,eAAehxF,UAC9C,EACE3hG,KAAK2yL,eAAesD,gBAAkBj2L,KAAK2yL,eAAehxF,UAC5D,EAEA,G,wCC5Hb,cACE,YAAG,QAA6B,OAChC,cAAiB,QAAqB,OACtC,YACE,iBAAoB,QAAsB,OAAO,aACjD,eAAM,SAAyB,OACjC,OACA,oBAAsC,mEACpC,SACF,OACF,O,uBATK,wCACc,gCAEK,iCACd,oCAGN,2C,wCAKF,mCACA,cAA6B,QAC3B,cAAG,mEAA2B,QAA4B,OAC5D,O,uBAF6B,+CACG,wC,uCD8BrB,IAAoB,eAwBX,KAAkB,yC,wBAxB3B,GAAoB,+D,OAAA,K,KACpB,IAAsB,G,2pCD9CnC,gBACE,gBAGE,gBACE,eACA,qBAIF,OAEA,gBAEE,uBAIA,uBAIA,uBAeF,OAEA,gBACE,wBAcA,0CAeF,OAEF,OACF,Q,sBAnEU,2CACD,iCAMA,wCAEE,+BAIA,+BAIA,+BAkBA,0EAA8E,gB,iHGClF,MAAM,GAaX,YAAsBjhG,EACAm5C,EACD9wC,EACF4pL,GAHG,KAAAjyL,OACA,KAAAm5C,iBACD,KAAA9wC,WACF,KAAA4pL,iBAfZ,KAAA/6K,KAAO,CACZu+K,aAAcn2L,KAAKU,KAAKU,EAAE,iDAC1Bg1L,YAAap2L,KAAKU,KAAKU,EAAE,8CACzBi1L,WAAYr2L,KAAKU,KAAKU,EAAE,yCACxBk1L,YAAat2L,KAAKU,KAAKU,EAAE,0CACzBm1L,eAAgBv2L,KAAKU,KAAKU,EAAE,6CAC5Bo1L,mBAAoBx2L,KAAKU,KAAKU,EAAE,gDAChCq1L,mBAAoBz2L,KAAKU,KAAKU,EAAE,mCAChCs1L,WAAY12L,KAAKU,KAAKU,EAAE,yCACxBu1L,kBAAmB32L,KAAKU,KAAKU,EAAE,gDAS1B,iBAELpB,KAAK2yL,eAAehxF,WAAY,EAChC3hG,KAAK2yL,eAAelC,WAAY,EAChCzwL,KAAK65C,eAAe94C,KAAK,GAAsBf,KAAK+I,UAGtD,uBACE,YAAsC2C,IAA/B1L,KAAK2yL,eAAeh3I,Q,yBPrDzB,gB,oBAAuD,0C,0BACvD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,uC,yBAGV,gB,oBAAsD,yC,0BACtD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,sC,yBAGV,gB,oBAAyD,gD,0BACzD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,yC,yBAGV,gB,oBAAwD,4C,0BACxD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,wC,yBAIV,gB,oBAAyD,6C,0BACzD,gBACE,gBACE,iBACF,OACF,Q,oBAFU,yC,uCOFH,IAAuB,yC,wBAAvB,GAAuB,qN,GAAA,MDzCpC,wBAYA,0C,qBAZK,gCAA+C,gB,mKEuC7C,MAAM,WAAoC,GAS/C,YAAqBn7C,EACAE,GACnBZ,MAAMY,GAFa,KAAAF,aACA,KAAAE,OATd,KAAA6zL,WAAav0L,KAAKQ,WAAWsG,cAAc2J,QAAoB,WAC/D,KAAAo2I,MAAQ7mJ,KAAKQ,WAAWsG,cAAc2J,QAAe,MACrD,KAAAqiL,QAAU9yL,KAAKQ,WAAWsG,cAAc2J,QAAiB,QACzD,KAAAwiL,OAASjzL,KAAKQ,WAAWsG,cAAc2J,QAAgB,OACvD,KAAAmmL,UAAY52L,KAAKQ,WAAWsG,cAAc2J,QAAmB,UAC7D,KAAAomL,SAAW72L,KAAKQ,WAAWsG,cAAc2J,QAAkB,SAC3D,KAAAqmL,UAAY92L,KAAKQ,WAAWsG,cAAc2J,QAAmB,W,uCAPzD,IAA2B,sB,wBAA3B,GAA2B,wdRvCxC,gBACE,gBACE,gBACE,gBACA,gBACE,gBACE,iBACF,OACF,OACA,gBACA,gBACE,gBACE,kBACF,OACF,OACA,wBACA,wBAKA,wBACA,wBAKA,wBACA,wBAKA,wBACA,wBAMA,wBACA,wBAKF,OACF,OACF,Q,MA7C6C,oDAG7B,yCAG6B,+CAG7B,oCAGL,+BACA,+BAKA,8BACA,8BAKA,iCACA,iCAKA,gCACA,gCAMA,iCACA,mC,2FSVJ,MAAMsmL,GAeX,YAAqBhuL,GAAA,KAAAA,WAPd,KAAA6O,KAAO,CACZoV,KAAMhtB,KAAK63D,KAAKz2D,EAAE,kBAClBs0C,OAAQ11C,KAAK63D,KAAKz2D,EAAE,oBACpB4d,MAAOhf,KAAK63D,KAAKz2D,EAAE,qBACnBszJ,WAAY10J,KAAK63D,KAAKz2D,EAAE,yBAM1B,gBACEpB,KAAKg3L,YACFvnL,KAAKsyD,IACJ/hE,KAAK+1K,qBACF/oJ,KAAK+0C,GACLtyD,KAAK,KACJ+Q,OAAOgoB,SAASR,WAEjBxtB,MAAM,UAMf,kBACOgG,OAAOgrB,QAAQxrC,KAAK4X,KAAK88I,aAI9B10J,KAAKg3L,YACFvnL,KAAKsyD,IACJ/hE,KACGq6C,aACAqb,aACAxtD,GAAG65D,GACHrsB,SACAr1C,UACC,IAAMmgB,OAAOgoB,SAASR,SACtBhpB,GAAShf,KAAKJ,qBAAqBm6D,SAAS/6C,GAAShf,KAAK4X,KAAKoH,UAK/D,YACR,IAAIi4K,EAAcj3L,KAAKQ,WAAWsG,cAAc2J,QAAe,MAE/D,OAAOzQ,KACJq6C,aACAqb,aACAxtD,GAAG+uL,GACHvyL,MACAmoB,a,uCA3DMkqK,IAA4B,Y,wBAA5BA,GAA4B,iEAL5B,CACT,KACA,MACD,0LAfC,cAAG,gCAAS,EAAAG,mBAGV,oBACF,OACA,cAAG,gCAAS,EAAAC,qBAGV,oBACF,Q,MARG,0BAKA,sC,sDAYU,aAAd,c,0BAA4C,K,4CAC9B,aAAd,c,0BAAoC,M,oCACtB,aAAd,c,0BAA4C,M,4CAC9B,aAAd,c,0BAAkC,M,kCACpB,aAAd,c,0BAA4B,M,4BACd,aAAd,c,0BAA6B,M,wECKzB,MAAM,GAUX,YAAqB1zL,EACAqqD,EACAp2C,EACAhX,GAHA,KAAA+C,eACA,KAAAqqD,cACA,KAAAp2C,iBACA,KAAAhX,OAXrB,KAAAkX,KAAO,CACLw/K,UAAWp3L,KAAKU,KAAKU,EAAE,kDAKjB,KAAAi2L,OAAS,cAQfvpI,EAAYhjC,QAAQ,GAAI,KACtB9qB,KAAKq3L,OAAOhyL,SACL,IAYX,QAAQ40H,EAAgC/xH,GACtC,MAAM4M,EAAa,GAAGmlH,KAAS/xH,IACzB4I,EAAQ9Q,KAAKq3L,OAAO3yL,IAAIoQ,GAE9B,GAAIhE,EAAMuzD,aAAc,CACtB,MAAMp/B,EAAUjlC,KAAKggC,KAAKi6F,EAAO/xH,GAAI2kB,YAGrC,OAFA/b,EAAM61D,uBAAuB1hC,GAEtBA,EAGT,OAAOn0B,EACJ5Q,UACAC,KACC,OAAAi3C,GAAA,GAAK,GACL,OAAAwa,GAAA,GAAIhwD,GAAOgc,QAAQyuD,IAAI,OAASzqE,GAAMgsC,GAAOhwB,QAAQoB,MAAM,OAAS4uB,KAErE/gB,YAGG,KAAKotG,EAAgC/xH,GAC3C,OAAQ+xH,GACN,IAAK,cACH,OAAOj6H,KAAKs3L,gBAAgBpvL,GAC9B,IAAK,UACH,OAAOlI,KAAKyiI,YAAYv6H,GAC1B,QACE,OAAO,MAIL,YAAYA,GAGlB,OAFAA,EAAKA,GAAMlI,KAAK0X,eAAexP,IAMxBlI,KACJyD,aACAid,SACAxY,GAAGA,GACHxD,MACAvE,KACC,OAAAi3C,GAAA,GAAK,IATA,OAAAn4B,GAAA,GAAWjf,KAAK4X,KAAKw/K,WAaxB,gBAAgBlvL,GACtB,OAAKA,EAKD,aAAaqrD,KAAKrrD,GACblI,KACJyD,aACAmC,cACAsC,GAAGA,GACHxD,MACAvE,KACC,OAAAi3C,GAAA,GAAK,IAKJp3C,KACJyD,aACAkpB,oBAAoB3sB,KAAK0X,eAAexP,IACxCtC,cACAqlL,oBAAoB/iL,GAAI,EAAO,CAAEqyC,SAAU,MAC3C71C,MACAvE,KACC,OAAAi3C,GAAA,GAAK,GACL,OAAAloC,GAAA,GAAIy0B,GAAcA,EAAWn/B,SAAS,IAAM,OAxBvC,OAAAya,GAAA,GAAWjf,KAAK4X,KAAKw/K,Y,uCAhFrB,IAA2B,4D,0BAA3B,GAA2B,QAA3B,GAA2B,qBADd,S,mCC5BnB,MAAMG,GAUX,YAAoBxuL,EACAomE,EACA95D,GAFA,KAAAtM,WACA,KAAAomE,sBACA,KAAA95D,cAPX,KAAAmiL,cAAiD,QACjD,KAAAv4I,oBAA6C,GAStD,WACEj/C,KAAKqV,YACF28C,aAAahyD,KAAKud,UAClB9N,KAAKjN,IACJxC,KAAKuhB,OAAO/e,EAAOxC,KAAKoH,cAI9B,OAAOyxD,GACL,MAAM3xD,EAAQlH,KAAKy3L,wBAAwB5+H,GAErC53C,EAAYjhB,KAAKihB,UAAUna,cACjCma,EAAUkV,QAAS,EAGfjvB,EAAMoQ,UACR2J,EAAU1P,YAAc,IAExBrK,EAAMqa,OAAON,EAAW/Z,EAAMyoB,aAI1B,wBAAwBkpC,GAC9B,GAAI74D,KAAK03L,aAAc,CACrB,IAAIjyH,EAAW,IAAIzlE,KAAK03L,aAAa13L,KAAKoH,UAAWpH,KAAK23L,qBAE1D,OADAlyH,EAAS0E,MAAMnqE,KAAKud,SAAUs7C,GACvB4M,EAGT,OAAOzlE,KAAKmvE,oBAAoBN,SAC9B7uE,KAAKud,SACLvd,KAAKoH,UACLyxD,EACA74D,KAAK23L,qBAIT,0BACE,MAAO,CAAE5uL,SAAU/I,KAAK+I,SAAUkY,UAAWjhB,KAAKw3L,cAAe1nK,QAAS9vB,KAAKi/C,sB,uCArDtEs4I,IAAqB,iC,wBAArBA,GAAqB,sD,OAAA,K,mSAHrB,uB,4FCVb,eACE,cACA,eACF,Q,oBADM,qC,kEAEN,0B,oBACe,4BAAqB,iCAArB,CAAqB,0BCyD7B,MAAM,GAmBX,YAAqB/2L,EACAuI,EACA6uL,EACAviL,EACAosG,EACA/gH,EACAb,GANA,KAAAW,aACA,KAAAuI,WACA,KAAA6uL,iBACA,KAAAviL,cACA,KAAAosG,eACA,KAAA/gH,OACA,KAAAb,QArBrB,KAAAmf,MAAoB,KAEpB,KAAApH,KAAO,CACLwsK,KAAMpkL,KAAKU,KAAKU,EAAE,0DAClBouB,YAAaxvB,KAAKU,KAAKU,EAAE,2BACzBg2L,UAAWp3L,KAAKU,KAAKU,EAAE,iDACvBy2L,kBAAoB5tL,GAClBjK,KAAKU,KAAKU,EAAE,wDAAyD,CAAEqF,KAAMwD,KAG3D,KAAA6tL,UAAY93L,KAAK4X,KAAKwsK,KAe5C,WACE,MAAMx0J,EAAU5vB,KAAKQ,WAAWsG,cAC1BmzH,EAAiCrqG,EAAQnf,QAAQwpH,MACjD/xH,EAAY0nB,EAAQnf,QAAQvI,GAC5B0mE,EAAuBh/C,EAAQnf,QAAQwS,UAE7CjjB,KAAK41K,cAAc37C,EAAO/xH,EAAI0mE,GAGlB,cAAcqrD,EAAgC/xH,EAAW0mE,G,mDACrE,IAAIrxD,EAEJ,IACEA,QAAiBvd,KAAK43L,eAAennK,QAAQwpG,EAAO/xH,GACpD,MAAOoE,GAEP,OADAsR,QAAQoB,MAAM,0BAA4B1S,GACnCtM,KAAK+3L,UAAU/3L,KAAK4X,KAAKw/K,WAGlC,IAAK75K,EAEH,YADAvd,KAAK+3L,UAAU/3L,KAAK4X,KAAKw/K,WAI3B,MAAM50L,QAAexC,KAAKqV,YAAY28C,aAAaz0C,GAC7C0F,EAAYzgB,EAAOw1L,2BAA2BppH,IAAkBA,EAClDpsE,EAAOygB,IAGzBjjB,KAAKud,SAAWA,EAChBvd,KAAKoH,UAAY6b,GAEjBjjB,KAAK+3L,UAAU/3L,KAAK4X,KAAKigL,kBAAkBjpH,IAG7C5uE,KAAKH,MAAMS,mBAGb,UAAUk6C,GACRx6C,KAAKgf,MAAQhf,KAAKU,KAAKU,EAAE,wBAAyB,CAAEo5C,QAASA,IAC7Dx6C,KAAKH,MAAMS,iBCnIR,IAAU23L,G,uCD8DJ,IAA4B,wE,wBAA5B,GAA4B,yE,OAAA,K,uJAJ5B,CACT,QACD,M,mCAAA,qND5DH,wBAIA,kC,MAJM,qBAIS,oC,oXEJf,SAAiBA,GAMC,EAAAC,WAAhB,SAA2B/xL,GACzB,OAAOA,EAAMq+E,OAAO,GAAG3hE,cAAgB1c,EAAMue,MAAM,IAPvD,CAAiBuzK,QAAa,K,0BCA9B,QACE,iBACA,gCAGF,Q,oBAJQ,oCACe,sCAAuB,oC,0BAK9C,eACE,cACA,eACF,Q,oBADM,qCCsDC,MAAM,GAuBX,YAAqBz3L,EACAuI,EACA6uL,EACAviL,EACAosG,EACA/gH,EACAb,GANA,KAAAW,aACA,KAAAuI,WACA,KAAA6uL,iBACA,KAAAviL,cACA,KAAAosG,eACA,KAAA/gH,OACA,KAAAb,QA1BrB,KAAAmf,MAAoB,KAEpB,KAAApH,KAAO,CACLwsK,KAAMpkL,KAAKU,KAAKU,EAAE,0DAClBg2L,UAAWp3L,KAAKU,KAAKU,EAAE,iDACvBy2L,kBAAoB5tL,GAClBjK,KAAKU,KAAKU,EAAE,wDAAyD,CAAEqF,KAAMwD,KAG3D,KAAA6tL,UAAY93L,KAAK4X,KAAKwsK,KAG5C,KAAA7mK,SAA4B,KAkB5B,WACE,MAAMqS,EAAU5vB,KAAKQ,WAAWsG,cAC1BmzH,EAAiCrqG,EAAQnf,QAAQwpH,MACjD/xH,EAAY0nB,EAAQnf,QAAQvI,GAC5B0mE,EAAuBh/C,EAAQnf,QAAQwS,UAC7CjjB,KAAK+oH,eAAiBkvE,GAAcC,WAAWj+D,GAE/Cj6H,KAAKm4L,sBAAsBl+D,EAAO/xH,EAAI0mE,GAG1B,sBAAsBqrD,EAAgC/xH,EAAW0mE,G,yDAC7E,IAAIrxD,EAEJ,IACEvd,KAAKud,SAAWA,QAAiBvd,KAAK43L,eAAennK,QAAQwpG,EAAO/xH,GACpE,MAAOoE,GAEP,OADAsR,QAAQoB,MAAM,0BAA4B1S,GACnCtM,KAAK+3L,UAAU/3L,KAAK4X,KAAKw/K,WAGlC,IAAK75K,EAEH,YADAvd,KAAK+3L,UAAU/3L,KAAK4X,KAAKw/K,WAI3B,MAAM50L,QAAexC,KAAKqV,YAAY28C,aAAaz0C,GACnDvd,KAAKijB,UAAYzgB,EAAOw1L,2BAA2BppH,IAAkBA,EACrE5uE,KAAKsiC,MAA8B,QAAzB,EAAG9/B,EAAOxC,KAAKijB,kBAAU,eAAExc,KAEhCzG,KAAKsiC,OACRtiC,KAAK+3L,UAAU/3L,KAAK4X,KAAKigL,kBAAkBjpH,IAG7C5uE,KAAKH,MAAMS,mBAGb,UAAUk6C,GACRx6C,KAAKgf,MAAQhf,KAAKU,KAAKU,EAAE,wBAAyB,CAAEo5C,QAASA,IAC7Dx6C,KAAKH,MAAMS,iB,uCAvEF,IAA4B,wE,wBAA5B,GAA4B,4F,0CAJ5B,CACT,QACD,M,mCAAA,2ID7DH,gCAOA,yB,MAPc,wBAOR,+B,ycENJ,0B,yBACe,mBAAwB,mC,yBAkBpC,0B,0BACc,mBAAwB,mC,yBAIvC,0B,mCACe,mBAAwB,iCAAxB,CAAwB,oC,0BAPzC,QACE,aAAC,iCAKD,iCAKgB,aAClB,Q,yBAXkB,8BAKD,8B,0BAzBnB,QACE,iCAKA,0BAIA,cAGE,QACF,OACA,0BAIA,gCAaF,Q,6BA/BiB,gCAKA,2BAAwB,kCAKpC,4CACA,kCACD,6BAEa,2BAAwB,mCAIzB,iC,0BAchB,eACE,eACA,gBACF,Q,oBADM,qCCiBC,MAAM,GAiBX,YAAqBE,EACAuI,EACAtF,EACA4R,EACAosG,EACA5yG,EACAnO,EACAb,GAPA,KAAAW,aACA,KAAAuI,WACA,KAAAtF,eACA,KAAA4R,cACA,KAAAosG,eACA,KAAA5yG,aACA,KAAAnO,OACA,KAAAb,QAtBrB,KAAAmf,MAAoB,KAEpB,KAAApH,KAAO,CACLw/K,UAAWp3L,KAAKU,KAAKU,EAAE,iDACvBgjL,KAAMpkL,KAAKU,KAAKU,EAAE,2DAGE,KAAA02L,UAAY93L,KAAK4X,KAAKwsK,KAI5C,KAAA52F,iBAAmB,KAEnB,KAAA4qG,UAAmB,EAanB,WACE,MAAMxoK,EAAU5vB,KAAKQ,WAAWsG,cAC1BoB,EAAY0nB,EAAQnf,QAAQvI,GAClClI,KAAKo4L,SAAwC,SAA7BxoK,EAAQnf,QAAQ2nL,SAChCp4L,KAAKujL,gBAAkBvjL,KAAK6O,WAAWsW,gBAAgBjd,GAEvDlI,KAAKq4L,aAAer4L,KACjByD,aACAmC,cACAsC,GAAGA,GACHxD,MACAvE,KACC,OAAAyxD,GAAA,GAAI,CAAE5yC,MAAQ1S,GAAMtM,KAAK+3L,UAAU/3L,KAAK4X,KAAKw/K,cAInD,UAAU58I,GACR58B,QAAQoB,MAAM,0BAA4Bw7B,GAC1Cx6C,KAAKgf,MAAQhf,KAAKU,KAAKU,EAAE,wBAAyB,CAAEo5C,QAASA,IAC7Dx6C,KAAKH,MAAMS,iB,uCA/CF,IAAkC,mF,wBAAlC,GAAkC,yF,0CAJlC,CACT,QACD,M,gCAAA,6qBDlDH,iC,gBAiCA,yB,MAjCc,sCAiCR,+B,obE6HC,MAAMg4L,GAAwD,CACnE,CAAE7mK,SAAUumJ,GAAiB90H,IAAK+0H,IAClC,CAAExmJ,SAAU,KAA2ByxB,IAAK,MAC5C,CAAEzxB,SAAU,KAA8ByxB,IAAK,KAA8B8Y,YAAY,GACzF,CAAEvqC,SvDlIuC,uBuDkIAyxB,IAAK,IAC9C,CAAEzxB,SAAU,KAA0ByxB,IAAK,MAC3C,CAAEzxB,SAAU,KAAqByxB,IAAK,KAAsB8Y,YAAY,GACxE,CAAEvqC,SAAU,KAA4ByxB,IAAK,MAC7C,CAAEzxB,SzB7JwC,wByB6JAyxB,IAAK,IAC/C,CAAEzxB,S3BtIoC,qB2BsIAyxB,IAAK,IAC3C,CAAEzxB,StD9H4C,8BsD8HAyxB,IAAK,IACnD,CAAEzxB,SrDtI8C,gCqDsIAyxB,IAAK,IACrD,CAAEzxB,SAAU,KAA+ByxB,IAAK,MAChD,CAAEzxB,SAAU,KAAoByxB,IAAK,MACrC,CAAEzxB,SnD9IiD,oCmD8IAyxB,IAAK+jI,IACxD,CAAEx1J,SAAU,KAAgCyxB,IAAK,MACjD,CAAEzxB,SrF/I8C,gCqF+IAyxB,IAAK,IACrD,CAAEzxB,SAAU,KAAmCyxB,IAAK,KAAoC8Y,YAAY,GACpG,CAAEvqC,SlDlJoC,oBkDkJAyxB,IAAKgkI,IAC3C,CAAEz1J,SAAU,KAAoByxB,IAAK,MACrC,CAAEzxB,ShDnJmC,oBgDmJAyxB,IAAKykI,IAC1C,CAAEl2J,S9CpJuC,wB8CoJAyxB,IAAK6kI,IAC9C,CAAEt2J,S5ClJsC,uB4CkJAyxB,IAAK,IAC7C,CAAEzxB,S3CpJgD,iC2CoJAyxB,IAAKolI,IACvD,CAAE72J,S1C/I+B,e0C+IAyxB,IAAK,IACtC,CAAEzxB,S7BnJqC,sB6BmJAyxB,IAAK,IAC5C,CAAEzxB,SzCtJmC,oByCsJAyxB,IAAK4lI,IAC1C,CAAEr3J,SxCzJqC,sBwCyJAyxB,IAAKmmI,IAC5C,CAAE53J,SvCxJmC,oBuCwJAyxB,IAAK,IAC1C,CAAEzxB,S1BvJkC,mB0BuJAyxB,IAAK,IACzC,CAAEzxB,SrCnIgC,sBqCmIAyxB,IAAK,IACvC,CAAEzxB,SpC9J6C,8BoC8JAyxB,IAAKgpI,IACpD,CAAEz6J,SlC3LoC,8BkC2LAyxB,IAAKmpI,IAC3C,CAAE56J,SZ7JkC,kBY6JAyxB,IAAK,IACzC,CAAEzxB,SXhK8C,gCWgKAyxB,IAAK,IACrD,CAAEzxB,ShC/I2C,4BgC+IAyxB,IAAK,IAClD,CAAEzxB,S9BlKsC,uB8BkKAyxB,IAAK,IAC7C,CAAEzxB,SnHtLmC,oBmHsLAyxB,IAAK,IAC1C,CAAEzxB,SAAU,KAAuByxB,IAAK,MACxC,CAAEzxB,SV5LgD,oCU4LAyxB,IAAK6zI,GAA8B/6H,YAAY,GACjG,CAAEvqC,SAAU,KAA+ByxB,IAAK,MAChD,CAAEzxB,SNpJ+B,+BMoJAyxB,IAAK,GAA8B8Y,YAAY,GAChF,CAAEvqC,SHpJ+B,+BGoJAyxB,IAAK,GAA8B8Y,YAAY,GAChF,CAAEvqC,SDhKkC,4BCgKAyxB,IAAK,GAAoC8Y,YAAY,GACzF,CAAEvqC,S9ErMsC,uB8EqMAyxB,IAAK86H,IAC7C,CAAEvsJ,SAAU,KAAqByxB,IAAK,OChKjC,MAAMq1I,I,wBAAAA,K,qDAAAA,KAAwB,SAT1B,CACP,IACA,SCqBG,MAAMC,I,wBAAAA,K,qDAAAA,KAA2B,UAZ3B,CACT,IACD,SAPQ,CACP,IACA,IACA,QCNG,MAAM,GAEX,YAAwC98G,EAClB3yE,EACA8wC,GAFkB,KAAA6hC,kBAClB,KAAA3yE,WACA,KAAA8wC,iBAMf,gBACL,MAAMjoB,EAAU5xB,KAAK07E,gBAAgBxf,iBAAiB,yCACtD,IAAK,IAAIn/C,EAAI,EAAGA,EAAI6U,EAAQ3qB,SAAU8V,EACpC/c,KAAKy4L,YAAY5xL,OAAO+qB,EAAQ7U,KAO7B,YAAY6S,GAEjB,IAAI8oK,EAAiB9oK,EAAQpkB,KAAK,mCAC9BmtL,EAAqB/oK,EAAQzhB,KAAK,sBAElCwqL,IACFD,EAAiB7xL,OAAO8xL,IAGJ/oK,EAAQzhB,KAAK,sBAGjCnO,KAAKe,KAAK6uB,GAEV8oK,EAAetsL,MAAOvL,IACpBb,KAAKe,KAAK6uB,GACV/uB,EAAI0L,mBAKF,KAAKqjB,GAEX,MAAMwsI,EAAiBxsI,EAAQzhB,KAAK,kBAE9ByqL,EAAYhpK,EAAQzhB,KAAK,kBAI/B,IAAIkuJ,EADmBzsI,EAAQpkB,KAAK,2BACLs4F,OAE3B80F,IACFv8B,EAAYr8J,KAAK64L,aAAax8B,EAAWu8B,IAG3C54L,KAAK65C,eAAe94C,KAClB,EACAf,KAAK+I,SACL,CACEszJ,UAAWA,EACXD,eAAgBA,IAKd,aAAa19I,EAAa1Q,GAChC,IAAI8qL,EAASjyL,OAAO6X,GAChBq6K,EAASlyL,OAAO,mEAKpB,OAJAkyL,EAAO9uL,KAAK,MAAO+D,GAEnB8qL,EAAOttL,KAzEY,0BAyES2pB,OAAO4jK,GAE5BD,EAAOh1F,Q,uCAxEL,IAA0B,KAEjB,MAAQ,sB,0BAFjB,GAA0B,QAA1B,GAA0B,qBADb,SCFnB,MAAM,GAEX,YAAwCpoB,GAAA,KAAAA,kBAWjC,sBACL,MAAM9pD,EAAU5xB,KAAK07E,gBAAgBxf,iBAAkC,gCACvE,IAAK,IAAIn/C,EAAI,EAAGA,EAAI6U,EAAQ3qB,SAAU8V,EAAG,CACvC,MAAMtW,EAAOmrB,EAAQ7U,GAAG8jB,QACxB,YAAS,2BAA6Bp6B,GACtC,UAAO,KAAwBA,K,uCAlBxB,IAAwB,KAEf,Q,0BAFT,GAAwB,QAAxB,GAAwB,qBADX,SCKnB,MAAMuyL,GACX,YAAYC,EACAC,GAEVD,EAAaE,gBACbD,EAAWE,uB,wBALFJ,K,qDAAAA,IAA2B,8BAL3B,CACT,GACA,MC3BG,MAAMK,GAIX,YAAqBtwL,EACA8uD,GADA,KAAA9uD,WACA,KAAA8uD,OACar3C,OAAO8wI,UAAUC,UAAUlvH,OAAO,UAAY,IAG5EriC,KAAKs5L,UAAYzhI,EAAKz2D,EAAE,kCACxBpB,KAAKu5L,eAAiB1hI,EAAKz2D,EAAE,yBAE7BpB,KAAKw5L,kBACLx5L,KAAKy5L,oBAIF,kBACL,MAAMC,EAAWxuL,SAASC,eAAe,aAEzC,GAAIuuL,EAAU,CACZ,MAAMrrL,EAAuBnD,SAASoF,cAAc,MACpDjC,EAASoC,QAAQhK,KAAOzG,KAAKs5L,UAC7BjrL,EAAS0lB,UAAY,uEACyC/zB,KAAKs5L,4EACpBt5L,KAAKs5L,yCAIpDjrL,EAASjD,iBAAiB,QAAS,IAAMpL,KAAK25L,gBAC9CD,EAASroL,YAAYhD,IAIlB,mBACL,MAAMurL,EAAa1uL,SAAS2O,cAAc,sBAE1C,GAAI+/K,EAAY,CACd,MAAMC,EAA4B3uL,SAASoF,cAAc,OAEzDupL,EAAcppL,QAAQhK,KAAOzG,KAAKs5L,UAClCO,EAAc9lK,UAAY,sIAIhB/zB,KAAKu5L,uPAK4Bv5L,KAAKs5L,iFAKhDM,EAAWvoL,YAAYwoL,GAEAD,EAAW//K,cAAc,wBAEhCzO,iBAAiB,QAAS,IAAMpL,KAAK25L,iBAIzD,eACEn5K,OAAOgwI,YAAYI,mBAAmB,eAAgB,IAAK,K,uCAhElDyoC,IAA+B,sB,0BAA/BA,GAA+B,QAA/BA,GAA+B,YCqKrC,MAAM,GAGX,cAAc7uK,GAKZ,IAAoB+0B,YAAY+4I,IAIhC,IAAoBwB,0BAA0BtvK,EAAQtf,UAIjCsf,EAAeuvK,UAAUr1L,IAAI,KAE/CuoB,KAAK,+BACLvnB,QAAS5B,IACR,IAAoBg2L,0BAA0BtvK,EAAQtf,SAAUpH,M,wBApB3D,K,qDAAA,KAAiB,UAhCjB,CACT,CAAE6hD,QAAS,IAAQskB,SAAU,IAAI,KACjC,CAAEtkB,QAAS,IAAiBG,WAuDzB,SAA4B/8C,GACjC,MAAO,KACL,MAAMixL,EAAiBjxL,EAASrE,IAAI,IAC9Bu1L,EAA4BlxL,EAASrE,IAAI,MACzCw1L,EAAoBnxL,EAASrE,IAAI4/K,IAEvCv7K,EAASrE,IAAI20L,IAEbY,EAA0B16I,WAE1By6I,EAAeb,gBAEfe,EAAkB36I,aAnE0CyG,KAAM,CAAC,KAAWH,OAAO,GACrF,IACA,IACA,IAEA,IACA,IACAwzI,IACD,SAtEQ,CAEP,IAEA,IAEA,GAEA,IAGA,KAEA,IACAhiB,GACA,KAGA,KAGA,KACAoD,GAGA,GAGArM,GAGA+U,GAGAU,GAGAG,GAGAnI,GAGAqC,GACAsa,GAGA,EAEAl3B,GAGAi3B,GAGA,IAGAS,OClIHx4K,OAAewqE,OAASxqE,OAQzBA,OAAOD,YAAc,EAAO,4BAA4BtW,KAAK,YAAc,GAI3E,IAA0BuW,OAAOD,YAPT,oBASxBC,OAAO8kC,cAAgB,ICsChB,MAUL,cARQ,KAAA60I,iBAAmC,GAEnC,KAAAC,aAA+B,GAEtB,KAAAC,kBAA2B,EAK1C,MAAMC,EAAgBpvL,SAAS2O,cAAc,iCACzCygL,EACF,kCAA0B7qL,KAAM8qL,IAC9BA,EAAO9kH,KAAK,CACV+kH,IAAKF,EAAc7pL,QAAQ+pL,IAC3BC,OAAQrtI,EAAA,EAAYC,WACpBqtI,aAAc,CAEZ,+DAEA,yBAEFC,WAAa3yL,GAAUhI,KAAK46L,YAAY5yL,KAG1ChI,KAAK66L,aAAaN,MAGpBv6L,KAAKq6L,kBAAmB,EACxBr6L,KAAKo6L,aAAe,IAIjB,aAAaU,GAClB96L,KAAK86L,OAASA,EACdA,EAAOC,eAAe/6L,KAAKg7L,aAAaluL,KAAK9M,OAG7CA,KAAKo6L,aAAa10L,QAASoF,IACzB9K,KAAK8K,EAAKgI,MAAMhG,KAAK9M,MAAMmqE,MAAMr/D,EAAKszF,QAInC,eAAe4gD,EAAYi8C,EAA2B,QAC3D,IAAKj7L,KAAK86L,OACR,OAAO96L,KAAKk7L,qBAAqB,iBAAkBh+K,MAAM3B,KAAKwzG,YAGhE/uH,KAAK86L,OAAOK,UAAWnmI,IACrBh1D,KAAKg7L,aAAahmI,GAClBh1D,KAAK86L,OAAOt1I,eAAew5F,EAAK,IAASo8C,WAAWH,MAIjD,iBAAiBrtJ,GACtB,IAAK5tC,KAAK86L,SAAWltJ,EAEnB,MADA5tC,KAAKk7L,qBAAqB,mBAAoBh+K,MAAM3B,KAAKwzG,YACnDnhF,EAGR,GAAmB,iBAARA,EACT,OAAO5tC,KAAKwlD,eAAe5X,EAAK,SAGlC5tC,KAAK86L,OAAOK,UAAWnmI,IACrBh1D,KAAKg7L,aAAahmI,GAClBh1D,KAAK86L,OAAOv1I,iBAAiB3X,KAI1B,cAAcytJ,GACnBr7L,KAAKm6L,iBAAiBj5L,QAAQm6L,GAE1Br7L,KAAK86L,QAEPO,EAAU31L,QAAQw7B,GAAMlhC,KAAK86L,OAAOC,eAAe75J,IAS/C,qBAAqBpuB,EAA0CsrF,GACjEp+F,KAAKq6L,iBACPr6L,KAAKo6L,aAAal5L,KAAK,CAAE4R,OAAMsrF,SAE/BxgF,QAAQyuD,IAAI,2EAA4Ev5D,EAAMsrF,GAQ1F,aAAappC,GACnBA,EAAM+xF,OAAO,SAAUrmJ,KAAK+nD,QAC5BuM,EAAM+xF,OAAO,SAAUvmI,OAAOgoB,SAAS8yJ,UACvCtmI,EAAM+xF,OAAO,WAAYvmI,OAAOgoB,SAASoxI,UACzC5kH,EAAMgyF,SAAS,YAAaxmI,OAAOgoB,SAASnG,QAG5CriC,KAAKm6L,iBAAiBz0L,QAAQw7B,GAAMA,EAAG8zB,IASjC,YAAYhtD,GAElB,OAD2BkD,SAASwT,KAAKnO,UAAUlF,SAAS,yBAE1DuS,QAAQC,KAAK,mEACN,MAGF7V,ID5JX,EAAQ,QACR,EAAQ,QAER,MAAMuzL,GAAO,EAAO,sCACpB76L,KAAK+nD,OAAS8yI,GAAKptL,KAAK,WAAa,KACrCzN,KAAKgoD,eAAiBrrB,SAASk+J,GAAKptL,KAAK,kBAAmB,IAExDi/C,EAAA,EAAYC,YACd,eAIF,YAAc,KACX7sC,OAAeg7K,4BAA8B,IAAM,aAA4B,GAC/Eh7K,OAAei7K,6BAA+B,IAAM,aAA4B,KAInF,UAAO,KAAa/6L,KAAK+nD,aACtBh5C,KAAK,KACJ,GAAO,WAEL,MAAwB,gBACL,IAChBA,KAAKisL,IACJ,EAAO,QAAQ/wL,SAAS,mC,kCEtBlC,4JAUO,MAAegxL,EAOpB,YAA+B/4L,GAAA,KAAAA,aALrB,KAAA4Q,aAAe,cAGf,KAAAu+B,cAAgB,cAoBnB,WAAWluC,EAAqBC,EAAuCtB,GAC5E,MAAM8yK,EAAUt1K,KAAK+4H,eAAel1H,EAAOC,GAC3C9D,KAAK+xC,cAAc/tC,SAASsxK,GAGvB,OAAOnvK,GACZnG,KAAKwT,aAAaxP,SAASmC,GAGtB,MAAME,GACXrG,KAAK+xC,cAAc1sC,MAAMgB,GACzBrG,KAAKwT,aAAanO,MAAMgB,GAOnB,QACL,OAAO,YACLrG,KAAK+xC,cAAc7xC,UACnBF,KAAKwT,aAAatT,WASf,YACL,OAAOF,KACJ+xC,cACA7xC,UAQE,WACL,OAAOF,KACJwT,aACAtT,UAQE,WACL,OAAOF,KACJwT,aACAiZ,WAGE,UACL,OAAOzsB,KACJ+xC,cACA7xC,UACAC,KACC,YAAK,GACL,YAAM,OAEP0sB,YAIL,uBACE,MAAM+uK,EAAc,YAAQ57L,KAAK+xC,cAAe/xC,KAAKwT,cAErD,OAAO,YAAUooL,EACd5+H,GAAMA,EACJ78D,KACC,YAAI,EAAE07L,EAAU57L,UACEyL,IAAZzL,EACK47L,EAEF57L,KAUjB,YAAsB2B,GAChBA,EACF5B,KAAKwT,aAAaxP,SAASpC,GAE3B5B,KAAKwT,aAAanO,QAOtB,cACE,OAAOrF,KAAK+W,iBAAiB5Q,O,sCA/HXw1L,GAA0B,Y,yBAA1BA,EAA0B,QAA1BA,EAA0B,YAoIzC,MAAeG,UAAwCH,G,oCAAxCG,I,yBAAAA,EAA4B,QAA5BA,EAA4B,Y,aAA5BA,K","file":"main.ff03802e86912aaa5af1.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\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport { WorkPackageSchemaProxy } from 'core-app/modules/hal/schemas/work-package-schema-proxy';\n\nexport class WorkPackageChangeset extends ResourceChangeset {\n\n public setValue(key:string, val:any) {\n super.setValue(key, val);\n\n if (key === 'project' || key === 'type') {\n this.updateForm();\n }\n }\n\n protected applyChanges(payload:any):any {\n // Explicitly delete the description if it was not set by the user.\n // if it was set by the user, #applyChanges will set it again.\n // Otherwise, the backend will set it for us.\n delete payload.description;\n\n return super.applyChanges(payload);\n }\n\n protected setNewDefaultFor(key:string, val:unknown) {\n // Special handling for taking over the description\n // to the pristine resource\n if (key === 'description' && this.pristineResource.isNew) {\n this.pristineResource.description = val;\n return;\n }\n\n super.setNewDefaultFor(key, val);\n }\n\n /**\n * Get the best schema currently available, either the default resource schema (must exist).\n * If loaded, return the form schema, which provides better information on writable status\n * and contains available values.\n */\n public get schema():SchemaResource {\n if (this.form$.hasValue()) {\n return WorkPackageSchemaProxy.create(super.schema, this.projectedResource);\n } else {\n return super.schema;\n }\n }\n}\n","import {States} from '../states.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {QueryFormResource} from 'core-app/modules/hal/resources/query-form-resource';\nimport {WorkPackagesListChecksumService} from './wp-list-checksum.service';\nimport {AuthorisationService} from 'core-app/modules/common/model-auth/model-auth.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {QuerySchemaResource} from 'core-app/modules/hal/resources/query-schema-resource';\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {take} from \"rxjs/operators\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {WorkPackageViewDisplayRepresentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageViewSumService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {WorkPackageViewAdditionalElementsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-additional-elements.service\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageViewPaginationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {WorkPackageViewCollapsedGroupsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service\";\n\n@Injectable()\nexport class WorkPackageStatesInitializationService {\n constructor(protected states:States,\n protected querySpace:IsolatedQuerySpace,\n protected wpTableColumns:WorkPackageViewColumnsService,\n protected wpTableGroupBy:WorkPackageViewGroupByService,\n protected wpTableGroupFold:WorkPackageViewCollapsedGroupsService,\n protected wpTableSortBy:WorkPackageViewSortByService,\n protected wpTableFilters:WorkPackageViewFiltersService,\n protected wpTableSum:WorkPackageViewSumService,\n protected wpTableTimeline:WorkPackageViewTimelineService,\n protected wpTableHierarchies:WorkPackageViewHierarchiesService,\n protected wpTableHighlighting:WorkPackageViewHighlightingService,\n protected wpTableRelationColumns:WorkPackageViewRelationColumnsService,\n protected wpTablePagination:WorkPackageViewPaginationService,\n protected wpTableOrder:WorkPackageViewOrderService,\n protected wpTableAdditionalElements:WorkPackageViewAdditionalElementsService,\n protected apiV3Service:APIV3Service,\n protected wpListChecksumService:WorkPackagesListChecksumService,\n protected authorisationService:AuthorisationService,\n protected wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService) {\n }\n\n /**\n * Initialize the query and table states from the given query and results.\n * They may or may not come from the same query source.\n *\n * @param query\n * @param results\n */\n public initialize(query:QueryResource, results:WorkPackageCollectionResource) {\n this.clearStates();\n\n // Update the (global) wp query states\n this.querySpace.query.putValue(query);\n this.initializeFromQuery(query, results);\n\n // Update the (local) table states\n this.updateQuerySpace(query, results);\n\n // Ensure checksum for state is correct\n this.updateChecksum(query, results);\n }\n\n /**\n * Insert new information from the query from to the states.\n *\n * @param query\n * @param form\n */\n public updateStatesFromForm(query:QueryResource, form:QueryFormResource) {\n let schema:QuerySchemaResource = form.schema as any;\n\n _.each(schema.filtersSchemas.elements, (schema) => {\n this.states.schemas.get(schema.$href as string).putValue(schema as any);\n });\n\n this.wpTableFilters.initializeFilters(query, schema);\n this.querySpace.queryForm.putValue(form);\n\n this.states.queries.columns.putValue(schema.columns.allowedValues);\n this.states.queries.sortBy.putValue(schema.sortBy.allowedValues);\n this.states.queries.groupBy.putValue(schema.groupBy.allowedValues);\n this.states.queries.displayRepresentation.putValue(schema.displayRepresentation.allowedValues);\n }\n\n public updateQuerySpace(query:QueryResource, results:WorkPackageCollectionResource) {\n // Clear table required data states\n this.querySpace.additionalRequiredWorkPackages.clear('Clearing additional WPs before updating rows');\n this.querySpace.tableRendered.clear('Clearing rendered data before upgrading query space');\n\n if (results.schemas) {\n _.each(results.schemas.elements, (schema:SchemaResource) => {\n this.states.schemas.get(schema.href as string).putValue(schema);\n });\n }\n\n this.querySpace.query.putValue(query);\n\n this.authorisationService.initModelAuth('work_packages', results.$links);\n\n results.elements.forEach(wp => this.apiV3Service.work_packages.cache.updateWorkPackage(wp, true));\n\n this.querySpace.results.putValue(results);\n\n this.querySpace.groups.putValue(results.groups);\n\n this.wpTablePagination.initialize(query, results);\n\n this.wpTableRelationColumns.initialize(query, results);\n\n this.wpTableAdditionalElements.initialize(query, results);\n\n this.wpTableOrder.initialize(query, results);\n\n this.wpDisplayRepresentation.initialize(query, results);\n\n this.querySpace.additionalRequiredWorkPackages\n .values$()\n .pipe(take(1))\n .subscribe(() => this.querySpace.initialized.putValue(null));\n }\n\n public updateChecksum(query:QueryResource, results:WorkPackageCollectionResource) {\n this.wpListChecksumService.updateIfDifferent(this.querySpace.query.value!, this.wpTablePagination.current);\n this.authorisationService.initModelAuth('work_packages', results.$links);\n }\n\n public initializeFromQuery(query:QueryResource, results:WorkPackageCollectionResource) {\n this.querySpace.query.putValue(query);\n\n this.wpTableSum.initialize(query);\n this.wpTableColumns.initialize(query, results);\n this.wpTableSortBy.initialize(query, results);\n this.wpTableGroupBy.initialize(query, results);\n this.wpTableGroupFold.initialize(query, results);\n this.wpTableTimeline.initialize(query, results);\n this.wpTableHierarchies.initialize(query, results);\n this.wpTableHighlighting.initialize(query, results);\n this.wpDisplayRepresentation.initialize(query, results);\n\n this.authorisationService.initModelAuth('query', query.$links);\n this.authorisationService.initModelAuth('work_packages', results.$links);\n }\n\n public applyToQuery(query:QueryResource) {\n this.wpTableFilters.applyToQuery(query);\n this.wpTableSum.applyToQuery(query);\n this.wpTableColumns.applyToQuery(query);\n this.wpTableSortBy.applyToQuery(query);\n this.wpTableGroupBy.applyToQuery(query);\n this.wpTableGroupFold.applyToQuery(query);\n this.wpTableTimeline.applyToQuery(query);\n this.wpTableHighlighting.applyToQuery(query);\n this.wpTableHierarchies.applyToQuery(query);\n this.wpTableOrder.applyToQuery(query);\n this.wpDisplayRepresentation.applyToQuery(query);\n }\n\n public clearStates() {\n const reason = 'Clearing states before re-initialization.';\n\n // Clear immediate input states\n this.querySpace.initialized.clear(reason);\n this.querySpace.query.clear(reason);\n this.querySpace.results.clear(reason);\n this.querySpace.groups.clear(reason);\n this.querySpace.additionalRequiredWorkPackages.clear(reason);\n\n this.wpTableFilters.clear(reason);\n this.wpTableColumns.clear(reason);\n this.wpTableSortBy.clear(reason);\n this.wpTableGroupBy.clear(reason);\n this.wpTableGroupFold.clear(reason);\n this.wpDisplayRepresentation.clear(reason);\n this.wpTableSum.clear(reason);\n\n // Clear rendered state\n this.querySpace.tableRendered.clear(reason);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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} from \"rxjs/operators\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ResourceChangesetCommit} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\n\nexport interface HalEvent {\n id:string;\n eventType:string;\n resourceType:string;\n commit?:ResourceChangesetCommit;\n}\n\nexport interface HalCreatedEvent extends HalEvent {\n eventType:'created';\n}\n\nexport interface HalUpdatedEvent extends HalEvent {\n eventType:'updated';\n}\n\nexport interface RelatedWorkPackageEvent extends HalEvent {\n eventType:'association';\n relatedWorkPackage:string|null;\n relationType:string;\n}\n\nexport interface HalDeletedEvent extends HalEvent {\n eventType:'deleted';\n}\n\nexport type HalEventTypes =\n HalCreatedEvent|HalUpdatedEvent|RelatedWorkPackageEvent|HalDeletedEvent;\n\n@Injectable({ providedIn: 'root' })\nexport class HalEventsService {\n private _events = new Subject();\n\n /** Entire event stream */\n public events$ = this._events.asObservable();\n\n /** Aggregated events */\n public aggregated$(resourceType:string, debounceTimeInMs = 500):Observable {\n return this\n .events$\n .pipe(\n filter((event:HalEvent) => event.resourceType === resourceType),\n buffer(this.events$.pipe(debounceTime(debounceTimeInMs)))\n );\n }\n\n public push(resourceReference:HalResource|{ id:string, _type:string }, event:Partial) {\n event.id = resourceReference.id!;\n event.resourceType = resourceReference._type!;\n\n this._events.next(event as HalEvent);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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-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//++\nexport const ANIMATION_RATE_MS = 100;\n\nexport class TopMenu {\n private hover = false;\n private menuIsOpen = false;\n\n constructor(readonly menuContainer:JQuery) {\n this.withHeadingFoldOutAtBorder();\n this.setupDropdownClick();\n this.registerEventHandlers();\n this.closeOnBodyClick();\n this.accessibility();\n this.skipContentClickListener();\n }\n\n skipContentClickListener() {\n // Skip menu on content\n jQuery('#skip-navigation--content').on('click', () => {\n // Skip to the breadcrumb or the first link in the toolbar or the first link in the content (homescreen)\n const selectors = '.first-breadcrumb-element a, .toolbar-container a:first-of-type, #content a:first-of-type';\n const visibleLink = jQuery(selectors)\n .not(':hidden')\n .first();\n\n if (visibleLink.length) {\n visibleLink.trigger('focus');\n }\n });\n }\n\n accessibility() {\n jQuery(\".drop-down > ul\").attr(\"aria-expanded\", \"false\");\n }\n\n toggleClick(dropdown:JQuery) {\n if (this.menuIsOpen) {\n if (this.isOpen(dropdown)) {\n this.closing();\n } else {\n this.open(dropdown);\n }\n } else {\n this.opening();\n this.open(dropdown);\n }\n }\n\n // somebody opens the menu via click, hover possible afterwards\n opening() {\n this.startHover();\n this.menuIsOpen = true;\n this.menuContainer.trigger(\"openedMenu\", this.menuContainer);\n }\n\n // the entire menu gets closed, no hover possible afterwards\n closing() {\n this.stopHover();\n this.closeAllItems();\n this.menuIsOpen = false;\n this.menuContainer.trigger(\"closedMenu\", this.menuContainer);\n }\n\n stopHover() {\n this.hover = false;\n this.menuContainer.removeClass(\"hover\");\n }\n\n startHover() {\n this.hover = true;\n this.menuContainer.addClass(\"hover\");\n }\n\n closeAllItems() {\n this.openDropdowns().each((ix, item) => {\n this.close(jQuery(item));\n });\n }\n\n closeOnBodyClick() {\n let self = this;\n let wrapper = document.getElementById('wrapper');\n\n if (!wrapper) {\n return;\n }\n\n wrapper.addEventListener('click', function (evt) {\n if (self.menuIsOpen && !self.openDropdowns()[0].contains(evt.target as HTMLElement)) {\n self.closing();\n }\n }, true);\n }\n\n openDropdowns() {\n return this.dropdowns().filter(\".open\");\n }\n\n dropdowns() {\n return this.menuContainer.find(\"li.drop-down\");\n }\n\n withHeadingFoldOutAtBorder() {\n var menu_start_position;\n if (this.menuContainer.next().get(0) !== undefined && (this.menuContainer.next().get(0).tagName === 'H2')) {\n menu_start_position = this.menuContainer.next().innerHeight()! + this.menuContainer.next().position().top;\n this.menuContainer.find(\"ul.menu-drop-down-container\").css({ top: menu_start_position });\n } else if (this.menuContainer.next().hasClass(\"wiki-content\") &&\n this.menuContainer.next().children().next().first().get(0) !== undefined &&\n this.menuContainer.next().children().next().first().get(0).tagName === 'H1') {\n var wiki_heading = this.menuContainer.next().children().next().first();\n menu_start_position = wiki_heading.innerHeight()! + wiki_heading.position().top;\n this.menuContainer.find(\"ul.menu-drop-down-container\").css({ top: menu_start_position });\n }\n }\n\n setupDropdownClick() {\n var self = this;\n this.dropdowns().each(function (ix, it) {\n jQuery(it).click(function () {\n self.toggleClick(jQuery(this));\n return false;\n });\n jQuery(it).on('touchstart', function (e) {\n // This shall avoid the hover event is fired,\n // which would otherwise lead to menu being closed directly after its opened.\n // Ignore clicks from within the dropdown\n if (jQuery(e.target).closest('.menu-drop-down-container').length) {\n return true;\n }\n e.preventDefault();\n jQuery(this).click();\n return false;\n });\n });\n }\n\n isOpen(dropdown:JQuery) {\n return dropdown.filter(\".open\").length === 1;\n }\n\n isClosed(dropdown:JQuery) {\n return !this.isOpen(dropdown);\n }\n\n open(dropdown:JQuery) {\n this.dontCloseWhenUsing(dropdown);\n this.closeOtherItems(dropdown);\n this.slideAndFocus(dropdown, function () {\n dropdown.trigger(\"opened\", dropdown);\n });\n }\n\n close(dropdown:JQuery, immediate?:any) {\n this.slideUp(dropdown, immediate);\n dropdown.trigger(\"closed\", dropdown);\n }\n\n closeOtherItems(dropdown:JQuery) {\n var self = this;\n this.openDropdowns().each(function (ix, it) {\n if (jQuery(it) !== jQuery(dropdown)) {\n self.close(jQuery(it), true);\n }\n });\n }\n\n dontCloseWhenUsing(dropdown:JQuery) {\n jQuery(dropdown).find(\"li\").click(function (event) {\n event.stopPropagation();\n });\n jQuery(dropdown).bind(\"mousedown mouseup click\", function (event) {\n event.stopPropagation();\n });\n }\n\n slideAndFocus(dropdown:JQuery, callback:any) {\n this.slideDown(dropdown, callback);\n this.focusFirstInputOrLink(dropdown);\n }\n\n slideDown(dropdown:JQuery, callback:any) {\n var toDrop = dropdown.find(\"> ul\");\n dropdown.addClass(\"open\");\n toDrop.slideDown(ANIMATION_RATE_MS, callback).attr(\"aria-expanded\", \"true\");\n }\n\n slideUp(dropdown:JQuery, immediate:any) {\n var toDrop = jQuery(dropdown).find(\"> ul\");\n dropdown.removeClass(\"open\");\n\n if (immediate) {\n toDrop.hide();\n } else {\n toDrop.slideUp(ANIMATION_RATE_MS);\n }\n\n toDrop.attr(\"aria-expanded\", \"false\");\n }\n\n // If there is ANY input, it will have precedence over links,\n // i.e. links will only get focussed, if there is NO input whatsoever\n focusFirstInputOrLink(dropdown:JQuery) {\n var toFocus = dropdown.find(\"ul :input:visible:first\");\n if (toFocus.length === 0) {\n toFocus = dropdown.find(\"ul a:visible:first\");\n }\n // actually a simple focus should be enough.\n // The rest is only there to work around a rendering bug in webkit (as of Oct 2011),\n // occuring mostly inside the login/signup dropdown.\n toFocus.blur();\n setTimeout(function () {\n toFocus.focus();\n }, 10);\n }\n\n registerEventHandlers() {\n const toggler = jQuery(\"#main-menu-toggle\");\n\n this.menuContainer.on(\"closeDropDown\", (event) => {\n this.close(jQuery(event.target));\n }).on(\"openDropDown\", (event) => {\n this.open(jQuery(event.target));\n }).on(\"closeMenu\", () => {\n this.closing();\n }).on(\"openMenu\", () => {\n this.open(this.dropdowns().first());\n this.opening();\n });\n\n toggler.on(\"click\", () => { // click on hamburger icon is closing other menu\n this.closing();\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {WorkPackageOverviewTabComponent} from 'core-components/wp-single-view-tabs/overview-tab/overview-tab.component';\nimport {WorkPackageActivityTabComponent} from 'core-components/wp-single-view-tabs/activity-panel/activity-tab.component';\nimport {WorkPackageRelationsTabComponent} from 'core-components/wp-single-view-tabs/relations-tab/relations-tab.component';\nimport {WorkPackageWatchersTabComponent} from 'core-components/wp-single-view-tabs/watchers-tab/watchers-tab.component';\nimport {WorkPackageNewSplitViewComponent} from 'core-components/wp-new/wp-new-split-view.component';\nimport {Ng2StateDeclaration} from \"@uirouter/angular\";\nimport {ComponentType} from \"@angular/cdk/overlay\";\nimport {WorkPackageCopySplitViewComponent} from \"core-components/wp-copy/wp-copy-split-view.component\";\n\n/**\n * Return a set of routes for a split view mounted under the given base route,\n * which must be a grandchild of a PartitionedQuerySpacePageComponent.\n *\n * Example: base route = foo.bar\n *\n * Split view will be created at\n *\n * foo.bar.details\n * foo.bar.details.activity\n * foo.bar.details.relations\n * foo.bar.details.watchers\n *\n * NOTE: All parameters here must either be `export const` or literal strings,\n * otherwise AOT will not be able to look them up. This might result in missing routes.\n *\n * @param baseRoute The base route to mount under\n * @param showComponent The split view component to mount\n */\nexport function makeSplitViewRoutes(baseRoute:string,\n menuItemClass:string|undefined,\n showComponent:ComponentType,\n newComponent:ComponentType = WorkPackageNewSplitViewComponent,\n makeFullWidth?:boolean,\n routeName = baseRoute):Ng2StateDeclaration[] {\n // makeFullWidth configuration\n const views:any = makeFullWidth ?\n {'content-left@^.^': { component: showComponent }} :\n {'content-right@^.^': { component: showComponent }};\n const partition = makeFullWidth ? '-left-only' : '-split';\n\n return [\n {\n name: routeName + '.details',\n url: '/details/{workPackageId:[0-9]+}',\n redirectTo: routeName + '.details.overview',\n reloadOnSearch: false,\n data: {\n bodyClasses: 'router--work-packages-partitioned-split-view-details',\n menuItem: menuItemClass,\n // Remember the base route so we can route back to it anywhere\n baseRoute: baseRoute,\n newRoute: routeName + '.new',\n partition,\n },\n // Retarget and by that override the grandparent views\n // https://ui-router.github.io/guide/views#relative-parent-state\n views,\n },\n {\n name: routeName + '.details.overview',\n url: '/overview',\n component: WorkPackageOverviewTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: routeName + '.details'\n }\n },\n {\n name: routeName + '.details.activity',\n url: '/activity',\n component: WorkPackageActivityTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: routeName + '.details'\n }\n },\n {\n name: routeName + '.details.relations',\n url: '/relations',\n component: WorkPackageRelationsTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: routeName + '.details'\n }\n },\n {\n name: routeName + '.details.watchers',\n url: '/watchers',\n component: WorkPackageWatchersTabComponent,\n data: {\n baseRoute: baseRoute,\n menuItem: menuItemClass,\n parent: routeName + '.details'\n }\n },\n // Split create route\n {\n name: routeName + '.new',\n url: '/create_new?{type:[0-9]+}&{parent_id:[0-9]+}',\n reloadOnSearch: false,\n data: {\n partition: '-split',\n allowMovingInEditMode: true,\n bodyClasses: 'router--work-packages-partitioned-split-view-new',\n // Remember the base route so we can route back to it anywhere\n baseRoute: baseRoute,\n parent: baseRoute\n },\n views: {\n // Retarget and by that override the grandparent views\n // https://ui-router.github.io/guide/views#relative-parent-state\n 'content-right@^.^': { component: newComponent }\n }\n },\n // Split copy route\n {\n name: routeName + '.copy',\n url: '/details/{copiedFromWorkPackageId:[0-9]+}/copy',\n views: {\n 'content-right@^.^': { component: WorkPackageCopySplitViewComponent }\n },\n reloadOnSearch: false,\n data: {\n baseRoute: baseRoute,\n parent: baseRoute,\n allowMovingInEditMode: true,\n bodyClasses: 'router--work-packages-partitioned-split-view',\n menuItem: menuItemClass,\n partition: '-split'\n },\n },\n ];\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injectable} from '@angular/core';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {HalLink} from \"core-app/modules/hal/hal-link/hal-link\";\n\n@Injectable()\nexport class BcfPathHelperService {\n constructor(readonly pathHelper:PathHelperService) {\n }\n\n public projectImportIssuePath(projectIdentifier:string) {\n return this.pathHelper.projectPath(projectIdentifier) + '/issues/upload';\n }\n\n public projectExportIssuesPath(projectIdentifier:string, filters:string|null) {\n if (filters) {\n return this.pathHelper.projectPath(projectIdentifier) + '/work_packages.bcf?filters=' + filters;\n } else {\n return this.pathHelper.projectPath(projectIdentifier) + '/work_packages.bcf';\n }\n }\n\n public snapshotPath(viewpoint:HalLink) {\n return viewpoint.href + '/snapshot';\n }\n}\n","var map = {\n\t\"./af.js\": [\n\t\t\"NTxu\",\n\t\t142\n\t],\n\t\"./ar.js\": [\n\t\t\"sz2f\",\n\t\t143\n\t],\n\t\"./az.js\": [\n\t\t\"cJhg\",\n\t\t144\n\t],\n\t\"./be.js\": [\n\t\t\"ytP5\",\n\t\t145\n\t],\n\t\"./bg.js\": [\n\t\t\"wq8R\",\n\t\t146\n\t],\n\t\"./bn.js\": [\n\t\t\"xax0\",\n\t\t147\n\t],\n\t\"./bs.js\": [\n\t\t\"Mn6t\",\n\t\t148\n\t],\n\t\"./ca.js\": [\n\t\t\"bFR9\",\n\t\t149\n\t],\n\t\"./cs.js\": [\n\t\t\"uT64\",\n\t\t150\n\t],\n\t\"./cy.js\": [\n\t\t\"XBH+\",\n\t\t151\n\t],\n\t\"./da.js\": [\n\t\t\"oqPE\",\n\t\t152\n\t],\n\t\"./de-AT.js\": [\n\t\t\"WrCB\",\n\t\t153\n\t],\n\t\"./de-CH.js\": [\n\t\t\"oai4\",\n\t\t154\n\t],\n\t\"./de-DE.js\": [\n\t\t\"tJ4f\",\n\t\t155\n\t],\n\t\"./de.js\": [\n\t\t\"iFlR\",\n\t\t156\n\t],\n\t\"./el-CY.js\": [\n\t\t\"TPLK\",\n\t\t157\n\t],\n\t\"./el.js\": [\n\t\t\"k48E\",\n\t\t158\n\t],\n\t\"./en-AU.js\": [\n\t\t\"M4sl\",\n\t\t159\n\t],\n\t\"./en-CA.js\": [\n\t\t\"xfKs\",\n\t\t160\n\t],\n\t\"./en-CY.js\": [\n\t\t\"ufn/\",\n\t\t161\n\t],\n\t\"./en-GB.js\": [\n\t\t\"r3/2\",\n\t\t162\n\t],\n\t\"./en-IE.js\": [\n\t\t\"u1k6\",\n\t\t163\n\t],\n\t\"./en-IN.js\": [\n\t\t\"8VPa\",\n\t\t164\n\t],\n\t\"./en-NZ.js\": [\n\t\t\"THql\",\n\t\t165\n\t],\n\t\"./en-US.js\": [\n\t\t\"KW4L\",\n\t\t166\n\t],\n\t\"./en-ZA.js\": [\n\t\t\"Wc4I\",\n\t\t167\n\t],\n\t\"./en.js\": [\n\t\t\"CQue\",\n\t\t168\n\t],\n\t\"./eo.js\": [\n\t\t\"zj11\",\n\t\t169\n\t],\n\t\"./es-419.js\": [\n\t\t\"AuO9\",\n\t\t170\n\t],\n\t\"./es-AR.js\": [\n\t\t\"kEy0\",\n\t\t171\n\t],\n\t\"./es-CL.js\": [\n\t\t\"ft4/\",\n\t\t172\n\t],\n\t\"./es-CO.js\": [\n\t\t\"s2os\",\n\t\t173\n\t],\n\t\"./es-CR.js\": [\n\t\t\"2jQJ\",\n\t\t174\n\t],\n\t\"./es-EC.js\": [\n\t\t\"U6Bt\",\n\t\t175\n\t],\n\t\"./es-ES.js\": [\n\t\t\"ZPhd\",\n\t\t176\n\t],\n\t\"./es-MX.js\": [\n\t\t\"06FW\",\n\t\t177\n\t],\n\t\"./es-NI.js\": [\n\t\t\"a+FD\",\n\t\t178\n\t],\n\t\"./es-PA.js\": [\n\t\t\"QXC7\",\n\t\t179\n\t],\n\t\"./es-PE.js\": [\n\t\t\"I5eF\",\n\t\t180\n\t],\n\t\"./es-US.js\": [\n\t\t\"pDd2\",\n\t\t181\n\t],\n\t\"./es-VE.js\": [\n\t\t\"feyl\",\n\t\t182\n\t],\n\t\"./es.js\": [\n\t\t\"0MJg\",\n\t\t183\n\t],\n\t\"./et.js\": [\n\t\t\"Cagy\",\n\t\t184\n\t],\n\t\"./eu.js\": [\n\t\t\"J9ic\",\n\t\t185\n\t],\n\t\"./fa.js\": [\n\t\t\"eWY+\",\n\t\t186\n\t],\n\t\"./fi.js\": [\n\t\t\"/z4B\",\n\t\t187\n\t],\n\t\"./fil.js\": [\n\t\t\"PQTg\",\n\t\t188\n\t],\n\t\"./fr-CA.js\": [\n\t\t\"kmLF\",\n\t\t189\n\t],\n\t\"./fr-CH.js\": [\n\t\t\"bJRw\",\n\t\t190\n\t],\n\t\"./fr-FR.js\": [\n\t\t\"O+Vq\",\n\t\t191\n\t],\n\t\"./fr.js\": [\n\t\t\"S399\",\n\t\t192\n\t],\n\t\"./gl.js\": [\n\t\t\"GRki\",\n\t\t193\n\t],\n\t\"./he.js\": [\n\t\t\"R/Q/\",\n\t\t194\n\t],\n\t\"./hi-IN.js\": [\n\t\t\"zRlf\",\n\t\t195\n\t],\n\t\"./hi.js\": [\n\t\t\"TOBP\",\n\t\t196\n\t],\n\t\"./hr.js\": [\n\t\t\"ED+y\",\n\t\t197\n\t],\n\t\"./hu.js\": [\n\t\t\"a/eb\",\n\t\t198\n\t],\n\t\"./id.js\": [\n\t\t\"u8bJ\",\n\t\t199\n\t],\n\t\"./is.js\": [\n\t\t\"pUlV\",\n\t\t200\n\t],\n\t\"./it-CH.js\": [\n\t\t\"M295\",\n\t\t201\n\t],\n\t\"./it.js\": [\n\t\t\"VfVk\",\n\t\t202\n\t],\n\t\"./ja.js\": [\n\t\t\"EQXh\",\n\t\t203\n\t],\n\t\"./ka.js\": [\n\t\t\"+Ljo\",\n\t\t204\n\t],\n\t\"./km.js\": [\n\t\t\"WMQS\",\n\t\t205\n\t],\n\t\"./kn.js\": [\n\t\t\"8qXJ\",\n\t\t206\n\t],\n\t\"./ko.js\": [\n\t\t\"QfUy\",\n\t\t207\n\t],\n\t\"./lb.js\": [\n\t\t\"9q38\",\n\t\t208\n\t],\n\t\"./lo.js\": [\n\t\t\"AGs6\",\n\t\t209\n\t],\n\t\"./lt.js\": [\n\t\t\"D+E8\",\n\t\t210\n\t],\n\t\"./lv.js\": [\n\t\t\"TGF+\",\n\t\t211\n\t],\n\t\"./mg.js\": [\n\t\t\"4VZG\",\n\t\t212\n\t],\n\t\"./mk.js\": [\n\t\t\"VzW1\",\n\t\t213\n\t],\n\t\"./ml.js\": [\n\t\t\"Nm61\",\n\t\t214\n\t],\n\t\"./mn.js\": [\n\t\t\"aew7\",\n\t\t215\n\t],\n\t\"./mr-IN.js\": [\n\t\t\"Ivdp\",\n\t\t216\n\t],\n\t\"./ms.js\": [\n\t\t\"PIEu\",\n\t\t217\n\t],\n\t\"./nb.js\": [\n\t\t\"NgvQ\",\n\t\t218\n\t],\n\t\"./ne.js\": [\n\t\t\"2RGT\",\n\t\t219\n\t],\n\t\"./nl.js\": [\n\t\t\"Vw9A\",\n\t\t220\n\t],\n\t\"./nn.js\": [\n\t\t\"3tCn\",\n\t\t221\n\t],\n\t\"./no.js\": [\n\t\t\"i6Wc\",\n\t\t222\n\t],\n\t\"./oc.js\": [\n\t\t\"Peea\",\n\t\t223\n\t],\n\t\"./or.js\": [\n\t\t\"7kX+\",\n\t\t224\n\t],\n\t\"./pa.js\": [\n\t\t\"OB7H\",\n\t\t225\n\t],\n\t\"./pl.js\": [\n\t\t\"023k\",\n\t\t226\n\t],\n\t\"./pt-BR.js\": [\n\t\t\"GZMl\",\n\t\t227\n\t],\n\t\"./pt.js\": [\n\t\t\"03fs\",\n\t\t228\n\t],\n\t\"./rm.js\": [\n\t\t\"1n3U\",\n\t\t229\n\t],\n\t\"./ro.js\": [\n\t\t\"1Oix\",\n\t\t230\n\t],\n\t\"./ru.js\": [\n\t\t\"ue6V\",\n\t\t231\n\t],\n\t\"./sk.js\": [\n\t\t\"QBQ5\",\n\t\t232\n\t],\n\t\"./sl.js\": [\n\t\t\"0ek5\",\n\t\t233\n\t],\n\t\"./sq.js\": [\n\t\t\"GouJ\",\n\t\t234\n\t],\n\t\"./sr.js\": [\n\t\t\"iiJJ\",\n\t\t235\n\t],\n\t\"./sv-SE.js\": [\n\t\t\"w/km\",\n\t\t236\n\t],\n\t\"./sv.js\": [\n\t\t\"rcLn\",\n\t\t237\n\t],\n\t\"./sw.js\": [\n\t\t\"ci3q\",\n\t\t238\n\t],\n\t\"./ta.js\": [\n\t\t\"HgV+\",\n\t\t239\n\t],\n\t\"./te.js\": [\n\t\t\"icKA\",\n\t\t240\n\t],\n\t\"./th.js\": [\n\t\t\"Uvgq\",\n\t\t241\n\t],\n\t\"./tl.js\": [\n\t\t\"VyBs\",\n\t\t242\n\t],\n\t\"./tr.js\": [\n\t\t\"5nPu\",\n\t\t243\n\t],\n\t\"./tt.js\": [\n\t\t\"hEsF\",\n\t\t244\n\t],\n\t\"./ug.js\": [\n\t\t\"JCdo\",\n\t\t245\n\t],\n\t\"./uk.js\": [\n\t\t\"4ZxZ\",\n\t\t246\n\t],\n\t\"./ur.js\": [\n\t\t\"IzNn\",\n\t\t247\n\t],\n\t\"./uz.js\": [\n\t\t\"2yAK\",\n\t\t248\n\t],\n\t\"./vi.js\": [\n\t\t\"mhGZ\",\n\t\t249\n\t],\n\t\"./wo.js\": [\n\t\t\"JViR\",\n\t\t250\n\t],\n\t\"./zh-CN.js\": [\n\t\t\"L27e\",\n\t\t251\n\t],\n\t\"./zh-HK.js\": [\n\t\t\"J9h6\",\n\t\t252\n\t],\n\t\"./zh-TW.js\": [\n\t\t\"FEz5\",\n\t\t253\n\t],\n\t\"./zh-YUE.js\": [\n\t\t\"tZgQ\",\n\t\t254\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tvar ids = map[req], id = ids[0];\n\treturn __webpack_require__.e(ids[1]).then(function() {\n\t\treturn __webpack_require__.t(id, 7);\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = \"0Int\";\nmodule.exports = webpackAsyncContext;","import {Injector} from '@angular/core';\nimport {States} from '../../states.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {tdClassName} from './cell-builder';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {QueryColumn} from '../../wp-query/query-column';\nimport {WorkPackageRelationsService} from '../../wp-relations/wp-relations.service';\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport const relationCellTdClassName = 'wp-table--relation-cell-td';\nexport const relationCellIndicatorClassName = 'wp-table--relation-indicator';\n\nexport class RelationCellbuilder {\n\n @InjectField() states:States;\n @InjectField() wpRelations:WorkPackageRelationsService;\n @InjectField() wpTableRelationColumns:WorkPackageViewRelationColumnsService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public build(workPackage:WorkPackageResource, column:QueryColumn) {\n const td = document.createElement('td');\n td.classList.add(tdClassName, relationCellTdClassName, column.id);\n td.dataset['columnId'] = column.id;\n\n // Get current expansion and value state\n const expanded = this.wpTableRelationColumns.getExpandFor(workPackage.id!) === column.id;\n const relationState = this.wpRelations.state(workPackage.id!).value;\n const relations = this.wpTableRelationColumns.relationsForColumn(workPackage,\n relationState,\n column);\n\n const indicator = this.renderIndicator();\n const badge = this.renderBadge(relations);\n\n if (expanded) {\n td.classList.add('-expanded');\n }\n\n if (relations.length > 0) {\n td.appendChild(badge);\n td.appendChild(indicator);\n }\n\n return td;\n }\n\n private renderIndicator() {\n const indicator = document.createElement('span');\n indicator.classList.add(relationCellIndicatorClassName);\n indicator.setAttribute('aria-hidden', 'true');\n indicator.setAttribute('tabindex', '0');\n\n return indicator;\n }\n\n private renderBadge(relations:RelationResource[]) {\n const badge = document.createElement('span');\n badge.classList.add('wp-table--relation-count');\n\n badge.textContent = '' + relations.length;\n badge.classList.add('badge', '-border-only');\n\n return badge;\n }\n}\n\n","import {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","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 {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageViewBaseService} from './wp-view-base.service';\nimport {Injectable} from '@angular/core';\nimport {WorkPackageViewGroupByService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service';\nimport {IsolatedQuerySpace} from 'core-app/modules/work_packages/query-space/isolated-query-space';\nimport {take} from 'rxjs/operators';\nimport {GroupObject, WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {QuerySchemaResource} from 'core-app/modules/hal/resources/query-schema-resource';\nimport {QueryGroupByResource} from 'core-app/modules/hal/resources/query-group-by-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {SchemaCacheService} from 'core-components/schemas/schema-cache.service';\n\n@Injectable()\nexport class WorkPackageViewCollapsedGroupsService extends WorkPackageViewBaseService {\n readonly wpTypesToShowInCollapsedGroupHeaders:((wp:WorkPackageResource) => boolean)[];\n readonly groupTypesWithHeaderCellsWhenCollapsed = ['project'];\n\n get config():IGroupsCollapseEvent {\n return this.updatesState.getValueOr(this.getDefaultState());\n }\n\n get currentGroups():GroupObject[] {\n return this.querySpace.groups.value!;\n }\n\n get allGroupsAreCollapsed():boolean {\n return this.config.allGroupsAreCollapsed;\n }\n\n get allGroupsAreExpanded():boolean {\n return this.config.allGroupsAreExpanded;\n }\n\n get currentGroupedBy():QueryGroupByResource|null {\n return this.workPackageViewGroupByService.current;\n }\n\n constructor(\n protected readonly querySpace:IsolatedQuerySpace,\n readonly workPackageViewGroupByService:WorkPackageViewGroupByService,\n private schemaCacheService:SchemaCacheService,\n ) {\n super(querySpace);\n this.wpTypesToShowInCollapsedGroupHeaders = [this.isMilestone];\n }\n\n // Every time the groupedBy changes, this services is initialized\n private getDefaultState():IGroupsCollapseEvent {\n return {\n state: this.querySpace.collapsedGroups.value || {},\n allGroupsChanged: false,\n lastChangedGroup: null,\n groupedBy: this.currentGroupedBy?.id || null,\n ...this.getAllGroupsCollapsedState(this.currentGroups, this.querySpace.collapsedGroups.value!),\n };\n }\n\n isMilestone = (workPackage:WorkPackageResource):boolean => {\n return this.schemaCacheService.of(workPackage)?.isMilestone;\n }\n\n toggleGroupCollapseState(groupIdentifier:string):void {\n const newCollapsedState = !this.config.state[groupIdentifier];\n const state = {\n ...this.config.state,\n [groupIdentifier]: newCollapsedState\n };\n const newState = {\n ...this.config,\n state,\n lastChangedGroup: groupIdentifier,\n ...this.getAllGroupsCollapsedState(this.currentGroups, state),\n };\n\n this.update(newState);\n }\n\n setAllGroupsCollapseStateTo(collapsedState:boolean):void {\n const groupUpdatedState = this.currentGroups.reduce((updatedState:{[key:string]:boolean}, group) => {\n return {\n ...updatedState,\n [group.identifier]:collapsedState,\n };\n }, {});\n const newState = {\n ...this.config,\n state: {\n ...this.config.state,\n ...groupUpdatedState,\n },\n lastChangedGroup: null,\n allGroupsAreCollapsed: collapsedState,\n allGroupsAreExpanded: !collapsedState,\n allGroupsChanged: true,\n };\n\n this.update(newState);\n }\n\n getAllGroupsCollapsedState(groups:GroupObject[], currentCollapsedGroupsState:IGroupsCollapseEvent['state']) {\n let allGroupsAreCollapsed = false;\n let allGroupsAreExpanded = true;\n\n if (currentCollapsedGroupsState && groups?.length) {\n const firstGroupIdentifier = groups[0].identifier;\n const firstGroupCollapsedState = currentCollapsedGroupsState[firstGroupIdentifier];\n const allGroupsHaveTheSameCollapseState = groups.every((group) => {\n return currentCollapsedGroupsState[group.identifier] != null &&\n currentCollapsedGroupsState[group.identifier] === currentCollapsedGroupsState[firstGroupIdentifier];\n });\n\n allGroupsAreCollapsed = allGroupsHaveTheSameCollapseState && firstGroupCollapsedState;\n allGroupsAreExpanded = allGroupsHaveTheSameCollapseState && !firstGroupCollapsedState;\n }\n\n return {allGroupsAreCollapsed, allGroupsAreExpanded};\n }\n\n initialize(query:QueryResource, results:WorkPackageCollectionResource, schema?:QuerySchemaResource) {\n // When this service is initialized (first time the table is loaded and very time the groupBy changes),\n // we need to wait until the table is ready to emit the collapseStatus. Otherwise the groups are not\n // ready in the DOM and can't be collapsed/expanded.\n this.querySpace.tableRendered.values$().pipe(take(1)).subscribe(() => this.update({ ...this.config, allGroupsChanged: true }));\n }\n\n valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource) {\n return this.getDefaultState();\n }\n\n applyToQuery(query:QueryResource) { return; }\n}\n","import {Injectable} from \"@angular/core\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {\n QueryFilterInstanceSchemaResource,\n QueryFilterInstanceSchemaResourceLinks\n} from \"core-app/modules/hal/resources/query-filter-instance-schema-resource\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\n\n@Injectable()\nexport class QueryFiltersService {\n constructor(protected schemaCache:SchemaCacheService) {\n }\n\n /**\n * Get the matching schema of the filter resource\n * from the schema\n */\n private getFilterSchema(filter:QueryFilterInstanceResource, form:QueryFormResource):QueryFilterInstanceSchemaResource|undefined {\n const available = form.$embedded.schema.filtersSchemas.elements;\n return _.find(available, schema => schema.allowedFilterValue.href === filter.filter.href);\n }\n\n /**\n * Prepares the schemas of each filter to be readily placed to make alterations\n * to the filter based on the filter e.g. when sending an updated filter to the backend.\n * @param query\n * @param form\n */\n public mapSchemasIntoFilters(query:QueryResource, form:QueryFormResource) {\n query.filters.forEach(filter => {\n let schema = this.getFilterSchema(filter, form)!;\n filter.$links.schema = schema.$links.self;\n this.schemaCache.update(filter, schema);\n });\n }\n\n public setSchemas(schemas:CollectionResource) {\n schemas.elements.forEach(schema => {\n this.schemaCache.updateValue(schema.$links.self.href!, schema);\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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, Directive } from \"@angular/core\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {Subject} from \"rxjs\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\n\n@Directive()\nexport abstract class WorkPackageCommentFieldHandler extends EditFieldHandler implements OnInit {\n public fieldName = 'comment';\n public handler = this;\n public active = false;\n public inEditMode = false;\n public inFlight = false;\n\n public change:WorkPackageChangeset;\n\n // Destroy events\n public onDestroy = new Subject();\n\n constructor(protected elementRef:ElementRef,\n protected injector:Injector) {\n super();\n }\n\n public ngOnInit() {\n this.change = new WorkPackageChangeset(this.workPackage);\n }\n\n /**\n * Handle saving the comment\n */\n public abstract handleUserSubmit():Promise;\n\n /**\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 {Injector} from \"@angular/core\";\nimport {Constructor} from \"@angular/cdk/table\";\nimport {SimpleResource, SimpleResourceCollection} from \"core-app/modules/apiv3/paths/path-resources\";\n\nexport class BcfResourcePath extends SimpleResource {\n constructor(readonly injector:Injector,\n basePath:string,\n readonly id:string|number) {\n super(basePath, id);\n }\n}\n\nexport class BcfResourceCollectionPath extends SimpleResourceCollection {\n constructor(readonly injector:Injector,\n protected basePath:string,\n segment:string,\n protected resource?:Constructor) {\n super(basePath, segment, resource);\n }\n\n public id(id:string|number):T {\n return new (this.resource || BcfResourcePath)(this.injector, this.path, id) as T;\n }\n\n}","import {HttpClient, HttpErrorResponse, HttpParams} from \"@angular/common/http\";\nimport {Injector} from \"@angular/core\";\nimport {TypedJSON} from \"typedjson\";\nimport {Constructor} from \"@angular/cdk/table\";\nimport {Observable, throwError} from \"rxjs\";\nimport {\n HTTPClientHeaders,\n HTTPClientOptions,\n HTTPClientParamMap,\n HTTPSupportedMethods\n} from \"core-app/modules/hal/http/http.interfaces\";\nimport {URLParamsEncoder} from \"core-app/modules/hal/services/url-params-encoder\";\nimport {catchError, map} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class BcfApiRequestService {\n @InjectField() http:HttpClient;\n\n /**\n * Create a BCF api request service.\n * Optionally pass a resource map to map the resulting data to with TypedJson.\n *\n * @param injector Injector\n * @param resourceClass Optional mapped resource class with TypedJson annotations\n */\n constructor(readonly injector:Injector,\n readonly resourceClass?:Constructor) {\n }\n\n /**\n * Request GET from the given BCF API 2.1 resource and map it to +resourceClass+.\n *\n * @param path API path to request\n * @param params Request query params\n * @param headers optional headers map\n */\n get(path:string, params:HTTPClientParamMap, headers:HTTPClientHeaders = {}):Observable {\n const config:HTTPClientOptions = {\n headers: headers,\n params: new HttpParams({ encoder: new URLParamsEncoder(), fromObject: params }),\n withCredentials: true,\n responseType: 'json'\n };\n\n return this._request('get', path, config);\n }\n\n /**\n * Request the given BCF API 2.1 resource and map it to +resourceClass+.\n *\n * @param method request method\n * @param path API path to request\n * @param data Request payload (URL params for get, JSON payload otherwise)\n * @param data Request payload (URL params for get, JSON payload otherwise)\n */\n public request(method:HTTPSupportedMethods, path:string, data:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}):Observable {\n\n // HttpClient requires us to create HttpParams instead of passing data for get\n // so forward to that method instead.\n if (method === 'get') {\n return this.get(path, data, headers);\n }\n\n const config:HTTPClientOptions = {\n body: data || {},\n headers: headers,\n withCredentials: true,\n responseType: 'json'\n };\n\n return this._request(method, path, config);\n }\n\n /**\n * Perform the request with httpClient and deserialize the result\n *\n * @param method Request method\n * @param path Request path\n * @param config HTTP client configuration\n *\n * @private\n */\n private _request(method:HTTPSupportedMethods, path:string, config:HTTPClientOptions):Observable {\n return this\n .http\n .request(method, path, config)\n .pipe(\n map((response:any) => this.deserialize(response)),\n catchError((error:HttpErrorResponse) => {\n console.error(`Failed to ${method} ${path}: ${error.name}`);\n return throwError(error);\n })\n );\n }\n\n /**\n * Deserialize the JSON data into the mapped resource class, if given.\n * @param data JSON API response.\n */\n protected deserialize(data:any):T {\n if (this.resourceClass) {\n const serializer = new TypedJSON(this.resourceClass);\n return serializer.parse(data)!;\n } else {\n return data;\n }\n }\n}","import {jsonMember, jsonObject} from \"typedjson\";\n\n@jsonObject\nexport class BcfProjectResource {\n\n @jsonMember\n project_id:number;\n\n @jsonMember\n name:string;\n}\n","import {jsonArrayMember, jsonMember, jsonObject} from \"typedjson\";\nimport * as moment from \"moment\";\nimport {Moment} from \"moment\";\n\n@jsonObject\nexport class BcfTopicAuthorizationMap {\n @jsonArrayMember(String)\n topic_actions:string[];\n\n @jsonArrayMember(String)\n topic_status:string[];\n}\n\n@jsonObject\nexport class BcfTopicResource {\n\n @jsonMember\n guid:string;\n\n @jsonMember\n topic_type:string;\n\n @jsonMember\n topic_status:string;\n\n @jsonMember\n priority:string;\n\n @jsonArrayMember(String)\n reference_links:string[];\n\n @jsonMember\n title:string;\n\n @jsonMember({ preserveNull: true })\n index:number|null;\n\n @jsonArrayMember(String)\n labels:string[];\n\n @jsonMember({ deserializer: value => moment(value), serializer: (timestamp:Moment) => timestamp.toISOString() })\n creation_date:Moment;\n\n @jsonMember\n creation_author:string;\n\n @jsonMember({ deserializer: value => moment(value), serializer: (timestamp:Moment) => timestamp.toISOString() })\n modified_date:Moment;\n\n @jsonMember({ preserveNull: true })\n modified_author:string|null;\n\n @jsonMember\n assigned_to:string;\n\n @jsonMember({ preserveNull: true })\n stage:string|null;\n\n @jsonMember\n description:string;\n\n @jsonMember({\n deserializer: value => moment(value),\n serializer: (timestamp:Moment) => timestamp.format('YYYY-MM-DD')\n })\n due_date:Moment;\n\n @jsonMember\n authorization:BcfTopicAuthorizationMap;\n}\n","import {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {BcfResourcePath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\n\nexport class BcfViewpointPaths extends BcfResourcePath {\n readonly bcfTopicService = new BcfApiRequestService(this.injector);\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n return this.bcfTopicService.get(this.toPath(), params, headers);\n }\n\n delete(headers:HTTPClientHeaders = {}) {\n return this.bcfTopicService.request('delete', this.toPath(), {}, headers);\n }\n}","import {BcfResourceCollectionPath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {Observable} from \"rxjs\";\nimport {BcfViewpointPaths} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths\";\n\nexport class BcfViewpointCollectionPath extends BcfResourceCollectionPath {\n readonly bcfTopicService = new BcfApiRequestService(this.injector);\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n throw new Error(\"Not implemented\");\n }\n\n post(viewpoint:BcfViewpointInterface):Observable {\n return this\n .bcfTopicService\n .request(\n 'post',\n this.toPath(),\n viewpoint\n );\n }\n}","import {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {BcfResourceCollectionPath, BcfResourcePath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfTopicResource} from \"core-app/modules/bim/bcf/api/topics/bcf-topic.resource\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {BcfViewpointPaths} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths\";\nimport {BcfViewpointCollectionPath} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint-collection.paths\";\n\nexport class BcfTopicPaths extends BcfResourcePath {\n readonly bcfTopicService = new BcfApiRequestService(this.injector, BcfTopicResource);\n\n /** /comments */\n public readonly comments = new BcfResourceCollectionPath(this.injector, this.path, 'comments');\n\n /** /viewpoints */\n public readonly viewpoints = new BcfViewpointCollectionPath(this.injector, this.path, 'viewpoints', BcfViewpointPaths);\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n return this.bcfTopicService.get(this.toPath(), params, headers);\n }\n}","import {BcfResourceCollectionPath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {Observable} from \"rxjs\";\nimport {BcfTopicPaths} from \"core-app/modules/bim/bcf/api/topics/bcf-topic.paths\";\nimport {Injector} from \"@angular/core\";\nimport {BcfTopicResource} from \"core-app/modules/bim/bcf/api/topics/bcf-topic.resource\";\n\nexport class BcfTopicCollectionPath extends BcfResourceCollectionPath {\n readonly bcfTopicService = new BcfApiRequestService(this.injector, BcfTopicResource);\n\n constructor(readonly injector:Injector,\n protected basePath:string,\n segment:string) {\n super(injector, basePath, segment, BcfTopicPaths);\n }\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n throw new Error(\"Not implemented\");\n }\n\n /**\n * Create a topic from its to-be-associated work package\n */\n post(payload:any):Observable {\n return this\n .bcfTopicService\n .request(\n 'post',\n this.toPath(),\n payload\n );\n }\n}","import {jsonArrayMember, jsonObject} from \"typedjson\";\n\n@jsonObject\nexport class BcfExtensionResource {\n\n @jsonArrayMember(String)\n topic_actions:string[];\n\n @jsonArrayMember(String)\n project_actions:string[];\n\n @jsonArrayMember(String)\n comment_actions:string[];\n}\n","import {BcfResourcePath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {BcfExtensionResource} from \"core-app/modules/bim/bcf/api/extensions/bcf-extension.resource\";\n\nexport class BcfExtensionPaths extends BcfResourcePath {\n readonly bcfExtensionService = new BcfApiRequestService(this.injector, BcfExtensionResource);\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n return this.bcfExtensionService.get(this.toPath(), params, headers);\n }\n}\n","import {BcfResourcePath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfApiRequestService} from \"core-app/modules/bim/bcf/api/bcf-api-request.service\";\nimport {BcfProjectResource} from \"core-app/modules/bim/bcf/api/projects/bcf-project.resource\";\nimport {HTTPClientHeaders, HTTPClientParamMap} from \"core-app/modules/hal/http/http.interfaces\";\nimport {BcfTopicCollectionPath} from \"core-app/modules/bim/bcf/api/topics/bcf-viewpoint-collection.paths\";\nimport {BcfExtensionPaths} from \"core-app/modules/bim/bcf/api/extensions/bcf-extension.paths\";\n\nexport class BcfProjectPaths extends BcfResourcePath {\n readonly bcfProjectService = new BcfApiRequestService(this.injector, BcfProjectResource);\n\n /** /topics */\n public readonly topics = new BcfTopicCollectionPath(this.injector, this.path, 'topics');\n\n public readonly extensions = new BcfExtensionPaths(this.injector, this.path, 'extensions');\n\n get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) {\n return this.bcfProjectService.get(this.toPath(), params, headers);\n }\n}","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injectable, Injector} from \"@angular/core\";\nimport {BcfResourceCollectionPath} from \"core-app/modules/bim/bcf/api/bcf-path-resources\";\nimport {BcfProjectPaths} from \"core-app/modules/bim/bcf/api/projects/bcf-project.paths\";\n\n\n@Injectable({ providedIn: 'root' })\nexport class BcfApiService {\n\n public readonly bcfApiVersion = '2.1';\n public readonly appBasePath = window.appBasePath || '';\n public readonly bcfApiBase = `${this.appBasePath}/api/bcf/${this.bcfApiVersion}`;\n\n // /api/bcf/:version/projects\n public readonly projects = new BcfResourceCollectionPath(this.injector, this.bcfApiBase, 'projects', BcfProjectPaths);\n\n constructor(readonly injector:Injector) {\n }\n\n /**\n * Parse the given string into a BCF resource path\n *\n * @param href\n */\n parse(href:string):T {\n if (!href.startsWith(this.bcfApiBase)) {\n throw new Error(`Cannot parse ${href} into BCF resource.`);\n }\n\n const parts = href\n .replace(this.bcfApiBase + '/', '')\n .split('/');\n\n // Try to find a target collection or resource\n let current:any = this;\n\n for (let i = 0; i < parts.length; i++) {\n let pathOrId:string = parts[i];\n if (pathOrId in current) {\n // Current has a member named like this URL part\n // descend into it\n current = current[pathOrId];\n } else if (current instanceof BcfResourceCollectionPath) {\n // Otherwise, assume we're looking for an ID\n current = current.id(pathOrId);\n } else {\n // Otherwise, return the current\n break;\n }\n }\n\n return current === this ? undefined : current;\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {ColorsService} from \"core-app/modules/common/colors/colors.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport interface UserLike {\n name:string;\n id:string|number|null;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class UserAvatarRendererService {\n\n constructor(private pathHelper:PathHelperService,\n private apiV3Service:APIV3Service,\n private colors:ColorsService) {\n\n }\n\n renderMultiple(container:HTMLElement,\n users:UserLike[],\n renderName:boolean = true,\n multiLine:boolean = false) {\n\n const span = document.createElement('span');\n\n\n for (let i = 0; i < users.length; i++) {\n const avatar = document.createElement('span');\n if (multiLine) {\n avatar.classList.add('user-avatar--multi-line');\n }\n\n this.render(avatar, users[i], renderName);\n\n if (!multiLine && i < users.length - 1) {\n const sep = document.createElement('span');\n sep.textContent = ', ';\n avatar.appendChild(sep);\n }\n\n span.appendChild(avatar);\n }\n\n container.appendChild(span);\n }\n\n render(container:HTMLElement,\n user:UserLike,\n renderName:boolean = true,\n classes:string = 'avatar-medium'):void {\n const userInitials = this.getInitials(user.name);\n const colorCode = this.colors.toHsl(user.name);\n\n let fallback = document.createElement('div');\n fallback.className = classes;\n fallback.classList.add('avatar-default');\n fallback.textContent = userInitials;\n fallback.style.background = colorCode;\n\n container.appendChild(fallback);\n\n if (renderName) {\n const name = document.createElement('span');\n name.textContent = user.name;\n container.appendChild(name);\n }\n\n // Avoid using the image when ID is null\n if (!user.id) {\n return;\n }\n\n const image = new Image();\n image.className = classes;\n image.classList.add('avatar--fallback');\n image.src = this.apiV3Service.users.id(user.id).avatar.toString();\n image.title = user.name;\n image.alt = user.name;\n image.onload = function () {\n fallback.replaceWith(image);\n (fallback as any) = undefined;\n };\n }\n\n private getInitials(name:string) {\n let characters = [...name];\n let lastSpace = name.lastIndexOf(' ');\n let first = characters[0]?.toUpperCase();\n let last = name[lastSpace + 1]?.toUpperCase();\n\n return [first, last].join(\"\");\n }\n}","import {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport namespace AngularTrackingHelpers {\n export function halHref(_index:number, item:T):string|null {\n return item.$href;\n }\n\n export function compareByName(a:T|undefined|null, b:T|undefined|null):boolean {\n return compareByAttribute('name')(a, b);\n }\n\n export function compareByAttribute(attribute:string) {\n return (a:any, b:any) => {\n const bothNil = !a && !b;\n return bothNil || (!!a && !!b && a[attribute] === b[attribute]);\n };\n }\n\n export function trackByName(i:number, item:any) {\n return _.get(item, 'name');\n }\n\n export function trackByHref(i:number, item:HalResource) {\n return _.get(item, 'href');\n }\n\n export function trackByProperty(prop:string) {\n return (i:number, item:HalResource) => _.get(item, prop);\n }\n\n export function trackByHrefAndProperty(propertyName:string) {\n return (i:number, item:HalResource) => {\n let href = _.get(item, 'href');\n let prop = _.get(item, propertyName, 'none');\n\n return `${href}#${propertyName}=${prop}`;\n };\n }\n\n export function trackByTrackingIdentifier(i:number, item:any) {\n return _.get(item, 'trackingIdentifier', item && item.href);\n }\n\n export function compareByHref(a:T|undefined|null, b:T|undefined|null):boolean {\n const bothNil = !a && !b;\n return bothNil || (!!a && !!b && a.$href === b.$href);\n }\n\n export function compareByHrefOrString(a:T|string|undefined|null, b:T|string|undefined|null):boolean {\n if (a instanceof HalResource && b instanceof HalResource) {\n return compareByHref(a as HalResource, b as HalResource);\n }\n\n const bothNil = !a && !b;\n return bothNil || a === b;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {ActivityPanelBaseController} from 'core-components/wp-single-view-tabs/activity-panel/activity-base.controller';\nimport {ChangeDetectionStrategy, Component, Input} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {ActivityEntryInfo} from 'core-components/wp-single-view-tabs/activity-panel/activity-entry-info';\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\n\n@Component({\n selector: 'newest-activity-on-overview',\n templateUrl: './activity-on-overview.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class NewestActivityOnOverviewComponent extends ActivityPanelBaseController {\n @Input('workPackage') public workPackage:WorkPackageResource;\n\n public latestActivityInfo:ActivityEntryInfo[] = [];\n public trackByHref = AngularTrackingHelpers.trackByProperty('identifier');\n\n ngOnInit() {\n this.workPackageId = this.workPackage.id!;\n super.ngOnInit();\n }\n\n protected shouldShowToggler() {\n return false;\n }\n\n protected updateActivities(activities:any) {\n super.updateActivities(activities);\n this.latestActivityInfo = this.latestActivities();\n }\n\n private latestActivities(visible:number = 3) {\n\n if (this.reverse) {\n // In reverse, we already get reversed entries from API.\n // So simply take the first three\n let segment = this.unfilteredActivities.slice(0, visible);\n return segment.map((el:HalResource, i:number) => this.info(el, i));\n } else {\n // In ascending sort, take the last three items\n let segment = this.unfilteredActivities.slice(-visible);\n let startIndex = this.unfilteredActivities.length - segment.length;\n return segment.map((el:HalResource, i:number) => this.info(el, startIndex + i));\n }\n }\n}\n","\n \n
\n
\n \n \n
\n
\n
\n
\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-relations-hierarchy',\n templateUrl: './wp-relations-hierarchy.template.html'\n})\nexport class WorkPackageRelationsHierarchyComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public relationType:string;\n\n public showEditForm:boolean = false;\n public workPackagePath:string;\n public canHaveChildren:boolean;\n public canModifyHierarchy:boolean;\n public canAddRelation:boolean;\n\n public childrenQueryProps:any;\n\n constructor(protected wpRelationsHierarchyService:WorkPackageRelationsHierarchyService,\n protected apiV3Service:APIV3Service,\n protected PathHelper:PathHelperService,\n readonly I18n:I18nService) {\n super();\n }\n\n public text = {\n parentHeadline: this.I18n.t('js.relations_hierarchy.parent_headline'),\n childrenHeadline: this.I18n.t('js.relations_hierarchy.children_headline'),\n };\n\n ngOnInit() {\n this.workPackagePath = this.PathHelper.workPackagePath(this.workPackage.id!);\n this.canModifyHierarchy = !!this.workPackage.changeParent;\n this.canAddRelation = !!this.workPackage.addRelation;\n\n this.childrenQueryProps = {\n filters: JSON.stringify([{ parent: { operator: '=', values: [this.workPackage.id] } }]),\n 'columns[]': ['id', 'type', 'subject', 'status'],\n showHierarchies: false\n };\n\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n\n let parentId = this.workPackage.parent?.id?.toString();\n\n if (parentId) {\n this\n .apiV3Service\n .work_packages\n .id(parentId)\n .get()\n .pipe(\n take(1)\n )\n .subscribe((parent:WorkPackageResource) => {\n this.workPackage.parent = parent;\n });\n }\n });\n }\n}\n","
\n
\n
\n

\n

\n
\n
\n \n \n \n \n
\n","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 isDuplicatedCell?:boolean;\n withAlternativeLabels?:boolean;\n}\n\n/**\n *\n */\nexport function calculatePositionValueForDayCountingPx(viewParams:TimelineViewParameters, days:number):number {\n const daysInPx = days * viewParams.pixelPerDay;\n return daysInPx;\n}\n\n/**\n *\n */\nexport function calculatePositionValueForDayCount(viewParams:TimelineViewParameters, days:number):string {\n const value = calculatePositionValueForDayCountingPx(viewParams, days);\n return value + 'px';\n}\n\nexport function getTimeSlicesForHeader(vp:TimelineViewParameters,\n unit:moment.unitOfTime.DurationConstructor,\n startView:Moment,\n endView:Moment) {\n\n const inViewport:[Moment, Moment][] = [];\n const rest:[Moment, Moment][] = [];\n\n const time = startView.clone().startOf(unit);\n const end = endView.clone().endOf(unit);\n\n while (time.isBefore(end)) {\n const sliceStart = moment.max(time, startView).clone();\n const sliceEnd = moment.min(time.clone().endOf(unit), endView).clone();\n time.add(1, unit);\n\n const viewport = vp.visibleViewportAtCalculationTime;\n if ((sliceStart.isSameOrAfter(viewport[0]) && sliceStart.isSameOrBefore(viewport[1]))\n || (sliceEnd.isSameOrAfter(viewport[0]) && sliceEnd.isSameOrBefore(viewport[1]))) {\n\n inViewport.push([sliceStart, sliceEnd]);\n } else {\n rest.push([sliceStart, sliceEnd]);\n }\n }\n\n const firstRest:[Moment, Moment] = rest.splice(0, 1)[0];\n const lastRest:[Moment, Moment] = rest.pop()!;\n const inViewportAndBoundaries = _.concat(\n [firstRest].filter(e => !_.isNil(e)),\n inViewport,\n [lastRest].filter(e => !_.isNil(e))\n );\n\n return {\n inViewportAndBoundaries,\n rest\n };\n\n}\n\nexport function calculateDaySpan(visibleWorkPackages:RenderedWorkPackage[],\n loadedWorkPackages:MultiInputState,\n viewParameters:TimelineViewParameters):number {\n let earliest:Moment = moment();\n let latest:Moment = moment();\n\n visibleWorkPackages.forEach((renderedRow) => {\n const wpId = renderedRow.workPackageId;\n\n if (!wpId) {\n return;\n }\n const workPackageState:InputState = loadedWorkPackages.get(wpId);\n const workPackage:WorkPackageResource|undefined = workPackageState.value;\n\n if (!workPackage) {\n return;\n }\n\n const start = workPackage.startDate ? workPackage.startDate : workPackage.date;\n if (start && moment(start).isBefore(earliest)) {\n earliest = moment(start);\n }\n\n const due = workPackage.dueDate ? workPackage.dueDate : workPackage.date;\n if (due && moment(due).isAfter(latest)) {\n latest = moment(due);\n }\n });\n\n const daysSpan = latest.diff(earliest, 'days') + 1;\n return daysSpan;\n}\n","import {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 {Observable, Subject} from 'rxjs';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {HookService} from 'core-app/modules/plugins/hook-service';\nimport {WorkPackageFilterValues} from \"core-components/wp-edit-form/work-package-filter-values\";\nimport {\n HalResourceEditingService,\n ResourceChangesetCommit\n} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {filter} from \"rxjs/operators\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {HalResource, HalSource, HalSourceLink} from \"core-app/modules/hal/resources/hal-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\n\nexport const newWorkPackageHref = '/api/v3/work_packages/new';\n\n@Injectable()\nexport class WorkPackageCreateService extends UntilDestroyedMixin {\n protected form:Promise|undefined;\n\n // Allow callbacks to happen on newly created work packages\n protected newWorkPackageCreatedSubject = new Subject();\n\n constructor(protected injector:Injector,\n protected hooks:HookService,\n protected apiV3Service:APIV3Service,\n protected halResourceService:HalResourceService,\n protected querySpace:IsolatedQuerySpace,\n protected authorisationService:AuthorisationService,\n protected halEditing:HalResourceEditingService,\n protected schemaCache:SchemaCacheService,\n protected halEvents:HalEventsService) {\n super();\n\n this.halEditing\n .committedChanges\n .pipe(\n this.untilDestroyed(),\n filter(commit => commit.resource._type === 'WorkPackage' && commit.wasNew)\n )\n .subscribe((commit:ResourceChangesetCommit) => {\n this.newWorkPackageCreated(commit.resource);\n });\n\n this.halEditing\n .changes$(newWorkPackageHref)\n .pipe(\n this.untilDestroyed(),\n filter(changeset => !changeset)\n )\n .subscribe(() => {\n this.reset();\n });\n }\n\n protected newWorkPackageCreated(wp:WorkPackageResource) {\n this.reset();\n this.newWorkPackageCreatedSubject.next(wp);\n }\n\n public onNewWorkPackage():Observable {\n return this.newWorkPackageCreatedSubject.asObservable();\n }\n\n public createNewWorkPackage(projectIdentifier:string|undefined|null, payload:HalSource):Promise {\n return this\n .apiV3Service\n .withOptionalProject(projectIdentifier)\n .work_packages\n .form\n .forPayload(payload)\n .toPromise()\n .then((form:FormResource) => {\n return this.fromCreateForm(form);\n });\n }\n\n public fromCreateForm(form:FormResource):WorkPackageChangeset {\n let wp = this.initializeNewResource(form);\n\n const change = this.halEditing.edit(wp, form);\n\n // Call work package initialization hook\n this.hooks.call('workPackageNewInitialization', change);\n\n return change;\n }\n\n public copyWorkPackage(copyFrom:WorkPackageChangeset) {\n let request = copyFrom.pristineResource.$source;\n\n // Ideally we would make an empty request before to get the create schema (cannot use the update schema of the source changeset)\n // to get all the writable attributes and only send those.\n // But as this would require an additional request, we don't.\n return this\n .apiV3Service\n .work_packages\n .form\n .post(request)\n .toPromise()\n .then((form:FormResource) => {\n let changeset = this.fromCreateForm(form);\n\n return changeset;\n });\n }\n\n /**\n * Create a copy resource from other and the new work package form\n * @param form Work Package create form\n */\n private copyFrom(form:FormResource) {\n let wp = this.initializeNewResource(form);\n\n return this.halEditing.edit(wp, form);\n }\n\n\n public getEmptyForm(projectIdentifier:string|null|undefined):Promise {\n if (!this.form) {\n this.form = this\n .apiV3Service\n .withOptionalProject(projectIdentifier)\n .work_packages\n .form\n .post({})\n .toPromise();\n }\n\n return this.form as Promise;\n }\n\n public cancelCreation() {\n this.halEditing.stopEditing({ href: newWorkPackageHref });\n this.reset();\n }\n\n public changesetUpdates$() {\n return this\n .halEditing\n .state(newWorkPackageHref)\n .values$();\n }\n\n public createOrContinueWorkPackage(projectIdentifier:string|null|undefined, type?:number, defaults?:HalSource) {\n let changePromise = this.continueExistingEdit(type);\n\n if (!changePromise) {\n changePromise = this.createNewWithDefaults(projectIdentifier, defaults);\n }\n\n return changePromise.then((change:WorkPackageChangeset) => {\n this.authorisationService.initModelAuth('work_package', change.pristineResource);\n this.halEditing.updateValue(newWorkPackageHref, change);\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(change.pristineResource, true);\n\n return change;\n });\n }\n\n protected reset() {\n this\n .apiV3Service\n .work_packages\n .cache\n .clearSome('new');\n this.form = undefined;\n }\n\n protected continueExistingEdit(type?:number) {\n const change = this.halEditing.state(newWorkPackageHref).value as WorkPackageChangeset;\n if (change !== undefined) {\n const changeType = change.projectedResource.type;\n\n const hasChanges = !change.isEmpty();\n const typeEmpty = !changeType && !type;\n const typeMatches = type && changeType && changeType.idFromLink === type.toString();\n\n if (hasChanges && (typeEmpty || typeMatches)) {\n return Promise.resolve(change);\n }\n }\n\n return null;\n }\n\n /**\n * Initializes a new work package. The work package is not yet persisted.\n * The properties of the work package are initialized from two sources:\n * * The default values provided\n * * The filter values that might exist in the query space\n *\n * The first can be employed to e.g. provide the type or the parent of the work package.\n * The later can be employed to create a work package that adheres to the filter values.\n *\n * @params projectIdentifier The project the work package is to be created in.\n * @param defaults Values the new work package should possess on creation.\n */\n protected createNewWithDefaults(projectIdentifier:string|null|undefined, defaults?:HalSource) {\n return this\n .withFiltersPayload(projectIdentifier, defaults)\n .then(filterDefaults => {\n const mergedPayload = _.merge({ _links: {} }, filterDefaults, defaults);\n\n return this.createNewWorkPackage(projectIdentifier, mergedPayload).then((change:WorkPackageChangeset) => {\n if (!change) {\n throw 'No new work package was created';\n }\n\n // We need to apply the defaults again (after them being applied in the form requests)\n // here as the initial form requests might have led to some default\n // values not being carried over. This can happen when custom fields not available in one type are filter values.\n this.defaultsFromFilters(change, defaults);\n\n return change;\n });\n });\n }\n\n /**\n * Fetches all values of filters applicable to work as default values (e.g. assignee = 123).\n * If defaults already contain the type, that filter is ignored.\n *\n * The ignoring functionality could be generalized.\n *\n * @params object\n * @param defaults\n */\n private defaultsFromFilters(object:HalSource|WorkPackageChangeset, defaults?:HalSource) {\n // Not using WorkPackageViewFiltersService here as the embedded table does not load the form\n // which will result in that service having empty current filters.\n let query = this.querySpace.query.value;\n\n if (query) {\n const except:string[] = defaults?._links && defaults._links['type'] ? ['type'] : [];\n\n new WorkPackageFilterValues(this.injector, query.filters, except)\n .applyDefaultsFromFilters(object);\n }\n }\n\n /**\n * Returns valid payload based on the filters active in the query space validated by the backend via a form\n * request. In case no filters are active, the (empty) filters payload is just passed through.\n *\n * If there are filters applied, we need the additional form request to turn the defaults of the filters into\n * a valid payload in the sense that all properties are at their correct place and are in the right format. That means\n * HalResources are in the _links section and follow the { href: some_link } format while simple properties stay on the\n * top level.\n */\n private withFiltersPayload(projectIdentifier:string|null|undefined, defaults?:HalSource):Promise {\n const fromFilter = { _links: {} };\n this.defaultsFromFilters(fromFilter, defaults);\n\n const filtersApplied = Object.keys(fromFilter).length > 1 || Object.keys(fromFilter._links).length > 0;\n\n if (filtersApplied) {\n return this\n .apiV3Service\n .withOptionalProject(projectIdentifier)\n .work_packages\n .form\n .forTypePayload(defaults || { _links: {} })\n .toPromise()\n .then((form:FormResource) => {\n this.toApiPayload(fromFilter, form.schema);\n return fromFilter;\n });\n } else {\n return Promise.resolve(fromFilter);\n }\n }\n\n private toApiPayload(payload:HalSource, schema:SchemaResource) {\n let links:string[] = [];\n\n Object.keys(schema.$source).forEach(attribute => {\n if (!['Integer',\n 'Float',\n 'Date',\n 'DateTime',\n 'Duration',\n 'Formattable',\n 'Boolean',\n 'String',\n 'Text',\n undefined].includes(schema.$source[attribute].type)) {\n links.push(attribute);\n }\n });\n\n links.forEach(attribute => {\n const value = payload[attribute];\n if (value === undefined) {\n // nothing\n } else if (value instanceof HalResource) {\n payload._links[attribute] = { href: value.$links.self.href };\n } else if (!value) {\n payload._links[attribute] = { href: null };\n } else {\n payload._links[attribute] = value as unknown as HalSourceLink;\n }\n delete payload[attribute];\n });\n }\n\n /**\n * Assign values from the form for a newly created work package resource.\n * @param form\n */\n private initializeNewResource(form:FormResource) {\n let payload = form.payload.$plain();\n\n // maintain the reference to the schema\n payload['_links']['schema'] = { href: 'new' };\n\n let wp = this.halResourceService.createHalResourceOfType('WorkPackage', payload);\n\n wp.$source.id = 'new';\n\n // Ensure type is set to identify the resource\n wp._type = 'WorkPackage';\n\n // Since the ID will change upon saving, keep track of the WP\n // with the actual creation date\n wp.__initialized_at = Date.now();\n\n // Set update link to form\n wp['update'] = wp.$links.update = form.$links.self;\n // Use POST /work_packages for saving link\n wp['updateImmediately'] = wp.$links.updateImmediately = (payload) => {\n return this.apiV3Service.work_packages.post(payload).toPromise();\n };\n\n // We need to provide the schema to the cache so that it is available in the html form to e.g. determine\n // the editability.\n // It would be better if the edit field could simply rely on the changeset if it exists.\n this.schemaCache.update(wp, form.schema);\n\n return wp;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {Transition} from \"@uirouter/core\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Directive()\nexport class ActivityPanelBaseController extends UntilDestroyedMixin implements OnInit {\n public workPackage:WorkPackageResource;\n public workPackageId:string;\n\n // All activities retrieved for the work package\n public unfilteredActivities:HalResource[] = [];\n\n // Visible activities\n public visibleActivities:ActivityEntryInfo[] = [];\n\n public reverse:boolean;\n public showToggler:boolean;\n\n public onlyComments:boolean = false;\n public togglerText:string;\n public text = {\n commentsOnly: this.I18n.t('js.label_activity_show_only_comments'),\n showAll: this.I18n.t('js.label_activity_show_all')\n };\n\n constructor(readonly apiV3Service:APIV3Service,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly $transition:Transition,\n readonly wpActivity:WorkPackagesActivityService) {\n super();\n\n this.reverse = wpActivity.isReversed;\n this.togglerText = this.text.commentsOnly;\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.wpActivity.require(this.workPackage).then((activities:any) => {\n this.updateActivities(activities);\n this.cdRef.detectChanges();\n });\n });\n }\n\n protected updateActivities(activities:HalResource[]) {\n this.unfilteredActivities = activities;\n\n const visible = this.getVisibleActivities();\n this.visibleActivities = visible.map((el:HalResource, i:number) => this.info(el, i));\n this.showToggler = this.shouldShowToggler();\n }\n\n protected shouldShowToggler() {\n const count_all = this.unfilteredActivities.length;\n const count_with_comments = this.getActivitiesWithComments().length;\n\n return count_all > 1 &&\n count_with_comments > 0 &&\n count_with_comments < this.unfilteredActivities.length;\n }\n\n protected getVisibleActivities() {\n if (!this.onlyComments) {\n return this.unfilteredActivities;\n } else {\n return this.getActivitiesWithComments();\n }\n }\n\n protected getActivitiesWithComments() {\n return this.unfilteredActivities\n .filter((activity:HalResource) => !!_.get(activity, 'comment.html'));\n }\n\n public toggleComments() {\n this.onlyComments = !this.onlyComments;\n this.updateActivities(this.unfilteredActivities);\n\n if (this.onlyComments) {\n this.togglerText = this.text.showAll;\n } else {\n this.togglerText = this.text.commentsOnly;\n }\n }\n\n public info(activity:HalResource, index:number) {\n return this.wpActivity.info(this.unfilteredActivities, activity, index);\n }\n}\n\n","/**\n * Return the row html id attribute for the given work package ID.\n */\nimport {collapsedGroupClass} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\n\nexport function rowId(workPackageId:string):string {\n return `wp-row-${workPackageId}-table`;\n}\n\nexport function relationRowClass():string {\n return `wp-table--relations-aditional-row`;\n}\n\nexport function locateTableRow(workPackageId:string):JQuery {\n return jQuery('.' + rowId(workPackageId));\n}\n\nexport function locateTableRowByIdentifier(identifier:string) {\n return jQuery(`.${identifier}-table`);\n}\n\nexport function isInsideCollapsedGroup(el?:Element | null) {\n if (!el) {\n return false;\n }\n\n return Array.from(el.classList).find(listClass => listClass.includes(collapsedGroupClass())) != null;\n}\n\nexport function locatePredecessorBySelector(el:HTMLElement, selector:string):HTMLElement|null {\n let previous = el.previousElementSibling;\n\n while (previous) {\n if (previous.matches(selector)) {\n return previous as HTMLElement;\n } else {\n previous = previous.previousElementSibling;\n }\n }\n\n return null;\n}\n\nexport function scrollTableRowIntoView(workPackageId:string):void {\n try {\n const element = locateTableRow(workPackageId);\n const container = element.scrollParent()!;\n const containerTop = container.scrollTop()!;\n const containerBottom = containerTop + container.height()!;\n\n const elemTop = element[0].offsetTop;\n const elemBottom = elemTop + element.height()!;\n\n if (elemTop < containerTop) {\n container[0].scrollTop = elemTop;\n } else if (elemBottom > containerBottom) {\n container[0].scrollTop = elemBottom - container.height()!;\n }\n } catch (e) {\n console.warn(\"Can't scroll row element into view: \" + e);\n }\n}\n","import {Injector} from \"@angular/core\";\nimport {\n OpEditingPortalChangesetToken,\n OpEditingPortalHandlerToken,\n OpEditingPortalSchemaToken\n} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {PortalInjector} from \"@angular/cdk/portal\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\n\n/**\n * Creates an injector for the edit field portal to pass data into.\n *\n * @returns {PortalInjector}\n */\nexport function createLocalInjector(injector:Injector, change:ResourceChangeset, fieldHandler:EditFieldHandler, schema:IFieldSchema):Injector {\n const injectorTokens = new WeakMap();\n\n injectorTokens.set(OpEditingPortalChangesetToken, change);\n injectorTokens.set(OpEditingPortalHandlerToken, fieldHandler);\n injectorTokens.set(OpEditingPortalSchemaToken, schema);\n\n return new PortalInjector(injector, injectorTokens);\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Moment} from 'moment';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport { OnInit, Directive } from '@angular/core';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Directive()\nexport abstract class AbstractDateTimeValueController extends UntilDestroyedMixin implements OnInit {\n public filter:QueryFilterInstanceResource;\n\n constructor(protected I18n:I18nService,\n protected timezoneService:TimezoneService) {\n super();\n }\n\n ngOnInit() {\n _.remove(this.filter.values as string[], value => !this.timezoneService.isValidISODateTime(value));\n }\n\n public abstract get lowerBoundary():Moment|null;\n\n public abstract get upperBoundary():Moment|null;\n\n public isoDateParser(data:any) {\n if (!this.timezoneService.isValidISODate(data)) {\n return '';\n }\n var d = this.timezoneService.parseISODatetime(data);\n return this.timezoneService.formattedISODateTime(d);\n }\n\n public isoDateFormatter(data:any) {\n if (!this.timezoneService.isValidISODateTime(data)) {\n return '';\n }\n var d = this.timezoneService.parseISODatetime(data);\n return this.timezoneService.formattedISODate(d);\n }\n\n public get isTimeZoneDifferent() {\n let value = this.lowerBoundary || this.upperBoundary;\n\n if (!value) {\n return false;\n } else {\n return value.hours() !== 0 || value.minutes() !== 0;\n }\n }\n\n public get timeZoneText() {\n if (this.lowerBoundary && this.upperBoundary) {\n return this.I18n.t('js.filter.time_zone_converted.two_values',\n {\n from: this.lowerBoundary.format('YYYY-MM-DD HH:mm'),\n to: this.upperBoundary.format('YYYY-MM-DD HH:mm')\n });\n } else if (this.upperBoundary) {\n return this.I18n.t('js.filter.time_zone_converted.only_end',\n { to: this.upperBoundary.format('YYYY-MM-DD HH:mm') });\n\n } else if (this.lowerBoundary) {\n return this.I18n.t('js.filter.time_zone_converted.only_start',\n { from: this.lowerBoundary.format('YYYY-MM-DD HH:mm') });\n\n }\n\n return '';\n }\n}\n","import {Injector} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {PrimaryRenderPass} from '../primary-render-pass';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport abstract class RowsBuilder {\n\n @InjectField() public states:States;\n\n constructor(public readonly injector:Injector, public workPackageTable:WorkPackageTable) {\n }\n\n /**\n * Build all rows of the table.\n */\n public abstract buildRows():PrimaryRenderPass;\n\n /**\n * Determine if this builder applies to the current view mode.\n */\n public isApplicable(table:WorkPackageTable) {\n return true;\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {groupName} from './grouped-rows-helpers';\nimport {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {rowGroupClassName} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport function groupClassNameFor(group:GroupObject) {\n return `group-${group.identifier}`;\n}\n\nexport class GroupHeaderBuilder {\n\n @InjectField() public I18n:I18nService;\n public text:{ collapse:string, expand:string };\n\n constructor(public readonly injector:Injector) {\n this.text = {\n collapse: this.I18n.t('js.label_collapse'),\n expand: this.I18n.t('js.label_expand'),\n };\n }\n\n public buildGroupRow(group:GroupObject, colspan:number) {\n let row = document.createElement('tr');\n let togglerIconClass, text;\n\n if (group.collapsed) {\n text = this.text.expand;\n togglerIconClass = 'icon-plus';\n } else {\n text = this.text.collapse;\n togglerIconClass = 'icon-minus2';\n }\n\n row.classList.add(rowGroupClassName, groupClassNameFor(group));\n row.id = `wp-table-rowgroup-${group.index}`;\n row.dataset['groupIndex'] = (group.index).toString();\n row.dataset['groupIdentifier'] = group.identifier;\n row.innerHTML = `\n \n
\n ${_.escape(text)}\n
\n
\n ${_.escape(groupName(group))}\n \n (${group.count})\n \n
\n \n `;\n\n return row;\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {States} from '../../../states.service';\nimport {isRelationColumn, QueryColumn} from '../../../wp-query/query-column';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {tdClassName} from '../cell-builder';\nimport {commonRowClassName, SingleRowBuilder, tableRowClassName} from '../rows/single-row-builder';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {RelationColumnType} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport function relationGroupClass(workPackageId:string) {\n return `__relations-expanded-from-${workPackageId}`;\n}\n\nexport function relationIdentifier(targetId:string, workPackageId:string) {\n return `wp-relation-row-${workPackageId}-to-${targetId}`;\n}\n\nexport const relationCellClassName = 'wp-table--relation-cell-td';\n\nexport class RelationRowBuilder extends SingleRowBuilder {\n\n @InjectField() public states:States;\n @InjectField() public I18n:I18nService;\n\n constructor(public readonly injector:Injector,\n protected workPackageTable:WorkPackageTable) {\n\n super(injector, workPackageTable);\n }\n\n /**\n * For additional relation rows, we don't want to render an expandable relation cell,\n * but instead we render the relation label.\n * @param workPackage\n * @param column\n * @return {any}\n */\n public buildCell(workPackage:WorkPackageResource, column:QueryColumn):HTMLElement|null {\n\n // handle relation types\n if (isRelationColumn(column)) {\n return this.emptyRelationCell(column);\n }\n\n return super.buildCell(workPackage, column);\n }\n\n /**\n * Build the columns on the given empty row\n */\n public buildEmptyRelationRow(from:WorkPackageResource, relation:RelationResource, type:RelationColumnType):[HTMLElement, WorkPackageResource] {\n const denormalized = relation.denormalized(from);\n\n const to = this.states.workPackages.get(denormalized.targetId).value!;\n\n // Let the primary row builder build the row\n const row = this.createEmptyRelationRow(from, to);\n const [tr, _] = super.buildEmptyRow(to, row);\n\n return [tr, to];\n }\n\n /**\n * Create an empty unattached row element for the given work package\n * @param workPackage\n * @returns {any}\n */\n public createEmptyRelationRow(from:WorkPackageResource, to:WorkPackageResource) {\n const identifier = this.relationClassIdentifier(from, to);\n let tr = document.createElement('tr');\n tr.dataset['workPackageId'] = to.id!;\n tr.dataset['classIdentifier'] = identifier;\n\n tr.classList.add(\n commonRowClassName, tableRowClassName, 'issue',\n `wp-table--relations-aditional-row`,\n identifier,\n `${identifier}-table`,\n relationGroupClass(from.id!)\n );\n\n return tr;\n }\n\n public relationClassIdentifier(from:WorkPackageResource, to:WorkPackageResource) {\n return relationIdentifier(to.id!, from.id!);\n }\n\n /**\n *\n * @param from\n * @param denormalized\n * @param type\n */\n public appendRelationLabel(jRow:JQuery, from:WorkPackageResource, relation:RelationResource, columnId:string, type:RelationColumnType) {\n const denormalized = relation.denormalized(from);\n let typeLabel = '';\n\n // Add the relation label if this is a \"Relations for \" column\n if (type === 'toType') {\n typeLabel = this.I18n.t(`js.relation_labels.${denormalized.reverseRelationType}`);\n }\n // Add the WP type label if this is a \" Relations\" column\n if (type === 'ofType') {\n const wp = this.states.workPackages.get(denormalized.target.id!).value!;\n typeLabel = wp.type.name;\n }\n\n const relationLabel = document.createElement('span');\n relationLabel.classList.add('relation-row--type-label');\n relationLabel.textContent = typeLabel;\n\n const textNode = document.createTextNode(denormalized.target.name);\n\n jRow.find(`.${relationCellClassName}`).empty();\n jRow.find(`.${relationCellClassName}.${columnId}`).append(relationLabel);\n }\n\n protected emptyRelationCell(column:QueryColumn) {\n const cell = document.createElement('td');\n cell.classList.add(relationCellClassName, tdClassName, column.id);\n\n return cell;\n }\n}\n","import {Injector} from '@angular/core';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {PrimaryRenderPass, RowRenderInfo} from '../primary-render-pass';\nimport {relationGroupClass, RelationRowBuilder} from './relation-row-builder';\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {\n RelationColumnType,\n WorkPackageViewRelationColumnsService\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport interface RelationRenderInfo extends RowRenderInfo {\n data:{\n relation:RelationResource;\n columnId:string;\n relationType:RelationColumnType;\n };\n}\n\nexport class RelationsRenderPass {\n @InjectField() wpRelations:WorkPackageRelationsService;\n @InjectField() wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() wpTableRelationColumns:WorkPackageViewRelationColumnsService;\n\n public relationRowBuilder:RelationRowBuilder;\n\n constructor(public readonly injector:Injector,\n private table:WorkPackageTable,\n private tablePass:PrimaryRenderPass) {\n\n this.relationRowBuilder = new RelationRowBuilder(injector, table);\n }\n\n public render() {\n // If no relation column active, skip this pass\n if (!this.isApplicable) {\n return;\n }\n\n // Render for each original row, clone it since we're modifying the tablepass\n const rendered = _.clone(this.tablePass.renderedOrder);\n rendered.forEach((row:RowRenderInfo, position:number) => {\n\n // We only care for rows that are natural work packages\n if (!row.workPackage) {\n return;\n }\n\n // If the work package has no relations, ignore\n const workPackage = row.workPackage;\n const fromId = workPackage.id!;\n const state = this.wpRelations.state(fromId);\n if (!state.hasValue() || _.size(state.value) === 0) {\n return;\n }\n\n this.wpTableRelationColumns.relationsToExtendFor(workPackage,\n state.value,\n (relation:RelationResource, column:QueryColumn, type:any) => {\n\n // Build each relation row (currently sorted by order defined in API)\n const [relationRow, target] = this.relationRowBuilder.buildEmptyRelationRow(\n workPackage,\n relation,\n type\n );\n\n // Augment any data for the belonging work package row to it\n relationRow.classList.add(...row.additionalClasses);\n this.relationRowBuilder.appendRelationLabel(jQuery(relationRow),\n workPackage,\n relation,\n column.id,\n type);\n\n // Insert next to the work package row\n // If no relations exist until here, directly under the row\n // otherwise as the last element of the relations\n // Insert into table\n this.tablePass.spliceRow(\n relationRow,\n `.${this.relationRowBuilder.classIdentifier(workPackage)},.${relationGroupClass(fromId)}`,\n {\n classIdentifier: this.relationRowBuilder.relationClassIdentifier(workPackage, target),\n additionalClasses: row.additionalClasses.concat(['wp-table--relations-aditional-row']),\n workPackage: target,\n belongsTo: workPackage,\n renderType: 'relations',\n hidden: row.hidden,\n data: {\n relation: relation,\n columnId: column.id,\n relationType: type\n }\n } as RelationRenderInfo\n );\n });\n });\n }\n\n public refreshRelationRow(renderedRow:RelationRenderInfo,\n workPackage:WorkPackageResource,\n oldRow:JQuery) {\n const newRow = this.relationRowBuilder.refreshRow(workPackage, oldRow);\n this.relationRowBuilder.appendRelationLabel(newRow,\n renderedRow.belongsTo!,\n renderedRow.data.relation,\n renderedRow.data.columnId,\n renderedRow.data.relationType);\n\n return newRow;\n }\n\n private get isApplicable() {\n return this.wpTableColumns.hasRelationColumns();\n }\n}\n","import {Injector} from '@angular/core';\nimport {PrimaryRenderPass, RowRenderInfo} from '../primary-render-pass';\nimport {TimelineRowBuilder} from './timeline-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\n\nexport class TimelineRenderPass {\n\n /** Row builders */\n protected timelineBuilder:TimelineRowBuilder;\n\n /** Resulting timeline body */\n public timelineBody:DocumentFragment;\n\n constructor(public readonly injector:Injector,\n private table:WorkPackageTable,\n private tablePass:PrimaryRenderPass) {\n }\n\n public render() {\n // Prepare and reset the render pass\n this.timelineBody = document.createDocumentFragment();\n this.timelineBuilder = new TimelineRowBuilder(this.injector, this.table);\n\n // Render into timeline fragment\n this.tablePass.renderedOrder.forEach((row:RowRenderInfo) => {\n const wpId = row.workPackage ? row.workPackage.id : null;\n\n const secondary = this.timelineBuilder.build(wpId);\n secondary.classList.add(row.classIdentifier, `${row.classIdentifier}-timeline`, ...row.additionalClasses);\n this.timelineBody.appendChild(secondary);\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {PrimaryRenderPass, RowRenderInfo} from \"core-components/wp-fast-table/builders/primary-render-pass\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HighlightingRenderPass {\n\n @InjectField() wpTableHighlighting:WorkPackageViewHighlightingService;\n @InjectField() querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n private table:WorkPackageTable,\n private tablePass:PrimaryRenderPass) {\n\n }\n\n public render() {\n // If highlighting is done inline in attributes, skip\n if (!this.isApplicable) {\n return;\n }\n\n const highlightAttribute = this.wpTableHighlighting.current.mode;\n\n // Get the computed style to identify bright properties\n const styles = window.getComputedStyle(document.body);\n\n // Render for each original row, clone it since we're modifying the tablepass\n this.tablePass.renderedOrder.forEach((row:RowRenderInfo, position:number) => {\n\n // We only care for rows that are natural work packages\n if (!row.workPackage) {\n return;\n }\n\n // Get the loaded attribute of the WP\n const property = row.workPackage[highlightAttribute] as HalResource;\n\n // We only color rows that have an active attribute\n if (!property) {\n return;\n }\n\n const id = property.id!;\n const element:HTMLElement = this.tablePass.tableBody.children[position] as HTMLElement;\n element.classList.add(Highlighting.backgroundClass(highlightAttribute, id));\n });\n }\n\n private get isApplicable() {\n return !(this.wpTableHighlighting.isInline || this.wpTableHighlighting.isDisabled);\n }\n}\n","import {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {tdClassName} from \"core-components/wp-fast-table/builders/cell-builder\";\nimport {Injector} from \"@angular/core\";\nimport {TableDragActionsRegistryService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-actions-registry.service\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {internalSortColumn} from \"core-components/wp-fast-table/builders/internal-sort-columns\";\n\n/** Debug the render position */\nconst RENDER_DRAG_AND_DROP_POSITION = false;\n\nexport class DragDropHandleBuilder {\n\n // Injections\n private actionService:TableDragActionService;\n\n constructor(public readonly injector:Injector) {\n const dragActionRegistry = this.injector.get(TableDragActionsRegistryService);\n this.actionService = dragActionRegistry.get(injector);\n }\n\n /**\n * Renders an angular CDK drag component into the column\n */\n public build(workPackage:WorkPackageResource, position?:number):HTMLElement {\n // Append sort handle\n let td = document.createElement('td');\n\n 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 {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {QueryOrder} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-order\";\n\nexport class DragDropHandleRenderPass {\n\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() public wpTableOrder:WorkPackageViewOrderService;\n\n // Drag & Drop handle builder\n protected dragDropHandleBuilder = new DragDropHandleBuilder(this.injector);\n\n constructor(public readonly injector:Injector,\n private table:WorkPackageTable,\n private tablePass:PrimaryRenderPass) {\n }\n\n public render() {\n if (!this.table.configuration.dragAndDropEnabled) {\n return;\n }\n\n\n this.wpTableOrder.withLoadedPositions().then((positions:QueryOrder) => {\n this.tablePass.renderedOrder.forEach((row:RowRenderInfo, position:number) => {\n // We only care for rows that are natural work packages and are not relation sub-rows\n if (!row.workPackage || row.renderType === 'relations') {\n return;\n }\n\n const handle = this.dragDropHandleBuilder.build(row.workPackage!, positions[row.workPackage!.id!]);\n\n if (handle) {\n row.element.replaceChild(handle, row.element.firstElementChild!);\n }\n });\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {timeOutput} from '../../../helpers/debug_output';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../../states.service';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageTable} from '../wp-fast-table';\nimport {RelationRenderInfo, RelationsRenderPass} from './relations/relations-render-pass';\nimport {SingleRowBuilder} from './rows/single-row-builder';\nimport {TimelineRenderPass} from './timeline/timeline-render-pass';\nimport {HighlightingRenderPass} from \"core-components/wp-fast-table/builders/highlighting/row-highlight-render-pass\";\nimport {DragDropHandleRenderPass} from \"core-components/wp-fast-table/builders/drag-and-drop/drag-drop-handle-render-pass\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport type RenderedRowType = 'primary'|'relations';\n\nexport interface RowRenderInfo {\n // The rendered row\n element:HTMLTableRowElement;\n // Unique class name as an identifier to uniquely identify the row in both table and timeline\n classIdentifier:string;\n // Additional classes to be added by any secondary render passes\n additionalClasses:string[];\n // If this row is a work package, contains a reference to the rendered WP\n workPackage:WorkPackageResource|null;\n // If this is an additional row not present, this contains a reference to the WP\n // it originated from\n belongsTo?:WorkPackageResource;\n // The type of row this was rendered from\n renderType:RenderedRowType;\n // Marks if the row is currently hidden to the user\n hidden:boolean;\n // Additional data by the render passes\n data?:any;\n}\n\nexport abstract class PrimaryRenderPass {\n\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() states:States;\n @InjectField() I18n:I18nService;\n\n /** The rendered order of rows of work package IDs or , if not a work package row */\n public renderedOrder:RowRenderInfo[];\n\n /** Resulting table body */\n public tableBody:DocumentFragment;\n\n /** Additional render pass that handles timeline rendering */\n public timeline:TimelineRenderPass;\n\n /** Additional render pass that handles table relation rendering */\n public relations:RelationsRenderPass;\n\n /** Additional render pass that handles drag'n'drop handle rendering */\n public dragDropHandle:DragDropHandleRenderPass;\n\n /** Additional render pass that handles highlighting of rows */\n public highlighting:HighlightingRenderPass;\n\n constructor(public readonly injector:Injector,\n public workPackageTable:WorkPackageTable,\n public rowBuilder:SingleRowBuilder) {\n }\n\n /**\n * Execute the entire render pass, executing this pass and all subsequent registered passes\n * for timeline and relations.\n * @return {PrimaryRenderPass}\n */\n public render():this {\n\n timeOutput('Primary render pass', () => {\n\n // Prepare and reset the render pass\n this.prepare();\n\n // Render into the table fragment\n this.doRender();\n\n // Post render\n this.postRender();\n });\n\n // Render subsequent passes\n // that may modify the structure of the table\n this.highlighting.render();\n\n timeOutput('Relations render pass', () => {\n this.relations.render();\n });\n\n timeOutput('Drag handle render pass', () => {\n this.dragDropHandle.render();\n });\n\n // Synchronize the rows to timeline\n timeOutput('Timelines render pass', () => {\n this.timeline.render();\n });\n\n return this;\n }\n\n /**\n * Refresh a single row using the render pass it was originally created from.\n * @param row\n */\n public refresh(row:RowRenderInfo, workPackage:WorkPackageResource, body:HTMLElement) {\n let oldRow = jQuery(body).find(`.${row.classIdentifier}`);\n let replacement:JQuery|null = null;\n\n switch (row.renderType) {\n case 'primary':\n replacement = this.rowBuilder.refreshRow(workPackage, oldRow);\n break;\n case 'relations':\n replacement = this.relations.refreshRelationRow(row as RelationRenderInfo, workPackage, oldRow);\n }\n\n if (replacement !== null && oldRow.length) {\n oldRow.replaceWith(replacement);\n }\n }\n\n public get result():RenderedWorkPackage[] {\n return this.renderedOrder.map((row) => {\n return {\n classIdentifier: row.classIdentifier,\n workPackageId: row.workPackage ? row.workPackage.id : null,\n hidden: row.hidden\n };\n });\n }\n\n /**\n * Splice a row into a specific location of the current render pass through the given selector.\n *\n * 1. Insert into the document fragment after the last match of the selector\n * 2. Splice into the renderedOrder array.\n */\n public spliceRow(row:HTMLElement, selector:string, renderedInfo:RowRenderInfo) {\n // Insert into table using the selector\n // If it matches multiple, select the last element\n const target = jQuery(this.tableBody)\n .find(selector)\n .last();\n\n target.after(row);\n\n // Splice the renderedOrder at this exact location\n const index = target.index();\n this.renderedOrder.splice(index + 1, 0, renderedInfo);\n }\n\n protected prepare() {\n this.timeline = new TimelineRenderPass(this.injector, this.workPackageTable, this);\n this.relations = new RelationsRenderPass(this.injector, this.workPackageTable, this);\n this.dragDropHandle = new DragDropHandleRenderPass(this.injector, this.workPackageTable, this);\n this.highlighting = new HighlightingRenderPass(this.injector, this.workPackageTable, this);\n this.tableBody = document.createDocumentFragment();\n this.renderedOrder = [];\n }\n\n /**\n * The actual render function of this renderer.\n */\n protected abstract doRender():void;\n\n /**\n * Post render shared among all sub passes\n */\n protected postRender():void {\n if (this.renderedOrder.length === 0 && this.workPackageTable.renderPlaceholderRow) {\n this.tableBody.appendChild(this.rowBuilder.placeholderRow);\n }\n }\n\n /**\n * Append a work package row to both containers\n * @param workPackage The work package, if the row belongs to one\n * @param row HTMLElement to append\n * @param rowClasses Additional classes to apply to the timeline row for mirroring purposes\n * @param hidden whether the row was rendered hidden\n */\n protected appendRow(workPackage:WorkPackageResource,\n row:HTMLTableRowElement,\n additionalClasses:string[] = [],\n hidden:boolean = false) {\n\n this.tableBody.appendChild(row);\n\n this.renderedOrder.push({\n classIdentifier: this.rowBuilder.classIdentifier(workPackage),\n additionalClasses: additionalClasses,\n workPackage: workPackage,\n renderType: 'primary',\n element: row,\n hidden: hidden\n });\n }\n\n /**\n * Append a non-work package row to both containers\n * @param row HTMLElement to append\n * @param classIdentifer a unique identifier for the two rows (one each in table/timeline).\n * @param hidden whether the row was rendered hidden\n */\n protected appendNonWorkPackageRow(row:HTMLTableRowElement,\n classIdentifer:string,\n additionalClasses:string[] = [],\n hidden:boolean = false) {\n row.classList.add(classIdentifer);\n this.tableBody.appendChild(row);\n\n this.renderedOrder.push({\n element: row,\n classIdentifier: classIdentifer,\n additionalClasses: additionalClasses,\n workPackage: null,\n renderType: 'primary',\n hidden: hidden\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {PrimaryRenderPass} from '../../primary-render-pass';\nimport {SingleRowBuilder} from '../../rows/single-row-builder';\n\nexport class PlainRenderPass extends PrimaryRenderPass {\n\n constructor(public readonly injector:Injector,\n public workPackageTable:WorkPackageTable,\n public rowBuilder:SingleRowBuilder) {\n\n super(injector, workPackageTable, rowBuilder);\n }\n\n /**\n * The actual render function of this renderer.\n */\n protected doRender():void {\n this.workPackageTable.originalRows.forEach((wpId:string) => {\n let row = this.workPackageTable.originalRowIndex[wpId];\n let [tr,] = this.rowBuilder.buildEmpty(row.object);\n row.element = tr;\n this.appendRow(row.object, tr);\n this.tableBody.appendChild(tr);\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {WorkPackageTableRow} from '../../../wp-table.interfaces';\nimport {SingleRowBuilder} from '../../rows/single-row-builder';\nimport {PlainRenderPass} from '../plain/plain-render-pass';\nimport {groupClassNameFor, GroupHeaderBuilder} from './group-header-builder';\nimport {groupByProperty, groupedRowClassName} from './grouped-rows-helpers';\nimport {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {collapsedRowClass} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants\";\nimport {GroupSumsBuilder} from \"core-components/wp-fast-table/builders/modes/grouped/group-sums-builder\";\n\nexport const groupRowClass = '-group-row';\n\nexport class GroupedRenderPass extends PlainRenderPass {\n\n private sumsBuilder = new GroupSumsBuilder(this.injector, this.workPackageTable);\n\n constructor(public readonly injector:Injector,\n public workPackageTable:WorkPackageTable,\n public groups:GroupObject[],\n public headerBuilder:GroupHeaderBuilder,\n public colspan:number) {\n\n super(injector, workPackageTable, new SingleRowBuilder(injector, workPackageTable));\n }\n\n /**\n * Rebuild the entire grouped tbody from the given table\n */\n protected doRender() {\n let currentGroup:GroupObject | null = null;\n const length = this.workPackageTable.originalRows.length;\n this.workPackageTable.originalRows.forEach((wpId:string, index:number) => {\n let row = this.workPackageTable.originalRowIndex[wpId];\n let nextGroup = this.matchingGroup(row.object);\n let groupsChanged = currentGroup !== nextGroup;\n\n // Render the sums row\n if (currentGroup && groupsChanged) {\n this.renderSumsRow(currentGroup);\n }\n\n // Render the next group row\n if (nextGroup && groupsChanged) {\n const groupClass = groupClassNameFor(nextGroup);\n let rowElement = this.headerBuilder.buildGroupRow(nextGroup, this.colspan);\n this.appendNonWorkPackageRow(rowElement, groupClass, [groupRowClass]);\n currentGroup = nextGroup;\n }\n\n row.group = currentGroup;\n this.buildSingleRow(row);\n });\n\n // Render the last sums row\n if (currentGroup) {\n this.renderSumsRow(currentGroup);\n }\n }\n\n /**\n * Find a matching group for the given work package.\n * The API sadly doesn't provide us with the information which group a WP belongs to.\n */\n private matchingGroup(workPackage:WorkPackageResource) {\n return _.find(this.groups, (group:GroupObject) => {\n let property = workPackage[groupByProperty(group)];\n // explicitly check for undefined as `false` (bool) is a valid value.\n if (property === undefined) {\n property = null;\n }\n\n // If the property is a multi-value\n // Compare the href's of all resources with the ones in valueLink\n if (_.isArray(property)) {\n return this.matchesMultiValue(property as HalResource[], group);\n }\n\n //// If its a linked resource, compare the href,\n //// which is an array of links the resource offers\n if (property && property.$href) {\n return !!_.find(group._links.valueLink, (l:any):any => property.$href === l.href);\n }\n\n // Otherwise, fall back to simple value comparison.\n let value = group.value === '' ? null : group.value;\n\n if (value) {\n // For matching we have to remove the % sign which is shown when grouping after progress\n value = value.replace('%', '');\n }\n\n // Values provided by the API are always string\n // so avoid triple equal here\n // tslint:disable-next-line\n return value == property;\n }) as GroupObject;\n }\n\n private matchesMultiValue(property:HalResource[], group:GroupObject) {\n if (property.length !== group.href.length) {\n return false;\n }\n\n let joinedOrderedHrefs = (objects:any[]) => {\n return _.map(objects, object => object.href).sort().join(', ');\n };\n\n return _.isEqualWith(\n property,\n group.href,\n (a, b) => joinedOrderedHrefs(a) === joinedOrderedHrefs(b)\n );\n }\n\n /**\n * Enhance a row from the rowBuilder with group information.\n */\n private buildSingleRow(row:WorkPackageTableRow):void {\n const group = row.group;\n\n if (!group) {\n console.warn(\"All rows should have a group, but this one doesn't %O\", row);\n }\n\n let hidden = false;\n let additionalClasses:string[] = [];\n\n let [tr, _] = this.rowBuilder.buildEmpty(row.object);\n\n if (group) {\n additionalClasses.push(groupedRowClassName(group.index));\n hidden = !!group.collapsed;\n\n if (hidden) {\n additionalClasses.push(collapsedRowClass);\n }\n }\n\n row.element = tr;\n tr.classList.add(...additionalClasses);\n this.appendRow(row.object, tr, additionalClasses, hidden);\n }\n\n /**\n * Render the sums row for the current group\n */\n private renderSumsRow(group:GroupObject) {\n if (!group.sums) {\n return;\n }\n\n const groupClass = groupClassNameFor(group);\n let rowElement = this.sumsBuilder.buildSumsRow(group);\n this.appendNonWorkPackageRow(rowElement, groupClass);\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {States} from '../../../../states.service';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {tableRowClassName} from '../../rows/single-row-builder';\nimport {RowsBuilder} from '../rows-builder';\nimport {GroupHeaderBuilder} from './group-header-builder';\nimport {GroupedRenderPass} from './grouped-render-pass';\nimport {groupedRowClassName, groupIdentifier} from './grouped-rows-helpers';\nimport {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {\n collapsedRowClass,\n rowGroupClassName\n} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class GroupedRowsBuilder extends RowsBuilder {\n\n // Injections\n @InjectField() private readonly querySpace:IsolatedQuerySpace;\n @InjectField() public states:States;\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() public I18n:I18nService;\n\n constructor(public readonly injector:Injector, workPackageTable:WorkPackageTable) {\n super(injector, workPackageTable);\n }\n\n /**\n * The hierarchy builder is only applicable if the hierachy mode is active\n */\n public isApplicable(table:WorkPackageTable) {\n return !_.isEmpty(this.groups);\n }\n\n /**\n * Returns the reference to the last table.groups state value\n */\n public get groups() {\n return this.querySpace.groups.value || [];\n }\n\n /**\n * Returns the reference to the last table.collapesedGroups state value\n */\n public get collapsedGroups() {\n return this.querySpace.collapsedGroups.value || {};\n }\n\n public get colspan() {\n // Columns + manual sorting column + settings column\n return this.wpTableColumns.columnCount + 2;\n }\n\n public buildRows() {\n const builder = new GroupHeaderBuilder(this.injector);\n return new GroupedRenderPass(\n this.injector,\n this.workPackageTable,\n this.getGroupData(),\n builder,\n this.colspan\n ).render();\n }\n\n /**\n * Refresh the group expansion state\n */\n public refreshExpansionState() {\n const groups = this.getGroupData();\n const rendered = this.querySpace.tableRendered.value!;\n const builder = new GroupHeaderBuilder(this.injector);\n\n jQuery(this.workPackageTable.tableAndTimelineContainer)\n .find(`.${rowGroupClassName}`)\n .each((i:number, oldRow:Element) => {\n let groupIndex = jQuery(oldRow).data('groupIndex');\n let group = groups[groupIndex];\n\n // Refresh the group header\n let newRow = builder.buildGroupRow(group, this.colspan);\n\n if (oldRow.parentNode) {\n oldRow.parentNode.replaceChild(newRow, oldRow);\n }\n\n // Set expansion state of contained rows\n const affected = jQuery(this.workPackageTable.tableAndTimelineContainer)\n .find(`.${groupedRowClassName(groupIndex)}`);\n affected.toggleClass(collapsedRowClass, !!group.collapsed);\n\n // Update the hidden section of the rendered state\n affected.filter(`.${tableRowClassName}`).each((i, el) => {\n // Get the index of this row\n const index = jQuery(el).index();\n\n // Update the hidden state\n rendered[index].hidden = !!group.collapsed;\n });\n });\n\n this.querySpace.tableRendered.putValue(rendered, 'Updated hidden state of rows after group change.');\n }\n\n /**\n * Augment the given groups with the current collapsed state data.\n */\n private getGroupData() {\n return this.groups.map((group:GroupObject, index:number) => {\n group.index = index;\n if (group._links && group._links.valueLink) {\n group.href = group._links.valueLink;\n }\n group.identifier = groupIdentifier(group);\n group.collapsed = this.collapsedGroups[group.identifier];\n return group;\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {additionalHierarchyRowClassName, SingleHierarchyRowBuilder} from './single-hierarchy-row-builder';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {PrimaryRenderPass, RowRenderInfo} from \"core-components/wp-fast-table/builders/primary-render-pass\";\nimport {States} from \"core-components/states.service\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageTableRow} from \"core-components/wp-fast-table/wp-table.interfaces\";\nimport {\n ancestorClassIdentifier,\n hierarchyGroupClass\n} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\nimport {WorkPackageViewHierarchies} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-hierarchies\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class HierarchyRenderPass extends PrimaryRenderPass {\n\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() states:States;\n @InjectField() apiV3Service:APIV3Service;\n @InjectField() wpTableHierarchies:WorkPackageViewHierarchiesService;\n\n // Remember which rows were already rendered\n readonly rendered:{ [workPackageId:string]:boolean } = {};\n\n // Remember additional parents inserted that are not part of the results table\n private additionalParents:{ [workPackageId:string]:WorkPackageResource } = {};\n\n // Defer children to be rendered when their parent occurs later in the table\n private deferred:{ [parentId:string]:WorkPackageResource[] } = {};\n\n // Collapsed state\n private hierarchies:WorkPackageViewHierarchies;\n\n // Build a map of hierarchy elements present in the table\n // with at least a visible child\n public parentsWithVisibleChildren:{ [id:string]:boolean } = {};\n\n constructor(public readonly injector:Injector,\n public workPackageTable:WorkPackageTable,\n public rowBuilder:SingleHierarchyRowBuilder) {\n super(injector, workPackageTable, rowBuilder);\n }\n\n protected prepare() {\n super.prepare();\n\n this.hierarchies = this.wpTableHierarchies.current;\n\n _.each(this.workPackageTable.originalRowIndex, (row, ) => {\n row.object.ancestors.forEach((ancestor:WorkPackageResource) => {\n this.parentsWithVisibleChildren[ancestor.id!] = true;\n });\n });\n\n this.rowBuilder.parentsWithVisibleChildren = this.parentsWithVisibleChildren;\n }\n\n /**\n * Render the hierarchy table into the document fragment\n */\n protected doRender() {\n this.workPackageTable.originalRows.forEach((wpId:string) => {\n const row:WorkPackageTableRow = this.workPackageTable.originalRowIndex[wpId];\n const workPackage:WorkPackageResource = row.object;\n\n // If we need to defer this row, skip it for now\n if (this.deferInsertion(workPackage)) {\n return;\n }\n\n if (workPackage.ancestors.length) {\n // If we have ancestors, render it\n this.buildWithHierarchy(row);\n } else {\n // Render a work package root with no parents\n let [tr, hidden] = this.rowBuilder.buildEmpty(workPackage);\n row.element = tr;\n this.tableBody.appendChild(tr);\n this.markRendered(tr, workPackage, hidden);\n }\n\n // Render all potentially deferred rows\n this.renderAllDeferredChildren(workPackage);\n });\n }\n\n /**\n * If the given work package has a visible ancestor in the table, return true\n * and remember the work package until the ancestor is rendered.\n * @param workPackage\n * @returns {boolean}\n */\n public deferInsertion(workPackage:WorkPackageResource):boolean {\n const ancestors = workPackage.ancestors;\n\n // Will only defer if at least one ancestor exists\n if (ancestors.length === 0) {\n return false;\n }\n\n // Cases for wp\n // 1. No wp.ancestors in table -> Render them immediately (defer=false)\n // 2. Parent in table -> deffered[parent] = wp\n // 3. Parent not in table BUT a ancestor in table\n // -> deferred[a ancestor] = parent\n // -> deferred[parent] = wp\n // 4. Any ancestor already rendered -> Render normally (don't defer)\n let ancestorChain = ancestors.concat([workPackage]);\n for (let i = ancestorChain.length - 2; i >= 0; --i) {\n const parent = ancestorChain[i];\n\n const inTable = this.workPackageTable.originalRowIndex[parent.id!];\n const alreadyRendered = this.rendered[parent.id!];\n\n if (alreadyRendered) {\n // parent is already rendered.\n // Don't defer, but render all intermediate parents below it\n return false;\n }\n\n if (inTable) {\n // Get the current elements\n let elements = this.deferred[parent.id!] || [];\n // Append to them the child and all children below\n let newElements:WorkPackageResource[] = ancestorChain.slice(i + 1, ancestorChain.length);\n newElements = newElements.map(child => this.apiV3Service.work_packages.cache.state(child.id!).value!);\n // Append all new elements\n elements = elements.concat(newElements);\n // Remove duplicates (Regression #29652)\n this.deferred[parent.id!] = _.uniqBy(elements, el => el.id!);\n return true;\n }\n // Otherwise, continue the chain upwards\n }\n\n return false;\n }\n\n\n /**\n * Render any deferred children of the given work package. If recursive children were\n * deferred, each of them will be passed through renderCallback.\n * @param workPackage\n */\n private renderAllDeferredChildren(workPackage:WorkPackageResource) {\n const wpId = workPackage.id!;\n const deferredChildren = this.deferred[wpId] || [];\n\n // If the work package has deferred children to render,\n // run them through the callback\n deferredChildren.forEach((child:WorkPackageResource) => {\n this.insertUnderParent(this.getOrBuildRow(child), child.parent || workPackage);\n\n // Descend into any children the child WP might have and callback\n this.renderAllDeferredChildren(child);\n });\n }\n\n private getOrBuildRow(workPackage:WorkPackageResource) {\n let row:WorkPackageTableRow = this.workPackageTable.originalRowIndex[workPackage.id!];\n\n if (!row) {\n row = {object: workPackage} as WorkPackageTableRow;\n }\n\n return row;\n }\n\n private buildWithHierarchy(row:WorkPackageTableRow) {\n // Ancestor data [root, med, thisrow]\n const ancestors = row.object.ancestors;\n const ancestorGroups:string[] = [];\n\n // Iterate ancestors\n ancestors.forEach((el:WorkPackageResource, index:number) => {\n const ancestor = this.states.workPackages.get(el.id!).getValueOr(el);\n\n // If we see the parent the first time,\n // build it as an additional row and insert it into the ancestry\n if (!this.rendered[ancestor.id!]) {\n let [ancestorRow, hidden] = this.rowBuilder.buildAncestorRow(ancestor, ancestorGroups, index);\n // Insert the ancestor row, either right here if it's a root node\n // Or below the appropriate parent\n\n if (index === 0) {\n // Special case, first ancestor => root without parent\n this.tableBody.appendChild(ancestorRow);\n this.markRendered(ancestorRow, ancestor, hidden, true);\n } else {\n // This ancestor must be inserted in the last position of its root\n const parent = ancestors[index - 1];\n this.insertAtExistingHierarchy(ancestor, ancestorRow, parent, hidden, true);\n }\n\n // Remember we just added this extra ancestor row\n this.additionalParents[ancestor.id!] = ancestor;\n }\n\n // Push the correct ancestor groups for identifiying a hierarchy group\n ancestorGroups.push(hierarchyGroupClass(ancestor.id!));\n ancestors.slice(0, index).forEach((previousAncestor) => {\n ancestorGroups.push(hierarchyGroupClass(previousAncestor.id!));\n });\n });\n\n // Insert this row to parent\n const parent = _.last(ancestors);\n this.insertUnderParent(row, parent!);\n }\n\n /**\n * Insert the given node as a child of the parent\n * @param row\n * @param parent\n */\n private insertUnderParent(row:WorkPackageTableRow, parent:WorkPackageResource) {\n const [tr, hidden] = this.rowBuilder.buildEmpty(row.object);\n row.element = tr;\n this.insertAtExistingHierarchy(row.object, tr, parent, hidden, false);\n }\n\n /**\n * Mark the given work package as rendered\n * @param workPackage\n * @param hidden\n * @param isAncestor\n */\n private markRendered(row:HTMLTableRowElement, workPackage:WorkPackageResource, hidden:boolean = false, isAncestor:boolean = false) {\n this.rendered[workPackage.id!] = true;\n this.renderedOrder.push(this.buildRenderInfo(row, workPackage, hidden, isAncestor));\n }\n\n /**\n * Append a row to the given parent hierarchy group.\n */\n private insertAtExistingHierarchy(workPackage:WorkPackageResource,\n el:HTMLTableRowElement,\n parent:WorkPackageResource,\n hidden:boolean,\n isAncestor:boolean) {\n // Either append to the hierarchy group root (= the parentID row itself)\n const hierarchyRoot = `.__hierarchy-root-${parent.id}`;\n // Or, if it has descendants, append to the LATEST of that set\n const hierarchyGroup = `.__hierarchy-group-${parent.id}`;\n\n // Insert into table\n this.spliceRow(\n el,\n `${hierarchyRoot},${hierarchyGroup}`,\n this.buildRenderInfo(el, workPackage, hidden, isAncestor)\n );\n\n this.rendered[workPackage.id!] = true;\n }\n\n private buildRenderInfo(row:HTMLTableRowElement, workPackage:WorkPackageResource, hidden:boolean, isAncestor:boolean):RowRenderInfo {\n let info:RowRenderInfo = {\n element: row,\n classIdentifier: '',\n additionalClasses: [],\n workPackage: workPackage,\n renderType: 'primary',\n hidden: hidden\n };\n\n let [ancestorClasses, _] = this.rowBuilder.ancestorRowData(workPackage);\n\n if (isAncestor) {\n info.additionalClasses = [additionalHierarchyRowClassName].concat(ancestorClasses);\n info.classIdentifier = ancestorClassIdentifier(workPackage.id!);\n } else {\n info.additionalClasses = ancestorClasses;\n info.classIdentifier = this.rowBuilder.classIdentifier(workPackage);\n }\n\n return info as RowRenderInfo;\n }\n}\n","import {Injector} from '@angular/core';\nimport {States} from '../../../../states.service';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {RowsBuilder} from '../rows-builder';\nimport {HierarchyRenderPass} from './hierarchy-render-pass';\nimport {SingleHierarchyRowBuilder} from './single-hierarchy-row-builder';\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HierarchyRowsBuilder extends RowsBuilder {\n\n // Injections\n @InjectField() states:States;\n @InjectField() wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() wpTableHierarchies:WorkPackageViewHierarchiesService;\n\n // The group expansion state\n constructor(public readonly injector:Injector, public workPackageTable:WorkPackageTable) {\n super(injector, workPackageTable);\n }\n\n /**\n * The hierarchy builder is only applicable if the hierachy mode is active\n */\n public isApplicable(_table:WorkPackageTable) {\n return this.wpTableHierarchies.isEnabled;\n }\n\n /**\n * Rebuild the entire grouped tbody from the given table\n */\n public buildRows():HierarchyRenderPass {\n const builder = new SingleHierarchyRowBuilder(this.injector, this.workPackageTable);\n return new HierarchyRenderPass(this.injector, this.workPackageTable, builder).render();\n }\n}\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageTable} from '../../../wp-fast-table';\nimport {PrimaryRenderPass} from '../../primary-render-pass';\nimport {SingleRowBuilder} from '../../rows/single-row-builder';\nimport {RowsBuilder} from '../rows-builder';\nimport {PlainRenderPass} from './plain-render-pass';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class PlainRowsBuilder extends RowsBuilder {\n\n // Injections\n @InjectField() public I18n:I18nService;\n\n // The group expansion state\n constructor(public readonly injector:Injector, workPackageTable:WorkPackageTable) {\n super(injector, workPackageTable);\n }\n\n /**\n * Rebuild the entire grouped tbody from the given table\n */\n public buildRows():PrimaryRenderPass {\n const builder = new SingleRowBuilder(this.injector, this.workPackageTable);\n return new PlainRenderPass(this.injector, this.workPackageTable, builder).render();\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injector} from '@angular/core';\nimport {Subscription} from 'rxjs';\nimport {States} from 'core-components/states.service';\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\n\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {FocusHelperService} from \"core-app/modules/common/focus/focus-helper\";\nimport {EditingPortalService} from \"core-app/modules/fields/edit/editing-portal/editing-portal-service\";\nimport {CellBuilder, editCellContainer, tdClassName} from \"core-components/wp-fast-table/builders/cell-builder\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {EditForm} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {editModeClassName} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const activeFieldContainerClassName = 'inline-edit--active-field';\nexport const activeFieldClassName = 'inline-edit--field';\n\nexport class TableEditForm extends EditForm {\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n @InjectField() public apiV3Service:APIV3Service;\n @InjectField() public states:States;\n @InjectField() public FocusHelper:FocusHelperService;\n @InjectField() public editingPortalService:EditingPortalService;\n\n // Use cell builder to reset edit fields\n private cellBuilder = new CellBuilder(this.injector);\n\n // Subscription\n private resourceSubscription:Subscription = this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .subscribe((wp) => this.resource = wp);\n\n constructor(public injector:Injector,\n public table:WorkPackageTable,\n public workPackageId:string,\n public classIdentifier:string) {\n super(injector);\n }\n\n destroy() {\n this.resourceSubscription.unsubscribe();\n }\n\n public findContainer(fieldName:string):JQuery {\n return this.rowContainer.find(`.${tdClassName}.${fieldName} .${editCellContainer}`).first();\n }\n\n public findCell(fieldName:string) {\n return this.rowContainer.find(`.${tdClassName}.${fieldName}`).first();\n }\n\n public activateField(form:EditForm, schema:IFieldSchema, fieldName:string, errors:string[]):Promise {\n return this.waitForContainer(fieldName)\n .then((cell) => {\n\n // Forcibly set the width since the edit field may otherwise\n // be given more width. Thereby preserve a minimum width of 150.\n // To avoid flickering content, the padding is removed, too.\n const td = this.findCell(fieldName);\n td.addClass(editModeClassName);\n let width = parseInt(td.css('width'));\n width = width > 150 ? width - 10 : 150;\n td.css('max-width', width + 'px');\n td.css('width', width + 'px');\n\n return this.editingPortalService.create(\n cell,\n this.injector,\n form,\n schema,\n fieldName,\n errors\n );\n });\n }\n\n public reset(fieldName:string, focus?:boolean) {\n const cell = this.findContainer(fieldName);\n const td = this.findCell(fieldName);\n\n if (cell.length) {\n this.findCell(fieldName).css('width', '');\n this.findCell(fieldName).css('max-width', '');\n this.cellBuilder.refresh(cell[0], this.resource, fieldName);\n td.removeClass(editModeClassName);\n\n if (focus) {\n this.FocusHelper.focusElement(cell);\n }\n }\n }\n\n public requireVisible(fieldName:string):Promise {\n this.wpTableColumns.addColumn(fieldName);\n return this.waitForContainer(fieldName);\n }\n\n protected focusOnFirstError():void {\n // Focus the first field that is erroneous\n jQuery(this.table.tableAndTimelineContainer)\n .find(`.${activeFieldContainerClassName}.-error .${activeFieldClassName}`)\n .first()\n .trigger('focus');\n }\n\n /**\n * Load the resource form to get the current field schema with all\n * values loaded.\n * @param fieldName\n */\n protected loadFieldSchema(fieldName:string, noWarnings:boolean = false):Promise {\n // We need to handle start/due date cases like they were combined dates\n if (['startDate', 'dueDate', 'date'].includes(fieldName)) {\n fieldName = 'combinedDate';\n }\n\n return super.loadFieldSchema(fieldName, noWarnings);\n }\n\n // Ensure the given field is visible.\n // We may want to look into MutationObserver if we need this in several places.\n private waitForContainer(fieldName:string):Promise {\n return new Promise((resolve, reject) => {\n const interval = setInterval(() => {\n const container = this.findContainer(fieldName);\n\n if (container.length > 0) {\n clearInterval(interval);\n resolve(container[0]);\n }\n }, 100);\n });\n }\n\n private get rowContainer() {\n return jQuery(this.table.tableAndTimelineContainer).find(`.${this.classIdentifier}-table`);\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageTable} from 'core-components/wp-fast-table/wp-fast-table';\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {EditForm} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {TableEditForm} from \"core-components/wp-edit-form/table-edit-form\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class WorkPackageTableEditingContext {\n\n @InjectField() public halEditing:HalResourceEditingService;\n\n constructor(readonly table:WorkPackageTable,\n readonly injector:Injector) {\n }\n\n public forms:{ [wpId:string]:TableEditForm } = {};\n\n public reset() {\n _.each(this.forms, (form) => form.destroy());\n this.forms = {};\n }\n\n public change(workPackage:WorkPackageResource):WorkPackageChangeset|undefined {\n return this.halEditing.typedState(workPackage).value;\n }\n\n // TODO\n public stopEditing(workPackage:WorkPackageResource) {\n this.halEditing.stopEditing(workPackage);\n\n const existing = this.forms[workPackage.id!];\n if (existing) {\n existing.destroy();\n delete this.forms[workPackage.id!];\n }\n }\n\n public startEditing(workPackage:WorkPackageResource, classIdentifier:string):EditForm {\n const wpId = workPackage.id!;\n const existing = this.forms[wpId];\n if (existing) {\n return existing;\n }\n\n // Get any existing edit state for this work package\n return this.forms[wpId] = new TableEditForm(this.injector, this.table, wpId, classIdentifier);\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {IsolatedQuerySpace} from 'core-app/modules/work_packages/query-space/isolated-query-space';\nimport {debugLog} from '../../helpers/debug_output';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../states.service';\nimport {WorkPackageTimelineTableController} from '../wp-table/timeline/container/wp-timeline-container.directive';\nimport {GroupedRowsBuilder} from './builders/modes/grouped/grouped-rows-builder';\nimport {HierarchyRowsBuilder} from './builders/modes/hierarchy/hierarchy-rows-builder';\nimport {PlainRowsBuilder} from './builders/modes/plain/plain-rows-builder';\nimport {RowsBuilder} from './builders/modes/rows-builder';\nimport {PrimaryRenderPass} from './builders/primary-render-pass';\nimport {WorkPackageTableEditingContext} from './wp-table-editing';\nimport {WorkPackageTableRow} from './wp-table.interfaces';\nimport {WorkPackageTableConfiguration} from 'core-app/components/wp-table/wp-table-configuration';\nimport {RenderedWorkPackage} from 'core-app/modules/work_packages/render-info/rendered-work-package.type';\nimport {InjectField} from 'core-app/helpers/angular/inject-field.decorator';\nimport {APIV3Service} from 'core-app/modules/apiv3/api-v3.service';\nimport {WorkPackageViewCollapsedGroupsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service';\n\nexport class WorkPackageTable {\n\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() apiV3Service:APIV3Service;\n @InjectField() states:States;\n @InjectField() I18n:I18nService;\n @InjectField() workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService;\n\n public originalRows:string[] = [];\n public originalRowIndex:{ [id:string]:WorkPackageTableRow } = {};\n private hierarchyRowsBuilder = new HierarchyRowsBuilder(this.injector, this);\n private groupedRowsBuilder = new GroupedRowsBuilder(this.injector, this);\n private plainRowsBuilder = new PlainRowsBuilder(this.injector, this);\n\n // WP rows builder\n // Ordered by priority\n private builders = [this.hierarchyRowsBuilder, this.groupedRowsBuilder, this.plainRowsBuilder];\n\n // Last render pass used for refreshing single rows\n public lastRenderPass:PrimaryRenderPass|null = null;\n\n // Work package editing context handler in the table, which handles open forms\n // and their contexts\n public editing:WorkPackageTableEditingContext = new WorkPackageTableEditingContext(this, this.injector);\n\n constructor(public readonly injector:Injector,\n public tableAndTimelineContainer:HTMLElement,\n public scrollContainer:HTMLElement,\n public tbody:HTMLElement,\n public timelineBody:HTMLElement,\n public timelineController:WorkPackageTimelineTableController,\n public configuration:WorkPackageTableConfiguration) {\n }\n\n public get renderedRows() {\n return this.querySpace.tableRendered.getValueOr([]);\n }\n\n public findRenderedRow(classIdentifier:string):[number, RenderedWorkPackage] {\n const index = _.findIndex(this.renderedRows, (row) => row.classIdentifier === classIdentifier);\n\n return [index, this.renderedRows[index]];\n }\n\n public get rowBuilder():RowsBuilder {\n return _.find(this.builders, (builder:RowsBuilder) => builder.isApplicable(this))!;\n }\n\n /**\n * Build the row index and positions from the given set of ordered work packages.\n * @param rows\n */\n private buildIndex(rows:WorkPackageResource[]) {\n this.originalRowIndex = {};\n this.originalRows = rows.map((wp:WorkPackageResource, i:number) => {\n let wpId = wp.id!;\n\n // Ensure we get the latest version\n wp = this.apiV3Service.work_packages.cache.current(wpId, wp)!;\n\n this.originalRowIndex[wpId] = { object: wp, workPackageId: wpId, position: i };\n return wpId;\n });\n }\n\n /**\n *\n * @param rows\n */\n public initialSetup(rows:WorkPackageResource[]) {\n // Build the row representation\n this.buildIndex(rows);\n\n // Draw work packages\n this.redrawTableAndTimeline();\n }\n\n /**\n * Removes the contents of this table's tbody and redraws\n * all elements.\n */\n public redrawTableAndTimeline() {\n const renderPass = this.performRenderPass(false);\n\n // Insert timeline body\n requestAnimationFrame(() => {\n this.tbody.innerHTML = '';\n this.timelineBody.innerHTML = '';\n this.tbody.appendChild(renderPass.tableBody);\n this.timelineBody.appendChild(renderPass.timeline.timelineBody);\n\n // Mark rendering event in a timeout to let DOM process\n setTimeout(() =>\n this.querySpace.tableRendered.putValue(renderPass.result)\n );\n });\n }\n\n /**\n * Redraw all elements in the table section only\n */\n public redrawTable() {\n const renderPass = this.performRenderPass();\n this.querySpace.tableRendered.putValue(renderPass.result);\n }\n\n /**\n * Redraw single rows for a given work package being updated.\n */\n public refreshRows(workPackage:WorkPackageResource) {\n const pass = this.lastRenderPass;\n if (!pass) {\n debugLog('Trying to refresh a singular row without a previous render pass.');\n return;\n }\n\n _.each(pass.renderedOrder, (row) => {\n if (row.workPackage && row.workPackage.id === workPackage.id!) {\n debugLog(`Refreshing rendered row ${row.classIdentifier}`);\n row.workPackage = workPackage;\n pass.refresh(row, workPackage, this.tbody);\n }\n });\n }\n\n /**\n * Determine whether we need an empty placeholder row.\n * When D&D is enabled, the table requires a drag target that is non-empty,\n * and the tbody cannot be resized appropriately.\n */\n public get renderPlaceholderRow() {\n return this.configuration.dragAndDropEnabled;\n }\n\n\n /**\n * Perform the render pass\n * @param insert whether to insert the result (set to false for timeline)\n */\n private performRenderPass(insert:boolean = true) {\n this.editing.reset();\n const renderPass = this.lastRenderPass = this.rowBuilder.buildRows();\n\n // Insert table body\n if (insert) {\n requestAnimationFrame(() => {\n this.tbody.innerHTML = '';\n this.tbody.appendChild(renderPass.tableBody);\n });\n }\n\n return renderPass;\n }\n\n setGroupsCollapseState(newState:{[key:string]:boolean}) {\n this.querySpace.collapsedGroups.putValue(newState);\n\n const t0 = performance.now();\n this.groupedRowsBuilder.refreshExpansionState();\n const t1 = performance.now();\n\n debugLog('Group redraw took ' + (t1 - t0) + ' milliseconds.');\n }\n}\n","import {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Injectable} from \"@angular/core\";\n\nexport interface ICKEditorInstance {\n getData(obtions:{ trim:boolean }):string;\n\n setData(content:string):void;\n\n on(event:string, callback:Function):void;\n\n model:any;\n editing:any;\n config:any;\n ui:any;\n element:HTMLElement;\n}\n\nexport interface ICKEditorStatic {\n create(el:HTMLElement, config?:any):Promise;\n\n createCustomized(el:string|HTMLElement, config?:any):Promise;\n}\n\nexport interface ICKEditorContext {\n resource?:HalResource;\n // Specific removing of plugins\n removePlugins?:string[];\n // Set of enabled macro plugins or false to disable all\n macros?:'none'|'wp'|'full'|boolean|string[];\n // Additional options like the text orientation of the editors content\n options?:{\n rtl?:boolean;\n };\n // context link to append on preview requests\n previewContext?:string;\n}\n\ndeclare global {\n interface Window {\n OPConstrainedEditor:ICKEditorStatic;\n OPClassicEditor:ICKEditorStatic;\n }\n}\n\n@Injectable()\nexport class CKEditorSetupService {\n constructor(private PathHelper:PathHelperService) {\n }\n\n /**\n * Create a CKEditor instance of the given type on the wrapper element.\n * Pass a ICKEditorContext object that will be used to decide active plugins.\n *\n *\n * @param {\"full\" | \"constrained\"} type\n * @param {HTMLElement} wrapper\n * @param {ICKEditorContext} context\n * @returns {Promise}\n */\n public async create(type:'full'|'constrained', wrapper:HTMLElement, context:ICKEditorContext, initialData:string|null = null) {\n // Load the bundle\n await this.load();\n\n const editorClass = type === 'constrained' ? window.OPConstrainedEditor : window.OPClassicEditor;\n wrapper.classList.add(`ckeditor-type-${type}`);\n\n const toolbarWrapper = wrapper.querySelector('.document-editor__toolbar') as HTMLElement;\n const contentWrapper = wrapper.querySelector('.document-editor__editable') as HTMLElement;\n\n var contentLanguage = context.options && context.options.rtl ? 'ar' : 'en';\n\n\n const editor:ICKEditorInstance = await editorClass\n .createCustomized(contentWrapper, {\n openProject: this.createConfig(context),\n initialData: initialData,\n language: {\n content: contentLanguage\n }\n });\n\n toolbarWrapper.appendChild(editor.ui.view.toolbar.element);\n\n // Allow custom events on wrapper to set/get data for debugging\n jQuery(wrapper)\n .on('op:ckeditor:setData', (event:any, data:string) => editor.setData(data))\n .on('op:ckeditor:clear', (event:any) => editor.setData(' '))\n .on('op:ckeditor:getData', (event:any, cb:any) => cb(editor.getData({ trim: false })));\n\n return editor;\n }\n\n /**\n * Load the ckeditor asset\n */\n private load():Promise {\n // untyped module cannot be dynamically imported\n // @ts-ignore\n return import(/* webpackChunkName: \"ckeditor\" */ 'core-vendor/ckeditor/ckeditor.js');\n }\n\n private createConfig(context:ICKEditorContext):any {\n if (context.macros === 'none') {\n context.macros = false;\n } else if (context.macros === 'wp') {\n context.macros = [\n 'OPMacroToc',\n 'OPMacroEmbeddedTable',\n 'OPMacroWpButton'\n ];\n } else {\n context.macros = context.macros;\n }\n\n return {\n context: context,\n helpURL: this.PathHelper.textFormattingHelp(),\n pluginContext: window.OpenProject.pluginContext.value\n };\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {WorkPackageStaticQueriesService} from 'core-components/wp-query-select/wp-static-queries.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {LinkHandling} from \"core-app/modules/common/link-handling/link-handling\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {MainMenuToggleService} from \"core-components/main-menu/main-menu-toggle.service\";\nimport {MainMenuNavigationService} from \"core-components/main-menu/main-menu-navigation.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport type QueryCategory = 'starred'|'public'|'private'|'default';\n\nexport interface IAutocompleteItem {\n // Some optional identifier\n identifier?:string;\n // Internal id for selecting items\n auto_id?:number;\n // The autocomplete item may be a static link (e.g., summary page)\n static_link?:string;\n // Label for the current locale\n label:string;\n // May be tied to a persisted query\n query?:QueryResource;\n // Or a loose map of query_props\n query_props?:any;\n // And is tied to a category\n category?:QueryCategory;\n}\n\ninterface IQueryAutocompleteJQuery extends JQuery {\n querycomplete(...args:any[]):void;\n}\n\nexport const wpQuerySelectSelector = 'wp-query-select';\n\n@Component({\n selector: wpQuerySelectSelector,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './wp-query-select.template.html',\n})\nexport class WorkPackageQuerySelectDropdownComponent extends UntilDestroyedMixin implements OnInit {\n @ViewChild('wpQueryMenuSearchInput', { static: true }) _wpQueryMenuSearchInput:ElementRef;\n @ViewChild('queryResultsContainer', { static: true }) _queryResultsContainerElement:ElementRef;\n\n public loading = false;\n public noResults = false;\n\n public text = {\n search: this.I18n.t('js.toolbar.search_query_label'),\n label: this.I18n.t('js.toolbar.search_query_label'),\n scope_default: this.I18n.t('js.label_default_queries'),\n scope_starred: this.I18n.t('js.label_starred_queries'),\n scope_global: this.I18n.t('js.label_global_queries'),\n scope_private: this.I18n.t('js.label_custom_queries'),\n no_results: this.I18n.t('js.work_packages.query.text_no_results'),\n };\n private unregisterTransitionListener:Function;\n\n private projectIdentifier:string|null;\n\n private hiddenCategories:any = [];\n\n private reportsBodySelector = '.controller-work_packages\\\\/reports';\n\n private queryResultsContainer:JQuery;\n private buttonArrowLeft:JQuery;\n\n private searchInput:IQueryAutocompleteJQuery;\n\n private initialized = false;\n\n\n constructor(readonly ref:ChangeDetectorRef,\n readonly element:ElementRef,\n readonly apiV3Service:APIV3Service,\n readonly $state:StateService,\n readonly $transitions:TransitionService,\n readonly I18n:I18nService,\n readonly states:States,\n readonly CurrentProject:CurrentProjectService,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly pathHelper:PathHelperService,\n readonly wpStaticQueries:WorkPackageStaticQueriesService,\n readonly mainMenuService:MainMenuNavigationService,\n readonly toggleService:MainMenuToggleService,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n public ngOnInit() {\n this.queryResultsContainer = jQuery(this._queryResultsContainerElement.nativeElement);\n this.projectIdentifier = this.element.nativeElement.getAttribute('data-project-identifier');\n\n // When activating the work packages submenu,\n // either initially or through click on the toggle, load the results\n this.mainMenuService\n .onActivate('work_packages', 'work_packages_query_select')\n .subscribe(() => this.initializeAutocomplete());\n\n // Register click handler on results\n this.addClickHandler();\n this.cdRef.detach();\n }\n\n ngOnDestroy() {\n super.ngOnDestroy();\n this.unregisterTransitionListener();\n }\n\n private initializeAutocomplete() {\n if (this.initialized) {\n return;\n }\n\n this.searchInput = jQuery(this._wpQueryMenuSearchInput.nativeElement) as any;\n this.buttonArrowLeft = jQuery('.main-menu--arrow-left-to-project', jQuery('#main-menu-work-packages-wrapper').parent()) as any;\n this.initialized = true;\n this.buttonArrowLeft.focus();\n this.setupAutoCompletion(this.searchInput);\n this.updateMenuOnChanges();\n this.loadQueries();\n }\n\n private transformQueries(collection:CollectionResource) {\n let loadedQueries:IAutocompleteItem[] = collection.elements\n .map(query => {\n return { label: query.name, query: query, query_props: null };\n });\n\n // Add to the loaded set of queries the fixed set of queries for the current project context\n const combinedQueries = loadedQueries.concat(this.wpStaticQueries.all);\n return this.sortQueries(combinedQueries);\n }\n\n // Filter the collection by categories, add the correct categories to every item of the filtered array\n // Sort every category array alphabetically, except the default queries\n private sortQueries(items:IAutocompleteItem[]):IAutocompleteItem[] {\n // Concat all categories in the right order\n let categorized:{ [category:string]:IAutocompleteItem[] } = {\n // Starred / favored\n starred: [],\n // default\n default: [],\n // public\n public: [],\n // private\n private: []\n };\n\n let auto_id = 0;\n items.forEach((item):any => {\n item.auto_id = auto_id++;\n\n if (!item.query) {\n item.category = 'default';\n return categorized.default.push(item);\n }\n\n if (item.query.starred) {\n item.category = 'starred';\n return categorized.starred.push(item);\n }\n\n if (!item.query.starred && item.query.public) {\n item.category = 'public';\n return categorized.public.push(item);\n }\n\n if (!(item.query.starred || item.query.public)) {\n item.category = 'private';\n return categorized.private.push(item);\n }\n });\n\n return _.flatten(\n [categorized.starred, categorized.default, categorized.public, categorized.private]\n .map(items => this.sortByLabel(items))\n );\n }\n\n // Sort a given array of items by the value of their label attribute\n private sortByLabel(items:IAutocompleteItem[]):IAutocompleteItem[] {\n return items.sort((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase()));\n }\n\n private loadQueries() {\n return this.loadingPromise = this\n .apiV3Service\n .queries\n .filterNonHidden(this.CurrentProject.identifier)\n .toPromise()\n .then(collection => {\n\n // Update the complete collection\n this.searchInput.querycomplete(\"option\", { source: this.transformQueries(collection) });\n\n // To visibly show the changes, we need to search again\n this.searchInput.querycomplete(\"search\", this.searchInput.val());\n\n // To search an empty string would expand all categories again every time\n // Remember all previously hidden categories and set them again after updating the menu\n _.each(this.hiddenCategories, category => {\n let thisCategory:string = jQuery(category).attr(\"category\")!;\n this.expandCollapseCategory(thisCategory);\n });\n\n // Update view\n this.ref.detectChanges();\n });\n }\n\n private set loadingPromise(promise:Promise) {\n this.loading = true;\n promise\n .then(() => {\n this.loading = false;\n this.cdRef.detectChanges();\n })\n .catch(() => {\n this.loading = false;\n this.cdRef.detectChanges();\n });\n }\n\n private setupAutoCompletion(input:IQueryAutocompleteJQuery) {\n this.defineJQueryQueryComplete();\n\n input.querycomplete({\n delay: 100,\n // The values are added later by the listener also covering\n // the changes to queries (updateMenuOnChanges()).\n source: [],\n select: (ul:any, selected:{ item:IAutocompleteItem }) => {\n return false; // Don't show title of selected query in the input field\n },\n response: (event:any, ui:any) => {\n // Show the noResults span if we don't have any matches\n this.noResults = (ui.content.length === 0);\n },\n close: (event:any, ui:any) => {\n const autocompleteUi = this.queryResultsContainer.find('ul.ui-autocomplete');\n if (!autocompleteUi.is(\":visible\") && !this.noResults) {\n autocompleteUi.show();\n }\n },\n focus: (_event:JQuery.TriggeredEvent, ui:{ item:IAutocompleteItem }) => {\n let sourceEvent:any|null = _event;\n\n while (sourceEvent && sourceEvent.originalEvent) {\n sourceEvent = sourceEvent.originalEvent as any;\n }\n\n // Focus the given item, but only when we're using the keyboard.\n // With the mouse, hover shall suffice to avoid weird focus/hover combinations\n // e.g., https://community.openproject.com/wp/28197\n if (sourceEvent && sourceEvent.type === 'keydown') {\n this.queryResultsContainer\n .find(`#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","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","import {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageRelationsService} from '../wp-relations.service';\nimport {Component, Input} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Component({\n selector: 'wp-relations-create',\n templateUrl: './wp-relation-create.template.html'\n})\nexport class WorkPackageRelationsCreateComponent {\n @Input() readonly workPackage:WorkPackageResource;\n\n public showRelationsCreateForm:boolean = false;\n public selectedRelationType:string = RelationResource.DEFAULT();\n public selectedWpId:string;\n public relationTypes = RelationResource.LOCALIZED_RELATION_TYPES(false);\n\n public isDisabled = false;\n\n public text = {\n abort: this.I18n.t('js.relation_buttons.abort'),\n relationType: this.I18n.t('js.relation_buttons.relation_type'),\n addNewRelation: this.I18n.t('js.relation_buttons.add_new_relation')\n };\n\n constructor(readonly I18n:I18nService,\n protected wpRelations:WorkPackageRelationsService,\n protected notificationService:WorkPackageNotificationService,\n protected halEvents:HalEventsService) {\n }\n\n\n public createRelation() {\n\n if (!this.selectedRelationType || !this.selectedWpId) {\n return;\n }\n\n this.isDisabled = true;\n this.createCommonRelation()\n .catch(() => this.isDisabled = false)\n .then(() => this.isDisabled = false);\n }\n\n public onSelected(workPackage?:WorkPackageResource) {\n if (workPackage) {\n this.selectedWpId = workPackage.id!;\n this.createCommonRelation();\n }\n }\n\n protected createCommonRelation() {\n return this.wpRelations.addCommonRelation(this.workPackage.id!,\n this.selectedRelationType,\n this.selectedWpId)\n .then(relation => {\n this.halEvents.push(this.workPackage, {\n eventType: 'association',\n relatedWorkPackage: relation.id!,\n relationType: this.selectedRelationType\n });\n this.notificationService.showSave(this.workPackage);\n this.toggleRelationsCreateForm();\n })\n .catch(err => {\n this.notificationService.handleRawError(err, this.workPackage);\n this.toggleRelationsCreateForm();\n });\n }\n\n public toggleRelationsCreateForm() {\n this.showRelationsCreateForm = !this.showRelationsCreateForm;\n // Reset value\n this.selectedWpId = '';\n }\n}\n","
    \n
    \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n \n \n
    \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","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 {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {Subscription} from 'rxjs';\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {EditForm} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Component({\n selector: '[wpInlineCreate]',\n templateUrl: './wp-inline-create.component.html'\n})\nexport class WorkPackageInlineCreateComponent extends UntilDestroyedMixin implements OnInit, AfterViewInit {\n\n @Input('wp-inline-create--table') table:WorkPackageTable;\n @Input('wp-inline-create--project-identifier') projectIdentifier:string;\n\n // inner state\n public canAdd:boolean = false;\n public canReference:boolean = false;\n\n // Inline create / reference row is active\n public mode:'inactive'|'create'|'reference' = 'inactive';\n\n public focus:boolean = false;\n\n public text = this.wpInlineCreate.buttonTexts;\n\n private currentWorkPackage:WorkPackageResource|null;\n\n private workPackageEditForm:EditForm|undefined;\n\n private editingSubscription:Subscription|undefined;\n\n private $element:JQuery;\n\n get isActive():boolean {\n return this.mode !== 'inactive';\n }\n\n constructor(public readonly injector:Injector,\n protected readonly elementRef:ElementRef,\n protected readonly schemaCache:SchemaCacheService,\n protected readonly I18n:I18nService,\n protected readonly querySpace:IsolatedQuerySpace,\n protected readonly cdRef:ChangeDetectorRef,\n protected readonly wpCreate:WorkPackageCreateService,\n protected readonly wpInlineCreate:WorkPackageInlineCreateService,\n protected readonly wpTableColumns:WorkPackageViewColumnsService,\n protected readonly wpTableFocus:WorkPackageViewFocusService,\n protected readonly authorisationService:AuthorisationService) {\n super();\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n }\n\n ngAfterViewInit() {\n this.authorisationService\n .observeUntil(componentDestroyed(this))\n .subscribe(() => {\n this.canReference = this.hasReferenceClass && this.wpInlineCreate.canReference;\n this.canAdd = this.wpInlineCreate.canAdd;\n this.cdRef.detectChanges();\n\n if (this.canAdd || this.canReference) {\n // Add this row's height as a padding to the timeline\n // so the table and the timeline keep aligned\n const container = jQuery(this.table.timelineBody);\n container.addClass('-inline-create-mirror');\n }\n });\n\n // Register callback on newly created work packages\n this.registerCreationCallback();\n\n // Watch on this scope when the columns change and refresh this row\n this.refreshOnColumnChanges();\n\n // Cancel edition of current new row\n this.registerCancelHandler();\n }\n\n /**\n * Reset the inline creation row on the cancel button,\n * which is dynamically inserted into the action row by the inline create renderer.\n */\n private registerCancelHandler() {\n this.$element.on('click keydown', `.${inlineCreateCancelClassName}`, (evt:JQuery.TriggeredEvent) => {\n onClickOrEnter(evt, () => {\n this.resetRow();\n });\n\n evt.stopImmediatePropagation();\n return false;\n });\n }\n\n /**\n * Since the table is refreshed imperatively whenever columns are changed,\n * we need to manually ensure the inline create row gets refreshed as well.\n */\n private refreshOnColumnChanges() {\n this.wpTableColumns\n .updates$()\n .pipe(\n filter(() => this.isActive), // Take only when row is inserted\n this.untilDestroyed()\n )\n .subscribe(() => this.refreshRow());\n }\n\n /**\n * Listen to newly created work packages to detect whether the WP is the one we created,\n * and properly reset inline create in this case\n */\n private registerCreationCallback() {\n this.wpCreate\n .onNewWorkPackage()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n if (this.currentWorkPackage && this.currentWorkPackage.__initialized_at === wp.__initialized_at) {\n // Remove row and focus\n this.resetRow();\n\n // Split view on the last inserted id if any\n if (!this.table.configuration.isEmbedded) {\n this.wpTableFocus.updateFocus(wp.id!);\n }\n\n // Notify inline create service\n this.wpInlineCreate.newInlineWorkPackageCreated.next(wp.id!);\n } else {\n // Remove current row\n this.wpCreate.cancelCreation();\n this.removeWorkPackageRow();\n this.showRow();\n }\n\n this.cdRef.detectChanges();\n });\n }\n\n public handleAddRowClick() {\n this.addWorkPackageRow();\n return false;\n }\n\n public handleReferenceClick() {\n this.mode = 'reference';\n return false;\n }\n\n public get referenceClass() {\n return this.wpInlineCreate.referenceComponentClass;\n }\n\n public get hasReferenceClass() {\n return !!this.referenceClass;\n }\n\n public addWorkPackageRow() {\n this.wpCreate\n .createOrContinueWorkPackage(this.projectIdentifier)\n .then((change:WorkPackageChangeset) => {\n\n const wp = this.currentWorkPackage = change.projectedResource;\n\n this.editingSubscription = this\n .wpCreate\n .changesetUpdates$()\n .pipe(\n filter(() => !!this.currentWorkPackage),\n ).subscribe((form) => {\n if (!this.isActive) {\n this.insertRow(wp);\n } else {\n this.schemaCache.update(this.currentWorkPackage!, form!.schema);\n this.refreshRow();\n }\n });\n });\n }\n\n private insertRow(wp:WorkPackageResource) {\n // Actually render the row\n const form = this.workPackageEditForm = this.renderInlineCreateRow(wp);\n\n setTimeout(() => {\n // Activate any required fields\n form.activateMissingFields();\n\n // Hide the button row\n this.hideRow();\n });\n }\n\n private refreshRow() {\n const builder = new InlineCreateRowBuilder(this.injector, this.table);\n const rowElement = this.$element.find(`.${inlineCreateRowClassName}`);\n\n if (rowElement.length && this.currentWorkPackage) {\n builder.refreshRow(this.currentWorkPackage, rowElement);\n }\n }\n\n /**\n * Actually render the row manually\n * in the same fashion as all rows in the table are rendered.\n *\n * @param wp Work package to be rendered\n * @returns The work package form of the row\n */\n private renderInlineCreateRow(wp:WorkPackageResource):EditForm {\n const builder = new InlineCreateRowBuilder(this.injector, this.table);\n const form = this.table.editing.startEditing(wp, builder.classIdentifier(wp));\n\n const [row,] = builder.buildNew(wp, form);\n this.$element.append(row);\n\n return form;\n }\n\n /**\n * Reset the new work package row and refocus on the button\n */\n @HostListener('keydown.escape')\n public resetRow() {\n this.focus = true;\n this.removeWorkPackageRow();\n // Manually cancelled, show the row again\n setTimeout(() => {\n this.showRow();\n this.cdRef.detectChanges();\n }, 50);\n }\n\n public removeWorkPackageRow() {\n this.wpCreate.cancelCreation();\n this.currentWorkPackage = null;\n this.$element.find('.wp-row-new').remove();\n if (this.editingSubscription) {\n this.editingSubscription.unsubscribe();\n }\n }\n\n public showRow() {\n this.mode = 'inactive';\n this.cdRef.detectChanges();\n }\n\n public hideRow() {\n this.mode = 'create';\n this.cdRef.detectChanges();\n }\n\n public get colspan():number {\n return this.wpTableColumns.columnCount + 1;\n }\n\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 let activeFilterCount = this.currentFilterLength();\n\n if (activeFilterCount === 0) {\n this.focusElementIndex = ADD_FILTER_SELECT_INDEX;\n } else {\n const filterIndex = (index < activeFilterCount) ? index : activeFilterCount - 1;\n const filter = this.currentFilterAt(filterIndex);\n this.focusElementIndex = this.filters.indexOf(filter);\n }\n }\n\n public currentFilterLength() {\n return this.filters.length;\n }\n\n public currentFilterAt(index:number) {\n return this.filters[index];\n }\n\n public isFilterAvailable(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","import { Injectable } from '@angular/core';\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Injectable({\n providedIn: 'root'\n})\nexport class GlobalEditFormChangesTrackerService {\n private activeForms = new Map();\n\n get thereAreFormsWithUnsavedChanges () {\n return Array.from(this.activeForms.keys()).some(form => {\n return !form.change.isEmpty();\n });\n }\n\n constructor(\n private i18nService:I18nService,\n ) {\n // Global beforeunload hook to show a data loss warn\n // when the user clicks on a link out of the Angular app\n window.addEventListener('beforeunload', (event) => {\n if (this.thereAreFormsWithUnsavedChanges) {\n event.preventDefault();\n event.returnValue = this.i18nService.t('js.work_packages.confirm_edit_cancel');\n }\n });\n }\n\n public addToActiveForms(form:EditFormComponent) {\n this.activeForms.set(form, true);\n }\n\n public removeFromActiveForms(form:EditFormComponent) {\n this.activeForms.delete(form);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Component, ElementRef, EventEmitter, Injector, Input, OnDestroy, OnInit, Optional, Output} from '@angular/core';\nimport {StateService, Transition, TransitionService} from '@uirouter/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {EditableAttributeFieldComponent} from 'core-app/modules/fields/edit/field/editable-attribute-field.component';\nimport {input} from 'reactivestates';\nimport {filter, map, take} from 'rxjs/operators';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n activeFieldClassName,\n activeFieldContainerClassName,\n EditForm\n} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {EditingPortalService} from \"core-app/modules/fields/edit/editing-portal/editing-portal-service\";\nimport {EditFormRoutingService} from \"core-app/modules/fields/edit/edit-form/edit-form-routing.service\";\nimport {ResourceChangesetCommit} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {GlobalEditFormChangesTrackerService} from \"core-app/modules/fields/edit/services/global-edit-form-changes-tracker/global-edit-form-changes-tracker.service\";\n\n@Component({\n selector: 'edit-form,[edit-form]',\n template: ''\n})\nexport class EditFormComponent extends EditForm implements OnInit, OnDestroy {\n @Input('resource') resource:HalResource;\n @Input('inEditMode') initializeEditMode:boolean = false;\n @Input('skippedFields') skippedFields:string[] = [];\n\n @Output('onSaved') onSavedEmitter = new EventEmitter<{ savedResource:HalResource, isInitial:boolean }>();\n\n public fields:{ [attribute:string]:EditableAttributeFieldComponent } = {};\n private registeredFields = input();\n private unregisterListener:Function;\n\n constructor(public readonly injector:Injector,\n protected readonly elementRef:ElementRef,\n protected readonly $transitions:TransitionService,\n protected readonly ConfigurationService:ConfigurationService,\n protected readonly editingPortalService:EditingPortalService,\n protected readonly $state:StateService,\n protected readonly I18n:I18nService,\n @Optional() protected readonly editFormRouting:EditFormRoutingService,\n private globalEditFormChangesTrackerService:GlobalEditFormChangesTrackerService) {\n super(injector);\n\n const confirmText = I18n.t('js.work_packages.confirm_edit_cancel');\n const requiresConfirmation = ConfigurationService.warnOnLeavingUnsaved();\n\n this.unregisterListener = $transitions.onBefore({}, (transition:Transition) => {\n if (!this.editing) {\n return undefined;\n }\n\n // Show confirmation message when transitioning to a new state\n // that's not within the edit mode.\n if (!this.editFormRouting || this.editFormRouting.blockedTransition(transition)) {\n if (requiresConfirmation && !window.confirm(confirmText)) {\n return false;\n }\n\n this.cancel(false);\n }\n\n return true;\n });\n }\n\n ngOnInit() {\n this.editMode = this.initializeEditMode;\n this.globalEditFormChangesTrackerService.addToActiveForms(this);\n\n if (this.initializeEditMode) {\n this.start();\n }\n }\n\n ngOnDestroy() {\n this.unregisterListener();\n this.globalEditFormChangesTrackerService.removeFromActiveForms(this);\n }\n\n public async activateField(form:EditForm, schema:IFieldSchema, fieldName:string, errors:string[]):Promise {\n return this.waitForField(fieldName).then((ctrl) => {\n ctrl.setActive(true);\n const container = ctrl.editContainer.nativeElement;\n return this.editingPortalService.create(\n container,\n this.injector,\n form,\n schema,\n fieldName,\n errors\n );\n });\n }\n\n public async reset(fieldName:string, focus:boolean = false) {\n const ctrl = await this.waitForField(fieldName);\n ctrl.reset();\n ctrl.deactivate(focus);\n }\n\n public onSaved(commit:ResourceChangesetCommit) {\n this.cancel(false);\n this.onSavedEmitter.emit({savedResource: commit.resource, isInitial: commit.wasNew });\n }\n\n public cancel(reset:boolean = false) {\n this.editMode = false;\n this.closeEditFields('all', reset);\n\n if (reset) {\n this.halEditing.reset(this.change);\n }\n }\n\n public requireVisible(fieldName:string):Promise {\n return new Promise((resolve, _) => {\n const interval = setInterval(() => {\n const field = this.fields[fieldName];\n\n if (field !== undefined) {\n clearInterval(interval);\n resolve();\n }\n }, 50);\n });\n }\n\n public get editing():boolean {\n return this.editMode || this.hasActiveFields();\n }\n\n public register(field:EditableAttributeFieldComponent) {\n this.fields[field.fieldName] = field;\n this.registeredFields.putValue(_.keys(this.fields));\n\n const shouldActivate =\n (this.editMode && !this.skipField(field) || this.activeFields[field.fieldName]);\n\n if (shouldActivate) {\n field.activateOnForm(true);\n }\n }\n\n public waitForField(name:string):Promise {\n return this.registeredFields\n .values$()\n .pipe(\n filter(keys => keys.indexOf(name) >= 0),\n take(1),\n map(() => this.fields[name])\n )\n .toPromise();\n }\n\n public start() {\n _.each(this.fields, ctrl => this.activate(ctrl.fieldName));\n }\n\n protected focusOnFirstError():void {\n // Focus the first field that is erroneous\n jQuery(this.elementRef.nativeElement)\n .find(`.${activeFieldContainerClassName}.-error .${activeFieldClassName}`)\n .first()\n .trigger('focus');\n }\n\n private skipField(field:EditableAttributeFieldComponent) {\n const fieldName = field.fieldName;\n\n const isSkipField = this.skippedFields.indexOf(fieldName) !== -1;\n\n // Only skip status or type\n if (!isSkipField) {\n return false;\n }\n\n // Only skip if value present and not changed in changeset\n const hasDefault = this.resource[fieldName];\n const changed = this.change.changes[fieldName];\n\n return hasDefault && !changed;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","import {AfterViewInit, ChangeDetectorRef, Directive, Input, SimpleChanges} from '@angular/core';\nimport {CurrentProjectService} from '../../projects/current-project.service';\nimport {WorkPackageStatesInitializationService} from '../../wp-list/wp-states-initialization.service';\nimport {\n WorkPackageTableConfiguration,\n WorkPackageTableConfigurationObject\n} from 'core-components/wp-table/wp-table-configuration';\nimport {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service';\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackagesViewBase} from \"core-app/modules/work_packages/routing/wp-view-base/work-packages-view.base\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Directive()\nexport abstract class WorkPackageEmbeddedBaseComponent extends WorkPackagesViewBase implements AfterViewInit {\n @Input('configuration') protected providedConfiguration:WorkPackageTableConfigurationObject;\n @Input() public uniqueEmbeddedTableName:string = `embedded-table-${Date.now()}`;\n @Input() public initialLoadingIndicator:boolean = true;\n\n public renderTable = false;\n public showTablePagination = false;\n public configuration:WorkPackageTableConfiguration;\n public error:string|null = null;\n\n protected initialized:boolean = false;\n\n @InjectField() apiV3Service:APIV3Service;\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() I18n:I18nService;\n @InjectField() urlParamsHelper:UrlParamsHelperService;\n @InjectField() loadingIndicatorService:LoadingIndicatorService;\n @InjectField() wpStatesInitialization:WorkPackageStatesInitializationService;\n @InjectField() currentProject:CurrentProjectService;\n @InjectField() cdRef:ChangeDetectorRef;\n\n ngOnInit() {\n this.configuration = new WorkPackageTableConfiguration(this.providedConfiguration);\n // Set embedded status in configuration\n this.configuration.isEmbedded = true;\n this.initialized = true;\n\n super.ngOnInit();\n }\n\n ngAfterViewInit():void {\n // Load initially\n this.loadQuery(true, false);\n }\n\n ngOnChanges(changes:SimpleChanges) {\n if (this.initialized && (changes.queryId || changes.queryProps)) {\n this.loadQuery(this.initialLoadingIndicator, false);\n }\n }\n\n public get projectIdentifier() {\n if (this.configuration.projectContext) {\n return this.currentProject.identifier || undefined;\n } else {\n return this.configuration.projectIdentifier || undefined;\n }\n }\n\n public buildQueryProps() {\n const query = this.querySpace.query.value!;\n this.wpStatesInitialization.applyToQuery(query);\n\n return this.urlParamsHelper.buildV3GetQueryFromQueryResource(query);\n }\n\n public buildUrlParams() {\n const query = this.querySpace.query.value!;\n this.wpStatesInitialization.applyToQuery(query);\n\n return this.urlParamsHelper.encodeQueryJsonParams(query);\n }\n\n protected setLoaded() {\n this.renderTable = this.configuration.tableVisible;\n this.cdRef.detectChanges();\n }\n\n public refresh(visible:boolean = true, firstPage:boolean = false):Promise {\n const query = this.querySpace.query.value!;\n const pagination = this.wpTablePagination.paginationObject;\n\n if (firstPage) {\n pagination.offset = 1;\n }\n\n const params = this.urlParamsHelper.buildV3GetQueryFromQueryResource(query, pagination);\n const promise =\n this\n .wpListService\n .loadQueryFromExisting(query, params, this.queryProjectScope)\n .toPromise()\n .then((query) => this.wpStatesInitialization.updateQuerySpace(query, query.results));\n\n if (visible) {\n this.loadingIndicator = promise;\n }\n return promise;\n }\n\n public get isInitialized() {\n return !!this.configuration;\n }\n\n public set loadingIndicator(promise:Promise) {\n if (this.configuration.tableVisible) {\n this.loadingIndicatorService\n .indicator(this.uniqueEmbeddedTableName)\n .promise = promise;\n }\n }\n\n public abstract loadQuery(visible:boolean, firstPage:boolean):Promise;\n\n protected get queryProjectScope() {\n if (!this.configuration.projectContext) {\n return undefined;\n } else {\n return this.projectIdentifier;\n }\n }\n\n protected initializeStates(query:QueryResource) {\n this.wpStatesInitialization.clearStates();\n this.wpStatesInitialization.initializeFromQuery(query, query.results);\n this.wpStatesInitialization.updateQuerySpace(query, query.results);\n }\n}\n","
    \n\n \n \n \n\n \n\n \n \n\n \n
    \n \n \n
    \n\n \n \n
    \n\n
    \n \n
    \n
    \n","import {AfterViewInit, Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';\nimport {WorkPackageViewTimelineService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service';\nimport {WorkPackageViewPaginationService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service';\nimport {OpTableActionFactory} from 'core-components/wp-table/table-actions/table-action';\nimport {OpTableActionsService} from 'core-components/wp-table/table-actions/table-actions.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WpTableConfigurationModalComponent} from 'core-components/wp-table/configuration-modal/wp-table-configuration.modal';\nimport {OpModalService} from 'core-components/op-modals/op-modal.service';\nimport {WorkPackageEmbeddedBaseComponent} from \"core-components/wp-table/embedded/wp-embedded-base.component\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {distinctUntilChanged, map, take, withLatestFrom} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {KeepTabService} from \"core-components/wp-single-view-tabs/keep-tab/keep-tab.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-embedded-table',\n templateUrl: './wp-embedded-table.html'\n})\nexport class WorkPackageEmbeddedTableComponent extends WorkPackageEmbeddedBaseComponent implements OnInit, AfterViewInit, OnDestroy {\n @Input('queryId') public queryId?:string;\n @Input('queryProps') public queryProps:any = {};\n @Input() public tableActions:OpTableActionFactory[] = [];\n @Input() public externalHeight:boolean = false;\n\n /** Inform about loading errors */\n @Output() public onError = new EventEmitter();\n\n /** Inform about loaded query */\n @Output() public onQueryLoaded = new EventEmitter();\n\n @InjectField() apiv3Service:APIV3Service;\n @InjectField() opModalService:OpModalService;\n @InjectField() tableActionsService:OpTableActionsService;\n @InjectField() wpTableTimeline:WorkPackageViewTimelineService;\n @InjectField() wpTablePagination:WorkPackageViewPaginationService;\n @InjectField() keepTab:KeepTabService;\n\n // Cache the form promise\n private formPromise:Promise|undefined;\n\n // If the query was provided to use via the query space,\n // use it to cache first loading\n private loadedQuery:QueryResource|undefined;\n\n ngOnInit() {\n super.ngOnInit();\n this.loadedQuery = this.querySpace.query.value;\n }\n\n ngAfterViewInit():void {\n super.ngAfterViewInit();\n\n // Provision embedded table actions\n if (this.tableActions) {\n this.tableActionsService.setActions(...this.tableActions);\n }\n\n // Reload results on changes to pagination (Regression #29845)\n this.wpTablePagination\n .updates$()\n .pipe(\n map(pagination => [pagination.page, pagination.perPage]),\n distinctUntilChanged(),\n this.untilDestroyed(),\n withLatestFrom(this.querySpace.query.values$())\n ).subscribe(([_, query]) => {\n const pagination = this.wpTablePagination.paginationObject;\n const params = this.urlParamsHelper.buildV3GetQueryFromQueryResource(query, pagination);\n\n this.loadingIndicator =\n this\n .wpListService\n .loadQueryFromExisting(query, params, this.queryProjectScope)\n .toPromise()\n .then((query) => this.initializeStates(query));\n });\n }\n\n public openConfigurationModal(onUpdated:() => void) {\n this.querySpace.query\n .valuesPromise()\n .then(() => {\n const modal = this.opModalService\n .show(WpTableConfigurationModalComponent, this.injector);\n\n // Detach this component when the modal closes and pass along the query data\n modal.onDataUpdated.subscribe(onUpdated);\n });\n }\n\n protected initializeStates(query:QueryResource) {\n // If the configuration requests filters, we need to load the query form as well.\n if (this.configuration.withFilters) {\n this.loadForm(query);\n }\n\n super.initializeStates(query);\n\n\n this.querySpace\n .initialized\n .values$()\n .pipe(take(1))\n .subscribe(() => {\n this.showTablePagination = query.results.total > query.results.count;\n this.setLoaded();\n\n // Disable compact mode when timeline active\n if (this.wpTableTimeline.isVisible) {\n this.configuration = { ...this.configuration, compactTableStyle: false };\n }\n });\n }\n\n private loadForm(query:QueryResource):Promise {\n if (this.formPromise) {\n return this.formPromise;\n }\n\n return this.formPromise =\n this\n .apiv3Service\n .withOptionalProject(this.projectIdentifier)\n .queries\n .form\n .load(query)\n .toPromise()\n .then(([form, _]) => {\n this.wpStatesInitialization.updateStatesFromForm(query, form);\n return form;\n })\n .catch(() => this.formPromise = undefined);\n }\n\n public loadQuery(visible:boolean = true, firstPage:boolean = false):Promise {\n // Ensure we are loading the form.\n this.formPromise = undefined;\n\n if (this.loadedQuery) {\n const query = this.loadedQuery;\n this.loadedQuery = undefined;\n this.initializeStates(query);\n return Promise.resolve(this.loadedQuery!);\n }\n\n // HACK: Decrease loading time of queries when results are not needed.\n // We should allow the backend to disable results embedding instead.\n if (!this.configuration.tableVisible) {\n this.queryProps.pageSize = 1;\n }\n\n // Set first page\n if (firstPage) {\n this.queryProps.page = 1;\n }\n\n this.error = null;\n const promise = this\n .apiv3Service\n .queries\n .find(\n this.queryProps,\n this.queryId,\n this.queryProjectScope\n )\n .toPromise()\n .then((query:QueryResource) => {\n this.initializeStates(query);\n this.onQueryLoaded.emit(query);\n return query;\n })\n .catch((error) => {\n this.error = this.I18n.t(\n 'js.error.embedded_table_loading',\n { message: _.get(error, 'message', error) }\n );\n this.onError.emit(error);\n });\n\n if (visible) {\n this.loadingIndicator = promise;\n }\n\n return promise;\n }\n\n handleWorkPackageClicked(event:{ workPackageId:string; double:boolean }) {\n if (event.double) {\n this.$state.go(\n 'work-packages.show',\n { workPackageId: event.workPackageId }\n );\n }\n }\n\n openStateLink(event:{ workPackageId:string; requestedState:string }) {\n this.$state.go(\n (this.keepTab as any)[event.requestedState] || event.requestedState,\n { workPackageId: event.workPackageId, focus: true }\n );\n }\n}\n","import {\n AfterViewInit,\n Component,\n ElementRef,\n EventEmitter,\n Injector,\n Input,\n OnDestroy,\n OnInit,\n Output\n} from \"@angular/core\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {\n OpEditingPortalChangesetToken,\n OpEditingPortalHandlerToken,\n OpEditingPortalSchemaToken\n} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {createLocalInjector} from \"core-app/modules/fields/edit/editing-portal/edit-form-portal.injector\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {EditFieldService, IEditFieldType} from \"core-app/modules/fields/edit/edit-field.service\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\n\n@Component({\n selector: 'edit-form-portal',\n templateUrl: './edit-form-portal.component.html'\n})\nexport class EditFormPortalComponent implements OnInit, OnDestroy, AfterViewInit {\n @Input() schemaInput:IFieldSchema;\n @Input() changeInput:ResourceChangeset;\n @Input() editFieldHandler:EditFieldHandler;\n @Output() public onEditFieldReady = new EventEmitter();\n\n public handler:EditFieldHandler;\n public schema:IFieldSchema;\n public change:ResourceChangeset;\n public fieldInjector:Injector;\n\n public componentClass:IEditFieldType;\n public htmlId:string;\n public label:string;\n\n constructor(readonly injector:Injector,\n readonly editField:EditFieldService,\n readonly elementRef:ElementRef) {\n }\n\n ngOnInit() {\n if (this.editFieldHandler && this.schemaInput) {\n this.handler = this.editFieldHandler;\n this.schema = this.schemaInput;\n this.change = this.changeInput;\n\n } else {\n this.handler = this.injector.get(OpEditingPortalHandlerToken);\n this.schema = this.injector.get(OpEditingPortalSchemaToken);\n this.change = this.injector.get(OpEditingPortalChangesetToken);\n }\n\n this.componentClass = this.editField.getSpecificClassFor(this.change.pristineResource._type, this.handler.fieldName, this.schema.type);\n this.fieldInjector = createLocalInjector(this.injector, this.change, this.handler, this.schema);\n }\n\n ngOnDestroy() {\n this.onEditFieldReady.complete();\n }\n\n ngAfterViewInit() {\n // Fire in a timeout to avoid same execution context in AfterViewInit\n setTimeout(() => {\n this.onEditFieldReady.emit();\n });\n }\n}\n","
    \n
    \n\n \n \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {SchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\n\nexport class WorkPackageSchemaProxy extends SchemaProxy {\n get(schema:SchemaResource, property:PropertyKey, receiver:any):any {\n switch (property) {\n case 'isMilestone': {\n return this.isMilestone;\n }\n case 'isReadonly': {\n return this.isReadonly;\n }\n default: {\n return super.get(schema, property, receiver);\n }\n }\n }\n\n /**\n * Returns the part of the schema relevant for the provided property.\n *\n * We use it to support the virtual attribute 'combinedDate' which is the combination of the three\n * attributes 'startDate', 'dueDate' and 'scheduleManually'. That combination exists only in the front end\n * and not on the native schema. As a property needs to be writable for us to allow the user editing,\n * we need to mark the writability positively if any of the combined properties are writable.\n *\n * @param property the schema part is desired for\n */\n public ofProperty(property:string) {\n if (property === 'combinedDate') {\n let propertySchema = super.ofProperty('startDate');\n\n if (!propertySchema) {\n return null;\n }\n\n propertySchema.writable = propertySchema.writable ||\n this.isAttributeEditable('dueDate') ||\n this.isAttributeEditable('scheduleManually');\n\n return propertySchema;\n } else {\n return super.ofProperty(property);\n }\n }\n\n public get isReadonly():boolean {\n return this.resource.status?.isReadonly;\n }\n\n /**\n * Return whether the work package is editable with the user's permission\n * on the given work package attribute.\n *\n * @param property\n */\n public isAttributeEditable(property:string):boolean {\n if (this.isReadonly && property !== 'status') {\n return false;\n } else if (['startDate', 'dueDate', 'date'].includes(property) &&\n this.resource.scheduleManually) {\n // This is a blatant shortcut but should be adequate.\n return super.isAttributeEditable('scheduleManually');\n } else {\n return super.isAttributeEditable(property);\n }\n }\n\n public get isMilestone():boolean {\n return this.schema.hasOwnProperty('date');\n }\n\n public mappedName(property:string):string {\n if (this.isMilestone && (property === 'startDate' || property === 'dueDate')) {\n return 'date';\n } else {\n return property;\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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 {WorkPackageViewDisplayRepresentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageViewHierarchyIdentationService {\n\n constructor(private wpViewHierarchies:WorkPackageViewHierarchiesService,\n private wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService,\n private states:States,\n private wpRelationHierarchy:WorkPackageRelationsHierarchyService,\n private apiV3Service:APIV3Service,\n private querySpace:IsolatedQuerySpace) {\n }\n\n /**\n * Return whether the current hierarchy mode is active\n */\n public get applicable():boolean {\n return this.wpViewHierarchies.isEnabled && this.wpDisplayRepresentation.isList;\n }\n\n /**\n * Returns whether the given work package can be indented in the current render order\n * @param workPackage\n */\n public canIndent(workPackage:WorkPackageResource):boolean {\n if (!workPackage.changeParent || !this.applicable) {\n return false;\n }\n\n const rendered = this.renderedWorkPackageIds;\n const index = rendered.indexOf(workPackage.id!);\n\n // We can never indent the first item\n if (index === 0) {\n return false;\n }\n\n // We can not indent work packages whose predecessors are already their ancestors\n const ancestors = workPackage.ancestorIds;\n const ancestorCount = ancestors.length;\n\n // We can always indent if the ancestor count is 0\n if (ancestorCount === 0) {\n return true;\n }\n\n // Otherwise, we can only indent if the predecessor is NOT the last ancestor\n const lastAncestor:string = ancestors[ancestorCount - 1];\n const predecessorId:string = rendered[index - 1];\n\n return predecessorId !== lastAncestor;\n }\n\n /**\n * Returns whether the given work package can be outdented\n * @param workPackage\n */\n public canOutdent(workPackage:WorkPackageResource):boolean {\n if (!workPackage.changeParent || !this.applicable) {\n return false;\n }\n\n // We can always outdent if the work package has a parent\n return !!workPackage.parent;\n }\n\n /**\n * Try to indent the work package.\n * @return a Promise with the change parent result\n */\n public async indent(workPackage:WorkPackageResource):Promise {\n if (!this.canIndent(workPackage)) {\n return Promise.reject();\n }\n\n const rendered = this.renderedWorkPackageIds;\n const index = rendered.indexOf(workPackage.id!);\n const predecessorId:string = rendered[index - 1];\n\n // By default, assume we're going to insert under parent\n let newParentId = predecessorId;\n\n // If the predecessor is in an ancestor chain.\n // get the first element of the ancestor chain that workPackage is not in\n const predecessor = await this.apiV3Service.work_packages.id(predecessorId).get().toPromise();\n\n const difference = _.difference(predecessor.ancestorIds, workPackage.ancestorIds);\n if (difference && difference.length > 0) {\n newParentId = difference[0];\n }\n\n return this\n .wpRelationHierarchy\n .changeParent(workPackage, newParentId);\n }\n\n /**\n * Try to outdent the work package.\n * @return a Promise with the change parent result\n */\n public outdent(workPackage:WorkPackageResource):Promise {\n if (!this.canOutdent(workPackage)) {\n return Promise.reject();\n }\n\n let newParentId:string|null = null;\n\n // If we have more than one ancestor,\n // just drop the last one\n const ancestorIds = workPackage.ancestorIds;\n const ancestorCount = ancestorIds.length;\n if (ancestorCount > 1) {\n newParentId = ancestorIds[ancestorCount - 2];\n }\n\n return this\n .wpRelationHierarchy\n .changeParent(workPackage, newParentId);\n }\n\n /**\n * Get the currently rendered work packages\n */\n private get renderedWorkPackageIds():string[] {\n return this.querySpace.renderedWorkPackageIds.getValueOr([]);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageWatchersService} from 'core-components/wp-single-view-tabs/watchers-tab/wp-watchers.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-watcher-button',\n templateUrl: './wp-watcher-button.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageWatcherButtonComponent extends UntilDestroyedMixin implements OnInit {\n @Input('workPackage') public workPackage:WorkPackageResource;\n @Input('showText') public showText:boolean = false;\n @Input('disabled') public disabled:boolean = false;\n\n public buttonText:string;\n public buttonTitle:string;\n public buttonClass:string;\n public buttonId:string;\n public watchIconClass:string;\n\n constructor(readonly I18n:I18nService,\n readonly wpWatchersService:WorkPackageWatchersService,\n readonly apiV3Service:APIV3Service,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.setWatchStatus();\n this.cdRef.detectChanges();\n });\n }\n\n public get isWatched() {\n return this.workPackage.hasOwnProperty('unwatch');\n }\n\n public get displayWatchButton() {\n return this.isWatched || this.workPackage.hasOwnProperty('watch');\n }\n\n public toggleWatch() {\n const toggleLink = this.nextStateLink();\n\n toggleLink(toggleLink.$link.payload).then(() => {\n this.wpWatchersService.clear(this.workPackage.id!);\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .refresh();\n });\n }\n\n public nextStateLink() {\n const linkName = this.isWatched ? 'unwatch' : 'watch';\n return this.workPackage[linkName];\n }\n\n private setWatchStatus() {\n if (this.isWatched) {\n this.buttonTitle = this.I18n.t('js.label_unwatch_work_package');\n this.buttonText = this.I18n.t('js.label_unwatch');\n this.buttonClass = '-active';\n this.buttonId = 'unwatch-button';\n this.watchIconClass = 'icon-watched';\n\n } else {\n this.buttonTitle = this.I18n.t('js.label_watch_work_package');\n this.buttonText = this.I18n.t('js.label_watch');\n this.buttonClass = '';\n this.buttonId = 'watch-button';\n this.watchIconClass = 'icon-unwatched';\n }\n }\n}\n","\n","export namespace SelectionHelpers {\n\n /**\n * Test whether we currently have a selection within.\n * @param {HTMLElement} target\n * @return {boolean}\n */\n export function hasSelectionWithin(target:Element):boolean {\n try {\n const selection = window.getSelection()!;\n const hasSelection = selection.toString().length > 0;\n const isWithin = target.contains(selection.anchorNode);\n\n return hasSelection && isWithin;\n } catch (e) {\n console.error('Failed to test whether in selection ', e);\n return false;\n }\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {States} from 'core-components/states.service';\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {SelectionHelpers} from '../../../../helpers/selection-helpers';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input,\n OnDestroy,\n OnInit, Optional,\n ViewChild\n} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {ClickPositionMapper} from \"core-app/modules/common/set-click-position/set-click-position\";\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {ISchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {\n displayClassName,\n DisplayFieldRenderer,\n editFieldContainerClass\n} from \"core-app/modules/fields/display/display-field-renderer\";\n\n@Component({\n selector: 'editable-attribute-field',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './editable-attribute-field.component.html'\n})\nexport class EditableAttributeFieldComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n @Input() public fieldName:string;\n @Input() public resource:HalResource;\n @Input() public wrapperClasses?:string;\n @Input() public displayFieldOptions:any = {};\n @Input() public displayPlaceholder?:string;\n @Input() public isDropTarget?:boolean = false;\n\n @ViewChild('displayContainer', { static: true }) readonly displayContainer:ElementRef;\n @ViewChild('editContainer', { static: true }) readonly editContainer:ElementRef;\n\n public fieldRenderer:DisplayFieldRenderer;\n public editFieldContainerClass = editFieldContainerClass;\n public active = false;\n private $element:JQuery;\n\n public destroyed:boolean = false;\n\n constructor(protected states:States,\n protected injector:Injector,\n protected elementRef:ElementRef,\n protected ConfigurationService:ConfigurationService,\n protected opContextMenu:OPContextMenuService,\n protected halEditing:HalResourceEditingService,\n protected schemaCache:SchemaCacheService,\n // Get parent field group from injector if we're in a form\n @Optional() protected editForm:EditFormComponent,\n protected NotificationsService:NotificationsService,\n protected cdRef:ChangeDetectorRef,\n protected I18n:I18nService) {\n super();\n }\n\n public setActive(active:boolean = true) {\n this.active = active;\n if (!this.componentDestroyed) {\n this.cdRef.detectChanges();\n }\n }\n\n public ngOnInit() {\n this.fieldRenderer = new DisplayFieldRenderer(this.injector, 'single-view', this.displayFieldOptions);\n this.$element = jQuery(this.elementRef.nativeElement);\n\n // Register on the form if we're in an editable context\n this.editForm?.register(this);\n\n this.halEditing\n .temporaryEditResource(this.resource)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(resource => {\n this.resource = resource;\n this.render();\n });\n }\n\n // Open the field when its closed and relay drag & drop events to it.\n public startDragOverActivation(event:JQuery.TriggeredEvent) {\n if (!this.isDropTarget || !this.isEditable || this.active) {\n return true;\n }\n\n this.handleUserActivate(null);\n event.preventDefault();\n return false;\n }\n\n public render() {\n const el = this.fieldRenderer.render(this.resource, this.fieldName, null, this.displayPlaceholder);\n this.displayContainer.nativeElement.innerHTML = '';\n this.displayContainer.nativeElement.appendChild(el);\n }\n\n public deactivate(focus:boolean = false) {\n this.editContainer.nativeElement.innerHTML = '';\n this.editContainer.nativeElement.hidden = true;\n this.setActive(false);\n\n if (focus) {\n setTimeout(() => this.$element.find(`.${displayClassName}`).focus(), 20);\n }\n }\n\n public get isEditable():boolean {\n return this.editForm && this.schema.isAttributeEditable(this.fieldName);\n }\n\n public activateIfEditable(event:JQuery.TriggeredEvent) {\n // Ignore selections\n if (SelectionHelpers.hasSelectionWithin(event.target)) {\n debugLog(`Not activating ${this.fieldName} because of active selection within`);\n return true;\n }\n\n // Skip activation if the user clicked on a link or within a macro\n const target = jQuery(event.target);\n if (target.closest('a,macro', this.displayContainer.nativeElement).length > 0) {\n return true;\n }\n\n if (this.isEditable) {\n this.handleUserActivate(event);\n }\n\n this.opContextMenu.close();\n event.preventDefault();\n event.stopImmediatePropagation();\n\n return false;\n }\n\n public activateOnForm(noWarnings:boolean = false) {\n // Activate the field\n this.setActive(true);\n\n return this.editForm\n .activate(this.fieldName, noWarnings)\n .catch(() => this.deactivate(true));\n }\n\n public handleUserActivate(evt:JQuery.TriggeredEvent|null) {\n let positionOffset = 0;\n\n if (evt) {\n // Get the position where the user clicked.\n positionOffset = ClickPositionMapper.getPosition(evt);\n }\n\n this.activateOnForm()\n .then((handler) => {\n if (!handler) {\n return;\n }\n\n handler.$onUserActivate.next();\n handler.focus(positionOffset);\n });\n\n return false;\n }\n\n public reset() {\n this.render();\n this.deactivate();\n }\n\n private get schema() {\n if (this.halEditing.typedState(this.resource).hasValue()) {\n return this.halEditing.typedState(this.resource).value!.schema;\n } else {\n return this.schemaCache.of(this.resource) as ISchemaProxy;\n }\n }\n}\n","
    \n\n
    \n
    \n\n
    \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n@Component({\n template: `\n \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-fold-toggle-view-button'\n})\nexport class WorkPackageFoldToggleButtonComponent {\n}\n","import {Injectable, Injector, Optional} from '@angular/core';\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {States} from \"core-components/states.service\";\nimport {WorkPackageCreateService} from \"core-components/wp-new/wp-create.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {DragAndDropService} from \"core-app/modules/common/drag-and-drop/drag-and-drop.service\";\nimport {DragAndDropHelpers} from \"core-app/modules/common/drag-and-drop/drag-and-drop.helpers\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageCardDragAndDropService {\n\n private _workPackages:WorkPackageResource[];\n\n /** Whether the card view has an active inline created wp */\n public activeInlineCreateWp?:WorkPackageResource;\n\n /** A reference to the component in use, to have access to the current input variables */\n public cardView:WorkPackageCardViewComponent;\n\n\n public constructor(readonly states:States,\n readonly injector:Injector,\n readonly reorderService:WorkPackageViewOrderService,\n readonly wpCreate:WorkPackageCreateService,\n readonly notificationService:WorkPackageNotificationService,\n readonly apiV3Service:APIV3Service,\n readonly currentProject:CurrentProjectService,\n @Optional() readonly dragService:DragAndDropService,\n readonly wpInlineCreate:WorkPackageInlineCreateService) {\n\n }\n\n public init(componentRef:WorkPackageCardViewComponent) {\n this.cardView = componentRef;\n }\n\n public destroy() {\n if (this.dragService !== null) {\n this.dragService.remove(this.cardView.container.nativeElement);\n }\n }\n\n public registerDragAndDrop() {\n // The DragService may not have been provided\n // in which case we do not provide drag and drop\n if (this.dragService === null) {\n return;\n }\n\n this.dragService.register({\n dragContainer: this.cardView.container.nativeElement,\n scrollContainers: [this.cardView.container.nativeElement],\n moves: (card:HTMLElement) => {\n const wpId:string = card.dataset.workPackageId!;\n const workPackage = this.states.workPackages.get(wpId).value;\n\n return !!workPackage && this.cardView.canDragOutOf(workPackage) && !card.dataset.isNew;\n },\n accepts: () => this.cardView.dragInto,\n onMoved: async (card:HTMLElement) => {\n const wpId:string = card.dataset.workPackageId!;\n const toIndex = DragAndDropHelpers.findIndex(card);\n\n const newOrder = await this.reorderService.move(this.currentOrder, wpId, toIndex);\n this.updateOrder(newOrder);\n\n this.cardView.onMoved.emit();\n },\n onRemoved: (card:HTMLElement) => {\n const wpId:string = card.dataset.workPackageId!;\n\n const newOrder = this.reorderService.remove(this.currentOrder, wpId);\n this.updateOrder(newOrder);\n },\n onAdded: async (card:HTMLElement) => {\n const wpId:string = card.dataset.workPackageId!;\n const toIndex = DragAndDropHelpers.findIndex(card);\n\n const workPackage = await this\n .apiV3Service\n .work_packages\n .id(wpId)\n .get()\n .toPromise();\n const result = await this.addWorkPackageToQuery(workPackage, toIndex);\n\n if (card.parentElement) {\n card.parentElement.removeChild(card);\n }\n\n return result;\n }\n });\n }\n\n /**\n * Get the current work packages\n */\n public get workPackages():WorkPackageResource[] {\n return this._workPackages;\n }\n\n /**\n * Set work packages array,\n * remembering to keep the active inline-create\n */\n public set workPackages(workPackages:WorkPackageResource[]) {\n if (this.activeInlineCreateWp) {\n let existingNewWp = this._workPackages.find(o => o.isNew);\n\n // If there is already a card for a new WP,\n // we have to replace this one by the new activeInlineCreateWp\n if (existingNewWp) {\n let index = this._workPackages.indexOf(existingNewWp);\n this._workPackages[index] = this.activeInlineCreateWp;\n } else {\n this._workPackages = [this.activeInlineCreateWp, ...workPackages];\n }\n } else {\n this._workPackages = [...workPackages];\n }\n }\n\n /**\n * Get current order\n */\n private get currentOrder():string[] {\n return this.workPackages\n .filter(wp => wp && !wp.isNew)\n .map(el => el.id!);\n }\n\n /**\n * Update current order\n */\n private updateOrder(newOrder:string[]) {\n newOrder = _.uniq(newOrder);\n\n Promise\n .all(newOrder.map(id =>\n this\n .apiV3Service\n .work_packages\n .id(id)\n .get()\n .toPromise()\n ))\n .then((workPackages:WorkPackageResource[]) => {\n this.workPackages = workPackages;\n this.cardView.cdRef.detectChanges();\n });\n }\n\n /**\n * Inline create a new card\n */\n public addNewCard() {\n this.wpCreate\n .createOrContinueWorkPackage(this.currentProject.identifier)\n .then((changeset:WorkPackageChangeset) => {\n this.activeInlineCreateWp = changeset.projectedResource;\n this.workPackages = this.workPackages;\n this.cardView.cdRef.detectChanges();\n });\n }\n\n /**\n * Add the given work package to the query\n */\n async addWorkPackageToQuery(workPackage:WorkPackageResource, toIndex:number = -1):Promise {\n try {\n await this.cardView.workPackageAddedHandler(workPackage);\n const newOrder = await this.reorderService.add(this.currentOrder, workPackage.id!, toIndex);\n this.updateOrder(newOrder);\n return true;\n } catch (e) {\n this.notificationService.handleRawError(e, workPackage);\n }\n\n return false;\n }\n\n /**\n * Remove the new card\n */\n public removeReferenceWorkPackageForm() {\n if (this.activeInlineCreateWp) {\n this.removeCard(this.activeInlineCreateWp);\n }\n }\n\n removeCard(wp:WorkPackageResource) {\n const index = this.workPackages.indexOf(wp);\n this.workPackages.splice(index, 1);\n this.activeInlineCreateWp = undefined;\n\n if (!wp.isNew) {\n const newOrder = this.reorderService.remove(this.currentOrder, wp.id!);\n this.updateOrder(newOrder);\n }\n }\n\n /**\n * On new card saved\n */\n async onCardSaved(wp:WorkPackageResource) {\n const index = this.workPackages.findIndex((el) => el.id === 'new');\n\n if (index !== -1) {\n this.activeInlineCreateWp = undefined;\n\n // Add this item to the results\n const newOrder = await this.reorderService.add(this.currentOrder, wp.id!, index);\n this.updateOrder(newOrder);\n\n // Notify inline create service\n this.wpInlineCreate.newInlineWorkPackageCreated.next(wp.id!);\n }\n }\n}\n","export namespace DomHelpers {\n export function setBodyCursor(cursor:string, priority:'important'|'' = '') {\n document.body.style.setProperty('cursor', cursor, priority);\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport interface WorkPackageCollectionResourceEmbedded {\n elements:WorkPackageResource[];\n groups:GroupObject[];\n}\n\nexport class WorkPackageCollectionResource extends CollectionResource {\n public schemas:CollectionResource;\n public createWorkPackage:any;\n public elements:WorkPackageResource[];\n public groups:GroupObject[];\n public totalSums?:Object;\n public sumsSchema?:SchemaResource;\n public representations:Array;\n}\n\nexport interface WorkPackageCollectionResource extends WorkPackageCollectionResourceEmbedded {\n}\n\n/**\n * A reference to a group object as returned from the API.\n * Augmented with state information such as collapsed state.\n */\nexport interface GroupObject {\n value:any;\n count:number;\n collapsed?:boolean;\n index:number;\n identifier:string;\n sums:{[attribute:string]:number|null};\n href:{ href:string }[];\n _links:{\n valueLink:{ href:string }[];\n groupBy:{ href:string };\n };\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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\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';\nimport {Attachable} from \"core-app/modules/hal/resources/mixins/attachable-mixin\";\n\nexport class HelpTextBaseResource 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 const HelpTextResource = Attachable(HelpTextBaseResource);\n\nexport interface HelpTextResource extends HelpTextBaseResource {\n editText?:CallableHalLink;\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class TimeEntryResource extends HalResource {\n public get state() {\n return this.states.timeEntries.get(this.id!) as any;\n }\n\n /**\n * Exclude the schema _link from the linkable Resources.\n */\n public $linkableKeys():string[] {\n return _.without(super.$linkableKeys(), 'schema');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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';\n\nexport class ProjectResource extends HalResource {\n public get state() {\n return this.states.projects.get(this.id!) as any;\n }\n\n public getEditorTypeFor(fieldName:string):\"full\"|\"constrained\" {\n if (['statusExplanation', 'description'].indexOf(fieldName) !== -1) {\n return 'full';\n }\n\n return 'constrained';\n }\n\n /**\n * Exclude the schema _link from the linkable Resources.\n */\n public $linkableKeys():string[] {\n return _.without(super.$linkableKeys(), 'schema');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","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 {OpenProjectHeaderInterceptor} from 'core-app/modules/hal/http/openproject-header-interceptor';\nimport {CommonModule} from \"@angular/common\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {HalAwareErrorHandler} from \"core-app/modules/hal/services/hal-aware-error-handler\";\n\n@NgModule({\n imports: [\n CommonModule,\n HttpClientModule,\n ],\n providers: [\n { provide: ErrorHandler, useClass: HalAwareErrorHandler },\n { provide: HTTP_INTERCEPTORS, useClass: OpenProjectHeaderInterceptor, multi: true },\n { provide: APP_INITIALIZER, useFactory: initializeHalResourceConfig, deps: [HalResourceService], multi: true },\n HalResourceNotificationService\n ]\n})\nexport class OpenprojectHalModule { }\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OpContextMenuItem} from 'core-components/op-context-menu/op-context-menu.types';\nimport {StateService} from '@uirouter/core';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {Directive, ElementRef, Input, OnInit} from \"@angular/core\";\nimport {LinkHandling} from \"core-app/modules/common/link-handling/link-handling\";\nimport {OpContextMenuTrigger} from \"core-components/op-context-menu/handlers/op-context-menu-trigger.directive\";\nimport {TypeResource} from 'core-app/modules/hal/resources/type-resource';\nimport {Highlighting} from 'core-app/components/wp-fast-table/builders/highlighting/highlighting.functions';\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {WorkPackageCreateService} from 'core-components/wp-new/wp-create.service';\n\n@Directive({\n selector: '[opTypesCreateDropdown]'\n})\nexport class OpTypesContextMenuDirective extends OpContextMenuTrigger {\n @Input('projectIdentifier') public projectIdentifier:string|null|undefined;\n @Input('stateName') public stateName:string;\n @Input('dropdownActive') active:boolean;\n\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly browserDetector:BrowserDetector,\n readonly wpCreate:WorkPackageCreateService,\n readonly $state:StateService) {\n super(elementRef, opContextMenu);\n }\n\n ngAfterViewInit():void {\n super.ngAfterViewInit();\n\n if (!this.active) {\n return;\n }\n\n // Force full-view create if in mobile view\n if (this.browserDetector.isMobile) {\n this.stateName = 'work-packages.new';\n }\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n this\n .wpCreate\n .getEmptyForm(this.projectIdentifier)\n .then(form => {\n this.buildItems(form.schema.type.allowedValues);\n this.opContextMenu.show(this, evt);\n });\n }\n\n public get locals():{ showAnchorRight?:boolean, contextMenuId?:string, items:OpContextMenuItem[] } {\n return {\n items: this.items,\n contextMenuId: 'types-context-menu'\n };\n }\n\n private buildItems(types:TypeResource[]) {\n this.items = types.map((type:TypeResource) => {\n return {\n disabled: false,\n linkText: type.name,\n href: this.$state.href(this.stateName, { type: type.id! }),\n ariaLabel: type.name,\n class: Highlighting.inlineClass('type', type.id!),\n onClick: ($event:JQuery.TriggeredEvent) => {\n if (LinkHandling.isClickedWithModifier($event)) {\n return false;\n }\n\n this.$state.go(this.stateName, { type: type.id });\n return true;\n }\n };\n });\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {ConfigurationResource} from \"core-app/modules/hal/resources/configuration-resource\";\nimport * as moment from \"moment\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class ConfigurationService {\n // fetches configuration from the ApiV3 endpoint\n // TODO: this currently saves the request between page reloads,\n // but could easily be stored in localStorage\n private configuration:ConfigurationResource;\n public initialized:Promise;\n\n public constructor(readonly I18n:I18nService,\n readonly apiV3Service:APIV3Service) {\n this.initialized = this.loadConfiguration().then(() => true).catch(() => false);\n }\n\n public commentsSortedInDescendingOrder() {\n return this.userPreference('commentSortDescending');\n }\n\n public warnOnLeavingUnsaved() {\n return this.userPreference('warnOnLeavingUnsaved');\n }\n\n public autoHidePopups() {\n return this.userPreference('autoHidePopups');\n }\n\n public isTimezoneSet() {\n return !!this.timezone();\n }\n\n public timezone() {\n return this.userPreference('timeZone');\n }\n\n public isDirectUploads() {\n return !!this.prepareAttachmentURL;\n }\n\n public get prepareAttachmentURL() {\n return _.get(this.configuration, ['prepareAttachment', 'href']);\n }\n\n public get maximumAttachmentFileSize() {\n return this.systemPreference('maximumAttachmentFileSize');\n }\n\n public get perPageOptions() {\n return this.systemPreference('perPageOptions');\n }\n\n public dateFormatPresent() {\n return !!this.systemPreference('dateFormat');\n }\n\n public dateFormat() {\n return this.systemPreference('dateFormat');\n }\n\n public timeFormatPresent() {\n return !!this.systemPreference('timeFormat');\n }\n\n public timeFormat() {\n return this.systemPreference('timeFormat');\n }\n\n public startOfWeekPresent() {\n return !!this.systemPreference('startOfWeek');\n }\n\n public startOfWeek() {\n if (this.startOfWeekPresent()) {\n return this.systemPreference('startOfWeek');\n } else {\n return moment.localeData(I18n.locale).firstDayOfWeek();\n }\n }\n\n private loadConfiguration() {\n return this\n .apiV3Service\n .configuration\n .get()\n .toPromise()\n .then((configuration) => {\n this.configuration = configuration;\n });\n }\n\n private userPreference(pref:string) {\n return _.get(this.configuration, ['userPreferences', pref]);\n }\n\n private systemPreference(pref:string) {\n return _.get(this.configuration, pref);\n }\n}\n","import {OPContextMenuService} from 'core-components/op-context-menu/op-context-menu.service';\nimport {OpContextMenuItem} from 'core-components/op-context-menu/op-context-menu.types';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n/**\n * Interface passed to CM service to open a particular context menu.\n * This will often be a trigger component, but does not have to be.\n */\nexport abstract class OpContextMenuHandler extends UntilDestroyedMixin {\n protected $element:JQuery;\n protected items:OpContextMenuItem[] = [];\n\n constructor(readonly opContextMenu:OPContextMenuService) {\n super();\n }\n\n /**\n * Called when the service closes this context menu\n */\n public onClose() {\n this.afterFocusOn.focus();\n }\n\n public onOpen(menu:JQuery) {\n menu.find('.menu-item').first().focus();\n }\n\n /**\n * Positioning args for jquery-ui position.\n *\n * @param {Event} openerEvent\n */\n public positionArgs(openerEvent:JQuery.TriggeredEvent):any {\n return {\n my: 'left top',\n at: 'right bottom',\n of: openerEvent,\n collision: 'flipfit'\n };\n }\n\n /**\n * Get the locals passed to the op-context-menu component\n */\n public get locals():{ showAnchorRight?:boolean, contextMenuId?:string, items:OpContextMenuItem[] } {\n return {\n items: this.items\n };\n }\n\n /**\n * Open this context menu\n */\n protected open(evt:JQuery.TriggeredEvent) {\n this.opContextMenu.show(this, evt);\n }\n\n protected get afterFocusOn():JQuery {\n return this.$element;\n }\n}\n","export namespace DragAndDropHelpers {\n export function findIndex(el:HTMLElement):number {\n if (!el.parentElement) {\n return -1;\n }\n\n const children = Array.from(el.parentElement.children);\n return children.indexOf(el);\n }\n\n export function reinsert(el:HTMLElement, previousIndex:number|string, container:HTMLElement) {\n previousIndex = typeof previousIndex === 'string' ? parseInt(previousIndex, 10) : previousIndex;\n const currentIndex = el.parentNode && Array.from(el.parentNode.children).indexOf(el) || null;\n const children = Array.from(container.children);\n let pointOfInsertion;\n\n if (currentIndex != null) {\n const isDraggingDown = currentIndex > previousIndex;\n pointOfInsertion = isDraggingDown ? children[previousIndex] : children[previousIndex + 1];\n } else {\n pointOfInsertion = children[previousIndex];\n }\n\n if (pointOfInsertion) {\n container.insertBefore(el, pointOfInsertion);\n } else {\n container.appendChild(el);\n }\n }\n}\n","import {Injector} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {commonRowClassName} from '../rows/single-row-builder';\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const timelineCellClassName = 'wp-timeline-cell';\n\nexport class TimelineRowBuilder {\n\n @InjectField() public states:States;\n @InjectField() public wpTableTimeline:WorkPackageViewTimelineService;\n\n constructor(public readonly injector:Injector,\n protected workPackageTable:WorkPackageTable) {\n }\n\n public build(workPackageId:string|null) {\n const cell = document.createElement('div');\n cell.classList.add(timelineCellClassName, commonRowClassName);\n\n if (workPackageId) {\n cell.dataset['workPackageId'] = workPackageId;\n }\n\n return cell;\n }\n\n /**\n * Build and insert a timeline row for the given work package using the additional classes.\n * @param workPackage\n * @param timelineBody\n * @param rowClasses\n */\n public insert(workPackageId:string|null,\n timelineBody:DocumentFragment|HTMLElement,\n rowClasses:string[] = []) {\n\n const cell = this.build(workPackageId);\n cell.classList.add(...rowClasses);\n\n timelineBody.appendChild(cell);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {WorkPackageWatchersService} from 'core-app/components/wp-single-view-tabs/watchers-tab/wp-watchers.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './wp-relations-count.html',\n selector: 'wp-watchers-count',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageWatchersCountComponent extends UntilDestroyedMixin implements OnInit {\n @Input('wpId') wpId:string;\n public count:number = 0;\n\n constructor(protected apiV3Service:APIV3Service,\n protected wpWatcherService:WorkPackageWatchersService,\n protected cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit():void {\n this\n .apiV3Service\n .work_packages\n .id(this.wpId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n ).subscribe((workPackage) => {\n this.wpWatcherService\n .require(workPackage)\n .then((watchers:HalResource[]) => {\n this.count = watchers.length;\n this.cdRef.detectChanges();\n });\n });\n }\n}\n"," 0\"\n [textContent]=\"count\">\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\n\nexport class QueryFilterInstanceResource extends HalResource {\n public filter:QueryFilterResource;\n public operator:QueryOperatorResource;\n public values:HalResource[]|string[];\n private memoizedCurrentSchemas:{ [key:string]:QueryFilterInstanceSchemaResource } = {};\n\n @InjectField(SchemaCacheService) schemaCache:SchemaCacheService;\n @InjectField(PathHelperService) pathHelper:PathHelperService;\n\n public $initialize(source:any) {\n super.$initialize(source);\n\n this.$links['schema'] = {\n href: this.pathHelper.api.v3.apiV3Base + '/queries/filter_instance_schemas/' + this.filter.idFromLink\n };\n }\n\n public get id():string {\n return this.filter.id;\n }\n\n public get name():string {\n return this.filter.name;\n }\n\n /**\n * Get the complete current schema.\n *\n * The filter instance's schema is made up of a static and a variable part.\n * The variable part depends on the currently selected operator.\n * Therefore, the schema differs based on the selected operator.\n */\n public get currentSchema():QueryFilterInstanceSchemaResource|null {\n if (!this.operator) {\n return null;\n }\n\n let key = this.operator.href!.toString();\n\n if (this.memoizedCurrentSchemas[key] === undefined) {\n try {\n this.memoizedCurrentSchemas[key] = this.schemaCache.of(this).resultingSchema(this.operator);\n } catch(e) {\n console.error(\"Failed to access filter schema\" + e);\n }\n }\n\n return this.memoizedCurrentSchemas[key];\n }\n\n public isCompletelyDefined() {\n return this.values.length || (this.currentSchema && !this.currentSchema.isValueRequired());\n }\n\n public findOperator(operatorSymbol:string):QueryOperatorResource|undefined {\n return _.find(this.schemaCache.of(this).availableOperators, (operator:QueryOperatorResource) => operator.id === operatorSymbol) as QueryOperatorResource|undefined;\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {BoardActionService} from \"core-app/modules/boards/board/board-actions/board-action.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class BoardActionsRegistryService {\n\n private mapping:{ [attribute:string]:BoardActionService } = {};\n\n public add(attribute:string, service:BoardActionService) {\n this.mapping[attribute] = service;\n }\n\n public available() {\n return _.map(this.mapping, (service:BoardActionService, attribute:string) => {\n return { attribute: attribute, text: service.localizedName, icon:'', description:'', image:''};\n });\n }\n\n public get(attribute:string):BoardActionService {\n if (this.mapping[attribute]) {\n return this.mapping[attribute];\n }\n\n throw(`No action service exists for ${attribute}`);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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 {Directive, OnDestroy} from \"@angular/core\";\nimport {Observable} from \"rxjs\";\n\n/**\n * Mixin function to provide access to observable and flags\n * whether this component has been destroyed.\n *\n * Use for rxjs with .pipe(this.untilDestroyed)\n */\n@Directive()\nexport class UntilDestroyedMixin extends OnDestroyMixin implements OnDestroy {\n public componentDestroyed = false;\n\n ngOnDestroy():void {\n this.componentDestroyed = true;\n super.ngOnDestroy();\n }\n\n /**\n * Helper function to access `untilComponentDestroyed`\n */\n protected untilDestroyed():(source:Observable) => Observable {\n return untilComponentDestroyed(this);\n }\n}","import {\n Component,\n Injector,\n OnInit,\n} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {QueryFilterResource} from \"core-app/modules/hal/resources/query-filter-resource\";\nimport {QueryOperatorResource} from \"core-app/modules/hal/resources/query-operator-resource\";\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Component({\n templateUrl: './wp-table-configuration-relation-selector.html',\n selector: 'wp-table-configuration-relation-selector'\n})\nexport class WpTableConfigurationRelationSelectorComponent implements OnInit {\n private relationFilterIds:string[] = [\n 'parent',\n 'precedes',\n 'follows',\n 'relates',\n 'duplicates',\n 'duplicated',\n 'blocks',\n 'blocked',\n 'partof',\n 'includes',\n 'requires',\n 'required'\n ];\n\n public availableRelationFilters:QueryFilterResource[] = [];\n public selectedRelationFilter:QueryFilterResource|undefined = undefined;\n\n public text = {\n filter_work_packages_by_relation_type: this.I18n.t('js.work_packages.table_configuration.relation_filters.filter_work_packages_by_relation_type'),\n please_select: this.I18n.t('js.placeholders.selection'),\n // We need to inverse the translation strings, as the filters's are named the other way around than what\n // a user knows from the relations tab:\n parent: this.I18n.t('js.relation_labels.children'),\n precedes: this.I18n.t('js.relation_labels.follows'),\n follows: this.I18n.t('js.relation_labels.precedes'),\n relates: this.I18n.t('js.relation_labels.relates'),\n duplicates: this.I18n.t('js.relation_labels.duplicated'),\n duplicated: this.I18n.t('js.relation_labels.duplicates'),\n blocks: this.I18n.t('js.relation_labels.blocked'),\n blocked: this.I18n.t('js.relation_labels.blocks'),\n requires: this.I18n.t('js.relation_labels.required'),\n required: this.I18n.t('js.relation_labels.requires'),\n partof: this.I18n.t('js.relation_labels.includes'),\n includes: this.I18n.t('js.relation_labels.partof')\n };\n\n constructor(readonly injector:Injector,\n readonly I18n:I18nService,\n readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly ConfigurationService:ConfigurationService,\n readonly schemaCache:SchemaCacheService) {\n }\n\n ngOnInit() {\n let self:WpTableConfigurationRelationSelectorComponent = this;\n\n this.wpTableFilters\n .onReady()\n .then(() => {\n self.availableRelationFilters = self.relationFiltersOf(self.wpTableFilters.availableFilters) as QueryFilterResource[];\n self.setSelectedRelationFilter();\n });\n }\n\n private setSelectedRelationFilter():void {\n let currentRelationFilters:QueryFilterInstanceResource[] = this.relationFiltersOf(this.wpTableFilters.current) as QueryFilterInstanceResource[];\n if (currentRelationFilters.length > 0) {\n this.selectedRelationFilter = _.find(this.availableRelationFilters, { id: currentRelationFilters[0].id }) as QueryFilterResource;\n } else {\n this.selectedRelationFilter = this.availableRelationFilters[0];\n }\n this.onRelationFilterSelected();\n }\n\n public onRelationFilterSelected() {\n if (this.selectedRelationFilter) {\n this.removeRelationFiltersFromCurrentState();\n this.addFilterToCurrentState(this.selectedRelationFilter as QueryFilterResource);\n }\n }\n\n private removeRelationFiltersFromCurrentState() {\n let filtersToRemove = this.relationFiltersOf(this.wpTableFilters.current) as QueryFilterInstanceResource[];\n this.wpTableFilters.remove(...filtersToRemove);\n }\n\n private relationFiltersOf(filters:QueryFilterResource[]|QueryFilterInstanceResource[]):QueryFilterResource[]|QueryFilterInstanceResource[] {\n return _.filter(filters, (filter:QueryFilterResource|QueryFilterInstanceResource) => _.includes(this.relationFilterIds, filter.id));\n }\n\n private addFilterToCurrentState(filter:QueryFilterResource):void {\n let newFilter = this.wpTableFilters.instantiate(filter);\n let operator:QueryOperatorResource = this.getOperatorForId(newFilter, '=');\n newFilter.operator = operator;\n newFilter.values = [{href: '/api/v3/work_packages/{id}'}] as HalResource[];\n\n this.wpTableFilters.add(newFilter);\n }\n\n private getOperatorForId(filter:QueryFilterResource, id:string):QueryOperatorResource {\n return _.find(this.schemaCache.of(filter).availableOperators, { 'id': id}) as QueryOperatorResource;\n }\n\n public compareRelationFilters(f1:undefined|QueryFilterResource, f2:undefined|QueryFilterResource):boolean {\n return f1 && f2 ? f1.id === f2.id : f1 === f2;\n }\n}\n","
    \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/apiv3/endpoints/queries/apiv3-query-order\";\n\nexport interface QueryResourceEmbedded {\n results:WorkPackageCollectionResource;\n columns:QueryColumn[];\n groupBy:QueryGroupByResource|undefined;\n project:ProjectResource;\n sortBy:QuerySortByResource[];\n filters:QueryFilterInstanceResource[];\n}\n\nexport type TimelineZoomLevel = 'days'|'weeks'|'months'|'quarters'|'years'|'auto';\n\nexport interface TimelineLabels {\n left:string|null;\n right:string|null;\n farRight:string|null;\n}\n\nexport class QueryResource extends HalResource {\n public $embedded:QueryResourceEmbedded;\n public results:WorkPackageCollectionResource;\n public columns:QueryColumn[];\n public groupBy:QueryGroupByResource|undefined;\n public sortBy:QuerySortByResource[];\n public filters:QueryFilterInstanceResource[];\n public starred:boolean;\n public sums:boolean;\n public hasError:boolean;\n public timelineVisible:boolean;\n public timelineZoomLevel:TimelineZoomLevel;\n public highlightingMode:HighlightingMode;\n public highlightedAttributes:HalResource[]|undefined;\n public displayRepresentation:string|undefined;\n public timelineLabels:TimelineLabels;\n public showHierarchies:boolean;\n public public:boolean;\n public hidden:boolean;\n public project:ProjectResource;\n public ordered_work_packages:QueryOrder;\n\n public $initialize(source:any) {\n super.$initialize(source);\n\n this.filters = this\n .filters\n .map((filter:Object) => new QueryFilterInstanceResource(\n this.injector,\n filter,\n true,\n this.halInitializer,\n 'QueryFilterInstance'\n )\n );\n }\n}\n\nexport interface QueryResourceLinks {\n updateImmediately?(attributes:any):Promise;\n}\n\nexport interface QueryResource extends QueryResourceLinks {\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 interface BoardWidgetOption {\n queryId:string;\n filters:ApiV3Filter[];\n}\n\nexport class Board {\n constructor(public grid:GridResource) {\n }\n\n public get id() {\n return this.grid.id;\n }\n\n public get name() {\n return this.grid.name;\n }\n\n public get editable() {\n return !!this.grid.updateImmediately;\n }\n\n public get isFree() {\n return !this.isAction;\n }\n\n public get isAction() {\n return this.grid.options.type === 'action';\n }\n\n public get actionAttribute():string|undefined {\n if (this.isFree) {\n return undefined;\n }\n\n return this.grid.options.attribute as string;\n }\n\n public set highlightingMode(val:CardHighlightingMode) {\n this.grid.options.highlightingMode = val;\n }\n\n public get highlightingMode():CardHighlightingMode {\n return (this.grid.options.highlightingMode || 'none') as CardHighlightingMode;\n }\n\n public set name(name:string) {\n this.grid.name = name;\n }\n\n public addQuery(widget:GridWidgetResource) {\n widget.isNewWidget = true;\n this.grid.widgets.push(widget);\n }\n\n public removeQuery(widget:GridWidgetResource) {\n this.grid.widgets = this.grid.widgets.filter(el => el.options.queryId !== widget.options.queryId);\n }\n\n public get queries():GridWidgetResource[] {\n return this.grid.widgets;\n }\n\n public get createdAt() {\n return this.grid.createdAt;\n }\n\n public get filters():ApiV3Filter[] {\n return (this.grid.options.filters || []) as ApiV3Filter[];\n }\n\n public set filters(filters:ApiV3Filter[]) {\n this.grid.options.filters = filters;\n }\n\n public sortWidgets() {\n this.grid.widgets = this.grid.widgets.sort((a, b) => {\n return a.startColumn - b.startColumn;\n });\n }\n\n public showStatusButton() {\n return this.actionAttribute !== 'status';\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {Observable} from \"rxjs\";\nimport {Apiv3GridForm} from \"core-app/modules/apiv3/endpoints/grids/apiv3-grid-form\";\n\nexport class Apiv3GridPaths extends APIv3GettableResource {\n // Static paths\n readonly form = this.subResource('form', Apiv3GridForm);\n\n /**\n * Update a grid resource or payload\n * @param resource\n * @param schema\n */\n public patch(resource:GridResource|Object, schema:SchemaResource|null = null):Observable {\n let payload = this.form.extractPayload(resource, schema);\n\n return this\n .halResourceService\n .patch(this.path, payload);\n }\n\n /**\n * Delete a grid resource\n */\n public delete():Observable {\n return this\n .halResourceService\n .delete(this.path);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {ApiV3FilterBuilder, FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {Observable} from \"rxjs\";\n\nexport interface Apiv3ListParameters {\n filters?:[string, FilterOperator, string[]][];\n sortBy?:[string, string][];\n pageSize?:number;\n}\n\nexport interface Apiv3ListResourceInterface {\n list(params:Apiv3ListParameters):Observable>;\n}\n\nexport function listParamsString(params?:Apiv3ListParameters):string {\n let queryProps = [];\n\n if (params && params.sortBy) {\n queryProps.push(`sortBy=${JSON.stringify(params.sortBy)}`);\n }\n\n // 0 should not be treated as false\n if (params && params.pageSize !== undefined) {\n queryProps.push(`pageSize=${params.pageSize}`);\n }\n\n if (params && params.filters) {\n let filters = new ApiV3FilterBuilder();\n\n params.filters.forEach((filterParam) => {\n filters.add(...filterParam);\n });\n\n queryProps.push(filters.toParams());\n }\n\n let queryPropsString = '';\n\n if (queryProps.length) {\n queryPropsString = `?${queryProps.join('&')}`;\n }\n\n return queryPropsString;\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {Apiv3GridPaths} from \"core-app/modules/apiv3/endpoints/grids/apiv3-grid-paths\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {Apiv3GridForm} from \"core-app/modules/apiv3/endpoints/grids/apiv3-grid-form\";\nimport {Observable} from \"rxjs\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface,\n listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\n\nexport class Apiv3GridsPaths\n extends APIv3ResourceCollection\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'grids', Apiv3GridPaths);\n }\n\n readonly form = this.subResource('form', Apiv3GridForm);\n\n /**\n * Load a list of grids with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n\n /**\n * Create a new GridResource\n *\n * @param resource\n * @param schema\n */\n public post(resource:GridResource, schema:SchemaResource|null = null):Observable {\n return this\n .halResourceService\n .post(\n this.path,\n this.form.extractPayload(resource, schema)\n );\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {States} from \"core-components/states.service\";\nimport {HasId, StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {concat, from, merge, Observable, of} from \"rxjs\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {mapTo, publish, share, shareReplay, switchMap, take, tap} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\nexport abstract class CachableAPIV3Resource\n extends APIv3GettableResource {\n @InjectField() states:States;\n @InjectField() schemaCache:SchemaCacheService;\n\n readonly cache = this.createCache();\n\n /**\n * Require the value to be loaded either when forced or the value is stale\n * according to the cache interval specified for this service.\n *\n * Returns an observable to the values stream of the state.\n *\n * @param force Load the value anyway.\n */\n public requireAndStream(force:boolean = false):Observable {\n const id = this.id.toString();\n\n // Refresh when stale or being forced\n if (this.cache.stale(id) || force) {\n const observable = this\n .load()\n .pipe(\n take(1),\n shareReplay(1)\n );\n\n this.cache.clearAndLoad(\n id,\n observable\n );\n\n // Return concat of the loading observable\n // for error handling and the like,\n // but then continue with the streamed cache\n return concat(\n observable,\n this.cache.state(id).values$()\n );\n }\n\n return this.cache.state(id).values$();\n }\n\n\n /**\n * Observe the values of this resource,\n * but do not request it actively.\n */\n public observe():Observable {\n return this\n .cache\n .observe(this.id.toString());\n }\n\n\n /**\n * Returns a (potentially cached) observable.\n *\n * Only observes one value.\n *\n * Accesses or modifies the global store for this resource.\n */\n get():Observable {\n return this\n .requireAndStream(false)\n .pipe(\n take(1)\n );\n }\n\n /**\n * Returns a freshly loaded value but ensuring the value\n * is also updated in the cache.\n *\n * Only observes one value.\n *\n * Accesses or modifies the global store for this resource.\n */\n refresh():Promise {\n return this\n .requireAndStream(true)\n .pipe(\n take(1),\n )\n // Use a promise to ensure this fires\n // even if caller isn't subscribing.\n .toPromise();\n }\n\n /**\n * Perform a request to the HalResourceService with the current path\n */\n protected load():Observable {\n return this\n .halResourceService\n .get(this.path)\n .pipe(\n switchMap((resource) => {\n if (resource.$links.schema) {\n return this.schemaCache\n .requireAndStream(resource.$links.schema.href)\n .pipe(\n take(1),\n mapTo(resource),\n );\n } else {\n return of(resource);\n }\n })\n ) as any; // T does not extend HalResource for virtual endpoints such as board, thus we need to cast here\n }\n\n /**\n * Update a single resource\n */\n protected touch(resource:T):void {\n this.cache.updateFor(resource);\n }\n\n /**\n * Inserts a collection response to cache as an rxjs tap function\n */\n protected cacheResponse():(source:Observable) => Observable {\n return (source$:Observable) => {\n return source$.pipe(\n tap(\n (resource:T) => this.touch(resource)\n )\n );\n };\n }\n\n /**\n * Creates the cache state instance\n */\n protected abstract createCache():StateCacheService;\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {MultiInputState} from \"reactivestates\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Observable} from \"rxjs\";\nimport {tap} from \"rxjs/operators\";\nimport {Apiv3TimeEntriesPaths} from \"core-app/modules/apiv3/endpoints/time-entries/apiv3-time-entries-paths\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\n\nexport class Apiv3TimeEntryPaths extends CachableAPIV3Resource {\n // Static paths\n readonly form = this.subResource('form', APIv3FormResource);\n\n /**\n * Update the time entry with the given payload.\n *\n * In case of updating from the hal resource, a schema resource is needed\n * to identify the writable attributes.\n * @param payload\n * @param schema\n */\n public patch(payload:Object, schema:SchemaResource|null = null):Observable {\n return this\n .halResourceService\n .patch(this.path, this.extractPayload(payload, schema))\n .pipe(\n tap(resource => this.touch(resource))\n );\n }\n\n /**\n * Delete the time entry under the current path\n */\n public delete():Observable {\n return this\n .halResourceService\n .delete(this.path)\n .pipe(\n tap(() => this.cache.clearSome(this.id.toString()))\n );\n }\n\n protected createCache():StateCacheService {\n return (this.parent as Apiv3TimeEntriesPaths).cache;\n }\n\n /**\n * Extract payload from the given request with schema.\n * This will ensure we will only write writable attributes and so on.\n *\n * @param resource\n * @param schema\n */\n protected extractPayload(resource:HalResource|Object|null, schema:SchemaResource|null = null) {\n if (resource instanceof HalResource && schema) {\n return HalPayloadHelper.extractPayloadFromSchema(resource, schema);\n } else if (!(resource instanceof HalResource)) {\n return resource;\n } else {\n return {};\n }\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {States} from \"core-components/states.service\";\nimport {HasId, StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {Observable} from \"rxjs\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {tap} from \"rxjs/operators\";\n\nexport abstract class CachableAPIV3Collection<\n T extends HasId = HalResource,\n V extends APIv3GettableResource = APIv3GettableResource,\n X extends StateCacheService = StateCacheService\n >\n extends APIv3ResourceCollection {\n @InjectField() states:States;\n\n readonly cache:X = this.createCache();\n\n /**\n * Observe all value changes of the cache\n */\n public observeAll():Observable {\n return this.cache.observeAll();\n }\n\n /**\n * Inserts a collection or single response to cache as an rxjs tap function\n */\n protected cacheResponse():(source:Observable) => Observable {\n return (source$) => {\n return source$.pipe(\n tap(\n (response:R) => {\n if (response instanceof CollectionResource) {\n response.elements.forEach(this.touch.bind(this));\n } else if (response instanceof HalResource) {\n this.touch(response as any);\n }\n }\n )\n );\n };\n }\n\n /**\n * Update a single resource\n */\n protected touch(resource:T):void {\n this.cache.updateFor(resource);\n }\n\n /**\n * Creates the cache state instance\n */\n protected abstract createCache():X;\n}\n","// -- copyright\n// OpenProject is 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 {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {States} from \"core-components/states.service\";\nimport {Injector} from \"@angular/core\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {MultiInputState} from \"reactivestates\";\n\nexport class TimeEntryCacheService extends StateCacheService {\n @InjectField() readonly states:States;\n @InjectField() readonly schemaCache:SchemaCacheService;\n\n constructor(readonly injector:Injector, state:MultiInputState) {\n super(state);\n }\n\n updateValue(id:string, val:TimeEntryResource):Promise {\n return this.schemaCache\n .ensureLoaded(val)\n .then(() => {\n this.putValue(id, val);\n return val;\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\n\nimport {Apiv3TimeEntryPaths} from \"core-app/modules/apiv3/endpoints/time-entries/apiv3-time-entry-paths\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {Observable} from \"rxjs\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {MultiInputState} from \"reactivestates\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface,\n listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {TimeEntryCacheService} from \"core-app/modules/apiv3/endpoints/time-entries/time-entry-cache.service\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class Apiv3TimeEntriesPaths\n extends CachableAPIV3Collection\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'time_entries', Apiv3TimeEntryPaths);\n }\n\n // Static paths\n public readonly form = this.subResource('form', APIv3FormResource);\n\n /**\n * Load a list of time entries with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params))\n .pipe(\n this.cacheResponse()\n );\n }\n\n /**\n * Create a time entry resource from the given payload\n * @param payload\n */\n public post(payload:Object):Observable {\n return this\n .halResourceService\n .post(this.path, payload)\n .pipe(\n this.cacheResponse()\n );\n }\n\n protected createCache():StateCacheService {\n return new TimeEntryCacheService(this.injector, this.states.timeEntries);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {buildApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {Observable} from \"rxjs\";\nimport {map} from \"rxjs/operators\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface, listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\n\nexport class Apiv3AvailableProjectsPaths\n extends APIv3GettableResource>\n implements Apiv3ListResourceInterface {\n\n /**\n * Load a list of available projects with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n\n /**\n * Performs a request against the available_projects endpoint\n * to see whether this is contained\n *\n * Returns whether the given id exists in the set\n * of available projects\n *\n * @param projectId\n */\n public exists(projectId:string):Observable {\n return this\n .halResourceService\n .get>(\n this.path,\n { filters: buildApiV3Filter('id', '=', [projectId]).toJson() }\n )\n .pipe(\n map(collection => collection.count > 0)\n );\n }\n\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3AvailableProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-available-projects-paths\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface, listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {Observable} from \"rxjs\";\nimport {MembershipResource} from \"core-app/modules/hal/resources/membership-resource\";\n\nexport class Apiv3MembershipsPaths\n extends APIv3ResourceCollection>\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'memberships');\n }\n\n /**\n * Load a list of membership entries with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n\n\n // /api/v3/memberships/available_projects\n readonly available_projects = this.subResource('available_projects', Apiv3AvailableProjectsPaths);\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {MultiInputState} from \"reactivestates\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIv3UserPaths extends CachableAPIV3Resource {\n\n readonly avatar = this.subResource('avatar');\n\n protected createCache():StateCacheService {\n return new StateCacheService(this.states.users);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {APIv3UserPaths} from \"core-app/modules/apiv3/endpoints/users/apiv3-user-paths\";\nimport {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class Apiv3UsersPaths extends APIv3ResourceCollection {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'users', APIv3UserPaths);\n }\n\n // Static paths\n\n // /api/v3/users/me\n public readonly me = this.path + '/me';\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {TypeResource} from \"core-app/modules/hal/resources/type-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {APIv3TypesPaths} from \"core-app/modules/apiv3/endpoints/types/apiv3-types-paths\";\n\nexport class APIv3TypePaths extends CachableAPIV3Resource {\n\n protected createCache():StateCacheService {\n return (this.parent as APIv3TypesPaths).cache;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {TypeResource} from \"core-app/modules/hal/resources/type-resource\";\nimport {APIv3TypePaths} from \"core-app/modules/apiv3/endpoints/types/apiv3-type-paths\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIv3TypesPaths extends CachableAPIV3Collection {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'types', APIv3TypePaths);\n }\n\n protected createCache():StateCacheService {\n return new StateCacheService(this.states.types);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injector} from \"@angular/core\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {HttpClient} from \"@angular/common/http\";\nimport {SimpleResource} from \"core-app/modules/apiv3/paths/path-resources\";\n\nexport type QueryOrder = { [wpId:string]:number };\n\nexport class APIV3QueryOrder extends SimpleResource {\n @InjectField() http:HttpClient;\n\n constructor(readonly injector:Injector,\n readonly basePath:string,\n readonly id:string|number) {\n super(basePath, id);\n }\n\n public get():Promise {\n return this.http\n .get(\n this.path\n )\n .toPromise()\n .then(result => result || {});\n }\n\n public update(delta:QueryOrder):Promise {\n return this.http\n .patch(\n this.path,\n { delta: delta },\n { withCredentials: true }\n )\n .toPromise()\n .then((response:{t:string}) => response.t);\n }\n\n public delete(id:string, ...wpIds:string[]) {\n let delta:QueryOrder = {};\n wpIds.forEach(id => delta[id] = -1);\n\n return this.update(delta);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {Observable} from \"rxjs\";\nimport * as URI from \"urijs\";\nimport {map, tap} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {QueryFiltersService} from \"core-components/wp-query/query-filters.service\";\n\nexport class Apiv3QueryForm extends APIv3FormResource {\n @InjectField() private queryFilters:QueryFiltersService;\n\n /**\n * Load the query form for the given existing (or new) query resource\n * @param query\n */\n public load(query:QueryResource):Observable<[QueryFormResource, QueryResource]> {\n // We need a valid payload so that we\n // can check whether form saving is possible.\n // The query needs a name to be valid.\n let payload:any = {\n 'name': query.name || '!!!__O__o__O__!!!'\n };\n\n if (query.project) {\n payload['_links'] = {\n 'project': {\n 'href': query.project.$href\n }\n };\n }\n\n let path = this.apiRoot.queries.withOptionalId(query.id).form.path;\n return this.halResourceService\n .post(path, payload)\n .pipe(\n tap(form => this.queryFilters.setSchemas(form.$embedded.schema.$embedded.filtersSchemas)),\n map(form => [form, this.buildQueryResource(form)])\n );\n }\n\n /**\n * Load the query form only with the given query props.\n *\n * @param params\n * @param queryId\n * @param projectIdentifier\n * @param payload\n */\n public loadWithParams(params:{[key:string]:unknown}, queryId:string|undefined, projectIdentifier:string|undefined|null, payload:any = {}):Observable<[QueryFormResource, QueryResource]> {\n // We need a valid payload so that we\n // can check whether form saving is possible.\n // The query needs a name to be valid.\n if (!queryId && !payload.name) {\n payload.name = '!!!__O__o__O__!!!';\n }\n\n if (projectIdentifier) {\n payload._links = payload._links || {};\n payload._links.project = {\n 'href': this.apiRoot.projects.id(projectIdentifier).toString()\n };\n\n }\n\n let path = this.apiRoot.queries.withOptionalId(queryId).form.path;\n const href = URI(path).search(params).toString();\n return this.halResourceService\n .post(href, payload)\n .pipe(\n tap(form => this.queryFilters.setSchemas(form.$embedded.schema.$embedded.filtersSchemas)),\n map(form => [form, this.buildQueryResource(form)])\n );\n }\n\n protected buildQueryResource(form:QueryFormResource):QueryResource {\n return this.halResourceService.createHalResourceOfType('Query', form.payload);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {APIV3QueryOrder} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-order\";\nimport {Apiv3QueryForm} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-form\";\nimport {Observable} from \"rxjs\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {QueryFiltersService} from \"core-components/wp-query/query-filters.service\";\nimport {PaginationObject} from \"core-components/table-pagination/pagination-service\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\n\nexport class APIv3QueryPaths extends APIv3GettableResource {\n @InjectField() private queryFilters:QueryFiltersService;\n\n // Static paths\n readonly form = this.subResource('form', Apiv3QueryForm);\n\n // Order path\n readonly order = new APIV3QueryOrder(this.injector, this.path, 'order');\n\n /**\n * Stream the response for the given query request\n * @param queryData\n */\n public parameterised(params:Object):Observable {\n return this.halResourceService\n .get(this.path, params);\n }\n\n /**\n * Update the given query\n * @param query\n * @param form\n */\n public patch(payload:QueryResource|Object, form?:QueryFormResource):Observable {\n if (payload instanceof QueryResource && form) {\n // Extracting requires having the filter schemas loaded as the dependencies\n this.queryFilters.mapSchemasIntoFilters(payload, form);\n payload = HalPayloadHelper.extractPayloadFromSchema(payload, form.schema);\n }\n\n return this\n .halResourceService\n .patch(this.path, payload);\n }\n\n /**\n * Delete the query\n */\n public delete() {\n return this\n .halResourceService\n .delete(this.path);\n }\n\n /**\n * Reload with a given pagination\n * @param pagination\n */\n public paginated(pagination:PaginationObject):Observable {\n return this.parameterised(pagination);\n }\n\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {APIv3QueryPaths} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-paths\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3QueryForm} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-form\";\nimport {Observable} from \"rxjs\";\nimport {QueryFormResource} from \"core-app/modules/hal/resources/query-form-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {Apiv3ListParameters, listParamsString} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {QueryFiltersService} from \"core-components/wp-query/query-filters.service\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\n\nexport class APIv3QueriesPaths extends APIv3ResourceCollection {\n @InjectField() private queryFilters:QueryFiltersService;\n\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'queries', APIv3QueryPaths);\n }\n\n // Static paths\n // /api/v3/queries/form\n readonly form = this.subResource('form', Apiv3QueryForm);\n\n // /api/v3/queries/default\n readonly default = this.subResource>('default');\n\n // /api/v3/queries/filter_instance_schemas/:id\n readonly filter_instance_schemas = new APIv3ResourceCollection(this.apiRoot, this.path, 'filter_instance_schemas');\n\n /**\n * Load a list of queries with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n\n /**\n * Locate a query for the response for the given query request.\n * This might be the default query or an existing query identified by its ID.\n * @param queryData\n * @param queryId\n * @param projectIdentifier\n */\n public find(queryData:Object, queryId?:string, projectIdentifier?:string|null|undefined):Observable {\n let path:string;\n\n if (queryId) {\n path = this.apiRoot.queries.id(queryId).toString();\n } else {\n path = this.apiRoot.withOptionalProject(projectIdentifier).queries.default.toString();\n }\n\n return this\n .halResourceService\n .get(path, queryData);\n }\n\n\n /**\n * Stream the response for the given query request\n *\n * @param params\n */\n public parameterised(params:Object):Observable {\n return this.halResourceService\n .get(\n this.default.path,\n params\n );\n }\n\n /**\n * Create a new query resource\n *\n * @param payload Payload object or query HAL resource\n * @param form Form resource, needed when QueryResource is passed\n */\n public post(payload:QueryResource|Object, form?:QueryFormResource):Observable {\n if (payload instanceof QueryResource && form) {\n // Extracting requires having the filter schemas loaded as the dependencies\n this.queryFilters.mapSchemasIntoFilters(payload, form);\n payload = HalPayloadHelper.extractPayloadFromSchema(payload, form.schema);\n }\n\n return this\n .halResourceService\n .post(\n this.apiRoot.queries.path, payload\n );\n }\n\n /**\n * Invert the starred state of the given query\n *\n * @param query\n */\n public toggleStarred(query:QueryResource):Promise {\n if (query.starred) {\n return query.unstar();\n } else {\n return query.star();\n }\n }\n\n /**\n * Filter for non-hidden queries\n *\n * @param projectIdentifier\n */\n public filterNonHidden(projectIdentifier?:string|null):Observable> {\n let listParams:Apiv3ListParameters = {\n filters: [['hidden', '=', ['f']]]\n };\n\n if (projectIdentifier) {\n // all queries with the provided projectIdentifier\n listParams.filters!.push(['project_identifier', '=', [projectIdentifier]]);\n } else {\n // all queries having no project (i.e. being global)\n listParams.filters!.push(['project', '!*', []]);\n }\n\n return this.list(listParams);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {from, NEVER, Observable} from \"rxjs\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {Apiv3AvailableProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-available-projects-paths\";\nimport {APIv3VersionPaths} from \"core-app/modules/apiv3/endpoints/versions/apiv3-version-paths\";\nimport {RelationResource} from \"core-app/modules/hal/resources/relation-resource\";\nimport {buildApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {map} from \"rxjs/operators\";\n\nexport class Apiv3RelationsPaths extends APIv3ResourceCollection> {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'relations');\n }\n\n /**\n * Get all versions\n */\n public get():Observable> {\n return this\n .halResourceService\n .get>(this.path);\n }\n\n public loadInvolved(workPackageIds:string[]):Observable {\n let validIds = _.filter(workPackageIds, id => /\\d+/.test(id));\n\n if (validIds.length === 0) {\n return from([]);\n }\n\n return this\n .filtered(buildApiV3Filter('involved', '=', validIds))\n .get()\n .pipe(\n map(collection => collection.elements)\n );\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource, APIv3ResourcePath} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {Apiv3RelationsPaths} from \"core-app/modules/apiv3/endpoints/relations/apiv3-relations-paths\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {Observable} from \"rxjs\";\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {APIV3WorkPackagesPaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIV3WorkPackagePaths extends CachableAPIV3Resource {\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/relations\n public readonly relations = this.subResource('relations', Apiv3RelationsPaths);\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/revisions\n public readonly revisions = this.subResource('revisions');\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/activities\n public readonly activities = this.subResource('activities');\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/available_watchers\n public readonly available_watchers = this.subResource('available_watchers');\n\n // /api/v3/(?:projectPath)/work_packages/(:workPackageId)/available_projects\n public readonly available_projects = this.subResource('available_projects');\n\n protected createCache():StateCacheService {\n return (this.parent as APIV3WorkPackagesPaths).cache;\n }\n}\n","import {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {Observable} from \"rxjs\";\nimport {HalSource} from \"core-app/modules/hal/resources/hal-resource\";\n\nexport class APIv3WorkPackageForm extends APIv3FormResource {\n /**\n * Returns a promise to post `/api/v3/work_packages/form` with only the type part of the\n * provided payload being sent to the backend.\n *\n * @param payload: The payload to be sent to the backend\n * @returns A work package form resource prefilled with the provided payload.\n */\n public forTypePayload(payload:HalSource):Observable {\n let typePayload = payload._links['type'] ? { _links: { type: payload['_links']['type'] } } : { _links: {} } ;\n\n return this.post(payload);\n }\n /**\n * Returns a promise to post `/api/v3/work_packages/form` where the\n * payload sent to the backend has been provided.\n *\n * @param payload: The payload to be sent to the backend\n * @returns A work package form resource prefilled with the provided payload.\n */\n public forPayload(payload:HalSource):Observable {\n return this.post(payload);\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {MultiInputState} from 'reactivestates';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Injectable, Injector} from '@angular/core';\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Injectable()\nexport class WorkPackageCache extends StateCacheService {\n @InjectField() private schemaCacheService:SchemaCacheService;\n\n constructor(readonly injector:Injector,\n state:MultiInputState) {\n super(state);\n }\n\n updateValue(id:string, val:WorkPackageResource):Promise {\n return this.schemaCacheService.ensureLoaded(val).then(() => {\n this.putValue(id, val);\n return val;\n });\n }\n\n updateWorkPackage(wp:WorkPackageResource, immediate:boolean = false):Promise {\n if (immediate || wp.isNew) {\n return super.updateValue(wp.id!, wp);\n } else {\n return this.updateValue(wp.id!, wp);\n }\n }\n\n updateWorkPackageList(list:WorkPackageResource[], skipOnIdentical = true) {\n for (var i of list) {\n const wp = i;\n const workPackageId = wp.id!;\n const state = this.multiState.get(workPackageId);\n\n // If the work package is new, ignore the schema\n if (wp.isNew) {\n state.putValue(wp);\n continue;\n }\n\n // Ensure the schema is loaded\n // so that no consumer needs to call schema#$load manually\n this.schemaCacheService.ensureLoaded(wp).then(() => {\n // Check if the work package has changed\n if (skipOnIdentical && state.hasValue() && _.isEqual(state.value!.$source, wp.$source)) {\n debugLog('Skipping identical work package from updating');\n return;\n }\n\n state.putValue(wp);\n });\n }\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {Observable} from \"rxjs\";\nimport {APIV3WorkPackagesPaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths\";\nimport {take, tap} from \"rxjs/operators\";\nimport {WorkPackageCache} from \"core-app/modules/apiv3/endpoints/work_packages/work-package.cache\";\n\nexport class ApiV3WorkPackageCachedSubresource extends APIv3GettableResource {\n\n public get():Observable {\n return this\n .halResourceService\n .get(this.path)\n .pipe(\n tap(collection => this.cache.updateWorkPackageList(collection.elements)),\n take(1)\n );\n }\n\n protected get cache():WorkPackageCache {\n return (this.parent as APIV3WorkPackagesPaths).cache;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIV3WorkPackagePaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-package-paths\";\nimport {ApiV3FilterBuilder, buildApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {Observable} from \"rxjs\";\nimport {APIv3WorkPackageForm} from \"core-app/modules/apiv3/endpoints/work_packages/apiv3-work-package-form\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {WorkPackageCache} from \"core-app/modules/apiv3/endpoints/work_packages/work-package.cache\";\nimport {APIv3GettableResource} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {ApiV3WorkPackageCachedSubresource} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-package-cached-subresource\";\n\nexport class APIV3WorkPackagesPaths extends CachableAPIV3Collection {\n // Base path\n public readonly path:string;\n\n constructor(readonly apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'work_packages', APIV3WorkPackagePaths);\n }\n\n // Static paths\n\n // /api/v3/(projects/:projectIdentifier)/work_packages/form\n public readonly form:APIv3WorkPackageForm = this.subResource('form', APIv3WorkPackageForm);\n\n /**\n *\n * Load a collection of work packages and put them all into cache\n *\n * @param ids\n */\n public requireAll(ids:string[]):Promise {\n return new Promise((resolve, reject) => {\n this\n .loadCollectionsFor(_.uniq(ids))\n .then((pagedResults:WorkPackageCollectionResource[]) => {\n _.each(pagedResults, (results) => {\n if (results.schemas) {\n _.each(results.schemas.elements, (schema:SchemaResource) => {\n this.states.schemas.get(schema.href as string).putValue(schema);\n });\n }\n\n if (results.elements) {\n this.cache.updateWorkPackageList(results.elements);\n }\n\n });\n\n resolve(undefined);\n }, reject);\n });\n }\n\n /**\n * Create a work package from a form payload\n *\n * @param payload\n * @return {Promise}\n */\n public post(payload:Object):Observable {\n return this\n .halResourceService\n .post(this.path, payload)\n .pipe(\n this.cacheResponse()\n );\n }\n\n filtered>(filters:ApiV3FilterBuilder, params:{ [p:string]:string } = {}):R {\n return super.filtered(filters, params, ApiV3WorkPackageCachedSubresource) as any;\n }\n\n /**\n * Shortcut to filter work packages by subject or ID\n * @param term\n * @param idOnly\n * @param additionalParams Additional set of params to the API\n */\n public filterBySubjectOrId(term:string, idOnly:boolean = false, additionalParams:{ [key:string]:string } = {}):ApiV3WorkPackageCachedSubresource {\n let filters:ApiV3FilterBuilder = new ApiV3FilterBuilder();\n\n if (idOnly) {\n filters.add('id', '=', [term]);\n } else {\n filters.add('subjectOrId', '**', [term]);\n }\n\n let params = {\n sortBy: '[[\"updatedAt\",\"desc\"]]',\n offset: '1',\n pageSize: '10',\n ...additionalParams\n };\n\n return this.filtered(filters, params);\n }\n\n /**\n * Returns work packages within the ids array to be updated since \n * @param ids work package IDs to filter for\n * @param timestamp The timestamp to clip at\n */\n public filterUpdatedSince(ids:(string|null)[], timestamp:unknown):ApiV3WorkPackageCachedSubresource {\n let filters = new ApiV3FilterBuilder()\n .add('id', '=', ids.filter((n:String|null) => n)) // no null values\n .add('updatedAt', '<>d', [timestamp, '']);\n\n let params = {\n offset: '1',\n pageSize: '10'\n };\n\n return this.filtered(filters, params);\n }\n\n /**\n * Loads the work packages collection for the given work package IDs.\n * Returns a WP Collection with schemas and results embedded.\n *\n * @param ids\n * @return {WorkPackageCollectionResource[]}\n */\n protected loadCollectionsFor(ids:string[]):Promise {\n return this\n .halResourceService\n .getAllPaginated(\n this.path,\n ids.length,\n {\n filters: buildApiV3Filter('id', '=', ids).toJson(),\n }\n );\n }\n\n protected createCache():WorkPackageCache {\n return new WorkPackageCache(this.injector, this.states.workPackages);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {Observable} from \"rxjs\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {MultiInputState} from \"reactivestates\";\nimport {tap} from \"rxjs/operators\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIv3VersionPaths extends CachableAPIV3Resource {\n\n /**\n * Update a version resource with the given payload\n *\n * @param resource\n * @param payload\n */\n public patch(payload:Object):Observable {\n return this\n .halResourceService\n .patch(\n this.path,\n payload\n )\n .pipe(\n tap(version => this.touch(version))\n );\n }\n\n protected createCache():StateCacheService {\n return new StateCacheService(this.states.versions);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {Observable} from \"rxjs\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {Apiv3AvailableProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-available-projects-paths\";\nimport {APIv3VersionPaths} from \"core-app/modules/apiv3/endpoints/versions/apiv3-version-paths\";\n\nexport class APIv3VersionsPaths extends APIv3ResourceCollection {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'versions', APIv3VersionPaths);\n }\n\n // /api/v3/versions/form\n public readonly form = this.subResource('form', APIv3FormResource);\n\n public readonly available_projects = this.subResource('available_projects', Apiv3AvailableProjectsPaths);\n\n /**\n * Get all versions\n */\n public get():Observable> {\n return this\n .halResourceService\n .get>(this.path);\n }\n\n /**\n * Create a version from the given payload\n *\n * @param payload\n * @return {Promise}\n */\n public post(payload:Object):Observable {\n return this\n .halResourceService\n .post(this.path, payload);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3QueriesPaths} from \"core-app/modules/apiv3/endpoints/queries/apiv3-queries-paths\";\nimport {APIv3TypesPaths} from \"core-app/modules/apiv3/endpoints/types/apiv3-types-paths\";\nimport {APIV3WorkPackagesPaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {MultiInputState} from \"reactivestates\";\nimport {APIv3VersionsPaths} from \"core-app/modules/apiv3/endpoints/versions/apiv3-versions-paths\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {APIv3ProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-projects-paths\";\n\nexport class APIv3ProjectPaths extends CachableAPIV3Resource {\n // /api/v3/projects/:project_id/available_assignees\n public readonly available_assignees = this.subResource('available_assignees');\n\n // /api/v3/projects/:project_id/queries\n public readonly queries = new APIv3QueriesPaths(this.apiRoot, this.path);\n\n // /api/v3/projects/:project_id/types\n public readonly types = new APIv3TypesPaths(this.apiRoot, this.path);\n\n // /api/v3/projects/:project_id/work_packages\n public readonly work_packages = new APIV3WorkPackagesPaths(this.apiRoot, this.path);\n\n // /api/v3/projects/:project_id/versions\n public readonly versions = new APIv3VersionsPaths(this.apiRoot, this.path);\n\n protected createCache():StateCacheService {\n return (this.parent as APIv3ProjectsPaths).cache;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {MultiInputState} from 'reactivestates';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {Injectable, Injector} from '@angular/core';\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\n\n@Injectable()\nexport class ProjectCache extends StateCacheService {\n @InjectField() private schemaCacheService:SchemaCacheService;\n\n constructor(readonly injector:Injector,\n state:MultiInputState) {\n super(state);\n }\n\n updateValue(id:string, val:ProjectResource):Promise {\n return this.schemaCacheService.ensureLoaded(val).then(() => {\n this.putValue(id, val);\n return val;\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3ProjectPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-project-paths\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface,\n listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {Observable} from \"rxjs\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {ProjectCache} from \"core-app/modules/apiv3/endpoints/projects/project.cache\";\n\nexport class APIv3ProjectsPaths\n extends CachableAPIV3Collection\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'projects', APIv3ProjectPaths);\n }\n\n // /api/v3/projects/schema\n public readonly schema = this.subResource('schema');\n\n /**\n * Load a list of project with a given list parameter filter\n *\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params))\n .pipe(\n this.cacheResponse()\n );\n }\n\n protected createCache():StateCacheService {\n return new ProjectCache(this.injector, this.states.projects);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {StatusResource} from \"core-app/modules/hal/resources/status-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class APIv3StatusPaths extends CachableAPIV3Resource {\n\n protected createCache():StateCacheService {\n return new StateCacheService(this.states.statuses);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3ResourceCollection, APIv3ResourcePath} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {Injector} from \"@angular/core\";\nimport {StatusResource} from \"core-app/modules/hal/resources/status-resource\";\nimport {APIv3StatusPaths} from \"core-app/modules/apiv3/endpoints/statuses/apiv3-status-paths\";\nimport {Observable} from \"rxjs\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {tap} from \"rxjs/operators\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class APIv3StatusesPaths extends APIv3ResourceCollection {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'statuses', APIv3StatusPaths);\n }\n\n /**\n * Perform a request to the HalResourceService with the current path\n */\n public get():Observable> {\n return this\n .halResourceService\n .get>(this.path)\n .pipe(\n tap(collection => {\n collection.elements.forEach((resource, id) => {\n this.id(resource.id!).cache.updateValue(resource.id!, resource);\n });\n })\n );\n }\n\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {\n Apiv3ListParameters,\n Apiv3ListResourceInterface,\n listParamsString\n} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {NewsResource} from \"core-app/modules/hal/resources/news-resource\";\n\nexport class Apiv3NewsPaths\n extends APIv3ResourceCollection>\n implements Apiv3ListResourceInterface {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'news');\n }\n\n /**\n * Load a list of time entries with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable> {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params));\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {HelpTextResource} from \"core-app/modules/hal/resources/help-text-resource\";\n\nexport class Apiv3HelpTextsPaths\n extends APIv3ResourceCollection> {\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'help_texts');\n }\n\n /**\n * Load a list of membership entries with a given list parameter filter\n * @param params\n */\n public get():Observable> {\n return this\n .halResourceService\n .get>(this.path);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3GettableResource, APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {ConfigurationResource} from \"core-app/modules/hal/resources/configuration-resource\";\nimport {Observable} from \"rxjs\";\nimport {shareReplay} from \"rxjs/operators\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class Apiv3ConfigurationPath extends APIv3GettableResource {\n private $configuration:Observable;\n\n constructor(protected apiRoot:APIV3Service,\n readonly basePath:string) {\n super(apiRoot, basePath, 'configuration');\n }\n\n\n\n public get():Observable {\n if (this.$configuration) {\n return this.$configuration;\n }\n\n return this.$configuration = this.halResourceService\n .get(this.path)\n .pipe(\n shareReplay()\n );\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Board} from \"core-app/modules/boards/board/board\";\nimport {Observable} from \"rxjs\";\nimport {map, switchMap, tap} from \"rxjs/operators\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {CachableAPIV3Resource} from \"core-app/modules/apiv3/cache/cachable-apiv3-resource\";\nimport {MultiInputState} from \"reactivestates\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {Apiv3BoardsPaths} from \"core-app/modules/apiv3/virtual/apiv3-boards-paths\";\n\nexport class APIv3BoardPath extends CachableAPIV3Resource {\n\n /**\n * Perform a request to the HalResourceService with the current path\n */\n protected load():Observable {\n return this\n .apiRoot\n .grids\n .id(this.id)\n .get()\n .pipe(\n map(grid => {\n const newBoard = new Board(grid);\n\n newBoard.sortWidgets();\n\n return newBoard;\n })\n );\n }\n\n /**\n * Save the changes to the board\n */\n public save(board:Board):Observable {\n return this\n .fetchSchema(board)\n .pipe(\n switchMap((schema:SchemaResource) => this\n .apiRoot\n .grids\n .id(board.grid)\n .patch(board.grid, schema)\n ),\n map(grid => {\n board.grid = grid;\n board.sortWidgets();\n return board;\n }),\n this.cacheResponse()\n );\n }\n\n public delete():Observable {\n return this\n .apiRoot\n .grids\n .id(this.id)\n .delete()\n .pipe(\n tap(() => this.cache.clearSome(this.id.toString()))\n );\n }\n\n private fetchSchema(board:Board):Observable {\n return this\n .apiRoot\n .grids\n .id(board.grid)\n .form\n .post({})\n .pipe(\n map(form => form.schema)\n );\n }\n\n protected createCache():StateCacheService {\n return (this.parent as Apiv3BoardsPaths).cache;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Constructor} from \"@angular/cdk/table\";\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {Apiv3ListParameters, listParamsString} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\nimport {Board, BoardType} from \"core-app/modules/boards/board/board\";\nimport {map, switchMap, tap} from \"rxjs/operators\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {CachableAPIV3Collection} from \"core-app/modules/apiv3/cache/cachable-apiv3-collection\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {MultiInputState} from \"reactivestates\";\nimport {APIv3BoardPath} from \"core-app/modules/apiv3/virtual/apiv3-board-path\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nexport class Apiv3BoardsPaths extends CachableAPIV3Collection {\n\n @InjectField() private authorisationService:AuthorisationService;\n @InjectField() private PathHelper:PathHelperService;\n\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string) {\n super(apiRoot, basePath, 'grids', APIv3BoardPath);\n }\n\n /**\n * Load a list of grids with a given list parameter filter\n * @param params\n */\n public list(params?:Apiv3ListParameters):Observable {\n return this\n .halResourceService\n .get>(this.path + listParamsString(params))\n .pipe(\n tap(collection => this.authorisationService.initModelAuth('boards', collection.$links)),\n map(collection =>\n collection.elements.map(grid => {\n let board = new Board(grid);\n board.sortWidgets();\n this.touch(board);\n\n return board;\n })\n )\n );\n }\n\n /**\n * Return all boards in the current scope of the project\n *\n * @param projectIdentifier\n */\n public allInScope(projectIdentifier:string):Observable {\n const path = this.boardPath(projectIdentifier);\n return this.list({ filters: [['scope', '=', [path]]] });\n }\n\n /**\n * Create a new board\n * @param type\n * @param name\n * @param projectIdentifier\n */\n public create(type:BoardType, name:string, projectIdentifier:string, actionAttribute?:string):Observable {\n const scope = this.boardPath(projectIdentifier);\n return this\n .createGrid(type, name, scope, actionAttribute)\n .pipe(\n map(grid => new Board(grid))\n );\n }\n\n /**\n * Retrieve the board path identifier for looking up grids.\n *\n * @param projectIdentifier The current project identifier\n */\n public boardPath(projectIdentifier:string) {\n return this.PathHelper.projectBoardsPath(projectIdentifier);\n }\n\n protected createCache():StateCacheService {\n let state = this.states.forType('boards');\n return new StateCacheService(state);\n }\n\n private createGrid(type:BoardType, name:string, scope:string, actionAttribute?:string):Observable {\n let payload:any = _.set({ name: name }, '_links.scope.href', scope);\n payload.options = {\n type: type,\n };\n\n if (actionAttribute) {\n payload.options.attribute = actionAttribute;\n }\n\n return this\n .apiRoot\n .grids\n .form\n .post(payload)\n .pipe(\n switchMap((form) => {\n return this\n .apiRoot\n .grids\n .post(form.payload.$source);\n })\n );\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injectable, Injector} from \"@angular/core\";\nimport {\n APIv3GettableResource,\n APIv3ResourceCollection,\n APIv3ResourcePath\n} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {Constructor} from \"@angular/cdk/table\";\nimport {Apiv3GridsPaths} from \"core-app/modules/apiv3/endpoints/grids/apiv3-grids-paths\";\nimport {Apiv3TimeEntriesPaths} from \"core-app/modules/apiv3/endpoints/time-entries/apiv3-time-entries-paths\";\nimport {Apiv3MembershipsPaths} from \"core-app/modules/apiv3/endpoints/memberships/apiv3-memberships-paths\";\nimport {Apiv3UsersPaths} from \"core-app/modules/apiv3/endpoints/users/apiv3-users-paths\";\nimport {APIv3TypesPaths} from \"core-app/modules/apiv3/endpoints/types/apiv3-types-paths\";\nimport {APIv3QueriesPaths} from \"core-app/modules/apiv3/endpoints/queries/apiv3-queries-paths\";\nimport {APIv3ProjectsPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-projects-paths\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {APIV3WorkPackagesPaths} from \"core-app/modules/apiv3/endpoints/work_packages/api-v3-work-packages-paths\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIv3ProjectPaths} from \"core-app/modules/apiv3/endpoints/projects/apiv3-project-paths\";\nimport {RootResource} from \"core-app/modules/hal/resources/root-resource\";\nimport {APIv3StatusesPaths} from \"core-app/modules/apiv3/endpoints/statuses/apiv3-statuses-paths\";\nimport {APIv3VersionsPaths} from \"core-app/modules/apiv3/endpoints/versions/apiv3-versions-paths\";\nimport {Apiv3RelationsPaths} from \"core-app/modules/apiv3/endpoints/relations/apiv3-relations-paths\";\nimport {Apiv3NewsPaths} from \"core-app/modules/apiv3/endpoints/news/apiv3-news-paths\";\nimport {Apiv3HelpTextsPaths} from \"core-app/modules/apiv3/endpoints/help_texts/apiv3-help-texts-paths\";\nimport {Apiv3ConfigurationPath} from \"core-app/modules/apiv3/endpoints/configuration/apiv3-configuration-path\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport * as ts from \"typescript/lib/tsserverlibrary\";\nimport Project = ts.server.Project;\nimport {Apiv3BoardsPaths} from \"core-app/modules/apiv3/virtual/apiv3-boards-paths\";\n\n@Injectable({ providedIn: 'root' })\nexport class APIV3Service {\n // /api/v3/attachments\n public readonly attachments = this.apiV3CollectionEndpoint('attachments');\n\n // /api/v3/configuration\n public readonly configuration = this.apiV3CustomEndpoint(Apiv3ConfigurationPath);\n\n // /api/v3/documents\n public readonly documents = this.apiV3CollectionEndpoint('documents');\n\n // /api/v3/grids\n public readonly grids = this.apiV3CustomEndpoint(Apiv3GridsPaths);\n\n // /api/v3/groups\n public readonly groups = this.apiV3CollectionEndpoint('groups');\n\n // /api/v3/root\n public readonly root = this.apiV3SingularEndpoint('');\n\n // /api/v3/statuses\n public readonly statuses = this.apiV3CustomEndpoint(APIv3StatusesPaths);\n\n // /api/v3/relations\n public readonly relations = this.apiV3CustomEndpoint(Apiv3RelationsPaths);\n\n // /api/v3/priorities\n public readonly priorities = this.apiV3CollectionEndpoint('priorities');\n\n // /api/v3/time_entries\n public readonly time_entries = this.apiV3CustomEndpoint(Apiv3TimeEntriesPaths);\n\n // /api/v3/memberships\n public readonly memberships = this.apiV3CustomEndpoint(Apiv3MembershipsPaths);\n\n // /api/v3/news\n public readonly news = this.apiV3CustomEndpoint(Apiv3NewsPaths);\n\n // /api/v3/types\n public readonly types = this.apiV3CustomEndpoint(APIv3TypesPaths);\n\n // /api/v3/versions\n public readonly versions = this.apiV3CustomEndpoint(APIv3VersionsPaths);\n\n // /api/v3/work_packages\n public readonly work_packages = this.apiV3CustomEndpoint(APIV3WorkPackagesPaths);\n\n // /api/v3/queries\n public readonly queries = this.apiV3CustomEndpoint(APIv3QueriesPaths);\n\n // /api/v3/projects\n public readonly projects = this.apiV3CustomEndpoint(APIv3ProjectsPaths);\n\n // /api/v3/users\n public readonly users = this.apiV3CustomEndpoint(Apiv3UsersPaths);\n\n // /api/v3/help_texts\n public readonly help_texts = this.apiV3CustomEndpoint(Apiv3HelpTextsPaths);\n\n // /api/v3/job_statuses\n public readonly job_statuses = this.apiV3CollectionEndpoint('job_statuses');\n\n // VIRTUAL boards are /api/v3/grids + a scope filter\n public readonly boards = this.apiV3CustomEndpoint(Apiv3BoardsPaths);\n\n constructor(readonly injector:Injector,\n readonly pathHelper:PathHelperService) {\n }\n\n /**\n * Returns the part of the API that exists both\n * - WITHIN a project scope /api/v3/projects/*\n * - GLOBALLY /api/v3/*\n *\n * The available API endpoints are being restricted automatically by typescript.\n *\n * @param projectIdentifier\n */\n public withOptionalProject(projectIdentifier:string|number|null|undefined):APIv3ProjectPaths|this {\n if (_.isNil(projectIdentifier)) {\n return this;\n } else {\n return this.projects.id(projectIdentifier);\n }\n }\n\n private apiV3CollectionEndpoint>(segment:string, resource?:Constructor) {\n return new APIv3ResourceCollection(this, this.pathHelper.api.v3.apiV3Base, segment, resource);\n }\n\n private apiV3CustomEndpoint(cls:Constructor):T {\n return new cls(this, this.pathHelper.api.v3.apiV3Base);\n }\n\n private apiV3SingularEndpoint(segment:string):APIv3GettableResource {\n return new APIv3GettableResource(this, this.pathHelper.api.v3.apiV3Base, segment);\n }\n}\n","
    \n \n \n \n \n \n {{ selectedTitle || text.input_placeholder }}{{ selectedTitle ? '  ' : ''}}\n
    \n

    {{ selectedTitle }}\n

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

    \n\n \n \n \n \n
    \n\n \n
    \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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.availableState.putValue(schema.filtersSchemas.elements);\n this.pristineState.putValue(filters);\n }\n\n /**\n * Return whether the filters are empty\n */\n public get isEmpty() {\n const value = this.lastUpdatedState.value;\n return !value || value.length === 0;\n }\n\n public get availableState():InputState {\n return this.states.queries.filters;\n }\n\n /** Return whether the filters the user is working on are incomplete */\n public get incomplete$() {\n return this.incomplete.values$();\n }\n\n\n /**\n * Add a filter instantiation from the set of available filter schemas\n *\n * @param filter\n */\n public add(filter:QueryFilterInstanceResource) {\n this.updatesState.putValue([...this.rawFilters, filter]);\n }\n\n /**\n * Replace a filter, or add a new one\n */\n public replace(id:string, modifier:(filter:QueryFilterInstanceResource) => void):void {\n let filter:QueryFilterInstanceResource = this.instantiate(id);\n\n let newFilters = [...this.rawFilters];\n modifier(filter);\n\n const index = this.findIndex(id);\n if (index === -1) {\n newFilters.push(filter);\n } else {\n newFilters.splice(index, 1, filter);\n }\n\n this.update(newFilters);\n }\n\n /**\n * Modify a live filter and push it to the state.\n * Avoids copying the resource.\n *\n * Returns whether the filter was found and modified\n */\n public modify(id:string, modifier:(filter:QueryFilterInstanceResource) => void):boolean {\n const index = this.findIndex(id);\n\n if (index === -1) {\n return false;\n }\n\n let filters = [...this.rawFilters];\n modifier(filters[index]!);\n this.update(filters);\n\n return true;\n }\n\n /**\n * Get an instantiated filter without adding it to the current state\n * @param filterOrId The query filter or id to instantiate\n */\n public instantiate(filterOrId:QueryFilterResource|string):QueryFilterInstanceResource {\n let id = (filterOrId instanceof QueryFilterResource) ? filterOrId.id : filterOrId;\n\n let schema = _.find(\n this.availableSchemas,\n schema => (schema.filter.allowedValues as HalResource)[0].id === id\n )!;\n\n return schema.getFilter();\n }\n\n /**\n * Remove one or more filters from the live state of filters.\n * @param filters Filters to be removed\n */\n public remove(...filters:(QueryFilterInstanceResource|string)[]) {\n let mapper = (f:QueryFilterInstanceResource|string) => (f instanceof QueryFilterInstanceResource) ? f.id : f;\n let set = new Set(filters.map(mapper));\n\n this.update(\n this.rawFilters.filter(f => !set.has(mapper(f)))\n );\n }\n\n /**\n * Return the remaining visible filters from the given filters set.\n * @param filters Array of active filters, defaults to the current live state.\n */\n public remainingVisibleFilters(filters = this.current) {\n return this\n .remainingFilters(filters)\n .filter((filter) => this.hidden.indexOf(filter.id) === -1);\n }\n\n /**\n * Return all available filter resources.\n * They need to be instantiated before using them in this service.\n */\n public get availableFilters():QueryFilterResource[] {\n return this.availableSchemas.map(schema => schema.allowedFilterValue);\n }\n\n private get availableSchemas():QueryFilterInstanceSchemaResource[] {\n return this.availableState.getValueOr([]);\n }\n\n /**\n * Determine whether all given filters are completely defined.\n * @param filters\n */\n public isComplete(filters:QueryFilterInstanceResource[]):boolean {\n return _.every(filters, filter => filter.isCompletelyDefined());\n }\n\n /**\n * Compare the current set of filters to the given query.\n * @param query\n */\n public hasChanged(query:QueryResource) {\n const comparer = (filter:HalResource[]) => filter.map(el => el.$source);\n\n return !_.isEqual(\n comparer(query.filters),\n comparer(this.rawFilters)\n );\n }\n\n public valueFromQuery(query:QueryResource) {\n return undefined;\n }\n\n update(value:QueryFilterInstanceResource[]) {\n super.update(value);\n this.incomplete.putValue(false);\n }\n\n /**\n * Returns the live filter instance for the given ID, or undefined\n * if it does not exist.\n *\n * @param id Identifier of the filter\n */\n public find(id:string):QueryFilterInstanceResource|undefined {\n const index = this.findIndex(id);\n\n if (index === -1) {\n return;\n }\n\n return this.rawFilters[index];\n }\n\n /**\n * Returns the index of the filter, or -1 if it does not exist\n * @param id Identifier of the filter\n */\n public findIndex(id:string):number {\n return _.findIndex(this.current, f => f.id === id);\n }\n\n public applyToQuery(query:QueryResource) {\n query.filters = this.cloneFilters();\n return true;\n }\n\n /**\n * Returns a shallow copy of the current filters.\n * Modifications to filters themselves will still\n */\n public get current():QueryFilterInstanceResource[] {\n return [...this.rawFilters];\n }\n\n /**\n * Returns a deep clone of the current filters set, may be used\n * to modify the filters without altering this state.\n */\n public cloneFilters() {\n return cloneHalResourceCollection(this.rawFilters);\n }\n\n /**\n * Returns the live state array, used for inspection of the filters\n * without modification.\n */\n protected get rawFilters():QueryFilterInstanceResource[] {\n return this.lastUpdatedState.value || [];\n }\n\n public get currentlyVisibleFilters() {\n const invisibleFilters = new Set(this.hidden);\n invisibleFilters.delete('search');\n\n return _.reject(this.currentFilterResources, (filter) => invisibleFilters.has(filter.id));\n }\n\n /**\n * Replace this filter state, but only if the given filters are complete\n * @param newState\n */\n public replaceIfComplete(newState:QueryFilterInstanceResource[]) {\n if (this.isComplete(newState)) {\n this.update(newState);\n } else {\n this.incomplete.putValue(true);\n }\n }\n\n /**\n * Filters service depends on two states\n */\n public onReady() {\n return combine(this.pristineState, this.availableState)\n .values$()\n .pipe(\n take(1),\n mapTo(null)\n )\n .toPromise();\n }\n\n /**\n * Get all filters that are not in the current active set\n */\n private remainingFilters(filters = this.rawFilters) {\n return _.differenceBy(this.availableFilters, filters, filter => filter.id);\n }\n\n /**\n * Map current filter instances to their FilterResource\n */\n private get currentFilterResources():QueryFilterResource[] {\n return this.rawFilters.map((filter:QueryFilterInstanceResource) => filter.filter);\n }\n\n isAvailable(el:QueryFilterInstanceResource):boolean {\n return !!this.availableFilters.find(available => available.id === el.id);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageViewColumnsService} from './wp-view-columns.service';\nimport {WorkPackageViewBaseService} from './wp-view-base.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageViewRelationColumns} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-relation-columns\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {RelationsStateValue, WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {Injectable} from \"@angular/core\";\nimport {\n QueryColumn,\n queryColumnTypes,\n RelationQueryColumn,\n TypeRelationQueryColumn\n} from \"core-components/wp-query/query-column\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport type RelationColumnType = 'toType'|'ofType';\n\n@Injectable()\nexport class WorkPackageViewRelationColumnsService extends WorkPackageViewBaseService {\n constructor(public querySpace:IsolatedQuerySpace,\n public wpTableColumns:WorkPackageViewColumnsService,\n public halResourceService:HalResourceService,\n public apiV3Service:APIV3Service,\n public wpRelations:WorkPackageRelationsService) {\n super(querySpace);\n }\n\n public valueFromQuery(query:QueryResource):WorkPackageViewRelationColumns {\n // Take over current expanded values\n // which are not yet saved\n return this.current;\n }\n\n /**\n * Returns a subset of all relations that the user has currently expanded.\n *\n * @param workPackage\n * @param relation\n */\n public relationsToExtendFor(workPackage:WorkPackageResource,\n relations:RelationsStateValue|undefined,\n eachCallback:(relation:RelationResource, column:QueryColumn, type:RelationColumnType) => void) {\n // Only if any relation columns or stored expansion state exist\n if (!(this.wpTableColumns.hasRelationColumns() && this.lastUpdatedState.hasValue())) {\n return;\n }\n\n // Only if any relations exist for this work package\n if (_.isNil(relations)) {\n return;\n }\n\n // Only if the work package has anything expanded\n const expanded = this.getExpandFor(workPackage.id!);\n if (expanded === undefined) {\n return;\n }\n\n const column = this.wpTableColumns.findById(expanded)!;\n const type = this.relationColumnType(column);\n\n if (type !== null) {\n _.each(this.relationsForColumn(workPackage, relations, column),\n (relation) => eachCallback(relation, column, type));\n }\n }\n\n /**\n * Get the subset of relations for the work package that belong to this relation column\n *\n * @param workPackage A work package resource\n * @param relations The RelationStateValue of this work package\n * @param column The relation column to filter for\n * @return The filtered relations\n */\n public relationsForColumn(workPackage:WorkPackageResource, relations:RelationsStateValue|undefined, column:QueryColumn) {\n if (_.isNil(relations)) {\n return [];\n }\n\n // Get the type of TO work package\n const type = this.relationColumnType(column);\n if (type === 'toType') {\n const typeHref = (column as TypeRelationQueryColumn).type.href;\n\n return _.filter(relations, (relation:RelationResource) => {\n const denormalized = relation.denormalized(workPackage);\n const target = this.apiV3Service.work_packages.cache.state(denormalized.targetId).value;\n\n return _.get(target, 'type.href') === typeHref;\n });\n }\n\n // Get the relation types for OF relation columns\n if (type === 'ofType') {\n const relationType = (column as RelationQueryColumn).relationType;\n\n return _.filter(relations, (relation:RelationResource) => {\n return relation.denormalized(workPackage).relationType === relationType;\n });\n }\n\n return [];\n }\n\n public relationColumnType(column:QueryColumn):RelationColumnType|null {\n switch (column._type) {\n case queryColumnTypes.RELATION_TO_TYPE:\n return 'toType';\n case queryColumnTypes.RELATION_OF_TYPE:\n return 'ofType';\n default:\n return null;\n }\n }\n\n public getExpandFor(workPackageId:string):string|undefined {\n return this.current[workPackageId];\n }\n\n public setExpandFor(workPackageId:string, columnId:string) {\n const nextState = { ...this.current };\n nextState[workPackageId] = columnId;\n\n this.update(nextState);\n }\n\n public collapse(workPackageId:string) {\n const nextState = { ...this.current };\n delete nextState[workPackageId];\n\n this.update(nextState);\n }\n\n public get current():WorkPackageViewRelationColumns {\n return this.lastUpdatedState.getValueOr({});\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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/disable-selection.js');\nrequire('jquery-ui/ui/widgets/sortable.js');\nrequire('jquery-ui/ui/widgets/autocomplete.js');\nrequire('jquery-ui/ui/widgets/dialog.js');\nrequire('jquery-ui/ui/widgets/tooltip.js');\n\nrequire('expose-loader?moment!moment');\nrequire('moment/locale/en-gb.js');\nrequire('moment/locale/de.js');\n\nrequire('jquery.caret');\n// Text highlight for autocompleter\nrequire('mark.js/dist/jquery.mark.min.js');\n// Micro Text fuzzy search library\nrequire('fuse.js');\n\nrequire('moment-timezone/builds/moment-timezone-with-data.min.js');\n\nrequire('expose-loader?URI!urijs');\nrequire('urijs/src/URITemplate');\n\nrequire(\"expose-loader?I18n!core-vendor/i18n\");\n\n// Localization for fullcalendar\nrequire(\"@fullcalendar/core/locales-all\");\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {\n SchemaAttributeObject,\n SchemaResource\n} from 'core-app/modules/hal/resources/schema-resource';\nimport {SchemaDependencyResource} from 'core-app/modules/hal/resources/schema-dependency-resource';\nimport {QueryOperatorResource} from 'core-app/modules/hal/resources/query-operator-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {HalLink} from \"core-app/modules/hal/hal-link/hal-link\";\n\nexport interface QueryFilterInstanceSchemaResourceLinks {\n self:HalLink;\n filter:QueryFilterResource;\n}\n\nexport class QueryFilterInstanceSchemaResource extends SchemaResource {\n\n public $links:QueryFilterInstanceSchemaResourceLinks;\n\n public operator:SchemaAttributeObject;\n public filter:SchemaAttributeObject;\n public dependency:SchemaDependencyResource;\n public values:SchemaAttributeObject|null;\n\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 return new QueryFilterInstanceResource(this.injector, source, true, this.halInitializer, 'QueryFilterInstance');\n }\n\n public isValueRequired():boolean {\n return !!(this.values);\n }\n\n public isResourceValue():boolean {\n return !!(this.values && this.values.allowedValues);\n }\n\n public resultingSchema(operator:QueryOperatorResource):QueryFilterInstanceSchemaResource {\n let staticSchema = this.$source;\n let dependentSchema = this.dependency.forValue(operator.href!.toString());\n let resultingSchema = {};\n\n _.merge(resultingSchema, staticSchema, dependentSchema);\n\n return new QueryFilterInstanceSchemaResource(this.injector, resultingSchema, true, this.halInitializer, 'QueryFilterInstanceSchema');\n }\n\n private definesAllowedValues() {\n return _.some(this._dependencies[0].dependencies,\n (dependency:any) => dependency.values && dependency.values._links && dependency.values._links.allowedValues);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {OpenprojectCommonModule} from 'core-app/modules/common/openproject-common.module';\nimport {OpenprojectFieldsModule} from 'core-app/modules/fields/openproject-fields.module';\nimport {NgModule} from '@angular/core';\nimport {OpenprojectHalModule} from \"core-app/modules/hal/openproject-hal.module\";\n\n\n@NgModule({\n imports: [\n // Commons\n OpenprojectCommonModule,\n\n OpenprojectHalModule,\n OpenprojectFieldsModule,\n ]\n})\nexport class OpenprojectProjectsModule {\n}\n","\nimport {debugLog} from '../../../helpers/debug_output';\nexport namespace ClickPositionMapper {\n\n /**\n * Try to set the position on the given input element.\n *\n * @param element The element to set the cursor to\n * @param offset The character offset retrieved from getPosition.\n */\n export function setPosition(element:HTMLInputElement, offset:number):void {\n try {\n element.setSelectionRange(offset, offset);\n } catch (e) {\n debugLog('Failed to set click position for edit field.', e);\n }\n }\n\n /**\n * Get the cursor offset from the click event.\n *\n * @param evt\n * @return {number}\n */\n export function getPosition(evt:any):number {\n const originalEvt = evt.originalEvent;\n\n try {\n if (document.caretRangeFromPoint) {\n return document\n .caretRangeFromPoint(evt.clientX!, evt.clientY!)\n .startOffset;\n } else if (originalEvt.rangeParent) {\n let range = document.createRange();\n range.setStart(originalEvt.rangeParent, originalEvt.rangeOffset);\n return range.startOffset;\n }\n\n return 0;\n } catch (e) {\n debugLog('Failed to get click position for edit field.', e);\n return 0;\n }\n }\n}\n","export type ChangeItem = {\n from:unknown;\n to:unknown;\n};\nexport type ChangeMap = { [attribute:string]:ChangeItem };\n\nexport class Changeset {\n private changes:ChangeMap = {};\n\n /**\n * Return whether a change value exist for the given attribute key.\n * @param {string} key\n * @return {boolean}\n */\n public contains(key:string) {\n return this.changes.hasOwnProperty(key);\n }\n\n /**\n * Get changed attribute names\n * @returns {string[]}\n */\n public get changed():string[] {\n return _.keys(this.changes);\n }\n\n /**\n * Returns the live set of the changes.\n */\n public get all():ChangeMap {\n return this.changes;\n }\n\n /**\n * Reset one or multiple changes\n * @param key\n */\n public reset(...keys:string[]) {\n keys.forEach((k) => {\n delete this.changes[k];\n });\n }\n\n /**\n * Reset the entire changeset\n */\n public clear():void {\n this.changes = {};\n }\n\n public set(key:string, value:unknown, pristineValue:unknown):void {\n this.changes[key] = {\n from: pristineValue,\n to: value\n };\n }\n\n /**\n * Get a change item for the given key, if any\n * @param key\n */\n public getItem(key:string):ChangeItem|undefined {\n return this.changes[key];\n }\n\n /**\n * Get a single value from the changeset\n * @param key\n */\n public getValue(key:string):unknown|undefined {\n return this.getItem(key)?.to;\n }\n\n /**\n * Get a single pristine value from the changeset\n * @param key\n */\n public getPristine(key:string):unknown|undefined {\n return this.changes[key]?.from;\n }\n}\n","import {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ChangeItem, ChangeMap, Changeset} from \"core-app/modules/fields/changeset/changeset\";\nimport {input, InputState} from \"reactivestates\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {take} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport { Injector } from '@angular/core';\nimport {SchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\n\nexport const PROXY_IDENTIFIER = '__is_changeset_proxy';\n\n/**\n * Temporary class living while a resource is being edited\n * Maintains references to:\n * - The source resource (a pristine base)\n * - The open set of changes (a changeset object)\n * - The current form (due to temporary type/project changes)\n *\n * Provides access to:\n * - The projected resource with all changes applied as properties\n */\nexport class ResourceChangeset {\n /** Maintain a single change set while editing */\n protected changeset = new Changeset();\n\n /** Reference and load promise for the current form */\n protected form$ = input();\n\n /** Request cache for objects within the changeset for the current form */\n protected cache:{ [key:string]:Promise } = {};\n\n /** Flag whether this is currently being saved */\n public inFlight = false;\n\n /** Keep a reference to the original resource */\n protected _pristineResource:T;\n\n /** The projected resource, which will proxy values from the changeset */\n public projectedResource:T;\n\n /** The cache to all the schemas. Used to maintain the schema of the projectedResource which does not stem from a form.\n * The schema of the form is kept inside the changeset.\n * */\n protected schemaCache:SchemaCacheService;\n\n constructor(pristineResource:T,\n public readonly state?:InputState>,\n loadedForm:FormResource|null = null) {\n this.updatePristineResource(pristineResource);\n\n this.schemaCache = (pristineResource.injector as Injector).get(SchemaCacheService);\n\n if (loadedForm) {\n this.form$.putValue(loadedForm);\n }\n }\n\n /**\n * Push the change to the editing state to notify others.\n * This will happen internally on resource wide changes\n */\n public push() {\n if (this.state) {\n this.state.putValue(this);\n }\n }\n\n /**\n * Build the request attributes against the fresh form\n */\n public buildRequestPayload():Promise {\n return this\n .getForm()\n .then(() => this.buildPayloadFromChanges());\n }\n\n /**\n * Update the pristine resource in case it changed\n *\n * @param attribute\n */\n public updatePristineResource(resource:T) {\n // Ensure we're not passing in a proxy\n if ((resource as any)[PROXY_IDENTIFIER]) {\n throw \"You're trying to pass proxy object as a pristine resource. This will cause errors\";\n }\n\n this._pristineResource = resource;\n this.projectedResource = new Proxy(\n this._pristineResource,\n {\n get: (_, key:string) => this.proxyGet(key),\n set: (_, key:string, val:any) => {\n this.setValue(key, val);\n return true;\n },\n }\n );\n }\n\n public get pristineResource():T {\n return this._pristineResource;\n }\n\n /**\n * Returns the cached form or loads it if necessary.\n */\n public getForm():Promise {\n if (this.form$.isPristine() && !this.form$.hasActivePromiseRequest()) {\n return this.updateForm();\n }\n\n return this\n .form$\n .values$()\n .pipe(take(1))\n .toPromise();\n }\n\n /**\n * Cache some promised value in the course of this changeset.\n * Will get cleared automatically by the changeset on destroy/submission\n */\n\n /**\n * Posts to the form with the current changes\n * to get the up to date projected object.\n */\n protected updateForm():Promise {\n let payload = this.buildPayloadFromChanges();\n\n const promise = this.pristineResource\n .$links\n .update(payload)\n .then((form:FormResource) => {\n this.cache = {};\n this.form$.putValue(form);\n this.setNewDefaults(form);\n this.push();\n return form;\n });\n\n this.form$.putFromPromiseIfPristine(() => promise);\n return promise;\n }\n\n /**\n * Return whether no changes were made to the work package\n */\n public isEmpty() {\n return this.changeset.changed.length === 0;\n }\n\n /**\n * Return the ID of the resource we're editing\n */\n public get id():string {\n return this.pristineResource.id!.toString();\n }\n\n /**\n * Return the HAL href of the resource we're editing\n */\n public get href():string {\n return this.pristineResource.href as string;\n }\n\n /**\n * Returns the changed `to` values of the ChangeMap\n */\n public get changes():{ [key:string]:unknown } {\n let changes:{ [key:string]:unknown } = {};\n\n _.each(this.changeset.all, (item, key) => {\n changes[key] = item.to;\n });\n\n return changes;\n }\n\n /**\n * Returns the change map with from and to values\n */\n public get changeMap():ChangeMap {\n return { ...this.changeset.all };\n }\n\n /**\n * Return the changed attributes in this change;\n */\n public get changedAttributes():string[] {\n return this.changeset.changed;\n }\n\n /**\n * Return whether the element is writable\n * given the current best schema.\n *\n * @param key\n */\n public isWritable(key:string):boolean {\n const fieldSchema = this.schema.ofProperty(key) as IFieldSchema|null;\n return !!(fieldSchema && fieldSchema.writable);\n }\n\n /**\n * Return the best humanized name for this attribute\n * @param attribute\n */\n public humanName(attribute:string):string {\n return _.get(this.schema, `${attribute}.name`, attribute);\n }\n\n /**\n * Returns whether the given attribute was changed\n */\n public contains(key:string) {\n return this.changeset.contains(key);\n }\n\n /**\n * Proxy getters to base or changeset.\n * @param key\n */\n private proxyGet(key:string) {\n if (key === '__is_proxy') {\n return true;\n }\n\n return this.value(key);\n }\n\n /**\n * Retrieve the editing value for the given attribute\n *\n * @param {string} key The attribute to read\n * @return {any} Either the value from the overriden change, or the default value\n */\n public value(key:string) {\n // Overridden value by user?\n if (this.changeset.contains(key)) {\n return this.changeset.getValue(key);\n }\n\n // Return whatever is on the base.\n return this.pristineResource[key];\n }\n\n /**\n * Return whether the given value exists,\n * even if its undefined.\n *\n * @param key\n */\n public valueExists(key:string):boolean {\n return this.changeset.contains(key) || this.pristineResource.hasOwnProperty(key);\n }\n\n /**\n * Change the value of the projected resource to some value\n *\n * @param key\n * @param val\n */\n public setValue(key:string, val:any) {\n this.changeset.set(key, val, this.pristineResource[key]);\n }\n\n /**\n * Clear the changed value of the projected resource\n *\n * @param keys A set of keys to reset\n */\n public clearValue(...keys:string[]) {\n this.changeset.reset(...keys);\n }\n\n public clear() {\n this.state && this.state.clear();\n this.changeset.clear();\n this.cache = {};\n this.form$.clear();\n }\n\n /**\n * Reset the given changed attribute\n * @param key\n */\n public reset(key:string) {\n this.changeset.reset(key);\n }\n\n /**\n * Return whether a change value exist for the given attribute key.\n * @param {string} key\n * @return {boolean}\n */\n public isOverridden(key:string) {\n return this.changes.hasOwnProperty(key);\n }\n\n /**\n * Get the best schema currently available, either the default resource schema (must exist).\n * If loaded, return the form schema, which provides better information on writable status\n * and contains available values.\n */\n public get schema():SchemaResource {\n if (this.form$.hasValue()) {\n return SchemaProxy.create(this.form$.value!.schema, this.projectedResource);\n } else {\n return this.schemaCache.of(this.pristineResource);\n }\n }\n\n /**\n * Access some promised value\n * that should be cached for the lifetime duration of the form.\n */\n public cacheValue(key:string, request:() => Promise):Promise {\n if (this.cache[key]) {\n return this.cache[key] as Promise;\n }\n\n return this.cache[key] = request();\n }\n\n protected get minimalPayload() {\n return { lockVersion: this.pristineResource.lockVersion, _links: {} };\n }\n\n /**\n * Merge the current changes into the payload resource.\n *\n * @param {plainPayload:unknown} A set of attributes to merge into the payload\n * @return {any}\n */\n protected applyChanges(plainPayload:any) {\n // Fall back to the last known state of the HalResource should the form not be loaded.\n let reference = this.pristineResource.$source;\n if (this.form$.value) {\n reference = this.form$.value.payload.$source;\n }\n\n _.each(this.changeset.all, (val:ChangeItem, key:string) => {\n if (!this.schema.isAttributeEditable(key)) {\n debugLog(`Trying to write ${key} but is not writable in schema`);\n return;\n }\n\n const fieldSchema:IFieldSchema|null = this.schema.ofProperty(key);\n // Override in _links if it is a linked property\n if (fieldSchema && reference._links[key]) {\n plainPayload._links[key] = this.getLinkedValue(val.to, fieldSchema);\n } else {\n plainPayload[key] = val.to;\n }\n });\n\n return plainPayload;\n }\n\n /**\n * Create the payload from the current changes, and extend it with the current lock version.\n * -- This is the place to add additional logic when the lockVersion changed in between --\n */\n protected buildPayloadFromChanges() {\n let payload;\n\n if (this.pristineResource.isNew) {\n // If the resource is new, we need to pass the entire form payload\n // to let all default values be transmitted (type, status, etc.)\n // We clone the object to avoid later manipulations to affect the original resource.\n if (this.form$.value) {\n payload = _.cloneDeep(this.form$.value.payload.$source);\n } else {\n payload = _.cloneDeep(this.pristineResource.$source);\n }\n\n // Add attachments to be assigned.\n // They will already be created on the server but now\n // we need to claim them for the newly created work package.\n if (this.pristineResource.attachments) {\n payload['_links']['attachments'] = this.pristineResource\n .attachments\n .elements\n .map((a:HalResource) => {\n return { href: a.href };\n });\n }\n\n } else {\n // Otherwise, simply use the bare minimum\n payload = this.minimalPayload;\n }\n\n return this.applyChanges(payload);\n }\n\n /**\n * Extract the link(s) in the given changed value\n */\n protected getLinkedValue(val:any, fieldSchema:IFieldSchema) {\n // Links should always be nullified as { href: null }, but\n // this wasn't always the case, so ensure null values are returned as such.\n if (_.isNil(val)) {\n return { href: null };\n }\n\n // Test if we either have a CollectionResource or a HAL array,\n // or a single hal value.\n let isArrayType = (fieldSchema.type || '').startsWith('[]');\n let isArray = false;\n\n if (val.forEach || val.elements) {\n isArray = true;\n }\n\n if (isArray && isArrayType) {\n let links:{ href:string }[] = [];\n\n if (val) {\n let elements = (val.forEach && val) || val.elements;\n\n elements.forEach((link:{ href:string }) => {\n if (link.href) {\n links.push({ href: link.href });\n }\n });\n }\n\n return links;\n } else {\n return { href: _.get(val, 'href', null) };\n }\n }\n\n /**\n * When changing type or project, new custom fields may be present\n * that we need to set.\n */\n protected setNewDefaults(form:FormResource) {\n _.each(form.payload, (val:unknown, key:string) => {\n const fieldSchema:IFieldSchema|null = this.schema.ofProperty(key);\n if (!fieldSchema?.writable) {\n return;\n }\n\n this.setNewDefaultFor(key, val);\n });\n }\n\n /**\n * Set the default for the given attribute\n */\n protected setNewDefaultFor(key:string, val:unknown) {\n if (!this.valueExists(key)) {\n debugLog(\"Taking over default value from form for \" + key);\n this.setValue(key, val);\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\n\nexport class HalPayloadHelper {\n\n /**\n * Extract payload from the given request with schema.\n * This will ensure we will only write writable attributes and so on.\n *\n * @param resource\n * @param schema\n */\n static extractPayload(resource:T|Object|null, schema:SchemaResource|null = null):Object {\n if (resource instanceof HalResource && schema) {\n return this.extractPayloadFromSchema(resource, schema);\n } else if (resource && !(resource instanceof HalResource)) {\n return resource;\n } else {\n return {};\n }\n }\n\n /**\n * Extract writable payload from a HAL resource class to be used for API calls.\n *\n * The schema contains writable information about attributes, which is what this method\n * iterates in order to build the HAL-compatible object.\n *\n * @param resource A HalResource to extract payload from\n * @param schema The associated schema to determine writable state of attributes\n */\n static extractPayloadFromSchema(resource:T, schema:SchemaResource) {\n let payload:any = {\n '_links': {}\n };\n\n let nonLinkProperties = [];\n\n for (let key in schema) {\n if (schema.hasOwnProperty(key) && schema[key] && schema[key].writable) {\n if (resource.$links[key]) {\n if (Array.isArray(resource[key])) {\n payload['_links'][key] = _.map(resource[key], element => {\n return { href: (element as HalResource).$href };\n });\n } else {\n payload['_links'][key] = {\n href: (resource[key] && resource[key].$href)\n };\n }\n } else {\n nonLinkProperties.push(key);\n }\n }\n }\n\n _.each(nonLinkProperties, property => {\n if (resource.hasOwnProperty(property) || resource[property]) {\n if (Array.isArray(resource[property])) {\n payload[property] = _.map(resource[property], (element:any) => {\n if (element instanceof HalResource) {\n return this.extractPayloadFromSchema(element, element.currentSchema || element.schema);\n } else {\n return element;\n }\n });\n } else {\n payload[property] = resource[property];\n }\n }\n });\n\n return payload;\n }\n}\n","/**\n * A PortalOutlet that lets multiple components live for the lifetime of the outlet,\n * allowing faster switching and persistent data.\n */\nimport {ComponentPortal} from '@angular/cdk/portal';\nimport {\n ApplicationRef,\n ComponentFactoryResolver,\n ComponentRef,\n EmbeddedViewRef,\n Injector\n} from '@angular/core';\n\nexport interface TabInterface {\n name:string;\n title:string;\n disableBecause?:string;\n componentClass:{ new(...args:any[]):TabComponent };\n}\n\nexport interface TabComponent {\n onSave:() => void;\n}\n\nexport interface ActiveTabInterface {\n name:string;\n portal:ComponentPortal;\n componentRef:ComponentRef;\n dispose:() => void;\n}\n\nexport class TabPortalOutlet {\n\n // Active tabs that have been instantiated\n public activeTabs:{ [name:string]:ActiveTabInterface } = {};\n\n // The current tab\n public currentTab:ActiveTabInterface|null = null;\n\n constructor(\n public availableTabs:TabInterface[],\n public outletElement:HTMLElement,\n private componentFactoryResolver:ComponentFactoryResolver,\n private appRef:ApplicationRef,\n private injector:Injector) {\n }\n\n public get activeComponents():TabComponent[] {\n const tabs = _.values(this.activeTabs);\n return tabs.map((tab:ActiveTabInterface) => tab.componentRef.instance);\n }\n\n public switchTo(name:string) {\n const tab = _.find(this.availableTabs, tab => tab.name === name);\n\n if (!tab) {\n throw(`Trying to switch to unknown tab ${name}.`);\n }\n\n if (tab.disableBecause != null) {\n return false;\n }\n\n // Detach any current instance\n this.detach();\n\n // Get existing or new component instance\n const instance = this.activateInstance(tab);\n\n // At this point the component has been instantiated, so we move it to the location in the DOM\n // where we want it to be rendered.\n this.outletElement.innerHTML = '';\n this.outletElement.appendChild(this._getComponentRootNode(instance.componentRef));\n this.outletElement.dataset.tabName = tab.title;\n this.currentTab = instance;\n\n return false;\n }\n\n public detach():void {\n const current = this.currentTab;\n if (current !== null) {\n current.portal.setAttachedHost(null);\n this.currentTab = null;\n }\n }\n\n /**\n * Clears out a portal from the DOM.\n */\n dispose():void {\n // Dispose all active tabs\n _.each(this.activeTabs, active => active.dispose());\n\n // Remove outlet element\n if (this.outletElement.parentNode != null) {\n this.outletElement.parentNode.removeChild(this.outletElement);\n }\n }\n\n private activateInstance(tab:TabInterface):ActiveTabInterface {\n if (!this.activeTabs[tab.name]) {\n this.activeTabs[tab.name] = this.createComponent(tab);\n }\n\n return this.activeTabs[tab.name] || null;\n }\n\n private createComponent(tab:TabInterface):ActiveTabInterface {\n const componentFactory = this.componentFactoryResolver.resolveComponentFactory(tab.componentClass);\n const componentRef = componentFactory.create(this.injector);\n const portal = new ComponentPortal(tab.componentClass, null, this.injector);\n\n // Attach component view\n this.appRef.attachView(componentRef.hostView);\n\n return {\n name: tab.name,\n portal: portal,\n componentRef: componentRef,\n dispose: () => {\n this.appRef.detachView(componentRef.hostView);\n componentRef.destroy();\n }\n };\n }\n\n /** Gets the root HTMLElement for an instantiated component. */\n private _getComponentRootNode(componentRef:ComponentRef):HTMLElement {\n return (componentRef.hostView as EmbeddedViewRef).rootNodes[0] as HTMLElement;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Directive, ElementRef, Injector} from '@angular/core';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {OpTableActionsService} from \"core-components/wp-table/table-actions/table-actions.service\";\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {WorkPackageViewPaginationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-pagination.service\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageViewSumService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service\";\nimport {WorkPackageViewAdditionalElementsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-additional-elements.service\";\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {WorkPackageCreateService} from \"core-components/wp-new/wp-create.service\";\nimport {WorkPackageStatesInitializationService} from \"core-components/wp-list/wp-states-initialization.service\";\nimport {WorkPackageViewFocusService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {WorkPackageService} from \"core-components/work-packages/work-package.service\";\nimport {WorkPackageRelationsHierarchyService} from \"core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service\";\nimport {WorkPackageFiltersService} from \"core-components/filters/wp-filters/wp-filters.service\";\nimport {WorkPackageContextMenuHelperService} from \"core-components/wp-table/context-menu-helper/wp-context-menu-helper.service\";\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WpChildrenInlineCreateService} from \"core-components/wp-relations/embedded/children/wp-children-inline-create.service\";\nimport {WpRelationInlineCreateService} from \"core-components/wp-relations/embedded/relations/wp-relation-inline-create.service\";\nimport {WorkPackagesListChecksumService} from \"core-components/wp-list/wp-list-checksum.service\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {TableDragActionsRegistryService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-actions-registry.service\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {CausedUpdatesService} from \"core-app/modules/boards/board/caused-updates/caused-updates.service\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {WorkPackageViewDisplayRepresentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageViewHierarchyIdentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy-indentation.service\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {TimeEntryCreateService} from \"core-app/modules/time_entries/create/create.service\";\nimport {WorkPackageViewCollapsedGroupsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service\";\n\n/**\n * Directive to open a work package query 'space', an isolated injector hierarchy\n * that provides access to query-bound data and services, especially around the querySpace services.\n *\n * If you add services that depend on a table state, they should be provided here, not globally\n * in a module.\n */\n@Directive({\n selector: '[wp-isolated-query-space]',\n providers: [\n // Override the hal notification service\n { provide: HalResourceNotificationService, useExisting: WorkPackageNotificationService },\n\n // Open the isolated space first, order is important here\n IsolatedQuerySpace,\n OpTableActionsService,\n\n // Work package table services\n WorkPackagesListChecksumService,\n WorkPackagesListService,\n WorkPackageViewRelationColumnsService,\n WorkPackageViewPaginationService,\n WorkPackageViewGroupByService,\n WorkPackageViewCollapsedGroupsService,\n WorkPackageViewHierarchiesService,\n WorkPackageViewSortByService,\n WorkPackageViewColumnsService,\n WorkPackageViewFiltersService,\n WorkPackageViewTimelineService,\n WorkPackageViewSelectionService,\n WorkPackageViewSumService,\n WorkPackageViewAdditionalElementsService,\n WorkPackageViewFocusService,\n WorkPackageViewHighlightingService,\n WorkPackageViewDisplayRepresentationService,\n WorkPackageViewOrderService,\n WorkPackageViewHierarchyIdentationService,\n CausedUpdatesService,\n\n WorkPackageService,\n WorkPackageRelationsHierarchyService,\n WorkPackageFiltersService,\n WorkPackageContextMenuHelperService,\n\n // Provide a separate service for creation events of WP Inline create\n // This can be hierarchically injected to provide isolated events on an embedded table\n WorkPackageInlineCreateService,\n WpChildrenInlineCreateService,\n WpRelationInlineCreateService,\n\n WorkPackageCardViewService,\n\n HalResourceEditingService,\n TimeEntryCreateService,\n WorkPackageCreateService,\n\n WorkPackageStatesInitializationService,\n\n // Table Drag & Drop actions\n TableDragActionsRegistryService,\n ]\n})\nexport class WorkPackageIsolatedQuerySpaceDirective {\n\n constructor(private elementRef:ElementRef,\n public querySpace:IsolatedQuerySpace,\n private injector:Injector) {\n debugLog(\"Opening isolated query space %O in %O\", injector, elementRef.nativeElement);\n }\n}\n","import {\n HttpEvent,\n HttpInterceptor,\n HttpHandler,\n HttpRequest,\n} from '@angular/common/http';\nimport {Observable} from 'rxjs';\nimport { Injectable } from \"@angular/core\";\n\n@Injectable()\nexport class OpenProjectHeaderInterceptor implements HttpInterceptor {\n intercept(req:HttpRequest, next:HttpHandler):Observable> {\n const csrf_token:string|undefined = jQuery('meta[name=csrf-token]').attr('content');\n\n if (req.withCredentials !== false) {\n\n let newHeaders = req.headers\n .set('X-Authentication-Scheme', 'Session')\n .set('X-Requested-With', 'XMLHttpRequest');\n\n if (csrf_token) {\n newHeaders = newHeaders.set('X-CSRF-TOKEN', csrf_token);\n }\n\n // Clone the request to add the new header\n const clonedRequest = req.clone({\n withCredentials: true,\n headers: newHeaders\n });\n\n // Pass the cloned request instead of the original request to the next handle\n return next.handle(clonedRequest);\n }\n\n return next.handle(req);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {MultiInputState, State} from 'reactivestates';\nimport {Observable} from \"rxjs\";\nimport {auditTime, map, share, startWith, take} from \"rxjs/operators\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\n\nexport interface HasId {\n id:string|null;\n}\n\nexport class StateCacheService {\n protected cacheDurationInMs:number;\n protected multiState:MultiInputState;\n\n constructor(state:MultiInputState, holdValuesForSeconds:number = 3600) {\n this.multiState = state;\n this.cacheDurationInMs = holdValuesForSeconds * 1000;\n }\n\n public state(id:string):State {\n return this.multiState.get(id);\n }\n\n /**\n * Touch the current state to fire subscribers.\n */\n public touch(id:string):void {\n const state = this.multiState.get(id);\n state.putValue(state.value, 'Touching the state');\n }\n\n /**\n * Get the current value\n */\n public current(id:string, fallback?:T):T|undefined {\n return this.state(id).getValueOr(fallback);\n }\n\n /**\n * Sets a promise to the state\n */\n public clearAndLoad(id:string, loader:Observable):Observable {\n const observable =\n loader\n .pipe(\n take(1),\n share()\n );\n\n this\n .multiState.get(id)\n .clearAndPutFromPromise(observable.toPromise());\n\n return observable;\n }\n\n /**\n * Update the value due to application changes.\n *\n * @param id The value's identifier.\n * @param val The value.\n *\n * @return a promise of the value when it was inserted into cache\n */\n public updateValue(id:string, val:T):Promise {\n this.putValue(id, val);\n return Promise.resolve(val);\n }\n\n /**\n * Update the value due to application changes.\n *\n * @param resource The value.\n */\n public updateFor(resource:HasId):Promise {\n return this.updateValue(resource.id!, resource as any);\n }\n\n\n /**\n * Observe the value of the given id\n */\n public observe(id:string):Observable {\n return this.state(id).values$();\n }\n\n /**\n * Observe the changes of the given id\n */\n public changes$(id:string):Observable {\n return this.state(id).changes$();\n }\n\n /**\n * Observe the entire set of loaded results\n */\n public observeAll():Observable {\n return this.multiState\n .observeChange()\n .pipe(\n startWith([]),\n auditTime(250),\n map(() => {\n let mapped:T[] = [];\n _.each(this.multiState.getValueOr({}), (state:State) => {\n if (state.value) {\n mapped.push(state.value);\n }\n });\n\n return mapped;\n })\n );\n }\n\n /**\n * Clear a set of cached states.\n * @param ids\n */\n public clearSome(...ids:string[]) {\n ids.forEach(id => this.multiState.get(id).clear());\n }\n\n /**\n * Returns whether the state\n * @param id ID of the state\n * @return {boolean}\n */\n public stale(id:string):boolean {\n const state = this.multiState.get(id);\n\n // If there is an active request that is still pending\n if (state.hasActivePromiseRequest()) {\n return false;\n }\n\n return state.isPristine() || state.isValueOlderThan(this.cacheDurationInMs);\n }\n\n /**\n * Actually insert the value in the state right now.\n *\n * @param id\n * @param val\n */\n protected putValue(id:string, val:T) {\n this.multiState.get(id).putValue(val);\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const usersAutocompleterSelector = 'user-autocompleter';\n\n@Component({\n templateUrl: './user-autocompleter.component.html',\n selector: usersAutocompleterSelector\n})\nexport class UserAutocompleterComponent implements OnInit {\n userTracker = (item:any) => item.href || item.id;\n\n @ViewChild(NgSelectComponent, { static: true }) public ngSelectComponent:NgSelectComponent;\n @Output() public onChange = new EventEmitter();\n @Input() public clearAfterSelection:boolean = false;\n\n // Load all users as default\n @Input() public url:string = this.apiV3Service.users.path;\n @Input() public allowEmpty:boolean = false;\n @Input() public appendTo:string = '';\n @Input() public multiple:boolean = false;\n\n @Input() public initialSelection:number|null = null;\n\n // Update an input field after changing, used when externally loaded\n private updateInputField:HTMLInputElement|undefined;\n\n /** Keep a switchmap for search term and loading state */\n public requests = new DebouncedRequestSwitchmap(\n (searchTerm:string) => this.getAvailableUsers(this.url, searchTerm),\n errorNotificationHandler(this.halNotification)\n );\n\n public inputFilters:ApiV3FilterBuilder = new ApiV3FilterBuilder();\n\n constructor(protected elementRef:ElementRef,\n protected halResourceService:HalResourceService,\n protected I18n:I18nService,\n protected halNotification:HalResourceNotificationService,\n readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly injector:Injector) {\n }\n\n ngOnInit() {\n const input = this.elementRef.nativeElement.dataset['updateInput'];\n const allowEmpty = this.elementRef.nativeElement.dataset['allowEmpty'];\n const appendTo = this.elementRef.nativeElement.dataset['appendTo'];\n const multiple = this.elementRef.nativeElement.dataset['multiple'];\n const url = this.elementRef.nativeElement.dataset['url'];\n\n if (input) {\n this.updateInputField = document.getElementsByName(input)[0] as HTMLInputElement|undefined;\n this.setInitialSelection();\n }\n\n let filterInput = this.elementRef.nativeElement.dataset['additionalFilter'];\n if (filterInput) {\n JSON.parse(filterInput).forEach((filter:{selector:string; operator:FilterOperator, values:string[]}) => {\n this.inputFilters.add(filter['selector'], filter['operator'], filter['values']);\n });\n }\n\n if (allowEmpty === 'true') {\n this.allowEmpty = true;\n }\n\n if (appendTo) {\n this.appendTo = appendTo;\n }\n\n if (multiple === 'true') {\n this.multiple = true;\n }\n\n if (url) {\n this.url = url;\n }\n }\n\n public onFocus() {\n if (!this.requests.lastRequestedValue) {\n this.requests.input$.next('');\n }\n }\n\n public onModelChange(user:any) {\n if (user) {\n this.onChange.emit(user);\n this.requests.input$.next('');\n\n if (this.clearAfterSelection) {\n this.ngSelectComponent.clearItem(user);\n }\n\n if (this.updateInputField) {\n if (this.multiple) {\n this.updateInputField.value = user.map((u:UserResource) => u.id);\n } else {\n this.updateInputField.value = user.id;\n }\n }\n }\n }\n\n protected getAvailableUsers(url:string, searchTerm:any):Observable<{[key:string]:string|null}[]> {\n // Need to clone the filters to not add additional filters on every\n // search term being processed.\n let searchFilters = this.inputFilters.clone();\n\n if (searchTerm && searchTerm.length) {\n searchFilters.add('name', '~', [searchTerm]);\n }\n\n return this.halResourceService\n .get(url, { filters: searchFilters.toJson() })\n .pipe(\n map(res => {\n let options = res.elements.map((el:any) => {\n return {name: el.name, id: el.id, href: el.href, avatar: el.avatar};\n });\n\n if (this.allowEmpty) {\n options.unshift({name: this.I18n.t('js.timelines.filter.noneSelection'), href: null, id: null});\n }\n\n return options;\n })\n );\n }\n\n private setInitialSelection() {\n if (this.updateInputField) {\n const id = parseInt(this.updateInputField.value);\n this.initialSelection = isNaN(id) ? null : id;\n }\n }\n}\n\n","\n \n \n \n {{ item.name }}\n \n","import {\n ApplicationRef,\n ComponentFactoryResolver,\n ComponentRef,\n Injectable,\n InjectionToken,\n Injector\n} from '@angular/core';\nimport {ComponentPortal, ComponentType, DomPortalOutlet, PortalInjector} from '@angular/cdk/portal';\nimport {TransitionService} from '@uirouter/core';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {FocusHelperService} from 'core-app/modules/common/focus/focus-helper';\n\nexport const OpModalLocalsToken = new InjectionToken('OP_MODAL_LOCALS');\n\n@Injectable({ providedIn: 'root' })\nexport class OpModalService {\n public active:OpModalComponent|null = null;\n\n // Hold a reference to the DOM node we're using as a host\n private portalHostElement:HTMLElement;\n // And a reference to the actual portal host interface on top of the element\n private bodyPortalHost:DomPortalOutlet;\n\n // Remember when we're opening a new modal to avoid the outside click bubbling up.\n private opening:boolean = false;\n\n constructor(private componentFactoryResolver:ComponentFactoryResolver,\n readonly FocusHelper:FocusHelperService,\n private appRef:ApplicationRef,\n private $transitions:TransitionService,\n private injector:Injector) {\n\n const hostElement = this.portalHostElement = document.createElement('div');\n hostElement.classList.add('op-modals--overlay');\n document.body.appendChild(hostElement);\n\n // Listen to keyups on window to close context menus\n jQuery(window).on('keydown', (evt:JQuery.TriggeredEvent) => {\n if (this.active && this.active.closeOnEscape && evt.which === keyCodes.ESCAPE) {\n this.active.closeOnEscapeFunction(evt);\n }\n\n return true;\n });\n\n // Listen to any click when should close outside modal\n jQuery(window).on('click', (evt:JQuery.TriggeredEvent) => {\n if (this.active &&\n !this.opening &&\n this.active.closeOnOutsideClick &&\n this.activeModal[0] === evt.target as Element) {\n this.close();\n }\n });\n\n this.bodyPortalHost = new DomPortalOutlet(\n hostElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n }\n\n /**\n * Open a Modal reference and append it to the portal\n *\n * @param modal The modal component class to show\n * @param injector The injector to pass into the component. Ensure this is the hierarchical injector if needed.\n * Can be passed 'global' to take the default (global!) injector of this service.\n * @param locals A map to be injected via token into the component.\n */\n public show(modal:ComponentType, injector:Injector|'global', locals:any = {}):T {\n this.close();\n\n // Prevent closing events during the opening time frame.\n this.opening = true;\n\n // Allow users to pass the global injector when deliberately requested.\n if (injector === 'global') {\n injector = this.injector;\n }\n\n // Create a portal for the given component class and render it\n const portal = new ComponentPortal(modal, null, this.injectorFor(injector, locals));\n const ref:ComponentRef = this.bodyPortalHost.attach(portal) as ComponentRef;\n const instance = ref.instance as T;\n this.active = instance;\n this.portalHostElement.style.display = 'block';\n\n setTimeout(() => {\n // Focus on the first element\n this.active && this.active.onOpen(this.activeModal);\n\n // Mark that we've opened the modal now\n this.opening = false;\n }, 20);\n\n jQuery('.op-modal--modal-container').focus();\n\n return this.active as T;\n }\n\n public isActive(modal:OpModalComponent) {\n return this.active && this.active === modal;\n }\n\n /**\n * Closes currently open modal window\n */\n public close() {\n // Detach any component currently in the portal\n if (this.active && this.active.onClose()) {\n this.active.closingEvent.emit(this.active);\n this.bodyPortalHost.detach();\n this.portalHostElement.style.display = 'none';\n this.active = null;\n }\n }\n\n public get activeModal():JQuery {\n return jQuery(this.portalHostElement).find('.op-modal--portal');\n }\n\n /**\n * Create an augmented injector that is equal to this service's injector + the additional data\n * passed into +show+.\n * This allows callers to pass data into the newly created modal.\n *\n */\n private injectorFor(injector:Injector, data:any) {\n const injectorTokens = new WeakMap();\n // Pass the service because otherwise we're getting a cyclic dependency between the portal\n // host service and the bound portal\n data.service = this;\n\n injectorTokens.set(OpModalLocalsToken, data);\n\n return new PortalInjector(injector, injectorTokens);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {States} from 'core-components/states.service';\nimport {Injectable} from '@angular/core';\nimport {cloneHalResourceCollection} from 'core-app/modules/hal/helpers/hal-resource-builder';\nimport {QueryColumn, queryColumnTypes} from \"core-components/wp-query/query-column\";\nimport {combine} from \"reactivestates\";\nimport {mapTo, take} from \"rxjs/operators\";\n\n@Injectable()\nexport class WorkPackageViewColumnsService extends WorkPackageQueryStateService {\n\n public constructor(readonly states:States, readonly querySpace:IsolatedQuerySpace) {\n super(querySpace);\n }\n\n public initialize(query:any, results:any, schema?:any) {\n super.initialize(query, results, schema);\n }\n\n public valueFromQuery(query:QueryResource):QueryColumn[] {\n return [...query.columns];\n }\n\n public hasChanged(query:QueryResource) {\n return !this.isCurrentlyEqualTo(query.columns);\n }\n\n public isCurrentlyEqualTo(a:QueryColumn[]) {\n const comparer = (columns:QueryColumn[]) => columns.map(c => c.href);\n\n return _.isEqual(\n comparer(a),\n comparer(this.getColumns())\n );\n }\n\n public applyToQuery(query:QueryResource) {\n const toApply = this.getColumns();\n\n const oldColumns = query.columns.map(el => el.id);\n const newColumns = toApply.map(el => el.id);\n query.columns = cloneHalResourceCollection(toApply);\n\n // We can avoid reloading even with relation columns if we only removed columns\n const onlyRemoved = _.difference(newColumns, oldColumns).length === 0;\n\n // Reload the table visibly if adding relation columns.\n return !onlyRemoved && this.hasRelationColumns();\n }\n\n /**\n * Returns whether the current set of columns include relations\n */\n public hasRelationColumns() {\n const relationColumns = [queryColumnTypes.RELATION_OF_TYPE, queryColumnTypes.RELATION_TO_TYPE];\n return !!_.find(this.getColumns(), (c) => relationColumns.indexOf(c._type) >= 0);\n }\n\n /**\n * Retrieve the QueryColumn objects for the selected columns.\n * Returns a shallow copy with the original column objects.\n */\n public getColumns():QueryColumn[] {\n return [ ...this.current ];\n }\n\n /**\n * Return the index of the given column or -1 if it is not contained.\n */\n public index(id:string):number {\n return _.findIndex(this.getColumns(), column => column.id === id);\n }\n\n /**\n * Return the column object for the given id.\n * @param id\n */\n public findById(id:string):QueryColumn|undefined {\n return _.find(this.getColumns(), column => column.id === id);\n }\n\n /**\n * Return the previous column of the given column name\n * @param column\n */\n public previous(column:QueryColumn):QueryColumn|null {\n let index = this.index(column.id);\n\n if (index <= 0) {\n return null;\n }\n\n return this.getColumns()[index - 1];\n }\n\n /**\n * Return the next column of the given column name\n * @param column\n */\n public next(column:QueryColumn):QueryColumn|null {\n let index = this.index(column.id);\n\n if (index === -1 || this.isLast(name)) {\n return null;\n }\n\n return this.getColumns()[index + 1];\n }\n\n /**\n * Returns true if the column is the first selected\n */\n public isFirst(column:QueryColumn):boolean {\n return this.index(column.id) === 0;\n }\n\n /**\n * Returns true if the column is the last selected\n */\n public isLast(column:QueryColumn):boolean {\n return this.index(column.id) === this.columnCount - 1;\n }\n\n /**\n * Update the selected columns to a new set of columns.\n */\n public setColumns(columns:QueryColumn[]) {\n // Don't publish if this is the same content\n if (this.isCurrentlyEqualTo(columns)) {\n return;\n }\n\n this.update(columns);\n }\n\n public setColumnsById(columnIds:string[]) {\n const mapped = columnIds.map(id => _.find(this.all, c => c.id === id));\n this.setColumns(_.compact(mapped));\n }\n\n /**\n * Move the column at index {fromIndex} to {toIndex}.\n * - If toIndex is larger than all columns, insert at the end.\n * - If toIndex is less than zero, insert at the start.\n */\n public moveColumn(fromIndex:number, toIndex:number) {\n let columns = this.getColumns();\n\n if (toIndex >= columns.length) {\n toIndex = columns.length - 1;\n }\n\n if (toIndex < 0) {\n toIndex = 0;\n }\n\n let element = columns[fromIndex];\n columns.splice(fromIndex, 1);\n columns.splice(toIndex, 0, element);\n\n this.setColumns(columns);\n }\n\n /**\n * Shift the given column name X indices,\n * where X is the offset in indices (-1 = shift one to left)\n */\n public shift(column:QueryColumn, offset:number) {\n let index = this.index(column.id);\n if (index === -1) {\n return;\n }\n\n this.moveColumn(index, index + offset);\n }\n\n /**\n * Add a new column to the selection at the given position\n */\n public addColumn(id:string, position?:number) {\n let columns = this.getColumns();\n\n if (position === undefined) {\n position = columns.length;\n }\n\n if (this.index(id) === -1) {\n let newColumn = _.find(this.all, (column) => column.id === id);\n\n if (!newColumn) {\n throw \"Column with provided name is not found\";\n }\n\n columns.splice(position, 0, newColumn);\n this.setColumns(columns);\n }\n }\n\n /**\n * Remove a column from the active list\n */\n public removeColumn(column:QueryColumn) {\n let index = this.index(column.id);\n\n if (index !== -1) {\n let columns = this.getColumns();\n columns.splice(index, 1);\n this.setColumns(columns);\n }\n }\n\n // only exists to cast the state\n protected get current() {\n return this.lastUpdatedState.getValueOr([]);\n }\n\n // Get the available state\n protected get availableState() {\n return this.states.queries.columns;\n }\n\n /**\n * Return the number of selected rows.\n */\n public get columnCount():number {\n return this.getColumns().length;\n }\n\n /**\n * Get all available columns (regardless of whether they are selected already)\n */\n public get all():QueryColumn[] {\n return this.availableState.getValueOr([]);\n }\n\n public get allPropertyColumns():QueryColumn[] {\n return this\n .all\n .filter((column:QueryColumn) => column._type === queryColumnTypes.PROPERTY);\n }\n\n /**\n * Get columns not yet selected\n */\n public get unused():QueryColumn[] {\n return _.differenceBy(this.all, this.getColumns(), '$href');\n }\n\n /**\n * Columns service depends on two states\n */\n public onReady() {\n return combine(this.pristineState, this.availableState)\n .values$()\n .pipe(\n take(1),\n mapTo(null)\n )\n .toPromise();\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injectable} from '@angular/core';\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\n\nclass Apiv3Paths {\n readonly apiV3Base:string;\n\n constructor(basePath:string) {\n this.apiV3Base = basePath + '/api/v3';\n }\n\n /**\n * Preview markup path\n *\n * Primarily used from ckeditor\n * https://github.com/opf/commonmark-ckeditor-build/\n *\n * @param context\n */\n public previewMarkup(context:string) {\n let base = `${this.apiV3Base}/render/markdown`;\n\n if (context) {\n return `${base}?context=${context}`;\n } else {\n return base;\n }\n }\n\n /**\n * Principals autocompleter path\n *\n * Primarily used from ckeditor\n * https://github.com/opf/commonmark-ckeditor-build/\n *\n */\n public principals(projectId:string|number, term:string|null) {\n let filters:ApiV3FilterBuilder = new ApiV3FilterBuilder();\n // Only real and activated users:\n filters.add('status', '!', ['3']);\n // that are members of that project:\n filters.add('member', '=', [projectId.toString()]);\n // That are users:\n filters.add('type', '=', ['User', 'Group']);\n // That are not the current user:\n filters.add('id', '!', ['me']);\n\n if (term && term.length > 0) {\n // Containing the that substring:\n filters.add('name', '~', [term]);\n }\n\n return this.apiV3Base +\n '/principals?' +\n filters.toParams({ sortBy: '[[\"name\",\"asc\"]]', offset: '1', pageSize: '10' });\n }\n}\n\n@Injectable({ providedIn: 'root' })\nexport class PathHelperService {\n public readonly appBasePath = window.appBasePath || '';\n public readonly api = {\n v3: new Apiv3Paths(this.appBasePath)\n };\n\n public get staticBase() {\n return this.appBasePath;\n }\n\n public attachmentDownloadPath(attachmentIdentifier:string, slug:string|undefined) {\n let path = `${this.staticBase}/attachments/${attachmentIdentifier}`;\n\n if (slug) {\n return `${path}/${slug}`;\n } else {\n return path;\n }\n }\n\n public attachmentContentPath(attachmentIdentifier:number|string) {\n return `${this.staticBase}/attachments/${attachmentIdentifier}/content`;\n }\n\n public ifcModelsPath(projectIdentifier:string) {\n return `${this.staticBase}/projects/${projectIdentifier}/ifc_models`;\n }\n\n public bimDetailsPath(projectIdentifier:string, workPackageId:string, viewpoint:number|string|null = null) {\n let path = `${this.projectPath(projectIdentifier)}/bcf/split/details/${workPackageId}`;\n\n if (viewpoint !== null) {\n path += `?viewpoint=${viewpoint}`;\n }\n\n return path;\n }\n\n public highlightingCssPath() {\n return `${this.staticBase}/highlighting/styles`;\n }\n\n public forumPath(projectIdentifier:string, forumIdentifier:string) {\n return `${this.projectForumPath(projectIdentifier)}/${forumIdentifier}`;\n }\n\n public keyboardShortcutsHelpPath() {\n return `${this.staticBase}/help/keyboard_shortcuts`;\n }\n\n public messagePath(messageIdentifier:string) {\n return `${this.staticBase}/topics/${messageIdentifier}`;\n }\n\n public myPagePath() {\n return `${this.staticBase}/my/page`;\n }\n\n public newsPath(newsId:string) {\n return `${this.staticBase}/news/${newsId}`;\n }\n\n public loginPath() {\n return `${this.staticBase}/login`;\n }\n\n public projectsPath() {\n return `${this.staticBase}/projects`;\n }\n\n public projectPath(projectIdentifier:string) {\n return `${this.projectsPath()}/${projectIdentifier}`;\n }\n\n public projectActivityPath(projectIdentifier:string) {\n return `${this.projectPath(projectIdentifier)}/activity`;\n }\n\n public projectForumPath(projectIdentifier:string) {\n return `${this.projectPath(projectIdentifier)}/forums`;\n }\n\n public projectCalendarPath(projectId:string) {\n return `${this.projectPath(projectId)}/work_packages/calendar`;\n }\n\n public projectMembershipsPath(projectId:string) {\n return `${this.projectPath(projectId)}/members`;\n }\n\n public projectNewsPath(projectId:string) {\n return `${this.projectPath(projectId)}/news`;\n }\n\n public projectTimeEntriesPath(projectIdentifier:string) {\n return `${this.projectPath(projectIdentifier)}/cost_reports`;\n }\n\n public projectWikiPath(projectId:string) {\n return `${this.projectPath(projectId)}/wiki`;\n }\n\n public projectWorkPackagePath(projectId:string, wpId:string|number) {\n return `${this.projectWorkPackagesPath(projectId)}/${wpId}`;\n }\n\n public projectWorkPackagesPath(projectId:string) {\n return `${this.projectPath(projectId)}/work_packages`;\n }\n\n public projectWorkPackageNewPath(projectId:string) {\n return `${this.projectWorkPackagesPath(projectId)}/new`;\n }\n\n public projectBoardsPath(projectIdentifier:string|null) {\n if (projectIdentifier) {\n return `${this.projectPath(projectIdentifier)}/boards`;\n } else {\n return `${this.staticBase}/boards`;\n }\n }\n\n public projectDashboardsPath(projectIdentifier:string) {\n return `${this.projectPath(projectIdentifier)}/dashboards`;\n }\n\n public timeEntriesPath(workPackageId:string|number) {\n let suffix = '/time_entries';\n\n if (workPackageId) {\n return this.workPackagePath(workPackageId) + suffix;\n } else {\n return this.staticBase + suffix; // time entries root path\n }\n }\n\n public usersPath() {\n return `${this.staticBase}/users`;\n }\n\n public 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","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 {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {ISchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\n\n@Component({\n selector: 'wp-status-button',\n styleUrls: ['./wp-status-button.component.sass'],\n templateUrl: './wp-status-button.html'\n})\nexport class WorkPackageStatusButtonComponent extends UntilDestroyedMixin implements OnInit {\n @Input('workPackage') public workPackage:WorkPackageResource;\n @Input('containerClass') public containerClass:string;\n\n public text = {\n explanation: this.I18n.t('js.label_edit_status'),\n workPackageReadOnly: this.I18n.t('js.work_packages.message_work_package_read_only'),\n workPackageStatusBlocked: this.I18n.t('js.work_packages.message_work_package_status_blocked')\n };\n\n constructor(readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly schemaCache:SchemaCacheService,\n readonly halEditing:HalResourceEditingService) {\n super();\n }\n\n ngOnInit() {\n this.halEditing\n .temporaryEditResource(this.workPackage)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp) => {\n this.workPackage = wp;\n\n if (this.workPackage.status) {\n this.workPackage.status.$load();\n }\n\n this.cdRef.detectChanges();\n });\n }\n\n public get buttonTitle() {\n if (this.schema.isReadonly) {\n return this.text.workPackageReadOnly;\n } else if (this.schema.isEditable && !this.allowed) {\n return this.text.workPackageStatusBlocked;\n } else {\n return '';\n }\n }\n\n public get statusHighlightClass() {\n let status = this.status;\n if (!status) {\n return;\n }\n return Highlighting.backgroundClass('status', status.id!);\n }\n\n public get status():HalResource {\n return this.workPackage.status;\n }\n\n public get isReadonly() {\n return this.schema.isReadonly;\n }\n\n public get allowed() {\n return this.schema.isAttributeEditable('status');\n }\n\n private get schema() {\n if (this.halEditing.typedState(this.workPackage).hasValue()) {\n return this.halEditing.typedState(this.workPackage).value!.schema;\n } else {\n return this.schemaCache.of(this.workPackage) as ISchemaProxy;\n }\n }\n}\n","
    \n \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {ResourcesDisplayField} from \"./resources-display-field.module\";\nimport {cssClassCustomOption} from \"core-app/modules/fields/display/display-field.module\";\n\nexport class MultipleLinesCustomOptionsDisplayField extends ResourcesDisplayField {\n\n public render(element:HTMLElement, displayText:string):void {\n const values = this.value;\n element.setAttribute('title', displayText);\n element.textContent = displayText;\n\n element.innerHTML = '';\n\n if (values.length === 0) {\n this.renderEmpty(element);\n } else {\n this.renderValues(values, element);\n }\n }\n\n protected renderValues(values:string[], element:HTMLElement) {\n values.forEach((value) => {\n const div = document.createElement('div');\n div.classList.add(cssClassCustomOption, '-multiple-lines');\n div.setAttribute('title', value);\n div.textContent = value;\n\n element.appendChild(div);\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {MultipleLinesCustomOptionsDisplayField} from \"core-app/modules/fields/display/field-types/multiple-lines-custom-options-display-field.module\";\nimport {ProgressTextDisplayField} from \"core-app/modules/fields/display/field-types/progress-text-display-field.module\";\nimport {MultipleLinesUserFieldModule} from \"core-app/modules/fields/display/field-types/multiple-lines-user-display-field.module\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {ISchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DateDisplayField} from \"core-app/modules/fields/display/field-types/date-display-field.module\";\n\nexport const editableClassName = '-editable';\nexport const requiredClassName = '-required';\nexport const readOnlyClassName = '-read-only';\nexport const placeholderClassName = '-placeholder';\nexport const displayClassName = 'inline-edit--display-field';\nexport const editFieldContainerClass = 'inline-edit--container';\nexport const cellEmptyPlaceholder = '-';\n\nexport class DisplayFieldRenderer {\n\n @InjectField() displayFieldService:DisplayFieldService;\n @InjectField() schemaCache:SchemaCacheService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() I18n:I18nService;\n\n /** We cache the previously used fields to avoid reinitialization */\n private fieldCache:{ [key:string]:DisplayField } = {};\n\n constructor(public readonly injector:Injector,\n public readonly container:'table'|'single-view'|'timeline',\n public readonly options:{ [key:string]:any } = {}) {\n }\n\n public render(resource:T,\n name:string,\n change:ResourceChangeset|null,\n placeholder?:string):HTMLSpanElement {\n\n const [field, span] = this.renderFieldValue(resource, name, change, placeholder);\n\n if (field === null) {\n return span;\n }\n\n this.setSpanAttributes(span, field, name, resource, change);\n\n return span;\n }\n\n public renderFieldValue(resource:T,\n requestedAttribute:string,\n change:ResourceChangeset|null,\n placeholder?:string):[DisplayField|null, HTMLSpanElement] {\n const span = document.createElement('span');\n const schema = this.schema(resource, change);\n const attributeName = this.attributeName(requestedAttribute, schema);\n const fieldSchema = schema.ofProperty(attributeName);\n\n // If the resource does not have that field, return an empty\n // span (e.g., for the table).\n if (!fieldSchema) {\n return [null, span];\n }\n\n const field = this.getField(resource, fieldSchema, attributeName, change);\n field.render(span, this.getText(field, fieldSchema, placeholder), fieldSchema.options);\n\n const title = field.title;\n if (title) {\n span.setAttribute('title', title);\n }\n span.setAttribute('aria-label', this.getAriaLabel(field, schema));\n\n return [field, span];\n }\n\n public getField(resource:T,\n fieldSchema:IFieldSchema,\n attributeName:string,\n change:ResourceChangeset|null):DisplayField {\n let field = this.fieldCache[attributeName];\n\n if (!field) {\n field = this.fieldCache[attributeName] = this.getFieldForCurrentContext(resource, attributeName, fieldSchema);\n }\n\n field.apply(resource, fieldSchema);\n field.activeChange = change;\n\n return field;\n }\n\n private getFieldForCurrentContext(resource:T, attributeName:string, fieldSchema:IFieldSchema):DisplayField {\n const context:DisplayFieldContext = {container: this.container, injector: this.injector, options: this.options};\n\n // We handle multi value fields differently in the single view context\n const isCustomMultiLinesField = ['[]CustomOption'].indexOf(fieldSchema.type) >= 0;\n if (this.container === 'single-view' && isCustomMultiLinesField) {\n return new MultipleLinesCustomOptionsDisplayField(attributeName, context) as DisplayField;\n }\n const isUserMultiLinesField = ['[]User'].indexOf(fieldSchema.type) >= 0;\n if (this.container === 'single-view' && isUserMultiLinesField) {\n return new MultipleLinesUserFieldModule(attributeName, context) as DisplayField;\n }\n\n // We handle progress differently in the timeline\n if (this.container === 'timeline' && attributeName === 'percentageDone') {\n return new ProgressTextDisplayField(attributeName, context);\n }\n\n // We want to render an combined edit field but the display field must\n // show the original attribute\n if (this.container === 'table' && ['startDate', 'dueDate', 'date'].includes(attributeName)) {\n return new DateDisplayField(attributeName, context);\n }\n\n return this.displayFieldService.getField(resource, attributeName, fieldSchema, context);\n }\n\n private getText(field:DisplayField, fieldSchema:IFieldSchema, placeholder?:string):string {\n if (field.isEmpty()) {\n return placeholder || this.getDefaultPlaceholder(fieldSchema);\n } else {\n return field.valueString;\n }\n }\n\n private setSpanAttributes(span:HTMLElement, field:DisplayField, name:string, resource:T, change:ResourceChangeset|null):void {\n span.classList.add(displayClassName, name);\n span.dataset.fieldName = name;\n\n // Make span tabbable unless it's an id field\n span.setAttribute('tabindex', name === 'id' ? '-1' : '0');\n\n if (field.required) {\n span.classList.add(requiredClassName);\n }\n\n if (field.isEmpty()) {\n span.classList.add(placeholderClassName);\n }\n\n const schema = this.schema(resource, change);\n if (this.isAttributeEditable(schema, name)) {\n span.classList.add(editableClassName);\n span.setAttribute('role', 'button');\n } else {\n span.classList.add(readOnlyClassName);\n }\n }\n\n private isAttributeEditable(schema:SchemaResource, fieldName:string) {\n // We need to handle start/due date cases like they were combined dates\n if (['startDate', 'dueDate', 'date'].includes(fieldName)) {\n fieldName = 'combinedDate';\n }\n\n return schema.isAttributeEditable(fieldName);\n }\n\n private getAriaLabel(field:DisplayField, schema:SchemaResource):string {\n let titleContent;\n let labelContent = this.getLabelContent(field);\n\n if (field.isFormattable && !field.isEmpty()) {\n try {\n titleContent = _.escape(jQuery(`
    ${labelContent}
    `).text());\n } catch (e) {\n console.error(\"Failed to parse formattable labelContent\");\n titleContent = \"Label for \" + field.displayName;\n }\n\n } else {\n titleContent = labelContent;\n }\n\n if (field.writable && schema.isAttributeEditable(field.name)) {\n return this.I18n.t('js.inplace.button_edit', {attribute: `${field.displayName} ${titleContent}`});\n } else {\n return `${field.displayName} ${titleContent}`;\n }\n }\n\n private getLabelContent(field:DisplayField):string {\n if (field.isEmpty()) {\n return this.I18n.t('js.inplace.null_value_label');\n } else {\n return field.valueString;\n }\n }\n\n /**\n * Get the attribute name from either the schema if the mappedName method is implemented or\n * return the attribute itself.\n *\n * @param schema\n * @param attribute\n */\n private attributeName(attribute:string, schema:SchemaResource) {\n if (schema.mappedName) {\n return schema.mappedName(attribute);\n } else {\n return attribute;\n }\n }\n\n private getDefaultPlaceholder(fieldSchema:IFieldSchema):string {\n if (fieldSchema.type === 'Formattable') {\n return this.I18n.t('js.work_packages.placeholders.formattable', {name: fieldSchema.name});\n }\n\n return cellEmptyPlaceholder;\n }\n\n private schema(resource:T, change:ResourceChangeset|null) {\n if (!!change) {\n return change.schema;\n } else if (this.halEditing.typedState(resource).hasValue()) {\n return this.halEditing.typedState(resource).value!.schema;\n } else {\n return this.schemaCache.of(resource) as ISchemaProxy;\n }\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\n\nimport {Injectable} from \"@angular/core\";\nimport {input} from \"reactivestates\";\nimport {Observable} from \"rxjs\";\nimport {takeUntil} from \"rxjs/operators\";\n\nexport type ModelLinks = {[action:string]:any};\nexport type ModelLinksHash = { [model:string]:ModelLinks };\n\n@Injectable({ providedIn: 'root' })\nexport class AuthorisationService {\n private links = input({});\n\n public initModelAuth(modelName:string, modelLinks:ModelLinks) {\n this.links.doModify((value:ModelLinksHash) => {\n let links = { ...value };\n links[modelName] = modelLinks;\n return links;\n });\n }\n\n public observeUntil(unsubscribe:Observable) {\n return this.links.values$().pipe(takeUntil(unsubscribe));\n }\n\n public can(modelName:string, action:string) {\n const links:ModelLinksHash = this.links.getValueOr({});\n return links[modelName] && (action in links[modelName]);\n }\n\n public cannot(modelName:string, action:string) {\n return !this.can(modelName, action);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {AttachmentCollectionResource} from 'core-app/modules/hal/resources/attachment-collection-resource';\nimport {OpenProjectFileUploadService, UploadFile} from 'core-components/api/op-file-upload/op-file-upload.service';\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {HttpErrorResponse} from \"@angular/common/http\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport { OpenProjectDirectFileUploadService } from 'core-app/components/api/op-file-upload/op-direct-file-upload.service';\n\ntype Constructor = new (...args:any[]) => T;\n\nexport function Attachable>(Base:TBase) {\n return class extends Base {\n public attachments:AttachmentCollectionResource;\n\n private NotificationsService:NotificationsService;\n private halNotification:HalResourceNotificationService;\n private opFileUpload:OpenProjectFileUploadService;\n private opDirectFileUpload:OpenProjectDirectFileUploadService;\n private pathHelper:PathHelperService;\n private apiV3Service:APIV3Service;\n private config:ConfigurationService;\n\n /**\n * Can be used in the mixed in class to disable\n * attempts to upload attachments right away.\n */\n private attachmentsBackend:boolean|null;\n\n /**\n * Return whether the user is able to upload an attachment.\n *\n * If either the `addAttachment` link is provided or the resource is being created,\n * adding attachments is allowed.\n */\n public get canAddAttachments():boolean {\n return !!this.$links.addAttachment || this.isNew;\n }\n\n /**\n *\n */\n public get hasAttachments():boolean {\n return _.get(this.attachments, 'elements.length', 0) > 0;\n }\n\n /**\n * Try to find an existing file's download URL given its filename\n * @param file\n */\n public lookupDownloadLocationByName(file:string):string|null {\n if (!(this.attachments && this.attachments.elements)) {\n return null;\n }\n\n const match = _.find(this.attachments.elements, (res:HalResource) => res.name === file);\n return _.get(match, 'staticDownloadLocation.href', null);\n }\n\n /**\n * Remove the given attachment either from the pending attachments or from\n * the attachment collection, if it is a resource.\n *\n * Removing it from the elements array assures that the view gets updated immediately.\n * If an error occurs, the user gets notified and the attachment is pushed to the elements.\n */\n public removeAttachment(attachment:any):Promise {\n _.pull(this.attachments.elements, attachment);\n\n if (attachment.$isHal) {\n return attachment.delete()\n .then(() => {\n if (!!this.attachmentsBackend) {\n this.updateAttachments();\n } else {\n this.attachments.count = Math.max(this.attachments.count - 1, 0);\n }\n })\n .catch((error:any) => {\n this.halNotification.handleRawError(error, this as any);\n this.attachments.elements.push(attachment);\n });\n }\n return Promise.resolve();\n }\n\n /**\n * Get updated attachments from the server and push the state\n *\n * Return a promise that returns the attachments. Reject, if the work package has\n * no attachments.\n */\n public updateAttachments():Promise {\n return this\n .attachments\n .updateElements()\n .then(() => {\n this.updateState();\n return this.attachments;\n });\n }\n\n /**\n * Upload the given attachments, update the resource and notify the user.\n * Return an updated AttachmentCollectionResource.\n */\n public uploadAttachments(files:UploadFile[]):Promise<{ response:HalResource, uploadUrl:string }[]> {\n const {uploads, finished} = this.performUpload(files);\n\n const message = I18n.t('js.label_upload_notification');\n const notification = this.NotificationsService.addAttachmentUpload(message, uploads);\n\n return finished\n .then((result:{ response:HalResource, uploadUrl:string }[]) => {\n setTimeout(() => this.NotificationsService.remove(notification), 700);\n\n this.attachments.count += result.length;\n result.forEach(r => {\n this.attachments.elements.push(r.response);\n });\n this.updateState();\n\n return result;\n })\n .catch((error:HttpErrorResponse) => {\n let message:undefined|string;\n console.error(\"Error while uploading: %O\", error);\n\n if (error.error instanceof ErrorEvent) {\n // A client-side or network error occurred.\n message = this.I18n.t('js.error_attachment_upload', {error: error});\n } else if (_.get(error, 'error._type') === 'Error') {\n message = error.error.message;\n } else {\n // The backend returned an unsuccessful response code.\n message = error.error;\n }\n\n this.halNotification.handleRawError(message);\n return message || I18n.t('js.error.internal');\n });\n }\n\n private performUpload(files:UploadFile[]) {\n let href:string = this.directUploadURL || '';\n\n if (href) {\n return this.opDirectFileUpload.uploadAndMapResponse(href, files);\n } else if (this.isNew || !this.id || !this.attachmentsBackend) {\n href = this.apiV3Service.attachments.path;\n } else {\n href = this.addAttachment.$link.href;\n }\n\n return this.opFileUpload.uploadAndMapResponse(href, files);\n }\n\n private get directUploadURL():string|null {\n if (this.$links.prepareAttachment) {\n return this.$links.prepareAttachment.href;\n }\n\n if (this.isNew) {\n return this.config.prepareAttachmentURL;\n } else {\n return null;\n }\n }\n\n private updateState() {\n if (this.state) {\n this.state.putValue(this as any);\n }\n }\n\n public $initialize(source:any) {\n if (!this.NotificationsService) {\n this.NotificationsService = this.injector.get(NotificationsService);\n }\n if (!this.halNotification) {\n this.halNotification = this.injector.get(HalResourceNotificationService);\n }\n if (!this.opFileUpload) {\n this.opFileUpload = this.injector.get(OpenProjectFileUploadService);\n }\n if (!this.opDirectFileUpload) {\n this.opDirectFileUpload = this.injector.get(OpenProjectDirectFileUploadService);\n }\n if (!this.config) {\n this.config = this.injector.get(ConfigurationService);\n }\n if (!this.pathHelper) {\n this.pathHelper = this.injector.get(PathHelperService);\n }\n\n if (!this.apiV3Service) {\n this.apiV3Service = this.injector.get(APIV3Service);\n }\n\n super.$initialize(source);\n\n let attachments = this.attachments || {$source: {}, elements: []};\n this.attachments = new AttachmentCollectionResource(\n this.injector,\n attachments,\n false,\n this.halInitializer,\n 'HalResource'\n );\n }\n };\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {DisplayFieldContext} from \"core-app/modules/fields/display/display-field.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport interface IFieldSchema {\n type:string;\n writable:boolean;\n allowedValues?:any;\n required?:boolean;\n hasDefault:boolean;\n name?:string;\n options?:any;\n}\n\nexport class Field extends UntilDestroyedMixin {\n public static type:string;\n public resource:any;\n public name:string;\n public schema:IFieldSchema;\n public context:DisplayFieldContext;\n\n public get displayName():string {\n return this.schema.name || this.name;\n }\n\n public get value() {\n return this.resource[this.name];\n }\n\n public get type():string {\n return (this.constructor as typeof Field).type;\n }\n\n public get required():boolean {\n return !!this.schema.required;\n }\n\n public get writable():boolean {\n return this.schema.writable && this.context.options.writable !== false;\n }\n\n public get hasDefault():boolean {\n return this.schema.hasDefault;\n }\n\n public get options():boolean {\n return this.schema.options;\n }\n\n public isEmpty():boolean {\n return !this.value;\n }\n\n public get unknownAttribute():boolean {\n return this.isEmpty && !this.schema;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 type HalSourceLink = { href:string|null };\n\nexport type HalSourceLinks = {\n [key:string]:HalSourceLink\n};\n\nexport type HalSource = {\n [key:string]:string|number|null|HalSourceLinks,\n _links:HalSourceLinks\n};\n\nexport class HalResource {\n // TODO this is the source of many issues in the frontend\n // because it no longer properly type checks stuff\n // Since 2019-10-21 I'm documenting what bugs this caused:\n // https://community.openproject.com/wp/31462\n [attribute:string]:any;\n\n // The API type reported from API\n public _type:string;\n\n // Internal initialization time for objects\n // created in the frontend\n public __initialized_at:Number;\n\n // The HalResource that this type maps to\n // This will almost always be equal to _type, however may be different for dynamic types\n // e.g., { _type: 'StatusFilterInstance', $halType: 'QueryFilterInstance' }.\n //\n // This is required for attributes to be correctly mapped according to their configuration.\n public $halType:string;\n\n @InjectField() states:States;\n @InjectField() I18n:I18nService;\n\n /**\n * Constructs and initializes the HalResource. For this, the halResoureFactory is required.\n *\n * However, We can't inject the HalResourceFactory here because it itself depends on this class.\n * So if you need to initialize a HalResource, use +HalResourceFactory.createHalResource+ instead.\n *\n * @param {Injector} injector\n * @param $halType The HalResource type that this instance maps to\n * @param $source\n * @param {boolean} $loaded\n * @param {Function} initializer The initializer callback to HAL-transform all linked and embedded resources.\n *\n */\n public constructor(public injector:Injector,\n public $source:any,\n public $loaded:boolean,\n public halInitializer:(halResource:any) => void,\n $halType:string) {\n this.$halType = $halType;\n this.$initialize($source);\n }\n\n public static getEmptyResource(self:{ href:string|null } = {href: null}):any {\n return {_links: {self: self}};\n }\n\n public $links:any = {};\n public $embedded:any = {};\n public $self:Promise;\n\n public _name:string;\n\n public static idFromLink(href:string):string {\n return href.split('/').pop()!;\n }\n\n public get idFromLink():string {\n if (this.$href) {\n return HalResource.idFromLink(this.$href);\n }\n\n return '';\n }\n\n public $initialize(source:any) {\n this.$source = source.$source || source;\n this.halInitializer(this);\n }\n\n /**\n * Override toString to ensure the resource can\n * be printed nicely on console and in errors\n */\n public toString() {\n if (this.$href) {\n return `[HalResource href=${this.$href}]`;\n } else {\n return `[HalResource id=${this.id}]`;\n }\n }\n\n /**\n * Returns the ID and ensures it's a string, null.\n * Returns a string when:\n * - The embedded ID is actually set\n * - The self link is terminated by a number.\n */\n public get id():string|null {\n if (this.$source.id) {\n return this.$source.id.toString();\n }\n\n const id = this.idFromLink;\n if (id.match(/^\\d+$/)) {\n return id;\n }\n\n return null;\n }\n\n public set id(val:string|null) {\n this.$source.id = val;\n }\n\n public get isNew():boolean {\n return !this.id || this.id === 'new';\n }\n\n public get persisted() {\n return !!(this.id && this.id !== 'new');\n }\n\n /**\n * Retain the internal tracking identifier from the given other work package.\n * This is due to us needing to identify a work package beyond its actual ID,\n * because that changes upon saving.\n *\n * @param other\n */\n public retainFrom(other:HalResource) {\n this.__initialized_at = other.__initialized_at;\n }\n\n\n /**\n * Create a HalResource from the copied source of the given, other HalResource.\n *\n * @param {HalResource} other\n * @returns A HalResource with the identitical copied source of other.\n */\n public $copy(source:Object = {}):T {\n let clone:HalResourceClass = this.constructor as any;\n\n return new clone(this.injector, _.merge(this.$plain(), source), this.$loaded, this.halInitializer, this.$halType);\n }\n\n public $plain():any {\n return _.cloneDeep(this.$source);\n }\n\n public get $isHal():boolean {\n return true;\n }\n\n public get $link():HalLinkInterface {\n return this.$links.self.$link;\n }\n\n public get name():string {\n return this._name || this.$link.title || '';\n }\n\n public set name(name:string) {\n this._name = name;\n }\n\n /**\n * Alias for $href.\n */\n public get href():string|null {\n return this.$link.href;\n }\n\n public get $href():string|null {\n return this.$link.href;\n }\n\n /**\n * Return the associated state to this HAL resource, if any.\n */\n public get state():InputState|null {\n return null;\n }\n\n /**\n * Update the state\n */\n public push(newValue:this):Promise {\n if (this.state) {\n this.state.putValue(newValue);\n }\n\n return Promise.resolve();\n }\n\n public previewPath():string|undefined {\n if (this.isNew && this.project) {\n return this.project.href;\n }\n\n return undefined;\n }\n\n public getEditorTypeFor(_fieldName:string):'full'|'constrained' {\n return 'constrained';\n }\n\n public $load(force = false):Promise {\n if (!this.state) {\n return this.$loadResource(force);\n }\n\n const state = this.state;\n\n if (force) {\n state.clear();\n }\n\n // If nobody has asked yet for the resource to be $loaded, do it ourselves.\n // Otherwise, we risk returning a promise, that will never be resolved.\n state.putFromPromiseIfPristine(() => this.$loadResource(force));\n\n return >state.valuesPromise().then((source:any) => {\n this.$initialize(source);\n this.$loaded = true;\n return this;\n });\n }\n\n protected $loadResource(force = false):Promise {\n if (!force) {\n if (this.$loaded) {\n return Promise.resolve(this);\n }\n\n if (!this.$loaded && this.$self) {\n return this.$self;\n }\n }\n\n // Reset and load this resource\n this.$loaded = false;\n this.$self = this.$links.self({}).then((source:any) => {\n this.$loaded = true;\n this.$initialize(source.$source);\n return this;\n });\n\n return this.$self;\n }\n\n /**\n * Update the resource ignoring the cache.\n */\n public $update() {\n return this.$load(true);\n }\n\n /**\n * Specify this resource's embedded keys that should be transformed with resources.\n * Use this to restrict, e.g., links that should not be made properties if you have a custom get/setter.\n */\n public $embeddableKeys():string[] {\n const properties = Object.keys(this.$source);\n return _.without(properties, '_links', '_embedded', 'id');\n }\n\n /**\n * Specify this resource's keys that should not be transformed with resources.\n * Use this to restrict, e.g., links that should not be made properties if you have a custom get/setter.\n */\n public $linkableKeys():string[] {\n const properties = Object.keys(this.$links);\n return _.without(properties, 'self');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {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 {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {AngularTrackingHelpers} from 'core-components/angular/tracking-functions';\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {BannersService} from \"core-app/modules/common/enterprise/banners.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Component({\n selector: '[query-filter]',\n templateUrl: './query-filter.component.html'\n})\nexport class QueryFilterComponent implements OnInit {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new EventEmitter();\n @Output() public deactivateFilter = new EventEmitter();\n\n public availableOperators:any;\n public showValuesInput:boolean = false;\n public eeShowBanners:boolean = false;\n public trackByHref = AngularTrackingHelpers.halHref;\n public compareByHref = AngularTrackingHelpers.compareByHref;\n\n public text = {\n open_filter: this.I18n.t('js.filter.description.text_open_filter'),\n close_filter: this.I18n.t('js.filter.description.text_close_filter'),\n label_filter_add: this.I18n.t('js.work_packages.label_filter_add'),\n upsale_for_more: this.I18n.t('js.filter.upsale_for_more'),\n upsale_link: this.I18n.t('js.filter.upsale_link'),\n button_delete: this.I18n.t('js.button_delete'),\n };\n\n constructor(readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly schemaCache:SchemaCacheService,\n readonly I18n:I18nService,\n readonly bannerService:BannersService) {\n }\n\n public onFilterUpdated(filter:QueryFilterInstanceResource) {\n this.filter = filter;\n this.showValuesInput = this.showValues(this.filter);\n this.filterChanged.emit(this.filter);\n }\n\n public removeThisFilter() {\n this.deactivateFilter.emit(this.filter);\n }\n\n public get valueType():string|undefined {\n if (this.filter.currentSchema && this.filter.currentSchema.values) {\n return this.filter.currentSchema.values.type;\n }\n\n return undefined;\n }\n\n ngOnInit() {\n this.eeShowBanners = this.bannerService.eeShowBanners;\n this.availableOperators = this.schemaCache.of(this.filter).availableOperators;\n this.showValuesInput = this.showValues(this.filter);\n }\n\n private showValues(filter:QueryFilterInstanceResource) {\n return this.filter.currentSchema!.isValueRequired() && this.filter.currentSchema!.values!.type !== '[1]Boolean';\n }\n}\n","\n \n \n\n \n
    \n\n \n\n \n \n \n\n
    \n\n \n \n
    \n \n\n \n\n \n\n \n\n \n\n \n\n \n\n\n \n
    \n
    \n\n
    \n
    \n\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\n .apiV3Service\n .work_packages\n .id(this.copiedWorkPackageId)\n .get()\n .pipe(\n take(1)\n )\n .subscribe((wp:WorkPackageResource) => {\n this.createCopyFrom(wp).then(resolve, reject);\n });\n });\n }\n\n protected setTitle() {\n this.titleService.setFirstPart(this.I18n.t('js.work_packages.copy.title'));\n }\n\n private createCopyFrom(wp:WorkPackageResource) {\n let sourceChangeset = this.halEditing.changeFor(wp) as WorkPackageChangeset;\n\n return this.wpCreate\n .copyWorkPackage(sourceChangeset)\n .then((copyChangeset:WorkPackageChangeset) => {\n this.__initialized_at = copyChangeset.pristineResource.__initialized_at;\n\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(copyChangeset.pristineResource, true);\n\n this.halEditing.updateValue('new', copyChangeset);\n\n return copyChangeset;\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageViewColumnsService} from './wp-view-columns.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageViewHierarchiesService} from './wp-view-hierarchy.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {RelationsStateValue, WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageViewAdditionalElementsService {\n\n constructor(readonly querySpace:IsolatedQuerySpace,\n readonly wpTableHierarchies:WorkPackageViewHierarchiesService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly notificationService:WorkPackageNotificationService,\n readonly halResourceService:HalResourceService,\n readonly apiV3Service:APIV3Service,\n readonly schemaCache:SchemaCacheService,\n readonly wpRelations:WorkPackageRelationsService) {\n }\n\n public initialize(query:QueryResource, results:WorkPackageCollectionResource) {\n const rows = results.elements;\n\n // Add relations to the stack\n Promise.all([\n this.requireInvolvedRelations(rows.map(el => el.id!)),\n this.requireHierarchyElements(rows),\n this.requireSumsSchema(results)\n ]).then((results:string[][]) => {\n this.loadAdditional(_.flatten(results));\n });\n }\n\n private loadAdditional(wpIds:string[]) {\n this\n .apiV3Service\n .work_packages\n .requireAll(wpIds)\n .then(() => {\n this.querySpace.additionalRequiredWorkPackages.putValue(null, 'All required work packages are loaded');\n })\n .catch((e) => {\n this.querySpace.additionalRequiredWorkPackages.putValue(null, 'Failure loading required work packages');\n this.notificationService.handleRawError(e);\n });\n }\n\n /**\n * Requires both the relation resource of the given work package ids as well\n * as the `to` work packages returned from the relations\n */\n private requireInvolvedRelations(rows:string[]):Promise {\n\n if (!this.wpTableColumns.hasRelationColumns()) {\n return Promise.resolve([]);\n }\n return this.wpRelations\n .requireAll(rows)\n .then(() => {\n const ids = this.getInvolvedWorkPackages(rows.map(id => {\n return this.wpRelations.state(id).value!;\n }));\n return _.flatten(ids);\n });\n }\n\n /**\n * Return the id of all ancestors for visible rows in the table.\n * @param rows\n * @return {string[]}\n */\n private requireHierarchyElements(rows:WorkPackageResource[]):Promise {\n if (!this.wpTableHierarchies.isEnabled) {\n return Promise.resolve([]);\n }\n\n const ids = _.flatten(rows.map(el => el.ancestorIds));\n return Promise.resolve(ids);\n }\n\n /**\n * From a set of relations state values, return all involved IDs.\n * @param states\n * @return {string[]}\n */\n private getInvolvedWorkPackages(states:RelationsStateValue[]) {\n const ids:string[] = [];\n _.each(states, (relations:RelationsStateValue) => {\n _.each(relations, (resource:RelationResource) => {\n ids.push(resource.ids.from, resource.ids.to);\n });\n });\n\n return ids;\n }\n\n private requireSumsSchema(results:WorkPackageCollectionResource):Promise {\n if (results.sumsSchema) {\n return this\n .schemaCache\n .ensureLoaded(results.sumsSchema.$href!)\n .then(() => []);\n }\n\n return Promise.resolve([]);\n }\n}\n","import {createPointCB, getClientRect as getRect, pointInside} from 'dom-plane';\n\nexport class DomAutoscrollService {\n public elements:Element[];\n public scrolling:boolean;\n public down:boolean = false;\n public scrollWhenOutside:boolean;\n public autoScroll:() => boolean;\n public maxSpeed:number;\n public margin:number;\n public animationFrame:number;\n public windowAnimationFrame:number;\n public current:HTMLElement[];\n public outerScrollContainer:HTMLElement;\n public point:any;\n public pointCB:any;\n\n constructor(elements:Element[],\n params:any) {\n this.elements = elements;\n this.scrollWhenOutside = params.scrollWhenOutside || false;\n this.maxSpeed = params.maxSpeed || 5;\n this.margin = params.margin || 10;\n this.scrollWhenOutside = params.scrollWhenOutside || false;\n this.autoScroll = params.autoScroll;\n this.point = {};\n this.pointCB = createPointCB(this.point);\n\n this.init();\n }\n\n public init() {\n jQuery(window).on('mousemove.domautoscroll touchmove.domautoscroll', (evt:any) => {\n if (this.down) {\n this.pointCB(evt);\n this.onMove(evt);\n }\n });\n jQuery(window).on('mousedown.domautoscroll touchstart.domautoscroll', () => this.down = true);\n jQuery(window).on('mouseup.domautoscroll touchend.domautoscroll', () => this.onUp());\n jQuery(window).on('scroll.domautoscroll', (evt:any) => this.setScroll(evt));\n }\n\n public destroy() {\n jQuery(window).off('.domautoscroll');\n\n this.elements = [];\n this.cleanAnimation();\n }\n\n public add(el:Element|Element[]) {\n if (Array.isArray(el)) {\n this.elements = this.elements.concat(el);\n\n // Remove duplicates\n this.elements = Array.from(new Set(this.elements));\n } else {\n this.elements.push(el);\n }\n }\n\n public onUp() {\n this.down = false;\n cancelAnimationFrame(this.animationFrame);\n cancelAnimationFrame(this.windowAnimationFrame);\n }\n\n public setScroll(e:any) {\n for (let i = 0; i < this.elements.length; i++) {\n if (this.elements[i] === e.target) {\n this.scrolling = true;\n break;\n }\n }\n\n if (this.scrolling) {\n requestAnimationFrame(() => this.scrolling = false);\n }\n }\n\n public cleanAnimation() {\n cancelAnimationFrame(this.animationFrame);\n cancelAnimationFrame(this.windowAnimationFrame);\n }\n\n public getTarget(target:HTMLElement):HTMLElement[] {\n if (!target) {\n return [];\n }\n\n let results = [];\n if (this.elements.includes(target)) {\n results.push(target);\n }\n\n let targetObject = target;\n while (targetObject = targetObject.parentNode as HTMLElement) {\n if (this.elements.includes(targetObject)) {\n results.push(targetObject);\n }\n }\n\n return results;\n }\n\n public getElementsUnderPoint():HTMLElement[] {\n let underPoint = [];\n\n for (var i = 0; i < this.elements.length; i++) {\n if (this.inside(this.point, this.elements[i])) {\n underPoint.push(this.elements[i] as HTMLElement);\n }\n }\n\n return underPoint;\n }\n\n public onMove(event:any) {\n if (!this.autoScroll()) {\n return;\n }\n\n if (event.dispatched) {\n return;\n }\n\n let target = [] as HTMLElement[];\n if (event.target !== null) {\n target.push(event.target as HTMLElement);\n }\n let body = document.body;\n\n if (target.length > 0 && target[0].parentNode === body) {\n //The special condition to improve speed.\n target = this.getElementsUnderPoint();\n } else {\n target = this.getTarget(target[0]);\n\n if (target.length === 0) {\n target = this.getElementsUnderPoint();\n }\n }\n\n this.current = target;\n\n if (this.current.length === 0) {\n this.current = [this.outerScrollContainer];\n }\n\n cancelAnimationFrame(this.animationFrame);\n this.animationFrame = requestAnimationFrame(this.scrollTick.bind(this));\n }\n\n public setOuterScrollContainer(el:HTMLElement) {\n this.outerScrollContainer = el;\n }\n\n public scrollTick() {\n if (this.current.length === 0) {\n return;\n }\n\n this.current.forEach((e?:Element) => {\n if (e) {\n this.scrollAutomatically(e);\n }\n });\n\n cancelAnimationFrame(this.animationFrame);\n this.animationFrame = requestAnimationFrame(this.scrollTick.bind(this));\n\n }\n\n\n public scrollAutomatically(el:Element) {\n let rect = getRect(el);\n let scrollx:number;\n let scrolly:number;\n\n if (this.point.x < rect.left + this.margin) {\n scrollx = -this.maxSpeed;\n } else if (this.point.x > rect.right - this.margin) {\n scrollx = this.maxSpeed;\n } else {\n scrollx = 0;\n }\n\n if (this.point.y < rect.top + this.margin) {\n scrolly = -this.maxSpeed;\n } else if (this.point.y > rect.bottom - this.margin) {\n scrolly = this.maxSpeed;\n } else {\n scrolly = 0;\n }\n\n setTimeout(() => {\n if (scrolly) {\n this.scrollY(el, scrolly);\n }\n\n if (scrollx) {\n this.scrollX(el, scrollx);\n }\n });\n }\n\n public scrollY(el:any, amount:number) {\n if (el === window) {\n window.scrollTo(el.pageXOffset, el.pageYOffset + amount);\n } else {\n el.scrollTop += amount;\n }\n }\n\n public scrollX(el:any, amount:number) {\n if (el === window) {\n window.scrollTo(el.pageXOffset + amount, el.pageYOffset);\n } else {\n el.scrollLeft += amount;\n }\n }\n\n public inside(point:any, el:Element, rect?:any) {\n if (!rect) {\n return pointInside(point, el);\n } else {\n return (point.y > rect.top && point.y < rect.bottom &&\n point.x > rect.left && point.x < rect.right);\n }\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {RootResource} from 'core-app/modules/hal/resources/root-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n Input,\n OnInit,\n Output,\n ViewChild\n} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {AngularTrackingHelpers} from 'core-components/angular/tracking-functions';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {HalResourceSortingService} from \"core-app/modules/hal/services/hal-resource-sorting.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {CurrentUserService} from \"core-components/user/current-user.service\";\n\n@Component({\n selector: 'filter-toggled-multiselect-value',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './filter-toggled-multiselect-value.component.html'\n})\nexport class FilterToggledMultiselectValueComponent implements OnInit, AfterViewInit {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new EventEmitter();\n\n @ViewChild('ngSelectInstance', { static: true }) ngSelectInstance:NgSelectComponent;\n\n public _availableOptions:HalResource[] = [];\n public compareByHrefOrString = AngularTrackingHelpers.compareByHrefOrString;\n\n private _isEmpty:boolean;\n\n readonly text = {\n placeholder: this.I18n.t('js.placeholders.selection'),\n };\n\n constructor(readonly halResourceService:HalResourceService,\n readonly halSorting:HalResourceSortingService,\n readonly PathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly currentUser:CurrentUserService,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n }\n\n ngOnInit() {\n this.fetchAllowedValues();\n }\n\n ngAfterViewInit():void {\n if (this.ngSelectInstance && this.shouldFocus) {\n this.ngSelectInstance.focus();\n }\n }\n\n public get value() {\n return this.filter.values;\n }\n\n public setValues(val:any) {\n this.filter.values = _.castArray(val);\n this.filterChanged.emit(this.filter);\n this.cdRef.detectChanges();\n }\n\n public get availableOptions() {\n return this._availableOptions;\n }\n\n public set availableOptions(val:HalResource[]) {\n this._availableOptions = this.halSorting.sort(val);\n }\n\n public get isEmpty():boolean {\n return this._isEmpty = this.value.length === 0;\n }\n\n public repositionDropdown() {\n if (this.ngSelectInstance) {\n setTimeout(() => {\n const component = (this.ngSelectInstance) as any;\n if (component && component.dropdownPanel) {\n component.dropdownPanel._updatePosition();\n }\n }, 25);\n }\n }\n\n private get isUserResource() {\n let type = _.get(this.filter.currentSchema, 'values.type', null);\n return type && type.indexOf('User') > 0;\n }\n\n private fetchAllowedValues() {\n if ((this.filter.currentSchema!.values!.allowedValues as CollectionResource)['$load']) {\n this.loadAllowedValues();\n } else {\n this.availableOptions = (this.filter.currentSchema!.values!.allowedValues as HalResource[]);\n }\n }\n\n private loadAllowedValues() {\n let valuesSchema = this.filter.currentSchema!.values!;\n let loadingPromises = [(valuesSchema.allowedValues as any).$load()];\n\n // If it is a User resource, we want to have the 'me' option.\n // We therefore fetch the current user from the api and copy\n // the current user's value from the set of allowedValues. The\n // copy will have it's name altered to 'me' and will then be\n // prepended to the list.\n if (this.isUserResource) {\n loadingPromises.push(this.apiV3Service.root.get().toPromise());\n }\n\n Promise.all(loadingPromises)\n .then(((resources:Array) => {\n let options = (resources[0] as CollectionResource).elements;\n\n this.availableOptions = options;\n\n if (this.isUserResource && this.filter.filter.id !== 'memberOfGroup') {\n this.addMeValue((resources[1] as RootResource).user);\n }\n }));\n }\n\n private addMeValue(currentUser:UserResource) {\n if (!(currentUser && currentUser.$href)) {\n return;\n }\n\n let me:HalResource = this.halResourceService.createHalResource(\n {\n _links: {\n self: {\n href: this.apiV3Service.users.me,\n title: this.I18n.t('js.label_me')\n }\n }\n }, true\n );\n\n this._availableOptions.unshift(me);\n }\n}\n","
    \n\n \n \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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-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 * as moment from 'moment';\nimport flatpickr from 'flatpickr';\nimport {Instance} from 'flatpickr/dist/types/instance';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport DateOption = flatpickr.Options.DateOption;\n\nexport class DatePicker {\n private datepickerFormat = 'Y-m-d';\n\n private datepickerCont:HTMLElement = document.querySelector(this.datepickerElemIdentifier)! as HTMLElement;\n public datepickerInstance:Instance;\n private reshowTimeout:any;\n\n constructor(private datepickerElemIdentifier:string,\n private date:any,\n private options:any,\n private datepickerTarget?:HTMLElement,\n private configurationService?:ConfigurationService) {\n this.initialize(options);\n }\n\n private initialize(options:any) {\n const I18n = new I18nService();\n const firstDayOfWeek =\n this.configurationService?.startOfWeekPresent() ? this.configurationService.startOfWeek() : 1;\n\n const mergedOptions = _.extend({}, options, {\n weekNumbers: true,\n getWeek(dateObj:Date) {\n return moment(dateObj).week();\n },\n dateFormat: this.datepickerFormat,\n defaultDate: this.date,\n locale: {\n weekdays: {\n shorthand: I18n.t('date.abbr_day_names'),\n longhand: I18n.t('date.day_names'),\n },\n months: {\n shorthand: (I18n.t('date.abbr_month_names') as any).slice(1),\n longhand: (I18n.t('date.month_names') as any).slice(1),\n },\n firstDayOfWeek: firstDayOfWeek,\n weekAbbreviation: I18n.t('date.abbr_week')\n },\n });\n\n var datePickerInstances:Instance|Instance[];\n if (this.datepickerTarget) {\n datePickerInstances = flatpickr(this.datepickerTarget as Node, mergedOptions);\n } else {\n datePickerInstances = flatpickr(this.datepickerElemIdentifier, mergedOptions);\n }\n\n this.datepickerInstance = Array.isArray(datePickerInstances) ? datePickerInstances[0] : datePickerInstances;\n\n document.addEventListener('scroll', this.hideDuringScroll, true);\n }\n\n public clear() {\n this.datepickerInstance.clear();\n }\n\n public destroy() {\n this.hide();\n this.datepickerInstance.destroy();\n }\n\n public hide() {\n if (this.isOpen) {\n this.datepickerInstance.close();\n }\n\n document.removeEventListener('scroll', this.hideDuringScroll, true);\n }\n\n public show() {\n this.datepickerInstance.open();\n document.addEventListener('scroll', this.hideDuringScroll, true);\n }\n\n public setDates(dates:DateOption|DateOption[]) {\n this.datepickerInstance.setDate(dates);\n }\n\n public get isOpen():boolean {\n return this.datepickerInstance.isOpen;\n }\n\n private hideDuringScroll = (event:Event) => {\n // Prevent Firefox quirk: flatPicker emits\n // multiple scrolls event when it is open\n const target = event.target! as HTMLInputElement;\n\n if (target.classList.contains('flatpickr-monthDropdown-months')) {\n return;\n }\n\n this.datepickerInstance.close();\n\n if (this.reshowTimeout) {\n clearTimeout(this.reshowTimeout);\n }\n\n this.reshowTimeout = setTimeout(() => {\n if (this.visibleAndActive()) {\n this.datepickerInstance.open();\n }\n }, 50);\n }\n\n private visibleAndActive() {\n try {\n return this.isInViewport(this.datepickerCont) &&\n document.activeElement === this.datepickerCont;\n } catch (e) {\n console.error('Failed to test visibleAndActive ' + e);\n return false;\n }\n }\n\n private isInViewport(element:HTMLElement) {\n const rect = element.getBoundingClientRect();\n\n return (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\n rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {GridResource} from \"core-app/modules/hal/resources/grid-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\n\nexport class GridWidgetResource extends HalResource {\n @InjectField() protected halResource:HalResourceService;\n public identifier:string;\n public startRow:number;\n public endRow:number;\n public startColumn:number;\n public endColumn:number;\n\n public options:{[key:string]:unknown};\n\n public get height() {\n return this.endRow - this.startRow;\n }\n\n public get width() {\n return this.endColumn - this.startColumn;\n }\n\n public grid:GridResource;\n\n public get schema():SchemaResource {\n return this.halResource.createHalResource({'_type': 'Schema' }, true);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {StateService} from '@uirouter/core';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injectable, Injector} from '@angular/core';\nimport {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HttpErrorResponse} from \"@angular/common/http\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Injectable()\nexport class HalResourceNotificationService {\n\n @InjectField() protected I18n:I18nService;\n @InjectField() protected $state:StateService;\n @InjectField() protected halResourceService:HalResourceService;\n @InjectField() protected NotificationsService:NotificationsService;\n @InjectField() protected loadingIndicator:LoadingIndicatorService;\n @InjectField() protected schemaCache:SchemaCacheService;\n\n constructor(public injector:Injector) {\n }\n\n public showSave(resource:HalResource, isCreate:boolean = false) {\n let message:any = {\n message: this.I18n.t('js.notice_successful_' + (isCreate ? 'create' : 'update')),\n };\n\n this.NotificationsService.addSuccess(message);\n }\n\n /**\n * Handle any kind of error response:\n * - HAL ErrorResources\n * - Angular HttpErrorResponses\n * - Older .data error responses\n * - String error messages\n *\n * @param response\n * @param resource\n */\n public handleRawError(response:unknown, resource?:HalResource) {\n console.error(\"Handling error message %O for work package %O\", response, resource);\n\n // Some transformation may already have returned the error as a HAL resource,\n // which we will forward to handleErrorResponse\n if (response instanceof ErrorResource) {\n return this.handleErrorResponse(response, resource);\n }\n\n const errorBody = this.retrieveError(response);\n\n if (errorBody instanceof HalResource) {\n return this.handleErrorResponse(errorBody, resource);\n }\n\n if (typeof (response) === 'string') {\n this.NotificationsService.addError(response);\n return;\n }\n\n if (response instanceof Error) {\n this.NotificationsService.addError(response.message);\n return;\n }\n\n this.showGeneralError(errorBody || response);\n }\n\n /**\n * Retrieve an error message string from the given unknown response.\n * @param response\n */\n public retrieveErrorMessage(response:unknown):string {\n const error = this.retrieveError(response);\n\n if (error instanceof ErrorResource) {\n return error.message;\n }\n\n if (typeof (error) === 'string') {\n return error;\n }\n\n return this.I18n.t('js.error.internal');\n }\n\n public retrieveError(response:unknown):ErrorResource|unknown {\n // we try to detect what we got, this may either be an HttpErrorResponse,\n // some older XHR response object or a string\n let errorBody:any = response;\n\n // Angular http response have an error body attribute\n if (response instanceof HttpErrorResponse) {\n errorBody = response.message || response.error;\n }\n\n // Some older response may have a data attribute\n if (_.get(response, 'data._type') === 'Error') {\n errorBody = (response as any).data;\n }\n\n if (errorBody && errorBody._type === 'Error') {\n return this.halResourceService.createHalResourceOfClass(ErrorResource, errorBody);\n }\n\n return errorBody;\n }\n\n protected handleErrorResponse(errorResource:any, resource?:HalResource) {\n if (!(errorResource instanceof ErrorResource)) {\n return this.showGeneralError(errorResource);\n }\n\n if (resource) {\n return this.showError(errorResource, resource);\n }\n\n this.showApiErrorMessages(errorResource);\n }\n\n public showError(errorResource:any, resource:HalResource) {\n this.showCustomError(errorResource, resource) || this.showApiErrorMessages(errorResource);\n }\n\n public showGeneralError(message?:unknown) {\n let error = this.I18n.t('js.error.internal');\n\n if (typeof (message) === 'string' || _.has(message, 'toString')) {\n error += ' ' + (message as any).toString();\n }\n\n this.NotificationsService.addError(error);\n }\n\n public showEditingBlockedError(attribute:string) {\n this.NotificationsService.addError(this.I18n.t(\n 'js.hal.error.edit_prohibited',\n {attribute: attribute}\n ));\n }\n\n protected showCustomError(errorResource:any, resource:HalResource) {\n\n if (errorResource.errorIdentifier === 'urn:openproject-org:api:v3:errors:PropertyFormatError') {\n\n let schema = this.schemaCache.of(resource).ofProperty(errorResource.details.attribute);\n let attributeName = schema.name;\n let attributeType = schema.type.toLowerCase();\n let i18nString = 'js.hal.error.format.' + attributeType;\n\n if (this.I18n.lookup(i18nString) === undefined) {\n return false;\n }\n\n this.NotificationsService.addError(this.I18n.t(i18nString,\n {attribute: attributeName}));\n\n return true;\n }\n return false;\n }\n\n protected showApiErrorMessages(errorResource:any) {\n let messages = errorResource.errorMessages;\n\n if (messages.length > 1) {\n this.NotificationsService.addError('', messages);\n } else {\n this.NotificationsService.addError(messages[0]);\n }\n\n return true;\n }\n}\n","import {AfterViewInit, Directive, ElementRef} from \"@angular/core\";\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {OpContextMenuHandler} from \"core-components/op-context-menu/op-context-menu-handler\";\nimport {OpContextMenuItem} from \"core-components/op-context-menu/op-context-menu.types\";\n\n@Directive({\n selector: '[opContextMenuTrigger]'\n})\nexport class OpContextMenuTrigger extends OpContextMenuHandler implements AfterViewInit {\n protected $element:JQuery;\n protected items:OpContextMenuItem[] = [];\n\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService) {\n super(opContextMenu);\n }\n\n ngAfterViewInit():void {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n // Open by clicking the element\n this.$element.on('click', (evt:JQuery.TriggeredEvent) => {\n evt.preventDefault();\n evt.stopPropagation();\n\n // When clicking the same trigger twice, close the element instead.\n if (this.opContextMenu.isActive(this)) {\n this.opContextMenu.close();\n return false;\n }\n\n this.open(evt);\n return false;\n });\n\n // Open with keyboard combination as well\n Mousetrap(this.$element[0]).bind('shift+alt+f10', (evt:any) => {\n this.open(evt);\n });\n }\n\n /**\n * Positioning args for jquery-ui position.\n *\n * @param {Event} openerEvent\n */\n public positionArgs(openerEvent:JQuery.TriggeredEvent) {\n return {\n my: 'left top',\n at: 'left bottom',\n of: this.$element,\n collision: 'flipfit'\n };\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport namespace OpenprojectHalModuleHelpers {\n export function lazy(obj:HalResource,\n property:string,\n getter:{ ():any },\n setter?:{ (value:any):void }):void {\n\n if (_.isObject(obj)) {\n let done = false;\n let value:any;\n let config:any = {\n get() {\n if (!done) {\n value = getter();\n done = true;\n }\n return value;\n },\n set: ():void => undefined,\n\n configurable: true,\n enumerable: true\n };\n\n if (setter) {\n config.set = (val:any) => {\n value = setter(val);\n done = true;\n };\n }\n\n Object.defineProperty(obj, property, config);\n }\n }\n}\n","import {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {OpenprojectHalModuleHelpers} from 'core-app/modules/hal/helpers/lazy-accessor';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {HalLink} from 'core-app/modules/hal/hal-link/hal-link';\n\nimport * as ObservableArray from 'observable-array';\n\ninterface HalSource {\n _links:any;\n _embedded:any;\n _type?:string;\n type?:any;\n}\n\nexport function cloneHalResourceCollection(values:T[]|undefined):T[] {\n if (_.isNil(values)) {\n return [];\n } else {\n return values.map(v => v.$copy());\n }\n}\n\nexport function cloneHalResource(value:T|undefined):T|undefined {\n if (_.isNil(value)) {\n return value;\n } else {\n return value.$copy();\n }\n}\n\nexport function initializeHalProperties(halResourceService:HalResourceService, halResource:T) {\n setSource();\n setupLinks();\n setupEmbedded();\n proxyProperties();\n setLinksAsProperties();\n setEmbeddedAsProperties();\n\n function setSource() {\n if (!halResource.$source._links) {\n halResource.$source._links = {};\n }\n\n if (!halResource.$source._links.self) {\n halResource.$source._links.self = { href: null };\n }\n }\n\n function asHalResource(value?:HalSource, loaded:boolean = true):HalResource|HalSource|undefined|null {\n if (_.isNil(value)) {\n return value;\n }\n\n if (value._links || value._embedded || value._type) {\n return halResourceService.createHalResource(value, loaded);\n }\n\n return value;\n }\n\n function proxyProperties() {\n halResource.$embeddableKeys().forEach((property:any) => {\n Object.defineProperty(halResource, property, {\n get() {\n const value = halResource.$source[property];\n return asHalResource(value, true);\n },\n\n set(value) {\n halResource.$source[property] = value;\n },\n\n enumerable: true,\n configurable: true\n });\n });\n }\n\n function setLinksAsProperties() {\n halResource.$linkableKeys().forEach((linkName:string) => {\n OpenprojectHalModuleHelpers.lazy(halResource, linkName,\n () => {\n const link:any = halResource.$links[linkName].$link || halResource.$links[linkName];\n\n if (Array.isArray(link)) {\n var items = link.map(item => halResourceService.createLinkedResource(halResource,\n linkName,\n item.$link));\n var property:HalResource[] = new ObservableArray(...items).on('change', () => {\n property.forEach(item => {\n if (!item.$link) {\n property.splice(property.indexOf(item), 1);\n }\n });\n\n halResource.$source._links[linkName] = property.map(item => item.$link);\n });\n\n return property;\n }\n\n if (link.href) {\n if (link.method !== 'get') {\n return HalLink.fromObject(halResourceService, link).$callable();\n }\n\n return halResourceService.createLinkedResource(halResource, linkName, link);\n }\n\n return null;\n },\n (val:any) => setter(val, linkName)\n );\n });\n }\n\n function setEmbeddedAsProperties() {\n if (!halResource.$source._embedded) {\n return;\n }\n\n Object.keys(halResource.$source._embedded).forEach(name => {\n OpenprojectHalModuleHelpers.lazy(halResource,\n name,\n () => halResource.$embedded[name],\n (val:any) => setter(val, name));\n });\n }\n\n function setupProperty(name:string, callback:(element:any) => any) {\n const instanceName = '$' + name;\n const sourceName = '_' + name;\n const sourceObj:any = halResource.$source[sourceName];\n\n if (_.isObject(sourceObj)) {\n Object.keys(sourceObj).forEach(propName => {\n OpenprojectHalModuleHelpers.lazy((halResource)[instanceName],\n propName,\n () => callback((sourceObj as any)[propName]));\n });\n }\n }\n\n function setupLinks() {\n setupProperty('links',\n (link) => {\n if (Array.isArray(link)) {\n return link.map(l => HalLink.fromObject(halResourceService, l).$callable());\n } else {\n return HalLink.fromObject(halResourceService, link).$callable();\n }\n });\n }\n\n function setupEmbedded() {\n setupProperty('embedded', (element:any) => {\n\n if (Array.isArray(element)) {\n return element.map((source) => asHalResource(source, true));\n }\n\n if (_.isObject(element)) {\n _.each(element, (child:any, name:string) => {\n if (child && (child._embedded || child._links)) {\n OpenprojectHalModuleHelpers.lazy(element as any,\n name,\n () => asHalResource(child, true));\n }\n });\n }\n\n return asHalResource(element, true);\n });\n }\n\n function setter(val:HalResource[]|HalResource|{ href?:string }, linkName:string) {\n const isArray = Array.isArray(val);\n\n if (!val) {\n halResource.$source._links[linkName] = { href: null };\n } else if (isArray) {\n halResource.$source._links[linkName] = (val as HalResource[]).map((el:any) => {\n return { href: el.href };\n });\n } else if (val.hasOwnProperty('$link')) {\n const link = (val as HalResource).$link;\n\n if (link.href) {\n halResource.$source._links[linkName] = link;\n }\n } else if ('href' in val) {\n halResource.$source._links[linkName] = { href: val.href };\n }\n\n if (halResource.$embedded && halResource.$embedded[linkName]) {\n halResource.$embedded[linkName] = val;\n\n if (isArray) {\n halResource.$source._embedded[linkName] = (val as HalResource[]).map(el => el.$source);\n } else {\n halResource.$source._embedded[linkName] = _.get(val, '$source', val);\n }\n }\n\n return val;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {StateService, Transition, TransitionService} from '@uirouter/core';\nimport {ReplaySubject} from 'rxjs';\nimport {Injectable} from \"@angular/core\";\n\n@Injectable({ providedIn: 'root' })\nexport class KeepTabService {\n protected currentTab:string = 'overview';\n\n protected subject = new ReplaySubject<{ [tab:string]:string; }>(1);\n\n constructor(protected $state:StateService,\n protected $transitions:TransitionService) {\n\n this.updateTabs();\n $transitions.onSuccess({}, (transition:Transition) => {\n this.updateTabs(transition.to().name);\n });\n }\n\n public get observable() {\n return this.subject;\n }\n\n /**\n * Return the last active tab.\n */\n public get lastActiveTab():string {\n if (this.isCurrentState('show')) {\n return this.currentShowTab;\n }\n\n return this.currentDetailsTab;\n }\n\n public get currentShowState():string {\n return 'work-packages.show.' + this.currentShowTab;\n }\n\n public get currentDetailsState():string {\n return 'work-packages.partitioned.list.details.' + this.currentDetailsTab;\n }\n\n public get currentDetailsSubState():string {\n return '.details.' + this.currentDetailsTab;\n }\n\n public isDetailsState(stateName:string) {\n return !!stateName && stateName.includes('.details');\n }\n\n public get currentShowTab():string {\n // Show view doesn't have overview\n // use activity instead\n if (this.currentTab === 'overview') {\n return 'activity';\n }\n\n return this.currentTab;\n }\n\n public get currentDetailsTab():string {\n return this.currentTab;\n }\n\n protected notify() {\n // Notify when updated\n this.subject.next({\n active: this.lastActiveTab,\n show: this.currentShowState,\n details: this.currentDetailsState\n });\n }\n\n protected updateTab(stateName:string) {\n if (this.isCurrentState(stateName)) {\n const current = this.$state.current.name as string;\n this.currentTab = (current.split('.') as any[]).pop();\n\n this.notify();\n }\n }\n\n protected isCurrentState(stateName:string):boolean {\n if (stateName === 'show') {\n return this.$state.includes('work-packages.show.*');\n }\n if (stateName === 'details') {\n return this.$state.includes('**.details.*');\n }\n\n return false;\n }\n\n public updateTabs(stateName?:string) {\n // Ignore the switch from show#activity to details#activity\n // and show details#overview instead\n if (stateName === 'work-packages.show.activity') {\n this.currentTab = 'overview';\n return this.notify();\n }\n this.updateTab('show');\n this.updateTab('details');\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {Subject} from \"rxjs\";\nimport {debounceTime, distinctUntilChanged, map, tap} from \"rxjs/operators\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {input} from \"reactivestates\";\nimport {QueryFilterResource} from \"core-app/modules/hal/resources/query-filter-resource\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-filter-by-text-input',\n templateUrl: './quick-filter-by-text-input.html'\n})\n\nexport class WorkPackageFilterByTextInputComponent extends UntilDestroyedMixin {\n @Output() public deactivateFilter = new EventEmitter();\n\n public text = {\n createWithDropdown: this.I18n.t('js.work_packages.create.button'),\n createButton: this.I18n.t('js.label_work_package'),\n explanation: this.I18n.t('js.label_create_work_package'),\n placeholder: this.I18n.t('js.work_packages.placeholder_filter_by_text')\n };\n\n /** Observable to the current search filter term */\n public searchTerm = input('');\n\n /** Input for search requests */\n public searchTermChanged:Subject = new Subject();\n\n constructor(readonly I18n:I18nService,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpTableFilters:WorkPackageViewFiltersService) {\n super();\n\n this.wpTableFilters\n .pristine$()\n .pipe(\n this.untilDestroyed(),\n map(() => {\n const currentSearchFilter = this.wpTableFilters.find('search');\n return currentSearchFilter ? (currentSearchFilter.values[0] as string) : '';\n }),\n )\n .subscribe((upstreamTerm:string) => {\n console.log(\"upstream \" + upstreamTerm + \" \" + (this.searchTerm as any).timestampOfLastValue);\n if (!this.searchTerm.value || this.searchTerm.isValueOlderThan(500)) {\n console.log(\"Upstream value setting to \" + upstreamTerm);\n this.searchTerm.putValue(upstreamTerm);\n }\n });\n\n this.searchTermChanged\n .pipe(\n this.untilDestroyed(),\n distinctUntilChanged(),\n tap((val) => this.searchTerm.putValue(val)),\n debounceTime(500),\n )\n .subscribe(term => {\n if (term.length > 0) {\n this.wpTableFilters.replace('search', filter => {\n filter.operator = filter.findOperator('**')!;\n filter.values = [term];\n });\n } else {\n let filter = this.wpTableFilters.find('search');\n\n this.wpTableFilters.remove(filter!);\n\n this.deactivateFilter.emit(filter);\n }\n });\n }\n}\n","\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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' ;\nexport const FalseValue = ['f'];\nexport const TrueValue = ['t'];\n\nexport interface ApiV3FilterValue {\n operator:FilterOperator;\n values:unknown[];\n}\n\nexport interface ApiV3Filter {\n [filter:string]:ApiV3FilterValue;\n}\n\nexport type ApiV3FilterObject = { [filter:string]:ApiV3FilterValue };\n\nexport class ApiV3FilterBuilder {\n\n private filterMap:ApiV3FilterObject = {};\n\n public add(name:string, operator:FilterOperator, values:unknown[]|boolean):this {\n if (values === true) {\n values = TrueValue;\n }\n\n if (values === false) {\n values = FalseValue;\n }\n\n this.filterMap[name] = {\n operator: operator,\n values: values\n };\n\n return this;\n }\n\n /**\n * Remove from the filter set\n * @param name\n */\n public remove(name:string) {\n delete this.filterMap[name];\n }\n\n /**\n * Turns the array-map style of query filters to an actual object\n *\n * @param filters APIv3 filter array [ {foo: { operator: '=', val: ['bar'] } }, ...]\n * @return A map { foo: { operator: '=', val: ['bar'] } , ... }\n */\n public toFilterObject(filters:ApiV3Filter[]):ApiV3FilterObject {\n let map:ApiV3FilterObject = {};\n\n filters.forEach((item:ApiV3Filter) => {\n _.each(item, (val:ApiV3FilterValue, filter:string) => {\n map[filter] = val;\n });\n });\n\n return map;\n }\n\n /**\n * Merges the other filters into the current set,\n * replacing them if the are duplicated.\n *\n * @param filters\n * @param only Only apply the given filters\n */\n public merge(filters:ApiV3Filter[], ...only:string[]) {\n const toAdd:ApiV3FilterObject = _.pickBy(\n this.toFilterObject(filters),\n (_, filter:string) => only.includes(filter)\n );\n\n this.filterMap = {\n ...this.filterMap,\n ...toAdd\n };\n }\n\n public get filters():ApiV3Filter[] {\n let filters:ApiV3Filter[] = [];\n _.each(this.filterMap, (val:ApiV3FilterValue, filter:string) => {\n filters.push({ [filter]: val });\n });\n\n return filters;\n }\n\n public toJson():string {\n return JSON.stringify(this.filters);\n }\n\n public toParams(mergeParams:{ [key:string]:string } = {}):string {\n let transformedFilters:string[] = [];\n\n transformedFilters = this.filters.map((filter:ApiV3Filter) => {\n return this.serializeFilter(filter);\n });\n\n let params = { filters: `[${transformedFilters.join(\",\")}]`, ...mergeParams };\n return new URLSearchParams(params).toString();\n }\n\n public clone() {\n let newFilters = new ApiV3FilterBuilder();\n\n this.filters.forEach(filter => {\n Object.keys(filter).forEach(name => {\n newFilters.add(name, filter[name].operator, filter[name].values);\n });\n });\n\n return newFilters;\n }\n\n private serializeFilter(filter:ApiV3Filter) {\n let transformedFilter:string;\n let keys:Array;\n\n keys = Object.keys(filter);\n\n let typeName = keys[0];\n let operatorAndValues:any = filter[typeName];\n\n transformedFilter = `{\"${typeName}\":{\"operator\":\"${operatorAndValues['operator']}\",\"values\":[${operatorAndValues['values']\n .map((val:any) => this.serializeFilterValue(val))\n .join(',')}]}}`;\n\n return transformedFilter;\n }\n\n private serializeFilterValue(filterValue:any) {\n return `\"${filterValue}\"`;\n }\n}\n\nexport function buildApiV3Filter(name:string, operator:FilterOperator, values:any) {\n return new ApiV3FilterBuilder().add(name, operator, values);\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {combineLatest} from 'rxjs';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './wp-relations-count.html',\n selector: 'wp-relations-count',\n})\nexport class WorkPackageRelationsCountComponent extends UntilDestroyedMixin implements OnInit {\n @Input('wpId') wpId:string;\n public count:number = 0;\n\n constructor(protected apiV3Service:APIV3Service,\n protected wpRelations:WorkPackageRelationsService) {\n super();\n }\n\n ngOnInit():void {\n this.wpRelations.require(this.wpId.toString());\n\n combineLatest([\n this\n .wpRelations\n .state(this.wpId.toString())\n .values$(),\n this\n .apiV3Service\n .work_packages\n .id(this.wpId)\n .requireAndStream()\n ]).pipe(\n this.untilDestroyed()\n ).subscribe(([relations, workPackage]) => {\n let relationCount = _.size(relations);\n let childrenCount = _.size(workPackage.children);\n\n this.count = relationCount + childrenCount;\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n Input, OnChanges,\n OnInit,\n Output, SimpleChanges\n} from '@angular/core';\n\nexport const slideToggleSelector = 'slide-toggle';\n\n@Component({\n templateUrl: './slide-toggle.component.html',\n selector: slideToggleSelector,\n styleUrls: ['./slide-toggle.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\n\nexport class SlideToggleComponent implements OnInit, OnChanges {\n @Input() containerId:string;\n @Input() containerClasses:string;\n @Input() inputId:string;\n @Input() inputName:string;\n @Input() active:boolean;\n\n @Output() valueChanged = new EventEmitter();\n\n constructor(private elementRef:ElementRef,\n private cdRef:ChangeDetectorRef) {\n }\n\n ngOnChanges(changes:SimpleChanges) {\n console.warn(JSON.stringify(changes));\n }\n\n ngOnInit() {\n const dataset = this.elementRef.nativeElement.dataset;\n\n // Allow taking over values from dataset (Rails)\n if (dataset.inputName) {\n this.containerId = dataset.containerId;\n this.containerClasses = dataset.containerClasses;\n this.inputId = dataset.inputId;\n this.inputName = dataset.inputName;\n this.active = dataset.active.toString() === 'true';\n }\n }\n\n public onValueChanged(val:any) {\n this.active = val;\n this.valueChanged.emit(val);\n this.cdRef.detectChanges();\n }\n}\n","
    \n \n
    \n ","import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n Input,\n OnInit,\n Output\n} from \"@angular/core\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {checkedClassName, uiStateLinkClass} from \"core-components/wp-fast-table/builders/ui-state-link-builder\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {StateService} from \"@uirouter/core\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CardHighlightingMode} from \"core-components/wp-fast-table/builders/highlighting/highlighting-mode.const\";\nimport {CardViewOrientation} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {WorkPackageViewFocusService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service\";\nimport {splitViewRoute} from \"core-app/modules/work_packages/routing/split-view-routes.helper\";\n\n@Component({\n selector: 'wp-single-card',\n styleUrls: ['./wp-single-card.component.sass'],\n templateUrl: './wp-single-card.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageSingleCardComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public showInfoButton:boolean = false;\n @Input() public showStatusButton:boolean = true;\n @Input() public showRemoveButton:boolean = false;\n @Input() public highlightingMode:CardHighlightingMode = 'inline';\n @Input() public draggable:boolean = false;\n @Input() public orientation:CardViewOrientation = 'vertical';\n @Input() public shrinkOnMobile:boolean = false;\n\n @Output() onRemove = new EventEmitter();\n @Output() stateLinkClicked = new EventEmitter<{ workPackageId:string, requestedState:string }>();\n\n public uiStateLinkClass:string = uiStateLinkClass;\n\n public text = {\n removeCard: this.I18n.t('js.card.remove_from_list'),\n detailsView: this.I18n.t('js.button_open_details')\n };\n\n constructor(readonly pathHelper:PathHelperService,\n readonly I18n:I18nService,\n readonly $state:StateService,\n readonly wpTableSelection:WorkPackageViewSelectionService,\n readonly wpTableFocus:WorkPackageViewFocusService,\n readonly cardView:WorkPackageCardViewService,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit():void {\n // Update selection state\n this.wpTableSelection.live$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.cdRef.detectChanges();\n });\n }\n\n public classIdentifier(wp:WorkPackageResource) {\n return this.cardView.classIdentifier(wp);\n }\n\n public emitStateLinkClicked(wp:WorkPackageResource, detail?:boolean) {\n const classIdentifier = this.classIdentifier(wp);\n const stateToEmit = detail ? splitViewRoute(this.$state) : 'work-packages.show';\n\n this.wpTableSelection.setSelection(wp.id!, this.cardView.findRenderedCard(classIdentifier));\n this.wpTableFocus.updateFocus(wp.id!);\n this.stateLinkClicked.emit({ workPackageId:wp.id!, requestedState: stateToEmit });\n }\n\n public cardClasses() {\n let classes = this.isSelected(this.workPackage) ? checkedClassName : '';\n classes += this.draggable ? ' -draggable' : '';\n classes += this.workPackage.isNew ? ' -new' : '';\n classes += ' wp-card-' + this.workPackage.id;\n classes += ' -' + this.orientation;\n classes += this.shrinkOnMobile ? ' -shrink' : '';\n return classes;\n }\n\n public wpTypeAttribute(wp:WorkPackageResource) {\n return wp.type.name;\n }\n\n public wpSubject(wp:WorkPackageResource) {\n return wp.subject;\n }\n\n public wpProjectName(wp:WorkPackageResource) {\n return wp.project?.name;\n }\n\n public cardHighlightingClass(wp:WorkPackageResource) {\n return this.cardHighlighting(wp);\n }\n\n public typeHighlightingClass(wp:WorkPackageResource) {\n return this.attributeHighlighting('type', wp);\n }\n\n public onRemoved(wp:WorkPackageResource) {\n this.onRemove.emit(wp);\n }\n\n public cardCoverImageShown(wp:WorkPackageResource):boolean {\n return this.bcfSnapshotPath(wp) !== null;\n }\n\n public bcfSnapshotPath(wp:WorkPackageResource) {\n return wp.bcfViewpoints && wp.bcfViewpoints.length > 0 ? wp.bcfViewpoints[0].href + '/snapshot' : null;\n }\n\n private isSelected(wp:WorkPackageResource):boolean {\n return this.wpTableSelection.isSelected(wp.id!);\n }\n\n private cardHighlighting(wp:WorkPackageResource) {\n if (['status', 'priority', 'type'].includes(this.highlightingMode)) {\n return Highlighting.backgroundClass(this.highlightingMode, wp[this.highlightingMode].id);\n }\n return '';\n }\n\n private attributeHighlighting(type:string, wp:WorkPackageResource) {\n return Highlighting.inlineClass(type, wp.type.id!);\n }\n}\n","
    \n\n
    \n
    \n\n
    \n \n \n \n \n \n \n
    \n \n
    \n \n \n \n \n
    \n
    \n\n
    \n \n \n \n \n \n #{{workPackage.id}}\n \n \n \n \n \n \n \n \n
    \n
    ","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {combine, deriveRaw, InputState, multiInput, MultiInputState, State, StatesGroup} from 'reactivestates';\nimport {filter, map} from 'rxjs/operators';\nimport {Injectable, Injector} from '@angular/core';\nimport {Subject} from \"rxjs\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {ChangeMap} from \"core-app/modules/fields/changeset/changeset\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\n\nclass ChangesetStates extends StatesGroup {\n name = 'Changesets';\n\n changesets = multiInput();\n\n constructor() {\n super();\n this.initializeMembers();\n }\n}\n\n/**\n * Wrapper class for the saved change of a work package,\n * used to access the previous save and or previous state\n * of the work package (e.g., whether it was new).\n */\nexport class ResourceChangesetCommit {\n /**\n * The work package id of the change\n * (This is the new work package ID if +wasNew+ is true.\n */\n public readonly id:string;\n\n /**\n * The resulting, saved work package.\n */\n public readonly resource:T;\n\n /** Whether the commit saved an initial work package */\n public readonly wasNew:boolean = false;\n\n /** The previous changes */\n public readonly changes:ChangeMap;\n\n /**\n * Create a change commit from the change object\n * @param change The change object that resulted in the save\n * @param saved The returned work package\n */\n constructor(change:ResourceChangeset, saved:T) {\n this.id = saved.id!.toString();\n this.wasNew = change.pristineResource.isNew;\n this.resource = saved;\n this.changes = change.changeMap;\n }\n}\n\nexport interface ResourceChangesetClass {\n new(...args:any[]):ResourceChangeset;\n}\n\n@Injectable()\nexport class HalResourceEditingService extends StateCacheService {\n\n /** Committed / saved changes to work packages observable */\n public committedChanges = new Subject();\n\n constructor(protected readonly injector:Injector,\n protected readonly halEvents:HalEventsService,\n protected readonly hook:HookService) {\n super(new ChangesetStates().changesets);\n }\n\n public async save>(change:T):Promise> {\n // Form the payload we're going to save\n const payload = await change.buildRequestPayload();\n const savedResource = await change.pristineResource.$links.updateImmediately(payload);\n\n // Initialize any potentially new HAL values\n savedResource.retainFrom(change.pristineResource);\n\n await this.onSaved(savedResource);\n\n // Complete the change\n return this.complete(change, savedResource);\n }\n\n /**\n * Mark the given change as completed, notify changes\n * and reset it.\n */\n private complete>(change:T, saved:V):ResourceChangesetCommit {\n const commit = new ResourceChangesetCommit(change, saved);\n this.committedChanges.next(commit);\n this.reset(change);\n\n const eventType = commit.wasNew ? 'created' : 'updated';\n this.halEvents.push(commit.resource, { eventType, commit });\n\n return commit;\n }\n\n /**\n * Reset the given change, either due to cancelling or successful submission.\n * @param change\n */\n public reset>(change:T) {\n change.clear();\n this.clearSome(change.href);\n }\n\n /**\n * Returns the typed state value. Use this to get a changeset\n * for a subtype of ResourceChangeset.\n * @param resource\n */\n public typedState>(resource:V):State {\n return this.multiState.get(resource.href!) as InputState;\n }\n\n /**\n * Create a new changeset for the given work package, discarding any previous changeset that might exist.\n *\n * @param resource\n * @param form\n *\n * @return The state for the created changeset\n */\n public edit>(resource:V, form?:FormResource):T {\n const state = this.multiState.get(resource.href!) as InputState;\n const changeset = this.newChangeset(resource, state, form);\n\n state.putValue(changeset);\n\n return changeset;\n }\n\n protected newChangeset>(resource:V, state:InputState, form?:FormResource):T {\n // we take the last registered group component which means that\n // plugins will have their say if they register for it.\n const cls = this.hook.call('halResourceChangesetClass', resource).pop() || ResourceChangeset;\n return new cls(resource, state, form) as T;\n }\n\n /**\n * Start or continue editing the work package with a given edit context\n * @param fallback Fallback resource to use\n * @return {ResourceChangeset} Change object to work on\n */\n public changeFor>(fallback:V):T {\n const state = this.multiState.get(fallback.href!) as InputState;\n let resource = fallback;\n if (fallback.state) {\n resource = fallback.state.getValueOr(fallback);\n }\n let changeset = state.value;\n\n // If there is no changeset, or\n // If there is an empty one for a older work package reference\n // build a new changeset\n if (changeset && !changeset.isEmpty()) {\n return changeset;\n }\n\n if (!changeset) {\n return this.edit(resource);\n }\n\n if (resource.hasOwnProperty('lockVersion') && changeset.pristineResource.lockVersion < resource.lockVersion) {\n return this.edit(resource);\n }\n\n changeset.updatePristineResource(resource);\n return changeset;\n }\n\n /**\n * Get a temporary view on the resource being edited.\n * IF there is a changeset:\n * - Merge the changeset, including its form, into the work package resource\n * IF there is no changeset:\n * - The work package itself is returned.\n *\n * This resource has a read only index signature to make it clear it is NOT\n * meant for editing.\n *\n * @return {State}\n */\n public temporaryEditResource>(resource:V):State {\n const combined = combine(resource.state! as State, this.typedState(resource) as State);\n\n return deriveRaw(combined,\n ($) => $\n .pipe(\n filter(([resource, _]) => !!resource),\n map(([resource, change]) => {\n if (change) {\n change.updatePristineResource(resource as V);\n return change.projectedResource;\n }\n\n return resource;\n })\n )\n );\n }\n\n public stopEditing(resource:HalResource|{ href:string }) {\n this.multiState.get(resource.href!).clear();\n }\n\n protected onSaved(saved:HalResource):Promise {\n if (saved.state) {\n return saved.push(saved);\n }\n\n return Promise.resolve();\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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","import { ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy, OnInit, Directive } from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {OpModalService} from 'core-components/op-modals/op-modal.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Directive()\nexport abstract class OpModalComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n\n /* Close on escape? */\n public closeOnEscape:boolean = true;\n public closeOnEscapeFunction = this.closeMe;\n\n /* Close on outside click */\n public closeOnOutsideClick:boolean = true;\n\n /* Reference to service */\n protected service:OpModalService = this.locals.service;\n\n public $element:JQuery;\n\n /** Closing event called from the service when closing this modal */\n public closingEvent = new EventEmitter();\n\n public openingEvent = new EventEmitter();\n\n protected constructor(public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef) {\n super();\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n }\n\n ngOnDestroy() {\n this.closingEvent.complete();\n this.openingEvent.complete();\n }\n\n /**\n * Called when the user attempts to close the modal window.\n * The service will close this modal if this method returns true\n * @returns {boolean}\n */\n public onClose():boolean {\n this.afterFocusOn && this.afterFocusOn.focus();\n return true;\n }\n\n public closeMe(evt?:JQuery.TriggeredEvent) {\n this.service.close();\n\n if (evt) {\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n\n public onOpen(modalElement:JQuery) {\n this.openingEvent.emit();\n this.cdRef.detectChanges();\n }\n\n protected get afterFocusOn():JQuery {\n return this.$element;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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\n/**\n * Get the group type from its identifier.\n */\nexport function groupTypeFromIdentifier(groupIdentifier:string) {\n return groupIdentifier.split('-')[0];\n}\n\n/**\n * Get the group id from its identifier.\n */\nexport function groupIdFromIdentifier(groupIdentifier:string) {\n return groupIdentifier.split('-').pop();\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, EventEmitter, Input, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\n\n@Component({\n selector: 'filter-boolean-value',\n templateUrl: './filter-boolean-value.component.html'\n})\nexport class FilterBooleanValueComponent {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new EventEmitter();\n\n constructor(readonly I18n:I18nService) {\n }\n\n public get value():HalResource | string {\n return this.filter.values[0];\n }\n\n public onFilterUpdated(val:string | HalResource) {\n this.filter.values[0] = val;\n this.filterChanged.emit(this.filter);\n }\n\n}\n","\n","var map = {\n\t\"./apl/apl.js\": [\n\t\t\"4kmW\",\n\t\t0,\n\t\t45\n\t],\n\t\"./asciiarmor/asciiarmor.js\": [\n\t\t\"Jt+K\",\n\t\t0,\n\t\t46\n\t],\n\t\"./asn.1/asn.1.js\": [\n\t\t\"0OHD\",\n\t\t0,\n\t\t47\n\t],\n\t\"./asterisk/asterisk.js\": [\n\t\t\"yGjk\",\n\t\t0,\n\t\t48\n\t],\n\t\"./brainfuck/brainfuck.js\": [\n\t\t\"oF4/\",\n\t\t0,\n\t\t49\n\t],\n\t\"./clike/clike.js\": [\n\t\t\"S6bl\",\n\t\t0,\n\t\t5\n\t],\n\t\"./clojure/clojure.js\": [\n\t\t\"LA1u\",\n\t\t0,\n\t\t50\n\t],\n\t\"./cmake/cmake.js\": [\n\t\t\"qE+Q\",\n\t\t0,\n\t\t51\n\t],\n\t\"./cobol/cobol.js\": [\n\t\t\"JNJg\",\n\t\t0,\n\t\t52\n\t],\n\t\"./coffeescript/coffeescript.js\": [\n\t\t\"oL3q\",\n\t\t0,\n\t\t1\n\t],\n\t\"./commonlisp/commonlisp.js\": [\n\t\t\"kmAK\",\n\t\t0,\n\t\t53\n\t],\n\t\"./crystal/crystal.js\": [\n\t\t\"JRJP\",\n\t\t0,\n\t\t54\n\t],\n\t\"./css/css.js\": [\n\t\t\"ewDg\",\n\t\t0,\n\t\t3\n\t],\n\t\"./cypher/cypher.js\": [\n\t\t\"vW+e\",\n\t\t0,\n\t\t55\n\t],\n\t\"./d/d.js\": [\n\t\t\"zRyg\",\n\t\t0,\n\t\t56\n\t],\n\t\"./dart/dart.js\": [\n\t\t\"6q/U\",\n\t\t0,\n\t\t5,\n\t\t57\n\t],\n\t\"./diff/diff.js\": [\n\t\t\"3fnu\",\n\t\t0,\n\t\t58\n\t],\n\t\"./django/django.js\": [\n\t\t\"SzTn\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t36\n\t],\n\t\"./dockerfile/dockerfile.js\": [\n\t\t\"R6x9\",\n\t\t0,\n\t\t1,\n\t\t59\n\t],\n\t\"./dtd/dtd.js\": [\n\t\t\"/YIB\",\n\t\t0,\n\t\t60\n\t],\n\t\"./dylan/dylan.js\": [\n\t\t\"PLH4\",\n\t\t0,\n\t\t61\n\t],\n\t\"./ebnf/ebnf.js\": [\n\t\t\"AvIz\",\n\t\t0,\n\t\t62\n\t],\n\t\"./ecl/ecl.js\": [\n\t\t\"rSpl\",\n\t\t0,\n\t\t63\n\t],\n\t\"./eiffel/eiffel.js\": [\n\t\t\"t86p\",\n\t\t0,\n\t\t64\n\t],\n\t\"./elm/elm.js\": [\n\t\t\"Rba3\",\n\t\t0,\n\t\t65\n\t],\n\t\"./erlang/erlang.js\": [\n\t\t\"9RTS\",\n\t\t0,\n\t\t66\n\t],\n\t\"./factor/factor.js\": [\n\t\t\"yv4w\",\n\t\t0,\n\t\t1,\n\t\t67\n\t],\n\t\"./fcl/fcl.js\": [\n\t\t\"xvvs\",\n\t\t0,\n\t\t68\n\t],\n\t\"./forth/forth.js\": [\n\t\t\"CDkR\",\n\t\t0,\n\t\t69\n\t],\n\t\"./fortran/fortran.js\": [\n\t\t\"UYub\",\n\t\t0,\n\t\t70\n\t],\n\t\"./gas/gas.js\": [\n\t\t\"Upog\",\n\t\t0,\n\t\t71\n\t],\n\t\"./gfm/gfm.js\": [\n\t\t\"RKCW\",\n\t\t0,\n\t\t8,\n\t\t1,\n\t\t72\n\t],\n\t\"./gherkin/gherkin.js\": [\n\t\t\"tkAH\",\n\t\t0,\n\t\t73\n\t],\n\t\"./go/go.js\": [\n\t\t\"T/QY\",\n\t\t0,\n\t\t74\n\t],\n\t\"./groovy/groovy.js\": [\n\t\t\"X7TR\",\n\t\t0,\n\t\t75\n\t],\n\t\"./haml/haml.js\": [\n\t\t\"c+b1\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t37\n\t],\n\t\"./handlebars/handlebars.js\": [\n\t\t\"4d6s\",\n\t\t0,\n\t\t1\n\t],\n\t\"./haskell-literate/haskell-literate.js\": [\n\t\t\"INem\",\n\t\t0,\n\t\t1,\n\t\t76\n\t],\n\t\"./haskell/haskell.js\": [\n\t\t\"0+DK\",\n\t\t0,\n\t\t1\n\t],\n\t\"./haxe/haxe.js\": [\n\t\t\"We/1\",\n\t\t0,\n\t\t77\n\t],\n\t\"./htmlembedded/htmlembedded.js\": [\n\t\t\"dLt8\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t38\n\t],\n\t\"./htmlmixed/htmlmixed.js\": [\n\t\t\"1p+/\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t43\n\t],\n\t\"./http/http.js\": [\n\t\t\"scEK\",\n\t\t0,\n\t\t78\n\t],\n\t\"./idl/idl.js\": [\n\t\t\"HqpV\",\n\t\t0,\n\t\t79\n\t],\n\t\"./javascript/javascript.js\": [\n\t\t\"+dQi\",\n\t\t0,\n\t\t2\n\t],\n\t\"./jinja2/jinja2.js\": [\n\t\t\"ToA7\",\n\t\t0,\n\t\t80\n\t],\n\t\"./jsx/jsx.js\": [\n\t\t\"onn/\",\n\t\t0,\n\t\t2,\n\t\t44\n\t],\n\t\"./julia/julia.js\": [\n\t\t\"NGrM\",\n\t\t0,\n\t\t81\n\t],\n\t\"./livescript/livescript.js\": [\n\t\t\"5RX+\",\n\t\t0,\n\t\t82\n\t],\n\t\"./lua/lua.js\": [\n\t\t\"jrMQ\",\n\t\t0,\n\t\t83\n\t],\n\t\"./markdown/markdown.js\": [\n\t\t\"lZu9\",\n\t\t0,\n\t\t8\n\t],\n\t\"./mathematica/mathematica.js\": [\n\t\t\"ztbM\",\n\t\t0,\n\t\t84\n\t],\n\t\"./mbox/mbox.js\": [\n\t\t\"6mA5\",\n\t\t0,\n\t\t85\n\t],\n\t\"./mirc/mirc.js\": [\n\t\t\"o5kb\",\n\t\t0,\n\t\t86\n\t],\n\t\"./mllike/mllike.js\": [\n\t\t\"NU+Z\",\n\t\t0,\n\t\t87\n\t],\n\t\"./modelica/modelica.js\": [\n\t\t\"lQiH\",\n\t\t0,\n\t\t88\n\t],\n\t\"./mscgen/mscgen.js\": [\n\t\t\"6gTk\",\n\t\t0,\n\t\t89\n\t],\n\t\"./mumps/mumps.js\": [\n\t\t\"Q7su\",\n\t\t0,\n\t\t90\n\t],\n\t\"./nginx/nginx.js\": [\n\t\t\"srmC\",\n\t\t0,\n\t\t91\n\t],\n\t\"./nsis/nsis.js\": [\n\t\t\"bYLO\",\n\t\t0,\n\t\t1,\n\t\t92\n\t],\n\t\"./ntriples/ntriples.js\": [\n\t\t\"PWBO\",\n\t\t0,\n\t\t93\n\t],\n\t\"./octave/octave.js\": [\n\t\t\"mybg\",\n\t\t0,\n\t\t94\n\t],\n\t\"./oz/oz.js\": [\n\t\t\"yhmh\",\n\t\t0,\n\t\t95\n\t],\n\t\"./pascal/pascal.js\": [\n\t\t\"lB9V\",\n\t\t0,\n\t\t96\n\t],\n\t\"./pegjs/pegjs.js\": [\n\t\t\"ZGb1\",\n\t\t0,\n\t\t2,\n\t\t97\n\t],\n\t\"./perl/perl.js\": [\n\t\t\"kG+r\",\n\t\t0,\n\t\t98\n\t],\n\t\"./php/php.js\": [\n\t\t\"RNWO\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t5,\n\t\t39\n\t],\n\t\"./pig/pig.js\": [\n\t\t\"860+\",\n\t\t0,\n\t\t99\n\t],\n\t\"./powershell/powershell.js\": [\n\t\t\"naPG\",\n\t\t0,\n\t\t100\n\t],\n\t\"./properties/properties.js\": [\n\t\t\"3Fvf\",\n\t\t0,\n\t\t101\n\t],\n\t\"./protobuf/protobuf.js\": [\n\t\t\"cHwl\",\n\t\t0,\n\t\t102\n\t],\n\t\"./pug/pug.js\": [\n\t\t\"W+/v\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t7\n\t],\n\t\"./puppet/puppet.js\": [\n\t\t\"cwoo\",\n\t\t0,\n\t\t103\n\t],\n\t\"./python/python.js\": [\n\t\t\"25Eh\",\n\t\t0,\n\t\t1\n\t],\n\t\"./q/q.js\": [\n\t\t\"MiqB\",\n\t\t0,\n\t\t104\n\t],\n\t\"./r/r.js\": [\n\t\t\"kD6b\",\n\t\t0,\n\t\t105\n\t],\n\t\"./rpm/rpm.js\": [\n\t\t\"Qs4+\",\n\t\t0,\n\t\t106\n\t],\n\t\"./rst/rst.js\": [\n\t\t\"jIQM\",\n\t\t0,\n\t\t1,\n\t\t107\n\t],\n\t\"./ruby/ruby.js\": [\n\t\t\"hTYL\",\n\t\t0,\n\t\t1\n\t],\n\t\"./rust/rust.js\": [\n\t\t\"sY4N\",\n\t\t0,\n\t\t1,\n\t\t108\n\t],\n\t\"./sas/sas.js\": [\n\t\t\"Sh3j\",\n\t\t0,\n\t\t109\n\t],\n\t\"./sass/sass.js\": [\n\t\t\"G2Pi\",\n\t\t0,\n\t\t3,\n\t\t1\n\t],\n\t\"./scheme/scheme.js\": [\n\t\t\"8wdy\",\n\t\t0,\n\t\t110\n\t],\n\t\"./shell/shell.js\": [\n\t\t\"AvDn\",\n\t\t0,\n\t\t111\n\t],\n\t\"./sieve/sieve.js\": [\n\t\t\"1dRh\",\n\t\t0,\n\t\t112\n\t],\n\t\"./slim/slim.js\": [\n\t\t\"VI2i\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t40\n\t],\n\t\"./smalltalk/smalltalk.js\": [\n\t\t\"n4Nj\",\n\t\t0,\n\t\t113\n\t],\n\t\"./smarty/smarty.js\": [\n\t\t\"QWhe\",\n\t\t0,\n\t\t114\n\t],\n\t\"./solr/solr.js\": [\n\t\t\"xhF3\",\n\t\t0,\n\t\t115\n\t],\n\t\"./soy/soy.js\": [\n\t\t\"vH+N\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t41\n\t],\n\t\"./sparql/sparql.js\": [\n\t\t\"++e5\",\n\t\t0,\n\t\t116\n\t],\n\t\"./spreadsheet/spreadsheet.js\": [\n\t\t\"bEWP\",\n\t\t0,\n\t\t117\n\t],\n\t\"./sql/sql.js\": [\n\t\t\"/9rB\",\n\t\t0,\n\t\t118\n\t],\n\t\"./stex/stex.js\": [\n\t\t\"+NIl\",\n\t\t0,\n\t\t1\n\t],\n\t\"./stylus/stylus.js\": [\n\t\t\"dtKC\",\n\t\t0,\n\t\t11\n\t],\n\t\"./swift/swift.js\": [\n\t\t\"wOIU\",\n\t\t0,\n\t\t119\n\t],\n\t\"./tcl/tcl.js\": [\n\t\t\"BEBj\",\n\t\t0,\n\t\t120\n\t],\n\t\"./textile/textile.js\": [\n\t\t\"TD3l\",\n\t\t0,\n\t\t121\n\t],\n\t\"./tiddlywiki/tiddlywiki.js\": [\n\t\t\"9+NH\",\n\t\t0,\n\t\t122\n\t],\n\t\"./tiki/tiki.js\": [\n\t\t\"Km7L\",\n\t\t0,\n\t\t123\n\t],\n\t\"./toml/toml.js\": [\n\t\t\"0sou\",\n\t\t0,\n\t\t124\n\t],\n\t\"./tornado/tornado.js\": [\n\t\t\"xbNY\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t1,\n\t\t42\n\t],\n\t\"./troff/troff.js\": [\n\t\t\"s1o1\",\n\t\t0,\n\t\t125\n\t],\n\t\"./ttcn-cfg/ttcn-cfg.js\": [\n\t\t\"hmTv\",\n\t\t0,\n\t\t126\n\t],\n\t\"./ttcn/ttcn.js\": [\n\t\t\"TYrp\",\n\t\t0,\n\t\t127\n\t],\n\t\"./turtle/turtle.js\": [\n\t\t\"P3N9\",\n\t\t0,\n\t\t128\n\t],\n\t\"./twig/twig.js\": [\n\t\t\"SII/\",\n\t\t0,\n\t\t1,\n\t\t129\n\t],\n\t\"./vb/vb.js\": [\n\t\t\"Kr55\",\n\t\t0,\n\t\t130\n\t],\n\t\"./vbscript/vbscript.js\": [\n\t\t\"axah\",\n\t\t0,\n\t\t131\n\t],\n\t\"./velocity/velocity.js\": [\n\t\t\"/kYp\",\n\t\t0,\n\t\t132\n\t],\n\t\"./verilog/verilog.js\": [\n\t\t\"m2bc\",\n\t\t0,\n\t\t133\n\t],\n\t\"./vhdl/vhdl.js\": [\n\t\t\"PP56\",\n\t\t0,\n\t\t134\n\t],\n\t\"./vue/vue.js\": [\n\t\t\"aT2M\",\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t11,\n\t\t7,\n\t\t1,\n\t\t135\n\t],\n\t\"./webidl/webidl.js\": [\n\t\t\"PVgs\",\n\t\t0,\n\t\t136\n\t],\n\t\"./xml/xml.js\": [\n\t\t\"1eCo\",\n\t\t0,\n\t\t137\n\t],\n\t\"./xquery/xquery.js\": [\n\t\t\"bJEP\",\n\t\t0,\n\t\t138\n\t],\n\t\"./yacas/yacas.js\": [\n\t\t\"WThJ\",\n\t\t0,\n\t\t139\n\t],\n\t\"./yaml-frontmatter/yaml-frontmatter.js\": [\n\t\t\"0gIM\",\n\t\t0,\n\t\t1,\n\t\t140\n\t],\n\t\"./yaml/yaml.js\": [\n\t\t\"ztCB\",\n\t\t0,\n\t\t1\n\t],\n\t\"./z80/z80.js\": [\n\t\t\"dRHf\",\n\t\t0,\n\t\t141\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tvar ids = map[req], id = ids[0];\n\treturn Promise.all(ids.slice(1).map(__webpack_require__.e)).then(function() {\n\t\treturn __webpack_require__.t(id, 7);\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = \"TKcc\";\nmodule.exports = webpackAsyncContext;","export const PERMITTED_CONTEXT_MENU_ACTIONS = [\n {\n key: 'log_time',\n link: 'logTime',\n resource: 'workPackage'\n },\n {\n key: 'change_project',\n icon: 'icon-move',\n link: 'move',\n resource: 'workPackage'\n },\n {\n key: 'copy',\n link: 'copy',\n resource: 'workPackage'\n },\n {\n key: 'delete',\n link: 'delete',\n resource: 'workPackage'\n },\n {\n key: 'export-pdf',\n link: 'pdf',\n resource: 'workPackage'\n },\n {\n key: 'export-atom',\n link: 'atom',\n resource: 'workPackage'\n }\n];\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {DateDisplayField} from \"core-app/modules/fields/display/field-types/date-display-field.module\";\n\nexport class CombinedDateDisplayField extends DateDisplayField {\n text = {\n placeholder: {\n startDate: this.I18n.t('js.label_no_start_date'),\n dueDate: this.I18n.t('js.label_no_due_date')\n },\n };\n\n public render(element:HTMLElement, displayText:string):void {\n element.innerHTML = '';\n\n let startDateElement = this.createDateDisplayField('startDate');\n let dueDateElement = this.createDateDisplayField('dueDate');\n\n let separator = document.createElement('span');\n separator.textContent = ' - ';\n\n element.appendChild(startDateElement);\n element.appendChild(separator);\n element.appendChild(dueDateElement);\n }\n\n private createDateDisplayField(date:'dueDate'|'startDate'):HTMLElement {\n let dateElement = document.createElement('span');\n let dateDisplayField = new DateDisplayField(date, this.context);\n let text = this.resource[date] ?\n this.timezoneService.formattedDate(this.resource[date]) :\n this.text.placeholder[date];\n\n dateDisplayField.apply(this.resource, this.schema);\n dateDisplayField.render(dateElement, text);\n\n return dateElement;\n }\n}\n","
    \n
    \n
    \n \n \n \n \n

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

    \n

    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","export const demoProjectName = 'Demo project';\nexport const scrumDemoProjectName = 'Scrum project';\nexport const onboardingTourStorageKey = 'openProject-onboardingTour';\nexport type OnboardingTourNames = 'backlogs'|'taskboard'|'homescreen'|'main';\n\nexport function waitForElement(element:string, container:string, execFunction:Function) {\n // Wait for the element to be ready\n var observer = new MutationObserver(function (mutations, observerInstance) {\n if (jQuery(element).length) {\n observerInstance.disconnect(); // stop observing\n execFunction();\n return;\n }\n });\n observer.observe(jQuery(container)[0], {\n childList: true,\n subtree: true\n });\n}\n\nexport function demoProjectsLinks() {\n let demoProjects = [];\n let demoProjectsLink = jQuery(\".widget-box.welcome a:contains(\" + demoProjectName + \")\");\n let scrumDemoProjectsLink = jQuery(\".widget-box.welcome a:contains(\" + scrumDemoProjectName + \")\");\n\n if (demoProjectsLink.length) {\n demoProjects.push(demoProjectsLink);\n }\n if (scrumDemoProjectsLink.length) {\n demoProjects.push(scrumDemoProjectsLink);\n }\n\n return demoProjects;\n}\n\nexport function preventClickHandler(e:any) {\n e.preventDefault();\n e.stopPropagation();\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {\n AfterViewInit,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Inject,\n ViewChild\n} from \"@angular/core\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {TypeResource} from \"core-app/modules/hal/resources/type-resource\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\n\n@Component({\n templateUrl: './wp-button-macro.modal.html'\n})\nexport class WpButtonMacroModal extends OpModalComponent implements AfterViewInit {\n\n public changed = false;\n public showClose = true;\n public closeOnEscape = true;\n public closeOnOutsideClick = true;\n\n public selectedType:string;\n public buttonStyle:boolean;\n\n public availableTypes:TypeResource[];\n public type:string = '';\n public classes:string = '';\n\n @ViewChild('typeSelect', { static: true }) typeSelect:ElementRef;\n\n public text:any = {\n title: this.I18n.t('js.editor.macro.work_package_button.button'),\n none: this.I18n.t('js.label_none'),\n selected_type: this.I18n.t('js.editor.macro.work_package_button.type'),\n button_style: this.I18n.t('js.editor.macro.work_package_button.button_style'),\n button_style_hint: this.I18n.t('js.editor.macro.work_package_button.button_style_hint'),\n button_save: this.I18n.t('js.button_save'),\n button_cancel: this.I18n.t('js.button_cancel'),\n close_popup: this.I18n.t('js.close_popup_title')\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n protected currentProject:CurrentProjectService,\n protected apiV3Service:APIV3Service,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService) {\n\n super(locals, cdRef, elementRef);\n this.selectedType = this.type = this.locals.type;\n this.classes = this.locals.classes;\n this.buttonStyle = this.classes === 'button';\n\n this\n .apiV3Service\n .withOptionalProject(this.currentProject.identifier)\n .work_packages\n .form\n .post({})\n .subscribe((form:FormResource) => {\n this.availableTypes = form.schema.type.allowedValues;\n });\n }\n\n public applyAndClose(evt:JQuery.TriggeredEvent) {\n this.changed = true;\n this.classes = this.buttonStyle ? 'button' : '';\n this.type = this.selectedType;\n this.closeMe(evt);\n }\n\n ngAfterViewInit() {\n this.typeSelect.nativeElement.focus();\n }\n}\n\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n
    \n
    \n \n
    \n \n \n
    \n
    \n \n \n \n \n
    \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 {WorkPackagesListService} from '../../wp-list/wp-list.service';\nimport {States} from '../../states.service';\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {ChangeDetectorRef, Component, ElementRef, Inject, OnInit} from \"@angular/core\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {StateService} from '@uirouter/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageService} from \"core-components/work-packages/work-package.service\";\nimport {BackRoutingService} from \"core-app/modules/common/back-routing/back-routing.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Component({\n templateUrl: './wp-destroy.modal.html'\n})\nexport class WpDestroyModal extends OpModalComponent implements OnInit {\n // When deleting multiple\n public workPackages:WorkPackageResource[];\n public workPackageLabel:string;\n\n // Single work package\n public singleWorkPackage:WorkPackageResource;\n public singleWorkPackageChildren:WorkPackageResource[];\n public busy = false;\n\n // Need to confirm deletion when children are involved\n public childrenDeletionConfirmed = false;\n\n public text:any = {\n label_visibility_settings: this.I18n.t('js.label_visibility_settings'),\n button_save: this.I18n.t('js.modals.button_save'),\n confirm: this.I18n.t('js.button_confirm'),\n warning: this.I18n.t('js.label_warning'),\n cancel: this.I18n.t('js.button_cancel'),\n close: this.I18n.t('js.close_popup_title'),\n label_confirm_children_deletion: this.I18n.t('js.modals.destroy_work_package.confirm_deletion_children'),\n };\n\n constructor(readonly elementRef:ElementRef,\n readonly WorkPackageService:WorkPackageService,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly $state:StateService,\n readonly states:States,\n readonly wpTableFocus:WorkPackageViewFocusService,\n readonly wpListService:WorkPackagesListService,\n readonly notificationService:WorkPackageNotificationService,\n readonly backRoutingService:BackRoutingService) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n super.ngOnInit();\n\n this.workPackages = this.locals.workPackages;\n this.workPackageLabel = this.I18n.t('js.units.workPackage', { count: this.workPackages.length });\n\n // Ugly way to provide the same view bindings as the ng-init in the previous template.\n if (this.workPackages.length === 1) {\n this.singleWorkPackage = this.workPackages[0];\n this.singleWorkPackageChildren = this.singleWorkPackage.children;\n }\n\n this.text.title = this.I18n.t('js.modals.destroy_work_package.title', { label: this.workPackageLabel }),\n this.text.text = this.I18n.t('js.modals.destroy_work_package.text', {\n label: this.workPackageLabel,\n count: this.workPackages.length\n });\n\n this.text.childCount = (wp:WorkPackageResource) => {\n const count = this.children(wp).length;\n return this.I18n.t('js.units.child_work_packages', { count: count });\n };\n\n this.text.hasChildren = (wp:WorkPackageResource) =>\n this.I18n.t('js.modals.destroy_work_package.has_children', { childUnits: this.text.childCount(wp) }),\n\n this.text.deletesChildren = this.I18n.t('js.modals.destroy_work_package.deletes_children');\n }\n\n public get blockedDueToUnconfirmedChildren() {\n return this.mustConfirmChildren && !this.childrenDeletionConfirmed;\n }\n\n public get mustConfirmChildren() {\n let result = false;\n\n if (this.singleWorkPackage && this.singleWorkPackageChildren) {\n let result = this.singleWorkPackageChildren.length > 0;\n }\n\n return result || !!_.find(this.workPackages, wp =>\n wp.children && wp.children.length > 0);\n }\n\n public confirmDeletion($event:JQuery.TriggeredEvent) {\n if (this.busy || this.blockedDueToUnconfirmedChildren) {\n return false;\n }\n\n this.busy = true;\n this.WorkPackageService.performBulkDelete(this.workPackages.map(el => el.id!), true)\n .then(() => {\n this.busy = false;\n this.closeMe($event);\n this.wpTableFocus.clear('Clearing after destroying work packages');\n\n // Go back to a previous list state if we're in a split or full view\n if (this.$state.current.data.baseRoute) {\n this.backRoutingService.goBack(true);\n }\n })\n .catch(() => {\n this.busy = false;\n });\n\n return false;\n }\n\n public children(workPackage:WorkPackageResource) {\n if (workPackage.hasOwnProperty('children')) {\n return workPackage.children;\n } else {\n return [];\n }\n }\n}\n","
    \n
    \n
    \n \n \n \n \n

    \n
    \n\n
    \n \n

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

    \n
    0\">\n

    \n \n :\n \n

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

    \n \n

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

    \n \n \n

    \n
      \n
    • \n #\n &ngsp;\n \n 0\">\n (+ {{ text.childCount(wp) }})\n \n
    • \n
    \n
    \n
    \n \n
    \n
    \n\n
    \n \n \n
    \n
    \n
    \n","\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 {debugLog, timeOutput} from \"core-app/helpers/debug_output\";\nimport {QueryOrder} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-order\";\n\n// min allowed position\nexport const MIN_ORDER = -2147483647;\n// max postgres 4-byte integer position\nexport const MAX_ORDER = 2147483647;\n// default position to insert\nexport const DEFAULT_ORDER = 0;\n// The distance to keep between each element\nexport const ORDER_DISTANCE = 16384;\n\n/**\n * Computes the delta of positions for a given\n * operation and order\n */\nexport class ReorderDeltaBuilder {\n\n // We are building a delta of positions we need to update\n // ideally this will only be one, but more may need to be set (initially)\n // or shifted in case of spacing issues\n private delta:QueryOrder = {};\n\n /**\n * Create a delta builder\n *\n * @param order The current order of work packages that contains the user movement\n * @param positions The current positions as loaded from backend / persisted from previous calls\n * @param wpId The work package that got moved\n * @param index The index a work package got moved into\n * @param fromIndex If moved within the order, the previous index used for movement optimzation\n */\n constructor(readonly order:string[],\n readonly positions:QueryOrder,\n readonly wpId:string,\n readonly index:number,\n readonly fromIndex:number|null) {\n }\n\n public buildDelta():QueryOrder {\n timeOutput(`Building delta for ${this.wpId}@${this.index}`, () => {\n\n // Ensure positions are strictly ascending. There may be cases were this does not happen\n // e.g., having a flat sorted list and turning on hierarchy mode\n if (!this.isAscendingOrder()) {\n this.rebuildPositions();\n } else {\n // Insert only the new element\n this.buildInsertPosition();\n }\n });\n\n debugLog(\"Order DELTA was built as %O\", this.delta);\n\n return this.delta;\n }\n\n\n /**\n * Ensure +order+ is already ascending with the exception of +index+,\n * or otherwise reorder the positions starting from the first element.\n */\n private isAscendingOrder() {\n let current:number|undefined;\n\n for (let i = 0, l = this.order.length; i < l; i++) {\n const id = this.order[i];\n const position = this.positions[id];\n\n // Skip our insertion point\n if (i === this.index) {\n continue;\n }\n\n // If neither position is set\n if (current === undefined || position === undefined) {\n current = position;\n continue;\n }\n\n // If the next position is not larger, rebuild positions\n if (position < current) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Reassign mixed positions so that they are strictly ascending again,\n * but try to keep relative positions alive\n */\n private rebuildPositions() {\n let [min, max] = this.minMaxPositions;\n this.redistribute(min, max);\n }\n\n /**\n * Insert +wpId+ at +index+ in a position that is determined either\n * by its neighbors, one of them in case both do not yet have a position\n */\n private buildInsertPosition() {\n // Special case, order is empty or only contains wpId\n // Then simply insert as the default position unless it already has a position\n if (this.order.length <= 1 && this.positions[this.wpId] === undefined) {\n this.delta[this.wpId] = DEFAULT_ORDER;\n return;\n }\n\n // Special case, shifted movement by one\n if (this.fromIndex !== null && Math.abs(this.fromIndex - this.index) === 1 && this.positionSwap()) {\n return;\n }\n\n // Special case, index is 0\n if (this.index === 0) {\n return this.insertAsFirst();\n }\n\n // Ensure previous positions exist so we can insert wpId @ index\n const predecessorPosition = this.buildUpPredecessorPosition();\n\n // Ensure we reorder when predecessor is at max already\n if (predecessorPosition >= MAX_ORDER) {\n debugLog(`Predecessor position is at max order, need to reorder`);\n return this.reorderedInsert();\n }\n\n // Get the actual successor position, it might vary wildly from the optimal position\n const successorPosition = this.positionFor(this.index + 1);\n\n if (successorPosition === undefined) {\n // Successor does not have a position yet (is NULL), any position will work\n // so let's use the optimal one which is halfway to a potential successor\n this.delta[this.wpId] = predecessorPosition + (ORDER_DISTANCE / 2);\n return;\n }\n\n // Ensure we reorder when successor is at max already\n if (successorPosition >= MAX_ORDER) {\n debugLog(`Successor position is at max order, need to reorder`);\n return this.reorderedInsert();\n }\n\n // successor exists and has a position\n // We will want to insert at the half way from predecessorPosition ... successorPosition\n const distance = Math.floor((successorPosition - predecessorPosition) / 2);\n\n // If there is no space to insert, we're going to optimize the available space\n if (distance < 1) {\n debugLog(\"Cannot insert at optimal position, no space left. Need to reorder\");\n return this.reorderedInsert();\n }\n\n this.delta[this.wpId] = predecessorPosition + distance;\n }\n\n /**\n * Insert wpId as the first element\n */\n private insertAsFirst() {\n // Get the actual successor position, it might vary wildly from the optimal position\n const successorPosition = this.positionFor(this.index + 1);\n\n // If the successor also has no position yet, simply assign the default\n if (successorPosition === undefined) {\n this.delta[this.wpId] = DEFAULT_ORDER;\n } else {\n this.delta[this.wpId] = successorPosition - (ORDER_DISTANCE / 2);\n }\n }\n\n /**\n * Since from and to index or only one apart,\n * we can swap the positions.\n */\n private positionSwap():boolean {\n const myPosition = this.positionFor(this.index!);\n const neighbor = this.order[this.fromIndex!];\n const neighborPosition = this.positionFor(this.fromIndex!);\n\n // If either the neighbor or wpid have no position yet,\n // go through the regular update flow\n if (myPosition === undefined || neighborPosition === undefined) {\n return false;\n }\n\n // Simply swap the two positions\n this.delta[this.wpId] = neighborPosition;\n this.delta[neighbor] = myPosition;\n\n return true;\n }\n\n\n /**\n * Builds any previous unset position from 0 .. index\n * so we can properly insert the wpId @ index.\n */\n private buildUpPredecessorPosition() {\n let predecessorPosition:number = DEFAULT_ORDER - ORDER_DISTANCE;\n\n for (let i = 0; i < this.index; i++) {\n const id = this.order[i];\n const position = this.positions[id];\n\n // If this current ID has no position yet, assign the current one\n if (position === undefined) {\n predecessorPosition = this.delta[id] = predecessorPosition + ORDER_DISTANCE;\n } else {\n predecessorPosition = position;\n }\n }\n\n return predecessorPosition;\n }\n\n /**\n * Return the position number for the given index\n */\n private positionFor(index:number):number|undefined {\n const wpId = this.order[index];\n return this.livePosition(wpId);\n }\n\n /**\n * Return either the delta position or the previous persisted position,\n * in that order.\n *\n * @param wpId\n */\n private livePosition(wpId:string):number|undefined {\n // Explicitly check for undefined here as the delta might be 0 which is falsey.\n return this.delta[wpId] === undefined ? this.positions[wpId] : this.delta[wpId];\n }\n\n /**\n * There was no space left at the desired insert position,\n * we're going to evenly distribute all items again\n */\n private reorderedInsert() {\n // Get the current distance between orders\n // Both must be set by now due to +buildUpPredecessorPosition+ having run.\n let min = this.firstPosition!;\n let max = this.lastPosition!;\n\n this.redistribute(min, max);\n }\n\n /**\n * Distribute the items over a given min/max\n */\n private redistribute(min:number, max:number) {\n const itemsToDistribute = this.order.length;\n\n // We can keep min and max orders if distance/(items to distribute) >= 1\n let space = Math.floor((max - min) / (itemsToDistribute - 1));\n\n // If no space is left, first try to add to the max item\n // Or subtract from the min item\n if (space < 1) {\n if ((max + itemsToDistribute) <= MAX_ORDER) {\n max += itemsToDistribute;\n } else if ((min - itemsToDistribute) >= MIN_ORDER) {\n min -= itemsToDistribute;\n } else {\n // This should not happen in a 4-byte integer with our frontend\n throw \"Elements cannot be moved further and no space is left. Too many elements\";\n }\n\n // Rebuild space\n space = Math.floor((max - min) / (itemsToDistribute - 1));\n }\n\n // Assign positions for all values in between min/max\n for (let i = 0; i < itemsToDistribute; i++) {\n const wpId = this.order[i];\n this.delta[wpId] = min + (i * space);\n }\n }\n\n /**\n * Get the absolute minimum and maximum positions\n * currently assigned in the slot.\n *\n * If there is at least two positions assigned, returns the maximum\n * between them.\n *\n * Otherwise, returns the optimum min max for the given order length.\n */\n private get minMaxPositions():[number, number] {\n let min:number = MAX_ORDER;\n let max:number = MIN_ORDER;\n let any:boolean = false;\n\n for (let i = this.order.length - 1; i >= 0; i--) {\n let wpId = this.order[i];\n let position = this.livePosition(wpId);\n\n if (position !== undefined) {\n min = Math.min(position, min);\n max = Math.max(position, max);\n any = true;\n }\n }\n\n if (any && min !== max) {\n return [min, max];\n } else {\n return [DEFAULT_ORDER, this.order.length * ORDER_DISTANCE];\n }\n }\n\n\n /**\n * Returns the minimal position assigned currently\n */\n private get firstPosition():number {\n const wpId = this.order[0]!;\n return this.livePosition(wpId)!;\n }\n\n /**\n * Returns the maximum position assigned currently.\n * Note that a list can be unpositioned at the beginning, so this may return undefined\n */\n private get lastPosition():number|undefined {\n for (let i = this.order.length - 1; i >= 0; i--) {\n let wpId = this.order[i];\n let position = this.livePosition(wpId);\n\n // Return the first set position.\n if (position !== undefined) {\n return position;\n }\n }\n\n return;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {Injectable} from '@angular/core';\nimport {WorkPackageQueryStateService} from './wp-view-base.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {States} from \"core-components/states.service\";\nimport {QuerySchemaResource} from \"core-app/modules/hal/resources/query-schema-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {MAX_ORDER, ReorderDeltaBuilder} from \"core-app/modules/common/drag-and-drop/reorder-delta-builder\";\nimport {take} from \"rxjs/operators\";\nimport {InputState} from \"reactivestates\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {CausedUpdatesService} from \"core-app/modules/boards/board/caused-updates/caused-updates.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {QueryOrder} from \"core-app/modules/apiv3/endpoints/queries/apiv3-query-order\";\n\n\n@Injectable()\nexport class WorkPackageViewOrderService extends WorkPackageQueryStateService {\n\n constructor(protected readonly querySpace:IsolatedQuerySpace,\n protected readonly apiV3Service:APIV3Service,\n protected readonly states:States,\n protected readonly causedUpdates:CausedUpdatesService,\n protected readonly wpTableSortBy:WorkPackageViewSortByService,\n protected readonly pathHelper:PathHelperService) {\n super(querySpace);\n }\n\n public initialize(query:QueryResource, results:WorkPackageCollectionResource, schema?:QuerySchemaResource):Promise {\n // Take over our current value if the query is not saved\n if (!query.persisted && this.positions.hasValue()) {\n this.applyToQuery(query);\n }\n\n\n if (this.wpTableSortBy.isManualSortingMode) {\n return this.withLoadedPositions();\n }\n\n return Promise.resolve();\n }\n\n /**\n * Move an item in the list\n */\n public async move(order:string[], wpId:string, toIndex:number):Promise {\n // Find index of the work package\n let fromIndex:number = order.findIndex((id) => id === wpId);\n\n order.splice(fromIndex, 1);\n order.splice(toIndex, 0, wpId);\n\n await this.assignPosition(order, wpId, toIndex, fromIndex);\n\n return order;\n }\n\n /**\n * Pull an item from the rendered list\n */\n public remove(order:string[], wpId:string):string[] {\n _.remove(order, id => id === wpId);\n this.update({ [wpId]: -1 });\n return order;\n }\n\n /**\n * Add an item to the list\n */\n public async add(order:string[], wpId:string, toIndex:number = -1):Promise {\n if (toIndex === -1) {\n order.push(wpId);\n toIndex = order.length - 1;\n } else {\n order.splice(toIndex, 0, wpId);\n }\n\n await this.assignPosition(order, wpId, toIndex);\n\n return order;\n }\n\n public get applicable() {\n return this.currentQuery.persisted;\n }\n\n protected get currentQuery():QueryResource {\n return this.querySpace.query.value!;\n }\n\n /**\n * Assign a position for the given work package and its index given the current order\n * @param order Current order the work package was inserted to\n * @param wpId The work package ID that was moved\n * @param toIndex The id of the work package in order\n */\n protected async assignPosition(order:string[], wpId:string, toIndex:number, fromIndex:number|null = null) {\n const positions = await this.withLoadedPositions();\n const delta = new ReorderDeltaBuilder(order, positions, wpId, toIndex, fromIndex).buildDelta();\n\n await this.update(delta);\n }\n\n protected get positions():InputState {\n return this.updatesState;\n }\n\n /**\n * Update the order state\n */\n public async update(delta:QueryOrder) {\n let current = this.positions.getValueOr({});\n this.positions.putValue({ ...current, ...delta });\n\n // Push the update if the query is saved\n if (this.currentQuery.persisted) {\n const updatedAt = await this\n .apiV3Service\n .queries.id(this.currentQuery)\n .order\n .update(delta);\n\n this.currentQuery.updatedAt = updatedAt;\n\n // Remember that we caused this update\n this.causedUpdates.add(this.currentQuery);\n }\n\n // Push into the query object\n this.applyToQuery(this.currentQuery);\n\n // Update the query\n this.querySpace.query.putValue(this.currentQuery);\n }\n\n /**\n * Initialize (or load if persisted) the order for the query space\n */\n public withLoadedPositions():Promise {\n if (this.currentQuery.persisted) {\n const value = this.positions.value;\n\n // Remove empty or stale values given we can reload them\n if ((value === {} || this.positions.isValueOlderThan(60000))) {\n this.positions.clear(\"Clearing old positions value\");\n }\n\n // Load the current order from backend\n this.positions.putFromPromiseIfPristine(\n () => this\n .apiV3Service\n .queries.id(this.currentQuery)\n .order\n .get()\n );\n } else if (this.positions.isPristine()) {\n // Insert an empty fallback in case we have no data yet\n this.positions.putValue({});\n }\n\n return this.positions\n .values$()\n .pipe(take(1))\n .toPromise();\n }\n\n public valueFromQuery(query:QueryResource) {\n return undefined;\n }\n\n /**\n * Return ordered work packages\n */\n orderedWorkPackages():WorkPackageResource[] {\n const upstreamOrder = this.querySpace\n .results\n .value!\n .elements\n .map(wp => this.states.workPackages.get(wp.id!).getValueOr(wp));\n\n if (this.currentQuery.persisted || this.positions.isPristine()) {\n return upstreamOrder;\n } else {\n const positions = this.positions.value!;\n return _.sortBy(upstreamOrder, (wp) => {\n const pos = positions[wp.id!];\n return pos !== undefined ? pos : MAX_ORDER;\n });\n }\n }\n\n applyToQuery(query:QueryResource):boolean {\n query.orderedWorkPackages = this.positions.getValueOr({});\n return false;\n }\n\n hasChanged(query:QueryResource):boolean {\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {States} from '../../../states.service';\nimport {displayClassName, editableClassName, readOnlyClassName} from 'core-app/modules/fields/display/display-field-renderer';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ClickOrEnterHandler} from '../click-or-enter-handler';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {ClickPositionMapper} from \"core-app/modules/common/set-click-position/set-click-position\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class EditCellHandler extends ClickOrEnterHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public states:States;\n @InjectField() public halEditing:HalResourceEditingService;\n\n // Keep a reference to all\n\n public get EVENT() {\n return 'click.table.cell, keydown.table.cell';\n }\n\n public get SELECTOR() {\n return `.${displayClassName}.${editableClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n constructor(public readonly injector:Injector) {\n super();\n }\n\n protected processEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean {\n debugLog('Starting editing on cell: ', evt.target);\n evt.preventDefault();\n\n // Locate the cell from event\n let target = jQuery(evt.target).closest(`.${displayClassName}`);\n // Get the target field name\n let fieldName = target.data('fieldName');\n\n if (!fieldName) {\n debugLog('Click handled by cell not a field? ', evt.target);\n return true;\n }\n\n // Locate the row\n const rowElement = target.closest(`.${tableRowClassName}`);\n // Get the work package we're editing\n const workPackageId = rowElement.data('workPackageId');\n const workPackage = this.states.workPackages.get(workPackageId).value!;\n // Get the row context\n const classIdentifier = rowElement.data('classIdentifier');\n\n // Get any existing edit state for this work package\n const form = table.editing.startEditing(workPackage, classIdentifier);\n\n // Get the position where the user clicked.\n const positionOffset = ClickPositionMapper.getPosition(evt);\n\n // Activate the field\n form.activate(fieldName)\n .then((handler) => {\n handler.$onUserActivate.next();\n handler.focus(positionOffset);\n })\n .catch(() => target.addClass(readOnlyClassName));\n\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {relationCellIndicatorClassName, relationCellTdClassName} from '../../builders/relation-cell-builder';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ClickOrEnterHandler} from '../click-or-enter-handler';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RelationsCellHandler extends ClickOrEnterHandler implements TableEventHandler {\n\n // Injections\n @InjectField() wpTableRelationColumns:WorkPackageViewRelationColumnsService;\n\n public get EVENT() {\n return 'click.table.relationsCell, keydown.table.relationsCell';\n }\n\n public get SELECTOR() {\n return `.${relationCellIndicatorClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n constructor(public readonly injector:Injector) {\n super();\n }\n\n protected processEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean {\n debugLog('Handled click on relation cell %o', evt.target);\n evt.preventDefault();\n\n // Locate the relation td\n const td = jQuery(evt.target).closest(`.${relationCellTdClassName}`);\n const columnId = td.data('columnId');\n\n // Locate the row\n const rowElement = jQuery(evt.target).closest(`.${tableRowClassName}`);\n const workPackageId = rowElement.data('workPackageId');\n\n // If currently expanded\n if (this.wpTableRelationColumns.getExpandFor(workPackageId) === columnId) {\n this.wpTableRelationColumns.collapse(workPackageId);\n } else {\n this.wpTableRelationColumns.setExpandFor(workPackageId, columnId);\n }\n\n return false;\n }\n}\n","import {Injector} from \"@angular/core\";\nimport {WorkPackageAction} from \"core-components/wp-table/context-menu-helper/wp-context-menu-helper.service\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewContextMenu} from \"core-components/op-context-menu/wp-context-menu/wp-view-context-menu.directive\";\nimport {WorkPackageViewHierarchyIdentationService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy-indentation.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class WorkPackageTableContextMenu extends WorkPackageViewContextMenu {\n\n @InjectField() wpViewIndentation:WorkPackageViewHierarchyIdentationService;\n\n constructor(public injector:Injector,\n protected workPackageId:string,\n protected $element:JQuery,\n protected additionalPositionArgs:any = {},\n protected table:WorkPackageTable) {\n super(injector, workPackageId, $element, additionalPositionArgs, true);\n }\n\n public triggerContextMenuAction(action:WorkPackageAction) {\n switch (action.key) {\n case 'relation-precedes':\n this.table.timelineController.startAddRelationPredecessor(this.workPackage);\n break;\n\n case 'relation-follows':\n this.table.timelineController.startAddRelationFollower(this.workPackage);\n break;\n\n case 'hierarchy-indent':\n this.wpViewIndentation.indent(this.workPackage);\n break;\n\n case 'hierarchy-outdent':\n this.wpViewIndentation.outdent(this.workPackage);\n break;\n\n default:\n super.triggerContextMenuAction(action);\n break;\n }\n }\n}\n","import {Injector} from '@angular/core';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {WorkPackageTableContextMenu} from \"core-components/op-context-menu/wp-context-menu/wp-table-context-menu.directive\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport abstract class ContextMenuHandler implements TableEventHandler {\n // Injections\n @InjectField() public opContextMenu:OPContextMenuService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get rowSelector() {\n return `.${tableRowClassName}`;\n }\n\n public abstract get EVENT():string;\n\n public abstract get SELECTOR():string;\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n public abstract handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent):boolean;\n\n protected openContextMenu(table:WorkPackageTable, evt:JQuery.TriggeredEvent, workPackageId:string, positionArgs?:any):void {\n const handler = new WorkPackageTableContextMenu(this.injector, workPackageId, jQuery(evt.target) as JQuery, positionArgs, table);\n this.opContextMenu.show(handler, evt);\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {uiStateLinkClass} from '../../builders/ui-state-link-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ContextMenuHandler} from './context-menu-handler';\nimport {contextMenuLinkClassName} from \"core-components/wp-table/table-actions/table-action\";\nimport {TableEventComponent} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\n\nexport class ContextMenuClickHandler extends ContextMenuHandler {\n\n constructor(public readonly injector:Injector) {\n super(injector);\n }\n\n public get EVENT() {\n return 'click.table.contextmenu';\n }\n\n public get SELECTOR() {\n return `.${contextMenuLinkClassName}`;\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent):boolean {\n let target = jQuery(evt.target);\n\n // We want to keep the original context menu on hrefs\n // (currently, this is only the id\n if (target.closest(`.${uiStateLinkClass}`).length) {\n debugLog('Allowing original context menu on state link');\n return true;\n }\n\n evt.preventDefault();\n evt.stopPropagation();\n\n // Locate the row from event\n const element = target.closest(this.rowSelector);\n const wpId = element.data('workPackageId');\n\n if (wpId) {\n this.openContextMenu(view.workPackageTable, evt, wpId);\n }\n\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ContextMenuHandler} from './context-menu-handler';\nimport {TableEventComponent} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\n\nexport class ContextMenuKeyboardHandler extends ContextMenuHandler {\n\n constructor(public readonly injector:Injector) {\n super(injector);\n }\n\n public get EVENT() {\n return 'keydown.table.contextmenu';\n }\n\n public get SELECTOR() {\n return this.rowSelector;\n }\n\n public handleEvent(component:TableEventComponent, evt:JQuery.TriggeredEvent):boolean {\n if (!component.workPackageTable.configuration.contextMenuEnabled) {\n return false;\n }\n\n let target = jQuery(evt.target);\n\n if (!(evt.keyCode === keyCodes.F10 && evt.shiftKey && evt.altKey)) {\n return true;\n }\n\n evt.preventDefault();\n evt.stopPropagation();\n\n // Locate the row from event\n const element = target.closest(this.SELECTOR);\n const wpId = element.data('workPackageId');\n\n // Set position args to open at element\n let position = { my: 'left top', at: 'left bottom', of: target };\n\n super.openContextMenu(component.workPackageTable, evt, wpId, position);\n\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {timelineCellClassName} from '../../builders/timeline/timeline-row-builder';\nimport {uiStateLinkClass} from '../../builders/ui-state-link-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ContextMenuHandler} from './context-menu-handler';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {TableEventComponent} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\n\nexport class ContextMenuRightClickHandler extends ContextMenuHandler {\n\n @InjectField() readonly wpTableSelection:WorkPackageViewSelectionService;\n\n constructor(public readonly injector:Injector) {\n super(injector);\n }\n\n public get EVENT() {\n return 'contextmenu.table.rightclick';\n }\n\n public get SELECTOR() {\n return `.${tableRowClassName},.${timelineCellClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent):boolean {\n if (!view.workPackageTable.configuration.contextMenuEnabled) {\n return false;\n }\n let target = jQuery(evt.target);\n\n // We want to keep the original context menu on hrefs\n // (currently, this is only the id\n if (target.closest(`.${uiStateLinkClass}`).length) {\n debugLog('Allowing original context menu on state link');\n return true;\n }\n\n evt.preventDefault();\n evt.stopPropagation();\n\n // Locate the row from event\n const element = target.closest(this.SELECTOR);\n const wpId = element.data('workPackageId');\n\n if (wpId) {\n let [index,] = view.workPackageTable.findRenderedRow(wpId);\n\n if (!this.wpTableSelection.isSelected(wpId)) {\n this.wpTableSelection.setSelection(wpId, index);\n }\n\n this.openContextMenu(view.workPackageTable, evt, wpId);\n }\n\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {StateService} from '@uirouter/core';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {States} from '../../../states.service';\nimport {KeepTabService} from '../../../wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {displayClassName} from \"core-app/modules/fields/display/display-field-renderer\";\nimport {activeFieldClassName} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RowClickHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public $state:StateService;\n @InjectField() public states:States;\n @InjectField() public keepTab:KeepTabService;\n @InjectField() public wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() public wpTableFocus:WorkPackageViewFocusService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get EVENT() {\n return 'click.table.row';\n }\n\n public get SELECTOR() {\n return `.${tableRowClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tbody);\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // Ignore links\n if (target.is('a') || target.parent().is('a')) {\n return true;\n }\n\n // Shortcut to any clicks within a cell\n // We don't want to handle these.\n if (target.hasClass(`${displayClassName}`) || target.hasClass(`${activeFieldClassName}`)) {\n debugLog('Skipping click on inner cell');\n return true;\n }\n\n // Locate the row from event\n let element = target.closest(this.SELECTOR);\n let wpId = element.data('workPackageId');\n let classIdentifier = element.data('classIdentifier');\n\n if (!wpId) {\n return true;\n }\n\n let [index, row] = view.workPackageTable.findRenderedRow(classIdentifier);\n\n // Update single selection if no modifier present\n if (!(evt.ctrlKey || evt.metaKey || evt.shiftKey)) {\n this.wpTableSelection.setSelection(wpId, index);\n view.itemClicked.emit({ workPackageId: wpId, double: false });\n }\n\n // Multiple selection if shift present\n if (evt.shiftKey) {\n this.wpTableSelection.setMultiSelectionFrom(view.workPackageTable.renderedRows, wpId, index);\n }\n\n // Single selection expansion if ctrl / cmd(mac)\n if (evt.ctrlKey || evt.metaKey) {\n this.wpTableSelection.toggleRow(wpId);\n }\n\n view.selectionChanged.emit(this.wpTableSelection.getSelectedWorkPackageIds());\n\n // The current row is the last selected work package\n // not matter what other rows are (de-)selected below.\n // Thus save that row for the details view button.\n this.wpTableFocus.updateFocus(wpId);\n return false;\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {StateService} from '@uirouter/core';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {States} from '../../../states.service';\nimport {tdClassName} from '../../builders/cell-builder';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {LinkHandling} from \"core-app/modules/common/link-handling/link-handling\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {displayClassName} from \"core-app/modules/fields/display/display-field-renderer\";\nimport {activeFieldClassName} from \"core-app/modules/fields/edit/edit-form/edit-form\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RowDoubleClickHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public $state:StateService;\n @InjectField() public states:States;\n @InjectField() public wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() public wpTableFocus:WorkPackageViewFocusService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get EVENT() {\n return 'dblclick.table.row';\n }\n\n public get SELECTOR() {\n return `.${tdClassName}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tbody);\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // Skip clicks with modifiers\n if (LinkHandling.isClickedWithModifier(evt)) {\n return true;\n }\n\n // Shortcut to any clicks within a cell\n // We don't want to handle these.\n if (target.hasClass(`${displayClassName}`) || target.hasClass(`${activeFieldClassName}`)) {\n debugLog('Skipping click on inner cell');\n return true;\n }\n\n // Locate the row from event\n let element = target.closest(this.SELECTOR).closest(`.${tableRowClassName}`);\n let wpId = element.data('workPackageId');\n\n // Ignore links\n if (target.is('a') || target.parent().is('a')) {\n return true;\n }\n\n // Save the currently focused work package\n this.wpTableFocus.updateFocus(wpId);\n\n view.itemClicked.emit({ workPackageId: wpId, double: true });\n\n return false;\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {IsolatedQuerySpace} from 'core-app/modules/work_packages/query-space/isolated-query-space';\nimport {rowGroupClassName} from 'core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants';\nimport {InjectField} from 'core-app/helpers/angular/inject-field.decorator';\nimport {WorkPackageViewCollapsedGroupsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service';\n\nexport class GroupRowHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public querySpace:IsolatedQuerySpace;\n @InjectField() public workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get EVENT() {\n return 'click.table.groupheader';\n }\n\n public get SELECTOR() {\n return `.${rowGroupClassName} .expander`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tbody);\n }\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n evt.preventDefault();\n evt.stopPropagation();\n\n let groupHeader = jQuery(evt.target).parents(`.${rowGroupClassName}`);\n let groupIdentifier = groupHeader.data('groupIdentifier');\n\n this.workPackageViewCollapsedGroupsService.toggleGroupCollapseState(groupIdentifier);\n }\n}\n","import {Injector} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {ClickOrEnterHandler} from '../click-or-enter-handler';\nimport {TableEventComponent, TableEventHandler} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HierarchyClickHandler extends ClickOrEnterHandler implements TableEventHandler {\n // Injections\n @InjectField() public states:States;\n @InjectField() public wpTableHierarchies:WorkPackageViewHierarchiesService;\n\n constructor(public readonly injector:Injector) {\n super();\n }\n\n public get EVENT() {\n return 'click.table.hierarchy';\n }\n\n public get SELECTOR() {\n return `.wp-table--hierarchy-indicator`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tbody);\n }\n\n public processEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean {\n let target = jQuery(evt.target);\n\n // Locate the row from event\n let element = target.closest(`.${tableRowClassName}`);\n let wpId = element.data('workPackageId');\n\n this.wpTableHierarchies.toggle(wpId);\n\n evt.stopImmediatePropagation();\n evt.preventDefault();\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../../../states.service';\nimport {KeepTabService} from '../../../wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {uiStateLinkClass} from '../../builders/ui-state-link-builder';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {TableEventComponent, TableEventHandler} from '../table-handler-registry';\nimport {StateService} from '@uirouter/core';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class WorkPackageStateLinksHandler implements TableEventHandler {\n\n // Injections\n @InjectField() public $state:StateService;\n @InjectField() public keepTab:KeepTabService;\n @InjectField() public states:States;\n @InjectField() public wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() public wpTableFocus:WorkPackageViewFocusService;\n\n constructor(public readonly injector:Injector) {\n }\n\n public get EVENT() {\n return 'click.table.wpLink';\n }\n\n public get SELECTOR() {\n return `.${uiStateLinkClass}`;\n }\n\n public eventScope(view:TableEventComponent) {\n return jQuery(view.workPackageTable.tableAndTimelineContainer);\n }\n\n protected workPackage:WorkPackageResource;\n\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n // Avoid the state capture when clicking with modifier\n if (evt.shiftKey || evt.ctrlKey || evt.metaKey || evt.altKey) {\n return true;\n }\n\n // Locate the details link from event\n const target = jQuery(evt.target);\n const element = target.closest(this.SELECTOR);\n const state = element.data('wpState');\n const workPackageId = element.data('workPackageId');\n\n // Blur the target to avoid focus being kept there\n target.closest('a').blur();\n\n // The current row is the last selected work package\n // not matter what other rows are (de-)selected below.\n // Thus save that row for the details view button.\n // Locate the row from event\n let row = target.closest(`.${tableRowClassName}`);\n let classIdentifier = row.data('classIdentifier');\n let [index, _] = view.workPackageTable.findRenderedRow(classIdentifier);\n\n // Update single selection if no modifier present\n this.wpTableSelection.setSelection(workPackageId, index);\n\n view.stateLinkClicked.emit({ workPackageId: workPackageId, requestedState: state });\n\n evt.preventDefault();\n evt.stopPropagation();\n return false;\n }\n}\n","import {Injector} from '@angular/core';\nimport {debugLog} from '../../../../helpers/debug_output';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {takeUntil} from \"rxjs/operators\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class ColumnsTransformer {\n\n @InjectField() public querySpace:IsolatedQuerySpace;\n @InjectField() public wpTableColumns:WorkPackageViewColumnsService;\n\n constructor(public readonly injector:Injector,\n public table:WorkPackageTable) {\n\n this.wpTableColumns\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe(() => {\n if (table.originalRows.length > 0) {\n\n var t0 = performance.now();\n // Redraw the table section, ignore timeline\n table.redrawTable();\n\n var t1 = performance.now();\n\n debugLog('column redraw took ' + (t1 - t0) + ' milliseconds.');\n }\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {scrollTableRowIntoView} from 'core-components/wp-fast-table/helpers/wp-table-row-helpers';\nimport {distinctUntilChanged, filter, map, takeUntil} from 'rxjs/operators';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {\n collapsedGroupClass,\n hierarchyGroupClass,\n hierarchyRootClass\n} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\nimport {indicatorCollapsedClass} from \"core-components/wp-fast-table/builders/modes/hierarchy/single-hierarchy-row-builder\";\nimport {tableRowClassName} from \"core-components/wp-fast-table/builders/rows/single-row-builder\";\nimport {WorkPackageViewHierarchies} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-hierarchies\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HierarchyTransformer {\n\n @InjectField() public wpTableHierarchies:WorkPackageViewHierarchiesService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n\n this.wpTableHierarchies\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n map((state) => state.isVisible),\n distinctUntilChanged()\n )\n .subscribe(() => {\n // We don't have to reload all results when _disabling_ the hierarchy mode.\n if (!this.wpTableHierarchies.isEnabled) {\n table.redrawTableAndTimeline();\n }\n });\n\n let lastValue = this.wpTableHierarchies.isEnabled;\n\n this.wpTableHierarchies\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n filter(() => this.querySpace.tableRendered.hasValue())\n )\n .subscribe((state:WorkPackageViewHierarchies) => {\n\n if (state.isVisible === lastValue) {\n this.renderHierarchyState(state);\n }\n\n lastValue = state.isVisible;\n });\n }\n\n /**\n * Update all currently visible rows to match the selection state.\n */\n private renderHierarchyState(state:WorkPackageViewHierarchies) {\n const rendered = this.querySpace.tableRendered.value!;\n\n // Show all hierarchies\n jQuery('[class^=\"__hierarchy-group-\"]').removeClass((i:number, classNames:string):string => {\n return (classNames.match(/__collapsed-group-\\d+/g) || []).join(' ');\n });\n\n // Mark which rows were hidden by some other hierarchy group\n // (e.g., by a collapsed parent)\n const collapsed:{ [index:number]:boolean } = {};\n\n // Hide all collapsed hierarchies\n _.each(state.collapsed, (isCollapsed:boolean, wpId:string) => {\n // Toggle the root style\n jQuery(`.${hierarchyRootClass(wpId)} .wp-table--hierarchy-indicator`).toggleClass(indicatorCollapsedClass, isCollapsed);\n\n // Get parent row and mark/unmark it as collapsed\n const hierarchyRoot = document.querySelector(`.wp-timeline-cell.__hierarchy-root-${wpId}`);\n\n if (hierarchyRoot) {\n if (isCollapsed) {\n hierarchyRoot.classList.add(`__hierarchy-root-collapsed`);\n } else {\n hierarchyRoot.classList.remove(`__hierarchy-root-collapsed`);\n }\n }\n\n // Get all affected children rows\n const affected = jQuery(`.${hierarchyGroupClass(wpId)}`);\n\n // Hide/Show the descendants.\n affected.toggleClass(collapsedGroupClass(wpId), isCollapsed);\n\n // Update the hidden section of the rendered state\n affected.filter(`.${tableRowClassName}`).each((i, el) => {\n // Get the index of this row\n const index = jQuery(el).index();\n\n // Update the hidden state\n if (!collapsed[index]) {\n rendered[index].hidden = isCollapsed;\n collapsed[index] = isCollapsed;\n }\n });\n });\n\n // Keep focused on the last element, if any.\n // Based on https://stackoverflow.com/a/3782959\n if (state.last) {\n scrollTableRowIntoView(state.last);\n }\n\n\n this.querySpace.tableRendered.putValue(rendered, 'Updated hidden state of rows after hierarchy change.');\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {takeUntil} from \"rxjs/operators\";\nimport {WorkPackageViewRelationColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-relation-columns.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RelationsTransformer {\n\n @InjectField() public wpTableRelationColumns:WorkPackageViewRelationColumnsService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n\n this.wpTableRelationColumns\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe(() => {\n table.redrawTableAndTimeline();\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {filter, takeUntil} from 'rxjs/operators';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {States} from 'core-components/states.service';\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class RowsTransformer {\n\n @InjectField() querySpace:IsolatedQuerySpace;\n @InjectField() wpTableSortBy:WorkPackageViewSortByService;\n @InjectField() wpTableOrder:WorkPackageViewOrderService;\n @InjectField() states:States;\n\n constructor(public readonly injector:Injector,\n public table:WorkPackageTable) {\n\n // Redraw table if the current row state changed\n this.querySpace\n .initialized\n .values$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe(() => {\n let rows:WorkPackageResource[];\n\n if (this.wpTableSortBy.isManualSortingMode) {\n rows = this.wpTableOrder.orderedWorkPackages();\n } else {\n rows = this.querySpace.results.value!.elements;\n }\n\n table.initialSetup(rows);\n });\n\n // Refresh a single row if it exists\n this.states.workPackages.observeChange()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions.asObservable()),\n filter(() => {\n let rendered = this.querySpace.tableRendered.getValueOr([]);\n return rendered && rendered.length > 0;\n })\n )\n .subscribe(([changedId, wp]) => {\n if (wp === undefined) {\n return;\n }\n\n this.table.refreshRows(wp);\n });\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';\nimport {takeUntil} from 'rxjs/operators';\nimport {tableRowClassName} from '../../builders/rows/single-row-builder';\nimport {checkedClassName} from '../../builders/ui-state-link-builder';\nimport {locateTableRow, scrollTableRowIntoView} from '../../helpers/wp-table-row-helpers';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {FocusHelperService} from 'core-app/modules/common/focus/focus-helper';\nimport {\n WorkPackageViewSelectionService,\n WorkPackageViewSelectionState\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class SelectionTransformer {\n\n @InjectField() public wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() public wpTableFocus:WorkPackageViewFocusService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n @InjectField() public FocusHelper:FocusHelperService;\n\n constructor(public readonly injector:Injector,\n public readonly table:WorkPackageTable) {\n\n // Focus a single selection when active\n this.querySpace.tableRendered.values$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe(() => {\n\n this.wpTableFocus.ifShouldFocus((wpId:string) => {\n const element = locateTableRow(wpId);\n if (element.length) {\n scrollTableRowIntoView(wpId);\n this.FocusHelper.focusElement(element, true);\n }\n });\n });\n\n\n // Update selection state\n this.wpTableSelection.live$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe((state:WorkPackageViewSelectionState) => {\n this.renderSelectionState(state);\n });\n\n\n this.wpTableSelection.registerSelectAllListener(() => {\n return table.renderedRows;\n });\n this.wpTableSelection.registerDeselectAllListener();\n }\n\n /**\n * Update all currently visible rows to match the selection state.\n */\n private renderSelectionState(state:WorkPackageViewSelectionState) {\n const context = jQuery(this.table.tableAndTimelineContainer);\n\n context.find(`.${tableRowClassName}.${checkedClassName}`).removeClass(checkedClassName);\n\n _.each(state.selected, (selected:boolean, workPackageId:any) => {\n context.find(`.${tableRowClassName}[data-work-package-id=\"${workPackageId}\"]`).toggleClass(checkedClassName, selected);\n });\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {takeUntil} from 'rxjs/operators';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageTimelineState} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-timeline\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class TimelineTransformer {\n\n @InjectField() public querySpace:IsolatedQuerySpace;\n @InjectField() public wpTableTimeline:WorkPackageViewTimelineService;\n\n constructor(readonly injector:Injector,\n readonly table:WorkPackageTable) {\n\n this.wpTableTimeline\n .live$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions)\n )\n .subscribe((state:WorkPackageTimelineState) => {\n this.renderVisibility(state.visible);\n });\n }\n\n /**\n * Update all currently visible rows to match the selection state.\n */\n private renderVisibility(visible:boolean) {\n const container = jQuery(this.table.tableAndTimelineContainer).parent();\n container.find('.work-packages-tabletimeline--timeline-side').toggle(visible);\n container.find('.work-packages-tabletimeline--table-side').toggleClass('-timeline-visible', visible);\n }\n}\n","import {Injector} from '@angular/core';\nimport {distinctUntilChanged, takeUntil} from 'rxjs/operators';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageViewHighlightingService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class HighlightingTransformer {\n\n @InjectField() public wpTableHighlighting:WorkPackageViewHighlightingService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n this.wpTableHighlighting\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n distinctUntilChanged()\n )\n .subscribe(() => table.redrawTable());\n }\n}\n","import {Injector} from '@angular/core';\nimport {WorkPackageTable} from '../../wp-fast-table';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {take, takeUntil} from \"rxjs/operators\";\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {TableDragActionsRegistryService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-actions-registry.service\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {States} from \"core-components/states.service\";\nimport {tableRowClassName} from \"core-components/wp-fast-table/builders/rows/single-row-builder\";\nimport {DragAndDropService} from \"core-app/modules/common/drag-and-drop/drag-and-drop.service\";\nimport {DragAndDropHelpers} from \"core-app/modules/common/drag-and-drop/drag-and-drop.helpers\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {isInsideCollapsedGroup} from \"core-components/wp-fast-table/helpers/wp-table-row-helpers\";\nimport {collapsedGroupClass} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\n\nexport class DragAndDropTransformer {\n\n @InjectField() private readonly states:States;\n @InjectField() private readonly querySpace:IsolatedQuerySpace;\n @InjectField() private readonly inlineCreateService:WorkPackageInlineCreateService;\n @InjectField() private readonly halNotification:HalResourceNotificationService;\n @InjectField() private readonly wpTableSortBy:WorkPackageViewSortByService;\n @InjectField() private readonly wpTableOrder:WorkPackageViewOrderService;\n @InjectField() private readonly browserDetector:BrowserDetector;\n @InjectField() private readonly apiV3Service:APIV3Service;\n @InjectField() private readonly wpListService:WorkPackagesListService;\n @InjectField() private readonly dragActionRegistry:TableDragActionsRegistryService;\n @InjectField(DragAndDropService, null) private readonly dragService:DragAndDropService|null;\n\n constructor(public readonly injector:Injector,\n public table:WorkPackageTable) {\n\n // The DragService may not have been provided\n // in which case we do not provide drag and drop\n if (this.dragService === null) {\n return;\n }\n\n this.inlineCreateService.newInlineWorkPackageCreated\n .pipe(takeUntil(this.querySpace.stopAllSubscriptions))\n .subscribe(async (wpId) => {\n const newOrder = await this.wpTableOrder.add(this.currentOrder, wpId);\n this.updateRenderedOrder(newOrder);\n });\n\n this.querySpace.stopAllSubscriptions\n .pipe(take(1))\n .subscribe(() => {\n this.dragService!.remove(this.table.tbody);\n });\n\n this.dragService.register({\n dragContainer: this.table.tbody,\n scrollContainers: [this.table.scrollContainer],\n accepts: () => true,\n moves: (el:any, source:any, handle:HTMLElement) => {\n if (!handle.classList.contains('wp-table--drag-and-drop-handle')) {\n return false;\n }\n\n const wpId:string = el.dataset.workPackageId!;\n const workPackage = this.states.workPackages.get(wpId).value;\n return !!workPackage && this.actionService.canPickup(workPackage);\n },\n onMoved: async (el:HTMLElement, target:HTMLElement, source:HTMLElement, sibling:HTMLElement|null) => {\n const wpId:string = el.dataset.workPackageId!;\n let rowIndex;\n\n try {\n const workPackage = await this.apiV3Service.work_packages.id(wpId).get().toPromise();\n\n if (isInsideCollapsedGroup(sibling)) {\n const collapsedGroupCSSClass = Array.from(sibling!.classList).find(listClass => listClass.includes(collapsedGroupClass()))!;\n const collapsedGroupId = collapsedGroupCSSClass.replace(collapsedGroupClass(), '');\n const collapsedGroupElements = source.getElementsByClassName(collapsedGroupClass(collapsedGroupId));\n const collapsedGroupLastChild = collapsedGroupElements[collapsedGroupElements.length - 1];\n rowIndex = this.findRowIndex(collapsedGroupLastChild as HTMLElement);\n } else {\n rowIndex = this.findRowIndex(el);\n }\n\n const newOrder = await this.wpTableOrder.move(this.currentOrder, wpId, rowIndex);\n\n await this.actionService.handleDrop(workPackage, el);\n this.updateRenderedOrder(newOrder);\n this.actionService.onNewOrder(newOrder);\n\n // Save the query when switching to manual\n let query = this.querySpace.query.value;\n if (query && this.wpTableSortBy.switchToManualSorting(query)) {\n await this.wpListService.save(query);\n }\n } catch (e) {\n this.halNotification.handleRawError(e);\n\n // Restore original element's styles\n this.actionService.changeShadowElement(el, true);\n // Restore element in from container\n DragAndDropHelpers.reinsert(el, el.dataset.sourceIndex || -1, source);\n }\n },\n onRemoved: (el:HTMLElement) => {\n const wpId:string = el.dataset.workPackageId!;\n const newOrder = this.wpTableOrder.remove(this.currentOrder, wpId);\n this.updateRenderedOrder(newOrder);\n },\n onAdded: async (el:HTMLElement) => {\n const wpId:string = el.dataset.workPackageId!;\n const workPackage = await this.apiV3Service.work_packages.id(wpId).get().toPromise();\n const rowIndex = this.findRowIndex(el);\n\n return this.actionService\n .handleDrop(workPackage, el)\n .then(async () => {\n const newOrder = await this.wpTableOrder.add(this.currentOrder, wpId, rowIndex);\n this.updateRenderedOrder(newOrder);\n this.actionService.onNewOrder(newOrder);\n\n return true;\n })\n .catch(() => false);\n },\n onCloned: async (clone:HTMLElement, original:HTMLElement) => {\n // Replace clone with one TD of the subject\n const wpId:string = original.dataset.workPackageId!;\n const workPackage = await this.apiV3Service.work_packages.id(wpId).get().toPromise();\n\n const colspan = clone.children.length;\n const td = document.createElement('td');\n td.textContent = workPackage.subjectWithId();\n td.colSpan = colspan;\n td.classList.add('wp-table--cell-td', 'subject');\n\n clone.style.maxWidth = '500px';\n clone.innerHTML = td.outerHTML;\n },\n onShadowInserted: (el:HTMLElement) => {\n if (!this.browserDetector.isEdge) {\n this.actionService.changeShadowElement(el);\n }\n },\n onCancel: (el:HTMLElement) => {\n if (!this.browserDetector.isEdge) {\n this.actionService.changeShadowElement(el, true);\n }\n },\n });\n }\n\n /**\n * Update current rendered order\n */\n private async updateRenderedOrder(order:string[]) {\n order = _.uniq(order);\n\n const mappedOrder = await Promise.all(\n order.map(\n wpId => this.apiV3Service.work_packages.id(wpId).get().toPromise()\n )\n );\n\n /** Re-render the table */\n this.table.initialSetup(mappedOrder);\n }\n\n protected get actionService():TableDragActionService {\n return this.dragActionRegistry.get(this.injector);\n }\n\n protected get currentOrder():string[] {\n return this\n .currentRenderedOrder\n .map((row) => row.workPackageId!);\n }\n\n protected get currentRenderedOrder():RenderedWorkPackage[] {\n return this\n .querySpace\n .renderedWorkPackages\n .getValueOr([]);\n }\n\n /**\n * Find the index of the row in the set of rendered work packages.\n * This will skip non-work-package rows such as group headers\n * @param el\n */\n private findRowIndex(el:HTMLElement):number {\n const rows = Array.from(this.table.tbody.getElementsByClassName(tableRowClassName));\n return rows.indexOf(el) || 0;\n }\n}\n","import {Injector} from '@angular/core';\nimport {distinctUntilChanged, takeUntil} from 'rxjs/operators';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {WorkPackageViewCollapsedGroupsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service\";\n\nexport class GroupFoldTransformer {\n\n @InjectField() public workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService;\n @InjectField() public querySpace:IsolatedQuerySpace;\n\n constructor(public readonly injector:Injector,\n table:WorkPackageTable) {\n this.workPackageViewCollapsedGroupsService\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n distinctUntilChanged()\n )\n .subscribe((groupsCollapseEvent) => table.setGroupsCollapseState(groupsCollapseEvent.state));\n }\n}\n","import {EventEmitter, Injector} from '@angular/core';\nimport {WorkPackageTable} from '../wp-fast-table';\nimport {EditCellHandler} from './cell/edit-cell-handler';\nimport {RelationsCellHandler} from './cell/relations-cell-handler';\nimport {ContextMenuClickHandler} from './context-menu/context-menu-click-handler';\nimport {ContextMenuKeyboardHandler} from './context-menu/context-menu-keyboard-handler';\nimport {ContextMenuRightClickHandler} from './context-menu/context-menu-rightclick-handler';\nimport {RowClickHandler} from './row/click-handler';\nimport {RowDoubleClickHandler} from './row/double-click-handler';\nimport {GroupRowHandler} from './row/group-row-handler';\nimport {HierarchyClickHandler} from './row/hierarchy-click-handler';\nimport {WorkPackageStateLinksHandler} from './row/wp-state-links-handler';\nimport {ColumnsTransformer} from './state/columns-transformer';\nimport {HierarchyTransformer} from './state/hierarchy-transformer';\nimport {RelationsTransformer} from './state/relations-transformer';\nimport {RowsTransformer} from './state/rows-transformer';\nimport {SelectionTransformer} from './state/selection-transformer';\nimport {TimelineTransformer} from './state/timeline-transformer';\nimport {HighlightingTransformer} from \"core-components/wp-fast-table/handlers/state/highlighting-transformer\";\nimport {DragAndDropTransformer} from \"core-components/wp-fast-table/handlers/state/drag-and-drop-transformer\";\nimport {\n WorkPackageViewEventHandler, WorkPackageViewOutputs,\n WorkPackageViewHandlerRegistry\n} from \"core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry\";\nimport {WorkPackageFocusContext} from \"core-components/wp-table/wp-table.component\";\nimport {GroupFoldTransformer} from \"core-components/wp-fast-table/handlers/state/group-fold-transformer\";\n\ntype StateTransformers = {\n // noinspection JSUnusedLocalSymbols\n new(injector:Injector, table:WorkPackageTable):any;\n};\n\nexport interface TableEventComponent extends WorkPackageViewOutputs {\n // Reference to the fast table instance\n workPackageTable:WorkPackageTable;\n}\n\nexport type TableEventHandler = WorkPackageViewEventHandler;\n\nexport class TableHandlerRegistry extends WorkPackageViewHandlerRegistry {\n\n protected eventHandlers:((t:TableEventComponent) => TableEventHandler)[] = [\n // Hierarchy expansion/collapsing\n () => new HierarchyClickHandler(this.injector),\n // Clicking or pressing Enter on a single cell, editable or not\n () => new EditCellHandler(this.injector),\n // Clicking on the details view\n () => new WorkPackageStateLinksHandler(this.injector),\n // Clicking on the row (not within a cell)\n () => new RowClickHandler(this.injector),\n // Double Clicking on the cell within the row\n () => new RowDoubleClickHandler(this.injector),\n // Clicking on group headers\n () => new GroupRowHandler(this.injector),\n // Right clicking on rows\n () => new ContextMenuRightClickHandler(this.injector),\n // Left clicking on the dropdown icon\n () => new ContextMenuClickHandler(this.injector),\n // SHIFT+ALT+F10 on rows\n () => new ContextMenuKeyboardHandler(this.injector),\n // Clicking on relations cells\n () => new RelationsCellHandler(this.injector)\n ];\n\n protected readonly stateTransformers:StateTransformers[] = [\n SelectionTransformer,\n RowsTransformer,\n ColumnsTransformer,\n GroupFoldTransformer,\n TimelineTransformer,\n HierarchyTransformer,\n RelationsTransformer,\n HighlightingTransformer,\n DragAndDropTransformer\n ];\n\n attachTo(viewRef:TableEventComponent) {\n this.stateTransformers.map((cls) => {\n return new cls(this.injector, viewRef.workPackageTable);\n });\n\n super.attachTo(viewRef);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nconst cssClassRowHovered = 'row-hovered';\n\nexport class WpTableHoverSync {\n\n private lastHoveredElement:Element | null = null;\n\n private eventListener = (evt:MouseEvent) => {\n const target = evt.target as Element|null;\n if (target && target !== this.lastHoveredElement) {\n this.handleHover(target);\n }\n this.lastHoveredElement = target;\n }\n\n constructor(private tableAndTimeline:JQuery) {\n }\n\n activate() {\n window.addEventListener('mousemove', this.eventListener, { passive: true });\n }\n\n deactivate() {\n window.removeEventListener('mousemove', this.eventListener);\n this.removeAllHoverClasses();\n }\n\n private locateHoveredTableRow(child:JQuery):Element | null {\n const parent = child.closest('tr');\n if (parent.length === 0) {\n return null;\n }\n return parent[0];\n }\n\n private locateHoveredTimelineRow(child:JQuery):Element | null {\n const parent = child.closest('div.wp-timeline-cell');\n if (parent.length === 0) {\n return null;\n }\n return parent[0];\n }\n\n private handleHover(element:Element) {\n const $element = jQuery(element) as JQuery;\n const parentTableRow = this.locateHoveredTableRow($element);\n const parentTimelineRow = this.locateHoveredTimelineRow($element);\n\n // remove all hover classes if cursor does not hover a row\n if (parentTableRow === null && parentTimelineRow === null) {\n this.removeAllHoverClasses();\n return;\n }\n\n this.removeOldAndAddNewHoverClass(parentTableRow, parentTimelineRow);\n }\n\n private extractWorkPackageId(row:Element):number {\n return parseInt(row.getAttribute('data-work-package-id')!);\n }\n\n private removeOldAndAddNewHoverClass(parentTableRow:Element | null, parentTimelineRow:Element | null) {\n const hovered = parentTableRow !== null ? parentTableRow : parentTimelineRow;\n const wpId = this.extractWorkPackageId(hovered!);\n\n const tableRow:JQuery = this.tableAndTimeline.find('tr.wp-row-' + wpId).first();\n const timelineRow:JQuery = this.tableAndTimeline.find('div.wp-row-' + wpId).length ?\n this.tableAndTimeline.find('div.wp-row-' + wpId).first() :\n this.tableAndTimeline.find('div.wp-ancestor-row-' + wpId).first();\n\n requestAnimationFrame(() => {\n this.removeAllHoverClasses();\n timelineRow.addClass(cssClassRowHovered);\n tableRow.addClass(cssClassRowHovered);\n });\n }\n\n private removeAllHoverClasses() {\n this.tableAndTimeline\n .find(`.${cssClassRowHovered}`)\n .removeClass(cssClassRowHovered);\n }\n}\n","
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n {{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, EventEmitter,\n Injector,\n Input,\n NgZone,\n OnInit, Output,\n ViewEncapsulation\n} from '@angular/core';\nimport {QueryGroupByResource} from 'core-app/modules/hal/resources/query-group-by-resource';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {TableEventComponent, TableHandlerRegistry} from 'core-components/wp-fast-table/handlers/table-handler-registry';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {combineLatest} from 'rxjs';\nimport {States} from '../states.service';\nimport {\n WorkPackageTableConfiguration,\n WorkPackageTableConfigurationObject\n} from 'core-app/components/wp-table/wp-table-configuration';\nimport {QueryColumn} from 'core-components/wp-query/query-column';\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {createScrollSync} from \"core-components/wp-table/wp-table-scroll-sync\";\nimport {WpTableHoverSync} from \"core-components/wp-table/wp-table-hover-sync\";\nimport {WorkPackageTimelineTableController} from \"core-components/wp-table/timeline/container/wp-timeline-container.directive\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\nexport interface WorkPackageFocusContext {\n /** Work package that was focused */\n workPackageId:string;\n /** Through what action did the focus happen */\n through:'row-double-click'|'id-click'|'details-icon';\n}\n\n@Component({\n templateUrl: './wp-table.directive.html',\n styleUrls: ['./wp-table.styles.sass'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-table',\n})\nexport class WorkPackagesTableComponent extends UntilDestroyedMixin implements OnInit, TableEventComponent {\n\n @Input() projectIdentifier:string;\n @Input('configuration') configurationObject:WorkPackageTableConfigurationObject;\n\n @Output() selectionChanged = new EventEmitter();\n @Output() itemClicked = new EventEmitter<{ workPackageId:string, double:boolean }>();\n @Output() stateLinkClicked = new EventEmitter<{ workPackageId:string, requestedState:string }>();\n\n public trackByHref = AngularTrackingHelpers.trackByHref;\n\n public configuration:WorkPackageTableConfiguration;\n\n private $element:JQuery;\n\n private scrollSyncUpdate:(timelineVisible:boolean) => any;\n\n private wpTableHoverSync:WpTableHoverSync;\n\n public tableElement:HTMLElement;\n\n public workPackageTable:WorkPackageTable;\n\n public tbody:JQuery;\n\n public query:QueryResource;\n\n public timeline:HTMLElement;\n\n public locale:string;\n\n public text:any;\n\n public results:WorkPackageCollectionResource;\n\n public groupBy:QueryGroupByResource|null;\n\n public columns:QueryColumn[];\n\n public numTableColumns:number;\n\n public timelineVisible:boolean;\n\n public manualSortEnabled:boolean;\n\n public limitedResults = false;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly states:States,\n readonly querySpace:IsolatedQuerySpace,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly zone:NgZone,\n readonly wpTableGroupBy:WorkPackageViewGroupByService,\n readonly wpTableTimeline:WorkPackageViewTimelineService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly wpTableSortBy:WorkPackageViewSortByService) {\n super();\n }\n\n ngOnInit():void {\n this.configuration = new WorkPackageTableConfiguration(this.configurationObject);\n this.$element = jQuery(this.elementRef.nativeElement);\n\n // Clear any old table subscribers\n this.querySpace.stopAllSubscriptions.next();\n\n this.locale = I18n.locale;\n\n this.text = {\n cancel: I18n.t('js.button_cancel'),\n noResults: {\n title: I18n.t('js.work_packages.no_results.title'),\n description: I18n.t('js.work_packages.no_results.description')\n },\n limitedResults: (count:number, total:number) => {\n return I18n.t('js.work_packages.limited_results', { count: count, total: total });\n },\n tableSummary: I18n.t('js.work_packages.table.summary'),\n tableSummaryHints: [\n I18n.t('js.work_packages.table.text_inline_edit'),\n I18n.t('js.work_packages.table.text_select_hint'),\n I18n.t('js.work_packages.table.text_sort_hint')\n ].join(' ')\n };\n\n let statesCombined = combineLatest([\n this.querySpace.results.values$(),\n this.wpTableGroupBy.live$(),\n this.wpTableColumns.live$(),\n this.wpTableTimeline.live$(),\n this.wpTableSortBy.live$()\n ]);\n\n statesCombined.pipe(\n this.untilDestroyed()\n ).subscribe(([results, groupBy, columns, timelines, sort]) => {\n this.query = this.querySpace.query.value!;\n\n this.results = results;\n\n this.groupBy = groupBy;\n this.columns = columns;\n // Total columns = all available columns + id + checkbox\n this.numTableColumns = this.columns.length + 2;\n\n if (this.scrollSyncUpdate && this.timelineVisible !== timelines.visible) {\n this.scrollSyncUpdate(timelines.visible);\n }\n\n this.timelineVisible = timelines.visible;\n\n this.manualSortEnabled = this.wpTableSortBy.isManualSortingMode;\n this.limitedResults = this.manualSortEnabled && results.total > results.count;\n\n this.cdRef.detectChanges();\n });\n\n this.cdRef.detectChanges();\n }\n\n public ngOnDestroy():void {\n super.ngOnDestroy();\n this.wpTableHoverSync.deactivate();\n }\n\n public registerTimeline(controller:WorkPackageTimelineTableController, timelineBody:HTMLElement) {\n const tbody = this.$element.find('.work-package--results-tbody');\n const scrollContainer = this.$element.find('.work-package-table--container')[0];\n this.workPackageTable = new WorkPackageTable(\n this.injector,\n // Outer container for both table + Timeline\n this.$element[0],\n // Scroll container for the table/timeline\n scrollContainer,\n // Table tbody to insert into\n tbody[0],\n // Timeline body to insert into\n timelineBody,\n // Timeline controller\n controller,\n // Table configuration\n this.configuration\n );\n this.tbody = tbody;\n controller.workPackageTable = this.workPackageTable;\n new TableHandlerRegistry(this.injector).attachTo(this);\n\n // Locate table and timeline elements\n const tableAndTimeline = this.getTableAndTimelineElement();\n this.tableElement = tableAndTimeline[0];\n this.timeline = tableAndTimeline[1];\n\n // sync hover from table to timeline\n this.wpTableHoverSync = new WpTableHoverSync(this.$element);\n this.wpTableHoverSync.activate();\n\n // sync scroll from table to timeline\n this.scrollSyncUpdate = createScrollSync(this.$element);\n this.scrollSyncUpdate(this.timelineVisible);\n\n this.cdRef.detectChanges();\n }\n\n public get isEmbedded() {\n return this.configuration.isEmbedded;\n }\n\n private getTableAndTimelineElement():[HTMLElement, HTMLElement] {\n const $tableSide = this.$element.find('.work-packages-tabletimeline--table-side');\n const $timelineSide = this.$element.find('.work-packages-tabletimeline--timeline-side');\n\n if ($timelineSide.length === 0 || $tableSide.length === 0) {\n throw new Error('invalid state');\n }\n\n return [$tableSide[0], $timelineSide[0]];\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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.ofProperty(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.ofProperty(this.name);\n\n if (!fieldSchema) {\n return handler.deactivate(false);\n }\n\n this.change = change;\n this.schema = change.schema.ofProperty(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.schema.mappedName(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 {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","var map = {\n\t\"./admin_users\": [\n\t\t\"FyB/\",\n\t\t7,\n\t\t12\n\t],\n\t\"./admin_users.js\": [\n\t\t\"FyB/\",\n\t\t7,\n\t\t12\n\t],\n\t\"./administration_settings\": [\n\t\t\"pIQB\",\n\t\t7,\n\t\t13\n\t],\n\t\"./administration_settings.js\": [\n\t\t\"pIQB\",\n\t\t7,\n\t\t13\n\t],\n\t\"./backlogs\": [\n\t\t\"1cF+\",\n\t\t7,\n\t\t1,\n\t\t6\n\t],\n\t\"./backlogs.js\": [\n\t\t\"1cF+\",\n\t\t7,\n\t\t1,\n\t\t6\n\t],\n\t\"./backlogs/backlog\": [\n\t\t\"VbDW\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/backlog.js\": [\n\t\t\"VbDW\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/burndown\": [\n\t\t\"n+FW\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/burndown.js\": [\n\t\t\"n+FW\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/common\": [\n\t\t\"+TUS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/common.js\": [\n\t\t\"+TUS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/editable_inplace\": [\n\t\t\"xOUI\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/editable_inplace.js\": [\n\t\t\"xOUI\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/impediment\": [\n\t\t\"CO8W\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/impediment.js\": [\n\t\t\"CO8W\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/master_backlog\": [\n\t\t\"QrsS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/master_backlog.js\": [\n\t\t\"QrsS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/model\": [\n\t\t\"vTya\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/model.js\": [\n\t\t\"vTya\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/show_main\": [\n\t\t\"ySs4\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/show_main.js\": [\n\t\t\"ySs4\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/sprint\": [\n\t\t\"gFIQ\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/sprint.js\": [\n\t\t\"gFIQ\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/story\": [\n\t\t\"6Ibq\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/story.js\": [\n\t\t\"6Ibq\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/task\": [\n\t\t\"qE9B\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/task.js\": [\n\t\t\"qE9B\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/taskboard\": [\n\t\t\"g/gS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/taskboard.js\": [\n\t\t\"g/gS\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/work_package\": [\n\t\t\"UHLX\",\n\t\t7,\n\t\t1\n\t],\n\t\"./backlogs/work_package.js\": [\n\t\t\"UHLX\",\n\t\t7,\n\t\t1\n\t],\n\t\"./custom_fields\": [\n\t\t\"aLwj\",\n\t\t7,\n\t\t14\n\t],\n\t\"./custom_fields.js\": [\n\t\t\"aLwj\",\n\t\t7,\n\t\t14\n\t],\n\t\"./forums\": [\n\t\t\"9SdV\",\n\t\t7,\n\t\t15\n\t],\n\t\"./forums.js\": [\n\t\t\"9SdV\",\n\t\t7,\n\t\t15\n\t],\n\t\"./global_roles\": [\n\t\t\"qOGe\",\n\t\t7,\n\t\t10\n\t],\n\t\"./global_roles.ts\": [\n\t\t\"qOGe\",\n\t\t7,\n\t\t10\n\t],\n\t\"./meeting\": [\n\t\t\"dVjf\",\n\t\t7,\n\t\t16\n\t],\n\t\"./meeting.js\": [\n\t\t\"dVjf\",\n\t\t7,\n\t\t16\n\t],\n\t\"./members_form\": [\n\t\t\"jeHl\",\n\t\t7,\n\t\t17\n\t],\n\t\"./members_form.js\": [\n\t\t\"jeHl\",\n\t\t7,\n\t\t17\n\t],\n\t\"./new_user\": [\n\t\t\"1z6l\",\n\t\t7,\n\t\t18\n\t],\n\t\"./new_user.js\": [\n\t\t\"1z6l\",\n\t\t7,\n\t\t18\n\t],\n\t\"./project\": [\n\t\t\"y2NQ\",\n\t\t7,\n\t\t19\n\t],\n\t\"./project.js\": [\n\t\t\"y2NQ\",\n\t\t7,\n\t\t19\n\t],\n\t\"./project_form_listener\": [\n\t\t\"Y9rl\",\n\t\t7,\n\t\t20\n\t],\n\t\"./project_form_listener.js\": [\n\t\t\"Y9rl\",\n\t\t7,\n\t\t20\n\t],\n\t\"./repository_navigation\": [\n\t\t\"wJjJ\",\n\t\t7,\n\t\t21\n\t],\n\t\"./repository_navigation.js\": [\n\t\t\"wJjJ\",\n\t\t7,\n\t\t21\n\t],\n\t\"./repository_settings\": [\n\t\t\"815p\",\n\t\t7,\n\t\t22\n\t],\n\t\"./repository_settings.js\": [\n\t\t\"815p\",\n\t\t7,\n\t\t22\n\t],\n\t\"./two_factor_authentication\": [\n\t\t\"Q8SW\",\n\t\t9,\n\t\t9\n\t],\n\t\"./two_factor_authentication.ts\": [\n\t\t\"Q8SW\",\n\t\t9,\n\t\t9\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tvar ids = map[req], id = ids[0];\n\treturn Promise.all(ids.slice(2).map(__webpack_require__.e)).then(function() {\n\t\treturn __webpack_require__.t(id, ids[1])\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = \"VbPg\";\nmodule.exports = webpackAsyncContext;","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../../states.service';\nimport {StateService} from '@uirouter/core';\nimport {Injectable} from '@angular/core';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageRelationsHierarchyService {\n constructor(protected $state:StateService,\n protected states:States,\n protected halEvents:HalEventsService,\n protected notificationService:WorkPackageNotificationService,\n protected pathHelper:PathHelperService,\n protected apiV3Service:APIV3Service) {\n\n }\n\n public changeParent(workPackage:WorkPackageResource, parentId:string|null) {\n let payload:any = {\n lockVersion: workPackage.lockVersion\n };\n\n if (parentId) {\n payload['_links'] = {\n parent: {\n href: this.apiV3Service.work_packages.id(parentId).path\n }\n };\n } else {\n payload['_links'] = {\n parent: {\n href: null\n }\n };\n }\n\n return workPackage\n .changeParent(payload)\n .then((wp:WorkPackageResource) => {\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(wp);\n this.notificationService.showSave(wp);\n this.halEvents.push(workPackage, {\n eventType: 'association',\n relatedWorkPackage: parentId,\n relationType: 'parent'\n });\n\n return wp;\n })\n .catch((error) => {\n this.notificationService.handleRawError(error, workPackage);\n return Promise.reject(error);\n });\n }\n\n public removeParent(workPackage:WorkPackageResource) {\n return this.changeParent(workPackage, null);\n }\n\n public addExistingChildWp(workPackage:WorkPackageResource, childWpId:string):Promise {\n return this\n .apiV3Service\n .work_packages\n .id(childWpId)\n .get()\n .toPromise()\n .then((wpToBecomeChild:WorkPackageResource|undefined) => {\n return this.changeParent(wpToBecomeChild!, workPackage.id!)\n .then(wp => {\n // Reload work package\n this\n .apiV3Service\n .work_packages\n .id(workPackage)\n .refresh();\n\n this.halEvents.push(workPackage, {\n eventType: 'association',\n relatedWorkPackage: wpToBecomeChild!.id!,\n relationType: 'child'\n });\n\n return wp;\n });\n });\n }\n\n public addNewChildWp(baseRoute:string, workPackage:WorkPackageResource) {\n workPackage.project.$load()\n .then(() => {\n const args = [\n baseRoute + '.new',\n {\n parent_id: workPackage.id\n }\n ];\n\n if (this.$state.includes('work-packages.show')) {\n args[0] = 'work-packages.new';\n }\n\n (this.$state).go(...args);\n });\n }\n\n public removeChild(childWorkPackage:WorkPackageResource) {\n return childWorkPackage.$load().then(() => {\n let parentWorkPackage = childWorkPackage.parent;\n return childWorkPackage.changeParent({\n _links: {\n parent: {\n href: null\n }\n },\n lockVersion: childWorkPackage.lockVersion\n }).then(wp => {\n if (parentWorkPackage) {\n this\n .apiV3Service\n .work_packages\n .id(parentWorkPackage)\n .refresh()\n .then((wp) => {\n this.halEvents.push(wp, {\n eventType: 'association',\n relatedWorkPackage: null,\n relationType: 'child'\n });\n });\n }\n\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(wp);\n })\n .catch((error) => {\n this.notificationService.handleRawError(error, childWorkPackage);\n return Promise.reject(error);\n });\n });\n }\n}\n","import {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SingleRowBuilder} from \"core-components/wp-fast-table/builders/rows/single-row-builder\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {groupedRowClassName} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-rows-helpers\";\n\nexport class GroupSumsBuilder extends SingleRowBuilder {\n\n @InjectField() readonly querySpace:IsolatedQuerySpace;\n @InjectField() readonly schemaCache:SchemaCacheService;\n @InjectField() readonly displayFieldService:DisplayFieldService;\n\n private text = {\n sum: this.I18n.t('js.label_sum')\n };\n\n public buildSumsRow(group:GroupObject) {\n const tr:HTMLTableRowElement = document.createElement('tr');\n tr.classList.add('wp-table--sums-row', 'wp-table--row', groupedRowClassName(group.index));\n\n this.renderColumns(group.sums, tr);\n\n return tr;\n }\n\n public renderColumns(sums:{[key:string]:any}, tr:HTMLTableRowElement) {\n this.augmentedColumns.forEach((column, i:number) => {\n const td = document.createElement('td');\n const div = this.renderContent(sums, column.id, this.sumsSchema[column.id]);\n\n if (i === 0) {\n this.appendFirstLabel(div);\n }\n\n td.appendChild(div);\n tr.append(td);\n });\n }\n\n private appendFirstLabel(div:HTMLElement) {\n const span = document.createElement('span');\n span.textContent = `${this.text.sum}`;\n div.prepend(span);\n }\n\n private get sumsSchema():SchemaResource {\n // The schema is ensured to be loaded by wpViewAdditionalElementsService\n const results = this.querySpace.results.value!;\n const href = results.sumsSchema!.$href!;\n\n return this.schemaCache.state(href).value!;\n }\n\n private renderContent(sums:any, name:string, fieldSchema:IFieldSchema) {\n const div = document.createElement('div');\n div.classList.add('wp-table--sum-container', name);\n\n // The field schema for this element may be undefined\n // because it is not summable.\n if (!fieldSchema) {\n return div;\n }\n\n const field = this.displayFieldService.getField(\n sums,\n name,\n fieldSchema,\n { injector: this.injector, container: 'table', options: {} }\n );\n\n if (!field.isEmpty()) {\n field.render(div, field.valueString);\n }\n\n return div;\n }\n}\n","
    \n
    \n \n \n \n {{ descriptor.label }}\n *\n \n \n
    \n
    \n\n \n \n
    \n \n
    \n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Component, Injector, Input, AfterViewInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {FieldDescriptor, GroupDescriptor} from 'core-components/work-packages/wp-single-view/wp-single-view.component';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {fromEvent} from \"rxjs\";\nimport {debounceTime} from \"rxjs/operators\";\n\n@Component({\n selector: 'wp-attribute-group',\n templateUrl: './wp-attribute-group.template.html'\n})\nexport class WorkPackageFormAttributeGroupComponent extends UntilDestroyedMixin implements AfterViewInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public group:GroupDescriptor;\n\n constructor(readonly I18n:I18nService,\n public wpEditForm:EditFormComponent,\n protected injector:Injector) {\n super();\n }\n\n ngAfterViewInit() {\n setTimeout(() => this.fixColumns());\n\n // Listen to resize event and fix column start again\n fromEvent(window, 'resize', { passive: true })\n .pipe(\n this.untilDestroyed(),\n debounceTime(250)\n )\n .subscribe(() => {\n this.fixColumns();\n });\n }\n\n public trackByName(_index:number, elem:{ name:string }) {\n return elem.name;\n }\n\n /**\n * Hide read-only fields, but only when in the create mode\n * @param {FieldDescriptor} field\n */\n public shouldHideField(descriptor:FieldDescriptor) {\n const field = descriptor.field || descriptor.fields![0];\n return this.wpEditForm.editMode && !field.writable;\n }\n\n public fieldName(name:string) {\n if (name === 'startDate') {\n return 'combinedDate';\n } else {\n return name;\n }\n }\n\n /**\n * Fix the top of the columns after view has been loaded\n * to prevent columns from repositioning (e.g. when editing multi-select fields)\n */\n private fixColumns() {\n let lastOffset = 0;\n // Find corresponding HTML of attribute fields for each group\n let htmlAttributes = jQuery('div.attributes-group:contains(' + this.group.name + ')').find('.attributes-key-value');\n\n htmlAttributes.each(function() {\n let offset = jQuery(this).position().top;\n\n if (offset < lastOffset) {\n // Fix position of the column start\n jQuery(this).addClass('-column-start');\n }\n lastOffset = offset;\n });\n }\n}","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injector} from '@angular/core';\nimport * as moment from 'moment';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {RenderInfo} from '../wp-timeline';\nimport {TimelineCellRenderer} from './timeline-cell-renderer';\nimport {WorkPackageCellLabels} from './wp-timeline-cell';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {keyCodes} from 'core-app/modules/common/keyCodes.enum';\nimport {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport Moment = moment.Moment;\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {take} from \"rxjs/operators\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const classNameBar = 'bar';\nexport const classNameLeftHandle = 'leftHandle';\nexport const classNameRightHandle = 'rightHandle';\nexport const classNameBarLabel = 'bar-label';\n\n\nexport function registerWorkPackageMouseHandler(this:void,\n injector:Injector,\n getRenderInfo:() => RenderInfo,\n workPackageTimeline:WorkPackageTimelineTableController,\n halEditing:HalResourceEditingService,\n halEvents:HalEventsService,\n notificationService:WorkPackageNotificationService,\n loadingIndicator:LoadingIndicatorService,\n cell:HTMLElement,\n bar:HTMLDivElement,\n labels:WorkPackageCellLabels,\n renderer:TimelineCellRenderer,\n renderInfo:RenderInfo) {\n\n const querySpace:IsolatedQuerySpace = injector.get(IsolatedQuerySpace);\n\n let mouseDownStartDay:number|null = null; // also flag to signal active drag'n'drop\n renderInfo.change = halEditing.changeFor(renderInfo.workPackage) as WorkPackageChangeset;\n\n let dateStates:any;\n let placeholderForEmptyCell:HTMLElement;\n const jBody = jQuery('body');\n\n // handles change to existing work packages\n bar.onmousedown = (ev:MouseEvent) => {\n if (ev.which === 1) {\n // Left click only\n workPackageMouseDownFn(bar, ev);\n }\n };\n\n // handles initial creation of start/due values\n cell.onmousemove = handleMouseMoveOnEmptyCell;\n\n function applyDateValues(renderInfo:RenderInfo, dates:{ [name:string]:Moment }) {\n // Let the renderer decide which fields we change\n renderer.assignDateValues(renderInfo.change, labels, dates);\n }\n\n function getCursorOffsetInDaysFromLeft(renderInfo:RenderInfo, ev:MouseEvent) {\n const leftOffset = workPackageTimeline.getAbsoluteLeftCoordinates();\n const cursorOffsetLeftInPx = ev.clientX - leftOffset;\n const cursorOffsetLeftInDays = Math.floor(cursorOffsetLeftInPx / renderInfo.viewParams.pixelPerDay);\n return cursorOffsetLeftInDays;\n }\n\n function workPackageMouseDownFn(bar:HTMLDivElement, ev:MouseEvent) {\n ev.preventDefault();\n\n // add/remove css class while drag'n'drop is active\n const classNameActiveDrag = 'active-drag';\n bar.classList.add(classNameActiveDrag);\n jBody.on('mouseup.timelinecell', () => bar.classList.remove(classNameActiveDrag));\n\n workPackageTimeline.disableViewParamsCalculation = true;\n mouseDownStartDay = getCursorOffsetInDaysFromLeft(renderInfo, ev);\n\n // If this wp is a parent element, changing it is not allowed\n // if it is not on 'Manual scheduling' mode\n // But adding a relation to it is.\n if (!renderInfo.workPackage.isLeaf && !renderInfo.viewParams.activeSelectionMode && !renderInfo.workPackage.scheduleManually) {\n return;\n }\n\n // Determine what attributes of the work package should be changed\n const direction = renderer.onMouseDown(ev, null, renderInfo, labels, bar);\n\n jBody.on('mousemove.timelinecell', createMouseMoveFn(direction));\n jBody.on('keyup.timelinecell', keyPressFn);\n jBody.on('mouseup.timelinecell', () => deactivate(false));\n }\n\n function createMouseMoveFn(direction:'left'|'right'|'both'|'create'|'dragright') {\n return (ev:JQuery.MouseMoveEvent) => {\n const days = getCursorOffsetInDaysFromLeft(renderInfo, ev.originalEvent!) - mouseDownStartDay!;\n const offsetDayCurrent = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n const dayUnderCursor = renderInfo.viewParams.dateDisplayStart.clone().add(offsetDayCurrent, 'days');\n\n dateStates = renderer.onDaysMoved(renderInfo.change, dayUnderCursor, days, direction);\n applyDateValues(renderInfo, dateStates);\n renderer.update(bar, labels, renderInfo);\n };\n }\n\n function keyPressFn(ev:JQuery.TriggeredEvent) {\n const kev:KeyboardEvent = ev as any;\n if (kev.keyCode === keyCodes.ESCAPE) {\n deactivate(true);\n }\n }\n\n function handleMouseMoveOnEmptyCell(ev:MouseEvent) {\n const wp = renderInfo.workPackage;\n\n if (!renderer.isEmpty(wp)) {\n return;\n }\n\n const isEditable = (wp.isLeaf || wp.scheduleManually) && renderer.canMoveDates(wp);\n\n if (!isEditable) {\n cell.style.cursor = 'not-allowed';\n return;\n }\n\n // placeholder logic\n cell.style.cursor = '';\n placeholderForEmptyCell && placeholderForEmptyCell.remove();\n placeholderForEmptyCell = renderer.displayPlaceholderUnderCursor(ev, renderInfo);\n cell.appendChild(placeholderForEmptyCell);\n\n // abort if mouse leaves cell\n cell.onmouseleave = () => {\n placeholderForEmptyCell.remove();\n };\n\n // create logic\n cell.onmousedown = (ev) => {\n placeholderForEmptyCell.remove();\n bar.style.pointerEvents = 'none';\n ev.preventDefault();\n\n const offsetDayStart = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n const clickStart = renderInfo.viewParams.dateDisplayStart.clone().add(offsetDayStart, 'days');\n const dateForCreate = clickStart.format('YYYY-MM-DD');\n const mouseDownType = renderer.onMouseDown(ev, dateForCreate, renderInfo, labels, bar);\n renderer.update(bar, labels, renderInfo);\n\n if (mouseDownType === 'create') {\n deactivate(false);\n ev.preventDefault();\n return;\n }\n\n cell.onmousemove = (ev) => {\n const offsetDayCurrent = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n const dayUnderCursor = renderInfo.viewParams.dateDisplayStart.clone().add(offsetDayCurrent, 'days');\n const widthInDays = offsetDayCurrent - offsetDayStart;\n const moved = renderer.onDaysMoved(renderInfo.change, dayUnderCursor, widthInDays, mouseDownType);\n renderer.assignDateValues(renderInfo.change, labels, moved);\n renderer.update(bar, labels, renderInfo);\n };\n\n cell.onmouseleave = () => {\n deactivate(true);\n };\n\n cell.onmouseup = () => {\n deactivate(false);\n };\n\n jBody.on('keyup.timelinecell', keyPressFn);\n };\n }\n\n function deactivate(cancelled:boolean) {\n workPackageTimeline.disableViewParamsCalculation = false;\n\n cell.onmousemove = handleMouseMoveOnEmptyCell;\n cell.onmousedown = _.noop;\n cell.onmouseleave = _.noop;\n cell.onmouseup = _.noop;\n\n bar.style.pointerEvents = 'auto';\n\n jBody.off('.timelinecell');\n workPackageTimeline.resetCursor();\n mouseDownStartDay = null;\n dateStates = {};\n\n // const renderInfo = getRenderInfo();\n if (cancelled || renderInfo.change.isEmpty()) {\n cancelChange();\n } else {\n const stopAndRefresh = () => {\n renderInfo.change.clear();\n renderer.onMouseDownEnd(labels, renderInfo.change);\n };\n\n // Persist the changes\n saveWorkPackage(renderInfo.change)\n .then(stopAndRefresh)\n .catch(error => {\n notificationService.handleRawError(error, renderInfo.workPackage);\n cancelChange();\n });\n }\n }\n\n function cancelChange() {\n renderInfo.change.clear();\n renderer.update(bar, labels, renderInfo);\n renderer.onMouseDownEnd(labels, renderInfo.change);\n workPackageTimeline.refreshView();\n }\n\n function saveWorkPackage(change:WorkPackageChangeset) {\n const apiv3Service:APIV3Service = injector.get(APIV3Service);\n const querySpace:IsolatedQuerySpace = injector.get(IsolatedQuerySpace);\n\n // Remember the time before saving the work package to know which work packages to update\n const updatedAt = moment().toISOString();\n\n return loadingIndicator.table.promise = halEditing\n .save(change)\n .then((result) => {\n notificationService.showSave(result.resource);\n const ids = _.map(querySpace.tableRendered.value!, row => row.workPackageId);\n return apiv3Service\n .work_packages\n .filterUpdatedSince(ids, updatedAt)\n .get()\n .toPromise()\n .then(() => {\n halEvents.push(result.resource, { eventType: 'updated' });\n return querySpace.timelineRendered.pipe(take(1)).toPromise();\n });\n });\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from '../../../states.service';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {RenderInfo} from '../wp-timeline';\nimport {TimelineCellRenderer} from './timeline-cell-renderer';\nimport {TimelineMilestoneCellRenderer} from './timeline-milestone-cell-renderer';\nimport {registerWorkPackageMouseHandler} from './wp-timeline-cell-mouse-handler';\nimport {Injector} from '@angular/core';\nimport {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\nexport const classNameLeftLabel = 'labelLeft';\nexport const classNameRightContainer = 'containerRight';\nexport const classNameRightLabel = 'labelRight';\nexport const classNameLeftHoverLabel = 'labelHoverLeft';\nexport const classNameRightHoverLabel = 'labelHoverRight';\nexport const classNameHoverStyle = '-label-style';\nexport const classNameFarRightLabel = 'labelFarRight';\nexport const classNameShowOnHover = 'show-on-hover';\nexport const classNameHideOnHover = 'hide-on-hover';\n\nexport class WorkPackageCellLabels {\n\n constructor(public readonly center:HTMLDivElement|null,\n public readonly left:HTMLDivElement,\n public readonly leftHover:HTMLDivElement|null,\n public readonly right:HTMLDivElement,\n public readonly rightHover:HTMLDivElement|null,\n public readonly farRight:HTMLDivElement,\n public readonly withAlternativeLabels?:boolean) {\n }\n\n}\n\nexport class WorkPackageTimelineCell {\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() halEvents:HalEventsService;\n @InjectField() notificationService:WorkPackageNotificationService;\n @InjectField() states:States;\n @InjectField() loadingIndicator:LoadingIndicatorService;\n @InjectField() schemaCache:SchemaCacheService;\n\n private wpElement:HTMLDivElement|null = null;\n\n private elementShape:string;\n\n private labels:WorkPackageCellLabels;\n\n constructor(public readonly injector:Injector,\n public workPackageTimeline:WorkPackageTimelineTableController,\n public renderers:{ milestone:TimelineMilestoneCellRenderer, generic:TimelineCellRenderer },\n public latestRenderInfo:RenderInfo,\n public classIdentifier:string,\n public workPackageId:string) {\n }\n\n getMarginLeftOfLeftSide():number {\n const renderer = this.cellRenderer(this.latestRenderInfo.workPackage);\n return renderer.getMarginLeftOfLeftSide(this.latestRenderInfo);\n }\n\n getMarginLeftOfRightSide():number {\n const renderer = this.cellRenderer(this.latestRenderInfo.workPackage);\n return renderer.getMarginLeftOfRightSide(this.latestRenderInfo);\n }\n\n getPaddingLeftForIncomingRelationLines():number {\n const renderer = this.cellRenderer(this.latestRenderInfo.workPackage);\n return renderer.getPaddingLeftForIncomingRelationLines(this.latestRenderInfo);\n }\n\n getPaddingRightForOutgoingRelationLines():number {\n const renderer = this.cellRenderer(this.latestRenderInfo.workPackage);\n return renderer.getPaddingRightForOutgoingRelationLines(this.latestRenderInfo);\n }\n\n canConnectRelations():boolean {\n const wp = this.latestRenderInfo.workPackage;\n if (this.schemaCache.of(wp).isMilestone) {\n return !_.isNil(wp.date);\n }\n\n return !_.isNil(wp.startDate) || !_.isNil(wp.dueDate);\n }\n\n public clear() {\n this.cellElement.html('');\n this.wpElement = null;\n }\n\n private get cellContainer() {\n return this.workPackageTimeline.timelineBody;\n }\n\n private get cellElement():JQuery {\n return this.cellContainer.find(`.${this.classIdentifier}`);\n }\n\n private lazyInit(renderer:TimelineCellRenderer, renderInfo:RenderInfo):Promise {\n const body = this.workPackageTimeline.timelineBody[0];\n const cell = this.cellElement;\n\n if (!cell.length) {\n return Promise.reject('uninitialized');\n }\n\n const wasRendered = this.wpElement !== null && body.contains(this.wpElement);\n\n // If already rendered with correct shape, ignore\n if (wasRendered && this.elementShape === renderer.type) {\n return Promise.resolve();\n }\n\n // Remove the element first if we're redrawing\n if (!renderInfo.isDuplicatedCell) {\n this.clear();\n }\n\n // Render the given element\n this.wpElement = renderer.render(renderInfo);\n this.labels = renderer.createAndAddLabels(renderInfo, this.wpElement);\n this.elementShape = renderer.type;\n\n // Register the element\n cell.append(this.wpElement);\n\n // Allow editing if editable\n if (renderer.canMoveDates(renderInfo.workPackage)) {\n this.wpElement.classList.add('-editable');\n\n registerWorkPackageMouseHandler(\n this.injector,\n () => this.latestRenderInfo,\n this.workPackageTimeline,\n this.halEditing,\n this.halEvents,\n this.notificationService,\n this.loadingIndicator,\n cell[0],\n this.wpElement,\n this.labels,\n renderer,\n renderInfo);\n }\n\n return Promise.resolve();\n }\n\n private cellRenderer(workPackage:WorkPackageResource):TimelineCellRenderer {\n if (this.schemaCache.of(workPackage).isMilestone) {\n return this.renderers.milestone;\n }\n\n return this.renderers.generic;\n }\n\n public refreshView(renderInfo:RenderInfo) {\n this.latestRenderInfo = renderInfo;\n\n const renderer = this.cellRenderer(renderInfo.workPackage);\n\n // Render initial element if necessary\n this.lazyInit(renderer, renderInfo)\n .then(() => {\n // Render the upgrade from renderInfo\n const shouldBeDisplayed = renderer.update(\n this.wpElement as HTMLDivElement,\n this.labels,\n renderInfo);\n\n if (!shouldBeDisplayed) {\n this.clear();\n }\n })\n .catch(() => null);\n }\n\n}\n","import * as moment from 'moment';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {\n calculatePositionValueForDayCount,\n calculatePositionValueForDayCountingPx,\n RenderInfo,\n timelineBackgroundElementClass,\n timelineElementCssClass,\n timelineMarkerSelectionStartClass\n} from '../wp-timeline';\nimport {\n classNameFarRightLabel,\n classNameHideOnHover,\n classNameHoverStyle,\n classNameLeftHoverLabel,\n classNameLeftLabel,\n classNameRightContainer,\n classNameRightHoverLabel,\n classNameRightLabel,\n classNameShowOnHover,\n WorkPackageCellLabels\n} from './wp-timeline-cell';\nimport {classNameBarLabel, classNameLeftHandle, classNameRightHandle} from './wp-timeline-cell-mouse-handler';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {DisplayFieldRenderer} from 'core-app/modules/fields/display/display-field-renderer';\nimport {Injector} from '@angular/core';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {HierarchyRenderPass} from \"core-components/wp-fast-table/builders/modes/hierarchy/hierarchy-render-pass\";\nimport Moment = moment.Moment;\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\nexport interface CellDateMovement {\n // Target values to move work package to\n startDate?:moment.Moment;\n dueDate?:moment.Moment;\n // Target value to move milestone to\n date?:moment.Moment;\n}\n\nexport type LabelPosition = 'left'|'right'|'farRight';\n\nexport class TimelineCellRenderer {\n @InjectField() wpTableTimeline:WorkPackageViewTimelineService;\n @InjectField() TimezoneService:TimezoneService;\n @InjectField() schemaCache:SchemaCacheService;\n @InjectField() readonly I18n:I18nService;\n\n public text = {\n label_children_derived_duration: this.I18n.t('js.label_children_derived_duration')\n };\n\n public ganttChartRowHeight:number;\n\n public fieldRenderer:DisplayFieldRenderer = new DisplayFieldRenderer(this.injector, 'timeline');\n\n protected dateDisplaysOnMouseMove:{ left?:HTMLElement; right?:HTMLElement } = {};\n\n constructor(readonly injector:Injector,\n readonly workPackageTimeline:WorkPackageTimelineTableController) {\n this.ganttChartRowHeight = +getComputedStyle(document.documentElement)\n .getPropertyValue('--table-timeline--row-height')\n .replace('px', '');\n }\n\n public get type():string {\n return 'bar';\n }\n\n public canMoveDates(wp:WorkPackageResource) {\n const schema = this.schemaCache.of(wp);\n return schema.startDate.writable && schema.dueDate.writable && schema.isAttributeEditable('startDate');\n }\n\n public isEmpty(wp:WorkPackageResource) {\n const start = moment(wp.startDate as any);\n const due = moment(wp.dueDate as any);\n const noStartAndDueValues = _.isNaN(start.valueOf()) && _.isNaN(due.valueOf());\n return noStartAndDueValues;\n }\n\n public displayPlaceholderUnderCursor(ev:MouseEvent, renderInfo:RenderInfo):HTMLElement {\n const days = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n\n const placeholder = document.createElement('div');\n placeholder.style.pointerEvents = 'none';\n placeholder.style.position = 'absolute';\n placeholder.style.height = '1em';\n placeholder.style.width = '30px';\n placeholder.style.zIndex = '9999';\n placeholder.style.left = (days * renderInfo.viewParams.pixelPerDay) + 'px';\n\n this.applyTypeColor(renderInfo, placeholder);\n\n return placeholder;\n }\n\n /**\n * Assign changed dates to the work package.\n * For generic work packages, assigns start and finish date.\n *\n */\n public assignDateValues(change:WorkPackageChangeset,\n labels:WorkPackageCellLabels,\n dates:any):void {\n\n this.assignDate(change, 'startDate', dates.startDate);\n this.assignDate(change, 'dueDate', dates.dueDate);\n\n this.updateLabels(true, labels, change);\n }\n\n /**\n * Handle movement by days of the work package to either (or both) edge(s)\n * depending on which initial date was set.\n */\n public onDaysMoved(change:WorkPackageChangeset,\n dayUnderCursor:Moment,\n delta:number,\n direction:'left'|'right'|'both'|'create'|'dragright'):CellDateMovement {\n\n const initialStartDate = change.pristineResource.startDate;\n const initialDueDate = change.pristineResource.dueDate;\n\n const now = moment().format('YYYY-MM-DD');\n\n const startDate = moment(change.projectedResource.startDate);\n const dueDate = moment(change.projectedResource.dueDate);\n\n let dates:CellDateMovement = {};\n\n if (direction === 'left') {\n dates.startDate = moment(initialStartDate || initialDueDate).add(delta, 'days');\n } else if (direction === 'right') {\n dates.dueDate = moment(initialDueDate || now).add(delta, 'days');\n } else if (direction === 'both') {\n if (initialStartDate) {\n dates.startDate = moment(initialStartDate).add(delta, 'days');\n }\n if (initialDueDate) {\n dates.dueDate = moment(initialDueDate).add(delta, 'days');\n }\n } else if (direction === 'dragright') {\n dates.dueDate = startDate.clone().add(delta, 'days');\n }\n\n // avoid negative \"overdrag\" if only start or due are changed\n if (direction !== 'both') {\n if (dates.startDate !== undefined && dates.startDate.isAfter(dueDate)) {\n dates.startDate = dueDate;\n } else if (dates.dueDate !== undefined && dates.dueDate.isBefore(startDate)) {\n dates.dueDate = startDate;\n }\n }\n\n return dates;\n }\n\n public onMouseDown(ev:MouseEvent,\n dateForCreate:string|null,\n renderInfo:RenderInfo,\n labels:WorkPackageCellLabels,\n elem:HTMLElement):'left'|'right'|'both'|'dragright'|'create' {\n\n // check for active selection mode\n if (renderInfo.viewParams.activeSelectionMode) {\n renderInfo.viewParams.activeSelectionMode(renderInfo.workPackage);\n ev.preventDefault();\n return 'both'; // irrelevant\n }\n\n const projection = renderInfo.change.projectedResource;\n let direction:'left'|'right'|'both'|'dragright';\n\n // Update the cursor and maybe set start/due values\n if (jQuery(ev.target!).hasClass(classNameLeftHandle)) {\n // only left\n direction = 'left';\n this.workPackageTimeline.forceCursor('col-resize');\n if (projection.startDate === null) {\n projection.startDate = projection['dueDate'];\n }\n } else if (jQuery(ev.target!).hasClass(classNameRightHandle) || dateForCreate) {\n // only right\n direction = 'right';\n this.workPackageTimeline.forceCursor('col-resize');\n } else {\n // both\n direction = 'both';\n this.workPackageTimeline.forceCursor('ew-resize');\n }\n\n if (dateForCreate) {\n projection.startDate = dateForCreate;\n projection.dueDate = dateForCreate;\n direction = 'dragright';\n }\n\n this.updateLabels(true, labels, renderInfo.change);\n\n return direction;\n }\n\n public onMouseDownEnd(labels:WorkPackageCellLabels, change:WorkPackageChangeset) {\n this.updateLabels(false, labels, change);\n }\n\n /**\n * @return true, if the element should still be displayed.\n * false, if the element must be removed from the timeline.\n */\n public update(element:HTMLDivElement, labels:WorkPackageCellLabels|null, renderInfo:RenderInfo):boolean {\n const change = renderInfo.change;\n const bar = element.querySelector(`.${timelineBackgroundElementClass}`) as HTMLElement;\n let start = moment(change.projectedResource.startDate);\n let due = moment(change.projectedResource.dueDate);\n\n if (_.isNaN(start.valueOf()) && _.isNaN(due.valueOf())) {\n element.style.visibility = 'hidden';\n } else {\n element.style.visibility = 'visible';\n }\n\n // only start date, fade out bar to the right\n if (_.isNaN(due.valueOf()) && !_.isNaN(start.valueOf())) {\n // Set due date to today\n due = moment();\n bar.style.backgroundImage = `linear-gradient(90deg, rgba(255,255,255,0) 0%, #F1F1F1 100%)`;\n }\n\n // only finish date, fade out bar to the left\n if (_.isNaN(start.valueOf()) && !_.isNaN(due.valueOf())) {\n start = due.clone();\n bar.style.backgroundImage = `linear-gradient(90deg, #F1F1F1 0%, rgba(255,255,255,0) 80%)`;\n }\n\n this.setElementPositionAndSize(element, renderInfo, start, due);\n\n // Update labels if any\n if (labels) {\n this.updateLabels(false, labels, change);\n }\n\n this.checkForActiveSelectionMode(renderInfo, bar);\n this.checkForSpecialDisplaySituations(renderInfo, bar);\n this.applyTypeColor(renderInfo, bar);\n\n return true;\n }\n\n protected checkForActiveSelectionMode(renderInfo:RenderInfo, element:HTMLElement) {\n if (renderInfo.viewParams.activeSelectionMode) {\n element.style.backgroundImage = ''; // required! unable to disable \"fade out bar\" with css\n\n if (renderInfo.viewParams.selectionModeStart === '' + renderInfo.workPackage.id!) {\n jQuery(element).addClass(timelineMarkerSelectionStartClass);\n element.style.background = 'none';\n }\n }\n }\n\n getMarginLeftOfLeftSide(renderInfo:RenderInfo):number {\n const projection = renderInfo.change.projectedResource;\n\n let start = moment(projection.startDate);\n let due = moment(projection.dueDate);\n start = _.isNaN(start.valueOf()) ? due.clone() : start;\n\n const offsetStart = start.diff(renderInfo.viewParams.dateDisplayStart, 'days');\n\n return calculatePositionValueForDayCountingPx(renderInfo.viewParams, offsetStart);\n }\n\n getMarginLeftOfRightSide(renderInfo:RenderInfo):number {\n const projection = renderInfo.change.projectedResource;\n\n let start = moment(projection.startDate);\n let due = moment(projection.dueDate);\n\n start = _.isNaN(start.valueOf()) ? due.clone() : start;\n due = _.isNaN(due.valueOf()) ? start.clone() : due;\n\n const offsetStart = start.diff(renderInfo.viewParams.dateDisplayStart, 'days');\n const duration = due.diff(start, 'days') + 1;\n\n return calculatePositionValueForDayCountingPx(renderInfo.viewParams, offsetStart + duration);\n }\n\n getPaddingLeftForIncomingRelationLines(renderInfo:RenderInfo):number {\n return renderInfo.viewParams.pixelPerDay / 8;\n }\n\n getPaddingRightForOutgoingRelationLines(renderInfo:RenderInfo):number {\n return 0;\n }\n\n /**\n * Render the generic cell element, a bar spanning from\n * start to finish date.\n */\n public render(renderInfo:RenderInfo):HTMLDivElement {\n const container = document.createElement('div');\n const bar = document.createElement('div');\n const left = document.createElement('div');\n const right = document.createElement('div');\n\n container.className = timelineElementCssClass + ' ' + this.type;\n bar.className = timelineBackgroundElementClass;\n left.className = classNameLeftHandle;\n right.className = classNameRightHandle;\n container.appendChild(bar);\n container.appendChild(left);\n container.appendChild(right);\n\n return container;\n }\n\n createAndAddLabels(renderInfo:RenderInfo, element:HTMLElement):WorkPackageCellLabels {\n // create center label\n const labelCenter = document.createElement('div');\n labelCenter.classList.add(classNameBarLabel);\n this.applyTypeColor(renderInfo, labelCenter);\n element.appendChild(labelCenter);\n\n // create left label\n const labelLeft = document.createElement('div');\n labelLeft.classList.add(classNameLeftLabel, classNameHideOnHover);\n element.appendChild(labelLeft);\n\n // create right container\n const containerRight = document.createElement('div');\n containerRight.classList.add(classNameRightContainer);\n element.appendChild(containerRight);\n\n // create right label\n const labelRight = document.createElement('div');\n labelRight.classList.add(classNameRightLabel, classNameHideOnHover);\n containerRight.appendChild(labelRight);\n\n // create far right label\n const labelFarRight = document.createElement('div');\n labelFarRight.classList.add(classNameFarRightLabel, classNameHideOnHover);\n containerRight.appendChild(labelFarRight);\n\n // create left hover label\n const labelHoverLeft = document.createElement('div');\n labelHoverLeft.classList.add(classNameLeftHoverLabel, classNameShowOnHover, classNameHoverStyle);\n element.appendChild(labelHoverLeft);\n\n // create right hover label\n const labelHoverRight = document.createElement('div');\n labelHoverRight.classList.add(classNameRightHoverLabel, classNameShowOnHover, classNameHoverStyle);\n element.appendChild(labelHoverRight);\n\n const labels = new WorkPackageCellLabels(labelCenter, labelLeft, labelHoverLeft, labelRight, labelHoverRight, labelFarRight);\n this.updateLabels(false, labels, renderInfo.change);\n\n return labels;\n }\n\n protected applyTypeColor(renderInfo:RenderInfo, bg:HTMLElement):void {\n let wp = renderInfo.workPackage;\n let type = wp.type;\n let selectionMode = renderInfo.viewParams.activeSelectionMode;\n\n // Don't apply the class in selection mode\n const id = type.id;\n if (selectionMode) {\n bg.classList.remove(Highlighting.backgroundClass('type', id!));\n } else {\n bg.classList.add(Highlighting.backgroundClass('type', id!));\n }\n }\n\n protected assignDate(change:WorkPackageChangeset, attributeName:string, value:moment.Moment) {\n if (value) {\n change.projectedResource[attributeName] = value.format('YYYY-MM-DD');\n }\n }\n\n setElementPositionAndSize(element:HTMLElement, renderInfo:RenderInfo, start:moment.Moment, due:moment.Moment) {\n const viewParams = renderInfo.viewParams;\n // offset left\n const offsetStart = start.diff(viewParams.dateDisplayStart, 'days');\n element.style.left = calculatePositionValueForDayCount(viewParams, offsetStart);\n\n // duration\n const duration = due.diff(start, 'days') + 1;\n element.style.width = calculatePositionValueForDayCount(viewParams, duration);\n\n // ensure minimum width\n if (!_.isNaN(start.valueOf()) || !_.isNaN(due.valueOf())) {\n const minWidth = _.max([renderInfo.viewParams.pixelPerDay, 2]);\n element.style.minWidth = minWidth + 'px';\n }\n }\n\n /**\n * Changes the presentation of the work package.\n *\n * Known cases:\n * 1. Display a clamp if this work package is a parent element\n * and display a box wrapping all the visible children when the\n * parent is hovered\n */\n checkForSpecialDisplaySituations(renderInfo:RenderInfo, bar:HTMLElement) {\n const wp = renderInfo.workPackage;\n const row = bar.parentElement!.parentElement!;\n let selectionMode = renderInfo.viewParams.activeSelectionMode;\n\n // Cannot edit the work package if it has children\n // and it is not on 'Manual scheduling' mode\n if (!wp.isLeaf && !selectionMode && !wp.scheduleManually) {\n bar.classList.add('-readonly');\n } else {\n bar.classList.remove('-readonly');\n }\n\n // Display the children's duration clamp\n if (wp.derivedStartDate && wp.derivedDueDate) {\n const derivedStartDate = moment(wp.derivedStartDate);\n const derivedDueDate = moment(wp.derivedDueDate);\n const startDate = moment(renderInfo.change.projectedResource.startDate);\n const dueDate = moment(renderInfo.change.projectedResource.dueDate);\n const previousChildrenDurationBar = row.querySelector('.children-duration-bar');\n const childrenDurationBar = document.createElement('div');\n const childrenDurationHoverContainer = document.createElement('div');\n const visibleChildren = document.querySelectorAll(`.wp-timeline-cell.__hierarchy-group-${wp.id}:not([class*='__collapsed-group'])`).length || 0;\n\n childrenDurationBar.classList.add('children-duration-bar', '-clamp-style');\n childrenDurationBar.title = this.text.label_children_derived_duration;\n childrenDurationHoverContainer.classList.add('children-duration-hover-container');\n childrenDurationHoverContainer.style.height = this.ganttChartRowHeight * visibleChildren + 10 + 'px';\n\n if (derivedStartDate.isBefore(startDate) || derivedDueDate.isAfter(dueDate)) {\n childrenDurationBar.classList.add('-duration-overflow');\n }\n\n this.setElementPositionAndSize(childrenDurationBar, renderInfo, derivedStartDate, derivedDueDate);\n\n if (previousChildrenDurationBar) {\n previousChildrenDurationBar.remove();\n }\n\n childrenDurationBar.appendChild(childrenDurationHoverContainer);\n row!.appendChild(childrenDurationBar);\n }\n }\n\n protected updateLabels(activeDragNDrop:boolean,\n labels:WorkPackageCellLabels,\n change:WorkPackageChangeset) {\n\n const labelConfiguration = this.wpTableTimeline.getNormalizedLabels(change.projectedResource);\n\n if (!activeDragNDrop) {\n // normal display\n this.renderLabel(change, labels, 'left', labelConfiguration.left);\n this.renderLabel(change, labels, 'right', labelConfiguration.right);\n this.renderLabel(change, labels, 'farRight', labelConfiguration.farRight);\n }\n\n // Update hover labels\n this.renderHoverLabels(labels, change);\n }\n\n protected renderHoverLabels(labels:WorkPackageCellLabels, change:WorkPackageChangeset) {\n this.renderLabel(change, labels, 'leftHover', 'startDate');\n this.renderLabel(change, labels, 'rightHover', 'dueDate');\n }\n\n protected renderLabel(change:WorkPackageChangeset,\n labels:WorkPackageCellLabels,\n position:LabelPosition|'leftHover'|'rightHover',\n attribute:string|null) {\n\n // Get the label position\n // Skip label if it does not exist (milestones)\n let label = labels[position];\n if (!label) {\n return;\n }\n\n // Reset label value\n label.innerHTML = '';\n\n if (attribute === null) {\n label.classList.remove('not-empty');\n return;\n }\n\n // Get the rendered field\n let [field, span] = this.fieldRenderer.renderFieldValue(change.projectedResource, attribute, change);\n\n if (label && field && span) {\n span.classList.add('label-content');\n label.appendChild(span);\n label.classList.add('not-empty');\n } else if (label) {\n label.classList.remove('not-empty');\n }\n }\n\n protected isParentWithVisibleChildren(wp:WorkPackageResource):boolean {\n if (!this.workPackageTimeline.inHierarchyMode) {\n return false;\n }\n\n const renderPass = this.workPackageTimeline.workPackageTable.lastRenderPass as HierarchyRenderPass|null;\n if (renderPass) {\n return !!renderPass.parentsWithVisibleChildren[wp.id!];\n }\n\n return false;\n }\n}\n","import * as moment from 'moment';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {\n calculatePositionValueForDayCountingPx,\n RenderInfo,\n timelineElementCssClass\n} from '../wp-timeline';\nimport {CellDateMovement, LabelPosition, TimelineCellRenderer} from './timeline-cell-renderer';\nimport {\n classNameFarRightLabel,\n classNameHideOnHover,\n classNameHoverStyle,\n classNameLeftHoverLabel,\n classNameLeftLabel,\n classNameRightContainer,\n classNameRightHoverLabel,\n classNameRightLabel,\n classNameShowOnHover,\n WorkPackageCellLabels\n} from './wp-timeline-cell';\nimport Moment = moment.Moment;\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\n\nexport class TimelineMilestoneCellRenderer extends TimelineCellRenderer {\n public get type():string {\n return 'milestone';\n }\n\n public isEmpty(wp:WorkPackageResource) {\n const date = moment(wp.date as any);\n return _.isNaN(date.valueOf());\n }\n\n public canMoveDates(wp:WorkPackageResource) {\n const schema = this.schemaCache.of(wp);\n return schema.date.writable && schema.isAttributeEditable('date');\n }\n\n public displayPlaceholderUnderCursor(ev:MouseEvent, renderInfo:RenderInfo):HTMLElement {\n const days = Math.floor(ev.offsetX / renderInfo.viewParams.pixelPerDay);\n\n const placeholder = document.createElement('div');\n placeholder.className = 'timeline-element milestone';\n placeholder.style.pointerEvents = 'none';\n placeholder.style.height = '1em';\n placeholder.style.width = '1em';\n placeholder.style.left = (days * renderInfo.viewParams.pixelPerDay) + 'px';\n\n const diamond = document.createElement('div');\n diamond.className = 'diamond';\n diamond.style.left = '0.5em';\n diamond.style.height = '1em';\n diamond.style.width = '1em';\n placeholder.appendChild(diamond);\n\n this.applyTypeColor(renderInfo, diamond);\n\n return placeholder;\n }\n\n /**\n * Assign changed dates to the work package.\n * For generic work packages, assigns start and finish date .\n *\n */\n public assignDateValues(change:WorkPackageChangeset,\n labels:WorkPackageCellLabels,\n dates:any):void {\n\n this.assignDate(change, 'date', dates.date);\n this.updateLabels(true, labels, change);\n }\n\n /**\n * Handle movement by days of milestone.\n */\n public onDaysMoved(change:WorkPackageChangeset,\n dayUnderCursor:Moment,\n delta:number,\n direction:'left' | 'right' | 'both' | 'create' | 'dragright') {\n\n const initialDate = change.pristineResource.date;\n let dates:CellDateMovement = {};\n\n if (initialDate) {\n dates.date = moment(initialDate).add(delta, 'days');\n }\n\n return dates;\n }\n\n public onMouseDown(ev:MouseEvent,\n dateForCreate:string | null,\n renderInfo:RenderInfo,\n labels:WorkPackageCellLabels,\n elem:HTMLElement):'left' | 'right' | 'both' | 'create' | 'dragright' {\n\n // check for active selection mode\n if (renderInfo.viewParams.activeSelectionMode) {\n renderInfo.viewParams.activeSelectionMode(renderInfo.workPackage);\n ev.preventDefault();\n return 'both'; // irrelevant\n }\n\n let direction:'both' | 'create' = 'both';\n this.workPackageTimeline.forceCursor('ew-resize');\n\n if (dateForCreate) {\n renderInfo.change.projectedResource.date = dateForCreate;\n direction = 'create';\n return direction;\n }\n\n this.updateLabels(true, labels, renderInfo.change);\n\n return direction;\n }\n\n public update(element:HTMLDivElement, labels:WorkPackageCellLabels|null, renderInfo:RenderInfo):boolean {\n const viewParams = renderInfo.viewParams;\n const date = moment(renderInfo.change.projectedResource.date);\n\n // abort if no date\n if (_.isNaN(date.valueOf())) {\n return false;\n }\n\n const diamond = jQuery('.diamond', element)[0];\n\n diamond.style.width = 15 + 'px';\n diamond.style.height = 15 + 'px';\n diamond.style.width = 15 + 'px';\n diamond.style.height = 15 + 'px';\n diamond.style.marginLeft = -(15 / 2) + (renderInfo.viewParams.pixelPerDay / 2) + 'px';\n this.applyTypeColor(renderInfo, diamond);\n\n // offset left\n const offsetStart = date.diff(viewParams.dateDisplayStart, 'days');\n element.style.left = calculatePositionValueForDayCountingPx(viewParams, offsetStart) + 'px';\n\n // Update labels if any\n if (labels) {\n this.updateLabels(false, labels, renderInfo.change);\n }\n\n this.checkForActiveSelectionMode(renderInfo, diamond);\n\n return true;\n }\n\n getMarginLeftOfLeftSide(renderInfo:RenderInfo):number {\n const change = renderInfo.change;\n let start = moment(change.projectedResource.date);\n const offsetStart = start.diff(renderInfo.viewParams.dateDisplayStart, 'days');\n return calculatePositionValueForDayCountingPx(renderInfo.viewParams, offsetStart);\n }\n\n getMarginLeftOfRightSide(ri:RenderInfo):number {\n return this.getMarginLeftOfLeftSide(ri) + ri.viewParams.pixelPerDay;\n }\n\n getPaddingLeftForIncomingRelationLines(renderInfo:RenderInfo):number {\n return (renderInfo.viewParams.pixelPerDay / 2) - 1;\n }\n\n getPaddingRightForOutgoingRelationLines(renderInfo:RenderInfo):number {\n return (15 / 2);\n }\n\n /**\n * Render a milestone element, a single day event with no resize, but\n * move functionality.\n */\n public render(renderInfo:RenderInfo):HTMLDivElement {\n const element = document.createElement('div');\n element.className = timelineElementCssClass + ' ' + this.type;\n\n const diamond = document.createElement('div');\n diamond.className = 'diamond';\n element.appendChild(diamond);\n\n return element;\n }\n\n createAndAddLabels(renderInfo:RenderInfo, element:HTMLElement):WorkPackageCellLabels {\n // create left label\n const labelLeft = document.createElement('div');\n labelLeft.classList.add(classNameLeftLabel, classNameHideOnHover);\n element.appendChild(labelLeft);\n\n // create right container\n const containerRight = document.createElement('div');\n containerRight.classList.add(classNameRightContainer);\n element.appendChild(containerRight);\n\n // create right label\n const labelRight = document.createElement('div');\n labelRight.classList.add(classNameRightLabel, classNameHideOnHover);\n containerRight.appendChild(labelRight);\n\n // create far right label\n const labelFarRight = document.createElement('div');\n labelFarRight.classList.add(classNameFarRightLabel, classNameHideOnHover);\n containerRight.appendChild(labelFarRight);\n\n // Create right hover label\n const labelHoverRight = document.createElement('div');\n labelHoverRight.classList.add(classNameRightHoverLabel, classNameShowOnHover, classNameHoverStyle);\n element.appendChild(labelHoverRight);\n\n // Create left hover label\n const labelHoverLeft = document.createElement('div');\n labelHoverLeft.classList.add(classNameLeftHoverLabel, classNameShowOnHover, classNameHoverStyle);\n element.appendChild(labelHoverLeft);\n\n const labels = new WorkPackageCellLabels(null, labelLeft, labelHoverLeft, labelRight, labelHoverRight, labelFarRight, renderInfo.withAlternativeLabels);\n this.updateLabels(false, labels, renderInfo.change);\n\n return labels;\n }\n\n protected renderHoverLabels(labels:WorkPackageCellLabels, change:WorkPackageChangeset) {\n if (labels.withAlternativeLabels) {\n this.renderLabel(change, labels, 'leftHover', 'date');\n this.renderLabel(change, labels, 'rightHover', 'subject');\n } else {\n this.renderLabel(change, labels, 'rightHover', 'date');\n }\n }\n\n protected updateLabels(activeDragNDrop:boolean,\n labels:WorkPackageCellLabels,\n change:WorkPackageChangeset) {\n\n const labelConfiguration = this.wpTableTimeline.getNormalizedLabels(change.projectedResource);\n\n if (!activeDragNDrop) {\n // normal display\n\n if (labels.withAlternativeLabels) {\n this.renderLabel(change, labels, 'right', 'subject');\n } else {\n // Show only one date field if left=start, right=dueDate\n if (labelConfiguration.left === 'startDate' && labelConfiguration.right === 'dueDate') {\n this.renderLabel(change, labels, 'left', null);\n this.renderLabel(change, labels, 'right', 'date');\n } else {\n this.renderLabel(change, labels, 'left', labelConfiguration.left);\n this.renderLabel(change, labels, 'right', labelConfiguration.right);\n }\n }\n\n this.renderLabel(change, labels, 'farRight', labelConfiguration.farRight);\n }\n\n // Update hover labels\n this.renderHoverLabels(labels, change);\n }\n\n protected renderLabel(change:WorkPackageChangeset,\n labels:WorkPackageCellLabels,\n position:LabelPosition|'leftHover'|'rightHover',\n attribute:string|null) {\n // Normalize attribute\n if (attribute === 'startDate' || attribute === 'dueDate') {\n attribute = 'date';\n }\n\n super.renderLabel(change, labels, position, attribute);\n }\n\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injector} from '@angular/core';\nimport {States} from '../../../states.service';\nimport {WorkPackageTimelineTableController} from '../container/wp-timeline-container.directive';\nimport {RenderInfo} from '../wp-timeline';\nimport {TimelineCellRenderer} from './timeline-cell-renderer';\nimport {TimelineMilestoneCellRenderer} from './timeline-milestone-cell-renderer';\nimport {WorkPackageTimelineCell} from './wp-timeline-cell';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class WorkPackageTimelineCellsRenderer {\n\n // Injections\n @InjectField() public states:States;\n @InjectField() public halEditing:HalResourceEditingService;\n\n public cells:{ [classIdentifier:string]:WorkPackageTimelineCell } = {};\n\n private cellRenderers:{ milestone:TimelineMilestoneCellRenderer, generic:TimelineCellRenderer };\n\n constructor(readonly injector:Injector,\n readonly wpTimeline:WorkPackageTimelineTableController) {\n this.cellRenderers = {\n milestone: new TimelineMilestoneCellRenderer(this.injector, wpTimeline),\n generic: new TimelineCellRenderer(this.injector, wpTimeline)\n };\n }\n\n public hasCell(wpId:string) {\n return this.getCellsFor(wpId).length > 0;\n }\n\n public getCellsFor(wpId:string):WorkPackageTimelineCell[] {\n return _.filter(this.cells, (cell) => cell.workPackageId === wpId) || [];\n }\n\n /**\n * Synchronize the currently active cells and render them all\n */\n public refreshAllCells() {\n // Create new cells and delete old ones\n this.synchronizeCells();\n\n // Update all cells\n _.each(this.cells, (cell) => this.refreshSingleCell(cell));\n }\n\n public refreshCellsFor(wpId:string) {\n _.each(this.getCellsFor(wpId), (cell) => this.refreshSingleCell(cell));\n }\n\n public refreshSingleCell(cell:WorkPackageTimelineCell, isDuplicatedCell?:boolean, withAlternativeLabels?:boolean) {\n const renderInfo = this.renderInfoFor(cell.workPackageId, isDuplicatedCell, withAlternativeLabels);\n\n if (renderInfo.workPackage) {\n cell.refreshView(renderInfo);\n }\n }\n\n /**\n * Synchronize the current cells:\n *\n * 1. Create new cells in workPackageIdOrder not yet tracked\n * 2. Remove old cells no longer contained.\n */\n private synchronizeCells() {\n const currentlyActive:string[] = Object.keys(this.cells);\n const newCells:string[] = [];\n\n _.each(this.wpTimeline.workPackageIdOrder, (renderedRow:RenderedWorkPackage) => {\n const wpId = renderedRow.workPackageId;\n\n // Ignore extra rows not tied to a work package\n if (!wpId) {\n return;\n }\n\n const state = this.states.workPackages.get(wpId);\n if (state.isPristine()) {\n return;\n }\n\n // As work packages may occur several times, get the unique identifier\n // to identify the cell\n const identifier = renderedRow.classIdentifier;\n\n // Create a cell unless we already have an active cell\n if (!this.cells[identifier]) {\n this.cells[identifier] = this.buildCell(identifier, wpId.toString());\n }\n\n newCells.push(identifier);\n });\n\n _.difference(currentlyActive, newCells).forEach((identifier:string) => {\n this.cells[identifier].clear();\n delete this.cells[identifier];\n });\n }\n\n private buildCell(classIdentifier:string, workPackageId:string) {\n return new WorkPackageTimelineCell(\n this.injector,\n this.wpTimeline,\n this.cellRenderers,\n this.renderInfoFor(workPackageId),\n classIdentifier,\n workPackageId\n );\n }\n\n private renderInfoFor(wpId:string, isDuplicatedCell?:boolean, withAlternativeLabels?:boolean):RenderInfo {\n const wp = this.states.workPackages.get(wpId).value!;\n return {\n viewParams: this.wpTimeline.viewParameters,\n workPackage: wp,\n change: this.halEditing.changeFor(wp) as WorkPackageChangeset,\n isDuplicatedCell,\n withAlternativeLabels,\n };\n }\n\n public buildCellsAndRenderOnRow(workPackageIds:string[], rowClassIdentifier:string, isDuplicatedCell?:boolean):WorkPackageTimelineCell[] {\n const cells = workPackageIds.map(workPackageId => this.buildCell(rowClassIdentifier, workPackageId!));\n\n cells.forEach((cell:WorkPackageTimelineCell) => this.refreshSingleCell(cell, isDuplicatedCell, true));\n\n return cells;\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {AfterViewInit, Component, ElementRef, Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {INotification, NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {IsolatedQuerySpace} from 'core-app/modules/work_packages/query-space/isolated-query-space';\nimport * as moment from 'moment';\nimport {Moment} from 'moment';\nimport {filter, takeUntil} from 'rxjs/operators';\nimport {\n calculateDaySpan,\n getPixelPerDayForZoomLevel,\n requiredPixelMarginLeft,\n timelineElementCssClass,\n timelineHeaderSelector,\n timelineMarkerSelectionStartClass,\n TimelineViewParameters,\n zoomLevelOrder\n} from '../wp-timeline';\nimport {input, InputState} from 'reactivestates';\nimport {WorkPackageTable} from 'core-components/wp-fast-table/wp-fast-table';\nimport {WorkPackageTimelineCellsRenderer} from 'core-components/wp-table/timeline/cells/wp-timeline-cells-renderer';\nimport {States} from 'core-components/states.service';\nimport {WorkPackageViewTimelineService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service';\nimport {WorkPackageRelationsService} from 'core-components/wp-relations/wp-relations.service';\nimport {WorkPackageViewHierarchiesService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service';\nimport {WorkPackageTimelineCell} from 'core-components/wp-table/timeline/cells/wp-timeline-cell';\nimport {selectorTimelineSide} from 'core-components/wp-table/wp-table-scroll-sync';\nimport {debugLog, timeOutput} from 'core-app/helpers/debug_output';\nimport {RenderedWorkPackage} from 'core-app/modules/work_packages/render-info/rendered-work-package.type';\nimport {HalEventsService} from 'core-app/modules/hal/services/hal-events.service';\nimport {WorkPackageNotificationService} from 'core-app/modules/work_packages/notifications/work-package-notification.service';\nimport {combineLatest, Observable} from 'rxjs';\nimport {UntilDestroyedMixin} from 'core-app/helpers/angular/until-destroyed.mixin';\nimport {WorkPackagesTableComponent} from 'core-components/wp-table/wp-table.component';\nimport {\n groupIdFromIdentifier,\n groupTypeFromIdentifier\n} from 'core-components/wp-fast-table/builders/modes/grouped/grouped-rows-helpers';\nimport {WorkPackageViewCollapsedGroupsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service';\n\n@Component({\n selector: 'wp-timeline-container',\n templateUrl: './wp-timeline-container.html'\n})\nexport class WorkPackageTimelineTableController extends UntilDestroyedMixin implements AfterViewInit {\n private $element:JQuery;\n\n public workPackageTable:WorkPackageTable;\n\n private _viewParameters:TimelineViewParameters = new TimelineViewParameters();\n\n public disableViewParamsCalculation = false;\n\n public workPackageIdOrder:RenderedWorkPackage[] = [];\n\n private renderers:{ [name:string]:(vp:TimelineViewParameters) => void } = {};\n\n private cellsRenderer = new WorkPackageTimelineCellsRenderer(this.injector, this);\n\n public outerContainer:JQuery;\n\n public timelineBody:JQuery;\n\n private selectionParams:{ notification:INotification|null } = {\n notification: null\n };\n\n private text:{ selectionMode:string };\n\n private refreshRequest = input();\n\n private collapsedGroupsCellsMap:IGroupCellsMap = {};\n\n private orderedRows:RenderedWorkPackage[] = [];\n\n get commonPipes() {\n return (source:Observable) => {\n return source.pipe(\n this.untilDestroyed(),\n takeUntil(this.querySpace.stopAllSubscriptions),\n filter(() => this.initialized && this.wpTableTimeline.isVisible),\n );\n };\n }\n\n get workPackagesWithGroupHeaderCell():RenderedWorkPackage[] {\n const tableWorkPackages = this.querySpace.results.value!.elements;\n const wpsWithGroupHeaderCell = tableWorkPackages\n .filter(tableWorkPackage => this.shouldBeShownInCollapsedGroupHeaders(tableWorkPackage))\n .map(tableWorkPackage => tableWorkPackage.id);\n const workPackagesWithGroupHeaderCell = this.orderedRows.filter(row => wpsWithGroupHeaderCell.includes(row.workPackageId!) && !this.workPackageIdOrder.includes(row));\n\n return workPackagesWithGroupHeaderCell;\n }\n\n constructor(public readonly injector:Injector,\n private elementRef:ElementRef,\n private states:States,\n public wpTableComponent:WorkPackagesTableComponent,\n private NotificationsService:NotificationsService,\n private wpTableTimeline:WorkPackageViewTimelineService,\n private notificationService:WorkPackageNotificationService,\n private wpRelations:WorkPackageRelationsService,\n private wpTableHierarchies:WorkPackageViewHierarchiesService,\n private halEvents:HalEventsService,\n private querySpace:IsolatedQuerySpace,\n readonly I18n:I18nService,\n private workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService) {\n super();\n }\n\n ngAfterViewInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.text = {\n selectionMode: this.I18n.t('js.timelines.selection_mode.notification')\n };\n\n // Get the outer container for width computation\n this.outerContainer = this.$element.find('.wp-table-timeline--outer');\n this.timelineBody = this.$element.find('.wp-table-timeline--body');\n\n // Register this instance to the table\n this.wpTableComponent.registerTimeline(this, this.timelineBody[0]);\n\n // Refresh on window resize events\n window.addEventListener('wp-resize.timeline', () => this.refreshRequest.putValue(undefined));\n\n combineLatest([\n this.querySpace.tableRendered.values$(),\n this.refreshRequest.changes$(),\n this.wpTableTimeline.live$()\n ]).pipe(\n this.commonPipes,\n )\n .subscribe(([orderedRows, changes, timelineState]) => {\n // Remember all visible rows in their order of appearance.\n this.workPackageIdOrder = orderedRows.filter((row:RenderedWorkPackage) => !row.hidden);\n this.orderedRows = orderedRows;\n this.refreshView();\n });\n\n this.setupManageCollapsedGroupHeaderCells();\n }\n\n workPackageCells(wpId:string):WorkPackageTimelineCell[] {\n return this.cellsRenderer.getCellsFor(wpId);\n }\n\n /**\n * Return the index of a given row by its class identifier\n */\n workPackageIndex(classIdentifier:string):number {\n return this.workPackageIdOrder.findIndex((el) => el.classIdentifier === classIdentifier);\n }\n\n onRefreshRequested(name:string, callback:(vp:TimelineViewParameters) => void) {\n this.renderers[name] = callback;\n }\n\n getAbsoluteLeftCoordinates():number {\n return this.$element.offset()!.left;\n }\n\n getParentScrollContainer() {\n return this.outerContainer.closest(selectorTimelineSide)[0];\n }\n\n get viewParameters():TimelineViewParameters {\n return this._viewParameters;\n }\n\n get inHierarchyMode():boolean {\n return this.wpTableHierarchies.isEnabled;\n }\n\n get initialized():boolean {\n return this.workPackageTable && this.querySpace.tableRendered.hasValue();\n }\n\n refreshView() {\n if (!this.wpTableTimeline.isVisible) {\n debugLog('refreshView() requested, but TL is invisible.');\n return;\n }\n\n if (this.wpTableTimeline.isAutoZoom()) {\n // Update autozoom level\n this.applyAutoZoomLevel();\n } else {\n this._viewParameters.settings.zoomLevel = this.wpTableTimeline.zoomLevel;\n this.wpTableTimeline.appliedZoomLevel = this.wpTableTimeline.zoomLevel;\n }\n\n timeOutput('refreshView() in timeline container', () => {\n // Reset the width of the outer container if its content shrinks\n this.outerContainer.css('width', 'auto');\n\n this.calculateViewParams(this._viewParameters);\n\n // Update all cells\n this.cellsRenderer.refreshAllCells();\n\n _.each(this.renderers, (cb, key) => {\n debugLog(`Refreshing timeline member ${key}`);\n cb(this._viewParameters);\n });\n\n this.refreshCollapsedGroupsHeaderCells(this.collapsedGroupsCellsMap, this.cellsRenderer);\n\n // Calculate overflowing width to set to outer container\n // required to match width in all child divs.\n // The header is the only one reliable, as it already has the final width.\n const currentWidth = this.$element.find(timelineHeaderSelector)[0].scrollWidth;\n this.outerContainer.width(currentWidth);\n\n // Mark rendering event in a timeout to give DOM some time\n setTimeout(() => {\n this.querySpace.timelineRendered.next(null);\n });\n });\n }\n\n startAddRelationPredecessor(start:WorkPackageResource) {\n this.activateSelectionMode(start.id!, end => {\n this.wpRelations\n .addCommonRelation(start.id!, 'follows', end.id!)\n .then(() => {\n this.halEvents.push(start, {\n eventType: 'association',\n relatedWorkPackage: end.id!,\n relationType: 'follows'\n });\n })\n .catch((error:any) => this.notificationService.handleRawError(error, end));\n });\n }\n\n startAddRelationFollower(start:WorkPackageResource) {\n this.activateSelectionMode(start.id!, end => {\n this.wpRelations\n .addCommonRelation(start.id!, 'precedes', end.id!)\n .then(() => {\n this.halEvents.push(start, {\n eventType: 'association',\n relatedWorkPackage: end.id!,\n relationType: 'precedes'\n });\n })\n .catch((error:any) => this.notificationService.handleRawError(error, end));\n });\n }\n\n getFirstDayInViewport() {\n const outerContainer = this.getParentScrollContainer();\n const scrollLeft = outerContainer.scrollLeft;\n const nonVisibleDaysLeft = Math.floor(scrollLeft / this.viewParameters.pixelPerDay);\n return this.viewParameters.dateDisplayStart.clone().add(nonVisibleDaysLeft, 'days');\n }\n\n getLastDayInViewport() {\n const outerContainer = this.getParentScrollContainer();\n const scrollLeft = outerContainer.scrollLeft;\n const width = outerContainer.offsetWidth;\n const viewPortRight = scrollLeft + width;\n const daysUntilViewPortEnds = Math.ceil(viewPortRight / this.viewParameters.pixelPerDay) + 1;\n return this.viewParameters.dateDisplayStart.clone().add(daysUntilViewPortEnds, 'days');\n }\n\n forceCursor(cursor:string) {\n jQuery('.' + timelineElementCssClass).css('cursor', cursor);\n jQuery('.wp-timeline-cell').css('cursor', cursor);\n jQuery('.hascontextmenu').css('cursor', cursor);\n jQuery('.leftHandle').css('cursor', cursor);\n jQuery('.rightHandle').css('cursor', cursor);\n }\n\n resetCursor() {\n jQuery('.' + timelineElementCssClass).css('cursor', '');\n jQuery('.wp-timeline-cell').css('cursor', '');\n jQuery('.hascontextmenu').css('cursor', '');\n jQuery('.leftHandle').css('cursor', '');\n jQuery('.rightHandle').css('cursor', '');\n }\n\n private resetSelectionMode() {\n this._viewParameters.activeSelectionMode = null;\n this._viewParameters.selectionModeStart = null;\n\n if (this.selectionParams.notification) {\n this.NotificationsService.remove(this.selectionParams.notification);\n }\n\n Mousetrap.unbind('esc');\n\n this.$element.removeClass('active-selection-mode');\n jQuery('.' + timelineMarkerSelectionStartClass).removeClass(timelineMarkerSelectionStartClass);\n this.refreshView();\n }\n\n private activateSelectionMode(start:string, callback:(wp:WorkPackageResource) => any) {\n start = start.toString(); // old system bug: ID can be a 'number'\n\n this._viewParameters.activeSelectionMode = (wp:WorkPackageResource) => {\n callback(wp);\n this.resetSelectionMode();\n };\n\n this._viewParameters.selectionModeStart = start;\n Mousetrap.bind('esc', () => this.resetSelectionMode());\n this.selectionParams.notification = this.NotificationsService.addNotice(this.text.selectionMode);\n\n this.$element.addClass('active-selection-mode');\n\n this.refreshView();\n }\n\n private calculateViewParams(currentParams:TimelineViewParameters):boolean {\n if (this.disableViewParamsCalculation) {\n return false;\n }\n\n const newParams = new TimelineViewParameters();\n let changed = false;\n const workPackagesToCalculateTimelineWidthFrom = this.getWorkPackagesToCalculateTimelineWidthFrom();\n\n workPackagesToCalculateTimelineWidthFrom.forEach((renderedRow) => {\n const wpId = renderedRow.workPackageId;\n\n if (!wpId) {\n return;\n }\n const workPackageState:InputState = this.states.workPackages.get(wpId);\n const workPackage:WorkPackageResource|undefined = workPackageState.value;\n\n if (!workPackage) {\n return;\n }\n\n // We may still have a reference to a row that, e.g., just got deleted\n const startDate = workPackage.startDate ? moment(workPackage.startDate) : currentParams.now;\n const dueDate = workPackage.dueDate ? moment(workPackage.dueDate) : currentParams.now;\n const date = workPackage.date ? moment(workPackage.date) : currentParams.now;\n\n // start date\n newParams.dateDisplayStart = moment.min(\n newParams.dateDisplayStart,\n currentParams.now,\n startDate,\n date);\n\n // finish date\n newParams.dateDisplayEnd = moment.max(\n newParams.dateDisplayEnd,\n currentParams.now,\n dueDate,\n date);\n });\n\n // left spacing\n newParams.dateDisplayStart = newParams.dateDisplayStart.subtract(currentParams.dayCountForMarginLeft, 'days');\n\n // right spacing\n // RR: kept both variants for documentation purpose.\n // A: calculate the minimal width based on the width of the timeline view\n // B: calculate the minimal width based on the window width\n const width = this.$element.children().width()!; // A\n // const width = jQuery('body').width(); // B\n\n const pixelPerDay = currentParams.pixelPerDay;\n const visibleDays = Math.ceil((width / pixelPerDay) * 1.5);\n newParams.dateDisplayEnd = newParams.dateDisplayEnd.add(visibleDays, 'days');\n\n // Check if view params changed:\n\n // start date\n if (!newParams.dateDisplayStart.isSame(this._viewParameters.dateDisplayStart)) {\n changed = true;\n this._viewParameters.dateDisplayStart = newParams.dateDisplayStart;\n }\n\n // end date\n if (!newParams.dateDisplayEnd.isSame(this._viewParameters.dateDisplayEnd)) {\n changed = true;\n this._viewParameters.dateDisplayEnd = newParams.dateDisplayEnd;\n }\n\n // Calculate the visible viewport\n const firstDayInViewport = this.getFirstDayInViewport();\n const lastDayInViewport = this.getLastDayInViewport();\n const viewport:[Moment, Moment] = [firstDayInViewport, lastDayInViewport];\n this._viewParameters.visibleViewportAtCalculationTime = viewport;\n\n return changed;\n }\n\n private applyAutoZoomLevel() {\n if (this.workPackageIdOrder.length === 0) {\n return;\n }\n\n const workPackagesToCalculateWidthFrom = this.getWorkPackagesToCalculateTimelineWidthFrom();\n const daysSpan = calculateDaySpan(workPackagesToCalculateWidthFrom, this.states.workPackages, this._viewParameters);\n const timelineWidthInPx = this.$element.parent().width()! - (2 * requiredPixelMarginLeft);\n\n for (let zoomLevel of zoomLevelOrder) {\n const pixelPerDay = getPixelPerDayForZoomLevel(zoomLevel);\n const visibleDays = timelineWidthInPx / pixelPerDay;\n\n if (visibleDays >= daysSpan || zoomLevel === _.last(zoomLevelOrder)) {\n // Zoom level is enough\n const previousZoomLevel = this._viewParameters.settings.zoomLevel;\n\n // did the zoom level changed?\n if (previousZoomLevel !== zoomLevel) {\n this._viewParameters.settings.zoomLevel = zoomLevel;\n this.wpTableComponent.timeline.scrollLeft = 0;\n }\n\n this.wpTableTimeline.appliedZoomLevel = zoomLevel;\n return;\n }\n }\n }\n\n setupManageCollapsedGroupHeaderCells() {\n this.workPackageViewCollapsedGroupsService.updates$()\n .pipe(\n this.commonPipes,\n )\n .subscribe((groupsCollapseEvent:IGroupsCollapseEvent) => {\n this.manageCollapsedGroupHeaderCells(\n groupsCollapseEvent,\n this.querySpace.results.value!.elements,\n this.collapsedGroupsCellsMap,\n );\n });\n }\n\n manageCollapsedGroupHeaderCells(groupsCollapseConfig:IGroupsCollapseEvent,\n tableWorkPackages:WorkPackageResource[],\n collapsedGroupsCellsMap:IGroupCellsMap) {\n const refreshAllGroupHeaderCells = groupsCollapseConfig.allGroupsChanged;\n const collapsedGroupsChange = groupsCollapseConfig.state;\n const collapsedGroupsChangeArray = Object.keys(collapsedGroupsChange);\n let groupsToUpdate:string[] = [];\n\n if (!collapsedGroupsChangeArray.length) { return; }\n\n if (refreshAllGroupHeaderCells) {\n groupsToUpdate = collapsedGroupsChangeArray.filter(groupIdentifier => this.shouldManageCollapsedGroupHeaderCells(groupIdentifier, groupsCollapseConfig));\n } else {\n const groupIdentifier = groupsCollapseConfig.lastChangedGroup!;\n if (this.shouldManageCollapsedGroupHeaderCells(groupIdentifier, groupsCollapseConfig)) {\n groupsToUpdate = [groupIdentifier];\n }\n }\n\n groupsToUpdate.forEach(groupIdentifier => {\n const groupIsCollapsed = collapsedGroupsChange[groupIdentifier];\n\n if (groupIsCollapsed) {\n this.createCollapsedGroupHeaderCells(groupIdentifier, tableWorkPackages, collapsedGroupsCellsMap);\n } else {\n this.removeCollapsedGroupHeaderCells(groupIdentifier, collapsedGroupsCellsMap);\n }\n });\n }\n\n shouldManageCollapsedGroupHeaderCells(groupIdentifier:string, groupsCollapseConfig:IGroupsCollapseEvent) {\n const keyGroupType = groupTypeFromIdentifier(groupIdentifier);\n\n return this.workPackageViewCollapsedGroupsService.groupTypesWithHeaderCellsWhenCollapsed.includes(keyGroupType) &&\n this.workPackageViewCollapsedGroupsService.groupTypesWithHeaderCellsWhenCollapsed.includes(groupsCollapseConfig.groupedBy!);\n }\n\n createCollapsedGroupHeaderCells(groupIdentifier:string, tableWorkPackages:WorkPackageResource[], collapsedGroupsCellsMap:IGroupCellsMap) {\n this.removeCollapsedGroupHeaderCells(groupIdentifier, collapsedGroupsCellsMap);\n\n const changedGroupId = groupIdFromIdentifier(groupIdentifier);\n const changedGroupType = groupTypeFromIdentifier(groupIdentifier);\n const changedGroupTableWorkPackages = tableWorkPackages.filter(tableWorkPackage => tableWorkPackage[changedGroupType].id === changedGroupId);\n const changedGroupWpsWithHeaderCells = changedGroupTableWorkPackages.filter(tableWorkPackage => this.shouldBeShownInCollapsedGroupHeaders(tableWorkPackage) &&\n (tableWorkPackage.date || tableWorkPackage.startDate));\n const changedGroupWpsWithHeaderCellsIds = changedGroupWpsWithHeaderCells.map(workPackage => workPackage.id!);\n\n this.collapsedGroupsCellsMap[groupIdentifier!] = this.cellsRenderer.buildCellsAndRenderOnRow(changedGroupWpsWithHeaderCellsIds, `group-${groupIdentifier}-timeline`, true);\n }\n\n removeCollapsedGroupHeaderCells(groupIdentifier:string, collapsedGroupsCellsMap:IGroupCellsMap) {\n if (collapsedGroupsCellsMap[groupIdentifier!]) {\n collapsedGroupsCellsMap[groupIdentifier!].forEach((cell:WorkPackageTimelineCell) => cell.clear());\n collapsedGroupsCellsMap[groupIdentifier!] = [];\n }\n }\n\n refreshCollapsedGroupsHeaderCells(collapsedGroupsCellsMap:IGroupCellsMap, cellsRenderer:WorkPackageTimelineCellsRenderer) {\n Object.keys(collapsedGroupsCellsMap).forEach(collapsedGroupKey => {\n const collapsedGroupCells = collapsedGroupsCellsMap[collapsedGroupKey];\n\n collapsedGroupCells.forEach(cell => cellsRenderer.refreshSingleCell(cell, false, true));\n });\n }\n\n shouldBeShownInCollapsedGroupHeaders(workPackage:WorkPackageResource) {\n return this.workPackageViewCollapsedGroupsService\n .wpTypesToShowInCollapsedGroupHeaders\n .some(wpTypeFunction => wpTypeFunction(workPackage));\n }\n\n getWorkPackagesToCalculateTimelineWidthFrom() {\n // Include work packages that are show in collapsed group\n // headers into the calculation, if not they could be rendered out\n // of the timeline (ie: milestones are shown on collapsed row groups).\n return [...this.workPackageIdOrder, ...this.workPackagesWithGroupHeaderCell];\n }\n}\n","
    \n
    \n \n \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","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// ++\n\nimport * as moment from 'moment';\nimport {calculatePositionValueForDayCount, TimelineViewParameters} from '../wp-timeline';\nimport {TimelineStaticElement} from './timeline-static-element';\n\n\nexport class TodayLineElement extends TimelineStaticElement {\n\n protected finishElement(elem:HTMLElement, vp:TimelineViewParameters):HTMLElement {\n const offsetToday = vp.now.diff(vp.dateDisplayStart, 'days');\n const dayProgress = moment().hour() / 24;\n elem.style.left = calculatePositionValueForDayCount(vp, offsetToday + dayProgress);\n\n return elem;\n }\n\n public get identifier():string {\n return 'wp-timeline-static-element-today-line';\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free 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, Input} from '@angular/core';\nimport {takeUntil} from 'rxjs/operators';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {States} from '../../states.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {QueryColumn} from \"core-components/wp-query/query-column\";\nimport {WorkPackageViewColumnsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service\";\nimport {WorkPackageViewSumService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sum.service\";\nimport {combineLatest} from \"rxjs\";\nimport {GroupSumsBuilder} from \"core-components/wp-fast-table/builders/modes/grouped/group-sums-builder\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Directive({\n selector: '[wpTableSumsRow]'\n})\nexport class WorkPackageTableSumsRowController implements AfterViewInit {\n\n @Input('wpTableSumsRow-table') workPackageTable:WorkPackageTable;\n\n private text:{ sum:string };\n\n private $element:JQuery;\n\n private groupSumsBuilder:GroupSumsBuilder;\n\n constructor(readonly injector:Injector,\n readonly elementRef:ElementRef,\n readonly querySpace:IsolatedQuerySpace,\n readonly states:States,\n readonly schemaCache:SchemaCacheService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly wpTableSums:WorkPackageViewSumService,\n readonly I18n:I18nService) {\n\n this.text = {\n sum: I18n.t('js.label_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 this.schemaCache\n .ensureLoaded(resource.sumsSchema.$href!)\n .then((schema:SchemaResource) => {\n this.refresh(columns, resource, schema);\n });\n } else {\n this.clear();\n }\n });\n }\n\n private clear() {\n this.$element.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 this.groupSumsBuilder = new GroupSumsBuilder(this.injector, this.workPackageTable);\n this.groupSumsBuilder.renderColumns(resource.totalSums!, this.elementRef.nativeElement);\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 {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 {WorkPackageFoldToggleButtonComponent} from 'core-components/wp-buttons/wp-fold-toggle-button/wp-fold-toggle-button.component';\nimport {WpTableConfigurationModalComponent} from 'core-components/wp-table/configuration-modal/wp-table-configuration.modal';\nimport {WpTableConfigurationColumnsTab} from 'core-components/wp-table/configuration-modal/tabs/columns-tab.component';\nimport {WpTableConfigurationDisplaySettingsTab} from 'core-components/wp-table/configuration-modal/tabs/display-settings-tab.component';\nimport {WpTableConfigurationFiltersTab} from 'core-components/wp-table/configuration-modal/tabs/filters-tab.component';\nimport {WpTableConfigurationSortByTab} from 'core-components/wp-table/configuration-modal/tabs/sort-by-tab.component';\nimport {WpTableConfigurationTimelinesTab} from 'core-components/wp-table/configuration-modal/tabs/timelines-tab.component';\nimport {WpTableConfigurationHighlightingTab} from 'core-components/wp-table/configuration-modal/tabs/highlighting-tab.component';\nimport {WpTableConfigurationRelationSelectorComponent} from \"core-components/wp-table/configuration-modal/wp-table-configuration-relation-selector\";\nimport {WorkPackageWatchersTabComponent} from 'core-components/wp-single-view-tabs/watchers-tab/watchers-tab.component';\nimport {WorkPackageWatcherEntryComponent} from 'core-components/wp-single-view-tabs/watchers-tab/wp-watcher-entry.component';\nimport {WorkPackageCopyFullViewComponent} from 'core-components/wp-copy/wp-copy-full-view.component';\nimport {WorkPackageCopySplitViewComponent} from 'core-components/wp-copy/wp-copy-split-view.component';\nimport {WorkPackageTypeStatusComponent} from 'core-components/work-packages/wp-type-status/wp-type-status.component';\nimport {WorkPackageNewSplitViewComponent} from 'core-components/wp-new/wp-new-split-view.component';\nimport {WorkPackageNewFullViewComponent} from 'core-components/wp-new/wp-new-full-view.component';\nimport {WpTableExportModal} from 'core-components/modals/export-modal/wp-table-export.modal';\nimport {QuerySharingModal} from 'core-components/modals/share-modal/query-sharing.modal';\nimport {SaveQueryModal} from 'core-components/modals/save-modal/save-query.modal';\nimport {WpDestroyModal} from 'core-components/modals/wp-destroy-modal/wp-destroy.modal';\nimport {QuerySharingForm} from 'core-components/modals/share-modal/query-sharing-form.component';\nimport {EmbeddedTablesMacroComponent} from 'core-components/wp-table/embedded/embedded-tables-macro.component';\nimport {WpButtonMacroModal} from 'core-components/modals/editor/macro-wp-button-modal/wp-button-macro.modal';\nimport {OpenprojectEditorModule} from 'core-app/modules/editor/openproject-editor.module';\nimport {WorkPackageTableSumsRowController} from 'core-components/wp-table/wp-table-sums-row/wp-table-sums-row.directive';\nimport {ExternalQueryConfigurationComponent} from 'core-components/wp-table/external-configuration/external-query-configuration.component';\nimport {ExternalQueryConfigurationService} from 'core-components/wp-table/external-configuration/external-query-configuration.service';\nimport {ExternalRelationQueryConfigurationComponent} from \"core-components/wp-table/external-configuration/external-relation-query-configuration.component\";\nimport {ExternalRelationQueryConfigurationService} from \"core-components/wp-table/external-configuration/external-relation-query-configuration.service\";\nimport {WorkPackageStaticQueriesService} from 'core-components/wp-query-select/wp-static-queries.service';\nimport {WorkPackagesListInvalidQueryService} from 'core-components/wp-list/wp-list-invalid-query.service';\nimport {SchemaCacheService} from 'core-components/schemas/schema-cache.service';\nimport {WorkPackageWatchersService} from 'core-components/wp-single-view-tabs/watchers-tab/wp-watchers.service';\nimport {WorkPackagesActivityService} from 'core-components/wp-single-view-tabs/activity-panel/wp-activity.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageChildrenQueryComponent} from \"core-components/wp-relations/embedded/children/wp-children-query.component\";\nimport {WpRelationInlineAddExistingComponent} from \"core-components/wp-relations/embedded/inline/add-existing/wp-relation-inline-add-existing.component\";\nimport {WorkPackageRelationQueryComponent} from \"core-components/wp-relations/embedded/relations/wp-relation-query.component\";\nimport {WorkPackagesBaseComponent} from \"core-app/modules/work_packages/routing/wp-base/wp--base.component\";\nimport {WorkPackageSplitViewComponent} from \"core-app/modules/work_packages/routing/wp-split-view/wp-split-view.component\";\nimport {WorkPackagesFullViewComponent} from \"core-app/modules/work_packages/routing/wp-full-view/wp-full-view.component\";\nimport {AttachmentsUploadComponent} from 'core-app/modules/attachments/attachments-upload/attachments-upload.component';\nimport {AttachmentListComponent} from 'core-app/modules/attachments/attachment-list/attachment-list.component';\nimport {WorkPackageFilterByTextInputComponent} from \"core-components/filters/quick-filter-by-text-input/quick-filter-by-text-input.component\";\nimport {QueryFiltersService} from \"core-components/wp-query/query-filters.service\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageIsolatedQuerySpaceDirective} from \"core-app/modules/work_packages/query-space/wp-isolated-query-space.directive\";\nimport {WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {OpenprojectBcfModule} from \"core-app/modules/bim/bcf/openproject-bcf.module\";\nimport {WorkPackageRelationsAutocomplete} from \"core-components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.component\";\nimport {CustomDateActionAdminComponent} from 'core-components/wp-custom-actions/date-action/custom-date-action-admin.component';\nimport {WorkPackagesTableConfigMenu} from \"core-components/wp-table/config-menu/config-menu.component\";\nimport {WorkPackageIsolatedGraphQuerySpaceDirective} from \"core-app/modules/work_packages/query-space/wp-isolated-graph-query-space.directive\";\nimport {WorkPackageViewToggleButton} from \"core-components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component\";\nimport {WorkPackagesGridComponent} from \"core-components/wp-grid/wp-grid.component\";\nimport {WorkPackageViewDropdownMenuDirective} from \"core-components/op-context-menu/handlers/wp-view-dropdown-menu.directive\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {OpenprojectProjectsModule} from \"core-app/modules/projects/openproject-projects.module\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {WorkPackageEditActionsBarComponent} from \"core-app/modules/common/edit-actions-bar/wp-edit-actions-bar.component\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {WorkPackageSingleCardComponent} from \"core-components/wp-card-view/wp-single-card/wp-single-card.component\";\nimport {TimeEntryChangeset} from 'core-app/components/time-entries/time-entry-changeset';\nimport {WorkPackageListViewComponent} from \"core-app/modules/work_packages/routing/wp-list-view/wp-list-view.component\";\nimport {PartitionedQuerySpacePageComponent} from \"core-app/modules/work_packages/routing/partitioned-query-space-page/partitioned-query-space-page.component\";\nimport {WorkPackageViewPageComponent} from \"core-app/modules/work_packages/routing/wp-view-page/wp-view-page.component\";\nimport {WorkPackageSettingsButtonComponent} from \"core-components/wp-buttons/wp-settings-button/wp-settings-button.component\";\nimport {BackButtonComponent} from \"core-app/modules/common/back-routing/back-button.component\";\nimport {DatePickerModal} from \"core-components/datepicker/datepicker.modal\";\nimport {WorkPackagesTableComponent} from \"core-components/wp-table/wp-table.component\";\nimport {WorkPackageGroupToggleDropdownMenuDirective} from \"core-components/op-context-menu/handlers/wp-group-toggle-dropdown-menu.directive\";\n\n@NgModule({\n imports: [\n // Commons\n OpenprojectCommonModule,\n // Display + Edit field functionality\n OpenprojectFieldsModule,\n // CKEditor\n OpenprojectEditorModule,\n\n OpenprojectAttachmentsModule,\n\n OpenprojectBcfModule,\n\n OpenprojectProjectsModule,\n ],\n providers: [\n // Notification service\n WorkPackageNotificationService,\n\n // External query configuration\n ExternalQueryConfigurationService,\n ExternalRelationQueryConfigurationService,\n\n // Global work package states / services\n SchemaCacheService,\n\n // Global query/table state services\n // For any service that depends on the isolated query space,\n // they should be provided in wp-isolated-query-space.directive instead\n QueryFiltersService,\n WorkPackageStaticQueriesService,\n WorkPackagesListInvalidQueryService,\n\n // Provide a separate service for creation events of WP Inline create\n // This can be hierarchically injected to provide isolated events on an embedded table\n WorkPackageRelationsService,\n\n WorkPackagesActivityService,\n WorkPackageRelationsService,\n WorkPackageWatchersService,\n\n HalEventsService,\n ],\n declarations: [\n // Routing\n WorkPackagesBaseComponent,\n PartitionedQuerySpacePageComponent,\n WorkPackageViewPageComponent,\n\n // WP list side\n WorkPackageListViewComponent,\n WorkPackageSettingsButtonComponent,\n\n // Query injector isolation\n WorkPackageIsolatedQuerySpaceDirective,\n WorkPackageIsolatedGraphQuerySpaceDirective,\n\n // WP New\n WorkPackageNewFullViewComponent,\n WorkPackageNewSplitViewComponent,\n WorkPackageTypeStatusComponent,\n WorkPackageEditActionsBarComponent,\n\n // WP Copy\n WorkPackageCopyFullViewComponent,\n WorkPackageCopySplitViewComponent,\n\n // Embedded table\n WorkPackageEmbeddedTableComponent,\n WorkPackageEmbeddedTableEntryComponent,\n\n // External query configuration\n ExternalQueryConfigurationComponent,\n ExternalRelationQueryConfigurationComponent,\n\n // Inline create\n WorkPackageInlineCreateComponent,\n WpRelationInlineAddExistingComponent,\n\n WorkPackagesGridComponent,\n\n WorkPackagesTableComponent,\n WorkPackagesTableConfigMenu,\n WorkPackageTablePaginationComponent,\n\n WpResizerDirective,\n\n WorkPackageTableSumsRowController,\n\n // Fold/Unfold button on wp list\n WorkPackageFoldToggleButtonComponent,\n\n // Filters\n QueryFiltersComponent,\n QueryFilterComponent,\n FilterBooleanValueComponent,\n FilterDateValueComponent,\n FilterDatesValueComponent,\n FilterDateTimeValueComponent,\n FilterDateTimesValueComponent,\n FilterIntegerValueComponent,\n FilterStringValueComponent,\n FilterToggledMultiselectValueComponent,\n\n WorkPackageFilterContainerComponent,\n WorkPackageFilterButtonComponent,\n\n // Context menus\n OpTypesContextMenuDirective,\n OpColumnsContextMenu,\n OpSettingsMenuDirective,\n WorkPackageStatusDropdownDirective,\n WorkPackageCreateSettingsMenuDirective,\n WorkPackageSingleContextMenuDirective,\n WorkPackageQuerySelectDropdownComponent,\n WorkPackageViewDropdownMenuDirective,\n WorkPackageGroupToggleDropdownMenuDirective,\n\n // Timeline\n WorkPackageTimelineButtonComponent,\n WorkPackageTimelineHeaderController,\n WorkPackageTableTimelineRelations,\n WorkPackageTableTimelineStaticElements,\n WorkPackageTableTimelineGrid,\n WorkPackageTimelineTableController,\n\n WorkPackageCreateButtonComponent,\n WorkPackageFilterByTextInputComponent,\n\n // Single view\n WorkPackageOverviewTabComponent,\n WorkPackageSingleViewComponent,\n WorkPackageStatusButtonComponent,\n WorkPackageReplacementLabelComponent,\n UserLinkComponent,\n WorkPackageChildrenQueryComponent,\n WorkPackageRelationQueryComponent,\n WorkPackageFormAttributeGroupComponent,\n BackButtonComponent,\n\n // Activity Tab\n NewestActivityOnOverviewComponent,\n WorkPackageCommentComponent,\n WorkPackageCommentFieldComponent,\n ActivityEntryComponent,\n UserActivityComponent,\n RevisionActivityComponent,\n ActivityLinkComponent,\n WorkPackageActivityTabComponent,\n\n // Watchers tab\n WorkPackageWatchersTabComponent,\n WorkPackageWatcherEntryComponent,\n\n // Relations\n WorkPackageRelationsTabComponent,\n WorkPackageRelationsComponent,\n WorkPackageRelationsGroupComponent,\n WorkPackageRelationRowComponent,\n WorkPackageRelationsCreateComponent,\n WorkPackageRelationsHierarchyComponent,\n WorkPackageRelationsAutocomplete,\n WorkPackageBreadcrumbParentComponent,\n\n // Split view\n WorkPackageDetailsViewButtonComponent,\n WorkPackageSplitViewComponent,\n WorkPackageRelationsCountComponent,\n WorkPackageWatchersCountComponent,\n WorkPackageBreadcrumbComponent,\n WorkPackageSplitViewToolbarComponent,\n WorkPackageWatcherButtonComponent,\n WorkPackageSubjectComponent,\n\n // Full view\n WorkPackagesFullViewComponent,\n\n // Modals\n WpTableConfigurationModalComponent,\n WpTableConfigurationColumnsTab,\n WpTableConfigurationDisplaySettingsTab,\n WpTableConfigurationFiltersTab,\n WpTableConfigurationSortByTab,\n WpTableConfigurationTimelinesTab,\n WpTableConfigurationHighlightingTab,\n WpTableConfigurationRelationSelectorComponent,\n WpTableExportModal,\n QuerySharingForm,\n QuerySharingModal,\n SaveQueryModal,\n WpDestroyModal,\n DatePickerModal,\n\n // CustomActions\n WpCustomActionComponent,\n WpCustomActionsComponent,\n CustomDateActionAdminComponent,\n\n // CKEditor macros which could not be included in the\n // editor module to avoid circular dependencies\n EmbeddedTablesMacroComponent,\n WpButtonMacroModal,\n\n // Card view\n WorkPackageCardViewComponent,\n WorkPackageSingleCardComponent,\n WorkPackageViewToggleButton,\n\n\n ],\n exports: [\n WorkPackagesTableComponent,\n WorkPackageTablePaginationComponent,\n WorkPackageEmbeddedTableComponent,\n WorkPackageEmbeddedTableEntryComponent,\n WorkPackageCardViewComponent,\n WorkPackageSingleCardComponent,\n WorkPackageFilterButtonComponent,\n WorkPackageFilterContainerComponent,\n WorkPackageIsolatedQuerySpaceDirective,\n WorkPackageIsolatedGraphQuerySpaceDirective,\n QueryFiltersComponent,\n\n WpResizerDirective,\n WorkPackageBreadcrumbComponent,\n WorkPackageBreadcrumbParentComponent,\n WorkPackageSplitViewToolbarComponent,\n WorkPackageSubjectComponent,\n WorkPackageWatchersCountComponent,\n WorkPackageRelationsCountComponent,\n WorkPackagesGridComponent,\n\n // Modals\n WpTableConfigurationModalComponent,\n WpTableConfigurationFiltersTab,\n\n // Needed so that e.g. IFC can access it.\n WorkPackageCreateButtonComponent,\n WorkPackageTypeStatusComponent,\n WorkPackageEditActionsBarComponent,\n WorkPackageSingleViewComponent,\n WorkPackageSplitViewComponent,\n BackButtonComponent,\n ]\n})\nexport class OpenprojectWorkPackagesModule {\n static bootstrapAttributeGroupsCalled = false;\n\n constructor(injector:Injector) {\n OpenprojectWorkPackagesModule.bootstrapAttributeGroups(injector);\n }\n\n // The static property prevents running the function\n // multiple times. This happens e.g. when the module is included\n // into a plugin's module.\n public static bootstrapAttributeGroups(injector:Injector):void {\n if (this.bootstrapAttributeGroupsCalled) {\n return;\n }\n\n this.bootstrapAttributeGroupsCalled = true;\n\n const hookService = injector.get(HookService);\n\n hookService.register('attributeGroupComponent', (group:GroupDescriptor, workPackage:WorkPackageResource) => {\n if (group.type === 'WorkPackageFormAttributeGroup') {\n return WorkPackageFormAttributeGroupComponent;\n } else if (!workPackage.isNew && group.type === 'WorkPackageFormChildrenQueryGroup') {\n return WorkPackageChildrenQueryComponent;\n } else if (!workPackage.isNew && group.type === 'WorkPackageFormRelationQueryGroup') {\n return WorkPackageRelationQueryComponent;\n } else {\n return null;\n }\n });\n\n hookService.register('workPackageAttachmentUploadComponent', (workPackage:WorkPackageResource) => {\n return AttachmentsUploadComponent;\n });\n\n hookService.register('workPackageAttachmentListComponent', (workPackage:WorkPackageResource) => {\n return AttachmentListComponent;\n });\n\n /** Return specialized work package changeset for editing service */\n hookService.register('halResourceChangesetClass', (resource:HalResource) => {\n switch (resource._type) {\n case 'WorkPackage':\n return WorkPackageChangeset;\n case 'TimeEntry':\n return TimeEntryChangeset;\n default:\n return null;\n }\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {StateService, TransitionPromise} from '@uirouter/core';\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {Injectable} from '@angular/core';\nimport {WorkPackageViewPagination} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-pagination\";\n\n@Injectable()\nexport class WorkPackagesListChecksumService {\n constructor(protected UrlParamsHelper:UrlParamsHelperService,\n protected $state:StateService) {\n }\n\n public id:string|null;\n public checksum:string|null;\n public visibleChecksum:string|null;\n\n public updateIfDifferent(query:QueryResource,\n pagination:WorkPackageViewPagination):Promise {\n\n let newQueryChecksum = this.getNewChecksum(query, pagination);\n let routePromise:Promise = Promise.resolve();\n\n if (this.isUninitialized()) {\n // Do nothing\n } else if (this.isIdDifferent(query.id)) {\n routePromise = this.maintainUrlQueryState(query.id, null);\n\n this.clear();\n\n } else if (this.isChecksumDifferent(newQueryChecksum)) {\n routePromise = this.maintainUrlQueryState(query.id, newQueryChecksum);\n }\n\n this.set(query.id, newQueryChecksum);\n return routePromise;\n }\n\n public update(query:QueryResource, pagination:WorkPackageViewPagination) {\n let newQueryChecksum = this.getNewChecksum(query, pagination);\n\n this.set(query.id, newQueryChecksum);\n\n this.maintainUrlQueryState(query.id, newQueryChecksum);\n }\n\n public setToQuery(query:QueryResource, pagination:WorkPackageViewPagination) {\n let newQueryChecksum = this.getNewChecksum(query, pagination);\n\n this.set(query.id, newQueryChecksum);\n\n return this.maintainUrlQueryState(query.id, null);\n }\n\n public isQueryOutdated(query:QueryResource,\n pagination:WorkPackageViewPagination) {\n let newQueryChecksum = this.getNewChecksum(query, pagination);\n\n return this.isOutdated(query.id, newQueryChecksum);\n }\n\n public executeIfOutdated(newId:string,\n newChecksum:string|null,\n callback:Function) {\n if (this.isUninitialized() || this.isOutdated(newId, newChecksum)) {\n this.set(newId, newChecksum);\n\n callback();\n }\n }\n\n private set(id:string|null, checksum:string|null) {\n this.id = id;\n this.checksum = checksum;\n }\n\n public clear() {\n this.id = null;\n this.checksum = null;\n this.visibleChecksum = null;\n }\n\n public isUninitialized() {\n return !this.id && !this.checksum;\n }\n\n private isIdDifferent(otherId:string|null) {\n return this.id !== otherId;\n }\n\n private isChecksumDifferent(otherChecksum:string) {\n return this.checksum && otherChecksum !== this.checksum;\n }\n\n private isOutdated(otherId:string|null, otherChecksum:string|null) {\n const hasCurrentQueryID = !!this.id;\n const hasCurrentChecksum = !!this.checksum;\n const idChanged = (this.id !== otherId);\n\n const checksumChanged = (otherChecksum !== this.checksum);\n const visibleChecksumChanged = (this.checksum && !otherChecksum && this.visibleChecksum);\n\n return (\n // Can only be outdated if either ID or props set\n (hasCurrentQueryID || hasCurrentChecksum) &&\n (\n // Query ID changed\n idChanged ||\n // Query ID same + query props changed\n (!idChanged && checksumChanged && (otherChecksum || this.visibleChecksum)) ||\n // No query ID set\n (!hasCurrentQueryID && visibleChecksumChanged)\n )\n );\n }\n\n private getNewChecksum(query:QueryResource, pagination:WorkPackageViewPagination) {\n return this.UrlParamsHelper.encodeQueryJsonParams(query, _.pick(pagination, ['page', 'perPage']));\n }\n\n private maintainUrlQueryState(id:string|null, checksum:string|null):TransitionPromise {\n this.visibleChecksum = checksum;\n\n return this.$state.go(\n '.',\n { query_props: checksum, query_id: id },\n { custom: { notify: false } }\n );\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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/*\n The action menu is a menu that usually belongs to an OpenProject entity (like an Issue, WikiPage, Meeting, ..).\n Most likely it looks like this:\n \n The following code is responsible to open and close the \"more functions\" submenu.\n*/\nimport {ANIMATION_RATE_MS} from \"core-app/globals/global-listeners/top-menu\";\nimport ClickEvent = JQuery.ClickEvent;\n\nfunction menu_top_position(menu:JQuery) {\n // if an h2 tag follows the submenu should unfold out at the border\n var menu_start_position;\n if (menu.next().get(0) !== undefined && (menu.next().get(0).tagName === 'H2')) {\n menu_start_position = menu.next().innerHeight()! + menu.next().position().top;\n }\n else if (menu.next().hasClass(\"wiki-content\") && menu.next().children().next().first().get(0) != undefined && menu.next().children().next().first().get(0).tagName == 'H1') {\n var wiki_heading = menu.next().children().next().first();\n menu_start_position = wiki_heading.innerHeight()! + wiki_heading.position().top;\n }\n return menu_start_position;\n}\n\nfunction close_menu(event:any) {\n var menu = jQuery(event.data.menu);\n // do not close the menu, if the user accidentally clicked next to a menu item (but still within the menu)\n if (event.target !== menu.find(\" > li.drop-down.open > ul\").get(0)) {\n menu.find(\" > li.drop-down.open\").removeClass(\"open\").find(\"> ul\").slideUp(ANIMATION_RATE_MS);\n // no need to watch for clicks, when the menu is already closed\n jQuery('html').off('click', close_menu);\n }\n}\n\nfunction open_menu(menu:JQuery) {\n var drop_down = menu.find(\" > li.drop-down\");\n // do not open a menu, which is already open\n if (!drop_down.hasClass('open')) {\n drop_down.find('> ul').slideDown(ANIMATION_RATE_MS, function () {\n drop_down.find('li > a:first').focus();\n // when clicking on something, which is not the menu, close the menu\n jQuery('html').on('click', {menu: menu.get(0)}, close_menu);\n });\n drop_down.addClass('open');\n }\n}\n\n// open the given submenu when clicking on it\nexport function install_menu_logic(menu:JQuery) {\n menu.find(\" > li.drop-down\").on('click', (event:ClickEvent) => {\n open_menu(menu);\n // and prevent default action (href) for that element\n // but not for the menu items.\n var target = jQuery(event.target);\n if (target.is('.drop-down') || target.closest('li, ul').is('.drop-down')) {\n event.preventDefault();\n }\n });\n}\n","import {EventEmitter, InjectionToken, Injector} from '@angular/core';\n\nexport interface WorkPackageViewEventHandler {\n /** Event name to register **/\n EVENT:string;\n\n /** Event context CSS selector */\n SELECTOR:string;\n\n /** Event callback handler */\n handleEvent(view:T, evt:JQuery.TriggeredEvent):void;\n\n /** Event scope method */\n eventScope(view:T):JQuery;\n}\n\nexport interface WorkPackageViewOutputs {\n // On selection updated\n selectionChanged:EventEmitter;\n // On row (double) clicked\n itemClicked:EventEmitter<{ workPackageId:string, double:boolean }>;\n // On work package link / details icon clicked\n stateLinkClicked:EventEmitter<{ workPackageId:string, requestedState:string }>;\n}\n\nexport const WorkPackageViewHandlerToken = new InjectionToken>('CardEventHandler');\n\n/**\n * Abstract view handler registry for globally handling arbitrary event on the\n * view container. Used e.g., for table to register single event callbacks for the entirety\n * of the table.\n */\nexport abstract class WorkPackageViewHandlerRegistry {\n\n constructor(public readonly injector:Injector) {\n }\n\n protected abstract eventHandlers:((view:T) => WorkPackageViewEventHandler)[];\n\n attachTo(viewRef:T) {\n this.eventHandlers.map(factory => {\n let handler = factory(viewRef);\n let target = handler.eventScope(viewRef);\n\n target.on(handler.EVENT, handler.SELECTOR, (evt:JQuery.TriggeredEvent) => {\n handler.handleEvent(viewRef, evt);\n });\n\n return handler;\n });\n }\n}\n","import {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable} from '@angular/core';\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\n\n@Injectable()\nexport class WorkPackageCardViewService {\n public constructor(readonly querySpace:IsolatedQuerySpace) {\n }\n\n public classIdentifier(wp:WorkPackageResource) {\n // The same class names are used for the proximity to the table representation.\n return `wp-row-${wp.id}`;\n }\n\n public get renderedCards() {\n return this.querySpace.tableRendered.getValueOr([]);\n }\n\n public findRenderedCard(classIdentifier:string):number {\n const index = _.findIndex(this.renderedCards, (card) => card.classIdentifier === classIdentifier);\n\n return index;\n }\n\n public updateRenderedCardsValues(workPackages:WorkPackageResource[]) {\n this.querySpace.tableRendered.putValue(\n workPackages.map((wp) => {\n return {\n classIdentifier: this.classIdentifier(wp),\n workPackageId: wp.id,\n hidden: false\n };\n })\n )\n }\n}\n","import {Injector} from '@angular/core';\nimport {CardEventHandler} from \"core-components/wp-card-view/event-handler/card-view-handler-registry\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageViewFocusService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {StateService} from \"@uirouter/core\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class CardClickHandler implements CardEventHandler {\n\n // Injections\n @InjectField() deviceService:DeviceService;\n @InjectField() $state:StateService;\n @InjectField() wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() wpTableFocus:WorkPackageViewFocusService;\n @InjectField() wpCardView:WorkPackageCardViewService;\n\n constructor(public readonly injector:Injector,\n card:WorkPackageCardViewComponent) {\n }\n\n public get EVENT() {\n return 'click.cardView.card';\n }\n\n public get SELECTOR() {\n return `.wp-card`;\n }\n\n public eventScope(card:WorkPackageCardViewComponent) {\n return jQuery(card.container.nativeElement);\n }\n\n public handleEvent(card:WorkPackageCardViewComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // Ignore links\n if (target.is('a') || target.parent().is('a')) {\n return true;\n }\n\n // Locate the card from event\n let element = target.closest('wp-single-card');\n let wpId = element.data('workPackageId');\n\n if (!wpId) {\n return true;\n }\n\n this.handleWorkPackage(card, wpId, element, evt);\n\n return false;\n }\n\n\n protected handleWorkPackage(card:WorkPackageCardViewComponent, wpId:any, element:JQuery, evt:JQuery.TriggeredEvent) {\n this.setSelection(card, wpId, element, evt);\n\n card.itemClicked.emit({ workPackageId: wpId, double: false });\n }\n\n protected setSelection(card:WorkPackageCardViewComponent, wpId:string, element:JQuery, evt:JQuery.TriggeredEvent) {\n let classIdentifier = element.data('classIdentifier');\n let index = this.wpCardView.findRenderedCard(classIdentifier);\n\n // Update single selection if no modifier present\n if (!(evt.ctrlKey || evt.metaKey || evt.shiftKey)) {\n this.wpTableSelection.setSelection(wpId, index);\n }\n\n // Multiple selection if shift present\n if (evt.shiftKey) {\n this.wpTableSelection.setMultiSelectionFrom(this.wpCardView.renderedCards, wpId, index);\n }\n\n // Single selection expansion if ctrl / cmd(mac)\n if (evt.ctrlKey || evt.metaKey) {\n this.wpTableSelection.toggleRow(wpId);\n }\n\n card.selectionChanged.emit(this.wpTableSelection.getSelectedWorkPackageIds());\n\n // The current card is the last selected work package\n // not matter what other card are (de-)selected below.\n // Thus save that card for the details view button.\n this.wpTableFocus.updateFocus(wpId);\n }\n\n}\n","import {Injector} from '@angular/core';\nimport {CardEventHandler} from \"core-components/wp-card-view/event-handler/card-view-handler-registry\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {StateService} from \"@uirouter/core\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class CardDblClickHandler implements CardEventHandler {\n @InjectField() $state:StateService;\n @InjectField() wpTableSelection:WorkPackageViewSelectionService;\n\n constructor(public readonly injector:Injector,\n card:WorkPackageCardViewComponent) {\n }\n\n public get EVENT() {\n return 'dblclick.cardView.card';\n }\n\n public get SELECTOR() {\n return `.wp-card`;\n }\n\n public eventScope(card:WorkPackageCardViewComponent) {\n return jQuery(card.container.nativeElement);\n }\n\n public handleEvent(card:WorkPackageCardViewComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // Ignore links\n if (target.is('a') || target.parent().is('a')) {\n return true;\n }\n\n // Locate the row from event\n let element = target.closest('wp-single-card');\n let wpId = element.data('workPackageId');\n\n if (!wpId) {\n return true;\n }\n\n card.itemClicked.emit({ workPackageId: wpId, double: true });\n return false;\n }\n}\n\n","import {Injector} from '@angular/core';\nimport {CardEventHandler} from \"core-components/wp-card-view/event-handler/card-view-handler-registry\";\nimport {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {uiStateLinkClass} from \"core-components/wp-fast-table/builders/ui-state-link-builder\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {WorkPackageViewContextMenu} from \"core-components/op-context-menu/wp-context-menu/wp-view-context-menu.directive\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport class CardRightClickHandler implements CardEventHandler {\n\n // Injections\n @InjectField() wpTableSelection:WorkPackageViewSelectionService;\n @InjectField() wpCardView:WorkPackageCardViewService;\n @InjectField() opContextMenu:OPContextMenuService;\n\n constructor(public readonly injector:Injector,\n card:WorkPackageCardViewComponent) {\n }\n\n public get EVENT() {\n return 'contextmenu.cardView.rightclick';\n }\n\n public get SELECTOR() {\n return `.wp-card`;\n }\n\n public eventScope(card:WorkPackageCardViewComponent) {\n return jQuery(card.container.nativeElement);\n }\n\n public handleEvent(card:WorkPackageCardViewComponent, evt:JQuery.TriggeredEvent) {\n let target = jQuery(evt.target);\n\n // We want to keep the original context menu on hrefs\n // (currently, this is only the id)\n if (target.closest(`.${uiStateLinkClass}`).length) {\n debugLog('Allowing original context menu on state link');\n return true;\n }\n\n evt.preventDefault();\n evt.stopPropagation();\n\n // Locate the card from event\n const element = target.closest('wp-single-card');\n const wpId = element.data('workPackageId');\n\n if (!wpId) {\n return true;\n } else {\n let classIdentifier = element.data('classIdentifier');\n let index = this.wpCardView.findRenderedCard(classIdentifier);\n\n if (!this.wpTableSelection.isSelected(wpId)) {\n this.wpTableSelection.setSelection(wpId, index);\n }\n\n const handler = new WorkPackageViewContextMenu(this.injector, wpId, jQuery(evt.target) as JQuery, {}, card.showInfoButton);\n this.opContextMenu.show(handler, evt);\n }\n\n return false;\n }\n}\n\n","import {WorkPackageCardViewComponent} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {CardClickHandler} from \"core-components/wp-card-view/event-handler/click-handler\";\nimport {CardDblClickHandler} from \"core-components/wp-card-view/event-handler/double-click-handler\";\nimport {CardRightClickHandler} from \"core-components/wp-card-view/event-handler/right-click-handler\";\nimport {\n WorkPackageViewEventHandler,\n WorkPackageViewHandlerRegistry\n} from \"core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry\";\n\n\nexport type CardEventHandler = WorkPackageViewEventHandler;\n\nexport class CardViewHandlerRegistry extends WorkPackageViewHandlerRegistry {\n\n protected eventHandlers:((c:WorkPackageCardViewComponent) => CardEventHandler)[] = [\n // Clicking on the card (not within a cell)\n c => new CardClickHandler(this.injector, c),\n // Double Clicking on the row (not within a cell)\n c => new CardDblClickHandler(this.injector, c),\n // Right clicking on cards\n t => new CardRightClickHandler(this.injector, t),\n ];\n}\n","import {AfterViewInit, ChangeDetectorRef, Component, Inject, OnInit, ViewChild} from '@angular/core';\nimport {WorkPackageEmbeddedTableComponent} from 'core-components/wp-table/embedded/wp-embedded-table.component';\nimport {WpTableConfigurationService} from 'core-components/wp-table/configuration-modal/wp-table-configuration.service';\nimport {RestrictedWpTableConfigurationService} from 'core-components/wp-table/external-configuration/restricted-wp-table-configuration.service';\nimport {OpQueryConfigurationLocalsToken} from \"core-components/wp-table/external-configuration/external-query-configuration.constants\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\n\nexport interface QueryConfigurationLocals {\n service:any;\n currentQuery:any;\n urlParams?:boolean;\n disabledTabs?:{ [key:string]:string };\n callback:(newQuery:any) => void;\n}\n\n@Component({\n templateUrl: './external-query-configuration.template.html',\n providers: [[{ provide: WpTableConfigurationService, useClass: RestrictedWpTableConfigurationService }]]\n})\nexport class ExternalQueryConfigurationComponent implements OnInit, AfterViewInit {\n\n @ViewChild('embeddedTableForConfiguration', { static: true }) private embeddedTable:WorkPackageEmbeddedTableComponent;\n\n queryProps:string;\n\n constructor(@Inject(OpQueryConfigurationLocalsToken) readonly locals:QueryConfigurationLocals,\n readonly urlParamsHelper:UrlParamsHelperService,\n readonly cdRef:ChangeDetectorRef) {\n }\n\n ngOnInit() {\n if (this.locals.urlParams) {\n this.queryProps = this.urlParamsHelper.buildV3GetQueryFromJsonParams(this.locals.currentQuery);\n } else {\n this.queryProps = this.locals.currentQuery;\n }\n }\n\n ngAfterViewInit() {\n // Open the configuration modal in an asynchronous step\n // to avoid nesting components in the view initialization.\n setTimeout(() => {\n this.embeddedTable.openConfigurationModal(() => {\n this.service.detach();\n if (this.locals.urlParams) {\n this.locals.callback(this.embeddedTable.buildUrlParams());\n } else {\n this.locals.callback(this.embeddedTable.buildQueryProps());\n }\n });\n this.cdRef.detectChanges();\n });\n }\n\n public get service():any {\n return this.locals.service;\n }\n}\n","
    \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 {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 ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input, NgZone,\n OnInit\n} from \"@angular/core\";\nimport {CommentService} from \"core-components/wp-activity/comment-service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageCommentFieldHandler} from \"core-components/work-packages/work-package-comment/work-package-comment-field-handler\";\nimport {DomSanitizer, SafeHtml} from \"@angular/platform-browser\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'user-activity',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './user-activity.component.html'\n})\nexport class UserActivityComponent extends WorkPackageCommentFieldHandler implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public activity:HalResource;\n @Input() public activityNo:number;\n @Input() public isInitial:boolean;\n\n public userCanEdit = false;\n public userCanQuote = false;\n\n public userId:string | number;\n public user:UserResource;\n public userName:string;\n public userAvatar:string;\n public details:any[] = [];\n public isComment:boolean;\n public isBcfComment:boolean;\n public postedComment:SafeHtml;\n\n public focused = false;\n\n public text = {\n label_created_on: this.I18n.t('js.label_created_on'),\n label_updated_on: this.I18n.t('js.label_updated_on'),\n quote_comment: this.I18n.t('js.label_quote_comment'),\n edit_comment: this.I18n.t('js.label_edit_comment'),\n };\n\n private $element:JQuery;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly sanitization:DomSanitizer,\n readonly PathHelper:PathHelperService,\n readonly wpLinkedActivities:WorkPackagesActivityService,\n readonly commentService:CommentService,\n readonly ConfigurationService:ConfigurationService,\n readonly apiV3Service:APIV3Service,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService,\n readonly ngZone:NgZone) {\n 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\n .apiV3Service\n .users\n .id(this.activity.user.idFromLink)\n .get()\n .subscribe((user:UserResource) => {\n this.user = user;\n this.userId = user.id!;\n this.userName = user.name;\n this.userAvatar = user.avatar;\n this.cdRef.detectChanges();\n });\n\n if (window.location.hash === `#activity-${this.activityNo}`) {\n this.ngZone.runOutsideAngular(() => {\n setTimeout(() => {\n this.elementRef.nativeElement.scrollIntoView(true);\n });\n });\n }\n }\n\n public shouldHideIcons():boolean {\n return !((this.isComment || this.isBcfComment) && this.focussing());\n }\n\n public activate() {\n super.activate(this.activity.comment.raw);\n this.cdRef.detectChanges();\n }\n\n public handleUserSubmit() {\n if (this.inFlight || !this.rawComment) {\n return Promise.resolve();\n }\n return this.updateComment();\n }\n\n public quoteComment() {\n this.commentService.quoteEvents.next(this.quotedText(this.activity.comment.raw));\n }\n\n public get bcfSnapshotUrl() {\n if (_.get(this.activity, 'bcfViewpoints[0]')) {\n return `${_.get(this.activity, 'bcfViewpoints[0]').href}/snapshot`;\n } else {\n return null;\n }\n }\n\n public async updateComment() {\n this.inFlight = true;\n\n await this.onSubmit();\n return this.commentService.updateComment(this.activity, this.rawComment || '')\n .then((newActivity:HalResource) => {\n this.activity = newActivity;\n this.updateCommentText();\n this.wpLinkedActivities.require(this.workPackage, true);\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(this.workPackage);\n })\n .finally(() => {\n this.deactivate(true); this.inFlight = false;\n });\n }\n\n public focusEditIcon() {\n // Find the according edit icon and focus it\n jQuery('.edit-activity--' + this.activityNo + ' a').focus();\n }\n\n public focus() {\n this.focused = true;\n this.cdRef.detectChanges();\n }\n\n public blur() {\n this.focused = false;\n this.cdRef.detectChanges();\n }\n\n public focussing() {\n return this.focused;\n }\n\n setErrors(newErrors:string[]):void {\n // interface\n }\n\n public quotedText(rawComment:string) {\n let quoted = rawComment.split('\\n')\n .map(function(line:string) {\n return '\\n> ' + line;\n })\n .join('');\n return this.userName + ' wrote:\\n' + quoted;\n }\n\n 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 {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {BoardActionsRegistryService} from \"core-app/modules/boards/board/board-actions/board-actions-registry.service\";\nimport {BehaviorSubject, Observable} from \"rxjs\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport interface CreateBoardParams {\n type:BoardType;\n boardName?:string;\n attribute?:string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class BoardService {\n\n public currentBoard$:BehaviorSubject = new BehaviorSubject(null);\n\n private loadAllPromise:Promise|undefined;\n\n private text = {\n unnamed_board: this.I18n.t('js.boards.label_unnamed_board'),\n action_board: (attr:string) => this.I18n.t('js.boards.board_type.action_by_attribute',\n { attribute: this.I18n.t('js.boards.board_type.action_type.' + attr) }),\n unnamed_list: this.I18n.t('js.boards.label_unnamed_list'),\n };\n\n constructor(protected apiV3Service:APIV3Service,\n protected PathHelper:PathHelperService,\n protected CurrentProject:CurrentProjectService,\n protected halResourceService:HalResourceService,\n protected boardActions:BoardActionsRegistryService,\n protected I18n:I18nService,\n protected boardsList:BoardListsService) {\n }\n\n /**\n * Return all boards in the current scope of the project\n *\n * @param projectIdentifier\n */\n public loadAllBoards(projectIdentifier:string|null = this.CurrentProject.identifier, force = false) {\n if (!(force || this.loadAllPromise === undefined)) {\n return this.loadAllPromise;\n }\n\n return this.loadAllPromise = this\n .apiV3Service\n .boards\n .allInScope(projectIdentifier!)\n .toPromise();\n }\n\n /**\n * Check whether the current user can manage board-type grids.\n */\n public canManage(board:Board):boolean {\n return !!board.grid.$links.delete;\n }\n\n\n /**\n * Save the changes to the board\n */\n public save(board:Board):Observable {\n this.reorderWidgets(board);\n return this\n .apiV3Service\n .boards\n .id(board)\n .save(board);\n }\n\n /**\n * Create a new board\n * @param name\n */\n public async create(params:CreateBoardParams):Promise {\n const board = await this\n .apiV3Service\n .boards\n .create(params.type, this.boardName(params), this.CurrentProject.identifier!, params.attribute).toPromise();\n\n if (params.type === 'free') {\n await this.boardsList.addFreeQuery(board, { name: this.text.unnamed_list });\n } else {\n await this.boardActions.get(params.attribute!).addInitialColumnsForAction(board);\n }\n\n await this.save(board).toPromise();\n\n return board;\n }\n\n public delete(board:Board):Promise {\n return this\n .apiV3Service\n .boards\n .id(board)\n .delete()\n .toPromise();\n }\n\n /**\n * Build a default board name\n */\n private boardName(params:CreateBoardParams) {\n if (params.boardName) {\n return params.boardName;\n }\n\n if (params.type === \"action\") {\n return this.text.action_board(params.attribute!);\n }\n\n return this.text.unnamed_board;\n }\n\n /**\n * Reorders the widgets to correspond to the available columns\n * @param board\n */\n private reorderWidgets(board:Board) {\n board.grid.columnCount = Math.max(board.grid.widgets.length, 1);\n board.grid.widgets.map((el:GridWidgetResource, index:number) => {\n el.startColumn = index + 1;\n el.endColumn = index + 2;\n return el;\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {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 {Observable} from 'rxjs';\nimport {distinctUntilChanged, map} from 'rxjs/operators';\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {WorkPackageViewBaseService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\n\nexport interface WPFocusState {\n workPackageId:string;\n focusAfterRender:boolean;\n}\n\n@Injectable()\nexport class WorkPackageViewFocusService extends WorkPackageViewBaseService {\n\n constructor(public querySpace:IsolatedQuerySpace,\n public wpTableSelection:WorkPackageViewSelectionService) {\n super(querySpace);\n }\n\n public isFocused(workPackageId:string) {\n return this.focusedWorkPackage === workPackageId;\n }\n\n public ifShouldFocus(callback:(workPackageId:string) => void) {\n const value = this.current;\n\n if (value && value.focusAfterRender) {\n callback(value.workPackageId);\n value.focusAfterRender = false;\n this.update(value);\n }\n }\n\n public get focusedWorkPackage():string|null {\n const value = this.current;\n\n if (value) {\n return value.workPackageId;\n }\n\n // Return the first result if none selected\n const results = this.querySpace.results.value;\n if (results && results.elements.length > 0) {\n return results.elements[0].id!.toString();\n }\n\n return null;\n }\n\n public whenChanged():Observable {\n return this.live$()\n .pipe(\n map((val:WPFocusState) => val.workPackageId),\n distinctUntilChanged()\n );\n }\n\n public updateFocus(workPackageId:string, setFocusAfterRender:boolean = false) {\n // Set the selection to this row, if nothing else is selected.\n if (this.wpTableSelection.isEmpty) {\n this.wpTableSelection.setRowState(workPackageId, true);\n }\n this.update({ workPackageId: workPackageId, focusAfterRender: setFocusAfterRender });\n }\n\n valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource):WPFocusState|undefined {\n return undefined;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","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\";\nimport {TableEventComponent} from \"core-components/wp-fast-table/handlers/table-handler-registry\";\n\n\n/**\n * Execute the callback if the given JQuery Event is either an ENTER key or a click\n */\nexport function onClickOrEnter(evt:JQuery.TriggeredEvent, callback:() => void) {\n if (evt.type === 'click' || (evt.type === 'keydown' && evt.which === keyCodes.ENTER)) {\n callback();\n return false;\n }\n\n return true;\n}\n\n\nexport abstract class ClickOrEnterHandler {\n public handleEvent(view:TableEventComponent, evt:JQuery.TriggeredEvent) {\n onClickOrEnter(evt, () => this.processEvent(view.workPackageTable, evt));\n }\n\n protected abstract processEvent(table:WorkPackageTable, evt:JQuery.TriggeredEvent):boolean;\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Component, Input, OnInit} from '@angular/core';\nimport {UIRouterGlobals} from '@uirouter/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {randomString} from \"core-app/helpers/random-string\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-subject',\n templateUrl: './wp-subject.html'\n})\nexport class WorkPackageSubjectComponent extends UntilDestroyedMixin implements OnInit {\n @Input('workPackage') workPackage:WorkPackageResource;\n\n public readonly uniqueElementIdentifier = `work-packages--subject-type-row-${randomString(16)}`;\n\n constructor(protected uiRouterGlobals:UIRouterGlobals,\n protected apiV3Service:APIV3Service) {\n super();\n }\n\n ngOnInit() {\n if (!this.workPackage) {\n this\n .apiV3Service\n .work_packages\n .id(this.uiRouterGlobals.params['workPackageId'])\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n });\n }\n }\n}\n","
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {ChangeDetectorRef, Component, ElementRef, Inject, OnInit, ViewChild} from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {HttpClient, HttpErrorResponse, HttpResponse} from '@angular/common/http';\nimport {interval, Observable, timer} from \"rxjs\";\nimport {map, switchMap, takeUntil, takeWhile} from \"rxjs/operators\";\nimport {\n LoadingIndicatorService,\n withDelayedLoadingIndicator\n} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {JobStatusEnum, JobStatusInterface} from \"core-app/modules/job-status/job-status.interface\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Component({\n templateUrl: './job-status.modal.html',\n styleUrls: ['./job-status.modal.sass']\n})\nexport class JobStatusModal extends OpModalComponent implements OnInit {\n\n /* Close on escape? */\n public closeOnEscape = false;\n\n /* Close on outside click */\n public closeOnOutsideClick = false;\n\n public text = {\n title: this.I18n.t('js.job_status.title'),\n closePopup: this.I18n.t('js.close_popup_title'),\n redirect: this.I18n.t('js.job_status.redirect'),\n redirect_errors: this.I18n.t('js.job_status.redirect_errors') + ' ',\n redirect_link: this.I18n.t('js.job_status.redirect_link'),\n errors: this.I18n.t('js.job_status.errors'),\n download_starts: this.I18n.t('js.job_status.download_starts'),\n click_to_download: this.I18n.t('js.job_status.click_to_download'),\n };\n\n /** The job ID reference */\n public jobId:string;\n\n /** Whether to show the loading indicator */\n public isLoading = false;\n\n /** The current status */\n public status:JobStatusEnum;\n\n /** An associated icon to render, if any */\n public statusIcon:string|null;\n\n /** Public message to show */\n public message:string;\n\n /** Payload object of the response */\n public payload:any;\n\n /** Title to show */\n public title:string = this.text.title;\n\n /** A link in case the job results in a download */\n public downloadHref:string|null = null;\n\n @ViewChild('downloadLink') private downloadLink:ElementRef;\n\n constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService,\n readonly elementRef:ElementRef,\n readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly notifications:NotificationsService,\n readonly httpClient:HttpClient) {\n super(locals, cdRef, elementRef);\n\n this.jobId = locals.jobId;\n }\n\n ngOnInit() {\n super.ngOnInit();\n this.listenOnJobStatus();\n }\n\n private listenOnJobStatus() {\n timer(0, 2000)\n .pipe(\n switchMap(() => this.performRequest()),\n takeWhile(response => !!response.body && this.continuedStatus(response.body), true),\n this.untilDestroyed(),\n withDelayedLoadingIndicator(this.loadingIndicator.getter('modal')),\n ).subscribe(\n response => this.onResponse(response),\n error => this.handleError(error),\n () => this.isLoading = false\n );\n }\n\n private iconForStatus():string|null {\n switch (this.status) {\n case \"cancelled\":\n case \"failure\":\n case \"error\":\n return 'icon-error';\n break;\n case \"success\":\n return \"icon-checkmark\";\n break;\n default:\n return null;\n }\n }\n\n /**\n * Determine whether the given status continues the timer\n * @param response\n */\n private continuedStatus(response:JobStatusInterface) {\n return ['in_queue', 'in_process'].includes(response.status);\n }\n\n private onResponse(response:HttpResponse) {\n let body = response.body;\n\n if (!body) {\n throw new Error(response as any);\n }\n\n let status = this.status = body.status;\n\n this.message = body.message ||\n this.I18n.t(`js.job_status.generic_messages.${status}`, { defaultValue: status });\n\n this.payload = body.payload;\n if (body.payload) {\n this.title = body.payload.title || this.text.title;\n this.handleRedirect(body.payload);\n this.handleDownload(body.payload?.download);\n }\n\n this.statusIcon = this.iconForStatus();\n this.cdRef.detectChanges();\n }\n\n private handleRedirect(payload:any) {\n if (payload?.redirect && !payload?.errors) {\n setTimeout(() => window.location.href = payload.redirect, 2000);\n this.message += `. ${this.text.redirect}`;\n }\n }\n\n private handleDownload(downloadUrl?:string) {\n if (downloadUrl !== undefined) {\n this.downloadHref = downloadUrl;\n // Click download link manually\n setTimeout(() => this.downloadLink.nativeElement.click(), 50);\n }\n }\n\n private performRequest():Observable> {\n return this\n .httpClient\n .get(\n this.jobUrl,\n { observe: 'response', responseType: 'json' }\n );\n }\n\n private handleError(error:HttpErrorResponse) {\n if (error?.status === 404) {\n this.statusIcon = 'icon-help';\n this.message = this.I18n.t('js.job_status.generic_messages.not_found');\n return;\n }\n\n\n this.statusIcon = 'icon-error';\n this.message = error?.message || this.I18n.t('js.error.internal');\n this.notifications.addError(this.message);\n }\n\n private get jobUrl():string {\n return this.apiV3Service.job_statuses.id(this.jobId).toString();\n }\n}\n","
    \n
    \n
    \n

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

    \n
      \n
    • \n
    \n\n

    \n \n \n \n

    \n
    \n
    \n
    \n
    \n
    \n","import {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {EditFormComponent} from 'core-app/modules/fields/edit/edit-form/edit-form.component';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\n\n@Component({\n templateUrl: './form.component.html',\n selector: 'te-form',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TimeEntryFormComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n @Input() changeset:ResourceChangeset;\n @Input() showWorkPackageField:boolean = true;\n\n @Output() modifiedEntry = new EventEmitter<{ savedResource:TimeEntryResource, isInital:boolean }>();\n\n @ViewChild('editForm', { static: true }) editForm:EditFormComponent;\n\n text = {\n attributes: {\n comment: this.i18n.t('js.time_entry.comment'),\n hours: this.i18n.t('js.time_entry.hours'),\n activity: this.i18n.t('js.time_entry.activity'),\n workPackage: this.i18n.t('js.time_entry.work_package'),\n spentOn: this.i18n.t('js.time_entry.spent_on'),\n },\n wpRequired: this.i18n.t('js.time_entry.work_package_required')\n };\n\n public workPackageSelected:boolean = false;\n public customFields:{ key:string, label:string }[] = [];\n\n constructor(readonly halEditing:HalResourceEditingService,\n readonly cdRef:ChangeDetectorRef,\n readonly i18n:I18nService) {\n super();\n }\n\n ngOnInit() {\n this.halEditing\n .temporaryEditResource(this.changeset.projectedResource)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(changeset => {\n if (changeset && changeset.workPackage) {\n this.workPackageSelected = true;\n this.cdRef.markForCheck();\n }\n });\n\n this.setCustomFields();\n this.cdRef.detectChanges();\n }\n\n public get entry() {\n return this.changeset.projectedResource;\n }\n\n public signalModifiedEntry($event:{ savedResource:HalResource, isInital:boolean }) {\n this.modifiedEntry.emit($event as { savedResource:TimeEntryResource, isInital:boolean });\n }\n\n public save() {\n return this.editForm.submit();\n }\n\n public get inEditMode() {\n // For now, we always want the form in edit mode.\n // Alternatively, this.entry.isNew can be used.\n return true;\n }\n\n public isRequired(field:string) {\n // Other than defined in the schema, we consider the work package to be required.\n // Remove once the schema requires it explicitly.\n if (field === 'workPackage') {\n return true;\n } else {\n return this.schema.ofProperty(field).required;\n }\n }\n\n private setCustomFields() {\n Object.entries(this.schema).forEach(([key, keySchema]) => {\n if (key.match(/customField\\d+/)) {\n this.customFields.push({ key: key, label: keySchema.name });\n }\n });\n }\n\n private get schema() {\n return this.changeset.schema;\n }\n}\n","\n
    \n\n
    \n
    \n
    \n \n \n
    \n\n
    \n
    \n
    \n \n \n
    \n\n
    \n
    \n
    \n \n \n
    \n\n
    \n
    \n
    \n \n \n \n \n
    \n\n
    \n
    \n
    \n \n \n
    \n\n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {WorkPackageCollectionResource} from 'core-app/modules/hal/resources/wp-collection-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {PaginationObject, PaginationService} from 'core-components/table-pagination/pagination-service';\nimport {WorkPackageViewPagination} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-table-pagination\";\nimport {WorkPackageViewBaseService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service\";\n\nexport interface PaginationUpdateObject {\n page?:number;\n perPage?:number;\n total?:number;\n count?:number;\n}\n\n@Injectable()\nexport class WorkPackageViewPaginationService extends WorkPackageViewBaseService {\n public constructor(querySpace:IsolatedQuerySpace,\n readonly paginationService:PaginationService) {\n super(querySpace);\n }\n\n public get paginationObject():PaginationObject {\n if (this.current) {\n return {\n pageSize: this.current.perPage,\n offset: this.current.page\n };\n } else {\n return {\n pageSize: this.paginationService.getCachedPerPage([]),\n offset: 1\n };\n }\n\n }\n\n public valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource) {\n return new WorkPackageViewPagination(results);\n }\n\n public updateFromObject(object:PaginationUpdateObject) {\n let currentState = this.current;\n\n if (object.page) {\n currentState.page = object.page;\n }\n if (object.perPage) {\n currentState.perPage = object.perPage;\n }\n if (object.total) {\n currentState.total = object.total;\n }\n\n this.updatesState.putValue(currentState);\n }\n\n public updateFromResults(results:WorkPackageCollectionResource) {\n let update = {\n page: results.offset,\n perPage: results.pageSize,\n total: results.total,\n count: results.count\n };\n\n this.updateFromObject(update);\n }\n\n public get current():WorkPackageViewPagination {\n return this.lastUpdatedState.value!;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {HttpClient, HttpEvent, HttpEventType, HttpResponse} from \"@angular/common/http\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Observable} from \"rxjs\";\nimport {filter, map, share} from \"rxjs/operators\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\n\nexport interface UploadFile extends File {\n description?:string;\n customName?:string;\n}\n\n\nexport interface UploadBlob extends Blob {\n description?:string;\n customName?:string;\n name?:string;\n}\n\nexport type UploadHttpEvent = HttpEvent;\nexport type UploadInProgress = [UploadFile, Observable];\n\nexport interface UploadResult {\n uploads:UploadInProgress[];\n finished:Promise;\n}\n\nexport interface MappedUploadResult {\n uploads:UploadInProgress[];\n finished:Promise<{ response:any, uploadUrl:string }[]>;\n}\n\n@Injectable()\nexport class OpenProjectFileUploadService {\n constructor(protected http:HttpClient,\n protected halResource:HalResourceService) {\n }\n\n /**\n * Upload multiple files and return a promise for each uploading file and a single promise for all processed uploads\n * with their accessible URLs returned.\n * @param {string} url\n * @param {UploadFile[]} files\n * @param {string} method\n * @returns {Promise<{response:HalResource; uploadUrl:any}[]>}\n */\n public uploadAndMapResponse(url:string, files:UploadFile[], method:string = 'post') {\n const { uploads, finished } = this.upload(url, files);\n const mapped = finished\n .then((result:HalResource[]) => result.map((el:HalResource) => {\n return { response: el, uploadUrl: el.staticDownloadLocation.href };\n })) as Promise<{ response:HalResource, uploadUrl:string }[]>;\n\n return { uploads: uploads, finished: mapped } as MappedUploadResult;\n }\n\n /**\n * Upload multiple files and return a promise for each uploading file and a single promise for all processed uploads\n * Ignore directories.\n */\n public upload(url:string, files:UploadFile[], method:string = 'post'):UploadResult {\n files = _.filter(files, (file:UploadFile) => file.type !== 'directory');\n const uploads:UploadInProgress[] = _.map(files, (file:UploadFile) => this.uploadSingle(url, file, method));\n\n const finished = this.whenFinished(uploads);\n return {uploads, finished} as UploadResult;\n }\n\n /**\n * Upload a single file, get an UploadResult observable\n * @param {string} url\n * @param {UploadFile} file\n * @param {string} method\n */\n public uploadSingle(url:string, file:UploadFile|UploadBlob, method:string = 'post', responseType:'text'|'json' = 'json') {\n const formData = new FormData();\n const metadata = {\n description: file.description,\n fileName: file.customName || file.name\n };\n\n // add the metadata object\n formData.append(\n 'metadata',\n JSON.stringify(metadata),\n );\n\n // Add the file\n formData.append('file', file, metadata.fileName);\n\n const observable = this\n .http\n .request(\n method,\n url,\n {\n body: formData,\n // Observe the response, not the body\n observe: 'events',\n withCredentials: true,\n responseType: responseType as any,\n // Subscribe to progress events. subscribe() will fire multiple times!\n reportProgress: true\n }\n )\n .pipe(\n share()\n );\n\n return [file, observable] as UploadInProgress;\n }\n\n /**\n * Create a promise for all uploaded responses when all uploads are fully uploaded.\n *\n * @param {UploadInProgress[]} uploads\n */\n private whenFinished(uploads:UploadInProgress[]):Promise {\n const promises = uploads.map(([_, observable]) => {\n return observable\n .pipe(\n filter((evt) => evt.type === HttpEventType.Response),\n map((evt:HttpResponse) => this.halResource.createHalResource(evt.body))\n )\n .toPromise();\n });\n\n return Promise.all(promises);\n }\n}\n","
    \n
    \n
    \n \n \n\n \n \n\n
      \n\n \n
    • \n \n \n
    • \n
      \n
    \n
    \n
    \n\n
    \n \n \n
    \n\n
    \n \n
    \n
    \n\n \n
    \n
    \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from \"@angular/core\";\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {OpTitleService} from \"core-components/html/op-title.service\";\nimport {WorkPackagesViewBase} from \"core-app/modules/work_packages/routing/wp-view-base/work-packages-view.base\";\nimport {take} from \"rxjs/operators\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {QueryParamListenerService} from \"core-components/wp-query/query-param-listener.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {ComponentType} from \"@angular/cdk/overlay\";\nimport {Ng2StateDeclaration} from \"@uirouter/angular\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageFilterContainerComponent} from \"core-components/filters/filter-container/filter-container.directive\";\n\nexport interface DynamicComponentDefinition {\n component:ComponentType;\n inputs?:{ [inputName:string]:any };\n outputs?:{ [outputName:string]:Function };\n}\n\nexport interface ToolbarButtonComponentDefinition extends DynamicComponentDefinition {\n containerClasses?:string;\n show?:() => boolean;\n}\n\nexport type ViewPartitionState = '-split'|'-left-only'|'-right-only';\n\n@Component({\n selector: 'partitioned-query-space-page',\n templateUrl: './partitioned-query-space-page.component.html',\n styleUrls: ['./partitioned-query-space-page.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n /** We need to provide the wpNotification service here to get correct save notifications for WP resources */\n { provide: HalResourceNotificationService, useClass: WorkPackageNotificationService },\n QueryParamListenerService\n ]\n})\nexport class PartitionedQuerySpacePageComponent extends WorkPackagesViewBase implements OnInit, OnDestroy {\n @InjectField() I18n:I18nService;\n @InjectField() titleService:OpTitleService;\n @InjectField() queryParamListener:QueryParamListenerService;\n\n text:{ [key:string]:string } = {\n 'jump_to_pagination': this.I18n.t('js.work_packages.jump_marks.pagination'),\n 'text_jump_to_pagination': this.I18n.t('js.work_packages.jump_marks.label_pagination'),\n };\n\n /** Whether the title can be edited */\n titleEditingEnabled:boolean;\n\n /** Current query title to render */\n selectedTitle?:string;\n currentQuery:QueryResource|undefined;\n\n /** Whether we're saving the query */\n toolbarDisabled:boolean;\n\n /** Do we currently have query props ? */\n showToolbarSaveButton:boolean;\n\n /** Listener callbacks */\n unRegisterTitleListener:Function;\n removeTransitionSubscription:Function;\n\n /** Determine when query is initially loaded */\n showToolbar = false;\n\n /** The toolbar buttons to render */\n toolbarButtonComponents:ToolbarButtonComponentDefinition[] = [];\n\n /** Whether filtering is allowed */\n filterAllowed:boolean = true;\n\n /** We need to pass the correct partition state to the view to manage the grid */\n currentPartition:ViewPartitionState = '-split';\n\n /** What route (if any) should we go back to using the back button left of the title? */\n backButtonCallback:Function|undefined;\n\n /** Which filter container component to mount */\n filterContainerDefinition:DynamicComponentDefinition = {\n component: WorkPackageFilterContainerComponent\n };\n\n ngOnInit() {\n super.ngOnInit();\n\n this.showToolbarSaveButton = !!this.$state.params.query_props;\n this.setPartition(this.$state.current);\n this.removeTransitionSubscription = this.$transitions.onSuccess({}, (transition):any => {\n const params = transition.params('to');\n const toState = transition.to();\n this.showToolbarSaveButton = !!params.query_props;\n this.setPartition(toState);\n this.cdRef.detectChanges();\n });\n\n // If the query was loaded, reload invisibly\n const isFirstLoad = !this.querySpace.initialized.hasValue();\n this.refresh(isFirstLoad, isFirstLoad);\n\n // Mark tableInformationLoaded when initially loading done\n this.setupInformationLoadedListener();\n\n // Load query on URL transitions\n this.queryParamListener\n .observe$\n .pipe(\n this.untilDestroyed()\n ).subscribe(() => {\n /** Ensure we reload the query from the changed props */\n this.currentQuery = undefined;\n this.refresh(true, true);\n });\n\n // Update title on entering this state\n this.unRegisterTitleListener = this.$transitions.onSuccess({}, () => {\n this.updateTitle(this.querySpace.query.value);\n });\n\n this.querySpace.query.values$().pipe(\n this.untilDestroyed()\n ).subscribe((query) => {\n this.onQueryUpdated(query);\n });\n }\n\n /**\n * We need to set the current partition to the grid to ensure\n * either side gets expanded to full width if we're not in '-split' mode.\n *\n * @param state The current or entering state\n */\n protected setPartition(state:Ng2StateDeclaration) {\n this.currentPartition = (state.data && state.data.partition) ? state.data.partition : '-split';\n }\n\n protected setupInformationLoadedListener() {\n this\n .querySpace\n .initialized\n .values$()\n .pipe(take(1))\n .subscribe(() => {\n this.showToolbar = true;\n this.cdRef.detectChanges();\n });\n }\n\n protected onQueryUpdated(query:QueryResource) {\n // Update the title whenever the query changes\n this.updateTitle(query);\n this.currentQuery = query;\n\n this.cdRef.detectChanges();\n }\n\n ngOnDestroy():void {\n super.ngOnDestroy();\n this.unRegisterTitleListener();\n this.removeTransitionSubscription();\n this.queryParamListener.removeQueryChangeListener();\n }\n\n public changeChangesFromTitle(val:string) {\n if (this.currentQuery && this.currentQuery.persisted) {\n this.updateTitleName(val);\n } else {\n this.wpListService\n .create(this.currentQuery!, val)\n .then(() => this.toolbarDisabled = false)\n .catch(() => this.toolbarDisabled = false);\n }\n }\n\n updateTitleName(val:string) {\n this.toolbarDisabled = true;\n this.currentQuery!.name = val;\n this.wpListService.save(this.currentQuery)\n .then(() => this.toolbarDisabled = false)\n .catch(() => this.toolbarDisabled = false);\n }\n\n updateTitle(query?:QueryResource) {\n\n // Too early for loaded query\n if (!query) {\n return;\n }\n\n\n if (query.persisted) {\n this.selectedTitle = query.name;\n } else {\n this.selectedTitle = this.wpStaticQueries.getStaticName(query);\n }\n\n this.titleEditingEnabled = this.authorisationService.can('query', 'updateImmediately');\n\n // Update the title if we're in the list state alone\n if (this.shouldUpdateHtmlTitle()) {\n this.titleService.setFirstPart(this.selectedTitle);\n }\n }\n\n refresh(visibly:boolean = false, firstPage:boolean = false):Promise {\n let promise:Promise;\n let query = this.currentQuery;\n\n if (firstPage || !query) {\n promise = this.loadFirstPage();\n } else {\n let pagination = this.wpListService.getPaginationInfo();\n promise = this.wpListService\n .loadQueryFromExisting(query, pagination, this.projectIdentifier)\n .toPromise();\n }\n\n if (visibly) {\n return this.loadingIndicator = promise.then((loadedQuery:QueryResource) => {\n this.wpStatesInitialization.initialize(loadedQuery, loadedQuery.results);\n return this.additionalLoadingTime();\n });\n }\n\n return promise.then((loadedQuery:QueryResource) => {\n this.wpStatesInitialization.initialize(loadedQuery, loadedQuery.results);\n });\n }\n\n protected loadFirstPage():Promise {\n if (this.currentQuery) {\n return this.wpListService.reloadQuery(this.currentQuery, this.projectIdentifier).toPromise();\n } else {\n return this.wpListService.loadCurrentQueryFromParams(this.projectIdentifier);\n }\n }\n\n protected additionalLoadingTime():Promise {\n return Promise.resolve();\n }\n\n protected set loadingIndicator(promise:Promise) {\n this.loadingIndicatorService.table.promise = promise;\n }\n\n protected shouldUpdateHtmlTitle():boolean {\n return true;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\n\nimport {QueryFilterResource} from 'core-app/modules/hal/resources/query-filter-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {Component, Input, Output} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {DebouncedEventEmitter} from 'core-components/angular/debounced-event-emitter';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Component({\n selector: 'filter-integer-value',\n templateUrl: './filter-integer-value.component.html'\n})\nexport class FilterIntegerValueComponent extends UntilDestroyedMixin {\n @Input() public shouldFocus:boolean = false;\n @Input() public filter:QueryFilterInstanceResource;\n @Output() public filterChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n constructor(readonly I18n:I18nService,\n readonly schemaCache:SchemaCacheService) {\n super();\n }\n\n public get value() {\n return parseInt(this.filter.values[0] as string);\n }\n\n public set value(val) {\n if (typeof (val) === 'number') {\n this.filter.values = [val.toString()];\n } else {\n this.filter.values = [];\n }\n\n this.filterChanged.emit(this.filter);\n }\n\n public get unit() {\n switch ((this.schema.filter.allowedValues as QueryFilterResource[])[0].id) {\n case 'startDate':\n case 'dueDate':\n case 'updatedAt':\n case 'createdAt':\n return this.I18n.t('js.work_packages.time_relative.days');\n default:\n return '';\n }\n }\n\n private get schema() {\n return this.schemaCache.of(this.filter);\n }\n}\n","
    \n \n \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input,\n OnInit\n} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {distinctUntilChanged, map} from 'rxjs/operators';\nimport {debugLog} from '../../../helpers/debug_output';\nimport {CurrentProjectService} from '../../projects/current-project.service';\nimport {States} from '../../states.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DisplayFieldService} from 'core-app/modules/fields/display/display-field.service';\nimport {DisplayField} from 'core-app/modules/fields/display/display-field.module';\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {HookService} from 'core-app/modules/plugins/hook-service';\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport {Subject} from \"rxjs\";\nimport {randomString} from \"core-app/helpers/random-string\";\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {ISchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport interface FieldDescriptor {\n name:string;\n label:string;\n field?:DisplayField;\n fields?:DisplayField[];\n spanAll:boolean;\n multiple:boolean;\n}\n\nexport interface GroupDescriptor {\n name:string;\n id:string;\n members:FieldDescriptor[];\n query?:QueryResource;\n relationType?:string;\n isolated:boolean;\n type:string;\n}\n\nexport interface ResourceContextChange {\n isNew:boolean;\n schema:string|null;\n project:string|null;\n}\n\nexport const overflowingContainerAttribute = 'overflowingIdentifier';\n\n@Component({\n templateUrl: './wp-single-view.html',\n selector: 'wp-single-view',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageSingleViewComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n\n /** Should we show the project field */\n @Input() public showProject:boolean = false;\n\n // Grouped fields returned from API\n public groupedFields:GroupDescriptor[] = [];\n\n // State updated when structural changes to the single view may occur.\n // (e.g., when changing the type or project context).\n public resourceContextChange = new Subject();\n\n // Project context as an indicator\n // when editing the work package in a different project\n public projectContext:{\n matches:boolean,\n href:string|null,\n field?:FieldDescriptor[]\n };\n public text = {\n attachments: {\n label: this.I18n.t('js.label_attachments')\n },\n project: {\n required: this.I18n.t('js.project.required_outside_context'),\n context: this.I18n.t('js.project.context'),\n switchTo: this.I18n.t('js.project.click_to_switch_context'),\n },\n\n fields: {\n description: this.I18n.t('js.work_packages.properties.description'),\n },\n infoRow: {\n createdBy: this.I18n.t('js.label_created_by'),\n lastUpdatedOn: this.I18n.t('js.label_last_updated_on')\n },\n };\n\n protected firstTimeFocused:boolean = false;\n\n $element:JQuery;\n\n constructor(readonly I18n:I18nService,\n protected currentProject:CurrentProjectService,\n protected PathHelper:PathHelperService,\n protected states:States,\n protected halEditing:HalResourceEditingService,\n protected halResourceService:HalResourceService,\n protected displayFieldService:DisplayFieldService,\n protected schemaCache:SchemaCacheService,\n protected hook:HookService,\n protected injector:Injector,\n protected cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef,\n readonly browserDetector:BrowserDetector) {\n super();\n }\n\n public ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n const change = this.halEditing.changeFor(this.workPackage);\n this.resourceContextChange.next(this.contextFrom(change.projectedResource));\n this.refresh(change);\n\n // Whenever the resource context changes in any way,\n // update the visible fields.\n this.resourceContextChange\n .pipe(\n this.untilDestroyed(),\n distinctUntilChanged((a, b) => _.isEqual(a, b)),\n map(() => this.halEditing.changeFor(this.workPackage))\n )\n .subscribe((change:WorkPackageChangeset) => this.refresh(change));\n\n // Update the resource context on every update to the temporary resource.\n // This allows detecting a changed type value in a new work package.\n this.halEditing\n .temporaryEditResource(this.workPackage)\n .values$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(resource => {\n this.resourceContextChange.next(this.contextFrom(resource));\n });\n }\n\n private refresh(change:WorkPackageChangeset) {\n // Prepare the fields that are required always\n const isNew = this.workPackage.isNew;\n const resource = change.projectedResource;\n\n if (!resource.project) {\n this.projectContext = { matches: false, href: null };\n } else {\n this.projectContext = {\n href: this.PathHelper.projectWorkPackagePath(resource.project.idFromLink, this.workPackage.id!),\n matches: resource.project.href === this.currentProject.apiv3Path\n };\n }\n\n if (isNew && !this.currentProject.inProjectContext) {\n this.projectContext.field = this.getFields(change, ['project']);\n }\n\n const attributeGroups = this.schema(resource)._attributeGroups;\n this.groupedFields = this.rebuildGroupedFields(change, attributeGroups);\n this.cdRef.detectChanges();\n }\n\n /**\n * Returns whether a group should be hidden due to being empty\n * (e.g., consists only of CFs and none of them are active in this project.\n */\n public shouldHideGroup(group:GroupDescriptor) {\n // Hide if the group is empty\n const isEmpty = group.members.length === 0;\n\n // Is a query in a new screen\n const queryInNew = this.workPackage.isNew && !!group.query;\n\n return isEmpty || queryInNew;\n }\n\n /**\n * angular 2 doesn't support track by property any more but requires a custom function\n * https://github.com/angular/angular/issues/12969\n * @param index\n * @param elem\n */\n public trackByName(_index:number, elem:{ name:string }) {\n return elem.name;\n }\n\n /**\n * Allow other modules to register groups to insert into the single view\n */\n public prependedAttributeGroupComponents() {\n return this.hook.call('prependedAttributeGroups', this.workPackage);\n }\n\n public attributeGroupComponent(group:GroupDescriptor) {\n // we take the last registered group component which means that\n // plugins will have their say if they register for it.\n return this.hook.call('attributeGroupComponent', group, this.workPackage).pop() || null;\n }\n\n public attachmentListComponent() {\n // we take the last registered group component which means that\n // plugins will have their say if they register for it.\n return this.hook.call('workPackageAttachmentListComponent', this.workPackage).pop() || null;\n }\n\n public attachmentUploadComponent() {\n // we take the last registered group component which means that\n // plugins will have their say if they register for it.\n return this.hook.call('workPackageAttachmentUploadComponent', this.workPackage).pop() || null;\n }\n\n /*\n * Returns the work package label\n */\n public get idLabel() {\n return `#${this.workPackage.id}`;\n }\n\n public get projectContextText():string {\n let id = this.workPackage.project.idFromLink;\n let projectPath = this.PathHelper.projectPath(id);\n let project = `${this.workPackage.project.name}`;\n return this.I18n.t('js.project.work_package_belongs_to', { projectname: project });\n }\n\n /*\n * Show two column layout for new WP per default, but disable in MS Edge (#29941)\n */\n public get enableTwoColumnLayout() {\n return this.workPackage.isNew && !this.browserDetector.isEdge;\n }\n\n private rebuildGroupedFields(change:WorkPackageChangeset, attributeGroups:any) {\n if (!attributeGroups) {\n return [];\n }\n\n return attributeGroups.map((group:any) => {\n let groupId = this.getAttributesGroupId(group);\n\n if (group._type === 'WorkPackageFormAttributeGroup') {\n return {\n name: group.name,\n id: groupId || randomString(16),\n members: this.getFields(change, group.attributes),\n type: group._type,\n isolated: false\n };\n } else {\n return {\n name: group.name,\n id: groupId || randomString(16),\n query: this.halResourceService.createHalResourceOfClass(QueryResource, group._embedded.query),\n relationType: group.relationType,\n members: [group._embedded.query],\n type: group._type,\n isolated: true\n };\n }\n });\n }\n\n /**\n * Maps the grouped fields into their display fields.\n * May return multiple fields (for the date virtual field).\n */\n private getFields(change:WorkPackageChangeset, fieldNames:string[]):FieldDescriptor[] {\n const descriptors:FieldDescriptor[] = [];\n\n fieldNames.forEach((fieldName:string) => {\n if (fieldName === 'date') {\n descriptors.push(this.getDateField(change));\n return;\n }\n\n if (!change.schema.ofProperty(fieldName)) {\n debugLog('Unknown field for current schema', fieldName);\n return;\n }\n\n const field:DisplayField = this.displayField(change, fieldName);\n descriptors.push({\n name: fieldName,\n label: field.label,\n multiple: false,\n spanAll: field.isFormattable,\n field: field\n });\n });\n\n return descriptors;\n }\n\n /**\n * We need to discern between milestones, which have a single\n * 'date' field vs. all other types which should display a\n * combined 'start' and 'due' date field.\n */\n private getDateField(change:WorkPackageChangeset):FieldDescriptor {\n let object:any = {\n label: this.I18n.t('js.work_packages.properties.date'),\n multiple: false\n };\n\n if (change.schema.ofProperty('date')) {\n object.field = this.displayField(change, 'date');\n object.name = 'date';\n } else {\n object.field = this.displayField(change, 'combinedDate');\n object.name = 'combinedDate';\n }\n\n return object;\n }\n\n /**\n * Get the current resource context change from the WP resource.\n * Used to identify changes in the schema or project that may result in visual changes\n * to the single view.\n *\n * @param {WorkPackage} workPackage\n * @returns {SchemaContext}\n */\n private contextFrom(workPackage:WorkPackageResource):ResourceContextChange {\n let schema = this.schema(workPackage);\n\n let schemaHref:string|null = null;\n let projectHref:string|null = workPackage.project && workPackage.project.href;\n\n if (schema.baseSchema) {\n schemaHref = schema.baseSchema.href;\n } else {\n schemaHref = schema.href;\n }\n\n\n return {\n isNew: workPackage.isNew,\n schema: schemaHref,\n project: projectHref\n };\n }\n\n private displayField(change:WorkPackageChangeset, name:string):DisplayField {\n return this.displayFieldService.getField(\n change.projectedResource,\n name,\n change.schema.ofProperty(name),\n { container: 'single-view', injector: this.injector, options: {} }\n ) as DisplayField;\n }\n\n private getAttributesGroupId(group:any):string {\n let overflowingIdentifier = this.$element\n .find(\"[data-group-name=\\'\" + group.name + \"\\']\")\n .data(overflowingContainerAttribute);\n\n if (overflowingIdentifier) {\n return overflowingIdentifier.replace('.__overflowing_', '');\n } else {\n return '';\n }\n }\n\n private schema(resource:WorkPackageResource) {\n if (this.halEditing.typedState(resource).hasValue()) {\n return this.halEditing.typedState(this.workPackage).value!.schema;\n } else {\n return this.schemaCache.of(resource) as ISchemaProxy;\n }\n }\n}\n","\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 {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {HighlightableDisplayField} from \"core-app/modules/fields/display/field-types/highlightable-display-field.module\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class DateDisplayField extends HighlightableDisplayField {\n @InjectField() timezoneService:TimezoneService;\n @InjectField() apiV3Service:APIV3Service;\n\n public render(element:HTMLElement, displayText:string):void {\n super.render(element, displayText);\n\n // Show scheduling mode in front of the start date field\n if (this.showSchedulingMode()) {\n const schedulingIcon = document.createElement('span');\n schedulingIcon.classList.add('icon-context');\n\n if (this.resource.scheduleManually) {\n schedulingIcon.classList.add('icon-pin');\n }\n\n element.prepend(schedulingIcon);\n }\n\n // Highlight overdue tasks\n if (this.shouldHighlight && this.canOverdue) {\n const diff = this.timezoneService.daysFromToday(this.value);\n\n this\n .apiV3Service\n .statuses\n .id(this.resource.status.id)\n .get()\n .toPromise()\n .then((status) => {\n if (!status.isClosed) {\n element.classList.add(Highlighting.overdueDate(diff));\n }\n });\n }\n }\n\n public get canOverdue():boolean {\n return ['dueDate', 'date'].indexOf(this.name) !== -1;\n }\n\n public get valueString() {\n if (this.value) {\n return this.timezoneService.formattedDate(this.value);\n } else {\n return '';\n }\n }\n\n private showSchedulingMode():boolean {\n return this.name === 'startDate' || this.name === 'date';\n }\n}\n","import {APIv3ResourcePath} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {Observable} from \"rxjs\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\n\nexport class APIv3FormResource extends APIv3ResourcePath {\n /**\n * POST to the form resource identified by this path\n * @param request The request payload\n */\n public post(request:Object = {}, schema:SchemaResource|null = null):Observable {\n return this\n .halResourceService\n .post(\n this.path,\n this.extractPayload(request, schema)\n );\n }\n\n /**\n * Extract payload for the form from the request and optional schema.\n *\n * @param request\n * @param schema\n */\n public extractPayload(request:T|Object, schema:SchemaResource|null = null) {\n return HalPayloadHelper.extractPayload(request, schema);\n }\n}","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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\nfunction createFieldsetToggleStateLabel(legend:JQuery, text:string) {\n var labelClass = 'fieldset-toggle-state-label';\n var toggleLabel = legend.find('a span.' + labelClass);\n var legendLink = legend.children('a');\n\n if (toggleLabel.length === 0) {\n toggleLabel = jQuery(\"\").addClass(labelClass)\n .addClass(\"hidden-for-sighted\");\n\n legendLink.append(toggleLabel);\n }\n\n toggleLabel.text(' ' + text);\n}\n\nfunction setFieldsetToggleState(fieldset:JQuery) {\n var legend = fieldset.children('legend');\n\n\n if (fieldset.hasClass('collapsed')) {\n createFieldsetToggleStateLabel(legend, I18n.t('js.label_collapsed'));\n } else {\n createFieldsetToggleStateLabel(legend, I18n.t('js.label_expanded'));\n }\n}\n\nfunction getFieldset(el:HTMLElement) {\n var element = jQuery(el);\n\n if (element.is('legend')) {\n return jQuery(el).parent();\n } else if (element.is('fieldset')) {\n return element;\n }\n\n throw \"Cannot derive fieldset from element!\";\n}\n\nfunction toggleFieldset(el:HTMLElement) {\n var fieldset = getFieldset(el);\n // Mark the fieldset that the user has touched it at least once\n fieldset.attr('data-touched', 'true');\n var contentArea = fieldset.find('> div').not('.form--toolbar');\n\n fieldset.toggleClass('collapsed');\n contentArea.slideToggle('fast');\n\n setFieldsetToggleState(fieldset);\n}\n\nexport function setupToggableFieldsets() {\n const fieldsets = jQuery('fieldset.form--fieldset.-collapsible');\n\n // Toggle on click\n fieldsets.on('click', '.form--fieldset-legend', function(evt) {\n toggleFieldset(this);\n evt.preventDefault();\n evt.stopPropagation();\n return false;\n });\n\n // Set initial state\n fieldsets\n .each(function() {\n var fieldset = getFieldset(this);\n\n let contentArea = fieldset.find('> div');\n if (fieldset.hasClass('collapsed')) {\n contentArea.hide();\n }\n\n setFieldsetToggleState(fieldset);\n });\n}\n","// Legacy code ported from app/assets/javascripts/application.js.erb\n// Do not add stuff here, but ideally remove into components whenver changes are necessary\nexport function setupServerResponse() {\n initMainMenuExpandStatus();\n focusFirstErroneousField();\n activateFlashNotice();\n activateFlashError();\n autoHideFlashMessage();\n flashCloseHandler();\n\n jQuery(document).ajaxComplete(activateFlashNotice);\n jQuery(document).ajaxComplete(activateFlashError);\n\n /*\n * 1 - registers a callback which copies the csrf token into the\n * X-CSRF-Token header with each ajax request. Necessary to\n * work with rails applications which have fixed\n * CVE-2011-0447\n * 2 - shows and hides ajax indicator\n */\n jQuery(document).ajaxSend(function (event, request) {\n if (jQuery(event.target.activeElement!).closest('[ajax-indicated]').length &&\n jQuery('ajax-indicator')) {\n jQuery('#ajax-indicator').show();\n }\n\n var csrf_meta_tag = jQuery('meta[name=csrf-token]');\n\n if (csrf_meta_tag) {\n var header = 'X-CSRF-Token',\n token = csrf_meta_tag.attr('content');\n\n request.setRequestHeader(header, token!);\n }\n\n request.setRequestHeader('X-Authentication-Scheme', \"Session\");\n });\n\n // ajaxStop gets called when ALL Requests finish, so we won't need a counter as in PT\n jQuery(document).ajaxStop(function () {\n if (jQuery('#ajax-indicator')) {\n jQuery('#ajax-indicator').hide();\n }\n addClickEventToAllErrorMessages();\n });\n\n // show/hide the files table\n jQuery(\".attachments h4\").click(function () {\n jQuery(this).toggleClass(\"closed\").next().slideToggle(100);\n });\n\n let resizeTo:any = null;\n jQuery(window).on('resize', function () {\n // wait 200 milliseconds for no further resize event\n // then readjust breadcrumb\n\n if (resizeTo) {\n clearTimeout(resizeTo);\n }\n resizeTo = setTimeout(function () {\n jQuery(window).trigger('resizeEnd');\n }, 200);\n });\n\n // Do not close the login window when using it\n jQuery('#nav-login-content').click(function (event) {\n event.stopPropagation();\n });\n\n // Set focus on first error message\n var error_focus = jQuery('a.afocus').first();\n var input_focus = jQuery('.autofocus').first();\n if (error_focus !== undefined) {\n error_focus.focus();\n } else if (input_focus !== undefined) {\n input_focus.focus();\n if (input_focus[0].tagName === \"INPUT\") {\n input_focus.select();\n }\n }\n // Focus on field with error\n addClickEventToAllErrorMessages();\n\n // Click handler for formatting help\n jQuery(document.body).on('click', '.formatting-help-link-button', function () {\n window.open(window.appBasePath + '/help/wiki_syntax',\n \"\",\n \"resizable=yes, location=no, width=600, height=640, menubar=no, status=no, scrollbars=yes\"\n );\n return false;\n });\n}\n\nfunction flashCloseHandler() {\n jQuery('body').on('click keydown touchend', '.close-handler,.notification-box--close', function (e) {\n if (e.type === 'click' || e.which === 13) {\n jQuery(this).parent('.flash, .errorExplanation, .notification-box')\n .not('.persistent-toggle--notification')\n .remove();\n }\n });\n}\n\nfunction autoHideFlashMessage() {\n setTimeout(function () {\n jQuery('.flash.autohide-notification').remove();\n }, 5000);\n}\n\nfunction addClickEventToAllErrorMessages() {\n jQuery('a.afocus').each(function () {\n var target = jQuery(this);\n target.click(function (evt) {\n var field = jQuery('#' + target.attr('href')!.substr(1));\n if (field === null) {\n // Cut off '_id' (necessary for select boxes)\n field = jQuery('#' + target.attr('href')!.substr(1).concat('_id'));\n }\n target.unbind(evt);\n return false;\n });\n });\n}\n\nfunction initMainMenuExpandStatus() {\n let wrapper = jQuery('#wrapper');\n let upToggle = jQuery('ul.menu_root.closed li.open a.arrow-left-to-project');\n\n if (upToggle.length === 1 && wrapper.hasClass('hidden-navigation')) {\n upToggle.trigger('click');\n }\n}\n\nfunction activateFlash(selector:any) {\n let flashMessages = jQuery(selector);\n\n flashMessages.each(function (ix, e) {\n const flashMessage = jQuery(e);\n flashMessage.show();\n });\n}\n\nfunction activateFlashNotice() {\n\n activateFlash('.flash');\n}\n\nfunction activateFlashError() {\n activateFlash('.errorExplanation[role=\"alert\"]');\n}\n\nfunction focusFirstErroneousField() {\n const firstErrorSpan = jQuery('span.errorSpan').first();\n const erroneousInput = firstErrorSpan.find('*').filter(\":input\");\n\n erroneousInput.trigger('focus');\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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\";\nimport {setupToggableFieldsets} from \"core-app/globals/global-listeners/toggable-fieldset\";\nimport {TopMenu} from \"core-app/globals/global-listeners/top-menu\";\nimport {install_menu_logic} from \"core-app/globals/global-listeners/action-menu\";\nimport {makeColorPreviews} from \"core-app/globals/global-listeners/color-preview\";\nimport {dangerZoneValidation} from \"core-app/globals/global-listeners/danger-zone-validation\";\nimport {setupServerResponse} from \"core-app/globals/global-listeners/setup-server-response\";\nimport {listenToSettingChanges} from \"core-app/globals/global-listeners/settings\";\nimport {detectOnboardingTour} from \"core-app/globals/onboarding/onboarding_tour_trigger\";\n\n/**\n * A set of listeners that are relevant on every page to set sensible defaults\n */\n(function ($:JQueryStatic) {\n\n $(function () {\n $(document.documentElement!)\n .on('click', (evt:any) => {\n const target = jQuery(evt.target) as JQuery;\n\n // Create datepickers dynamically for Rails-based views\n augmentedDatePicker(evt, target);\n\n // Prevent angular handling clicks on href=\"#...\" links from other libraries\n // (especially jquery-ui and its datepicker) from routing to /#\n performAnchorHijacking(evt, target);\n\n return true;\n });\n\n // Jump to the element given by location.hash, if present\n const hash = window.location.hash;\n if (hash && hash.startsWith('#')) {\n try {\n const el = document.querySelector(hash);\n el && el.scrollIntoView();\n } catch (e) {\n // This is very likely an invalid selector such as a Google Analytics tag.\n // We can safely ignore this and just not scroll in this case.\n // Still log the error so one can confirm the reason there is no scrolling.\n console.log(\"Could not scroll to given location hash: \" + hash + \" ( \" + e.message + \")\");\n }\n }\n\n // Global submitting hook,\n // necessary to avoid a data loss warning on beforeunload\n $(document).on('submit', 'form', function () {\n window.OpenProject.pageIsSubmitted = true;\n });\n\n // Add to content if warnings displayed\n if (document.querySelector('.warning-bar--item')) {\n let content = document.querySelector('#content') as HTMLElement;\n if (content) {\n content.style.marginBottom = '100px';\n }\n }\n\n // Global beforeunload hook\n $(window).on('beforeunload', (e:JQuery.TriggeredEvent) => {\n const event = e.originalEvent as BeforeUnloadEvent;\n if (window.OpenProject.pageWasEdited && !window.OpenProject.pageIsSubmitted) {\n // Cancel the event\n event.preventDefault();\n // Chrome requires returnValue to be set\n event.returnValue = I18n.t(\"js.work_packages.confirm_edit_cancel\");\n }\n });\n\n // Disable global drag & drop handling, which results in the browser loading the image and losing the page\n $(document.documentElement!)\n .on('dragover drop', (evt:any) => {\n evt.preventDefault();\n return false;\n });\n\n refreshOnFormChanges();\n\n // Allow forms with [request-for-confirmation]\n // to show the password confirmation dialog\n registerRequestForConfirmation($);\n\n const deviceService:DeviceService = new DeviceService();\n // Register scroll handler on mobile header\n if (deviceService.isMobile) {\n scrollHeaderOnMobile();\n }\n\n // Detect and trigger the onboarding tour\n // through a lazy loaded script\n detectOnboardingTour();\n\n //\n // Legacy scripts from app/assets that are not yet component based\n //\n\n // Toggable fieldsets\n setupToggableFieldsets();\n\n // Top menu click handling\n new TopMenu(jQuery('#top-menu-items'));\n\n // Action menu logic\n jQuery('.project-actions, .toolbar-items').each(function (idx:number, menu:HTMLElement) {\n install_menu_logic(jQuery(menu));\n });\n\n // Legacy settings listener\n listenToSettingChanges();\n\n // Color patches preview the color\n makeColorPreviews();\n\n // Danger zone input validation\n dangerZoneValidation();\n\n // Bootstrap legacy app code\n setupServerResponse();\n });\n\n}(jQuery));\n","// Dynamically loads and triggers the onboarding tour\n// when on the correct spots\nimport {demoProjectsLinks, OnboardingTourNames, onboardingTourStorageKey} from \"core-app/globals/onboarding/helpers\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\n\nexport function detectOnboardingTour() {\n // ------------------------------- Global -------------------------------\n const url = new URL(window.location.href);\n const isMobile = document.body.classList.contains('-browser-mobile');\n const demoProjectsAvailable = jQuery('meta[name=demo_projects_available]').attr('content') === \"true\";\n let currentTourPart = sessionStorage.getItem(onboardingTourStorageKey);\n let tourCancelled = false;\n\n // ------------------------------- Initial start -------------------------------\n // Do not show the tutorial on mobile or when the demo data has been deleted\n if (!isMobile && demoProjectsAvailable) {\n\n // Start after the intro modal (language selection)\n // This has to be changed once the project selection is implemented\n if (url.searchParams.get(\"first_time_user\") && demoProjectsLinks().length === 2) {\n currentTourPart = '';\n sessionStorage.setItem(onboardingTourStorageKey, 'readyToStart');\n\n // Start automatically when the language selection is closed\n jQuery('.op-modal--modal-close-button').click(function () {\n tourCancelled = true;\n triggerTour('homescreen');\n });\n\n //Start automatically when the escape button is pressed\n document.addEventListener('keydown', function (event) {\n if (event.key === \"Escape\" && !tourCancelled) {\n tourCancelled = true;\n triggerTour('homescreen');\n }\n }, { once: true });\n }\n\n // ------------------------------- Tutorial Homescreen page -------------------------------\n if (currentTourPart === \"readyToStart\") {\n triggerTour('homescreen');\n }\n\n // ------------------------------- Tutorial WP page -------------------------------\n if (currentTourPart === \"startMainTourFromBacklogs\" || url.searchParams.get(\"start_onboarding_tour\")) {\n triggerTour('main');\n }\n\n // ------------------------------- Tutorial Backlogs page -------------------------------\n if (url.searchParams.get(\"start_scrum_onboarding_tour\")) {\n if (jQuery('.backlogs-menu-item').length > 0) {\n triggerTour('backlogs');\n }\n }\n\n // ------------------------------- Tutorial Task Board page -------------------------------\n if (currentTourPart === \"startTaskBoardTour\") {\n triggerTour('taskboard');\n }\n }\n}\n\nasync function triggerTour(name:OnboardingTourNames) {\n debugLog(\"Loading and triggering onboarding tour \" + name);\n const tour = await import(/* webpackChunkName: \"onboarding-tour\" */ './onboarding_tour');\n tour.start(name);\n}\n\n","import {DatePicker} from \"core-app/modules/common/op-date-picker/datepicker\";\n\n/**\n * Our application is still a hybrid one, meaning most routes are still\n * handled by Rails. As such, we disable the default link-hijacking that\n * Angular's HTML5-mode with results in\n * @param evt\n * @param target\n */\nexport function augmentedDatePicker(evt:JQuery.TriggeredEvent, target:JQuery) {\n if (target.hasClass('-augmented-datepicker')) {\n target\n .attr('autocomplete', 'off'); // Disable autocomplete for those fields\n\n window.OpenProject.getPluginContext()\n .then(context => {\n var datePicker = new DatePicker(\n '.-augmented-datepicker',\n target.val(),\n {\n weekNumbers: true,\n allowInput: true\n },\n target[0],\n context.services.configurationService\n );\n datePicker.show();\n });\n }\n}\n","/**\n * Our application is still a hybrid one, meaning most routes are still\n * handled by Rails. As such, we disable the default link-hijacking that\n * Angular's HTML5-mode with results in\n * @param evt\n * @param target\n */\nexport function performAnchorHijacking(evt:JQuery.TriggeredEvent, target:JQuery):void {\n // Avoid defaulting clicks on elements already removed from DOM\n if (!document.contains(evt.target as Element)) {\n evt.preventDefault();\n }\n\n // Avoid handling clicks on anything other than a\n const linkElement = target.closest('a');\n if (linkElement.length === 0) {\n return;\n }\n\n const link = linkElement.attr('href') || '';\n const hashPos = link.indexOf('#');\n\n // If link is neither empty nor starts with hash, ignore it\n if (link !== '' && hashPos !== 0) {\n return;\n }\n\n // Set the location to the hash if there is any\n // Since with the base tag, links like href=\"#whatever\" otherwise target to /#whatever\n if (hashPos !== -1 && link !== '#') {\n window.location.hash = link;\n }\n\n evt.preventDefault();\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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// Moved from app/assets/javascript/danger_zone_validation.js\n// Make the whole danger zone a component the next time this needs changes!\nexport function dangerZoneValidation() {\n // This will only work iff there is a single danger zone on the page\n var dangerZoneVerification = jQuery('.danger-zone--verification');\n var expectedValue = jQuery('.danger-zone--expected-value').text();\n\n dangerZoneVerification.find('input').on('input', function () {\n var actualValue = dangerZoneVerification.find('input').val() as String;\n if (expectedValue.toLowerCase() === actualValue.toLowerCase()) {\n dangerZoneVerification.find('button').prop('disabled', false);\n } else {\n dangerZoneVerification.find('button').prop('disabled', true);\n }\n });\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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 * Move from legacy app/assets/javascripts/application.js.erb\n *\n * This should not be loaded globally and ideally refactored into components\n */\nexport function listenToSettingChanges() {\n jQuery('#settings_session_ttl_enabled').on('change', function () {\n jQuery('#settings_session_ttl_container').toggle(jQuery(this).is(':checked'));\n }).trigger('change');\n\n\n /** Sync SCM vendor select when enabled SCMs are changed */\n jQuery('[name=\"settings[enabled_scm][]\"]').change(function (this:HTMLInputElement) {\n var wasDisabled = !this.checked,\n vendor = this.value,\n select = jQuery('#settings_repositories_automatic_managed_vendor'),\n option = select.find('option[value=\"' + vendor + '\"]');\n\n // Skip non-manageable SCMs\n if (option.length === 0) {\n return;\n }\n\n option.prop('disabled', wasDisabled);\n if (wasDisabled && option.prop('selected')) {\n select.val('');\n }\n });\n\n /* Javascript for Settings::TextSettingCell */\n let langSelectSwitchData = function (select:any) {\n let self = jQuery(select);\n let id:string = self.attr(\"id\") || '';\n let settingName = id.replace('lang-for-', '');\n let newLang = self.val();\n let textArea = jQuery(`#settings-${settingName}`);\n let editor = textArea.siblings('ckeditor-augmented-textarea').data('editor');\n\n return { id: id, settingName: settingName, newLang: newLang, textArea: textArea, editor: editor };\n };\n\n // Upon focusing:\n // * store the current value of the editor in the hidden field for that lang.\n // Upon change:\n // * get the current value from the hidden field for that lang and set the editor text to that value.\n // * Set the name of the textarea to reflect the current lang so that the value stored in the hidden field\n // is overwritten.\n jQuery(\".lang-select-switch\")\n .focus(function () {\n let data = langSelectSwitchData(this);\n\n jQuery(`#${data.id}-${data.newLang}`).val(data.editor.getData());\n })\n .change(function () {\n let data = langSelectSwitchData(this);\n\n let storedValue = jQuery(`#${data.id}-${data.newLang}`).val();\n\n data.editor.setData(storedValue);\n data.textArea.attr('name', `settings[${data.settingName}][${data.newLang}]`);\n });\n /* end Javascript for Settings::TextSettingCell */\n\n jQuery('.admin-settings--form').submit(function () {\n /* Update consent time if consent required */\n if (jQuery('#settings_consent_required').is(':checked') && jQuery('#toggle_consent_time').is(':checked')) {\n jQuery('#settings_consent_time')\n .val(new Date().toISOString())\n .prop('disabled', false);\n }\n\n return true;\n });\n\n /** Toggle notification settings fields */\n jQuery(\"#email_delivery_method_switch\").on(\"change\", function () {\n const delivery_method = jQuery(this).val();\n jQuery(\".email_delivery_method_settings\").hide();\n jQuery(\"#email_delivery_method_\" + delivery_method).show();\n }).trigger(\"change\");\n\n jQuery('#settings_smtp_authentication').on('change', function () {\n var isNone = jQuery(this).val() === 'none';\n jQuery('#settings_smtp_user_name,#settings_smtp_password')\n .closest('.form--field')\n .toggle(!isNone);\n });\n\n /** Toggle repository checkout fieldsets required when option is disabled */\n jQuery('.settings-repositories--checkout-toggle').change(function (this:HTMLInputElement) {\n var wasChecked = this.checked,\n fieldset = jQuery(this).closest('fieldset');\n\n fieldset\n .find('input,select')\n .filter(':not([type=checkbox])')\n .filter(':not([type=hidden])')\n .removeAttr('required') // Rails 4.0 still seems to use attribute\n .prop('required', wasChecked);\n });\n\n /** Toggle highlighted attributes visibility depending on if the highlighting mode 'inline' was selected*/\n jQuery('.settings--highlighting-mode select').change(function () {\n var highlightingMode = jQuery(this).val();\n jQuery(\".settings--highlighted-attributes\").toggle(highlightingMode === \"inline\");\n });\n\n /** Initialize hightlighted attributes checkboxes. If none is selected, it means we want them all. So let's\n * show them all as selected.\n * On submitting the form, we remove all checkboxes before sending to communicate, we actually want all and not\n * only the selected.*/\n if (jQuery(\".settings--highlighted-attributes input[type='checkbox']:checked\").length === 0) {\n jQuery(\".settings--highlighted-attributes input[type='checkbox']\").prop(\"checked\", true);\n }\n jQuery('#tab-content-work_packages form').submit(function () {\n var availableAttributes = jQuery(\".settings--highlighted-attributes input[type='checkbox']\");\n var selectedAttributes = jQuery(\".settings--highlighted-attributes input[type='checkbox']:checked\");\n if (selectedAttributes.length === availableAttributes.length) {\n availableAttributes.prop(\"checked\", false);\n }\n });\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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/**\n * Moved from app/assets/javascripts/colors.js\n *\n * Make this a component instead of modifying it the next time\n * this needs changes\n */\nexport function makeColorPreviews() {\n jQuery('.color--preview').each(function () {\n let preview = jQuery(this);\n let input:any;\n let func:any;\n let target = preview.data('target');\n\n if (target) {\n input = jQuery(target);\n } else {\n input = preview.next('input');\n }\n\n if (input.length === 0) {\n return;\n }\n\n func = function () {\n var previewColor = '';\n\n if (input.val() && input.val().length > 0) {\n previewColor = input.val();\n } else if (input.attr('placeholder') &&\n input.attr('placeholder').length > 0) {\n previewColor = input.attr('placeholder')\n }\n\n preview.css('background-color', previewColor);\n };\n\n input.keyup(func).change(func).focus(func);\n func();\n });\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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/**\n * A set of global helpers that were used in the app/assets/javascript namespace\n * but exposed globally.\n *\n * It is used in some `link_to_function` helpers in Rails templates\n */\nexport class GlobalHelpers {\n public checkAll(selector:any, checked:any) {\n jQuery('#' + selector + ' input:checkbox').not(':disabled').each(function(this:HTMLInputElement) {\n this.checked = checked;\n });\n }\n\n public toggleCheckboxesBySelector(selector:any) {\n const boxes = jQuery(selector);\n var all_checked = true;\n for (let i = 0; i < boxes.length; i++) { if (boxes[i].checked === false) { all_checked = false; } }\n for (let i = 0; i < boxes.length; i++) { boxes[i].checked = !all_checked; }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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';\nimport {GlobalHelpers} from \"core-app/globals/global-helpers\";\n\n/**\n * OpenProject instance methods\n */\nexport class OpenProject {\n\n public pluginContext:InputState = input();\n\n public helpers = new GlobalHelpers();\n\n /** Globally setable variable whether the page was edited */\n public pageWasEdited:boolean = false;\n /** Globally setable variable whether the page form is submitted.\n * Necessary to avoid a data loss warning on beforeunload */\n public pageIsSubmitted:boolean = false;\n /** Globally setable variable whether any of the EditFormComponent\n * contain changes.\n * Necessary to show a data loss warning on beforeunload when clicking\n * on a link out of the Angular app (ie: main side menu)\n * */\n public editFormsContainModelChanges:boolean;\n\n public getPluginContext():Promise {\n return this.pluginContext\n .values$()\n .pipe(take(1))\n .toPromise();\n }\n\n public get urlRoot():string {\n return jQuery('meta[name=app_base_path]').attr('content') || '';\n }\n\n public get environment():string {\n return jQuery('meta[name=openproject_initializer]').data('environment');\n }\n\n public get edition():string {\n return jQuery('meta[name=openproject_initializer]').data('edition');\n }\n\n public get isStandardEdition():boolean {\n return this.edition === \"standard\";\n }\n\n public get isBimEdition():boolean {\n return this.edition === \"bim\";\n }\n\n /**\n * Guard access to reads and writes to the localstorage due to corrupted local databases\n * in Firefox happening in one larger client.\n *\n * NS_ERROR_FILE_CORRUPTED\n *\n * @param {string} key\n * @param {string} newValue\n * @returns {string | undefined}\n */\n public guardedLocalStorage(key:string, newValue?:string):string | void {\n try {\n if (newValue !== undefined) {\n window.localStorage.setItem(key, newValue);\n } else {\n const value = window.localStorage.getItem(key);\n return value === null ? undefined : value;\n }\n } catch (e) {\n console.error('Failed to access your browsers local storage. Is your local database corrupted?');\n }\n }\n}\n\nwindow.OpenProject = new OpenProject();\n","import {Inject, Injectable} from \"@angular/core\";\nimport {DOCUMENT} from \"@angular/common\";\n\n@Injectable({ providedIn: 'root' })\nexport class BrowserDetector {\n\n constructor (@Inject(DOCUMENT) private documentElement:Document) {\n }\n\n /**\n * Detect mobile browser based on the Rails determined UA\n * and resulting body class.\n */\n public get isMobile() {\n return this.hasBodyClass('-browser-mobile');\n }\n\n /**\n * ToDo: Remove all occurences once Edge on Chromium is released\n */\n public get isEdge() {\n return this.hasBodyClass('-browser-edge');\n }\n\n private hasBodyClass(name:string):boolean {\n return this.documentElement.body.classList.contains(name);\n }\n\n}\n","import {Component, Injector} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {WorkPackageFiltersService} from 'core-components/filters/wp-filters/wp-filters.service';\nimport {WorkPackageViewFiltersService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service';\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {BannersService} from \"core-app/modules/common/enterprise/banners.service\";\n\n@Component({\n templateUrl: './filters-tab.component.html',\n selector: 'wp-table-config-filters-tab'\n})\nexport class WpTableConfigurationFiltersTab implements TabComponent {\n\n public filters:QueryFilterInstanceResource[] = [];\n public eeShowBanners:boolean = false;\n\n public text = {\n columnsLabel: this.I18n.t('js.label_columns'),\n selectedColumns: this.I18n.t('js.description_selected_columns'),\n multiSelectLabel: this.I18n.t('js.work_packages.label_column_multiselect'),\n\n upsaleRelationColumns: this.I18n.t('js.modals.upsale_relation_columns'),\n upsaleRelationColumnsLink: this.I18n.t('js.modals.upsale_relation_columns_link')\n };\n\n constructor(readonly injector:Injector,\n readonly I18n:I18nService,\n readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly wpFiltersService:WorkPackageFiltersService,\n readonly bannerService:BannersService) {\n }\n\n ngOnInit() {\n this.eeShowBanners = this.bannerService.eeShowBanners;\n this.wpTableFilters\n .onReady()\n .then(() => this.filters = this.wpTableFilters.current);\n\n this.wpTableFilters.changes$().subscribe(filters => {\n this.filters = this.wpTableFilters.current;\n });\n }\n\n public onSave() {\n if (this.filters) {\n this.wpTableFilters.replaceIfComplete(this.filters);\n }\n }\n}\n","\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {input} from 'reactivestates';\nimport {HelpTextResource} from 'core-app/modules/hal/resources/help-text-resource';\nimport {Injectable} from '@angular/core';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {APIv3ResourceCollection} from \"core-app/modules/apiv3/paths/apiv3-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {take} from \"rxjs/operators\";\n\n@Injectable({ providedIn: 'root' })\nexport class AttributeHelpTextsService {\n private helpTexts = input();\n\n constructor(private apiV3Service:APIV3Service) {\n }\n\n /**\n * Search for a given attribute help text\n *\n * @param attribute\n * @param scope\n */\n public require(attribute:string, scope:string):Promise {\n this.load();\n\n return new Promise((resolve, reject) => {\n this.helpTexts\n .valuesPromise()\n .then(() => resolve(this.find(attribute, scope)));\n });\n }\n\n /**\n * Search for a given attribute help text\n *\n */\n public requireById(id:string):Promise {\n this.load();\n\n return this\n .helpTexts\n .values$()\n .pipe(\n take(1)\n )\n .toPromise()\n .then(() => {\n const value = this.helpTexts.getValueOr([]);\n return _.find(value, element => element.id.toString() === id);\n });\n }\n\n private load():void {\n this.helpTexts.putFromPromiseIfPristine(() =>\n this.apiV3Service\n .help_texts\n .get()\n .toPromise()\n .then((resources:CollectionResource) => resources.elements)\n );\n\n }\n\n private find(attribute:string, scope:string):HelpTextResource|undefined {\n const value = this.helpTexts.getValueOr([]);\n return _.find(value, (element) => element.scope === scope && element.attribute === attribute);\n }\n}\n","
    \n
    \n
    \n

    \n \n \n

    \n\n \n \n \n \n
    \n\n
    \n
    \n\n \n \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, Inject, OnInit} from '@angular/core';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {HelpTextResource} from 'core-app/modules/hal/resources/help-text-resource';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\n\n@Component({\n templateUrl: './help-text.modal.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class AttributeHelpTextModal extends OpModalComponent implements OnInit {\n\n /* Close on escape? */\n public closeOnEscape = true;\n\n /* Close on outside click */\n public closeOnOutsideClick = false;\n\n readonly text = {\n 'edit': this.I18n.t('js.button_edit'),\n 'close': this.I18n.t('js.button_close')\n };\n\n public helpText:HelpTextResource = this.locals.helpText!;\n\n constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n super.ngOnInit();\n\n // Load the attachments\n this\n .helpText\n .attachments\n .$load()\n .then(() => this.cdRef.detectChanges());\n }\n\n public get helpTextLink() {\n if (this.helpText.editText) {\n return this.helpText.editText.$link.href;\n }\n\n return '';\n\n }\n}\n\n","\n \n {{ additionalLabel }}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {AttributeHelpTextsService} from './attribute-help-text.service';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n Input,\n OnInit\n} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {OpModalService} from 'core-components/op-modals/op-modal.service';\nimport {AttributeHelpTextModal} from \"core-app/modules/fields/help-texts/attribute-help-text.modal\";\n\nexport const attributeHelpTextSelector = 'attribute-help-text';\n\n@Component({\n selector: attributeHelpTextSelector,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './attribute-help-text.component.html'\n})\nexport class AttributeHelpTextComponent implements OnInit {\n // Attribute to show help text for\n @Input() public attribute:string;\n @Input() public additionalLabel?:string;\n\n // Scope to search for\n @Input() public attributeScope:string;\n // Load single id entry if given\n @Input() public helpTextId?:string;\n\n public exists:boolean = false;\n\n readonly text = {\n open_dialog: this.I18n.t('js.help_texts.show_modal'),\n 'edit': this.I18n.t('js.button_edit'),\n 'close': this.I18n.t('js.button_close')\n };\n\n constructor(protected elementRef:ElementRef,\n protected attributeHelpTexts:AttributeHelpTextsService,\n protected opModalService:OpModalService,\n protected cdRef:ChangeDetectorRef,\n protected injector:Injector,\n protected I18n:I18nService) {\n }\n\n ngOnInit() {\n const element:HTMLElement = this.elementRef.nativeElement;\n // Fall back to values provided by data\n this.helpTextId = this.helpTextId || element.dataset.helpTextId!;\n this.attribute = this.attribute || element.dataset.attribute!;\n this.attributeScope = this.attributeScope || element.dataset.attributeScope!;\n this.additionalLabel = this.additionalLabel || element.dataset.additionalLabel!;\n\n if (this.helpTextId) {\n this.exists = true;\n } else {\n // Need to load the promise to find out if the attribute exists\n this.load().then((resource) => {\n this.exists = !!resource;\n this.cdRef.detectChanges();\n return resource;\n });\n }\n }\n\n public handleClick() {\n this.load().then((resource) => {\n this.opModalService.show(AttributeHelpTextModal, this.injector, { helpText: resource });\n });\n }\n\n private load() {\n if (this.helpTextId) {\n return this.attributeHelpTexts.requireById(this.helpTextId);\n } else {\n return this.attributeHelpTexts.require(this.attribute, this.attributeScope);\n }\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 const currentDetailsState = 'currentDetailsState';\nexport const currentShowState = 'currentShowState';\n\nexport class UiStateLinkBuilder {\n\n constructor(public readonly $state:StateService,\n public readonly keepTab:KeepTabService) {\n }\n\n public linkToDetails(workPackageId:string, title:string, content:string) {\n return this.build(workPackageId, currentDetailsState, title, content);\n }\n\n public linkToShow(workPackageId:string, title:string, content:string) {\n return this.build(workPackageId, currentShowState, title, content);\n }\n\n private build(workPackageId:string, state:string, title:string, content:string) {\n let a = document.createElement('a');\n\n a.href = this.$state.href((this.keepTab as any)[state], {workPackageId: workPackageId});\n a.classList.add(uiStateLinkClass);\n a.dataset['workPackageId'] = workPackageId;\n a.dataset['wpState'] = state;\n\n a.setAttribute('title', title);\n a.textContent = content;\n\n return a;\n }\n}\n","function webpackEmptyAsyncContext(req) {\n\t// Here Promise.resolve().then() is used instead of new Promise() to prevent\n\t// uncaught exception popping up in devtools\n\treturn Promise.resolve().then(function() {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t});\n}\nwebpackEmptyAsyncContext.keys = function() { return []; };\nwebpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;\nmodule.exports = webpackEmptyAsyncContext;\nwebpackEmptyAsyncContext.id = \"crnd\";","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 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 {MultiInputState, State} from 'reactivestates';\nimport {States} from '../states.service';\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Injectable} from '@angular/core';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {ISchemaProxy, SchemaProxy} from \"core-app/modules/hal/schemas/schema-proxy\";\nimport {WorkPackageSchemaProxy} from \"core-app/modules/hal/schemas/work-package-schema-proxy\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {Observable} from \"rxjs\";\nimport {take} from \"rxjs/operators\";\n\n@Injectable()\nexport class SchemaCacheService extends StateCacheService {\n\n constructor(readonly states:States,\n readonly halResourceService:HalResourceService) {\n super(states.schemas);\n }\n\n public state(id:string|HalResource):State {\n return super.state(this.stateKey(id));\n }\n\n /**\n * Returns the schema of the provided resource.\n * This method assumes the schema is loaded and will fail if it is not.\n * @deprecated Assuming the schema to be loaded is deprecated. Rely on the states instead.\n * @param resource The HalResource for which the schema is to be returned\n * @return The schema for the HalResource\n */\n of(resource:HalResource):ISchemaProxy {\n let schema = this.state(resource).value;\n\n if (!schema) {\n throw `Schema for resource ${resource} was expected to be loaded but isn't.`;\n }\n\n if (resource._type === 'WorkPackage') {\n return WorkPackageSchemaProxy.create(schema, resource);\n } else {\n return SchemaProxy.create(schema, resource);\n }\n }\n\n public getSchemaHref(resource:HalResource):string {\n let href = resource.$links.schema?.href;\n\n if (!href) {\n throw new Error(`Resource ${resource} has no schema to load.`);\n }\n\n return href;\n }\n\n /**\n * Ensure the given schema identified by its href is currently loaded.\n * @param resource The resource with a schema property or a string to the schema href.\n * @return A promise with the loaded schema.\n */\n ensureLoaded(resource:HalResource|string):Promise {\n let href = resource instanceof HalResource ? this.getSchemaHref(resource) : resource;\n\n return this\n .requireAndStream(href)\n .pipe(\n take(1)\n )\n .toPromise();\n }\n\n /**\n * Require the value to be loaded either when forced or the value is stale\n * according to the cache interval specified for this service.\n *\n * Returns an observable to the values stream of the state.\n *\n * @param id The state to require\n * @param force Load the value anyway.\n */\n public requireAndStream(href:string, force:boolean = false):Observable {\n // Refresh when stale or being forced\n if (this.stale(href) || force) {\n this.clearAndLoad(\n href,\n this.load(href)\n );\n }\n\n return this.state(href).values$();\n }\n\n /**\n * Load the associated schema for the given work package, if needed.\n */\n protected load(href:string):Observable {\n return this\n .halResourceService\n .get(href)\n .pipe(\n take(1)\n );\n }\n\n protected loadAll(hrefs:string[]):Promise {\n return Promise.all(hrefs.map(href => this.load(href)));\n }\n\n /**\n * Places the schema in the schema state of the resource.\n * @param resource The resource for which the schema is to be updated\n * @param schema\n */\n update(resource:HalResource, schema:SchemaResource) {\n this.multiState.get(this.stateKey(resource)).putValue(schema);\n }\n\n private stateKey(id:string|HalResource):string {\n if (id instanceof HalResource) {\n return this.getSchemaHref(id);\n } else {\n return id;\n }\n }\n}\n\n","import {Title} from \"@angular/platform-browser\";\nimport {Injectable} from \"@angular/core\";\n\nconst titlePartsSeparator = ' | ';\n\n@Injectable({ providedIn: 'root' })\nexport class OpTitleService {\n constructor(private titleService:Title) {\n\n }\n\n public get current():string {\n return this.titleService.getTitle();\n }\n\n public get titleParts():string[] {\n return this.current.split(titlePartsSeparator);\n }\n\n public setFirstPart(value:string) {\n let parts = this.titleParts;\n parts[0] = value;\n\n this.titleService.setTitle(parts.join(titlePartsSeparator));\n }\n\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injector} from '@angular/core';\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {States} from 'core-components/states.service';\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\n\nimport {\n HalResourceEditingService,\n ResourceChangesetCommit\n} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {EditFieldHandler} from \"core-app/modules/fields/edit/editing-portal/edit-field-handler\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport const activeFieldContainerClassName = 'inline-edit--active-field';\nexport const activeFieldClassName = 'inline-edit--field';\n\nexport abstract class EditForm {\n\n // Injections\n @InjectField() states:States;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() halNotification:HalResourceNotificationService;\n @InjectField() halEvents:HalEventsService;\n\n // All current active (open) edit fields\n public activeFields:{ [fieldName:string]:EditFieldHandler } = {};\n\n // Errors of the last operation (required when adding opening fields afterwards)\n public errorsPerAttribute:{ [fieldName:string]:string[] } = {};\n\n // Reference to the changeset used in this form\n public resource:T;\n\n // Whether this form exists in edit mode\n public editMode:boolean = false;\n\n protected constructor(public injector:Injector) {\n }\n\n /**\n * Activate the field, returning the element and associated field handler\n */\n protected abstract activateField(form:EditForm, schema:IFieldSchema, fieldName:string, errors:string[]):Promise;\n\n /**\n * Show this required field. E.g., add the necessary column\n */\n protected abstract requireVisible(fieldName:string):Promise;\n\n /**\n * Reset the field and re-render the current resource's value\n */\n abstract reset(fieldName:string, focus?:boolean):void;\n\n /**\n * Optional callback when the form is being saved\n */\n protected onSaved(commit:ResourceChangesetCommit):void {\n // Does nothing by default\n }\n\n protected abstract focusOnFirstError():void;\n\n /**\n * Return whether this form has any active fields\n */\n public hasActiveFields():boolean {\n return !_.isEmpty(this.activeFields);\n }\n\n\n /**\n * Return the current or a new change object for the given resource.\n * This will always return a valid (potentially empty) change.\n *\n * @return {ResourceChangeset}\n */\n public get change():ResourceChangeset {\n return this.halEditing.changeFor(this.resource);\n }\n\n /**\n * Active the edit field upon user's request.\n * @param fieldName\n * @param noWarnings Ignore warnings if the field cannot be opened\n */\n public activate(fieldName:string, noWarnings:boolean = false):Promise {\n return this.loadFieldSchema(fieldName, noWarnings)\n .then((schema:IFieldSchema) => {\n if (!schema.writable && !noWarnings) {\n this.halNotification.showEditingBlockedError(schema.name || fieldName);\n return Promise.reject();\n }\n\n return this.renderField(fieldName, schema);\n });\n }\n\n /**\n * Activate the field unless it is marked active already\n * (e.g., already being activated).\n */\n public activateWhenNeeded(fieldName:string):Promise {\n const activeField = this.activeFields[fieldName];\n if (activeField) {\n return Promise.resolve();\n }\n\n return this.requireVisible(fieldName).then(() => {\n return this.activate(fieldName, true);\n });\n }\n\n /**\n * Activate all fields that are returned in validation errors\n */\n public activateMissingFields() {\n this.change.getForm().then((form:any) => {\n _.each(form.validationErrors, (val:any, key:string) => {\n if (key === 'id') {\n return;\n }\n this.activateWhenNeeded(key);\n });\n });\n }\n\n /**\n * Save the active changeset.\n * @return {any}\n */\n public async submit():Promise {\n if (this.change.isEmpty() && !this.resource.isNew) {\n this.closeEditFields();\n return Promise.resolve(this.resource);\n }\n\n // Mark changeset as in flight\n this.change.inFlight = true;\n\n // Reset old error notifcations\n this.errorsPerAttribute = {};\n\n // Notify all fields of upcoming save\n const openFields = _.keys(this.activeFields);\n\n // Call onSubmit handlers\n await Promise.all(_.map(this.activeFields, (handler:EditFieldHandler) => handler.onSubmit()));\n\n return new Promise((resolve, reject) => {\n this.halEditing.save>(this.change)\n .then(result => {\n // Close all current fields\n this.closeEditFields(openFields);\n\n resolve(result.resource);\n\n this.halNotification.showSave(result.resource, result.wasNew);\n this.editMode = false;\n this.onSaved(result);\n this.change.inFlight = false;\n })\n .catch((error:ErrorResource|Object) => {\n this.halNotification.handleRawError(error, this.resource);\n\n if (error instanceof ErrorResource) {\n this.handleSubmissionErrors(error);\n reject();\n }\n\n this.change.inFlight = false;\n\n return Promise.reject(error);\n });\n });\n }\n\n /**\n * Close the given or all open fields.\n *\n * @param {string[]} fields\n * @param resetChange whether to undo any changes made\n */\n public closeEditFields(fields:string[]|'all' = 'all', resetChange:boolean = true) {\n if (fields === 'all') {\n fields = _.keys(this.activeFields);\n }\n\n fields.forEach((name:string) => {\n const handler = this.activeFields[name];\n handler && handler.deactivate(false);\n\n if (resetChange) {\n this.change.reset(name);\n }\n });\n }\n\n protected handleSubmissionErrors(error:any) {\n // Process single API errors\n this.handleErroneousAttributes(error);\n }\n\n protected handleErroneousAttributes(error:any) {\n // Get attributes withe errors\n const erroneousAttributes = error.getInvolvedAttributes();\n\n // Save erroneous fields for when new fields appear\n this.errorsPerAttribute = error.getMessagesPerAttribute();\n if (erroneousAttributes.length === 0) {\n return;\n }\n\n return this.setErrorsForFields(erroneousAttributes);\n }\n\n private setErrorsForFields(erroneousFields:string[]) {\n // Accumulate errors for the given response\n let promises:Promise[] = erroneousFields.map((fieldName:string) => {\n return this.requireVisible(fieldName).then(() => {\n if (this.activeFields[fieldName]) {\n this.activeFields[fieldName].setErrors(this.errorsPerAttribute[fieldName] || []);\n }\n\n return this.activateWhenNeeded(fieldName) as any;\n });\n });\n\n Promise.all(promises)\n .then(() => {\n setTimeout(() => this.focusOnFirstError());\n })\n .catch(() => {\n console.error('Failed to activate all erroneous fields.');\n });\n }\n\n /**\n * Load the resource form to get the current field schema with all\n * values loaded.\n * @param fieldName\n */\n protected loadFieldSchema(fieldName:string, noWarnings:boolean = false):Promise {\n return new Promise((resolve, reject) => {\n this.loadFormAndCheck(fieldName, noWarnings);\n const fieldSchema:IFieldSchema = this.change.schema.ofProperty(fieldName);\n\n if (!fieldSchema) {\n throw new Error();\n }\n\n resolve(fieldSchema);\n });\n }\n\n /**\n * Ensure the form gets loaded and we show an error when the field cannot be opened\n * @param fieldName\n * @param noWarnings\n */\n private loadFormAndCheck(fieldName:string, noWarnings:boolean = false) {\n // Ensure the form is being loaded if necessary\n this.change\n .getForm()\n .then(() => {\n // Look up whether we're actually editable\n const fieldSchema = this.change.schema.ofProperty(fieldName);\n if (!fieldSchema.writable && !noWarnings) {\n this.halNotification.showEditingBlockedError(fieldSchema.name || fieldName);\n this.closeEditFields([fieldName]);\n }\n })\n .catch((error:any) => {\n console.error('Failed to build edit field: %o', error);\n this.halNotification.handleRawError(error, this.resource);\n this.closeEditFields([fieldName]);\n });\n }\n\n private renderField(fieldName:string, schema:IFieldSchema):Promise {\n const promise:Promise = this.activateField(this,\n schema,\n fieldName,\n this.errorsPerAttribute[fieldName] || []);\n\n return promise\n .then((fieldHandler:EditFieldHandler) => {\n this.activeFields[fieldName] = fieldHandler;\n return fieldHandler;\n })\n .catch((error) => {\n console.error('Failed to render edit field:' + error);\n this.halNotification.handleRawError(error);\n });\n }\n}\n","// I18n.js\n// =======\n//\n// This small library provides the Rails I18n API on the Javascript.\n// You don't actually have to use Rails (or even Ruby) to use I18n.js.\n// Just make sure you export all translations in an object like this:\n//\n// I18n.translations.en = {\n// hello: \"Hello World\"\n// };\n//\n// See tests for specific formatting like numbers and dates.\n//\n\n// Using UMD pattern from\n// https://github.com/umdjs/umd#regular-module\n// `returnExports.js` version\n;(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(\"i18n\", function(){ return factory(root);});\n } else if (typeof module === 'object' && module.exports) {\n // Node. Does not work with strict CommonJS, but\n // only CommonJS-like environments that support module.exports,\n // like Node.\n module.exports = factory(root);\n } else {\n // Browser globals (root is window)\n root.I18n = factory(root);\n }\n}(this, function(global) {\n \"use strict\";\n\n // Use previously defined object if exists in current scope\n var I18n = global && global.I18n || {};\n\n // Just cache the Array#slice function.\n var slice = Array.prototype.slice;\n\n // Apply number padding.\n var padding = function(number) {\n return (\"0\" + number.toString()).substr(-2);\n };\n\n // Improved toFixed number rounding function with support for unprecise floating points\n // JavaScript's standard toFixed function does not round certain numbers correctly (for example 0.105 with precision 2).\n var toFixed = function(number, precision) {\n return decimalAdjust('round', number, -precision).toFixed(precision);\n };\n\n // Is a given variable an object?\n // Borrowed from Underscore.js\n var isObject = function(obj) {\n var type = typeof obj;\n return type === 'function' || type === 'object'\n };\n\n var isFunction = function(func) {\n var type = typeof func;\n return type === 'function'\n };\n\n // Check if value is different than undefined and null;\n var isSet = function(value) {\n return typeof(value) !== 'undefined' && value !== null;\n };\n\n // Is a given value an array?\n // Borrowed from Underscore.js\n var isArray = function(val) {\n if (Array.isArray) {\n return Array.isArray(val);\n };\n return Object.prototype.toString.call(val) === '[object Array]';\n };\n\n var isString = function(val) {\n return typeof value == 'string' || Object.prototype.toString.call(val) === '[object String]';\n };\n\n var isNumber = function(val) {\n return typeof val == 'number' || Object.prototype.toString.call(val) === '[object Number]';\n };\n\n var isBoolean = function(val) {\n return val === true || val === false;\n };\n\n var decimalAdjust = function(type, value, exp) {\n // If the exp is undefined or zero...\n if (typeof exp === 'undefined' || +exp === 0) {\n return Math[type](value);\n }\n value = +value;\n exp = +exp;\n // If the value is not a number or the exp is not an integer...\n if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {\n return NaN;\n }\n // Shift\n value = value.toString().split('e');\n value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));\n // Shift back\n value = value.toString().split('e');\n return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));\n }\n\n var lazyEvaluate = function(message, scope) {\n if (isFunction(message)) {\n return message(scope);\n } else {\n return message;\n }\n }\n\n var merge = function (dest, obj) {\n var key, value;\n for (key in obj) if (obj.hasOwnProperty(key)) {\n value = obj[key];\n if (isString(value) || isNumber(value) || isBoolean(value) || isArray(value)) {\n dest[key] = value;\n } else {\n if (dest[key] == null) dest[key] = {};\n merge(dest[key], value);\n }\n }\n return dest;\n };\n\n // Set default days/months translations.\n var DATE = {\n day_names: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]\n , abbr_day_names: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"]\n , month_names: [null, \"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"]\n , abbr_month_names: [null, \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\n , meridian: [\"AM\", \"PM\"]\n };\n\n // Set default number format.\n var NUMBER_FORMAT = {\n precision: 3\n , separator: \".\"\n , delimiter: \",\"\n , strip_insignificant_zeros: false\n };\n\n // Set default currency format.\n var CURRENCY_FORMAT = {\n unit: \"$\"\n , precision: 2\n , format: \"%u%n\"\n , sign_first: true\n , delimiter: \",\"\n , separator: \".\"\n };\n\n // Set default percentage format.\n var PERCENTAGE_FORMAT = {\n unit: \"%\"\n , precision: 3\n , format: \"%n%u\"\n , separator: \".\"\n , delimiter: \"\"\n };\n\n // Set default size units.\n var SIZE_UNITS = [null, \"kb\", \"mb\", \"gb\", \"tb\"];\n\n // Other default options\n var DEFAULT_OPTIONS = {\n // Set default locale. This locale will be used when fallback is enabled and\n // the translation doesn't exist in a particular locale.\n defaultLocale: \"en\"\n // Set the current locale to `en`.\n , locale: \"en\"\n // Set the translation key separator.\n , defaultSeparator: \".\"\n // Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.\n , placeholder: /(?:\\{\\{|%\\{)(.*?)(?:\\}\\}?)/gm\n // Set if engine should fallback to the default locale when a translation\n // is missing.\n , fallbacks: false\n // Set the default translation object.\n , translations: {}\n // Set missing translation behavior. 'message' will display a message\n // that the translation is missing, 'guess' will try to guess the string\n , missingBehaviour: 'message'\n // if you use missingBehaviour with 'message', but want to know that the\n // string is actually missing for testing purposes, you can prefix the\n // guessed string by setting the value here. By default, no prefix!\n , missingTranslationPrefix: ''\n };\n\n // Set default locale. This locale will be used when fallback is enabled and\n // the translation doesn't exist in a particular locale.\n I18n.reset = function() {\n var key;\n for (key in DEFAULT_OPTIONS) {\n this[key] = DEFAULT_OPTIONS[key];\n }\n };\n\n // Much like `reset`, but only assign options if not already assigned\n I18n.initializeOptions = function() {\n var key;\n for (key in DEFAULT_OPTIONS) if (!isSet(this[key])) {\n this[key] = DEFAULT_OPTIONS[key];\n }\n };\n I18n.initializeOptions();\n\n // Return a list of all locales that must be tried before returning the\n // missing translation message. By default, this will consider the inline option,\n // current locale and fallback locale.\n //\n // I18n.locales.get(\"de-DE\");\n // // [\"de-DE\", \"de\", \"en\"]\n //\n // You can define custom rules for any locale. Just make sure you return a array\n // containing all locales.\n //\n // // Default the Wookie locale to English.\n // I18n.locales[\"wk\"] = function(locale) {\n // return [\"en\"];\n // };\n //\n I18n.locales = {};\n\n // Retrieve locales based on inline locale, current locale or default to\n // I18n's detection.\n I18n.locales.get = function(locale) {\n var result = this[locale] || this[I18n.locale] || this[\"default\"];\n\n if (isFunction(result)) {\n result = result(locale);\n }\n\n if (isArray(result) === false) {\n result = [result];\n }\n\n return result;\n };\n\n // The default locale list.\n I18n.locales[\"default\"] = function(locale) {\n var locales = []\n , list = []\n ;\n\n // Handle the inline locale option that can be provided to\n // the `I18n.t` options.\n if (locale) {\n locales.push(locale);\n }\n\n // Add the current locale to the list.\n if (!locale && I18n.locale) {\n locales.push(I18n.locale);\n }\n\n // Add the default locale if fallback strategy is enabled.\n if (I18n.fallbacks && I18n.defaultLocale) {\n locales.push(I18n.defaultLocale);\n }\n\n // Locale code format 1:\n // According to RFC4646 (http://www.ietf.org/rfc/rfc4646.txt)\n // language codes for Traditional Chinese should be `zh-Hant`\n //\n // But due to backward compatibility\n // We use older version of IETF language tag\n // @see http://www.w3.org/TR/html401/struct/dirlang.html\n // @see http://en.wikipedia.org/wiki/IETF_language_tag\n //\n // Format: `language-code = primary-code ( \"-\" subcode )*`\n //\n // primary-code uses ISO639-1\n // @see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes\n // @see http://www.iso.org/iso/home/standards/language_codes.htm\n //\n // subcode uses ISO 3166-1 alpha-2\n // @see http://en.wikipedia.org/wiki/ISO_3166\n // @see http://www.iso.org/iso/country_codes.htm\n //\n // @note\n // subcode can be in upper case or lower case\n // defining it in upper case is a convention only\n\n\n // Locale code format 2:\n // Format: `code = primary-code ( \"-\" region-code )*`\n // primary-code uses ISO 639-1\n // script-code uses ISO 15924\n // region-code uses ISO 3166-1 alpha-2\n // Example: zh-Hant-TW, en-HK, zh-Hant-CN\n //\n // It is similar to RFC4646 (or actually the same),\n // but seems to be limited to language, script, region\n\n // Compute each locale with its country code.\n // So this will return an array containing\n // `de-DE` and `de`\n // or\n // `zh-hans-tw`, `zh-hans`, `zh`\n // locales.\n locales.forEach(function(locale) {\n var localeParts = locale.split(\"-\");\n var firstFallback = null;\n var secondFallback = null;\n if (localeParts.length === 3) {\n firstFallback = [\n localeParts[0],\n localeParts[1]\n ].join(\"-\");\n secondFallback = localeParts[0];\n }\n else if (localeParts.length === 2) {\n firstFallback = localeParts[0];\n }\n\n if (list.indexOf(locale) === -1) {\n list.push(locale);\n }\n\n if (! I18n.fallbacks) {\n return;\n }\n\n [\n firstFallback,\n secondFallback\n ].forEach(function(nullableFallbackLocale) {\n // We don't want null values\n if (typeof nullableFallbackLocale === \"undefined\") { return; }\n if (nullableFallbackLocale === null) { return; }\n // We don't want duplicate values\n //\n // Comparing with `locale` first is faster than\n // checking whether value's presence in the list\n if (nullableFallbackLocale === locale) { return; }\n if (list.indexOf(nullableFallbackLocale) !== -1) { return; }\n\n list.push(nullableFallbackLocale);\n });\n });\n\n // No locales set? English it is.\n if (!locales.length) {\n locales.push(\"en\");\n }\n\n return list;\n };\n\n // Hold pluralization rules.\n I18n.pluralization = {};\n\n // Return the pluralizer for a specific locale.\n // If no specify locale is found, then I18n's default will be used.\n I18n.pluralization.get = function(locale) {\n return this[locale] || this[I18n.locale] || this[\"default\"];\n };\n\n // The default pluralizer rule.\n // It detects the `zero`, `one`, and `other` scopes.\n I18n.pluralization[\"default\"] = function(count) {\n switch (count) {\n case 0: return [\"zero\", \"other\"];\n case 1: return [\"one\"];\n default: return [\"other\"];\n }\n };\n\n // Return current locale. If no locale has been set, then\n // the current locale will be the default locale.\n I18n.currentLocale = function() {\n return this.locale || this.defaultLocale;\n };\n\n // Check if value is different than undefined and null;\n I18n.isSet = isSet;\n\n // Find and process the translation using the provided scope and options.\n // This is used internally by some functions and should not be used as an\n // public API.\n I18n.lookup = function(scope, options) {\n options = options || {}\n\n var locales = this.locales.get(options.locale).slice()\n , requestedLocale = locales[0]\n , locale\n , scopes\n , fullScope\n , translations\n ;\n\n fullScope = this.getFullScope(scope, options);\n\n while (locales.length) {\n locale = locales.shift();\n scopes = fullScope.split(this.defaultSeparator);\n translations = this.translations[locale];\n\n if (!translations) {\n continue;\n }\n while (scopes.length) {\n translations = translations[scopes.shift()];\n\n if (translations === undefined || translations === null) {\n break;\n }\n }\n\n if (translations !== undefined && translations !== null) {\n return translations;\n }\n }\n\n if (isSet(options.defaultValue)) {\n return lazyEvaluate(options.defaultValue, scope);\n }\n };\n\n // lookup pluralization rule key into translations\n I18n.pluralizationLookupWithoutFallback = function(count, locale, translations) {\n var pluralizer = this.pluralization.get(locale)\n , pluralizerKeys = pluralizer(count)\n , pluralizerKey\n , message;\n\n if (isObject(translations)) {\n while (pluralizerKeys.length) {\n pluralizerKey = pluralizerKeys.shift();\n if (isSet(translations[pluralizerKey])) {\n message = translations[pluralizerKey];\n break;\n }\n }\n }\n\n return message;\n };\n\n // Lookup dedicated to pluralization\n I18n.pluralizationLookup = function(count, scope, options) {\n options = options || {}\n var locales = this.locales.get(options.locale).slice()\n , requestedLocale = locales[0]\n , locale\n , scopes\n , translations\n , message\n ;\n scope = this.getFullScope(scope, options);\n\n while (locales.length) {\n locale = locales.shift();\n scopes = scope.split(this.defaultSeparator);\n translations = this.translations[locale];\n\n if (!translations) {\n continue;\n }\n\n while (scopes.length) {\n translations = translations[scopes.shift()];\n if (!isObject(translations)) {\n break;\n }\n if (scopes.length == 0) {\n message = this.pluralizationLookupWithoutFallback(count, locale, translations);\n }\n }\n if (message != null && message != undefined) {\n break;\n }\n }\n\n if (message == null || message == undefined) {\n if (isSet(options.defaultValue)) {\n if (isObject(options.defaultValue)) {\n message = this.pluralizationLookupWithoutFallback(count, options.locale, options.defaultValue);\n } else {\n message = options.defaultValue;\n }\n translations = options.defaultValue;\n }\n }\n\n return { message: message, translations: translations };\n };\n\n // Rails changed the way the meridian is stored.\n // It started with `date.meridian` returning an array,\n // then it switched to `time.am` and `time.pm`.\n // This function abstracts this difference and returns\n // the correct meridian or the default value when none is provided.\n I18n.meridian = function() {\n var time = this.lookup(\"time\");\n var date = this.lookup(\"date\");\n\n if (time && time.am && time.pm) {\n return [time.am, time.pm];\n } else if (date && date.meridian) {\n return date.meridian;\n } else {\n return DATE.meridian;\n }\n };\n\n // Merge serveral hash options, checking if value is set before\n // overwriting any value. The precedence is from left to right.\n //\n // I18n.prepareOptions({name: \"John Doe\"}, {name: \"Mary Doe\", role: \"user\"});\n // #=> {name: \"John Doe\", role: \"user\"}\n //\n I18n.prepareOptions = function() {\n var args = slice.call(arguments)\n , options = {}\n , subject\n ;\n\n while (args.length) {\n subject = args.shift();\n\n if (typeof(subject) != \"object\") {\n continue;\n }\n\n for (var attr in subject) {\n if (!subject.hasOwnProperty(attr)) {\n continue;\n }\n\n if (isSet(options[attr])) {\n continue;\n }\n\n options[attr] = subject[attr];\n }\n }\n\n return options;\n };\n\n // Generate a list of translation options for default fallbacks.\n // `defaultValue` is also deleted from options as it is returned as part of\n // the translationOptions array.\n I18n.createTranslationOptions = function(scope, options) {\n var translationOptions = [{scope: scope}];\n\n // Defaults should be an array of hashes containing either\n // fallback scopes or messages\n if (isSet(options.defaults)) {\n translationOptions = translationOptions.concat(options.defaults);\n }\n\n // Maintain support for defaultValue. Since it is always a message\n // insert it in to the translation options as such.\n if (isSet(options.defaultValue)) {\n translationOptions.push({ message: options.defaultValue });\n }\n\n return translationOptions;\n };\n\n // Translate the given scope with the provided options.\n I18n.translate = function(scope, options) {\n options = options || {}\n\n var translationOptions = this.createTranslationOptions(scope, options);\n\n var translation;\n\n var optionsWithoutDefault = this.prepareOptions(options)\n delete optionsWithoutDefault.defaultValue\n\n // Iterate through the translation options until a translation\n // or message is found.\n var translationFound =\n translationOptions.some(function(translationOption) {\n if (isSet(translationOption.scope)) {\n translation = this.lookup(translationOption.scope, optionsWithoutDefault);\n } else if (isSet(translationOption.message)) {\n translation = lazyEvaluate(translationOption.message, scope);\n }\n\n if (translation !== undefined && translation !== null) {\n return true;\n }\n }, this);\n\n if (!translationFound) {\n return this.missingTranslation(scope, options);\n }\n\n if (typeof(translation) === \"string\") {\n translation = this.interpolate(translation, options);\n } else if (isObject(translation) && isSet(options.count)) {\n translation = this.pluralize(options.count, scope, options);\n }\n\n return translation;\n };\n\n // This function interpolates the all variables in the given message.\n I18n.interpolate = function(message, options) {\n options = options || {}\n var matches = message.match(this.placeholder)\n , placeholder\n , value\n , name\n , regex\n ;\n\n if (!matches) {\n return message;\n }\n\n var value;\n\n while (matches.length) {\n placeholder = matches.shift();\n name = placeholder.replace(this.placeholder, \"$1\");\n\n if (isSet(options[name])) {\n value = options[name].toString().replace(/\\$/gm, \"_#$#_\");\n } else if (name in options) {\n value = this.nullPlaceholder(placeholder, message, options);\n } else {\n value = this.missingPlaceholder(placeholder, message, options);\n }\n\n regex = new RegExp(placeholder.replace(/\\{/gm, \"\\\\{\").replace(/\\}/gm, \"\\\\}\"));\n message = message.replace(regex, value);\n }\n\n return message.replace(/_#\\$#_/g, \"$\");\n };\n\n // Pluralize the given scope using the `count` value.\n // The pluralized translation may have other placeholders,\n // which will be retrieved from `options`.\n I18n.pluralize = function(count, scope, options) {\n options = this.prepareOptions({count: String(count)}, options)\n var pluralizer, message, result;\n\n result = this.pluralizationLookup(count, scope, options);\n if (result.translations == undefined || result.translations == null) {\n return this.missingTranslation(scope, options);\n }\n\n if (result.message != undefined && result.message != null) {\n return this.interpolate(result.message, options);\n }\n else {\n pluralizer = this.pluralization.get(options.locale);\n return this.missingTranslation(scope + '.' + pluralizer(count)[0], options);\n }\n };\n\n // Return a missing translation message for the given parameters.\n I18n.missingTranslation = function(scope, options) {\n //guess intended string\n if(this.missingBehaviour == 'guess'){\n //get only the last portion of the scope\n var s = scope.split('.').slice(-1)[0];\n //replace underscore with space && camelcase with space and lowercase letter\n return (this.missingTranslationPrefix.length > 0 ? this.missingTranslationPrefix : '') +\n s.replace('_',' ').replace(/([a-z])([A-Z])/g,\n function(match, p1, p2) {return p1 + ' ' + p2.toLowerCase()} );\n }\n\n var localeForTranslation = (options != null && options.locale != null) ? options.locale : this.currentLocale();\n var fullScope = this.getFullScope(scope, options);\n var fullScopeWithLocale = [localeForTranslation, fullScope].join(this.defaultSeparator);\n\n return '[missing \"' + fullScopeWithLocale + '\" translation]';\n };\n\n // Return a missing placeholder message for given parameters\n I18n.missingPlaceholder = function(placeholder, message, options) {\n return \"[missing \" + placeholder + \" value]\";\n };\n\n I18n.nullPlaceholder = function() {\n return I18n.missingPlaceholder.apply(I18n, arguments);\n };\n\n // Format number using localization rules.\n // The options will be retrieved from the `number.format` scope.\n // If this isn't present, then the following options will be used:\n //\n // - `precision`: `3`\n // - `separator`: `\".\"`\n // - `delimiter`: `\",\"`\n // - `strip_insignificant_zeros`: `false`\n //\n // You can also override these options by providing the `options` argument.\n //\n I18n.toNumber = function(number, options) {\n options = this.prepareOptions(\n options\n , this.lookup(\"number.format\")\n , NUMBER_FORMAT\n );\n\n var negative = number < 0\n , string = toFixed(Math.abs(number), options.precision).toString()\n , parts = string.split(\".\")\n , precision\n , buffer = []\n , formattedNumber\n , format = options.format || \"%n\"\n , sign = negative ? \"-\" : \"\"\n ;\n\n number = parts[0];\n precision = parts[1];\n\n while (number.length > 0) {\n buffer.unshift(number.substr(Math.max(0, number.length - 3), 3));\n number = number.substr(0, number.length -3);\n }\n\n formattedNumber = buffer.join(options.delimiter);\n\n if (options.strip_insignificant_zeros && precision) {\n precision = precision.replace(/0+$/, \"\");\n }\n\n if (options.precision > 0 && precision) {\n formattedNumber += options.separator + precision;\n }\n\n if (options.sign_first) {\n format = \"%s\" + format;\n }\n else {\n format = format.replace(\"%n\", \"%s%n\");\n }\n\n formattedNumber = format\n .replace(\"%u\", options.unit)\n .replace(\"%n\", formattedNumber)\n .replace(\"%s\", sign)\n ;\n\n return formattedNumber;\n };\n\n // Format currency with localization rules.\n // The options will be retrieved from the `number.currency.format` and\n // `number.format` scopes, in that order.\n //\n // Any missing option will be retrieved from the `I18n.toNumber` defaults and\n // the following options:\n //\n // - `unit`: `\"$\"`\n // - `precision`: `2`\n // - `format`: `\"%u%n\"`\n // - `delimiter`: `\",\"`\n // - `separator`: `\".\"`\n //\n // You can also override these options by providing the `options` argument.\n //\n I18n.toCurrency = function(number, options) {\n options = this.prepareOptions(\n options\n , this.lookup(\"number.currency.format\")\n , this.lookup(\"number.format\")\n , CURRENCY_FORMAT\n );\n\n return this.toNumber(number, options);\n };\n\n // Localize several values.\n // You can provide the following scopes: `currency`, `number`, or `percentage`.\n // If you provide a scope that matches the `/^(date|time)/` regular expression\n // then the `value` will be converted by using the `I18n.toTime` function.\n //\n // It will default to the value's `toString` function.\n //\n I18n.localize = function(scope, value, options) {\n options || (options = {});\n\n switch (scope) {\n case \"currency\":\n return this.toCurrency(value);\n case \"number\":\n scope = this.lookup(\"number.format\");\n return this.toNumber(value, scope);\n case \"percentage\":\n return this.toPercentage(value);\n default:\n var localizedValue;\n\n if (scope.match(/^(date|time)/)) {\n localizedValue = this.toTime(scope, value);\n } else {\n localizedValue = value.toString();\n }\n\n return this.interpolate(localizedValue, options);\n }\n };\n\n // Parse a given `date` string into a JavaScript Date object.\n // This function is time zone aware.\n //\n // The following string formats are recognized:\n //\n // yyyy-mm-dd\n // yyyy-mm-dd[ T]hh:mm::ss\n // yyyy-mm-dd[ T]hh:mm::ss\n // yyyy-mm-dd[ T]hh:mm::ssZ\n // yyyy-mm-dd[ T]hh:mm::ss+0000\n // yyyy-mm-dd[ T]hh:mm::ss+00:00\n // yyyy-mm-dd[ T]hh:mm::ss.123Z\n //\n I18n.parseDate = function(date) {\n var matches, convertedDate, fraction;\n // we have a date, so just return it.\n if (typeof(date) == \"object\") {\n return date;\n };\n\n matches = date.toString().match(/(\\d{4})-(\\d{2})-(\\d{2})(?:[ T](\\d{2}):(\\d{2}):(\\d{2})([\\.,]\\d{1,3})?)?(Z|\\+00:?00)?/);\n\n if (matches) {\n for (var i = 1; i <= 6; i++) {\n matches[i] = parseInt(matches[i], 10) || 0;\n }\n\n // month starts on 0\n matches[2] -= 1;\n\n fraction = matches[7] ? 1000 * (\"0\" + matches[7]) : null;\n\n if (matches[8]) {\n convertedDate = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], fraction));\n } else {\n convertedDate = new Date(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], fraction);\n }\n } else if (typeof(date) == \"number\") {\n // UNIX timestamp\n convertedDate = new Date();\n convertedDate.setTime(date);\n } else if (date.match(/([A-Z][a-z]{2}) ([A-Z][a-z]{2}) (\\d+) (\\d+:\\d+:\\d+) ([+-]\\d+) (\\d+)/)) {\n // This format `Wed Jul 20 13:03:39 +0000 2011` is parsed by\n // webkit/firefox, but not by IE, so we must parse it manually.\n convertedDate = new Date();\n convertedDate.setTime(Date.parse([\n RegExp.$1, RegExp.$2, RegExp.$3, RegExp.$6, RegExp.$4, RegExp.$5\n ].join(\" \")));\n } else if (date.match(/\\d+ \\d+:\\d+:\\d+ [+-]\\d+ \\d+/)) {\n // a valid javascript format with timezone info\n convertedDate = new Date();\n convertedDate.setTime(Date.parse(date));\n } else {\n // an arbitrary javascript string\n convertedDate = new Date();\n convertedDate.setTime(Date.parse(date));\n }\n\n return convertedDate;\n };\n\n // Formats time according to the directives in the given format string.\n // The directives begins with a percent (%) character. Any text not listed as a\n // directive will be passed through to the output string.\n //\n // The accepted formats are:\n //\n // %a - The abbreviated weekday name (Sun)\n // %A - The full weekday name (Sunday)\n // %b - The abbreviated month name (Jan)\n // %B - The full month name (January)\n // %c - The preferred local date and time representation\n // %d - Day of the month (01..31)\n // %-d - Day of the month (1..31)\n // %H - Hour of the day, 24-hour clock (00..23)\n // %-H - Hour of the day, 24-hour clock (0..23)\n // %I - Hour of the day, 12-hour clock (01..12)\n // %-I - Hour of the day, 12-hour clock (1..12)\n // %m - Month of the year (01..12)\n // %-m - Month of the year (1..12)\n // %M - Minute of the hour (00..59)\n // %-M - Minute of the hour (0..59)\n // %p - Meridian indicator (AM or PM)\n // %S - Second of the minute (00..60)\n // %-S - Second of the minute (0..60)\n // %w - Day of the week (Sunday is 0, 0..6)\n // %y - Year without a century (00..99)\n // %-y - Year without a century (0..99)\n // %Y - Year with century\n // %z - Timezone offset (+0545)\n //\n I18n.strftime = function(date, format) {\n var options = this.lookup(\"date\")\n , meridianOptions = I18n.meridian()\n ;\n\n if (!options) {\n options = {};\n }\n\n options = this.prepareOptions(options, DATE);\n\n if (isNaN(date.getTime())) {\n throw new Error('I18n.strftime() requires a valid date object, but received an invalid date.');\n }\n\n var weekDay = date.getDay()\n , day = date.getDate()\n , year = date.getFullYear()\n , month = date.getMonth() + 1\n , hour = date.getHours()\n , hour12 = hour\n , meridian = hour > 11 ? 1 : 0\n , secs = date.getSeconds()\n , mins = date.getMinutes()\n , offset = date.getTimezoneOffset()\n , absOffsetHours = Math.floor(Math.abs(offset / 60))\n , absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60)\n , timezoneoffset = (offset > 0 ? \"-\" : \"+\") +\n (absOffsetHours.toString().length < 2 ? \"0\" + absOffsetHours : absOffsetHours) +\n (absOffsetMinutes.toString().length < 2 ? \"0\" + absOffsetMinutes : absOffsetMinutes)\n ;\n\n if (hour12 > 12) {\n hour12 = hour12 - 12;\n } else if (hour12 === 0) {\n hour12 = 12;\n }\n\n format = format.replace(\"%a\", options.abbr_day_names[weekDay]);\n format = format.replace(\"%A\", options.day_names[weekDay]);\n format = format.replace(\"%b\", options.abbr_month_names[month]);\n format = format.replace(\"%B\", options.month_names[month]);\n format = format.replace(\"%d\", padding(day));\n format = format.replace(\"%e\", day);\n format = format.replace(\"%-d\", day);\n format = format.replace(\"%H\", padding(hour));\n format = format.replace(\"%-H\", hour);\n format = format.replace(\"%I\", padding(hour12));\n format = format.replace(\"%-I\", hour12);\n format = format.replace(\"%m\", padding(month));\n format = format.replace(\"%-m\", month);\n format = format.replace(\"%M\", padding(mins));\n format = format.replace(\"%-M\", mins);\n format = format.replace(\"%p\", meridianOptions[meridian]);\n format = format.replace(\"%S\", padding(secs));\n format = format.replace(\"%-S\", secs);\n format = format.replace(\"%w\", weekDay);\n format = format.replace(\"%y\", padding(year));\n format = format.replace(\"%-y\", padding(year).replace(/^0+/, \"\"));\n format = format.replace(\"%Y\", year);\n format = format.replace(\"%z\", timezoneoffset);\n\n return format;\n };\n\n // Convert the given dateString into a formatted date.\n I18n.toTime = function(scope, dateString) {\n var date = this.parseDate(dateString)\n , format = this.lookup(scope)\n ;\n\n if (date.toString().match(/invalid/i)) {\n return date.toString();\n }\n\n if (!format) {\n return date.toString();\n }\n\n return this.strftime(date, format);\n };\n\n // Convert a number into a formatted percentage value.\n I18n.toPercentage = function(number, options) {\n options = this.prepareOptions(\n options\n , this.lookup(\"number.percentage.format\")\n , this.lookup(\"number.format\")\n , PERCENTAGE_FORMAT\n );\n\n return this.toNumber(number, options);\n };\n\n // Convert a number into a readable size representation.\n I18n.toHumanSize = function(number, options) {\n var kb = 1024\n , size = number\n , iterations = 0\n , unit\n , precision\n ;\n\n while (size >= kb && iterations < 4) {\n size = size / kb;\n iterations += 1;\n }\n\n if (iterations === 0) {\n unit = this.t(\"number.human.storage_units.units.byte\", {count: size});\n precision = 0;\n } else {\n unit = this.t(\"number.human.storage_units.units.\" + SIZE_UNITS[iterations]);\n precision = (size - Math.floor(size) === 0) ? 0 : 1;\n }\n\n options = this.prepareOptions(\n options\n , {unit: unit, precision: precision, format: \"%n%u\", delimiter: \"\"}\n );\n\n return this.toNumber(size, options);\n };\n\n I18n.getFullScope = function(scope, options) {\n options = options || {}\n\n // Deal with the scope as an array.\n if (isArray(scope)) {\n scope = scope.join(this.defaultSeparator);\n }\n\n // Deal with the scope option provided through the second argument.\n //\n // I18n.t('hello', {scope: 'greetings'});\n //\n if (options.scope) {\n scope = [options.scope, scope].join(this.defaultSeparator);\n }\n\n return scope;\n };\n /**\n * Merge obj1 with obj2 (shallow merge), without modifying inputs\n * @param {Object} obj1\n * @param {Object} obj2\n * @returns {Object} Merged values of obj1 and obj2\n *\n * In order to support ES3, `Object.prototype.hasOwnProperty.call` is used\n * Idea is from:\n * https://stackoverflow.com/questions/8157700/object-has-no-hasownproperty-method-i-e-its-undefined-ie8\n */\n I18n.extend = function ( obj1, obj2 ) {\n if (typeof(obj1) === \"undefined\" && typeof(obj2) === \"undefined\") {\n return {};\n }\n return merge(obj1, obj2);\n };\n\n // Set aliases, so we can save some typing.\n I18n.t = I18n.translate;\n I18n.l = I18n.localize;\n I18n.p = I18n.pluralize;\n\n return I18n;\n}));\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output} from \"@angular/core\";\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {CardViewOrientation} from \"core-components/wp-card-view/wp-card-view.component\";\nimport {WorkPackageViewSortByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-sort-by.service\";\nimport {distinctUntilChanged, takeUntil} from \"rxjs/operators\";\nimport {HighlightingMode} from \"core-components/wp-fast-table/builders/highlighting/highlighting-mode.const\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {DragAndDropService} from \"core-app/modules/common/drag-and-drop/drag-and-drop.service\";\nimport {WorkPackageCardDragAndDropService} from \"core-components/wp-card-view/services/wp-card-drag-and-drop.service\";\nimport {WorkPackagesListService} from \"core-components/wp-list/wp-list.service\";\nimport {WorkPackageTableConfiguration} from \"core-components/wp-table/wp-table-configuration\";\nimport {WorkPackageViewOutputs} from \"core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry\";\n\n@Component({\n selector: 'wp-grid',\n template: `\n \n \n\n
    \n \n
    \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n DragAndDropService,\n WorkPackageCardDragAndDropService\n ]\n})\nexport class WorkPackagesGridComponent implements WorkPackageViewOutputs {\n @Input() public configuration:WorkPackageTableConfiguration;\n @Input() public showResizer:boolean = false;\n @Input() public resizerClass:string = '';\n @Input() public resizerStorageKey:string = '';\n\n @Output() selectionChanged = new EventEmitter();\n @Output() itemClicked = new EventEmitter<{ workPackageId:string, double:boolean }>();\n @Output() stateLinkClicked = new EventEmitter<{ workPackageId:string, requestedState:string }>();\n\n public canDragOutOf:() => boolean;\n public dragInto:boolean;\n public gridOrientation:CardViewOrientation = 'horizontal';\n public highlightingMode:HighlightingMode = 'none';\n\n constructor(readonly wpTableHighlight:WorkPackageViewHighlightingService,\n readonly wpTableSortBy:WorkPackageViewSortByService,\n readonly wpList:WorkPackagesListService,\n readonly querySpace:IsolatedQuerySpace,\n readonly cdRef:ChangeDetectorRef) {\n }\n\n ngOnInit() {\n this.dragInto = this.configuration.dragAndDropEnabled;\n this.canDragOutOf = () => {\n return this.configuration.dragAndDropEnabled;\n };\n\n this.wpTableHighlight\n .updates$()\n .pipe(\n takeUntil(this.querySpace.stopAllSubscriptions),\n distinctUntilChanged()\n )\n .subscribe(() => {\n this.highlightingMode = this.wpTableHighlight.current.mode;\n this.cdRef.detectChanges();\n });\n\n }\n\n public switchToManualSorting() {\n let query = this.querySpace.query.value;\n if (query && this.wpTableSortBy.switchToManualSorting(query)) {\n this.wpList.save(query);\n }\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ViewEncapsulation\n} from '@angular/core';\nimport {WorkPackageViewFiltersService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service';\nimport {WorkPackageFiltersService} from 'core-components/filters/wp-filters/wp-filters.service';\nimport {DebouncedEventEmitter} from \"core-components/angular/debounced-event-emitter\";\nimport {QueryFilterInstanceResource} from \"core-app/modules/hal/resources/query-filter-instance-resource\";\nimport {Observable} from \"rxjs\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\n\n@Component({\n templateUrl: './filter-container.directive.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'filter-container'\n})\nexport class WorkPackageFilterContainerComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {\n @Input('showFilterButton') showFilterButton:boolean = false;\n @Input('filterButtonText') filterButtonText:string = I18n.t('js.button_filter');\n @Output() public filtersChanged = new DebouncedEventEmitter(componentDestroyed(this));\n\n public visible$:Observable;\n public filters = this.wpTableFilters.current;\n public loaded = false;\n\n constructor(readonly wpTableFilters:WorkPackageViewFiltersService,\n readonly cdRef:ChangeDetectorRef,\n readonly wpFiltersService:WorkPackageFiltersService) {\n super();\n this.visible$ = this.wpFiltersService.observeUntil(componentDestroyed(this));\n }\n\n ngOnInit():void {\n this.wpTableFilters\n .pristine$()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.filters = this.wpTableFilters.current;\n this.loaded = true;\n this.cdRef.detectChanges();\n });\n }\n\n public replaceIfComplete(filters:QueryFilterInstanceResource[]) {\n let available = filters.filter(el => this.wpTableFilters.isAvailable(el));\n this.wpTableFilters.replaceIfComplete(available);\n this.filtersChanged.emit(available);\n }\n}\n","\n\n
    \n
    \n \n
    \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {AfterViewInit, Component, ElementRef, EventEmitter, Input, OnDestroy, Output, ViewChild} from '@angular/core';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {TimezoneService} from 'core-components/datetime/timezone.service';\nimport {DatePicker} from \"core-app/modules/common/op-date-picker/datepicker\";\nimport {DebouncedEventEmitter} from \"core-components/angular/debounced-event-emitter\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {keyCodes} from \"core-app/modules/common/keyCodes.enum\";\nimport {Instance} from \"flatpickr/dist/types/instance\";\n\n@Component({\n selector: 'op-date-picker',\n templateUrl: './op-date-picker.component.html'\n})\nexport class OpDatePickerComponent extends UntilDestroyedMixin implements OnDestroy, AfterViewInit {\n @Output() public onChange = new DebouncedEventEmitter(componentDestroyed(this));\n @Output() public onCancel = new EventEmitter();\n\n @Input() public initialDate:string = '';\n @Input() public appendTo?:HTMLElement = document.body;\n @Input() public classes:string = '';\n @Input() public id:string = '';\n @Input() public name:string = '';\n @Input() public required:boolean = false;\n @Input() public size:number = 20;\n @Input() public focus:boolean = false;\n @Input() public disabled:boolean = false;\n\n @ViewChild('dateInput') dateInput:ElementRef;\n\n private datePickerInstance:DatePicker;\n\n public constructor(private elementRef:ElementRef,\n private ConfigurationService:ConfigurationService,\n private timezoneService:TimezoneService) {\n super();\n\n if (!this.id) {\n this.id = 'datepicker-input-' + Math.floor(Math.random() * 1000).toString(3);\n }\n }\n\n ngAfterViewInit():void {\n this.initializeDatepicker();\n }\n\n ngOnDestroy() {\n this.datePickerInstance && this.datePickerInstance.destroy();\n }\n\n openOnClick() {\n if (!this.disabled) {\n this.datePickerInstance.show();\n }\n }\n\n onInputChange(_event:KeyboardEvent) {\n if (this.isEmpty()) {\n this.datePickerInstance.clear();\n } else if (this.inputIsValidDate()) {\n this.onChange.emit(this.currentValue);\n }\n }\n\n closeOnOutsideClick(event:any) {\n if (!(event.relatedTarget &&\n this.datePickerInstance.datepickerInstance.calendarContainer.contains(event.relatedTarget))) {\n this.datePickerInstance.hide();\n }\n }\n\n private isEmpty():boolean {\n return this.currentValue.trim() === '';\n }\n\n private get currentValue():string {\n return this.inputElement?.value || '';\n }\n\n private get inputElement():HTMLInputElement {\n return this.dateInput.nativeElement;\n }\n\n private inputIsValidDate():boolean {\n return this.currentValue.match(/\\d{4}-\\d{2}-\\d{2}/) !== null;\n }\n\n private initializeDatepicker() {\n let options:any = {\n allowInput: true,\n appendTo: this.appendTo,\n onChange:(selectedDates:Date[], dateStr:string) => {\n let val:string = dateStr;\n\n if (this.isEmpty()) {\n return;\n }\n\n this.inputElement.value = val;\n this.onChange.emit(val);\n },\n onKeyDown: (selectedDates:Date[], dateStr:string, instance:Instance, data:KeyboardEvent) => {\n if (data.which == keyCodes.ESCAPE) {\n this.onCancel.emit();\n }\n }\n };\n\n let initialValue;\n if (this.isEmpty && this.initialDate) {\n initialValue = this.timezoneService.parseISODate(this.initialDate).toDate();\n } else {\n initialValue = this.currentValue;\n }\n\n this.datePickerInstance = new DatePicker(\n '#' + this.id,\n initialValue,\n options\n );\n }\n}\n","\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {InputState} from 'reactivestates';\n\nexport class StatusResource extends HalResource {\n\n isClosed:boolean;\n isDefault:boolean;\n\n public get state():InputState {\n return this.states.statuses.get(this.href as string) as any;\n }\n}\n\n","import {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Injectable, OnDestroy} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {States} from 'core-components/states.service';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {RenderedWorkPackage} from \"core-app/modules/work_packages/render-info/rendered-work-package.type\";\nimport {WorkPackageViewBaseService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {WorkPackageCollectionResource} from \"core-app/modules/hal/resources/wp-collection-resource\";\n\nexport interface WorkPackageViewSelectionState {\n // Map of selected rows\n selected:{ [workPackageId:string]:boolean };\n // Index of current selection\n // required for shift-offsets\n activeRowIndex:number|null;\n}\n\n@Injectable()\nexport class WorkPackageViewSelectionService extends WorkPackageViewBaseService implements OnDestroy {\n\n public constructor(readonly querySpace:IsolatedQuerySpace,\n readonly states:States,\n readonly opContextMenu:OPContextMenuService) {\n super(querySpace);\n this.reset();\n }\n\n ngOnDestroy():void {\n Mousetrap.unbind(['command+d', 'ctrl+d']);\n Mousetrap.unbind(['command+a', 'ctrl+a']);\n }\n\n public initializeSelection(selectedWorkPackageIds:string[]) {\n let state:WorkPackageViewSelectionState = {\n selected: {},\n activeRowIndex: null\n };\n\n selectedWorkPackageIds.forEach(id => state.selected[id] = true);\n\n this.updatesState.clear();\n this.pristineState.putValue(state);\n }\n\n public isSelected(workPackageId:string):boolean {\n return !!this.current?.selected[workPackageId];\n }\n\n /**\n * Select all work packages\n */\n public selectAll(rows:RenderedWorkPackage[]) {\n const state:WorkPackageViewSelectionState = this._emptyState;\n\n rows.forEach((row) => {\n if (row.workPackageId) {\n state.selected[row.workPackageId] = true;\n }\n });\n\n this.update(state);\n }\n\n /**\n * Get the current work package resource form the selection state.\n */\n public getSelectedWorkPackages():WorkPackageResource[] {\n let wpState = this.states.workPackages;\n return this.getSelectedWorkPackageIds().map(id => wpState.get(id).value!);\n }\n\n public getSelectedWorkPackageIds():string[] {\n let selected:string[] = [];\n\n _.each(this.current?.selected, (isSelected:boolean, wpId:string) => {\n if (isSelected) {\n selected.push(wpId);\n }\n });\n\n return selected;\n }\n\n /**\n * Reset the selection state to an empty selection\n */\n public reset() {\n this.update(this._emptyState);\n }\n\n public get isEmpty() {\n return this.selectionCount === 0;\n }\n\n /**\n * Return the number of selected rows.\n */\n public get selectionCount():number {\n return _.size(this.current?.selected);\n }\n\n /**\n * Toggle a single row selection state and update the state.\n * @param workPackageId\n */\n public toggleRow(workPackageId:string) {\n let isSelected = this.current?.selected[workPackageId];\n this.setRowState(workPackageId, !isSelected);\n }\n\n /**\n * Force the given work package's selection state. Does not modify other states.\n * @param workPackageId\n * @param newState\n */\n public setRowState(workPackageId:string, newState:boolean) {\n let state = this.current || this._emptyState;\n state.selected[workPackageId] = newState;\n this.update(state);\n }\n\n /**\n * Override current selection with the given work package id.\n */\n public setSelection(wpId:string, position:number) {\n const current = this._emptyState;\n current.selected[wpId] = true;\n current.activeRowIndex = position;\n\n this.update(current);\n }\n\n /**\n * Select a number of rows from the current `activeRowIndex`\n * to the selected target.\n * (aka shift click expansion)\n */\n public setMultiSelectionFrom(rows:RenderedWorkPackage[], wpId:string, position:number) {\n let state = this.current || this._emptyState;\n\n // If there are no other selections, it does not matter what the index is\n if (this.selectionCount === 0 || state.activeRowIndex === null) {\n state.selected[wpId] = true;\n state.activeRowIndex = position;\n } else {\n let start = Math.min(position, state.activeRowIndex);\n let end = Math.max(position, state.activeRowIndex);\n\n rows.forEach((row, i) => {\n if (row.workPackageId) {\n state.selected[row.workPackageId] = i >= start && i <= end;\n }\n });\n }\n\n this.update(state);\n }\n\n public registerSelectAllListener(renderedElements:() => RenderedWorkPackage[]) {\n // Bind CTRL+A to select all work packages\n Mousetrap.bind(['command+a', 'ctrl+a'], (e) => {\n this.selectAll(renderedElements());\n e.preventDefault();\n\n this.opContextMenu.close();\n return false;\n });\n }\n\n public registerDeselectAllListener() {\n // Bind CTRL+D to deselect all work packages\n Mousetrap.bind(['command+d', 'ctrl+d'], (e) => {\n this.reset();\n e.preventDefault();\n\n this.opContextMenu.close();\n return false;\n });\n }\n\n private get _emptyState():WorkPackageViewSelectionState {\n return {\n selected: {},\n activeRowIndex: null\n };\n }\n\n valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource):WorkPackageViewSelectionState|undefined {\n return undefined;\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\n@Injectable()\nexport class WpChildrenInlineCreateService extends WorkPackageInlineCreateService implements WpRelationInlineCreateServiceInterface {\n\n constructor(readonly injector:Injector,\n protected readonly wpRelationsHierarchyService:WorkPackageRelationsHierarchyService,\n protected readonly schemaCache:SchemaCacheService) {\n super(injector);\n }\n\n /**\n * A separate reference pane for the inline create component\n */\n public readonly referenceComponentClass = WpRelationInlineAddExistingComponent;\n\n /**\n * Define the reference type\n */\n public relationType:string = 'children';\n\n /**\n * Add a new relation of the above type\n */\n public add(from:WorkPackageResource, toId:string):Promise {\n return this.wpRelationsHierarchyService.addExistingChildWp(from, toId);\n }\n\n /**\n * Remove a given relation\n */\n public remove(from:WorkPackageResource, to:WorkPackageResource):Promise {\n return this.wpRelationsHierarchyService.removeChild(to);\n }\n\n /**\n * A related work package for the inline create context\n */\n public referenceTarget:WorkPackageResource|null = null;\n\n public get canAdd() {\n return !!(this.referenceTarget && this.canCreateWorkPackages && this.canAddChild);\n }\n\n public get canReference() {\n return !!(this.referenceTarget && this.canAddChild);\n }\n\n public get canAddChild() {\n return this.schema && !this.schema.isMilestone && this.referenceTarget!.changeParent;\n }\n\n /**\n * Reference button text\n */\n public readonly buttonTexts = {\n reference: this.I18n.t('js.relation_buttons.add_existing_child'),\n create: this.I18n.t('js.relation_buttons.add_new_child')\n };\n\n private get schema() {\n return this.referenceTarget && this.schemaCache.of(this.referenceTarget);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from \"@angular/core\";\nimport {HttpEvent, HttpResponse} from \"@angular/common/http\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {from, Observable, of} from \"rxjs\";\nimport {share, switchMap} from \"rxjs/operators\";\nimport {OpenProjectFileUploadService, UploadBlob, UploadFile, UploadInProgress} from './op-file-upload.service';\n\ninterface PrepareUploadResult {\n url:string;\n form:FormData;\n response:any;\n}\n\n@Injectable()\nexport class OpenProjectDirectFileUploadService extends OpenProjectFileUploadService {\n /**\n * Upload a single file, get an UploadResult observable\n * @param {string} url\n * @param {UploadFile} file\n * @param {string} method\n */\n public uploadSingle(url:string, file:UploadFile|UploadBlob, method:string = 'post', responseType:'text'|'json' = 'text') {\n const observable = from(this.getDirectUploadFormFrom(url, file))\n .pipe(\n switchMap(this.uploadToExternal(file, method, responseType)),\n share()\n );\n\n return [file, observable] as UploadInProgress;\n }\n\n private uploadToExternal(file:UploadFile|UploadBlob, method:string, responseType:string):(result:PrepareUploadResult) => Observable> {\n return result => {\n result.form.append('file', file, file.customName || file.name);\n\n return this\n .http\n .request(\n method,\n result.url,\n {\n body: result.form,\n // Observe the response, not the body\n observe: 'events',\n // This is important as the CORS policy for the bucket is * and you can't use credentals then,\n // besides we don't need them here anyway.\n withCredentials: false,\n responseType: responseType as any,\n // Subscribe to progress events. subscribe() will fire multiple times!\n reportProgress: true\n }\n )\n .pipe(switchMap(this.finishUpload(result)));\n };\n }\n\n private finishUpload(result:PrepareUploadResult):(result:HttpEvent) => Observable> {\n return event => {\n if (event instanceof HttpResponse) {\n return this\n .http\n .get(\n result.response._links.completeUpload.href,\n {\n observe: 'response'\n }\n );\n }\n\n // Return as new observable due to switchMap\n return of(event);\n };\n }\n\n public getDirectUploadFormFrom(url:string, file:UploadFile|UploadBlob):Promise {\n const formData = new FormData();\n const metadata = {\n description: file.description,\n fileName: file.customName || file.name,\n fileSize: file.size,\n contentType: file.type\n };\n\n /*\n * @TODO We could calculate the MD5 hash here too and pass that.\n * The MD5 hash can be used as the `content-md5` option during the upload to S3 for instance.\n * This way S3 can verify the integrity of the file which we currently don't do.\n */\n\n // add the metadata object\n formData.append(\n 'metadata',\n JSON.stringify(metadata),\n );\n\n const result = this\n .http\n .request(\n \"post\",\n url,\n {\n body: formData,\n withCredentials: true,\n responseType: \"json\" as any\n }\n )\n .toPromise()\n .then((res) => {\n let form = new FormData();\n\n _.each(res._links.addAttachment.form_fields, (value, key) => {\n form.append(key, value);\n });\n\n return { url: res._links.addAttachment.href, form: form, response: res };\n });\n\n return result;\n }\n}\n","import {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {QueryFilterInstanceResource} from 'core-app/modules/hal/resources/query-filter-instance-resource';\nimport {CurrentUserService} from \"core-components/user/current-user.service\";\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {Injector} from '@angular/core';\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {WorkPackageChangeset} from \"core-components/wp-edit/work-package-changeset\";\nimport compareByHrefOrString = AngularTrackingHelpers.compareByHrefOrString;\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\n\nexport class WorkPackageFilterValues {\n\n @InjectField() currentUser:CurrentUserService;\n @InjectField() halResourceService:HalResourceService;\n\n handlers:Partial void>> = {\n '=': this.applyFirstValue.bind(this),\n '!*': this.setToNull.bind(this)\n };\n\n constructor(public injector:Injector,\n private filters:QueryFilterInstanceResource[],\n private excluded:string[] = []) {\n\n }\n\n public applyDefaultsFromFilters(change:WorkPackageChangeset|Object) {\n _.each(this.filters, filter => {\n // Exclude filters specified in constructor\n if (this.excluded.indexOf(filter.id) !== -1) {\n return;\n }\n\n // Look for a handler with the filter's operator\n const operator = filter.operator.id as FilterOperator;\n const handler = this.handlers[operator];\n\n // Apply the filter if there is any\n handler?.call(this, change, filter);\n });\n }\n\n /**\n * Apply a positive value from a '=' [value] filter\n *\n * @param filter A positive '=' filter with at least one value\n * @private\n */\n private applyFirstValue(change:WorkPackageChangeset|{[id:string]:any}, filter:QueryFilterInstanceResource):void {\n // Avoid setting a value if current value is in filter list\n // and more than one value selected\n if (this.filterAlreadyApplied(change, filter)) {\n return;\n }\n\n // Select the first value\n let value = filter.values[0];\n\n // Avoid empty values\n if (value) {\n let attributeName = this.mapFilterToAttribute(filter);\n this.setValueFor(change, attributeName, value);\n }\n }\n\n /**\n * Set a value no null for a none type filter (!*)\n *\n * @param filter A none '!*' filter\n * @private\n */\n private setToNull(change:WorkPackageChangeset|{[id:string]:any}, filter:QueryFilterInstanceResource):void {\n let attributeName = this.mapFilterToAttribute(filter);\n\n this.setValue(change, attributeName,{ href: null });\n }\n\n private setValueFor(change:WorkPackageChangeset|Object, field:string, value:string|HalResource) {\n let newValue = this.findSpecialValue(value, field) || value;\n\n if (newValue) {\n this.setValue(change, field, newValue);\n }\n }\n\n private setValue(change:WorkPackageChangeset|{[id:string]:any}, field:string, value:any) {\n if (change instanceof WorkPackageChangeset) {\n change.setValue(field, value);\n } else {\n change[field] = value;\n }\n }\n\n /**\n * Returns special values for which no allowed values exist (e.g., parent ID in embedded queries)\n * @param {string | HalResource} value\n * @param {string} field\n */\n private findSpecialValue(value:string|HalResource, field:string):string|HalResource|undefined {\n if (field === 'parent') {\n return value;\n }\n\n if (value instanceof HalResource && value.$href === '/api/v3/users/me' && this.currentUser.isLoggedIn) {\n return this.halResourceService.fromSelfLink(`/api/v3/users/${this.currentUser.userId}`);\n }\n\n return undefined;\n }\n\n /**\n * Avoid applying filter values when\n * - more than one filter value selected\n * - changeset already matches one of the selected values\n * @param filter\n */\n private filterAlreadyApplied(change:WorkPackageChangeset|{[id:string]:any}, filter:any):boolean {\n // Only applicable if more than one selected\n if (filter.values.length <= 1) {\n return false;\n }\n\n const current = change instanceof WorkPackageChangeset ? change.projectedResource[filter.id] : change[filter.id];\n\n for (let i = 0; i < filter.values.length; i++) {\n if (compareByHrefOrString(current, filter.values[i])) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Some filter ids need to be mapped to a different attribute name\n * in order to be processed correctly.\n *\n * @param filter The filter to map\n * @returns An attribute name string to set\n * @private\n */\n private mapFilterToAttribute(filter:any):string {\n if (filter.id === 'onlySubproject') {\n return 'project';\n }\n\n // Default to returning the filter id\n return filter.id;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Injector,\n OnInit,\n ElementRef,\n NgZone\n} from \"@angular/core\";\nimport {take} from \"rxjs/operators\";\nimport {CausedUpdatesService} from \"core-app/modules/boards/board/caused-updates/caused-updates.service\";\nimport {DragAndDropService} from \"core-app/modules/common/drag-and-drop/drag-and-drop.service\";\nimport {\n WorkPackageViewDisplayRepresentationService,\n wpDisplayCardRepresentation\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageTableConfigurationObject} from \"core-components/wp-table/wp-table-configuration\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {WorkPackageViewFiltersService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {StateService} from \"@uirouter/core\";\nimport {KeepTabService} from \"core-components/wp-single-view-tabs/keep-tab/keep-tab.service\";\n\n@Component({\n selector: 'wp-list-view',\n templateUrl: './wp-list-view.component.html',\n styleUrls: ['./wp-list-view.component.sass'],\n host: { 'class': 'work-packages-split-view--tabletimeline-side' },\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n { provide: HalResourceNotificationService, useClass: WorkPackageNotificationService },\n DragAndDropService,\n CausedUpdatesService\n ]\n})\nexport class WorkPackageListViewComponent extends UntilDestroyedMixin implements OnInit {\n\n text = {\n 'jump_to_pagination': this.I18n.t('js.work_packages.jump_marks.pagination'),\n 'text_jump_to_pagination': this.I18n.t('js.work_packages.jump_marks.label_pagination'),\n 'button_settings': this.I18n.t('js.button_settings')\n };\n\n /** Switch between list and card view */\n showTableView:boolean = true;\n\n /** Determine when query is initially loaded */\n tableInformationLoaded = false;\n\n /** If loaded list of work packages is empty */\n noResults:boolean = false;\n\n /** Whether we should render a blocked view */\n showResultOverlay$ = this.wpViewFilters.incomplete$;\n\n /** */\n readonly wpTableConfiguration:WorkPackageTableConfigurationObject = {\n dragAndDropEnabled: true\n };\n\n constructor(readonly I18n:I18nService,\n readonly injector:Injector,\n readonly $state:StateService,\n readonly keepTab:KeepTabService,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpViewFilters:WorkPackageViewFiltersService,\n readonly deviceService:DeviceService,\n readonly CurrentProject:CurrentProjectService,\n readonly wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef,\n private ngZone:NgZone) {\n super();\n }\n\n ngOnInit() {\n // Mark tableInformationLoaded when initially loading done\n this.setupInformationLoadedListener();\n\n this.querySpace.query.values$().pipe(\n this.untilDestroyed()\n ).subscribe((query) => {\n // Update the visible representation\n this.updateViewRepresentation(query);\n this.noResults = query.results.total === 0;\n this.cdRef.detectChanges();\n });\n\n // Scroll into view the card/row that represents the last selected WorkPackage\n // so when the user opens a WP detail page on a split-view and then clicks on\n // the 'back button', the last selected card is visible on this list.\n // ngAfterViewInit doesn't find the .-checked elements on components\n // that inherit from this class (BcfListContainerComponent) so\n // opting for a timeout 'runOutsideAngular' to avoid running change\n // detection on the entire app\n this.ngZone.runOutsideAngular(() => {\n setTimeout(() => {\n const selectedRow = this.elementRef.nativeElement.querySelector('.wp-table--row.-checked');\n const selectedCard = this.elementRef.nativeElement.querySelector('.wp-card.-checked');\n\n // The header of the table hides the scrolledIntoView element\n // so we scrollIntoView the previous element, if any\n if (selectedRow && selectedRow.previousSibling) {\n selectedRow.previousSibling.scrollIntoView({block: \"start\"});\n }\n\n if (selectedCard) {\n selectedCard.scrollIntoView({block: \"start\"});\n }\n }, 0);\n });\n }\n\n protected setupInformationLoadedListener() {\n this\n .querySpace\n .initialized\n .values$()\n .pipe(take(1))\n .subscribe(() => {\n this.tableInformationLoaded = true;\n this.cdRef.detectChanges();\n });\n }\n\n public showResizerInCardView():boolean {\n return false;\n }\n\n protected updateViewRepresentation(query:QueryResource) {\n this.showTableView = !(this.deviceService.isMobile ||\n this.wpDisplayRepresentation.valueFromQuery(query) === wpDisplayCardRepresentation);\n }\n\n handleWorkPackageClicked(event:{ workPackageId:string; double:boolean }) {\n if (event.double) {\n this.openInFullView(event.workPackageId);\n }\n }\n\n openStateLink(event:{ workPackageId:string; requestedState:string }) {\n this.$state.go(\n (this.keepTab as any)[event.requestedState] || event.requestedState,\n { workPackageId: event.workPackageId, focus: true }\n );\n }\n\n /**\n * Special handling for clicking on cards.\n * If we are on mobile, a click on the card should directly open the full view\n */\n handleWorkPackageCardClicked(event:{ workPackageId:string; double:boolean }) {\n if (this.deviceService.isMobile) {\n this.openInFullView(event.workPackageId);\n } else {\n this.handleWorkPackageClicked(event);\n }\n }\n\n private openInFullView(workPackageId:string) {\n this.$state.go(\n 'work-packages.show',\n { workPackageId: workPackageId }\n );\n }\n}\n","
    \n\n\n\n\n\n\n
    \n \n \n
    \n\n\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './overview-tab.html',\n selector: 'wp-overview-tab',\n})\nexport class WorkPackageOverviewTabComponent extends UntilDestroyedMixin {\n public workPackageId:string;\n public workPackage:WorkPackageResource;\n public tabName = this.I18n.t('js.label_latest_activity');\n\n public constructor(readonly I18n:I18nService,\n readonly $state:StateService,\n readonly apiV3Service:APIV3Service) {\n super();\n\n this.workPackageId = this.$state.params.workPackageId;\n\n this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp) => this.workPackage = wp);\n }\n}\n","\n\n
    \n
    \n
    \n

    \n
    \n
    \n\n \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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');\n","
    \n
    \n \n \n
    \n\n \n \n \n\n
    \n
    \n
    \n\n
    \n \n
    \n\n\n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n Injector,\n Input,\n OnInit,\n Output,\n ViewChild\n} from \"@angular/core\";\nimport {QueryResource} from 'core-app/modules/hal/resources/query-resource';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {QueryColumn} from \"app/components/wp-query/query-column\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WorkPackageCreateService} from \"core-components/wp-new/wp-create.service\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {CardHighlightingMode} from \"core-components/wp-fast-table/builders/highlighting/highlighting-mode.const\";\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {StateService} from \"@uirouter/core\";\nimport {States} from \"core-components/states.service\";\nimport {WorkPackageViewOrderService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-order.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {filter, map, withLatestFrom} from 'rxjs/operators';\nimport {CausedUpdatesService} from \"core-app/modules/boards/board/caused-updates/caused-updates.service\";\nimport {WorkPackageViewSelectionService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service\";\nimport {CardViewHandlerRegistry} from \"core-components/wp-card-view/event-handler/card-view-handler-registry\";\nimport {WorkPackageCardViewService} from \"core-components/wp-card-view/services/wp-card-view.service\";\nimport {WorkPackageCardDragAndDropService} from \"core-components/wp-card-view/services/wp-card-drag-and-drop.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {\n WorkPackageViewHandlerToken,\n WorkPackageViewOutputs\n} from \"core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\n\nexport type CardViewOrientation = 'horizontal'|'vertical';\n\n@Component({\n selector: 'wp-card-view',\n styleUrls: ['./styles/wp-card-view.component.sass', './styles/wp-card-view-horizontal.sass', './styles/wp-card-view-vertical.sass'],\n templateUrl: './wp-card-view.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WorkPackageCardViewComponent extends UntilDestroyedMixin implements OnInit, AfterViewInit, WorkPackageViewOutputs {\n @Input('dragOutOfHandler') public canDragOutOf:(wp:WorkPackageResource) => boolean;\n @Input() public dragInto:boolean;\n @Input() public highlightingMode:CardHighlightingMode;\n @Input() public workPackageAddedHandler:(wp:WorkPackageResource) => Promise;\n @Input() public showStatusButton:boolean = true;\n @Input() public showInfoButton:boolean = false;\n @Input() public orientation:CardViewOrientation = 'vertical';\n /** Whether cards are removable */\n @Input() public cardsRemovable:boolean = false;\n /** Whether a notification box shall be shown when there are no WP to display */\n @Input() public showEmptyResultsBox:boolean = false;\n /** Whether on special mobile version of the cards shall be shown */\n @Input() public shrinkOnMobile:boolean = false;\n\n /** Container reference */\n @ViewChild('container', { static: true }) public container:ElementRef;\n\n @Output() public onMoved = new EventEmitter();\n @Output() selectionChanged = new EventEmitter();\n @Output() itemClicked = new EventEmitter<{ workPackageId:string, double:boolean }>();\n @Output() stateLinkClicked = new EventEmitter<{ workPackageId:string, requestedState:string }>();\n\n public trackByHref = AngularTrackingHelpers.trackByHrefAndProperty('lockVersion');\n public query:QueryResource;\n public isResultEmpty:boolean = false;\n public columns:QueryColumn[];\n public text = {\n removeCard: this.I18n.t('js.card.remove_from_list'),\n addNewCard: this.I18n.t('js.card.add_new'),\n noResults: {\n title: this.I18n.t('js.work_packages.no_results.title'),\n description: this.I18n.t('js.work_packages.no_results.description')\n },\n };\n\n /** Inline create / reference properties */\n public canAdd = false;\n public canReference = false;\n public inReference = false;\n public referenceClass = this.wpInlineCreate.referenceComponentClass;\n // We need to mount a dynamic component into the view\n // but map the following output\n public referenceOutputs = {\n onCancel: () => this.setReferenceMode(false),\n onReferenced: (wp:WorkPackageResource) => this.cardDragDrop.addWorkPackageToQuery(wp, 0)\n };\n\n constructor(readonly querySpace:IsolatedQuerySpace,\n readonly states:States,\n readonly injector:Injector,\n readonly $state:StateService,\n readonly I18n:I18nService,\n readonly wpCreate:WorkPackageCreateService,\n readonly wpInlineCreate:WorkPackageInlineCreateService,\n readonly notificationService:WorkPackageNotificationService,\n readonly halEvents:HalEventsService,\n readonly authorisationService:AuthorisationService,\n readonly causedUpdates:CausedUpdatesService,\n readonly cdRef:ChangeDetectorRef,\n readonly pathHelper:PathHelperService,\n readonly wpTableSelection:WorkPackageViewSelectionService,\n readonly wpViewOrder:WorkPackageViewOrderService,\n readonly cardView:WorkPackageCardViewService,\n readonly cardDragDrop:WorkPackageCardDragAndDropService,\n readonly deviceService:DeviceService) {\n super();\n }\n\n ngOnInit() {\n this.registerCreationCallback();\n\n // Update permission on model updates\n this.authorisationService\n .observeUntil(componentDestroyed(this))\n .subscribe(() => {\n this.canAdd = this.wpInlineCreate.canAdd;\n this.canReference = this.wpInlineCreate.canReference;\n this.cdRef.detectChanges();\n });\n\n // Observe changes to the work packages in this view\n this.halEvents\n .aggregated$('WorkPackage')\n .pipe(\n map(events => events.filter(event => event.eventType === 'updated')),\n filter(events => {\n const wpIds:string[] = this.workPackages.map(el => el.id!.toString());\n return !!events.find(event => wpIds.indexOf(event.id) !== -1);\n })\n ).subscribe(() => {\n this.workPackages = this.wpViewOrder.orderedWorkPackages();\n this.cdRef.detectChanges();\n });\n\n this.querySpace.results\n .values$()\n .pipe(\n withLatestFrom(this.querySpace.query.values$()),\n this.untilDestroyed(),\n ).subscribe(([results, query]) => {\n this.query = query;\n this.workPackages = this.wpViewOrder.orderedWorkPackages();\n this.cardView.updateRenderedCardsValues(this.workPackages);\n this.isResultEmpty = this.workPackages.length === 0;\n this.cdRef.detectChanges();\n });\n }\n\n ngAfterViewInit() {\n this.cardDragDrop.init(this);\n\n // Register Drag & Drop only on desktop\n if (!this.deviceService.isMobile) {\n this.cardDragDrop.registerDragAndDrop();\n }\n\n // Register event handlers for the cards\n let registry = this.injector.get(WorkPackageViewHandlerToken, CardViewHandlerRegistry);\n if (registry instanceof CardViewHandlerRegistry) {\n registry.attachTo(this);\n } else {\n new registry(this.injector).attachTo(this);\n }\n this.wpTableSelection.registerSelectAllListener(() => {\n return this.cardView.renderedCards;\n });\n this.wpTableSelection.registerDeselectAllListener();\n }\n\n ngOnDestroy():void {\n super.ngOnDestroy();\n this.cardDragDrop.destroy();\n }\n\n public get workPackages():WorkPackageResource[] {\n return this.cardDragDrop.workPackages;\n }\n\n public set workPackages(workPackages:WorkPackageResource[]) {\n this.cardDragDrop.workPackages = workPackages;\n }\n\n public setReferenceMode(mode:boolean) {\n this.inReference = mode;\n this.cdRef.detectChanges();\n }\n\n public addNewCard() {\n this.cardDragDrop.addNewCard();\n }\n\n public removeCard(wp:WorkPackageResource) {\n this.cardDragDrop.removeCard(wp);\n }\n\n async onCardSaved(wp:WorkPackageResource) {\n await this.cardDragDrop.onCardSaved(wp);\n }\n\n public classes() {\n let classes = 'wp-cards-container ';\n classes += '-' + this.orientation;\n classes += this.shrinkOnMobile ? ' -shrink' : '';\n\n return classes;\n }\n\n /**\n * Listen to newly created work packages to detect whether the WP is the one we created,\n * and properly reset inline create in this case\n */\n private registerCreationCallback() {\n this.wpCreate\n .onNewWorkPackage()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(async (wp:WorkPackageResource) => {\n this.onCardSaved(wp);\n });\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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\";\nimport {WorkPackageFoldToggleButtonComponent} from \"core-components/wp-buttons/wp-fold-toggle-button/wp-fold-toggle-button.component\";\n\n@Component({\n selector: 'wp-view-page',\n templateUrl: '/app/modules/work_packages/routing/partitioned-query-space-page/partitioned-query-space-page.component.html',\n styleUrls: [\n // Absolute paths do not work for styleURLs :-(\n '../partitioned-query-space-page/partitioned-query-space-page.component.sass'\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n /** We need to provide the wpNotification service here to get correct save notifications for WP resources */\n { provide: HalResourceNotificationService, useClass: WorkPackageNotificationService },\n QueryParamListenerService\n ]\n})\nexport class WorkPackageViewPageComponent extends PartitionedQuerySpacePageComponent implements OnInit {\n toolbarButtonComponents:ToolbarButtonComponentDefinition[] = [\n {\n component: WorkPackageCreateButtonComponent,\n inputs: {\n stateName$: of(\"work-packages.partitioned.list.new\"),\n allowed: ['work_packages.createWorkPackage']\n }\n },\n {\n component: WorkPackageFilterButtonComponent\n },\n {\n component: WorkPackageViewToggleButton,\n containerClasses: 'hidden-for-mobile'\n },\n {\n component: WorkPackageFoldToggleButtonComponent,\n show: () => {\n return !!(this.currentQuery && this.currentQuery.groupBy);\n }\n },\n {\n component: WorkPackageDetailsViewButtonComponent,\n containerClasses: 'hidden-for-mobile'\n },\n {\n component: WorkPackageTimelineButtonComponent,\n containerClasses: 'hidden-for-mobile -no-spacing'\n },\n {\n component: ZenModeButtonComponent,\n containerClasses: 'hidden-for-mobile'\n },\n {\n component: WorkPackageSettingsButtonComponent\n }\n ];\n\n ngOnInit() {\n super.ngOnInit();\n this.text.button_settings = this.I18n.t('js.button_settings');\n }\n\n protected additionalLoadingTime():Promise {\n if (this.wpTableTimeline.isVisible) {\n return this.querySpace.timelineRendered.pipe(take(1)).toPromise();\n } else {\n return this.querySpace.tableRendered.valuesPromise() as Promise;\n }\n }\n\n protected shouldUpdateHtmlTitle():boolean {\n return this.$state.current.name === 'work-packages.partitioned.list';\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Component, Inject} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WorkPackageInlineCreateComponent} from \"core-components/wp-inline-create/wp-inline-create.component\";\nimport {WorkPackageRelationsService} from \"core-components/wp-relations/wp-relations.service\";\nimport {WpRelationInlineCreateServiceInterface} from \"core-components/wp-relations/embedded/wp-relation-inline-create.service.interface\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {ApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\nimport {RelationResource} from \"core-app/modules/hal/resources/relation-resource\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './wp-relation-inline-add-existing.component.html'\n})\nexport class WpRelationInlineAddExistingComponent {\n public selectedWpId:string;\n public isDisabled = false;\n\n public queryFilters = this.buildQueryFilters();\n\n public text = {\n abort: this.I18n.t('js.relation_buttons.abort'),\n };\n\n constructor(protected readonly parent:WorkPackageInlineCreateComponent,\n @Inject(WorkPackageInlineCreateService) protected readonly wpInlineCreate:WpRelationInlineCreateServiceInterface,\n protected apiV3Service:APIV3Service,\n protected wpRelations:WorkPackageRelationsService,\n protected notificationService:WorkPackageNotificationService,\n protected halEvents:HalEventsService,\n protected urlParamsHelper:UrlParamsHelperService,\n protected querySpace:IsolatedQuerySpace,\n protected readonly I18n:I18nService) {\n }\n\n public addExisting() {\n if (_.isNil(this.selectedWpId)) {\n return;\n }\n\n const newRelationId = this.selectedWpId;\n this.isDisabled = true;\n\n this.wpInlineCreate.add(this.workPackage, newRelationId)\n .then(() => {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .refresh();\n\n this.halEvents.push(this.workPackage, {\n eventType: 'association',\n relatedWorkPackage: newRelationId,\n relationType: this.relationType,\n });\n\n this.isDisabled = false;\n this.wpInlineCreate.newInlineWorkPackageReferenced.next(newRelationId);\n this.cancel();\n })\n .catch((err:any) => {\n this.notificationService.handleRawError(err, this.workPackage);\n this.isDisabled = false;\n this.cancel();\n });\n }\n\n public onSelected(workPackage?:WorkPackageResource) {\n if (workPackage) {\n this.selectedWpId = workPackage.id!;\n this.addExisting();\n }\n }\n\n public get relationType() {\n return this.wpInlineCreate.relationType;\n }\n\n public get workPackage() {\n return this.wpInlineCreate.referenceTarget!;\n }\n\n public cancel() {\n this.parent.resetRow();\n }\n\n private buildQueryFilters():ApiV3Filter[] {\n const query = this.querySpace.query.value;\n\n if (!query) {\n return [];\n }\n\n const relationTypes = RelationResource.RELATION_TYPES(true);\n let filters = query.filters.filter(filter => {\n let id = this.urlParamsHelper.buildV3GetFilterIdFromFilter(filter);\n return relationTypes.indexOf(id) === -1;\n });\n\n return this.urlParamsHelper.buildV3GetFilters(filters);\n }\n}\n","
    \n
    \n
    \n \n \n
    \n
    \n \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable} from '@angular/core';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\n@Injectable({ providedIn: 'root' })\nexport class HalResourceSortingService {\n\n /**\n * List of sortable properties by HAL type\n */\n private config:{ [typeName:string]:string } = {\n 'user': 'name',\n 'project': 'name'\n };\n\n constructor() {\n }\n\n /**\n * Sort the given HalResource based on its type.\n * If the type is not given, guess from the first element.\n *\n * @param {T[]} elements A collection of HalResources of type T\n * @param {string} type The HAL type of the collection\n * @returns {T[]} The sorted collection of HalResources\n */\n public sort(elements:T[], type?:string) {\n if (elements.length === 0) {\n return elements;\n }\n\n const halType = type || elements[0]._type;\n if (!halType) {\n return elements;\n }\n\n const property = this.sortingProperty(halType);\n if (property) {\n return _.sortBy(elements, v => v[property].toLowerCase());\n } else {\n return elements;\n }\n }\n\n /**\n * Transform the HAL type into the sorting property map.\n *\n * - Removes the leading multi identifier [] (e.g., from []User)\n * - Transforms to lowercase\n *\n * @param {string} type\n * @returns {string | undefined}\n */\n public sortingProperty(type:string):string | undefined {\n // Remove multi identifier and map to lowercase\n type = type\n .toLowerCase()\n .replace(/^\\[\\]/, '');\n\n return this.config[type];\n }\n\n public hasSortingProperty(type:string) {\n return this.sortingProperty(type) !== undefined;\n }\n\n}\n","import {ProjectResource} from 'core-app/modules/hal/resources/project-resource';\nimport {SchemaResource} from 'core-app/modules/hal/resources/schema-resource';\nimport {TypeResource} from 'core-app/modules/hal/resources/type-resource';\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {input, InputState, multiInput, MultiInputState, StatesGroup} from 'reactivestates';\nimport {QueryColumn} from './wp-query/query-column';\nimport {PostResource} from 'core-app/modules/hal/resources/post-resource';\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {StatusResource} from \"core-app/modules/hal/resources/status-resource\";\nimport {QueryFilterInstanceSchemaResource} from \"core-app/modules/hal/resources/query-filter-instance-schema-resource\";\nimport {Subject} from \"rxjs\";\nimport {QuerySortByResource} from \"core-app/modules/hal/resources/query-sort-by-resource\";\nimport {QueryGroupByResource} from \"core-app/modules/hal/resources/query-group-by-resource\";\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {WorkPackageDisplayRepresentationValue} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\n\nexport class States extends StatesGroup {\n name = 'MainStore';\n\n /* /api/v3/projects */\n projects:MultiInputState = multiInput();\n\n /* /api/v3/work_packages */\n workPackages = multiInput();\n\n /* /api/v3/wiki_pages */\n posts = multiInput();\n\n /* /api/v3/schemas */\n schemas = multiInput();\n\n /* /api/v3/types */\n types = multiInput();\n\n /* /api/v3/statuses */\n statuses = multiInput();\n\n /* /api/v3/time_entries */\n timeEntries:MultiInputState = multiInput();\n\n /* /api/v3/versions */\n versions = multiInput();\n\n /* /api/v3/users */\n users = multiInput();\n\n // Work Package query states\n queries = new QueryAvailableDataStates();\n\n // Global events to isolated changes\n changes = new GlobalStateChanges();\n\n // Additional state map that can be dynamically registered.\n additional:{ [id:string]:MultiInputState } = {};\n\n forType(stateName:string):MultiInputState {\n let state = (this as any)[stateName] || this.additional[stateName];\n\n if (!state) {\n state = this.additional[stateName] = multiInput();\n }\n\n return state as any;\n }\n\n forResource(resource:T):InputState|undefined {\n const stateName = _.camelCase(resource._type) + 's';\n let state = this.forType(stateName);\n\n return state && state.get(resource.id!);\n }\n\n public add(name:string, state:MultiInputState) {\n this.additional[name] = state;\n }\n}\n\nexport class GlobalStateChanges {\n // Global subject on changes to the given query ID\n queries = new Subject();\n}\n\nexport class QueryAvailableDataStates {\n // Available columns\n columns = input();\n\n // Available SortBy Columns\n sortBy = input();\n\n // Available GroupBy columns\n groupBy = input();\n\n // Available filter schemas (derived from their schema)\n filters = input();\n\n // Display of the WP results\n displayRepresentation = input();\n}\n","import {Component, OnInit, ViewEncapsulation} from \"@angular/core\";\n\nexport const backlogsPageComponentSelector = 'op-backlogs-page';\n\n@Component({\n selector: backlogsPageComponentSelector,\n // Empty wrapper around legacy backlogs for CSS loading\n // that got removed in the Rails assets pipeline\n encapsulation: ViewEncapsulation.None,\n template: '',\n styleUrls: [\n './styles/backlogs.sass'\n ]\n})\nexport class BacklogsPageComponent implements OnInit {\n ngOnInit() {\n document.getElementById('projected-content')!.hidden = false;\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {AttachmentCollectionResource} from 'core-app/modules/hal/resources/attachment-collection-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {TypeResource} from 'core-app/modules/hal/resources/type-resource';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {\n OpenProjectFileUploadService,\n UploadFile\n} from 'core-components/api/op-file-upload/op-file-upload.service';\nimport {States} from 'core-components/states.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {Attachable} from 'core-app/modules/hal/resources/mixins/attachable-mixin';\nimport {FormResource} from \"core-app/modules/hal/resources/form-resource\";\nimport {InputState} from \"reactivestates\";\nimport {WorkPackagesActivityService} from \"core-components/wp-single-view-tabs/activity-panel/wp-activity.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport interface WorkPackageResourceEmbedded {\n activities:CollectionResource;\n ancestors:WorkPackageResource[];\n assignee:HalResource|any;\n attachments:AttachmentCollectionResource;\n author:HalResource|any;\n availableWatchers:HalResource|any;\n category:HalResource|any;\n children:WorkPackageResource[];\n parent:WorkPackageResource|null;\n priority:HalResource|any;\n project:HalResource|any;\n relations:CollectionResource;\n responsible:HalResource|any;\n revisions:CollectionResource|any;\n status:HalResource|any;\n timeEntries:HalResource[]|any[];\n type:TypeResource;\n version:HalResource|any;\n watchers:CollectionResource;\n // For regular work packages\n startDate:string;\n dueDate:string;\n // Only for milestones\n date:string;\n relatedBy:RelationResource|null;\n scheduleManually:boolean;\n}\n\nexport interface WorkPackageResourceLinks extends WorkPackageResourceEmbedded {\n addAttachment(attachment:HalResource):Promise;\n\n addChild(child:HalResource):Promise;\n\n addComment(comment:unknown, headers?:any):Promise;\n\n addRelation(relation:any):Promise;\n\n addWatcher(watcher:HalResource):Promise;\n\n changeParent(params:any):Promise;\n\n copy():Promise;\n\n delete():Promise;\n\n logTime():Promise;\n\n move():Promise;\n\n removeWatcher():Promise;\n\n self():Promise;\n\n update(payload:any):Promise>;\n\n updateImmediately(payload:any):Promise;\n\n watch():Promise;\n}\n\nexport interface WorkPackageLinksObject extends WorkPackageResourceLinks {\n schema:HalResource;\n}\n\nexport class WorkPackageBaseResource extends HalResource {\n public $embedded:WorkPackageResourceEmbedded;\n public $links:WorkPackageLinksObject;\n public subject:string;\n public updatedAt:Date;\n public lockVersion:number;\n public description:any;\n public activities:CollectionResource;\n public attachments:AttachmentCollectionResource;\n\n @InjectField() I18n:I18nService;\n @InjectField() states:States;\n @InjectField() wpActivity:WorkPackagesActivityService;\n @InjectField() apiV3Service:APIV3Service;\n @InjectField() NotificationsService:NotificationsService;\n @InjectField() workPackageNotificationService:WorkPackageNotificationService;\n @InjectField() pathHelper:PathHelperService;\n @InjectField() opFileUpload:OpenProjectFileUploadService;\n\n readonly attachmentsBackend = true;\n\n /**\n * Return the ids of all its ancestors, if any\n */\n public get ancestorIds():string[] {\n const ancestors = (this as any).ancestors;\n return ancestors.map((el:WorkPackageResource) => el.id!);\n }\n\n /**\n * Return \": (#)\" if type and id are known.\n */\n public subjectWithType(truncateSubject:number = 40):string {\n const type = this.type ? `${this.type.name}: ` : '';\n const subject = this.subjectWithId(truncateSubject);\n\n return `${type}${subject}`;\n }\n\n /**\n * Return \" (#)\" if the id is known.\n */\n public subjectWithId(truncateSubject:number = 40):string {\n const id = this.isNew ? '' : ` (#${this.id})`;\n const subject = _.truncate(this.subject, {length: truncateSubject});\n\n return `${subject}${id}`;\n }\n\n public get isLeaf():boolean {\n let children = this.$links.children;\n return !(children && children.length > 0);\n }\n\n public previewPath() {\n if (!this.isNew) {\n return this.apiV3Service.work_packages.id(this.id!).path;\n } else {\n return super.previewPath();\n }\n }\n\n public getEditorTypeFor(fieldName:string):\"full\"|\"constrained\" {\n return fieldName === 'description' ? 'full' : 'constrained';\n }\n\n public isParentOf(otherWorkPackage:WorkPackageResource) {\n return otherWorkPackage.parent?.$links.self.$link.href === this.$links.self.$link.href;\n }\n\n /**\n * Invalidate a set of linked resources of this work package.\n * And inform the cache service about the work package update.\n *\n * Return a promise that returns the linked resources as properties.\n * Return a rejected promise, if the resource is not a property of the work package.\n */\n public updateLinkedResources(...resourceNames:string[]):Promise {\n const resources:{ [id:string]:Promise } = {};\n\n resourceNames.forEach(name => {\n const linked = this[name];\n resources[name] = linked ? linked.$update() : Promise.reject(undefined);\n });\n\n const promise = Promise.all(_.values(resources));\n promise.then(() => {\n this.wpCacheService.touch(this.id!);\n });\n\n return promise;\n }\n\n public $initialize(source:any) {\n super.$initialize(source);\n\n let attachments:any = this.attachments || {$source: {}, elements: []};\n this.attachments = new AttachmentCollectionResource(\n this.injector,\n // Attachments MAY be an array if we're building from a form\n _.get(attachments, '$source', attachments),\n false,\n this.halInitializer,\n 'HalResource'\n );\n }\n\n /**\n * Exclude the schema _link from the linkable Resources.\n */\n public $linkableKeys():string[] {\n return _.without(super.$linkableKeys(), 'schema');\n }\n\n /**\n * Return the associated state to this HAL resource, if any.\n */\n public get state():InputState {\n return this.states.workPackages.get(this.id!) as any;\n }\n\n /**\n * Update the state\n */\n public push(newValue:this):Promise {\n this.wpActivity.clear(newValue.id!);\n\n // If there is a parent, its view has to be updated as well\n if (newValue.parent) {\n this.apiV3Service.work_packages.id(newValue.parent).refresh();\n }\n\n return this.apiV3Service.work_packages.cache.updateWorkPackage(newValue as any);\n }\n}\n\nexport const WorkPackageResource = Attachable(WorkPackageBaseResource);\n\nexport interface WorkPackageResource extends WorkPackageBaseResource, WorkPackageResourceLinks, WorkPackageResourceEmbedded {\n}\n","// -- copyright\n// OpenProject is 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, filter, share, shareReplay,\n switchMap,\n takeUntil,\n tap\n} from \"rxjs/operators\";\nimport {RequestSwitchmapHandler} from \"core-app/helpers/rxjs/request-switchmap\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\n\nexport type RequestErrorHandler = (error:unknown) => void;\n\nexport function errorNotificationHandler(service:HalResourceNotificationService):RequestErrorHandler {\n return (error:unknown) => service.handleRawError(error);\n}\n\nexport class DebouncedRequestSwitchmap {\n\n /** Input request state */\n public input$ = new Subject();\n\n /** Output results observable */\n public output$:Observable;\n\n /** Loading flag */\n public loading$ = new Subject();\n\n /** Whether results were returned */\n public lastResult:R[] = [];\n\n /** Last requested value */\n public lastRequestedValue:T|undefined;\n\n /**\n * @param handler switch map handler function to output a response observable\n * @param debounceTime {number} Time to debounce in ms.\n * @param preFilterNull {boolean} Whether to exclude null and undefined searches\n * @param emptyValue {R} The empty fall back value before first response or on errors\n */\n constructor(readonly requestHandler:RequestSwitchmapHandler,\n readonly errorHandler:RequestErrorHandler,\n readonly preFilterNull:boolean = false,\n readonly debounceMs = 250) {\n\n /** Output switchmap observable */\n this.output$ = concat(\n of([]),\n this.input$.pipe(\n filter(val => !preFilterNull || (val !== undefined && val !== null)),\n distinctUntilChanged(),\n debounceTime(debounceMs),\n tap((val:T) => {\n this.lastRequestedValue = val;\n this.lastResult = [];\n this.loading$.next(true);\n }),\n switchMap(term =>\n this.requestHandler(term)\n .pipe(\n catchError((error) => {\n this.errorHandler(error);\n return of([]);\n }),\n tap((results) => {\n this.loading$.next(false);\n this.lastResult = results;\n })\n )\n ),\n shareReplay(1)\n )\n );\n }\n\n /**\n * Append a new request for the given request value and pass\n * that to the switchmap handler\n * @param newValue\n */\n public request(newValue:T) {\n this.input$.next(newValue);\n }\n\n /**\n * Returns whether the last results returned anything\n */\n public get hasResults() {\n return this.lastResult.length > 0;\n }\n\n /**\n * Observe the switched response\n */\n public observe(until:Observable) {\n return this\n .output$\n .pipe(\n takeUntil(until)\n );\n }\n}\n","import {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {Constructor} from \"@angular/cdk/table\";\n\n/**\n * Simple resource collection to construct paths for RESTful resources.\n * Base class for APIV3 and BCF API helpers\n */\nexport class SimpleResourceCollection {\n // Base path\n public readonly path:string;\n\n constructor(protected basePath:string, readonly segment:string, protected resource?:Constructor) {\n this.path = `${this.basePath}/${segment}`;\n }\n\n public id(id:string|number):T {\n return new (this.resource || SimpleResource)(this.path, id) as T;\n }\n\n /**\n * Returns either the collection itself, or the resource\n * located by the ID when present.\n *\n * TypeScript will reduce available endpoints to anything available\n * in this collection AND the resource.\n *\n * @param id\n */\n public withOptionalId(id?:string|number):this|T {\n if (_.isNil(id)) {\n return this;\n } else {\n return this.id(id);\n }\n }\n\n public toString():string {\n return this.path;\n }\n\n public toPath():string {\n return this.path;\n }\n}\n\n/**\n * Singular RESTful resource object identified by a base path and ID\n */\nexport class SimpleResource {\n public readonly path:string;\n\n constructor(readonly basePath:string, readonly segment:string|number) {\n let separator = segment.toString().startsWith('?') ? '' : '/';\n this.path = `${this.basePath}${separator}${segment}`;\n }\n\n public toString() {\n return this.path;\n }\n\n public toPath():string {\n return this.path;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","// @ts-ignore\nimport {utils} from \"@xeokit/xeokit-sdk/src/viewer/scene/utils\";\nimport {PathHelperService} from \"../../../common/path-helper/path-helper.service\";\nimport {IFCGonDefinition} from \"../pages/viewer/ifc-models-data.service\";\n\n/**\n * Default server client which loads content via HTTP from the file system.\n */\nexport class XeokitServer {\n private ifcModels:IFCGonDefinition;\n /**\n *\n * @param config\n * @param.config.pathHelper instance of PathHelperService.\n */\n constructor(private pathHelper:PathHelperService) {\n this.ifcModels = window.gon.ifc_models;\n }\n\n /**\n * Gets the manifest of all projects.\n * @param done\n * @param error\n */\n getProjects(done:Function, _error:Function) {\n done({ projects: this.ifcModels.projects });\n }\n\n /**\n * Gets a manifest for a project.\n * @param projectId\n * @param done\n * @param error\n */\n getProject(projectData:any, done:Function, _error:Function) {\n var manifestData = {\n id: projectData[0].id,\n name: projectData[0].name,\n models: this.ifcModels.models,\n viewerContent: {\n modelsLoaded: this.ifcModels.shown_models\n },\n viewerConfigs: {\n saoEnabled: true // Needs to be enabled by default if we want to use it selectively on the available models.\n }\n };\n\n done(manifestData);\n }\n\n /**\n * Gets metadata for a model within a project.\n * @param projectId\n * @param modelId\n * @param done\n * @param error\n */\n getMetadata(_projectId:string, modelId:number, done:Function, error:Function) {\n const attachmentId = this.ifcModels.metadata_attachment_ids[modelId];\n console.log(`Loading model metadata for: ${attachmentId}`);\n utils.loadJSON(this.pathHelper.attachmentContentPath(attachmentId), done, error);\n }\n\n /**\n * Gets geometry for a model within a project.\n * @param projectId\n * @param modelId\n * @param done\n * @param error\n */\n getGeometry(projectId:string, modelId:number, done:Function, error:Function) {\n const attachmentId = this.ifcModels.xkt_attachment_ids[modelId];\n console.log(`Loading model geometry for: ${attachmentId}`);\n utils.loadArraybuffer(this.pathHelper.attachmentContentPath(attachmentId), done, error);\n }\n}\n","import {Injectable, Inject, Injector} from '@angular/core';\nimport {XeokitServer} from \"core-app/modules/bim/ifc_models/xeokit/xeokit-server\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {ViewerBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service\";\nimport {BehaviorSubject, Observable, Subject} from \"rxjs\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {BcfApiService} from \"core-app/modules/bim/bcf/api/bcf-api.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {ViewpointsService} from \"core-app/modules/bim/bcf/helper/viewpoints.service\";\nimport {of} from 'rxjs';\n\n\nexport interface XeokitElements {\n canvasElement:HTMLElement;\n explorerElement:HTMLElement;\n toolbarElement:HTMLElement;\n navCubeCanvasElement:HTMLElement;\n busyModelBackdropElement:HTMLElement;\n}\n\nexport interface BCFCreationOptions {\n spacesVisible?:boolean;\n spaceBoundariesVisible?:boolean;\n openingsVisible?:boolean;\n}\n\nexport interface BCFLoadOptions {\n rayCast?:boolean;\n immediate?:boolean;\n duration?:number;\n}\n\n@Injectable()\nexport class IFCViewerService extends ViewerBridgeService {\n public shouldShowViewer = true;\n public viewerVisible$ = new BehaviorSubject(false);\n private _viewer:any;\n\n @InjectField() pathHelper:PathHelperService;\n @InjectField() bcfApi:BcfApiService;\n @InjectField() viewpointsService:ViewpointsService;\n\n constructor(readonly injector:Injector) {\n super(injector);\n }\n\n public newViewer(elements:XeokitElements, projects:any[]) {\n import('@xeokit/xeokit-bim-viewer/dist/main').then((XeokitViewerModule:any) => {\n let server = new XeokitServer(this.pathHelper);\n let viewerUI = new XeokitViewerModule.BIMViewer(server, elements);\n\n viewerUI.on(\"queryPicked\", (event:any) => {\n alert(`IFC Name = \"${event.objectName}\"\\nIFC class = \"${event.objectType}\"\\nIFC GUID = ${event.objectId}`);\n });\n\n viewerUI.on(\"modelLoaded\", () => this.viewerVisible$.next(true));\n\n viewerUI.loadProject(projects[0][\"id\"]);\n\n this.viewer = viewerUI;\n });\n }\n\n public destroy() {\n this.viewerVisible$.complete();\n\n if (!this.viewer) {\n return;\n }\n\n this.viewer.destroy();\n this.viewer = undefined;\n }\n\n public get viewer() {\n return this._viewer;\n }\n\n public set viewer(viewer:any) {\n this._viewer = viewer;\n }\n\n public setKeyboardEnabled(val:boolean) {\n this.viewer.setKeyboardEnabled(val);\n }\n\n public getViewpoint$():Observable {\n const viewpoint = this.viewer.saveBCFViewpoint({ spacesVisible: true });\n\n // The backend rejects viewpoints with bitmaps\n delete viewpoint.bitmaps;\n\n return of(viewpoint);\n }\n\n public showViewpoint(workPackage:WorkPackageResource, index:number) {\n // Avoid reload the app when there is a place to show the viewer\n // ('bim.partitioned.split')\n if (this.routeWithViewer) {\n if (this.viewer) {\n this.viewpointsService\n .getViewPoint$(workPackage, index)\n .subscribe(viewpoint => this.viewer.loadBCFViewpoint(viewpoint, {}));\n }\n } else {\n // Reload the whole app to get the correct menus and GON data\n // and redirect to a route with a place to show viewer\n // ('bim.partitioned.split')\n window.location.href = this.pathHelper.bimDetailsPath(\n workPackage.project.idFromLink,\n workPackage.id!,\n index\n );\n }\n }\n\n public viewerVisible():boolean {\n return !!this.viewer;\n }\n}","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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: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\",\"type\",\"subject\",\"status\",\"startDate\",\"dueDate\"],\"tv\":true,\"tzl\":\"auto\",\"tll\":\"{\\\\\"left\\\\\":\\\\\"startDate\\\\\",\\\\\"right\\\\\":\\\\\"dueDate\\\\\",\\\\\"farRight\\\\\":\\\\\"subject\\\\\"}\",\"hi\":true,\"g\":\"\",\"t\":\"startDate:asc\",\"f\":[{\"n\":\"status\",\"o\":\"o\",\"v\":[]}]}`\n },\n {\n identifier: 'recently_created',\n label: this.text.recently_created,\n query_props: '{\"c\":[\"id\",\"subject\",\"type\",\"status\",\"assignee\",\"createdAt\"],\"hi\":false,\"g\":\"\",\"t\":\"createdAt:desc\",\"f\":[{\"n\":\"status\",\"o\":\"o\",\"v\":[]}]}'\n }\n ] as IAutocompleteItem[];\n\n const projectIdentifier = this.CurrentProject.identifier;\n if (projectIdentifier) {\n items.push({\n identifier: 'summary',\n label: this.text.summary,\n static_link: this.PathHelper.projectWorkPackagesPath(projectIdentifier) + '/report'\n });\n }\n\n if (this.CurrentUserService.isLoggedIn) {\n items = items.concat([\n {\n identifier: 'created_by_me',\n label: this.text.created_by_me,\n query_props: '{\"c\":[\"id\",\"subject\",\"type\",\"status\",\"assignee\",\"updatedAt\"],\"hi\":false,\"g\":\"\",\"t\":\"updatedAt:desc,id:asc\",\"f\":[{\"n\":\"status\",\"o\":\"o\",\"v\":[]},{\"n\":\"author\",\"o\":\"=\",\"v\":[\"me\"]}]}'\n },\n {\n identifier: 'assigned_to_me',\n label: this.text.assigned_to_me,\n query_props: '{\"c\":[\"id\",\"subject\",\"type\",\"status\",\"author\",\"updatedAt\"],\"hi\":false,\"g\":\"\",\"t\":\"updatedAt:desc,id:asc\",\"f\":[{\"n\":\"status\",\"o\":\"o\",\"v\":[]},{\"n\":\"assigneeOrGroup\",\"o\":\"=\",\"v\":[\"me\"]}]}'\n }\n ]);\n }\n\n return items;\n }\n\n public getStaticName(query:QueryResource) {\n if (this.$state.params.query_props) {\n let queryProps = JSON.parse(this.$state.params.query_props);\n delete queryProps.pp;\n delete queryProps.pa;\n let queryPropsString = JSON.stringify(queryProps);\n\n const matched = _.find(this.all, item =>\n item.query_props && item.query_props === queryPropsString\n );\n\n if (matched) {\n return matched.label;\n }\n }\n\n // Try to detect the all open filter\n if (query.filters.length === 1 && // Only one filter\n query.filters[0].id === 'status' && // that is status\n query.filters[0].operator.id === 'o') { // and is open\n return this.text.all_open;\n }\n\n // Otherwise, fall back to work packages\n return this.text.work_packages;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Injectable, Injector} from '@angular/core';\nimport {HttpClient, HttpErrorResponse, HttpParams} from '@angular/common/http';\nimport {catchError, map} from 'rxjs/operators';\nimport {Observable, throwError} from 'rxjs';\nimport {HalResource, HalResourceClass} from 'core-app/modules/hal/resources/hal-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {HalLink, HalLinkInterface} from 'core-app/modules/hal/hal-link/hal-link';\nimport {URLParamsEncoder} from 'core-app/modules/hal/services/url-params-encoder';\nimport {ErrorResource} from \"core-app/modules/hal/resources/error-resource\";\nimport * as Pako from 'pako';\nimport {\n HTTPClientHeaders,\n HTTPClientOptions,\n HTTPClientParamMap,\n HTTPSupportedMethods\n} from \"core-app/modules/hal/http/http.interfaces\";\nimport {whenDebugging} from \"core-app/helpers/debug_output\";\nimport {initializeHalProperties} from \"../helpers/hal-resource-builder\";\n\nexport interface HalResourceFactoryConfigInterface {\n cls?:any;\n attrTypes?:{ [attrName:string]:string };\n}\n\n\n@Injectable({ providedIn: 'root' })\nexport class HalResourceService {\n\n /**\n * List of all known hal resources, extendable.\n */\n private config:{ [typeName:string]:HalResourceFactoryConfigInterface } = {};\n\n constructor(readonly injector:Injector,\n readonly http:HttpClient) {\n }\n\n /**\n * Perform a HTTP request and return a HalResource promise.\n */\n public request(method:HTTPSupportedMethods, href:string, data?:any, headers:HTTPClientHeaders = {}):Observable {\n\n // HttpClient requires us to create HttpParams instead of passing data for get\n // so forward to that method instead.\n if (method === 'get') {\n return this.get(href, data, headers);\n }\n\n const config:HTTPClientOptions = {\n body: data || {},\n headers: headers,\n withCredentials: true,\n responseType: 'json'\n };\n\n return this._request(method, href, config);\n }\n\n private _request(method:HTTPSupportedMethods, href:string, config:HTTPClientOptions):Observable {\n return this.http.request(method, href, config)\n .pipe(\n map((response:any) => this.createHalResource(response)),\n catchError((error:HttpErrorResponse) => {\n whenDebugging(() => console.error(`Failed to ${method} ${href}: ${error.name}`));\n const resource = this.createHalResource(error.error);\n resource.httpError = error;\n return throwError(resource);\n })\n ) as any;\n }\n\n /**\n * Perform a GET request and return a resource promise.\n *\n * @param href\n * @param params\n * @param headers\n * @returns {Promise}\n */\n public get(href:string, params?:HTTPClientParamMap, headers?:HTTPClientHeaders):Observable {\n const config:HTTPClientOptions = {\n headers: headers,\n params: new HttpParams({ encoder: new URLParamsEncoder(), fromObject: params }),\n withCredentials: true,\n responseType: 'json'\n };\n\n return this._request('get', href, config);\n }\n\n /**\n * Return all potential pages to the request, when the elements returned from API is smaller\n * than the expected.\n *\n * @param href\n * @param expected The expected number of elements\n * @param params\n * @param headers\n * @return {Promise}\n */\n public async getAllPaginated(href:string, expected:number, params:any = {}, headers:HTTPClientHeaders = {}) {\n // Total number retrieved\n let retrieved = 0;\n // Current offset page\n let page = 1;\n // Accumulated results\n const allResults:T = [] as any;\n // If possible, request all at once.\n params.pageSize = expected;\n\n while (retrieved < expected) {\n params.offset = page;\n\n const promise = this.request('get', href, this.toEprops(params), headers).toPromise();\n const results = await promise;\n\n if (results.count === 0) {\n throw 'No more results for this query, but expected more.';\n }\n\n allResults.push(results);\n\n retrieved += results.count;\n page += 1;\n }\n\n return allResults;\n }\n\n /**\n * Perform a PUT request and return a resource promise.\n * @param href\n * @param data\n * @param headers\n * @returns {Promise}\n */\n public put(href:string, data?:any, headers?:HTTPClientHeaders):Observable {\n return this.request('put', href, data, headers);\n }\n\n /**\n * Perform a POST request and return a resource promise.\n *\n * @param href\n * @param data\n * @param headers\n * @returns {Promise}\n */\n public post(href:string, data?:any, headers?:HTTPClientHeaders):Observable {\n return this.request('post', href, data, headers);\n }\n\n /**\n * Perform a PATCH request and return a resource promise.\n *\n * @param href\n * @param data\n * @param headers\n * @returns {Promise}\n */\n public patch(href:string, data?:any, headers?:HTTPClientHeaders):Observable {\n return this.request('patch', href, data, headers);\n }\n\n /**\n * Perform a DELETE request and return a resource promise\n *\n * @param href\n * @param data\n * @param headers\n * @returns {Promise}\n */\n public delete(href:string, data?:any, headers?:HTTPClientHeaders):Observable {\n return this.request('delete', href, data, headers);\n }\n\n /**\n * Register a HalResource for use with the API.\n * @param {HalResourceStatic} resource\n */\n public registerResource(key:string, entry:HalResourceFactoryConfigInterface) {\n this.config[key] = entry;\n }\n\n /**\n * Get the default class.\n * Initially, it's HalResource.\n *\n * @returns {HalResource}\n */\n public get defaultClass():HalResourceClass {\n let defaultCls:HalResourceClass = HalResource;\n return defaultCls;\n }\n\n /**\n * Create a HalResource from a source object.\n * If the APIv3 _type attribute is defined and the type is configured,\n * the respective class will be used for instantiation.\n *\n *\n * @param source\n * @returns {HalResource}\n */\n public createHalResource(source:any, loaded:boolean = true):T {\n if (_.isNil(source)) {\n source = HalResource.getEmptyResource();\n }\n\n const type = source._type || 'HalResource';\n return this.createHalResourceOfType(type, source, loaded);\n }\n\n public createHalResourceOfType(type:string, source:any, loaded:boolean = false) {\n const resourceClass:HalResourceClass = this.getResourceClassOfType(type);\n const initializer = (halResource:T) => initializeHalProperties(this, halResource);\n let resource = new resourceClass(this.injector, source, loaded, initializer, type);\n\n return resource;\n }\n\n /**\n * Create a resource class of the given class\n * @param resourceClass\n * @param source\n * @param loaded\n */\n public createHalResourceOfClass(resourceClass:HalResourceClass, source:any, loaded:boolean = false) {\n const initializer = (halResource:T) => initializeHalProperties(this, halResource);\n const type = source._type || 'HalResource';\n let resource = new resourceClass(this.injector, source, loaded, initializer, type);\n\n return resource;\n }\n\n /**\n * Create a linked HalResource from the given link.\n *\n * @param {HalLinkInterface} link\n * @returns {HalResource}\n */\n public fromLink(link:HalLinkInterface) {\n const resource = HalResource.getEmptyResource(HalLink.fromObject(this, link));\n return this.createHalResource(resource, false);\n }\n\n /**\n * Create an empty HAL resource with only the self link set.\n * @param href Self link of the HAL resource\n */\n public fromSelfLink(href:string|null) {\n const source = { _links: { self: { href: href } } };\n return this.createHalResource(source);\n }\n\n /**\n * Get a linked resource from its HalLink with the correct type.\n */\n public createLinkedResource(halResource:T, linkName:string, link:HalLinkInterface) {\n const source = HalResource.getEmptyResource();\n const fromType = halResource.$halType;\n const toType = this.getResourceClassOfAttribute(fromType, linkName) || 'HalResource';\n\n source._links.self = link;\n\n return this.createHalResourceOfType(toType, source, false);\n }\n\n /**\n * Get the configured resource class of a type.\n *\n * @param type\n * @returns {HalResource}\n */\n protected getResourceClassOfType(type:string):HalResourceClass {\n const config = this.config[type];\n return (config && config.cls) ? config.cls : this.defaultClass;\n }\n\n /**\n * Get the hal type for an attribute\n *\n * @param type\n * @param attribute\n * @returns {any}\n */\n protected getResourceClassOfAttribute(type:string, attribute:string):string|null {\n const typeConfig = this.config[type];\n const types = (typeConfig && typeConfig.attrTypes) || {};\n return types[attribute];\n }\n\n protected toEprops(params:{}):{} {\n let deflated = Pako.deflate(JSON.stringify(params), { to: 'string' });\n let compressed = btoa(deflated);\n\n return { eprops: compressed };\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\n\nimport {Component, HostListener, Input} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {HalResourceService} from 'core-app/modules/hal/services/hal-resource.service';\nimport {CustomActionResource} from 'core-app/modules/hal/resources/custom-action-resource';\nimport {WorkPackagesActivityService} from 'core-components/wp-single-view-tabs/activity-panel/wp-activity.service';\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-custom-action',\n templateUrl: './wp-custom-action.component.html'\n})\nexport class WpCustomActionComponent {\n\n @Input() workPackage:WorkPackageResource;\n @Input() action:CustomActionResource;\n\n constructor(private halResourceService:HalResourceService,\n private apiV3Service:APIV3Service,\n private wpSchemaCacheService:SchemaCacheService,\n private wpActivity:WorkPackagesActivityService,\n private notificationService:WorkPackageNotificationService,\n private halEditing:HalResourceEditingService,\n private halEvents:HalEventsService) {\n }\n\n private fetchAction() {\n this.halResourceService.get(this.action.href!)\n .toPromise()\n .then((action) => {\n this.action = action;\n });\n }\n\n public update() {\n let payload = {\n lockVersion: this.workPackage.lockVersion,\n _links: {\n workPackage: {\n href: this.workPackage.href\n }\n }\n };\n\n this.halResourceService\n .post(this.action.href + '/execute', payload)\n .subscribe(\n (savedWp:WorkPackageResource) => {\n this.notificationService.showSave(savedWp, false);\n this.workPackage = savedWp;\n this.wpActivity.clear(this.workPackage.id!);\n // Loading the schema might be necessary in cases where the button switches\n // project or type.\n this.apiV3Service.work_packages.cache.updateWorkPackage(savedWp).then(() => {\n this.halEditing.stopEditing(savedWp);\n this.halEvents.push(savedWp, { eventType: \"updated\" });\n });\n },\n (errorResource:any) => this.notificationService.handleRawError(errorResource, this.workPackage)\n );\n }\n\n @HostListener('mouseenter') onMouseEnter() {\n this.fetchAction();\n }\n}\n\n","\n {{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\nexport interface PaginationObject {\n pageSize:number;\n offset:number;\n}\n\n\n@Injectable()\nexport class PaginationService {\n private paginationOptions:IPaginationOptions;\n\n constructor(private configuration:ConfigurationService) {\n this.loadPaginationOptions();\n }\n\n public getCachedPerPage(initialPageOptions:number[]):number {\n const value = this.localStoragePerPage;\n const initialLength = initialPageOptions?.length || 0;\n\n if (value !== null && value > 0 && (initialLength === 0 || initialPageOptions?.indexOf(value) !== -1)) {\n return value;\n }\n\n if (initialLength > 0) {\n return initialPageOptions[0];\n }\n\n return 20;\n }\n\n private get localStoragePerPage() {\n const value = window.OpenProject.guardedLocalStorage('pagination.perPage') as string;\n\n if (value !== undefined) {\n return parseInt(value, 10);\n } else {\n return null;\n }\n }\n\n public getPaginationOptions() {\n return this.paginationOptions;\n }\n\n public get isPerPageKnown() {\n return !!(this.localStoragePerPage || this.paginationOptions);\n }\n\n public getPerPage() {\n return this.localStoragePerPage || this.paginationOptions.perPage;\n }\n\n public getMaxVisiblePageOptions() {\n return _.get(this.paginationOptions, 'maxVisiblePageOptions', DEFAULT_PAGINATION_OPTIONS.maxVisiblePageOptions);\n }\n\n public getOptionsTruncationSize() {\n return _.get(this.paginationOptions, 'optionsTruncationSize', DEFAULT_PAGINATION_OPTIONS.optionsTruncationSize);\n }\n\n public setPerPage(perPage:number) {\n window.OpenProject.guardedLocalStorage('pagination.perPage', perPage.toString());\n this.paginationOptions.perPage = perPage;\n }\n\n public getPerPageOptions() {\n return this.paginationOptions.perPageOptions;\n }\n\n public setPerPageOptions(perPageOptions:number[]) {\n this.paginationOptions.perPageOptions = perPageOptions;\n }\n\n public loadPaginationOptions() {\n return this.configuration.initialized.then(() => {\n this.paginationOptions = {\n perPage: this.getCachedPerPage(this.configuration.perPageOptions),\n perPageOptions: this.configuration.perPageOptions,\n maxVisiblePageOptions: DEFAULT_PAGINATION_OPTIONS.maxVisiblePageOptions,\n optionsTruncationSize: DEFAULT_PAGINATION_OPTIONS.optionsTruncationSize\n };\n\n return this.paginationOptions;\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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';\n\n@Injectable()\nexport class WorkPackagesListInvalidQueryService {\n constructor(protected halResourceService:HalResourceService) {\n }\n\n public restoreQuery(query:QueryResource, form:QueryFormResource) {\n this.restoreFilters(query, form.payload, form.schema);\n this.restoreColumns(query, form.payload, form.schema);\n this.restoreSortBy(query, form.payload, form.schema);\n this.restoreGroupBy(query, form.payload, form.schema);\n this.restoreOtherProperties(query, form.payload);\n }\n\n private restoreFilters(query:QueryResource, payload:QueryResource, querySchema:SchemaResource) {\n let filters = _.map((payload.filters), filter => {\n let filterInstanceSchema = _.find(querySchema.filtersSchemas.elements, (schema:QueryFilterInstanceSchemaResource) => {\n return (schema.filter.allowedValues as QueryFilterResource[])[0].$href === filter.filter.$href;\n });\n\n if (!filterInstanceSchema) {\n return null;\n }\n\n let recreatedFilter = filterInstanceSchema.getFilter();\n\n let operator = _.find(filterInstanceSchema.operator.allowedValues, operator => {\n return operator.$href === filter.operator.$href;\n });\n\n if (operator) {\n recreatedFilter.operator = operator;\n }\n\n recreatedFilter.values.length = 0;\n _.each(filter.values, value => recreatedFilter.values.push(value));\n\n return recreatedFilter;\n });\n\n filters = _.compact(filters);\n\n // clear filters while keeping reference\n query.filters.length = 0;\n _.each(filters, filter => query.filters.push(filter));\n }\n\n private restoreColumns(query:QueryResource, stubQuery:QueryResource, schema:SchemaResource) {\n let columns = _.map(stubQuery.columns, column => {\n return _.find((schema.columns.allowedValues as QueryColumn[]), candidate => {\n return candidate.$href === column.$href;\n });\n });\n\n columns = _.compact(columns);\n\n query.columns.length = 0;\n _.each(columns, column => query.columns.push(column!));\n }\n\n private restoreSortBy(query:QueryResource, stubQuery:QueryResource, schema:SchemaResource) {\n let sortBys = _.map((stubQuery.sortBy), sortBy => {\n return _.find((schema.sortBy.allowedValues as QuerySortByResource[]), candidate => {\n return candidate.$href === sortBy.$href;\n })!;\n });\n\n sortBys = _.compact(sortBys);\n\n query.sortBy.length = 0;\n _.each(sortBys, sortBy => query.sortBy.push(sortBy));\n }\n\n private restoreGroupBy(query:QueryResource, stubQuery:QueryResource, schema:SchemaResource) {\n let groupBy = _.find((schema.groupBy.allowedValues as QueryGroupByResource[]), candidate => {\n return stubQuery.groupBy && stubQuery.groupBy.$href === candidate.$href;\n }) as any;\n\n query.groupBy = groupBy;\n }\n\n private restoreOtherProperties(query:QueryResource, stubQuery:QueryResource) {\n _.without(Object.keys(stubQuery.$source), '_links', 'filters').forEach((property:any) => {\n query[property] = stubQuery[property];\n });\n\n _.without(Object.keys(stubQuery.$source._links), 'columns', 'groupBy', 'sortBy').forEach((property:any) => {\n query[property] = stubQuery[property];\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {CustomActionResource} from \"core-app/modules/hal/resources/custom-action-resource\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Component({\n selector: 'wp-custom-actions',\n templateUrl: './wp-custom-actions.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class WpCustomActionsComponent extends UntilDestroyedMixin implements OnInit {\n\n @Input() workPackage:WorkPackageResource;\n\n actions:CustomActionResource[] = [];\n\n constructor(readonly apiV3Service:APIV3Service,\n readonly cdRef:ChangeDetectorRef) {\n super();\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage.id!)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp) => {\n this.actions = wp.customActions ? [...wp.customActions] : [];\n this.cdRef.detectChanges();\n });\n }\n\n}\n","\n\n","/**\n * 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.filter(item => !item?.hidden);\n this.service = this.locals.service;\n }\n\n public handleClick(item:OpContextMenuItem, $event:JQuery.TriggeredEvent) {\n if (item.disabled || item.divider) {\n return false;\n }\n\n if (item.onClick!($event)) {\n this.locals.service.close();\n $event.preventDefault();\n $event.stopPropagation();\n return false;\n }\n\n return true;\n }\n}\n","
    \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 /**\n * Determine whether a viewer should be shown,\n * wether 'bim.partitioned.split' state/route should be activated\n */\n abstract shouldShowViewer:boolean;\n\n /**\n * Check if we are on a router state where there is a place\n * where the viewer could be shown\n */\n get routeWithViewer():boolean {\n return this.state.includes('bim.partitioned.split');\n }\n\n constructor(readonly injector:Injector) {}\n /**\n * Get a viewpoint from the viewer\n */\n abstract getViewpoint$():Observable;\n\n /**\n * Show the given viewpoint JSON in the viewer\n * @param viewpoint\n */\n abstract showViewpoint(workPackage:WorkPackageResource, index:number):void;\n\n /**\n * Determine whether a viewer is present to ensure we can show viewpoints\n */\n abstract viewerVisible():boolean;\n\n /**\n * Fires when viewer becomes visible.\n */\n abstract viewerVisible$:Observable;\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';\nimport {UploadFile, UploadHttpEvent, UploadInProgress} from \"core-components/api/op-file-upload/op-file-upload.service\";\nimport {HttpErrorResponse, HttpEventType, HttpProgressEvent} from \"@angular/common/http\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\n\n@Component({\n selector: 'notifications-upload-progress',\n template: `\n
  • \n \n \n

    0%

    \n \n \n \n \n
  • \n `\n})\nexport class UploadProgressComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public upload:UploadInProgress;\n @Output() public onError = new EventEmitter();\n @Output() public onSuccess = new EventEmitter();\n\n @ViewChild('progressBar')\n progressBar:ElementRef;\n @ViewChild('progressPercentage')\n progressPercentage:ElementRef;\n\n public file:UploadFile;\n public error:boolean = false;\n public completed = false;\n\n set value(value:number) {\n this.progressBar.nativeElement.value = value;\n this.progressPercentage.nativeElement.innerText = `${value}%`;\n\n if (value === 100) {\n this.progressBar.nativeElement.style.display = 'none';\n }\n }\n\n constructor(protected readonly I18n:I18nService) {\n super();\n }\n\n ngOnInit() {\n this.file = this.upload[0];\n const observable = this.upload[1];\n\n observable\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(\n (evt:UploadHttpEvent) => {\n switch (evt.type) {\n case HttpEventType.Sent:\n this.value = 5;\n return debugLog(`Uploading file \"${this.file.name}\" of size ${this.file.size}.`);\n\n case HttpEventType.UploadProgress:\n return this.updateProgress(evt);\n\n case HttpEventType.Response:\n debugLog(`File ${this.fileName} was fully uploaded.`);\n this.value = 100;\n this.completed = true;\n return this.onSuccess.emit();\n\n default:\n // Sent or unknown event\n return;\n }\n },\n (error:HttpErrorResponse) => this.handleError(error)\n );\n }\n\n public get fileName():string|undefined {\n return this.file && this.file.name;\n }\n\n private updateProgress(evt:HttpProgressEvent) {\n if (evt.total) {\n this.value = Math.round(evt.loaded / evt.total * 100);\n } else {\n this.value = 10;\n }\n }\n\n private handleError(error:HttpErrorResponse) {\n this.error = true;\n this.onError.emit(error);\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\nimport {Observable, zip} from 'rxjs';\nimport {take, takeUntil} from 'rxjs/operators';\nimport {RelatedWorkPackagesGroup} from './wp-relations.interfaces';\nimport {RelationsStateValue, WorkPackageRelationsService} from './wp-relations.service';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {componentDestroyed} from \"@w11k/ngx-componentdestroyed\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Component({\n selector: 'wp-relations',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './wp-relations.template.html'\n})\nexport class WorkPackageRelationsComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n public relationGroups:RelatedWorkPackagesGroup = {};\n public relationGroupKeys:string[] = [];\n public relationsPresent:boolean = false;\n public canAddRelation:boolean;\n\n // By default, group by relation type\n public groupByWorkPackageType = false;\n\n public text = {\n relations_header: this.I18n.t('js.work_packages.tabs.relations')\n };\n public currentRelations:WorkPackageResource[] = [];\n\n constructor(private I18n:I18nService,\n private wpRelations:WorkPackageRelationsService,\n private cdRef:ChangeDetectorRef,\n private apiV3Service:APIV3Service) {\n super();\n }\n\n ngOnInit() {\n this.canAddRelation = !!this.workPackage.addRelation;\n\n this.wpRelations\n .state(this.workPackage.id!)\n .values$()\n .pipe(\n takeUntil(componentDestroyed(this))\n )\n .subscribe((relations:RelationsStateValue) => {\n this.loadedRelations(relations);\n });\n\n this.wpRelations.require(this.workPackage.id!);\n\n // Listen for changes to this WP.\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .requireAndStream()\n .pipe(\n takeUntil(componentDestroyed(this))\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n });\n }\n\n private getRelatedWorkPackages(workPackageIds:string[]):Observable {\n let observablesToGetZipped:Observable[] = workPackageIds.map(wpId =>\n this\n .apiV3Service\n .work_packages\n .id(wpId)\n .get()\n );\n\n return zip(...observablesToGetZipped);\n }\n\n protected getRelatedWorkPackageId(relation:RelationResource):string {\n const involved = relation.ids;\n return (relation.to.href === this.workPackage.href) ? involved.from : involved.to;\n }\n\n public toggleGroupBy() {\n this.groupByWorkPackageType = !this.groupByWorkPackageType;\n this.buildRelationGroups();\n }\n\n protected buildRelationGroups() {\n if (_.isNil(this.currentRelations)) {\n return;\n }\n\n this.relationGroups = _.groupBy(this.currentRelations,\n (wp:WorkPackageResource) => {\n if (this.groupByWorkPackageType) {\n return wp.type.name;\n } else {\n var normalizedType = (wp.relatedBy as RelationResource).normalizedType(this.workPackage);\n return this.I18n.t('js.relation_labels.' + normalizedType);\n }\n });\n this.relationGroupKeys = _.keys(this.relationGroups);\n this.relationsPresent = _.size(this.relationGroups) > 0;\n this.cdRef.detectChanges();\n }\n\n protected loadedRelations(stateValues:RelationsStateValue):void {\n var relatedWpIds:string[] = [];\n var relations:{ [wpId:string]:any } = [];\n\n if (_.size(stateValues) === 0) {\n this.currentRelations = [];\n return this.buildRelationGroups();\n }\n\n _.each(stateValues, (relation:RelationResource) => {\n const relatedWpId = this.getRelatedWorkPackageId(relation);\n relatedWpIds.push(relatedWpId);\n relations[relatedWpId] = relation;\n });\n\n this.getRelatedWorkPackages(relatedWpIds)\n .pipe(\n take(1)\n )\n .subscribe((relatedWorkPackages:WorkPackageResource[]) => {\n this.currentRelations = relatedWorkPackages.map((wp:WorkPackageResource) => {\n wp.relatedBy = relations[wp.id!];\n return wp;\n });\n\n this.buildRelationGroups();\n });\n }\n}\n","
    \n\n
    \n
    \n
    \n

    \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 identifier() {\n return `${this.href}-${this.version}`;\n }\n\n public get version() {\n return this.activity.version;\n }\n\n public get isNextDate() {\n return this.date !== this.dateOfPrevious;\n }\n\n public isInitial(forceReverse:boolean = false) {\n var activityNo = this.number(forceReverse);\n\n if (this.activity._type.indexOf('Activity') !== 0) {\n return false;\n }\n\n if (activityNo === 1) {\n return true;\n }\n\n while (--activityNo > 0) {\n var idx = this.orderedIndex(activityNo, forceReverse) - 1;\n var activity = this.activities[idx];\n if (!_.isNil(activity) && activity._type.indexOf('Activity') === 0) {\n return false;\n }\n }\n\n return true;\n }\n\n protected activityDate(activity:any) {\n // Force long date regardless of current date settings for headers\n return moment(activity.createdAt).format('LL');\n }\n\n protected orderedIndex(activityNo:number, forceReverse:boolean = false) {\n if (forceReverse || this.isReversed) {\n return this.activities.length - activityNo;\n }\n\n return activityNo + 1;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Injectable()\nexport class ViewpointsService {\n topicUUID:string|number;\n\n @InjectField() bcfApi:BcfApiService;\n @InjectField() viewerBridge:ViewerBridgeService;\n @InjectField() apiV3Service:APIV3Service;\n\n constructor(readonly injector:Injector) {}\n\n public getViewPointResource(workPackage:WorkPackageResource, index:number):BcfViewpointPaths {\n const viewpointHref = workPackage.bcfViewpoints[index].href;\n\n return this.bcfApi.parse(viewpointHref);\n }\n\n public getViewPoint$(workPackage:WorkPackageResource, index:number):Observable {\n const viewpointResource = this.getViewPointResource(workPackage, index);\n\n return viewpointResource.get();\n }\n\n public deleteViewPoint$(workPackage:WorkPackageResource, index:number):Observable {\n const viewpointResource = this.getViewPointResource(workPackage, index);\n\n return viewpointResource\n .delete()\n .pipe(\n // Update the work package to reload the viewpoints\n tap(() => this.apiV3Service.work_packages.id(workPackage).requireAndStream(true))\n );\n }\n\n public saveViewpoint$(workPackage:WorkPackageResource, viewpoint?:BcfViewpointInterface):Observable {\n const wpProjectId = workPackage.project.idFromLink;\n const topicUUID$ = this.setBcfTopic$(workPackage);\n // Default to the current viewer's viewpoint\n const viewpoint$ = viewpoint ?\n of(viewpoint) :\n this.viewerBridge!.getViewpoint$();\n\n return forkJoin({\n topicUUID: topicUUID$,\n viewpoint: viewpoint$,\n })\n .pipe(\n switchMap(results => {\n return this.bcfApi\n .projects.id(wpProjectId)\n .topics.id(results.topicUUID as (string | number))\n .viewpoints\n .post(results.viewpoint);\n }\n ),\n // Update the work package to reload the viewpoints\n tap((results) =>\n this.apiV3Service.work_packages.id(workPackage).requireAndStream(true))\n );\n }\n\n public setBcfTopic$(workPackage:WorkPackageResource) {\n if (this.topicUUID) {\n return of(this.topicUUID);\n } else {\n const topicHref = workPackage.bcfTopic?.href;\n const topicUUID$ = topicHref ?\n of(this.bcfApi.parse(topicHref)!.id) :\n this.createBcfTopic$(workPackage);\n\n return topicUUID$.pipe(map(topicUUID => this.topicUUID = topicUUID));\n }\n }\n\n private createBcfTopic$(workPackage:WorkPackageResource):Observable {\n const wpProjectId = workPackage.project.idFromLink;\n const wpPayload = workPackage.convertBCF.payload;\n\n return this.bcfApi\n .projects.id(wpProjectId)\n .topics\n .post(wpPayload)\n .pipe(\n map((resource:BcfTopicResource) => {\n this.topicUUID = resource.guid;\n return this.topicUUID;\n })\n );\n }\n}","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, Output} from '@angular/core';\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {VersionResource} from \"core-app/modules/hal/resources/version-resource\";\nimport {CreateAutocompleterComponent} from \"core-app/modules/common/autocomplete/create-autocompleter.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './create-autocompleter.component.html',\n selector: 'version-autocompleter'\n})\nexport class VersionAutocompleterComponent extends CreateAutocompleterComponent implements AfterViewInit {\n @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 apiV3Service:APIV3Service,\n readonly halNotification:HalResourceNotificationService) {\n super(I18n, cdRef, currentProject, pathHelper);\n }\n\n ngAfterViewInit() {\n super.ngAfterViewInit();\n\n this.canCreateNewActionElements().then((val) => {\n if (val) {\n this.createAllowed = (input:string) => this.createNewVersion(input);\n this.cdRef.detectChanges();\n }\n });\n }\n\n /**\n * Checks for correct permissions\n * (whether the current project is in the list of allowed values in the version create form)\n * @returns {Promise}\n */\n public canCreateNewActionElements():Promise {\n if (!this.currentProject.id) {\n return Promise.resolve(false);\n }\n\n return this\n .apiV3Service\n .versions\n .available_projects\n .exists(this.currentProject.id!)\n .toPromise()\n .catch(() => false);\n }\n\n protected createNewVersion(name:string) {\n this\n .apiV3Service\n .versions\n .post(this.getVersionPayload(name))\n .subscribe(\n version => this.onCreate.emit(version),\n error => {\n this.closeSelect();\n this.halNotification.handleRawError(error);\n });\n }\n\n private getVersionPayload(name:string) {\n let payload:any = {};\n payload['name'] = name;\n payload['_links'] = {\n definingProject: {\n href: this.apiV3Service.projects.id(this.currentProject.id!).path\n }\n };\n\n return payload;\n }\n}\n","// Separated from render passes to avoid cyclic dependencies\nexport const rowGroupClassName = 'wp-table--group-header';\nexport const collapsedRowClass = '-collapsed';\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {Directive, ElementRef} from \"@angular/core\";\nimport {OpContextMenuTrigger} from \"core-components/op-context-menu/handlers/op-context-menu-trigger.directive\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n WorkPackageViewDisplayRepresentationService,\n wpDisplayCardRepresentation,\n wpDisplayListRepresentation\n} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service\";\nimport {WorkPackageViewTimelineService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service\";\nimport {WorkPackageViewCollapsedGroupsService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-collapsed-groups.service\";\n\n@Directive({\n selector: '[wpGroupToggleDropdown]'\n})\nexport class WorkPackageGroupToggleDropdownMenuDirective extends OpContextMenuTrigger {\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly I18n:I18nService,\n readonly wpViewCollapsedGroups:WorkPackageViewCollapsedGroupsService) {\n super(elementRef, opContextMenu);\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n this.buildItems();\n this.opContextMenu.show(this, evt);\n }\n\n public get locals() {\n return {\n items: this.items,\n contextMenuId: 'wp-group-fold-context-menu'\n };\n }\n\n private buildItems() {\n this.items = [\n {\n disabled: this.wpViewCollapsedGroups.allGroupsAreCollapsed,\n linkText: this.I18n.t('js.button_collapse_all'),\n icon: 'icon-minus2',\n onClick: (evt:JQuery.TriggeredEvent) => {\n this.wpViewCollapsedGroups.setAllGroupsCollapseStateTo(true);\n\n return true;\n }\n },\n {\n disabled: this.wpViewCollapsedGroups.allGroupsAreExpanded,\n linkText: this.I18n.t('js.button_expand_all'),\n icon: 'icon-plus',\n onClick: (evt:JQuery.TriggeredEvent) => {\n this.wpViewCollapsedGroups.setAllGroupsCollapseStateTo(false);\n\n return true;\n }\n }\n ];\n }\n}\n\n","import {Constructor} from \"@angular/cdk/table\";\nimport {SimpleResource, SimpleResourceCollection} from \"core-app/modules/apiv3/paths/path-resources\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {Observable} from \"rxjs\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class APIv3ResourcePath extends SimpleResource {\n readonly injector = this.apiRoot.injector;\n @InjectField() halResourceService:HalResourceService;\n\n constructor(protected apiRoot:APIV3Service,\n readonly basePath:string,\n readonly id:string|number,\n protected parent?:APIv3ResourcePath|APIv3ResourceCollection) {\n super(basePath, id);\n }\n\n\n /**\n * Build a singular resource from the current segment\n *\n * @param segment Additional segment to add to the current path\n */\n protected subResource(segment:string, cls:Constructor = APIv3GettableResource as any):R {\n return new cls(this.apiRoot, this.path, segment, this);\n }\n}\n\n\nexport class APIv3GettableResource extends APIv3ResourcePath {\n /**\n * Perform a request to the HalResourceService with the current path\n */\n public get():Observable {\n return this\n .halResourceService\n .get(this.path) as any;\n }\n}\n\nexport class APIv3ResourceCollection> extends SimpleResourceCollection {\n readonly injector = this.apiRoot.injector;\n @InjectField() halResourceService:HalResourceService;\n\n constructor(protected apiRoot:APIV3Service,\n protected basePath:string,\n segment:string,\n protected resource?:Constructor) {\n super(basePath, segment, resource);\n }\n\n /**\n * Returns an instance of T for the given singular resource ID.\n *\n * @param id Identifier of the resource, may be a string or number, or a HalResource with id property.\n */\n public id(input:string|number|{ id:string|null }):T {\n let id:string;\n if (typeof input === 'string' || typeof input === 'number') {\n id = input.toString();\n } else {\n id = input.id!;\n }\n\n return new (this.resource || APIv3GettableResource)(this.apiRoot, this.path, id, this) as T;\n }\n\n\n public withOptionalId(id?:string|number|null):this|T {\n if (_.isNil(id)) {\n return this;\n } else {\n return this.id(id);\n }\n }\n\n /**\n * Returns the path string to the requested endpoint.\n */\n public toString():string {\n return this.path;\n }\n\n /**\n * Returns the path string to the requested endpoint.\n */\n public toPath():string {\n return this.path;\n }\n\n /**\n * Returns a new resource with the path extended with a URL query\n * to match the filters.\n *\n * @param filters filter object to filter with\n * @param params additional URL params to append\n */\n public filtered>(filters:ApiV3FilterBuilder, params:{ [key:string]:string } = {}, resourceClass?:Constructor):R {\n return this.subResource('?' + filters.toParams(params), resourceClass) as R;\n }\n\n /**\n * Build a singular resource from the current segment\n *\n * @param segment Additional segment to add to the current path\n */\n protected subResource>(segment:string, cls:Constructor = APIv3GettableResource as any):R {\n return new cls(this.apiRoot, this.path, segment, this);\n }\n}","import {ApplicationRef, ComponentFactoryResolver, Injectable, Injector} from '@angular/core';\nimport {ComponentPortal, DomPortalOutlet, PortalInjector} from '@angular/cdk/portal';\nimport {TransitionService} from '@uirouter/core';\nimport {FocusHelperService} from 'core-app/modules/common/focus/focus-helper';\nimport {\n ExternalQueryConfigurationComponent,\n QueryConfigurationLocals\n} from \"core-components/wp-table/external-configuration/external-query-configuration.component\";\nimport {OpQueryConfigurationLocalsToken} from \"core-components/wp-table/external-configuration/external-query-configuration.constants\";\n\nexport type Class = { new(...args:any[]):any; };\n\n@Injectable()\nexport class ExternalQueryConfigurationService {\n\n // Hold a reference to the DOM node we're using as a host\n private _portalHostElement:HTMLElement;\n // And a reference to the actual portal host interface on top of the element\n private _bodyPortalHost:DomPortalOutlet;\n\n constructor(private componentFactoryResolver:ComponentFactoryResolver,\n readonly FocusHelper:FocusHelperService,\n private appRef:ApplicationRef,\n private $transitions:TransitionService,\n private injector:Injector) {\n }\n\n /**\n * Create a portal host element to contain the table configuration components.\n */\n private get bodyPortalHost() {\n if (!this._portalHostElement) {\n const hostElement = this._portalHostElement = document.createElement('div');\n hostElement.classList.add('op-external-query-configuration--container');\n document.body.appendChild(hostElement);\n\n this._bodyPortalHost = new DomPortalOutlet(\n hostElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n }\n\n return this._bodyPortalHost;\n }\n\n /**\n * Open a Modal reference and append it to the portal\n */\n public show(data:Partial) {\n this.detach();\n\n // Create a portal for the given component class and render it\n const portal = new ComponentPortal(\n this.externalQueryConfigurationComponent(),\n null,\n this.injectorFor(data)\n );\n this.bodyPortalHost.attach(portal);\n this._portalHostElement.style.display = 'block';\n }\n\n /**\n * Closes currently open modal window\n */\n public detach() {\n // Detach any component currently in the portal\n if (this.bodyPortalHost.hasAttached()) {\n this.bodyPortalHost.detach();\n this._portalHostElement.style.display = 'none';\n }\n }\n\n /**\n * Create an augmented injector that is equal to this service's injector + the additional data\n * passed into +show+.\n * This allows callers to pass data into the newly created modal.\n *\n */\n private injectorFor(data:any) {\n const injectorTokens = new WeakMap();\n // Pass the service because otherwise we're getting a cyclic dependency between the portal\n // host service and the bound portal\n data.service = this;\n\n injectorTokens.set(OpQueryConfigurationLocalsToken, data);\n\n return new PortalInjector(this.injector, injectorTokens);\n }\n\n externalQueryConfigurationComponent():Class {\n return ExternalQueryConfigurationComponent;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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 {UserResource} from \"core-app/modules/hal/resources/user-resource\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'revision-activity',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './revision-activity.component.html'\n})\nexport class RevisionActivityComponent implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public activity:any;\n @Input() public activityNo:number;\n\n public userId:string | number;\n public userName:string;\n public userActive:boolean;\n public userPath:string | null;\n public userLabel:string;\n public userAvatar:string;\n\n public project:ProjectResource;\n public revision:string;\n public message:string;\n\n public revisionLink:string;\n\n constructor(readonly I18n:I18nService,\n readonly timezoneService:TimezoneService,\n readonly cdRef:ChangeDetectorRef,\n readonly apiV3Service:APIV3Service) {\n }\n\n ngOnInit() {\n this.loadAuthor();\n\n this.project = this.workPackage.project;\n this.revision = this.activity.identifier;\n this.message = this.activity.message.html;\n\n const revisionPath = this.activity.showRevision.$link.href;\n const formattedRevision = this.activity.formattedIdentifier;\n\n const link = document.createElement('a');\n link.href = revisionPath;\n link.title = this.revision;\n link.textContent = this.I18n.t(\n \"js.label_committed_link\",\n {revision_identifier: formattedRevision}\n );\n\n this.revisionLink = this.I18n.t(\"js.label_committed_at\",\n {\n committed_revision_link: link.outerHTML,\n date: this.timezoneService.formattedDatetime(this.activity.createdAt)\n });\n }\n\n private loadAuthor() {\n if (this.activity.author === undefined) {\n this.userName = this.activity.authorName;\n } else {\n this\n .apiV3Service\n .users\n .id(this.activity.author.idFromLink)\n .get()\n .subscribe((user:UserResource) => {\n this.userId = user.id!;\n this.userName = user.name;\n this.userActive = user.isActive;\n this.userAvatar = user.avatar;\n this.userPath = user.showUser.href;\n this.userLabel = this.I18n.t('js.label_author', {user: this.userName});\n this.cdRef.detectChanges();\n });\n }\n }\n}\n","
    \n
    \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 = null;\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","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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, OnInit} from \"@angular/core\";\nimport * as moment from \"moment\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {EditFieldComponent} from \"core-app/modules/fields/edit/edit-field.component\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\n\n@Component({\n template: `\n \n \n `\n})\nexport class DateEditFieldComponent extends EditFieldComponent implements OnInit {\n @InjectField() readonly timezoneService:TimezoneService;\n @InjectField() opModalService:OpModalService;\n\n ngOnInit() {\n super.ngOnInit();\n }\n\n public onValueSelected(data:string) {\n this.value = this.parser(data);\n this.handler.handleUserSubmit();\n }\n\n public onCancel() {\n this.handler.handleUserCancel();\n }\n\n public parser(data:any) {\n if (moment(data, 'YYYY-MM-DD', true).isValid()) {\n return data;\n } else {\n return null;\n }\n }\n\n public formatter(data:any) {\n if (moment(data, 'YYYY-MM-DD', true).isValid()) {\n var d = this.timezoneService.parseDate(data);\n return this.timezoneService.formattedISODate(d);\n } else {\n return null;\n }\n }\n}\n","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 {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {\n TimeEntryWorkPackageAutocompleterComponent,\n TimeEntryWorkPackageAutocompleterMode\n} from \"core-app/modules/common/autocomplete/te-work-package-autocompleter.component\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nconst RECENT_TIME_ENTRIES_MAGIC_NUMBER = 30;\n\n@Component({\n templateUrl: './work-package-edit-field.component.html'\n})\nexport class TimeEntryWorkPackageEditFieldComponent extends WorkPackageEditFieldComponent {\n @InjectField() apiV3Service:APIV3Service;\n\n private recentWorkPackageIds:string[];\n\n protected initialize() {\n super.initialize();\n\n // For reasons beyond me, the referenceOutputs variable is not defined at first when editing\n // existing values.\n if (this.referenceOutputs) {\n this.referenceOutputs['modeSwitch'] = (mode:TimeEntryWorkPackageAutocompleterMode) => {\n this.valuesLoaded = false;\n let lastValue = this.requests.lastRequestedValue!;\n\n // Hack to provide a new value to \"reset\" the input.\n // Only the second input is actually processed as the input is debounced.\n this.requests.input$.next('_/&\"()____');\n this.requests.input$.next(lastValue);\n };\n }\n }\n\n public autocompleterComponent() {\n return TimeEntryWorkPackageAutocompleterComponent;\n }\n\n // Although the schema states the work packages to not be required,\n // as time entries can also be assigned to a project, we want to only assign\n // time entries to work packages and thus require a value.\n // The back end will have to be changed in due time but not as long as there is still a rails based\n // time entry view in the application.\n protected isRequired() {\n return true;\n }\n\n // We fetch the last RECENT_TIME_ENTRIES_MAGIC_NUMBER time entries by that user. We then use it to fetch the work packages\n // associated with the time entries so that we have the most recent work packages the user logged time on.\n // As a worst case, the user logged RECENT_TIME_ENTRIES_MAGIC_NUMBER times on one work package so we can not guarantee to actually have\n // a fixed number returned.\n protected loadAllowedValues(query?:string) {\n if (!this.recentWorkPackageIds) {\n return this\n .apiV3Service\n .time_entries\n .list({ filters: [['user_id', '=', ['me']]], sortBy: [[\"updated_at\", \"desc\"]], pageSize: RECENT_TIME_ENTRIES_MAGIC_NUMBER })\n .toPromise()\n .then(collection => {\n this.recentWorkPackageIds = collection\n .elements\n .map((timeEntry) => timeEntry.workPackage.idFromLink)\n .filter((v, i, a) => a.indexOf(v) === i);\n\n return this.fetchAllowedValueQuery(query);\n });\n } else {\n return this.fetchAllowedValueQuery(query);\n }\n }\n\n protected allowedValuesFilter(query?:string):{} {\n let filters:ApiV3FilterBuilder = new ApiV3FilterBuilder();\n\n if ((this._autocompleterComponent as TimeEntryWorkPackageAutocompleterComponent).mode === 'recent') {\n filters.add('id', '=', this.recentWorkPackageIds);\n }\n\n if (query) {\n filters.add('subjectOrId', '**', [query]);\n }\n\n return { filters: filters.toJson() };\n }\n\n protected sortValues(availableValues:HalResource[]) {\n if ((this._autocompleterComponent as TimeEntryWorkPackageAutocompleterComponent).mode === 'recent') {\n return this.sortValuesByRecentIds(availableValues);\n } else {\n return super.sortValues(availableValues);\n }\n }\n\n protected sortValuesByRecentIds(availableValues:HalResource[]) {\n return availableValues\n .sort((a, b) => {\n return this.recentWorkPackageIds.indexOf(a.id!) - this.recentWorkPackageIds.indexOf(b.id!);\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Component, OnDestroy, OnInit} from \"@angular/core\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {DatePickerModal} from \"core-components/datepicker/datepicker.modal\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\nimport {take} from \"rxjs/operators\";\nimport {DateEditFieldComponent} from \"core-app/modules/fields/edit/field-types/date-edit-field.component\";\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\n\n@Component({\n template: `\n \n `\n})\nexport class CombinedDateEditFieldComponent extends DateEditFieldComponent implements OnInit, OnDestroy {\n @InjectField() readonly timezoneService:TimezoneService;\n @InjectField() opModalService:OpModalService;\n\n dates:string = '';\n text_no_start_date = this.I18n.t('js.label_no_start_date');\n text_no_due_date = this.I18n.t('js.label_no_due_date');\n\n private modal:OpModalComponent;\n\n ngOnInit() {\n super.ngOnInit();\n\n this.handler\n .$onUserActivate\n .pipe(\n this.untilDestroyed()\n )\n .subscribe(() => {\n this.showDatePickerModal();\n });\n }\n\n ngOnDestroy() {\n super.ngOnDestroy();\n this.modal?.closeMe();\n }\n\n public handleClick() {\n this.showDatePickerModal();\n }\n\n private showDatePickerModal():void {\n const modal = this.modal = this\n .opModalService\n .show(DatePickerModal, this.injector, { changeset: this.change, fieldName: this.name });\n\n setTimeout(() => {\n const modalElement = jQuery(modal.elementRef.nativeElement).find('.datepicker-modal');\n const field = jQuery(this.elementRef.nativeElement);\n modal.reposition(modalElement, field);\n });\n\n modal\n .onDataUpdated\n .subscribe((dates:string) => {\n this.dates = dates;\n this.cdRef.detectChanges();\n });\n\n modal\n .closingEvent\n .pipe(take(1))\n .subscribe(() => {\n this.handler.handleUserSubmit();\n });\n }\n\n // Overwrite super in order to set the inital dates.\n protected initialize() {\n super.initialize();\n\n // this breaks the preceived abstraction of the edit fields. But the date picker\n // is already highly specific to start and due Date.\n this.dates = `${this.currentStartDate} - ${this.currentDueDate}`;\n }\n\n protected get currentStartDate():string {\n return this.resource.startDate || this.text_no_start_date;\n }\n\n protected get currentDueDate():string {\n return this.resource.dueDate || this.text_no_due_date;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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(\n 'read-value--html',\n 'highlight',\n 'op-uc-container',\n 'op-uc-container_reduced-headings',\n '-multiline',\n );\n if (options.rtl) {\n div.classList.add('-rtl');\n }\n\n div.innerHTML = displayText;\n\n element.innerHTML = '';\n element.appendChild(div);\n\n // Allow embeddable rendered content\n DynamicBootstrapper.bootstrapOptionalEmbeddable(this.appRef, div);\n }\n\n public get isFormattable():boolean {\n return true;\n }\n\n public get value() {\n if (!this.schema) {\n return null;\n }\n const element = this.resource[this.name];\n if (!(element && element.html)) {\n return '';\n }\n\n return this.unescape(element.html);\n }\n\n // Escape the given HTML string from the backend, which contains escaped Angular expressions.\n // Since formattable fields are only binded to but never evaluated, we can safely remove these expressions.\n protected unescape(html:string) {\n if (html) {\n return ExpressionService.unescape(html);\n } else {\n return '';\n }\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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 {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 { ProjectResource } from \"core-app/modules/hal/resources/project-resource\";\nimport { InjectField } from \"core-app/helpers/angular/inject-field.decorator\";\nimport * as URI from 'urijs';\nimport { TimeEntryCreateService } from 'core-app/modules/time_entries/create/create.service';\nimport { WorkPackageResource } from \"core-app/modules/hal/resources/work-package-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class WorkPackageSpentTimeDisplayField extends DurationDisplayField {\n public text = {\n linkTitle: this.I18n.t('js.work_packages.message_view_spent_time'),\n logTime: this.I18n.t('js.button_log_time')\n };\n\n @InjectField() PathHelper:PathHelperService;\n @InjectField(TimeEntryCreateService, null) timeEntryCreateService:TimeEntryCreateService;\n @InjectField() apiV3Service:APIV3Service;\n\n public render(element:HTMLElement, displayText:string):void {\n if (!this.value) {\n return;\n }\n\n const link = document.createElement('a');\n link.textContent = displayText;\n link.setAttribute('title', this.text.linkTitle);\n link.setAttribute('class', 'time-logging--value');\n\n if (this.resource.project) {\n const wpID = this.resource.id.toString();\n this\n .apiV3Service\n .projects\n .id(this.resource.project)\n .get()\n .subscribe((project:ProjectResource) => {\n // Link to the cost report having the work package filter preselected. No grouping.\n const href = URI(this.PathHelper.projectTimeEntriesPath(project.identifier))\n .search(`fields[]=WorkPackageId&operators[WorkPackageId]=%3D&values[WorkPackageId]=${wpID}&set_filter=1`)\n .toString();\n\n link.href = href;\n });\n }\n\n element.innerHTML = '';\n element.appendChild(link);\n\n this.appendTimelogLink(element);\n }\n\n private appendTimelogLink(element:HTMLElement) {\n if (this.timeEntryCreateService && this.resource.logTime) {\n const timelogElement = document.createElement('a');\n timelogElement.setAttribute('class', 'icon icon-time');\n timelogElement.setAttribute('href', '');\n timelogElement.setAttribute('title', this.text.logTime);\n\n element.appendChild(timelogElement);\n\n timelogElement.addEventListener('click', this.showTimelogWidget.bind(this, this.resource));\n }\n }\n\n private showTimelogWidget(wp:WorkPackageResource) {\n this.timeEntryCreateService\n .create(moment(new Date()), wp, false)\n .catch(() => {\n // do nothing, the user closed without changes\n });\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 const bulb = document.createElement('span');\n bulb.classList.add('project-status--bulb', projectStatusCodeCssClass(code));\n\n const name = document.createElement('span');\n name.classList.add('project-status--name', projectStatusCodeCssClass(code));\n name.textContent = projectStatusI18n(code, this.I18n);\n\n element.innerHTML = '';\n element.appendChild(bulb);\n element.appendChild(name);\n\n if (this.writable) {\n const pulldown = document.createElement('span');\n pulldown.classList.add('project-status--pulldown-icon', 'icon', 'icon-pulldown');\n\n element.appendChild(pulldown);\n }\n }\n}\n","// -- copyright\n// OpenProject is 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 let title = document.createElement('span');\n title.textContent = ' ' + _.truncate(this.title, {length: 40});\n\n element.innerHTML = '';\n element.appendChild(link);\n element.appendChild(title);\n }\n\n public get writable():boolean {\n return false;\n }\n\n public get valueString() {\n return '#' + this.wpId;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APP_INITIALIZER, NgModule} from '@angular/core';\nimport {EditFieldService} from \"core-app/modules/fields/edit/edit-field.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {initializeCoreEditFields} from \"core-app/modules/fields/edit/edit-field.initializer\";\nimport {initializeCoreDisplayFields} from \"core-app/modules/fields/display/display-field.initializer\";\nimport {BooleanEditFieldComponent} from \"core-app/modules/fields/edit/field-types/boolean-edit-field.component\";\nimport {DateEditFieldComponent} from \"core-app/modules/fields/edit/field-types/date-edit-field.component\";\nimport {DurationEditFieldComponent} from \"core-app/modules/fields/edit/field-types/duration-edit-field.component\";\nimport {FloatEditFieldComponent} from \"core-app/modules/fields/edit/field-types/float-edit-field.component\";\nimport {IntegerEditFieldComponent} from \"core-app/modules/fields/edit/field-types/integer-edit-field.component\";\nimport {MultiSelectEditFieldComponent} from \"core-app/modules/fields/edit/field-types/multi-select-edit-field.component\";\nimport {SelectEditFieldComponent} from \"core-app/modules/fields/edit/field-types/select-edit-field.component\";\nimport {FormattableEditFieldComponent} from \"core-app/modules/fields/edit/field-types/formattable-edit-field.component\";\nimport {TextEditFieldComponent} from \"core-app/modules/fields/edit/field-types/text-edit-field.component\";\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {EditFormPortalComponent} from \"core-app/modules/fields/edit/editing-portal/edit-form-portal.component\";\nimport {EditFieldControlsComponent,} from \"core-app/modules/fields/edit/field-controls/edit-field-controls.component\";\nimport {OpenprojectAccessibilityModule} from \"core-app/modules/a11y/openproject-a11y.module\";\nimport {OpenprojectEditorModule} from 'core-app/modules/editor/openproject-editor.module';\nimport {SelectAutocompleterRegisterService} from \"core-app/modules/fields/edit/field-types/select-autocompleter-register.service\";\nimport {EditFormComponent} from \"core-app/modules/fields/edit/edit-form/edit-form.component\";\nimport {WorkPackageEditFieldComponent} from \"core-app/modules/fields/edit/field-types/work-package-edit-field.component\";\nimport {EditableAttributeFieldComponent} from \"core-app/modules/fields/edit/field/editable-attribute-field.component\";\nimport {ProjectStatusEditFieldComponent} from \"core-app/modules/fields/edit/field-types/project-status-edit-field.component\";\nimport {PlainFormattableEditFieldComponent} from \"core-app/modules/fields/edit/field-types/plain-formattable-edit-field.component\";\nimport {TimeEntryWorkPackageEditFieldComponent} from \"core-app/modules/fields/edit/field-types/te-work-package-edit-field.component\";\nimport {AttributeValueMacroComponent} from \"core-app/modules/fields/macros/attribute-value-macro.component\";\nimport {AttributeLabelMacroComponent} from \"core-app/modules/fields/macros/attribute-label-macro.component\";\nimport {AttributeHelpTextComponent} from \"core-app/modules/fields/help-texts/attribute-help-text.component\";\nimport {AttributeHelpTextModal} from \"core-app/modules/fields/help-texts/attribute-help-text.modal\";\nimport {OpenprojectAttachmentsModule} from \"core-app/modules/attachments/openproject-attachments.module\";\nimport {WorkPackageQuickinfoMacroComponent} from \"core-app/modules/fields/macros/work-package-quickinfo-macro.component\";\nimport {DisplayFieldComponent} from \"core-app/modules/fields/display/display-field.component\";\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n OpenprojectAttachmentsModule,\n OpenprojectAccessibilityModule,\n OpenprojectEditorModule,\n ],\n exports: [\n EditFieldControlsComponent,\n EditFormPortalComponent,\n EditFormComponent,\n EditableAttributeFieldComponent,\n AttributeHelpTextComponent,\n ],\n providers: [\n {\n provide: APP_INITIALIZER,\n useFactory: initializeCoreEditFields,\n deps: [EditFieldService, SelectAutocompleterRegisterService],\n multi: true\n },\n {\n provide: APP_INITIALIZER,\n useFactory: initializeCoreDisplayFields,\n deps: [DisplayFieldService],\n multi: true\n },\n ],\n declarations: [\n EditFormPortalComponent,\n BooleanEditFieldComponent,\n DateEditFieldComponent,\n DurationEditFieldComponent,\n FloatEditFieldComponent,\n IntegerEditFieldComponent,\n FormattableEditFieldComponent,\n PlainFormattableEditFieldComponent,\n MultiSelectEditFieldComponent,\n SelectEditFieldComponent,\n TextEditFieldComponent,\n EditFieldControlsComponent,\n WorkPackageEditFieldComponent,\n TimeEntryWorkPackageEditFieldComponent,\n EditFormComponent,\n DisplayFieldComponent,\n EditableAttributeFieldComponent,\n ProjectStatusEditFieldComponent,\n AttributeValueMacroComponent,\n AttributeLabelMacroComponent,\n\n // Help texts\n AttributeHelpTextComponent,\n AttributeHelpTextModal,\n WorkPackageQuickinfoMacroComponent,\n ]\n})\nexport class OpenprojectFieldsModule {\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {EditFieldService} from \"core-app/modules/fields/edit/edit-field.service\";\nimport {TextEditFieldComponent} from \"core-app/modules/fields/edit/field-types/text-edit-field.component\";\nimport {IntegerEditFieldComponent} from \"core-app/modules/fields/edit/field-types/integer-edit-field.component\";\nimport {DurationEditFieldComponent} from \"core-app/modules/fields/edit/field-types/duration-edit-field.component\";\nimport {SelectEditFieldComponent} from \"core-app/modules/fields/edit/field-types/select-edit-field.component\";\nimport {MultiSelectEditFieldComponent} from \"core-app/modules/fields/edit/field-types/multi-select-edit-field.component\";\nimport {FloatEditFieldComponent} from \"core-app/modules/fields/edit/field-types/float-edit-field.component\";\nimport {BooleanEditFieldComponent} from \"core-app/modules/fields/edit/field-types/boolean-edit-field.component\";\nimport {WorkPackageEditFieldComponent} from \"core-app/modules/fields/edit/field-types/work-package-edit-field.component\";\nimport {DateEditFieldComponent} from \"core-app/modules/fields/edit/field-types/date-edit-field.component\";\nimport {FormattableEditFieldComponent} from \"core-app/modules/fields/edit/field-types/formattable-edit-field.component\";\nimport {WorkPackageCommentFieldComponent} from \"core-components/work-packages/work-package-comment/wp-comment-field.component\";\nimport {SelectAutocompleterRegisterService} from \"core-app/modules/fields/edit/field-types/select-autocompleter-register.service\";\nimport {VersionAutocompleterComponent} from \"core-app/modules/common/autocomplete/version-autocompleter.component\";\nimport {ProjectStatusEditFieldComponent} from \"core-app/modules/fields/edit/field-types/project-status-edit-field.component\";\nimport {PlainFormattableEditFieldComponent} from \"core-app/modules/fields/edit/field-types/plain-formattable-edit-field.component\";\nimport {WorkPackageAutocompleterComponent} from \"core-app/modules/common/autocomplete/wp-autocompleter.component\";\nimport {TimeEntryWorkPackageEditFieldComponent} from \"core-app/modules/fields/edit/field-types/te-work-package-edit-field.component\";\nimport {CombinedDateEditFieldComponent} from \"core-app/modules/fields/edit/field-types/combined-date-edit-field.component\";\n\n\nexport function initializeCoreEditFields(editFieldService:EditFieldService, selectAutocompleterRegisterService:SelectAutocompleterRegisterService) {\n return () => {\n editFieldService.defaultFieldType = 'text';\n editFieldService\n .addFieldType(TextEditFieldComponent, 'text', ['String'])\n .addFieldType(IntegerEditFieldComponent, 'integer', ['Integer'])\n .addFieldType(DurationEditFieldComponent, 'duration', ['Duration'])\n .addFieldType(SelectEditFieldComponent, 'select', ['Priority',\n 'Status',\n 'Type',\n 'User',\n 'Version',\n 'TimeEntriesActivity',\n 'Category',\n 'CustomOption',\n 'Project'])\n .addFieldType(MultiSelectEditFieldComponent, 'multi-select', [\n '[]CustomOption',\n '[]User'\n ])\n .addFieldType(FloatEditFieldComponent, 'float', ['Float'])\n .addFieldType(WorkPackageEditFieldComponent, 'workPackage', ['WorkPackage'])\n .addFieldType(BooleanEditFieldComponent, 'boolean', ['Boolean'])\n .addFieldType(DateEditFieldComponent, 'date', ['Date'])\n .addFieldType(FormattableEditFieldComponent, 'wiki-textarea', ['Formattable'])\n .addFieldType(ProjectStatusEditFieldComponent, 'project_status', ['ProjectStatus'])\n .addFieldType(WorkPackageCommentFieldComponent, '_comment', ['comment']);\n\n editFieldService\n .addSpecificFieldType('WorkPackage', CombinedDateEditFieldComponent,\n 'date',\n ['combinedDate', 'startDate', 'dueDate', 'date'])\n .addSpecificFieldType('TimeEntry', PlainFormattableEditFieldComponent, 'comment', ['comment'])\n .addSpecificFieldType('TimeEntry', TimeEntryWorkPackageEditFieldComponent, 'workPackage', ['WorkPackage']);\n\n selectAutocompleterRegisterService.register(VersionAutocompleterComponent, 'Version');\n selectAutocompleterRegisterService.register(WorkPackageAutocompleterComponent, 'WorkPackage');\n };\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {TextDisplayField} from \"core-app/modules/fields/display/field-types/text-display-field.module\";\nimport {FloatDisplayField} from \"core-app/modules/fields/display/field-types/float-display-field.module\";\nimport {IntegerDisplayField} from \"core-app/modules/fields/display/field-types/integer-display-field.module\";\nimport {ResourceDisplayField} from \"core-app/modules/fields/display/field-types/resource-display-field.module\";\nimport {ResourcesDisplayField} from \"core-app/modules/fields/display/field-types/resources-display-field.module\";\nimport {FormattableDisplayField} from \"core-app/modules/fields/display/field-types/formattable-display-field.module\";\nimport {DurationDisplayField} from \"core-app/modules/fields/display/field-types/duration-display-field.module\";\nimport {DateDisplayField} from \"core-app/modules/fields/display/field-types/date-display-field.module\";\nimport {DateTimeDisplayField} from \"core-app/modules/fields/display/field-types/datetime-display-field.module\";\nimport {BooleanDisplayField} from \"core-app/modules/fields/display/field-types/boolean-display-field.module\";\nimport {ProgressDisplayField} from \"core-app/modules/fields/display/field-types/progress-display-field.module\";\nimport {WorkPackageDisplayField} from \"core-app/modules/fields/display/field-types/work-package-display-field.module\";\nimport {WorkPackageSpentTimeDisplayField} from \"core-app/modules/fields/display/field-types/wp-spent-time-display-field.module\";\nimport {IdDisplayField} from \"core-app/modules/fields/display/field-types/id-display-field.module\";\nimport {HighlightedResourceDisplayField} from \"core-app/modules/fields/display/field-types/highlighted-resource-display-field.module\";\nimport {TypeDisplayField} from \"core-app/modules/fields/display/field-types/type-display-field.module\";\nimport {UserDisplayField} from \"core-app/modules/fields/display/field-types/user-display-field.module\";\nimport {MultipleUserFieldModule} from \"core-app/modules/fields/display/field-types/multiple-user-display-field.module\";\nimport {WorkPackageIdDisplayField} from \"core-app/modules/fields/display/field-types/wp-id-display-field.module\";\nimport {ProjectStatusDisplayField} from \"core-app/modules/fields/display/field-types/project-status-display-field.module\";\nimport {PlainFormattableDisplayField} from \"core-app/modules/fields/display/field-types/plain-formattable-display-field.module\";\nimport {LinkedWorkPackageDisplayField} from \"core-app/modules/fields/display/field-types/linked-work-package-display-field.module\";\nimport {CombinedDateDisplayField} from \"core-app/modules/fields/display/field-types/combined-date-display.field\";\n\nexport function initializeCoreDisplayFields(displayFieldService:DisplayFieldService) {\n return () => {\n displayFieldService.defaultFieldType = 'text';\n displayFieldService\n .addFieldType(TextDisplayField, 'text', ['String'])\n .addFieldType(FloatDisplayField, 'float', ['Float'])\n .addFieldType(IntegerDisplayField, 'integer', ['Integer'])\n .addFieldType(HighlightedResourceDisplayField, 'highlight', [\n 'Status',\n 'Priority'\n ])\n .addFieldType(TypeDisplayField, 'type', ['Type'])\n .addFieldType(ResourceDisplayField, 'resource', [\n 'Project',\n 'TimeEntriesActivity',\n 'Version',\n 'Category',\n 'CustomOption'])\n .addFieldType(ResourcesDisplayField, 'resources', ['[]CustomOption'])\n .addFieldType(MultipleUserFieldModule, 'users', ['[]User'])\n .addFieldType(FormattableDisplayField, 'formattable', ['Formattable'])\n .addFieldType(DurationDisplayField, 'duration', ['Duration'])\n .addFieldType(DateDisplayField, 'date', ['Date'])\n .addFieldType(DateTimeDisplayField, 'datetime', ['DateTime'])\n .addFieldType(BooleanDisplayField, 'boolean', ['Boolean'])\n .addFieldType(ProgressDisplayField, 'progress', ['percentageDone'])\n .addFieldType(LinkedWorkPackageDisplayField, 'work_package', ['WorkPackage'])\n .addFieldType(IdDisplayField, 'id', ['id'])\n .addFieldType(ProjectStatusDisplayField, 'project_status', ['ProjectStatus'])\n .addFieldType(UserDisplayField, 'user', ['User']);\n\n displayFieldService\n .addSpecificFieldType('WorkPackage', WorkPackageIdDisplayField, 'id', ['id'])\n .addSpecificFieldType('WorkPackage', WorkPackageSpentTimeDisplayField, 'spentTime', ['spentTime'])\n .addSpecificFieldType('WorkPackage', CombinedDateDisplayField, 'combinedDate', ['combinedDate'])\n .addSpecificFieldType('TimeEntry', PlainFormattableDisplayField, 'comment', ['comment'])\n .addSpecificFieldType('TimeEntry', WorkPackageDisplayField, 'work_package', ['workPackage']);\n };\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\n\nexport class SchemaDependencyResource extends HalResource {\n\n public dependencies:any;\n\n public forValue(value:string):any {\n return this.dependencies[value];\n }\n}\n","import {contextColumnIcon, OpTableAction} from 'core-components/wp-table/table-actions/table-action';\nimport {opIconElement} from 'core-app/helpers/op-icon-builder';\n\nimport {KeepTabService} from 'core-components/wp-single-view-tabs/keep-tab/keep-tab.service';\nimport {UiStateLinkBuilder} from 'core-components/wp-fast-table/builders/ui-state-link-builder';\nimport {StateService} from \"@uirouter/core\";\n\nexport const detailsLinkClassName = 'wp-table--details-link';\n\nexport class OpDetailsTableAction extends OpTableAction {\n\n public readonly identifier = 'open-details-action';\n private uiStatebuilder = new UiStateLinkBuilder(this.injector.get(StateService), this.injector.get(KeepTabService));\n private text = {\n button: this.I18n.t('js.button_open_details')\n }\n\n public buildElement() {\n // Append details button\n let detailsLink = this.uiStatebuilder.linkToDetails(\n this.workPackage.id!,\n this.text.button,\n ''\n );\n\n detailsLink.classList.add(detailsLinkClassName, contextColumnIcon, 'hidden-for-mobile');\n detailsLink.appendChild(opIconElement('icon', 'icon-info2'));\n\n return detailsLink;\n }\n}\n","import {\n contextColumnIcon,\n contextMenuLinkClassName,\n OpTableAction\n} from 'core-components/wp-table/table-actions/table-action';\nimport {opIconElement} from 'core-app/helpers/op-icon-builder';\n\nexport class OpContextMenuTableAction extends OpTableAction {\n\n public readonly identifier = 'open-context-menu-action';\n\n private text = {\n linkTitle: this.I18n.t('js.label_open_context_menu')\n };\n\n public buildElement() {\n let contextMenu = document.createElement('a');\n contextMenu.href = '#';\n contextMenu.classList.add(contextMenuLinkClassName, contextColumnIcon);\n contextMenu.title = this.text.linkTitle;\n contextMenu.appendChild(opIconElement('icon', 'icon-show-more-horizontal'));\n\n return contextMenu;\n }\n}\n","import {Injectable, Injector} from '@angular/core';\nimport {\n OpTableActionFactory,\n} from 'core-components/wp-table/table-actions/table-action';\nimport {OpDetailsTableAction} from 'core-components/wp-table/table-actions/actions/details-table-action';\nimport {OpContextMenuTableAction} from 'core-components/wp-table/table-actions/actions/context-menu-table-action';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\n@Injectable()\nexport class OpTableActionsService {\n\n constructor(private readonly injector:Injector) {\n }\n\n /**\n * Actions currently registered\n */\n private actions:OpTableActionFactory[] = [\n (injector, workPackage) => new OpDetailsTableAction(injector, workPackage),\n (injector, workPackage) => new OpContextMenuTableAction(injector, workPackage),\n ];\n\n /**\n * Replace the actions with a different set\n */\n public setActions(...actions:OpTableActionFactory[]) {\n this.actions = actions;\n }\n\n /**\n * Render actions for the given work package.\n * @param {WorkPackageResource} workPackage\n */\n public render(workPackage:WorkPackageResource):HTMLElement[] {\n let built = this.actions.map((factory) => factory(this.injector, workPackage).buildElement());\n return _.compact(built);\n }\n}\n","\n// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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) {\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 private goToOtherState(route:string, params:{}):Promise {\n return this.$state.go(route, params);\n }\n\n private goBackToDetailsState(preferListOverSplit:boolean, baseRoute:string):void {\n if (preferListOverSplit) {\n this.goToOtherState(baseRoute, this.backRoute.params);\n } else {\n this.goToOtherState(baseRoute + this.keepTab.currentDetailsSubState, this.backRoute.params);\n }\n }\n\n private goBackNotToDetailsState():void {\n if (this.backRoute.parent) {\n this.goToOtherState(this.backRoute.name, this.backRoute.params).then(() => { this.$state.reload(); });\n }\n else {\n this.goToOtherState(this.backRoute.name, this.backRoute.params);\n }\n }\n\n private goBackToPreviousState(preferListOverSplit:boolean, baseRoute:string):void {\n if (this.keepTab.isDetailsState(this.backRoute.parent)) {\n this.goBackToDetailsState(preferListOverSplit, baseRoute);\n } else {\n this.goBackNotToDetailsState();\n }\n }\n\n public goBack(preferListOverSplit:boolean = false) {\n // Default: back to list\n // When coming from a deep link or a create form\n const baseRoute = this.backRoute?.baseRoute || this.$state.current.data.baseRoute || 'work-packages.partitioned.list';\n // if we are in the first state\n if (!this.backRoute && baseRoute.includes('show')) { this.$state.reload(); }\n else {\n if (!this.backRoute || this.backRoute.name.includes('new')) {\n this.$state.go(baseRoute, this.$state.params);\n } else {\n this.goBackToPreviousState(preferListOverSplit, baseRoute);\n }\n }\n }\n\n public goToBaseState() {\n const baseRoute = this.$state.current.data.baseRoute || 'work-packages.partitioned.list';\n this.$state.go(baseRoute, this.$state.params);\n }\n\n public sync(transition:Transition) {\n const fromState = transition.from();\n const toState = transition.to();\n\n // Set backRoute to know where we came from\n if (fromState.name &&\n fromState.data &&\n toState.data &&\n fromState.data.parent !== toState.data.parent) {\n const paramsFromCopy = { ...transition.params('from') };\n this.backRoute = { name: fromState.name,\n params: paramsFromCopy,\n parent: fromState.data.parent,\n baseRoute: fromState.data.baseRoute };\n }\n }\n\n public set backRoute(route:BackRouteOptions) {\n this._backRoute = route;\n }\n\n public get backRoute():BackRouteOptions {\n return this._backRoute;\n }\n}\n","import {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {Injector} from \"@angular/core\";\n\nexport class TableDragActionService {\n\n /**\n * Initialize an action service in the given isolated query space\n * @param querySpace The isolated query space for this table\n * @param injector The hierarchical injector for this table\n */\n constructor(readonly querySpace:IsolatedQuerySpace,\n readonly injector:Injector) {\n }\n\n /**\n * Determine whether the service applies for the given\n * query spaces.\n */\n public get applies():boolean {\n return true;\n }\n\n /**\n * Perform a post-order update\n */\n public onNewOrder(newOrder:string[]):void {\n }\n\n /**\n * Returns whether the given work package is movable\n */\n public canPickup(workPackage:WorkPackageResource):boolean {\n return true;\n }\n\n /**\n * Perform the respective action for the drop that just happened\n *\n * @param workPackage\n * @param target\n * @param source\n * @param sibling\n */\n public handleDrop(workPackage:WorkPackageResource, el:HTMLElement):Promise {\n return Promise.resolve(undefined);\n }\n\n /**\n * Manipulate the shadow element\n * @param shadowElement\n * @param backToDefault: Shall the modifications be made undone\n */\n public changeShadowElement(shadowElement:HTMLElement, backToDefault:boolean = false) {\n if (backToDefault) {\n shadowElement.classList.remove('-dragged');\n } else {\n shadowElement.classList.add('-dragged');\n }\n return true;\n }\n}\n","import {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {WorkPackageRelationsHierarchyService} from \"core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service\";\nimport {\n hierarchyGroupClass,\n hierarchyRootClass\n} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\nimport {relationRowClass, isInsideCollapsedGroup} from \"core-components/wp-fast-table/helpers/wp-table-row-helpers\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport class HierarchyDragActionService extends TableDragActionService {\n\n @InjectField() private wpTableHierarchies:WorkPackageViewHierarchiesService;\n @InjectField() private relationHierarchyService:WorkPackageRelationsHierarchyService;\n @InjectField() private apiV3Service:APIV3Service;\n\n public get applies() {\n return this.wpTableHierarchies.isEnabled;\n }\n\n /**\n * Returns whether the given work package is movable\n */\n public canPickup(workPackage:WorkPackageResource):boolean {\n return !!workPackage.changeParent;\n }\n\n public handleDrop(workPackage:WorkPackageResource, el:HTMLElement):Promise {\n return this.determineParent(el).then((parentId:string|null) => {\n return this.relationHierarchyService.changeParent(workPackage, parentId);\n });\n }\n\n /**\n * Find an applicable parent element from the hierarchy information in the table.\n * @param el\n */\n private determineParent(el:Element):Promise {\n let previous = el.previousElementSibling;\n let next = el.nextElementSibling;\n let parent = null;\n\n if (previous !== null && this.droppedIntoGroup(el, previous, next)) {\n // If the previous element is a relation row,\n // skip it until we find the real previous sibling\n const isRelationRow = previous.className.indexOf(relationRowClass()) >= 0;\n\n if (isRelationRow) {\n let relationRoot = this.findRelationRowRoot(previous);\n if (relationRoot == null) {\n return Promise.resolve(null);\n }\n previous = relationRoot;\n }\n\n let previousWpId = (previous as HTMLElement).dataset.workPackageId!;\n\n if (this.isHiearchyRoot(previous, previousWpId)) {\n const droppedIntoCollapsedGroup = isInsideCollapsedGroup(next);\n\n if (droppedIntoCollapsedGroup) {\n return this.determineParent(previous);\n }\n // If the sibling is a hierarchy root, return that sibling as new parent.\n parent = previousWpId;\n } else {\n // If the sibling is no hierarchy root, return it's parent.\n // Thus, the dropped element will get the same hierarchy level as the sibling\n parent = this.loadParentOfWP(previousWpId);\n }\n }\n\n return Promise.resolve(parent);\n }\n\n private findRelationRowRoot(el:Element):Element|null {\n let previous = el.previousElementSibling;\n while (previous !== null) {\n if (previous.className.indexOf(relationRowClass()) < 0) {\n return previous;\n }\n previous = previous.previousElementSibling;\n }\n\n return null;\n }\n\n private droppedIntoGroup(element:Element, previous:Element, next:Element | null):boolean {\n const inGroup = previous.className.indexOf(hierarchyGroupClass('')) >= 0;\n const isRoot = previous.className.indexOf(hierarchyRootClass('')) >= 0;\n let skipDroppedIntoGroup;\n\n if (inGroup || isRoot) {\n const elementGroups = Array.from(element.classList).filter(listClass => listClass.includes('__hierarchy-group-')) || [];\n const previousGroups = Array.from(previous.classList).filter(listClass => listClass.includes('__hierarchy-group-')) || [];\n const nextGroups = next && Array.from(next.classList).filter(listClass => listClass.includes('__hierarchy-group-')) || [];\n const previousWpId = (previous as HTMLElement).dataset.workPackageId!;\n const isLastElementOfGroup = !nextGroups.some(nextGroup => previousGroups.includes(nextGroup)) && !nextGroups.includes(hierarchyGroupClass(previousWpId));\n const elementAlreadyBelongsToGroup = elementGroups.some(elementGroup => previousGroups.includes(elementGroup)) ||\n elementGroups.includes(hierarchyGroupClass(previousWpId));\n\n skipDroppedIntoGroup = isLastElementOfGroup && !elementAlreadyBelongsToGroup;\n }\n\n return !skipDroppedIntoGroup && inGroup || isRoot;\n }\n\n private isHiearchyRoot(previous:Element, previousWpId:string):boolean {\n return previous.classList.contains(hierarchyRootClass(previousWpId));\n }\n\n private loadParentOfWP(wpId:string):Promise {\n return this\n .apiV3Service\n .work_packages\n .id(wpId)\n .get()\n .toPromise()\n .then((wp:WorkPackageResource) => {\n return Promise.resolve(wp.parent?.id || null);\n });\n }\n}\n","import {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {WorkPackageViewGroupByService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-group-by.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {rowGroupClassName} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-classes.constants\";\nimport {locatePredecessorBySelector} from \"core-components/wp-fast-table/helpers/wp-table-row-helpers\";\nimport {groupIdentifier} from \"core-components/wp-fast-table/builders/modes/grouped/grouped-rows-helpers\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\n\nexport class GroupByDragActionService extends TableDragActionService {\n\n @InjectField() wpTableGroupBy:WorkPackageViewGroupByService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() halEvents:HalEventsService;\n @InjectField() halNotification:HalResourceNotificationService;\n @InjectField() schemaCache:SchemaCacheService;\n\n public get applies() {\n return this.wpTableGroupBy.isEnabled;\n }\n\n /**\n * Returns whether the given work package is movable\n */\n public canPickup(workPackage:WorkPackageResource):boolean {\n const attribute = this.groupedAttribute;\n return attribute !== null && this.schemaCache.of(workPackage).isAttributeEditable(attribute);\n }\n\n public handleDrop(workPackage:WorkPackageResource, el:HTMLElement):Promise {\n const changeset = this.halEditing.changeFor(workPackage);\n const groupedValue = this.getValueForGroup(el);\n\n changeset.projectedResource[this.groupedAttribute!] = groupedValue;\n return this.halEditing\n .save(changeset)\n .then((saved) => this.halEvents.push(saved.resource, {eventType: 'updated'}))\n .catch(e => this.halNotification.handleRawError(e, workPackage));\n }\n\n private getValueForGroup(el:HTMLElement):unknown|null {\n const groupHeader = locatePredecessorBySelector(el, `.${rowGroupClassName}`)!;\n const match = this.groups.find(group => groupIdentifier(group) === groupHeader.dataset.groupIdentifier);\n\n if (!match) {\n return null;\n }\n\n if (match._links && match._links.valueLink) {\n const links = match._links.valueLink;\n\n // Unwrap single links to properly use them\n return links.length === 1 ? links[0] : links;\n } else {\n return match.value;\n }\n }\n\n /**\n * Get the attribute we're grouping by\n */\n private get groupedAttribute():string|null {\n const current = this.wpTableGroupBy.current;\n return current ? current.id : null;\n }\n\n /**\n * Returns the reference to the last table.groups state value\n */\n public get groups() {\n return this.querySpace.groups.value || [];\n }\n}\n","import {Injectable, Injector} from \"@angular/core\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {TableDragActionService} from \"core-components/wp-table/drag-and-drop/actions/table-drag-action.service\";\nimport {HierarchyDragActionService} from \"core-components/wp-table/drag-and-drop/actions/hierarchy-drag-action.service\";\nimport {GroupByDragActionService} from \"core-components/wp-table/drag-and-drop/actions/group-by-drag-action.service\";\n\ninterface ITableDragActionService {\n new(querySpace:IsolatedQuerySpace, injector:Injector):TableDragActionService;\n}\n\n@Injectable()\nexport class TableDragActionsRegistryService {\n\n private register:ITableDragActionService[] = [\n HierarchyDragActionService,\n GroupByDragActionService,\n ];\n\n public add(service:ITableDragActionService) {\n this.register.push(service);\n }\n\n public get(injector:Injector):TableDragActionService {\n const querySpace = injector.get(IsolatedQuerySpace);\n\n const match = this.register\n .map(cls => new cls(querySpace, injector))\n .find(instance => instance.applies);\n\n return match || new TableDragActionService(querySpace, injector);\n }\n}\n","export namespace ImageHelpers {\n\n /**\n * Returns an absolute asset path from the assets/images/ folder\n *\n * e.g., to access:\n * frontend/src/assets/images/board_creation_modal/assignees.svg\n *\n * use\n * imagePath('board_creation_modal/assignees.svg')\n *\n *\n * @param image Path to the image starting from frontend/src/assets/images\n */\n export function imagePath(image:string) {\n return __webpack_public_path__ + 'assets/images/' + image;\n }\n}\n","import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {\n displayClassName,\n DisplayFieldRenderer,\n editFieldContainerClass\n} from \"core-app/modules/fields/display/display-field-renderer\";\nimport {Injector} from '@angular/core';\nimport {QueryColumn} from \"core-components/wp-query/query-column\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nexport const tdClassName = 'wp-table--cell-td';\nexport const editCellContainer = 'wp-table--cell-container';\n\nexport class CellBuilder {\n\n @InjectField(SchemaCacheService) schemaCache:SchemaCacheService;\n\n public fieldRenderer = new DisplayFieldRenderer(this.injector, 'table');\n\n constructor(public injector:Injector) {\n }\n\n public build(workPackage:WorkPackageResource, column:QueryColumn) {\n const td = document.createElement('td');\n const attribute = column.id;\n td.classList.add(tdClassName, attribute);\n\n if (attribute === 'subject') {\n td.classList.add('-max');\n }\n\n const schema = this.schemaCache.of(workPackage).ofProperty(attribute);\n if (schema && schema.type === 'User') {\n td.classList.add('-contains-avatar');\n }\n\n const container = document.createElement('span');\n container.classList.add(editCellContainer, editFieldContainerClass, attribute);\n const displayElement = this.fieldRenderer.render(workPackage, attribute, null);\n\n container.appendChild(displayElement);\n td.appendChild(container);\n\n return td;\n }\n\n public refresh(container:HTMLElement, workPackage:WorkPackageResource, attribute:string) {\n const displayElement = this.fieldRenderer.render(workPackage, attribute, null);\n\n container.innerHTML = '';\n container.appendChild(displayElement);\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class WorkPackageNotificationService extends HalResourceNotificationService {\n\n constructor(readonly injector:Injector,\n readonly apiV3Service:APIV3Service) {\n super(injector);\n }\n\n public showSave(resource:WorkPackageResource, isCreate:boolean = false) {\n let message:any = {\n message: this.I18n.t('js.notice_successful_' + (isCreate ? 'create' : 'update')),\n };\n\n this.addWorkPackageFullscreenLink(message, resource as any);\n\n this.NotificationsService.addSuccess(message);\n }\n\n protected showCustomError(errorResource:any, resource:WorkPackageResource):boolean {\n if (errorResource.errorIdentifier === 'urn:openproject-org:api:v3:errors:UpdateConflict') {\n this.NotificationsService.addError({\n message: errorResource.message,\n type: 'error',\n link: {\n text: this.I18n.t('js.hal.error.update_conflict_refresh'),\n target: () => this.apiV3Service.work_packages.id(resource).refresh()\n }\n });\n\n return true;\n }\n\n return super.showCustomError(errorResource, resource);\n }\n\n private addWorkPackageFullscreenLink(message:INotification, resource:WorkPackageResource) {\n // Don't show the 'Show in full screen' link if we're there already\n if (!this.$state.includes('work-packages.show')) {\n message.link = {\n target: () => this.$state.go('work-packages.show.activity', {workPackageId: resource.id}),\n text: this.I18n.t('js.work_packages.message_successful_show_in_fullscreen')\n };\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './relations-tab.html',\n selector: 'wp-relations-tab',\n})\nexport class WorkPackageRelationsTabComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackageId?:string;\n public workPackage:WorkPackageResource;\n\n public constructor(readonly I18n:I18nService,\n readonly $transition:Transition,\n readonly apiV3Service:APIV3Service) {\n super();\n }\n\n ngOnInit() {\n const wpId = this.workPackageId || this.$transition.params('to').workPackageId;\n this\n .apiV3Service\n .work_packages\n .id(wpId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp) => {\n this.workPackageId = wp.id!;\n this.workPackage = wp;\n });\n }\n\n}\n","
    \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\nimport * as sfimport from \"screenfull\";\nimport {Screenfull} from \"screenfull\";\n\nconst screenfull:Screenfull = sfimport as any;\nexport const zenModeComponentSelector = 'zen-mode-toggle-button';\n\n@Component({\n templateUrl: '../wp-button.template.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: zenModeComponentSelector,\n})\nexport class ZenModeButtonComponent extends AbstractWorkPackageButtonComponent {\n public buttonId:string = 'work-packages-zen-mode-toggle-button';\n public buttonClass:string = 'toolbar-icon';\n public iconClass:string = 'icon-zen-mode';\n\n static inZenMode:boolean = false;\n\n private activateLabel:string;\n private deactivateLabel:string;\n\n constructor(readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef) {\n super(I18n);\n\n this.activateLabel = I18n.t('js.zen_mode.button_activate');\n this.deactivateLabel = I18n.t('js.zen_mode.button_deactivate');\n let self = this;\n\n\n if (screenfull.enabled) {\n screenfull.onchange(function() {\n // This event might get triggered several times for once leaving\n // fullscreen mode.\n if (!screenfull.isFullscreen) {\n self.deactivateZenMode();\n }\n });\n }\n }\n\n public get label():string {\n if (this.isActive) {\n return this.deactivateLabel;\n } else {\n return this.activateLabel;\n }\n }\n\n public isToggle():boolean {\n return true;\n }\n\n private deactivateZenMode():void {\n this.isActive = ZenModeButtonComponent.inZenMode = false;\n jQuery('body').removeClass('zen-mode');\n this.disabled = false;\n if (screenfull.enabled && screenfull.isFullscreen) {\n screenfull.exit();\n }\n this.cdRef.detectChanges();\n }\n\n private activateZenMode() {\n this.isActive = ZenModeButtonComponent.inZenMode = true;\n jQuery('body').addClass('zen-mode');\n if (screenfull.enabled) {\n screenfull.request();\n }\n this.cdRef.detectChanges();\n }\n\n public performAction(evt:Event):false {\n if (ZenModeButtonComponent.inZenMode) {\n this.deactivateZenMode();\n } else {\n this.activateZenMode();\n }\n\n evt.preventDefault();\n return false;\n }\n}\n","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 {OpTitleService} from 'core-components/html/op-title.service';\nimport {AuthorisationService} from \"core-app/modules/common/model-auth/model-auth.service\";\nimport {States} from \"core-components/states.service\";\nimport {KeepTabService} from \"core-components/wp-single-view-tabs/keep-tab/keep-tab.service\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {catchError, subscribeOn} from \"rxjs/operators\";\n\nexport class WorkPackageSingleViewBase extends UntilDestroyedMixin {\n\n @InjectField() states:States;\n @InjectField() I18n:I18nService;\n @InjectField() keepTab:KeepTabService;\n @InjectField() PathHelper:PathHelperService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() wpTableFocus:WorkPackageViewFocusService;\n @InjectField() notificationService:WorkPackageNotificationService;\n @InjectField() authorisationService:AuthorisationService;\n @InjectField() cdRef:ChangeDetectorRef;\n @InjectField() readonly titleService:OpTitleService;\n @InjectField() readonly apiV3Service:APIV3Service;\n\n // Static texts\n public text:any = {};\n\n // Work package resource to be loaded from the cache\n public workPackage:WorkPackageResource;\n public projectIdentifier:string;\n\n public focusAnchorLabel:string;\n public showStaticPagePath:string;\n\n constructor(public injector:Injector, protected workPackageId:string) {\n super();\n this.initializeTexts();\n }\n\n /**\n * Observe changes of work package and re-run initialization.\n * Needs to be run explicitly by descendants.\n */\n protected observeWorkPackage() {\n /** Require the work package once to ensure we're displaying errors */\n this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.init();\n this.cdRef.detectChanges();\n },\n (error) => this.notificationService.handleRawError(error)\n );\n }\n\n /**\n * Provide static translations\n */\n protected initializeTexts() {\n this.text.tabs = {};\n ['overview', 'activity', 'relations', 'watchers'].forEach(tab => {\n this.text.tabs[tab] = this.I18n.t('js.work_packages.tabs.' + tab);\n });\n }\n\n /**\n * Initialize controller after workPackage resource has been loaded.\n */\n protected init() {\n // Set elements\n this\n .apiV3Service\n .projects\n .id(this.workPackage.project)\n .requireAndStream()\n .subscribe(() => {\n this.projectIdentifier = this.workPackage.project.identifier;\n this.cdRef.detectChanges();\n });\n\n // Set authorisation data\n this.authorisationService.initModelAuth('work_package', this.workPackage.$links);\n\n // Push the current title\n this.titleService.setFirstPart(this.workPackage.subjectWithType(20));\n\n // Preselect this work package for future list operations\n this.showStaticPagePath = this.PathHelper.workPackagePath(this.workPackageId);\n\n // Listen to tab changes to update the tab label\n this.keepTab.observable\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((tabs:any) => {\n this.updateFocusAnchorLabel(tabs.active);\n });\n }\n\n /**\n * Recompute the current tab focus label\n */\n public updateFocusAnchorLabel(tabName:string):string {\n const tabLabel = this.I18n.t('js.label_work_package_details_you_are_here', {\n tab: this.I18n.t('js.work_packages.tabs.' + tabName),\n type: this.workPackage.type.name,\n subject: this.workPackage.subject\n });\n\n return this.focusAnchorLabel = tabLabel;\n }\n\n public canViewWorkPackageWatchers() {\n return !!(this.workPackage && this.workPackage.watchers);\n }\n}\n","import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {WorkPackageRelationsService} from '../wp-relations.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {ChangeDetectorRef, Component, ElementRef, Input, OnInit, ViewChild} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Component({\n selector: 'wp-relation-row',\n templateUrl: './wp-relation-row.template.html'\n})\nexport class WorkPackageRelationRowComponent extends UntilDestroyedMixin implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public relatedWorkPackage:WorkPackageResource;\n @Input() public groupByWorkPackageType:boolean;\n\n @ViewChild('relationDescriptionTextarea') readonly relationDescriptionTextarea:ElementRef;\n\n public relationType:string;\n public showRelationInfo:boolean = false;\n public showEditForm:boolean = false;\n public availableRelationTypes:{ label:string, name:string }[];\n public selectedRelationType:{ name:string };\n\n public userInputs = {\n newRelationText: '',\n showDescriptionEditForm: false,\n showRelationTypesForm: false,\n showRelationInfo: false,\n };\n\n // Create a quasi-field object\n public fieldController = {\n handler: {\n active: true,\n },\n required: false\n };\n\n public relation:RelationResource;\n public text = {\n cancel: this.I18n.t('js.button_cancel'),\n save: this.I18n.t('js.button_save'),\n removeButton: this.I18n.t('js.relation_buttons.remove'),\n description_label: this.I18n.t('js.relation_buttons.update_description'),\n toggleDescription: this.I18n.t('js.relation_buttons.toggle_description'),\n updateRelation: this.I18n.t('js.relation_buttons.update_relation'),\n placeholder: {\n description: this.I18n.t('js.placeholders.relation_description')\n }\n };\n\n constructor(protected apiV3Service:APIV3Service,\n protected notificationService:WorkPackageNotificationService,\n protected wpRelations:WorkPackageRelationsService,\n protected halEvents:HalEventsService,\n protected I18n:I18nService,\n protected cdRef:ChangeDetectorRef,\n protected PathHelper:PathHelperService) {\n super();\n }\n\n ngOnInit() {\n this.relation = this.relatedWorkPackage.relatedBy as RelationResource;\n\n this.userInputs.newRelationText = this.relation.description || '';\n this.availableRelationTypes = RelationResource.LOCALIZED_RELATION_TYPES(false);\n this.selectedRelationType = _.find(this.availableRelationTypes,\n { 'name': this.relation.normalizedType(this.workPackage) })!;\n\n this\n .apiV3Service\n .work_packages\n .id(this.relatedWorkPackage)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n ).subscribe((wp) => {\n this.relatedWorkPackage = wp;\n });\n }\n\n /**\n * Return the normalized relation type for the work package we're viewing.\n * That is, normalize `precedes` where the work package is the `to` link.\n */\n public get normalizedRelationType() {\n var type = this.relation.normalizedType(this.workPackage);\n return this.I18n.t('js.relation_labels.' + type);\n }\n\n public get relationReady() {\n return this.relatedWorkPackage && this.relatedWorkPackage.$loaded;\n }\n\n public startDescriptionEdit() {\n this.userInputs.showDescriptionEditForm = true;\n setTimeout(() => {\n const textarea = jQuery(this.relationDescriptionTextarea.nativeElement);\n const textlen = (textarea.val() as string).length;\n // Focus and set cursor to end\n textarea.focus();\n\n textarea.prop('selectionStart', textlen);\n textarea.prop('selectionEnd', textlen);\n });\n }\n\n public handleDescriptionKey($event:JQuery.TriggeredEvent) {\n if ($event.which === 27) {\n this.cancelDescriptionEdit();\n }\n }\n\n public cancelDescriptionEdit() {\n this.userInputs.showDescriptionEditForm = false;\n this.userInputs.newRelationText = this.relation.description || '';\n }\n\n public saveDescription() {\n this.wpRelations.updateRelation(\n this.relation,\n { description: this.userInputs.newRelationText })\n .then((savedRelation:RelationResource) => {\n this.relation = savedRelation;\n this.relatedWorkPackage.relatedBy = savedRelation;\n this.userInputs.showDescriptionEditForm = false;\n this.notificationService.showSave(this.relatedWorkPackage);\n this.cdRef.detectChanges();\n });\n }\n\n public get showDescriptionInfo() {\n return this.userInputs.showRelationInfo || this.relation.description;\n }\n\n public activateRelationTypeEdit() {\n if (this.groupByWorkPackageType) {\n this.userInputs.showRelationTypesForm = true;\n }\n }\n\n public cancelRelationTypeEditOnEscape(evt:JQuery.TriggeredEvent) {\n this.userInputs.showRelationTypesForm = false;\n }\n\n public saveRelationType() {\n this.wpRelations.updateRelationType(\n this.workPackage,\n this.relatedWorkPackage,\n this.relation,\n this.selectedRelationType.name)\n .then((savedRelation:RelationResource) => {\n this.notificationService.showSave(this.relatedWorkPackage);\n this.relatedWorkPackage.relatedBy = savedRelation;\n this.relation = savedRelation;\n\n this.userInputs.showRelationTypesForm = false;\n this.cdRef.detectChanges();\n })\n .catch((error:any) => this.notificationService.handleRawError(error, this.workPackage));\n }\n\n public toggleUserDescriptionForm() {\n this.userInputs.showDescriptionEditForm = !this.userInputs.showDescriptionEditForm;\n }\n\n public removeRelation() {\n this.wpRelations.removeRelation(this.relation)\n .then(() => {\n this.halEvents.push(this.workPackage, {\n eventType: 'association',\n relatedWorkPackage: null,\n relationType: this.relation.normalizedType(this.workPackage)\n });\n\n this\n .apiV3Service\n .work_packages\n .cache\n .updateWorkPackage(this.relatedWorkPackage);\n\n this.notificationService.showSave(this.relatedWorkPackage);\n })\n .catch((err:any) => this.notificationService.handleRawError(err,\n this.relatedWorkPackage));\n }\n}\n","
    \n
    \n\n
    \n \n\n\n \n \n \n \n
    \n \n
    \n
    \n\n
    \n \n \n
    \n\n
    \n \n \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 {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {Board} from \"core-app/modules/boards/board/board\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {ApiV3Filter} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class BoardListsService {\n\n private v3 = this.pathHelper.api.v3;\n\n constructor(private readonly CurrentProject:CurrentProjectService,\n private readonly pathHelper:PathHelperService,\n private readonly apiV3Service:APIV3Service,\n private readonly halResourceService:HalResourceService,\n private readonly notifications:NotificationsService,\n private readonly I18n:I18nService) {\n\n }\n\n private create(params:Object, filters:ApiV3Filter[]):Promise {\n let filterJson = JSON.stringify(filters);\n\n return this\n .apiV3Service\n .queries\n .form\n .loadWithParams(\n {\n pageSize: 0,\n filters: filterJson\n },\n undefined,\n this.CurrentProject.identifier,\n this.buildQueryRequest(params),\n )\n .toPromise()\n .then(([form, query]) => {\n // When the permission to create public queries is missing, throw an error.\n // Otherwise private queries would be created.\n if (form.schema['public'].writable) {\n return this\n .apiV3Service\n .queries\n .post(query, form)\n .toPromise();\n } else {\n throw new Error(this.I18n.t('js.boards.error_permission_missing'));\n }\n });\n }\n\n /**\n * Add a free query to the board\n */\n public addFreeQuery(board:Board, queryParams:Object) {\n const filter = this.freeBoardQueryFilter();\n return this.addQuery(board, queryParams, [filter]);\n }\n\n /**\n * Add an empty query to the board\n * @param board\n * @param query\n */\n public async addQuery(board:Board, queryParams:Object, filters:ApiV3Filter[]):Promise {\n const count = board.queries.length;\n try {\n const query = await this.create(queryParams, filters);\n\n let source = {\n _type: 'GridWidget',\n identifier: 'work_package_query',\n startRow: 1,\n endRow: 2,\n startColumn: count + 1,\n endColumn: count + 2,\n options: {\n queryId: query.id,\n filters: filters,\n }\n };\n\n let resource = this.halResourceService.createHalResourceOfClass(GridWidgetResource, source);\n board.addQuery(resource);\n } catch (e) {\n this.notifications.addError(e);\n console.error(e);\n }\n return board;\n }\n\n private buildQueryRequest(params:Object) {\n return {\n hidden: true,\n public: true,\n \"_links\": {\n \"sortBy\": [\n { \"href\": this.v3.apiV3Base + \"/queries/sort_bys/manualSorting-asc\" },\n { \"href\": this.v3.apiV3Base + \"/queries/sort_bys/id-asc\" },\n ]\n },\n ...params\n };\n }\n\n private freeBoardQueryFilter():ApiV3Filter {\n return { manualSort: { operator: 'ow', values: [] } };\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free 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\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable({ providedIn: 'root' })\nexport class CurrentProjectService {\n private current:{ id:string, identifier:string, name:string };\n\n constructor(private PathHelper:PathHelperService,\n private apiV3Service:APIV3Service) {\n this.detect();\n }\n\n public get inProjectContext():boolean {\n return this.current !== undefined;\n }\n\n public get path():string|null {\n if (this.current) {\n return this.PathHelper.projectPath(this.current.identifier);\n }\n\n return null;\n }\n\n public get apiv3Path():string|null {\n if (this.current) {\n return this.apiV3Service.projects.id(this.current.id).toString();\n }\n\n return null;\n }\n\n public get id():string|null {\n return this.getCurrent('id');\n }\n\n public get name():string|null {\n return this.getCurrent('name');\n }\n\n public get identifier():string|null {\n return this.getCurrent('identifier');\n }\n\n private getCurrent(key:'id'|'identifier'|'name') {\n if (this.current && this.current[key]) {\n return this.current[key].toString();\n }\n\n return null;\n }\n\n /**\n * Detect the current project from its meta tag.\n */\n public detect() {\n const element:HTMLMetaElement|null = document.querySelector('meta[name=current_project]');\n if (element) {\n this.current = {\n id: element.dataset.projectId!,\n name: element.dataset.projectName!,\n identifier: element.dataset.projectIdentifier!\n };\n }\n }\n}\n","import {\n contextColumnIcon,\n OpTableAction,\n OpTableActionFactory,\n} from 'core-components/wp-table/table-actions/table-action';\nimport {opIconElement} from 'core-app/helpers/op-icon-builder';\nimport {Injector} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\n\nexport class OpUnlinkTableAction extends OpTableAction {\n\n constructor(public injector:Injector,\n public workPackage:WorkPackageResource,\n public readonly identifier:string,\n private title:string,\n readonly applicable:(workPackage:WorkPackageResource) => boolean,\n readonly onClick:(workPackage:WorkPackageResource) => void) {\n super(injector, workPackage);\n\n }\n\n /**\n * Returns a factory for this action with the given title and identifier for reusing\n * remove actions.\n *\n * @param {string} identifier\n * @param {string} title\n */\n public static factoryFor(identifier:string,\n title:string,\n onClick:(workPackage:WorkPackageResource) => void,\n applicable:(workPackage:WorkPackageResource) => boolean = () => true):OpTableActionFactory {\n return (injector:Injector, workPackage:WorkPackageResource) => {\n return new OpUnlinkTableAction(injector,\n workPackage,\n identifier,\n title,\n applicable,\n onClick) as OpTableAction;\n };\n }\n\n public buildElement() {\n if (!this.applicable(this.workPackage)) {\n return null;\n }\n\n let element = document.createElement('a');\n element.title = this.title;\n element.href = '#';\n element.classList.add(contextColumnIcon, 'wp-table-action--unlink');\n element.dataset.workPackageId = this.workPackage.id!;\n element.appendChild(opIconElement('icon', 'icon-close'));\n jQuery(element).click((event) => {\n event.preventDefault();\n this.onClick(this.workPackage);\n });\n\n return element;\n }\n}\n","import {\n ApplicationRef,\n ChangeDetectorRef,\n Component,\n ComponentFactoryResolver,\n ElementRef,\n EventEmitter,\n Inject,\n InjectionToken,\n Injector,\n OnDestroy,\n OnInit,\n Optional,\n ViewChild\n} from '@angular/core';\nimport {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';\nimport {ConfigurationService} from 'core-app/modules/common/config/configuration.service';\nimport {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service';\nimport {OpModalComponent} from 'core-components/op-modals/op-modal.component';\nimport {WpTableConfigurationService} from 'core-components/wp-table/configuration-modal/wp-table-configuration.service';\nimport {\n ActiveTabInterface,\n TabComponent,\n TabInterface,\n TabPortalOutlet\n} from 'core-components/wp-table/configuration-modal/tab-portal-outlet';\nimport {WorkPackageStatesInitializationService} from 'core-components/wp-list/wp-states-initialization.service';\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {QueryFormResource} from 'core-app/modules/hal/resources/query-form-resource';\nimport {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {ComponentType} from \"@angular/cdk/portal\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const WpTableConfigurationModalPrependToken = new InjectionToken>('WpTableConfigurationModalPrependComponent');\n\n@Component({\n templateUrl: './wp-table-configuration.modal.html'\n})\nexport class WpTableConfigurationModalComponent extends OpModalComponent implements OnInit, OnDestroy {\n\n /* Close on escape? */\n public closeOnEscape = false;\n\n /* Close on outside click */\n public closeOnOutsideClick = false;\n\n public $element:JQuery;\n\n public text = {\n title: this.I18n.t('js.work_packages.table_configuration.modal_title'),\n closePopup: this.I18n.t('js.close_popup_title'),\n\n columnsLabel: this.I18n.t('js.label_columns'),\n selectedColumns: this.I18n.t('js.description_selected_columns'),\n multiSelectLabel: this.I18n.t('js.work_packages.label_column_multiselect'),\n applyButton: this.I18n.t('js.modals.button_apply'),\n cancelButton: this.I18n.t('js.modals.button_cancel'),\n\n upsaleRelationColumns: this.I18n.t('js.modals.upsale_relation_columns'),\n upsaleRelationColumnsLink: this.I18n.t('js.modals.upsale_relation_columns_link')\n };\n\n public onDataUpdated = new EventEmitter();\n public selectedColumnMap:{ [id:string]:boolean } = {};\n\n // Get the view child we'll use as the portal host\n @ViewChild('tabContentOutlet', { static: true }) tabContentOutlet:ElementRef;\n // And a reference to the actual portal host interface\n public tabPortalHost:TabPortalOutlet;\n\n // Try to load an optional provided configuration service, and fall back to the default one\n private wpTableConfigurationService:WpTableConfigurationService =\n this.injector.get(WpTableConfigurationService, new WpTableConfigurationService(this.I18n));\n\n constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n @Optional() @Inject(WpTableConfigurationModalPrependToken) public prependModalComponent:ComponentType|null,\n readonly I18n:I18nService,\n readonly injector:Injector,\n readonly appRef:ApplicationRef,\n readonly componentFactoryResolver:ComponentFactoryResolver,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly querySpace:IsolatedQuerySpace,\n readonly wpStatesInitialization:WorkPackageStatesInitializationService,\n readonly apiV3Service:APIV3Service,\n readonly notificationService:WorkPackageNotificationService,\n readonly wpTableColumns:WorkPackageViewColumnsService,\n readonly cdRef:ChangeDetectorRef,\n readonly ConfigurationService:ConfigurationService,\n readonly elementRef:ElementRef) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.tabPortalHost = new TabPortalOutlet(\n this.wpTableConfigurationService.tabs,\n this.tabContentOutlet.nativeElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n\n this.loadingIndicator.indicator('modal').promise = this.loadForm()\n .then(() => {\n const initialTab = this.locals['initialTab'] || this.availableTabs[0].name;\n this.switchTo(initialTab);\n });\n }\n\n ngOnDestroy() {\n this.onDataUpdated.complete();\n this.tabPortalHost.dispose();\n }\n\n public get availableTabs():TabInterface[] {\n return this.tabPortalHost.availableTabs;\n }\n\n public get currentTab():ActiveTabInterface|null {\n return this.tabPortalHost.currentTab;\n }\n\n public switchTo(name:string) {\n this.tabPortalHost.switchTo(name);\n }\n\n public saveChanges():void {\n this.tabPortalHost.activeComponents.forEach((component:TabComponent) => {\n component.onSave();\n });\n\n this.onDataUpdated.emit();\n this.service.close();\n }\n\n /**\n * Called when the user attempts to close the modal window.\n * The service will close this modal if this method returns true\n * @returns {boolean}\n */\n public onClose():boolean {\n this.afterFocusOn.focus();\n return true;\n }\n\n protected get afterFocusOn():JQuery {\n return this.$element;\n }\n\n protected loadForm() {\n const query = this.querySpace.query.value!;\n return this\n .apiV3Service\n .queries\n .form\n .load(query)\n .toPromise()\n .then(([form, _]) => {\n this.wpStatesInitialization.updateStatesFromForm(query, form);\n\n return form;\n })\n .catch((error) => this.notificationService.handleRawError(error));\n }\n}\n","
    \n
    \n
    \n

    \n\n \n \n
    \n \n
    \n\n \n \n \n\n
    \n \n
    \n\n
    \n
    \n \n \n
    \n
    \n
    \n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {Component, Input, OnInit} from '@angular/core';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper';\nimport {WorkPackageRelationsHierarchyService} from 'core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service';\nimport {OpUnlinkTableAction} from 'core-components/wp-table/table-actions/actions/unlink-table-action';\nimport {OpTableActionFactory} from 'core-components/wp-table/table-actions/table-action';\nimport {WorkPackageInlineCreateService} from \"core-components/wp-inline-create/wp-inline-create.service\";\nimport {WorkPackageRelationQueryBase} from \"core-components/wp-relations/embedded/wp-relation-query.base\";\nimport {WpChildrenInlineCreateService} from \"core-components/wp-relations/embedded/children/wp-children-inline-create.service\";\nimport {filter} from \"rxjs/operators\";\nimport {QueryResource} from \"core-app/modules/hal/resources/query-resource\";\nimport {GroupDescriptor} from \"core-components/work-packages/wp-single-view/wp-single-view.component\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'wp-children-query',\n templateUrl: '../wp-relation-query.html',\n providers: [\n { provide: WorkPackageInlineCreateService, useClass: WpChildrenInlineCreateService },\n ]\n})\nexport class WorkPackageChildrenQueryComponent extends WorkPackageRelationQueryBase implements OnInit {\n @Input() public workPackage:WorkPackageResource;\n @Input() public query:QueryResource;\n\n /** An optional group descriptor if we're rendering on the single view */\n @Input() public group?:GroupDescriptor;\n @Input() public addExistingChildEnabled:boolean = false;\n\n public tableActions:OpTableActionFactory[] = [\n OpUnlinkTableAction.factoryFor(\n 'remove-child-action',\n this.I18n.t('js.relation_buttons.remove_child'),\n (child:WorkPackageResource) => {\n this.embeddedTable.loadingIndicator = this.wpRelationsHierarchyService.removeChild(child);\n },\n (child:WorkPackageResource) => !!child.changeParent\n )\n ];\n\n constructor(protected wpRelationsHierarchyService:WorkPackageRelationsHierarchyService,\n protected PathHelper:PathHelperService,\n protected wpInlineCreate:WorkPackageInlineCreateService,\n protected halEvents:HalEventsService,\n protected apiV3Service:APIV3Service,\n protected queryUrlParamsHelper:UrlParamsHelperService,\n readonly I18n:I18nService) {\n super(queryUrlParamsHelper);\n }\n\n ngOnInit() {\n // Set reference target and reference class\n this.wpInlineCreate.referenceTarget = this.workPackage;\n\n // Set up the query props\n this.queryProps = this.buildQueryProps();\n\n // Fire event that children were added\n this.wpInlineCreate.newInlineWorkPackageCreated\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((toId:string) => {\n this.halEvents.push(this.workPackage, {\n eventType: 'association',\n relatedWorkPackage: toId,\n relationType: 'child'\n });\n });\n\n // Refresh table when work package is refreshed\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .observe()\n .pipe(\n filter(() => this.embeddedTable && this.embeddedTable.isInitialized),\n this.untilDestroyed()\n )\n .subscribe(() => this.refreshTable());\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {StateService} from '@uirouter/core';\nimport {OPContextMenuService} from \"core-components/op-context-menu/op-context-menu.service\";\nimport {Directive, ElementRef, Input} from \"@angular/core\";\nimport {OpContextMenuTrigger} from \"core-components/op-context-menu/handlers/op-context-menu-trigger.directive\";\n\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {HalResource} from 'core-app/modules/hal/resources/hal-resource';\nimport {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {HalEventsService} from \"core-app/modules/hal/services/hal-events.service\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\n\n@Directive({\n selector: '[wpStatusDropdown]'\n})\nexport class WorkPackageStatusDropdownDirective extends OpContextMenuTrigger {\n @Input('wpStatusDropdown-workPackage') public workPackage:WorkPackageResource;\n\n constructor(readonly elementRef:ElementRef,\n readonly opContextMenu:OPContextMenuService,\n readonly $state:StateService,\n protected workPackageNotificationService:WorkPackageNotificationService,\n protected halEditing:HalResourceEditingService,\n protected notificationService:NotificationsService,\n protected I18n:I18nService,\n protected halEvents:HalEventsService) {\n\n super(elementRef, opContextMenu);\n }\n\n protected open(evt:JQuery.TriggeredEvent) {\n const change = this.halEditing.changeFor(this.workPackage);\n\n change.getForm().then((form:any) => {\n const statuses = form.schema.status.allowedValues;\n this.buildItems(statuses);\n\n const writable = change.schema.status.writable;\n if (!writable) {\n this.notificationService.addError(this.I18n.t('js.work_packages.message_work_package_status_blocked'));\n } else {\n this.opContextMenu.show(this, evt);\n }\n });\n }\n\n public get locals() {\n return {\n items: this.items,\n contextMenuId: 'wp-status-context-menu'\n };\n }\n\n private updateStatus(status:HalResource) {\n const change = this.halEditing.changeFor(this.workPackage);\n change.projectedResource.status = status;\n\n if (!this.workPackage.isNew) {\n this.halEditing\n .save(change)\n .then(() => {\n this.workPackageNotificationService.showSave(this.workPackage);\n });\n }\n }\n\n private buildItems(statuses:CollectionResource) {\n this.items = statuses.map((status:HalResource) => {\n return {\n disabled: false,\n linkText: status.name,\n postIcon: status.isReadonly ? 'icon-locked' : null,\n postIconTitle: this.I18n.t('js.work_packages.message_work_package_read_only'),\n class: Highlighting.inlineClass('status', status.id!),\n onClick: () => {\n this.updateStatus(status);\n return true;\n }\n };\n });\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","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 scrollContainers = member.scrollContainers;\n\n if (this.autoscroll) {\n this.autoscroll.add(scrollContainers);\n } else {\n this.setupAutoscroll(scrollContainers);\n }\n\n const dragContainer = member.dragContainer;\n if (this.drake === null) {\n this.initializeDrake([dragContainer]);\n } else {\n this.drake.containers.push(dragContainer);\n }\n }\n\n public addScrollContainer(el:Element) {\n if (this.autoscroll) {\n this.autoscroll.add(el);\n } else {\n this.setupAutoscroll([el]);\n }\n this.autoscroll.setOuterScrollContainer(el);\n }\n\n protected setupAutoscroll(containers:Element[]) {\n // Setup autoscroll\n this.autoscroll = new DomAutoscrollService(\n containers,\n {\n margin: 100,\n maxSpeed: 10,\n scrollWhenOutside: true,\n autoScroll: () => this.drake && this.drake.dragging\n });\n }\n\n /**\n * Retrieve a member from the container, if one exists.\n * @param container\n */\n protected getMember(container:Element):DragMember|undefined {\n return this.members.find(member => member.dragContainer === container);\n }\n\n protected initializeDrake(containers:Element[]) {\n this.drake = dragula(containers, {\n moves: (el:any, container:any, handle:any, sibling:any) => {\n const member = this.getMember(container);\n return member ? member.moves(el, container, handle, sibling) : false;\n },\n accepts: (el:any, container:any) => {\n const member = this.getMember(container);\n return (member && member.accepts) ? member.accepts(el, container) : true;\n },\n invalid: () => false,\n direction: 'vertical', // Y axis is considered when determining where an element would be dropped\n copy: false, // elements are moved by default, not copied\n revertOnSpill: true, // spilling will put the element back where it was dragged from, if this is true\n removeOnSpill: false, // spilling will `.remove` the element, if this is true\n mirrorContainer: document.body, // set the element that gets mirror elements appended\n ignoreInputTextSelection: true // allows users to select input text, see details below\n });\n\n this.drake.on('drag', (el:HTMLElement, source:HTMLElement) => {\n el.dataset.sourceIndex = DragAndDropHelpers.findIndex(el).toString();\n });\n\n this.drake.on('over', (el:HTMLElement, container:HTMLElement) => {\n const zone = container.closest('.drop-zone');\n if (zone) {\n zone.classList.add('-dragged-over');\n }\n });\n\n this.drake.on('out', (el:HTMLElement, container:HTMLElement) => {\n const zone = container.closest('.drop-zone');\n if (zone) {\n zone.classList.remove('-dragged-over');\n }\n });\n\n this.drake.on('cloned', (clone:HTMLElement, original:HTMLElement) => {\n const member = this.member(original.parentElement!);\n if (member && member.onCloned) {\n member.onCloned(clone, original);\n }\n });\n\n this.drake.on('drop', async (el:HTMLElement, target:HTMLElement, source:HTMLElement, sibling:HTMLElement) => {\n try {\n await this.handleDrop(el, target, source, sibling);\n } catch (e) {\n console.error(\"Failed to handle drop of %O, %O\", el, e);\n }\n });\n\n this.drake.on('shadow', (shadowElement:HTMLElement, container:HTMLElement) => {\n const member = this.member(container);\n if (member && member.onShadowInserted) {\n member.onShadowInserted(shadowElement);\n }\n });\n\n this.drake.on('cancel', (el:HTMLElement, container:HTMLElement, source:HTMLElement) => {\n const member = this.member(container);\n if (member && member.onCancel) {\n member.onCancel(el);\n }\n });\n }\n\n private async handleDrop(el:HTMLElement, target:HTMLElement, source:HTMLElement, sibling:HTMLElement|null) {\n const to = this.member(target);\n const from = this.member(source);\n\n if (!(to && from)) {\n return;\n }\n\n if (to === from) {\n return to.onMoved(el, target, source, sibling);\n }\n\n const result = await to.onAdded(el, target, source, sibling);\n\n if (result) {\n from.onRemoved(el, target, source, sibling);\n } else {\n // Restore element in from container\n DragAndDropHelpers.reinsert(el, el.dataset.sourceIndex || -1, source);\n }\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {OpIcon} from 'core-app/modules/common/icon/op-icon';\nimport {NotificationComponent} from 'core-app/modules/common/notifications/notification.component';\nimport {NotificationsContainerComponent} from 'core-app/modules/common/notifications/notifications-container.component';\nimport {UploadProgressComponent} from 'core-app/modules/common/notifications/upload-progress.component';\nimport {OpDatePickerComponent} from \"core-app/modules/common/op-date-picker/op-date-picker.component\";\nimport {FocusWithinDirective} from \"core-app/modules/common/focus/focus-within.directive\";\nimport {OpenprojectAccessibilityModule} from \"core-app/modules/a11y/openproject-a11y.module\";\nimport {FocusDirective} from \"core-app/modules/common/focus/focus.directive\";\nimport {HighlightColDirective} from \"core-app/modules/common/highlight-col/highlight-col.directive\";\nimport {CopyToClipboardDirective} from \"core-app/modules/common/copy-to-clipboard/copy-to-clipboard.directive\";\nimport {highlightColBootstrap} from \"./highlight-col/highlight-col.directive\";\nimport {HookService} from \"../plugins/hook-service\";\nimport {ColorsAutocompleter} from \"core-app/modules/common/colors/colors-autocompleter.component\";\nimport {ResizerComponent} from \"core-app/modules/common/resizer/resizer.component\";\nimport {TablePaginationComponent} from 'core-components/table-pagination/table-pagination.component';\nimport {SortHeaderDirective} from 'core-components/wp-table/sort-header/sort-header.directive';\nimport {ZenModeButtonComponent} from 'core-components/wp-buttons/zen-mode-toggle-button/zen-mode-toggle-button.component';\nimport {OPContextMenuComponent} from 'core-components/op-context-menu/op-context-menu.component';\nimport {StateService, UIRouterModule} from \"@uirouter/angular\";\nimport {PortalModule} from \"@angular/cdk/portal\";\nimport {CommonModule} from \"@angular/common\";\nimport {CollapsibleSectionComponent} from \"core-app/modules/common/collapsible-section/collapsible-section.component\";\nimport {NoResultsComponent} from \"core-app/modules/common/no-results/no-results.component\";\nimport {DragDropModule} from \"@angular/cdk/drag-drop\";\nimport {UserAutocompleterComponent} from \"app/modules/common/autocomplete/user-autocompleter.component\";\nimport {ScrollableTabsComponent} from \"core-app/modules/common/tabs/scrollable-tabs/scrollable-tabs.component\";\nimport {ContentTabsComponent} from \"core-app/modules/common/tabs/content-tabs/content-tabs.component\";\nimport {EditableToolbarTitleComponent} from \"core-app/modules/common/editable-toolbar-title/editable-toolbar-title.component\";\nimport {UserAvatarComponent} from \"core-components/user/user-avatar/user-avatar.component\";\nimport {EnterpriseBannerComponent} from \"core-components/enterprise-banner/enterprise-banner.component\";\nimport {EnterpriseBannerBootstrapComponent} from \"core-components/enterprise-banner/enterprise-banner-bootstrap.component\";\nimport {DynamicModule} from \"ng-dynamic-component\";\nimport {VersionAutocompleterComponent} from \"core-app/modules/common/autocomplete/version-autocompleter.component\";\nimport {CreateAutocompleterComponent} from \"core-app/modules/common/autocomplete/create-autocompleter.component\";\nimport {HomescreenNewFeaturesBlockComponent} from \"core-components/homescreen/blocks/new-features.component\";\nimport {BoardVideoTeaserModalComponent} from \"core-app/modules/boards/board/board-video-teaser-modal/board-video-teaser-modal.component\";\nimport {PersistentToggleComponent} from \"core-app/modules/common/persistent-toggle/persistent-toggle.component\";\nimport {AutocompleteSelectDecorationComponent} from \"core-app/modules/common/autocomplete/autocomplete-select-decoration.component\";\nimport {AddSectionDropdownComponent} from \"core-app/modules/common/hide-section/add-section-dropdown/add-section-dropdown.component\";\nimport {HideSectionLinkComponent} from \"core-app/modules/common/hide-section/hide-section-link/hide-section-link.component\";\nimport {RemoteFieldUpdaterComponent} from 'core-app/modules/common/remote-field-updater/remote-field-updater.component';\nimport {AutofocusDirective} from \"core-app/modules/common/autofocus/autofocus.directive\";\nimport {ShowSectionDropdownComponent} from \"core-app/modules/common/hide-section/show-section-dropdown.component\";\nimport {IconTriggeredContextMenuComponent} from \"core-components/op-context-menu/icon-triggered-context-menu/icon-triggered-context-menu.component\";\nimport {NgSelectModule} from \"@ng-select/ng-select\";\nimport {NgOptionHighlightModule} from \"@ng-select/ng-option-highlight\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {CurrentUserService} from \"core-components/user/current-user.service\";\nimport {WorkPackageAutocompleterComponent} from \"core-app/modules/common/autocomplete/wp-autocompleter.component\";\nimport {TimeEntryWorkPackageAutocompleterComponent} from \"core-app/modules/common/autocomplete/te-work-package-autocompleter.component\";\nimport {DraggableAutocompleteComponent} from \"core-app/modules/common/draggable-autocomplete/draggable-autocomplete.component\";\nimport {DragulaModule} from \"ng2-dragula\";\nimport {SlideToggleComponent} from \"core-app/modules/common/slide-toggle/slide-toggle.component\";\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 FocusWithinDirective,\n FocusDirective,\n AuthoringComponent,\n\n // Notifications\n NotificationsContainerComponent,\n NotificationComponent,\n UploadProgressComponent,\n OpDateTimeComponent,\n\n // Table highlight\n HighlightColDirective,\n\n ResizerComponent,\n\n TablePaginationComponent,\n SortHeaderDirective,\n\n ZenModeButtonComponent,\n\n OPContextMenuComponent,\n IconTriggeredContextMenuComponent,\n\n NoResultsComponent,\n\n UserAutocompleterComponent,\n\n ScrollableTabsComponent,\n\n EditableToolbarTitleComponent,\n\n // User Avatar\n UserAvatarComponent,\n\n // Enterprise Edition\n EnterpriseBannerComponent,\n\n DynamicModule,\n\n WorkPackageAutocompleterComponent,\n\n DraggableAutocompleteComponent,\n\n // filter\n\n SlideToggleComponent,\n ],\n declarations: [\n OpDatePickerComponent,\n OpDateTimeComponent,\n OpIcon,\n AutofocusDirective,\n\n FocusWithinDirective,\n FocusDirective,\n AuthoringComponent,\n\n // Notifications\n NotificationsContainerComponent,\n NotificationComponent,\n UploadProgressComponent,\n OpDateTimeComponent,\n\n OPContextMenuComponent,\n IconTriggeredContextMenuComponent,\n\n // Table highlight\n HighlightColDirective,\n\n // Add functionality to rails rendered templates\n CopyToClipboardDirective,\n CollapsibleSectionComponent,\n\n CopyToClipboardDirective,\n ColorsAutocompleter,\n\n ResizerComponent,\n\n TablePaginationComponent,\n SortHeaderDirective,\n\n // Zen mode button\n ZenModeButtonComponent,\n\n NoResultsComponent,\n\n UserAutocompleterComponent,\n\n ScrollableTabsComponent,\n ContentTabsComponent,\n\n EditableToolbarTitleComponent,\n\n // User Avatar\n UserAvatarComponent,\n\n PersistentToggleComponent,\n AutocompleteSelectDecorationComponent,\n HideSectionLinkComponent,\n ShowSectionDropdownComponent,\n AddSectionDropdownComponent,\n RemoteFieldUpdaterComponent,\n\n // Enterprise Edition\n EnterpriseBannerComponent,\n EnterpriseBannerBootstrapComponent,\n\n // Autocompleter\n CreateAutocompleterComponent,\n VersionAutocompleterComponent,\n WorkPackageAutocompleterComponent,\n TimeEntryWorkPackageAutocompleterComponent,\n DraggableAutocompleteComponent,\n\n HomescreenNewFeaturesBlockComponent,\n BoardVideoTeaserModalComponent,\n\n //filter\n SlideToggleComponent,\n ]\n})\nexport class OpenprojectCommonModule {\n constructor(injector:Injector) {\n bootstrapModule(injector);\n\n\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {UserResource} from 'core-app/modules/hal/resources/user-resource';\nimport {AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, Input} from \"@angular/core\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {UserAvatarRendererService} from \"core-components/user/user-avatar/user-avatar-renderer.service\";\n\nexport const userAvatarSelector = 'user-avatar';\n\n@Component({\n selector: userAvatarSelector,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: ''\n})\nexport class UserAvatarComponent implements AfterViewInit {\n /** If coming from angular, pass a user resource if available */\n @Input() public user?:UserResource;\n\n constructor(protected elementRef:ElementRef,\n protected avatarRenderer:UserAvatarRendererService,\n protected pathHelper:PathHelperService) {\n }\n\n public ngAfterViewInit() {\n const element = this.elementRef.nativeElement;\n let user = this.user || { name: element.dataset.userName!, id: element.dataset.userId };\n this.avatarRenderer.render(element, user, false, element.dataset.classList);\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APIv3FormResource} from \"core-app/modules/apiv3/forms/apiv3-form-resource\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {HalPayloadHelper} from \"core-app/modules/hal/schemas/hal-payload.helper\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {GridWidgetResource} from \"core-app/modules/hal/resources/grid-widget-resource\";\n\nexport class Apiv3GridForm extends APIv3FormResource {\n\n /**\n * We need to override the grid widget extraction\n * to pass the correct payload to the API.\n *\n * @param resource\n * @param schema\n */\n public static extractPayload(resource:HalResource|Object, schema:SchemaResource|null = null):Object {\n if (resource instanceof HalResource && schema) {\n let grid = resource as HalResource;\n let payload = HalPayloadHelper.extractPayloadFromSchema(grid, schema);\n\n // The widget only states the type of the widget resource but does not explain\n // the widget itself. We therefore have to do that by hand.\n if (payload.widgets) {\n payload.widgets = grid.widgets.map((widget:GridWidgetResource) => {\n return {\n id: widget.id,\n startRow: widget.startRow,\n endRow: widget.endRow,\n startColumn: widget.startColumn,\n endColumn: widget.endColumn,\n identifier: widget.identifier,\n options: widget.options\n };\n });\n }\n\n return payload;\n }\n\n return resource || {};\n }\n\n /**\n * Extract payload for the form from the request and optional schema.\n *\n * @param request\n * @param schema\n */\n public extractPayload(request:HalResource|Object, schema:SchemaResource|null = null) {\n return Apiv3GridForm.extractPayload(request, schema);\n }\n\n}\n","import {RelationResource} from 'core-app/modules/hal/resources/relation-resource';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service';\nimport {multiInput, MultiInputState, StatesGroup} from 'reactivestates';\nimport {Injectable} from \"@angular/core\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {StateCacheService} from \"core-app/modules/apiv3/cache/state-cache.service\";\nimport {Observable} from \"rxjs\";\nimport {map, take, tap} from \"rxjs/operators\";\nimport {CollectionResource} from \"core-app/modules/hal/resources/collection-resource\";\n\nexport type RelationsStateValue = { [relationId:string]:RelationResource };\n\nexport class RelationStateGroup extends StatesGroup {\n name = 'WP-Relations';\n\n relations:MultiInputState = multiInput();\n\n constructor() {\n super();\n this.initializeMembers();\n }\n}\n\n@Injectable()\nexport class WorkPackageRelationsService extends StateCacheService {\n\n constructor(private PathHelper:PathHelperService,\n private apiV3Service:APIV3Service,\n private halResource:HalResourceService) {\n super(new RelationStateGroup().relations);\n }\n\n /**\n * Require the value to be loaded either when forced or the value is stale\n * according to the cache interval specified for this service.\n *\n * Returns a single promise to one loaded value\n *\n * @param id The state to require\n * @param force Load the value anyway.\n */\n public require(id:string, force:boolean = false):Promise {\n return this\n .requireAndStream(id, force)\n .pipe(\n take(1)\n )\n .toPromise();\n }\n\n /**\n * Require the value to be loaded either when forced or the value is stale\n * according to the cache interval specified for this service.\n *\n * Returns an observable to the values stream of the state.\n *\n * @param id The state to require\n * @param force Load the value anyway.\n */\n public requireAndStream(id:string, force:boolean = false):Observable {\n // Refresh when stale or being forced\n if (this.stale(id) || force) {\n this.clearAndLoad(\n id,\n this.load(id)\n );\n }\n\n return this.state(id).values$();\n }\n\n /**\n * Load a set of work package ids into the states, regardless of them being loaded\n * @param workPackageIds\n */\n protected load(id:string):Observable {\n return this\n .apiV3Service\n .work_packages\n .id(id)\n .relations\n .get()\n .pipe(\n map(collection => this.relationsStateValue(id, collection.elements))\n );\n }\n\n public requireAll(ids:string[]):Promise {\n return new Promise((resolve, reject) => {\n this\n .apiV3Service\n .relations\n .loadInvolved(ids)\n .toPromise()\n .then((elements:RelationResource[]) => {\n this.clearSome(...ids);\n this.accumulateRelationsFromInvolved(ids, elements);\n resolve();\n })\n .catch(reject);\n });\n }\n\n /**\n * Find a given relation by from, to and relation Type\n */\n public find(from:WorkPackageResource, to:WorkPackageResource, type:string):RelationResource|undefined {\n const relations:RelationsStateValue|undefined = this.state(from.id!).value;\n\n if (!relations) {\n return;\n }\n\n return _.find(relations, (relation:RelationResource) => {\n const denormalized = relation.denormalized(from);\n // Check that\n // 1. the denormalized relation points at \"to\"\n // 2. that the denormalized relation type matches.\n return denormalized.target.id === to.id &&\n denormalized.relationType === type;\n });\n }\n\n /**\n * Remove the given relation.\n */\n public removeRelation(relation:RelationResource) {\n return relation.delete().then(() => {\n this.removeFromStates(relation);\n });\n }\n\n /**\n * Update the given relation type, setting new values for from and to\n */\n public updateRelationType(from:WorkPackageResource, to:WorkPackageResource, relation:RelationResource, type:string) {\n const params = {\n _links: {\n from: { href: from.href },\n to: { href: to.href }\n },\n type: type\n };\n\n return this.updateRelation(relation, params);\n }\n\n public updateRelation(relation:RelationResource, params:{ [key:string]:any }) {\n return relation.updateImmediately(params)\n .then((savedRelation:RelationResource) => {\n this.insertIntoStates(savedRelation);\n return savedRelation;\n });\n }\n\n public addCommonRelation(fromId:string,\n relationType:string,\n relatedWpId:string) {\n const params = {\n _links: {\n from: { href: this.apiV3Service.work_packages.id(fromId).toString() },\n to: { href: this.apiV3Service.work_packages.id(relatedWpId).toString() }\n },\n type: relationType\n };\n\n const path = this.apiV3Service.work_packages.id(fromId).relations.toString();\n return this.halResource\n .post(path, params)\n .toPromise()\n .then((relation:RelationResource) => {\n this.insertIntoStates(relation);\n return relation;\n });\n }\n\n /**\n * Merges a single relation\n * @param relation\n */\n private insertIntoStates(relation:RelationResource) {\n _.values(relation.ids).forEach(wpId => {\n this.multiState.get(wpId).doModify((value:RelationsStateValue) => {\n value[relation.id!] = relation;\n return value;\n }, () => {\n let value:RelationsStateValue = {};\n value[relation.id!] = relation;\n return value;\n });\n });\n }\n\n /**\n * Remove the given relation from the from/to states\n * @param relation\n */\n private removeFromStates(relation:RelationResource) {\n _.values(relation.ids).forEach(wpId => {\n this.multiState.get(wpId).doModify((value:RelationsStateValue) => {\n delete value[relation.id!];\n return value;\n }, () => {\n return {};\n });\n });\n }\n\n /**\n * Given a set of complete relations for this work packge,\n * returns the RelationsStateValue\n *\n * @param wpId The wpId the relations belong to\n * @param relations The relation resource array.\n */\n private relationsStateValue(wpId:string, relations:RelationResource[]):RelationsStateValue {\n return _.keyBy(relations, r => r.id!);\n }\n\n /**\n *\n * We don't know how many values we're getting for a single work package\n * when we use the involved filter.\n *\n * We need to group relevant relations for work packages based on their to/from filter.\n */\n private accumulateRelationsFromInvolved(involved:string[], relations:RelationResource[]) {\n involved.forEach(wpId => {\n const relevant = relations.filter(r => r.isInvolved(wpId));\n const value = this.relationsStateValue(wpId, relevant);\n\n this.updateValue(wpId, value);\n });\n\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 href() {\n return `/api/v3/users/${this.userId}`;\n }\n\n public get name() {\n return this.userMeta.data('name');\n }\n\n public get mail() {\n return this.userMeta.data('mail');\n }\n\n public get language() {\n return I18n.locale || 'en';\n }\n\n private get userMeta():JQuery {\n return jQuery('meta[name=current_user]');\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n//++\n\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\n\nexport interface ISchemaProxy extends SchemaResource {\n ofProperty(property:string):IFieldSchema;\n isAttributeEditable(property:string):boolean;\n isEditable:boolean;\n}\n\nexport class SchemaProxy implements ProxyHandler {\n constructor(protected schema:SchemaResource,\n protected resource:HalResource) {\n }\n\n static create(schema:SchemaResource, resource:HalResource) {\n return new Proxy(\n schema,\n new this(schema, resource)\n ) as ISchemaProxy;\n }\n\n get(schema:SchemaResource, property:PropertyKey, receiver:any):any {\n switch (property) {\n case 'ofProperty': {\n return this.proxyMethod(this.ofProperty);\n }\n case 'isAttributeEditable': {\n return this.proxyMethod(this.isAttributeEditable);\n }\n case 'mappedName': {\n return this.proxyMethod(this.mappedName);\n }\n case 'isEditable': {\n return this.isEditable;\n }\n default: {\n return Reflect.get(schema, property, receiver);\n }\n }\n }\n\n /**\n * Returns the part of the schema relevant for the provided property.\n *\n * We use it to support the virtual attribute 'combinedDate' which is the combination of the three\n * attributes 'startDate', 'dueDate' and 'scheduleManually'. That combination exists only in the front end\n * and not on the native schema. As a property needs to be writable for us to allow the user editing,\n * we need to mark the writability positively if any of the combined properties are writable.\n *\n * @param property the schema part is desired for\n */\n public ofProperty(property:string):IFieldSchema|null {\n let propertySchema = this.schema[this.mappedName(property)];\n\n if (propertySchema) {\n return Object.assign({}, propertySchema, { writable: this.isEditable && propertySchema && propertySchema.writable });\n } else {\n return null;\n }\n }\n\n /**\n * Return whether the resource is editable with the user's permission\n * on the given resource package attribute.\n * In order to be editable, there needs to be an update link on the resource and the schema for\n * the attribute needs to indicate the writability.\n *\n * @param property\n */\n public isAttributeEditable(property:string):boolean {\n let propertySchema = this.ofProperty(property);\n\n return !!propertySchema && propertySchema.writable;\n }\n\n /**\n * Return whether the user in general has permission to edit the resource.\n * This check is required, but not sufficient to check all attribute restrictions.\n *\n * Use +isAttributeEditable(property)+ for this case.\n */\n public get isEditable() {\n return this.resource.isNew || !!this.resource.$links.update;\n }\n\n public mappedName(property:string):string {\n return property;\n }\n\n private proxyMethod(method:Function) {\n const self = this;\n\n // Returning a Proxy here so that the call is bound\n // to the SchemaProxy instance.\n return new Proxy(method, {\n apply: function (_, __, argumentsList) {\n return method.apply(self, [argumentsList[0]]);\n }\n });\n }\n}\n","
    \n
    \n\n \n\n
    \n
    \n \n \n
    \n \n\n \n \n \n\n \n \n \n \n
    \n
    \n
    \n\n \n
    \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {ErrorResource} from 'core-app/modules/hal/resources/error-resource';\nimport {WorkPackagesActivityService} from 'core-components/wp-single-view-tabs/activity-panel/wp-activity.service';\nimport {LoadingIndicatorService} from \"core-app/modules/common/loading-indicator/loading-indicator.service\";\nimport {CommentService} from \"core-components/wp-activity/comment-service\";\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ElementRef,\n Injector,\n Input,\n OnDestroy,\n OnInit,\n TemplateRef,\n ViewChild\n} from \"@angular/core\";\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\n\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageCommentFieldHandler} from \"core-components/work-packages/work-package-comment/work-package-comment-field-handler\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n selector: 'work-package-comment',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './work-package-comment.component.html'\n})\nexport class WorkPackageCommentComponent extends WorkPackageCommentFieldHandler implements OnInit, OnDestroy {\n @Input() public workPackage:WorkPackageResource;\n\n @ContentChild(TemplateRef) template:TemplateRef;\n @ViewChild('commentContainer') public commentContainer:ElementRef;\n\n public text = {\n editTitle: this.I18n.t('js.label_add_comment_title'),\n addComment: this.I18n.t('js.label_add_comment'),\n cancelTitle: this.I18n.t('js.label_cancel_comment'),\n placeholder: this.I18n.t('js.label_add_comment_title')\n };\n public fieldLabel:string = this.text.editTitle;\n\n public inFlight = false;\n public canAddComment:boolean;\n public showAbove:boolean;\n\n constructor(protected elementRef:ElementRef,\n protected injector:Injector,\n protected commentService:CommentService,\n protected wpLinkedActivities:WorkPackagesActivityService,\n protected ConfigurationService:ConfigurationService,\n protected loadingIndicator:LoadingIndicatorService,\n protected apiV3Service:APIV3Service,\n protected workPackageNotificationService:WorkPackageNotificationService,\n protected NotificationsService:NotificationsService,\n protected cdRef:ChangeDetectorRef,\n protected I18n:I18nService) {\n super(elementRef, injector);\n }\n\n public ngOnInit() {\n super.ngOnInit();\n\n this.canAddComment = !!this.workPackage.addComment;\n this.showAbove = this.ConfigurationService.commentsSortedInDescendingOrder();\n\n this.commentService.quoteEvents\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((quote:string) => {\n this.activate(quote);\n this.commentContainer.nativeElement.scrollIntoView();\n });\n }\n\n // Open the field when its closed and relay drag & drop events to it.\n public startDragOverActivation(event:JQuery.TriggeredEvent) {\n if (this.active) {\n return true;\n }\n\n this.activate();\n\n event.preventDefault();\n return false;\n }\n\n public 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\n .apiV3Service\n .work_packages\n .id(this.workPackage.id!)\n .refresh();\n\n this.inFlight = false;\n this.deactivate(true);\n })\n .catch((error:any) => {\n this.inFlight = false;\n if (error instanceof ErrorResource) {\n this.workPackageNotificationService.showError(error, this.workPackage);\n } else {\n this.NotificationsService.addError(this.I18n.t('js.work_packages.comment_send_failed'));\n }\n });\n }\n\n scrollToBottom():void {\n const scrollableContainer = jQuery(this.elementRef.nativeElement).scrollParent()[0];\n if (scrollableContainer) {\n setTimeout(() => {\n scrollableContainer.scrollTop = scrollableContainer.scrollHeight;\n }, 400);\n }\n }\n\n setErrors(newErrors:string[]):void {\n // interface\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {BcfPathHelperService} from \"core-app/modules/bim/bcf/helper/bcf-path-helper.service\";\n\nexport class BcfThumbnailDisplayField extends DisplayField {\n @InjectField() bcfPathHelper:BcfPathHelperService;\n\n public render(element:HTMLElement, displayText:string):void {\n const viewpoints = this.resource.bcfViewpoints;\n if (viewpoints && viewpoints.length > 0) {\n const viewpoint = viewpoints[0];\n element.innerHTML = `\n \n `;\n } else {\n element.innerHTML = '';\n }\n }\n}\n","import {Inject, Injectable} from '@angular/core';\nimport {DOCUMENT} from \"@angular/common\";\n\n@Injectable()\nexport class BcfDetectorService {\n constructor (@Inject(DOCUMENT) private documentElement:Document) {\n }\n\n /**\n * Detect whether the BCF module was activated,\n * resulting in a body class.\n */\n public get isBcfActivated() {\n return this.hasBodyClass('bcf-activated');\n }\n\n private hasBodyClass(name:string):boolean {\n return this.documentElement.body.classList.contains(name);\n }\n}\n","import {multiInput} from \"reactivestates\";\nimport {BcfExtensionResource} from \"core-app/modules/bim/bcf/api/extensions/bcf-extension.resource\";\nimport {BcfApiService} from \"core-app/modules/bim/bcf/api/bcf-api.service\";\nimport {Observable} from \"rxjs\";\nimport {map, take} from \"rxjs/operators\";\nimport {Injectable} from \"@angular/core\";\n\nexport type AllowedExtensionKey = keyof BcfExtensionResource;\n\n@Injectable({ providedIn: 'root' })\nexport class BcfAuthorizationService {\n\n // Poor mans caching to avoid repeatedly fetching from the backend.\n protected authorizationMap = multiInput();\n\n constructor(readonly bcfApi:BcfApiService) {\n }\n\n /**\n * Returns an observable boolean whether the given action\n * is authorized in the project by using the project extensions.\n *\n * Ensures the extension is loaded only once per project\n *\n * @param projectIdentifier Project identifier to check permission in\n * @param extension The extension key to check for\n * @param action The desired action\n */\n public authorized$(projectIdentifier:string, extension:AllowedExtensionKey, action:string):Observable {\n const state = this.authorizationMap.get(projectIdentifier);\n\n state.putFromPromiseIfPristine(() =>\n this.bcfApi\n .projects.id(projectIdentifier)\n .extensions\n .get()\n .toPromise()\n );\n\n return state\n .values$()\n .pipe(\n map(\n resource => resource[extension] && resource[extension].includes(action)\n )\n );\n }\n\n /**\n * One-time check to determine current allowed state.\n *\n * @param projectIdentifier Project identifier to check permission in\n * @param extension The extension key to check for\n * @param action The desired action\n */\n public isAllowedTo(projectIdentifier:string, extension:AllowedExtensionKey, action:string):Promise {\n return this\n .authorized$(projectIdentifier, extension, action)\n .pipe(\n take(1)\n )\n .toPromise()\n .catch(() => false);\n }\n}\n\n","\n
    \n
    \n
    \n

    \n
    \n
    \n\n
    0\">\n \n \n
    \n\n \n \n {{text.viewpoint}} \n \n
    \n
    ","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Input,\n OnDestroy,\n OnInit,\n ViewChild\n} from \"@angular/core\";\nimport {StateService} from \"@uirouter/core\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {NgxGalleryComponent, NgxGalleryOptions} from '@kolkov/ngx-gallery';\nimport {HalLink} from \"core-app/modules/hal/hal-link/hal-link\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ViewerBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {WorkPackageCreateService} from \"core-components/wp-new/wp-create.service\";\nimport {BcfAuthorizationService} from \"core-app/modules/bim/bcf/api/bcf-authorization.service\";\nimport {ViewpointsService} from \"core-app/modules/bim/bcf/helper/viewpoints.service\";\nimport {BcfViewpointItem} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint-item.interface\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n\n@Component({\n templateUrl: './bcf-wp-attribute-group.component.html',\n styleUrls: ['./bcf-wp-attribute-group.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [ViewpointsService]\n})\nexport class BcfWpAttributeGroupComponent extends UntilDestroyedMixin implements AfterViewInit, OnDestroy, OnInit {\n @Input() workPackage:WorkPackageResource;\n @ViewChild(NgxGalleryComponent) gallery:NgxGalleryComponent;\n\n text = {\n bcf: this.I18n.t('js.bcf.label_bcf'),\n viewpoint: this.I18n.t('js.bcf.viewpoint'),\n add_viewpoint: this.I18n.t('js.bcf.add_viewpoint'),\n show_viewpoint: this.I18n.t('js.bcf.show_viewpoint'),\n delete_viewpoint: this.I18n.t('js.bcf.delete_viewpoint'),\n text_are_you_sure: this.I18n.t('js.text_are_you_sure'),\n notice_successful_create: this.I18n.t('js.notice_successful_create'),\n notice_successful_delete: this.I18n.t('js.notice_successful_delete'),\n };\n\n galleryOptions:NgxGalleryOptions[] = [\n {\n width: '100%',\n height: '400px',\n\n // Show first thumbnail by default\n startIndex: 0,\n\n // Show only one image (\"thumbnail\")\n // and disable the large image slideshow\n image: false,\n thumbnailsColumns: 1,\n // Ensure thumbnails are ALWAYS shown\n thumbnailsAutoHide: false,\n // For BCFs all information shall be visible\n thumbnailSize: 'contain',\n imageAnimation: '',\n previewAnimation: false,\n previewCloseOnEsc: true,\n previewKeyboardNavigation: true,\n imageSize: 'contain',\n imageArrowsAutoHide: true,\n // thumbnailsArrowsAutoHide: true,\n thumbnailsMargin: 5,\n thumbnailMargin: 5,\n previewDownload: true,\n previewCloseOnClick: true,\n arrowPrevIcon: 'icon-arrow-left2',\n arrowNextIcon: 'icon-arrow-right2',\n closeIcon: 'icon-close',\n downloadIcon: 'icon-download',\n thumbnailActions: this.actions(),\n actions: this.actions(),\n },\n // max-width 800\n {\n breakpoint: 800,\n width: '100%',\n height: '400px',\n imagePercent: 80,\n thumbnailsPercent: 20,\n thumbnailsMargin: 5,\n thumbnailMargin: 5\n },\n // max-width 680\n {\n breakpoint: 680,\n height: '200px',\n thumbnailsColumns: 3,\n thumbnailsMargin: 5,\n thumbnailMargin: 5,\n }\n ];\n\n viewpoints:BcfViewpointItem[] = [];\n\n galleryImages:any[] = [];\n\n // Store whether viewing is allowed\n viewAllowed:boolean = false;\n // Store whether viewpoint creation is allowed\n createAllowed:boolean = false;\n // Currently, this is static. Need observable if this changes over time\n viewerVisible = false;\n projectId:string;\n\n constructor(readonly state:StateService,\n readonly bcfAuthorization:BcfAuthorizationService,\n readonly viewerBridge:ViewerBridgeService,\n readonly apiV3Service:APIV3Service,\n readonly wpCreate:WorkPackageCreateService,\n readonly notifications:NotificationsService,\n readonly cdRef:ChangeDetectorRef,\n readonly I18n:I18nService,\n readonly viewpointsService:ViewpointsService) {\n super();\n }\n\n ngAfterViewInit():void {\n // Observe changes on the work package to update the viewpoints\n this.observeChanges();\n }\n\n ngOnInit() {\n this.viewerBridge.viewerVisible$.subscribe((visible:boolean) => {\n if (visible) {\n this.viewerVisible = true;\n } else {\n this.viewerVisible = false;\n }\n this.cdRef.detectChanges();\n });\n }\n\n protected observeChanges() {\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .requireAndStream()\n .pipe(this.untilDestroyed())\n .subscribe(async wp => {\n this.workPackage = wp;\n\n if (!this.projectId) {\n await this.initialize(this.workPackage);\n }\n\n if (wp.bcfViewpoints) {\n this.refreshViewpoints(wp.bcfViewpoints);\n }\n });\n }\n\n async initialize(workPackage:WorkPackageResource) {\n this.projectId = workPackage.project.idFromLink;\n this.viewAllowed = await this.bcfAuthorization.isAllowedTo(this.projectId, 'project_actions', 'viewTopic');\n this.createAllowed = await this.bcfAuthorization.isAllowedTo(this.projectId, 'topic_actions', 'createViewpoint');\n\n this.loadViewpointFromRoute(workPackage);\n this.cdRef.detectChanges();\n }\n\n refreshViewpoints(viewpoints:HalLink[]) {\n this.viewpoints = viewpoints.map((el:HalLink) => ({ href: el.href, snapshotURL: `${el.href}/snapshot` }));\n\n this.setViewpointsOnGallery(this.viewpoints);\n }\n\n protected showViewpoint(workPackage:WorkPackageResource, index:number) {\n this.viewerBridge.showViewpoint(workPackage, index);\n }\n\n protected deleteViewpoint(workPackage:WorkPackageResource, index:number) {\n if (!window.confirm(this.text.text_are_you_sure)) {\n return;\n }\n\n this.viewpointsService\n .deleteViewPoint$(workPackage, index)\n .subscribe(data => {\n this.notifications.addSuccess(this.text.notice_successful_delete);\n this.gallery.preview.close();\n });\n }\n\n public saveViewpoint(workPackage:WorkPackageResource) {\n this.viewpointsService\n .saveViewpoint$(workPackage)\n .subscribe(viewpoint => {\n this.notifications.addSuccess(this.text.notice_successful_create);\n this.showIndex = this.viewpoints.length;\n });\n }\n\n protected loadViewpointFromRoute(workPackage:WorkPackageResource) {\n if (typeof (this.state.params.viewpoint) === 'number') {\n const index = this.state.params.viewpoint;\n this.showViewpoint(workPackage, index);\n this.showIndex = index;\n this.selectViewpointInGallery();\n this.state.go('.', { ...this.state.params, viewpoint: undefined }, { reload: false });\n }\n }\n\n public shouldShowGroup() {\n return this.viewAllowed &&\n (this.viewpoints.length > 0 ||\n (this.createAllowed && this.viewerVisible));\n }\n\n // Gallery functionality\n protected actions() {\n return [\n {\n icon: 'icon-view-model',\n onClick: (evt:any, index:number) => {\n this.showViewpoint(this.workPackage, index);\n this.gallery.preview.close();\n },\n titleText: this.text.show_viewpoint\n },\n {\n icon: 'icon-delete',\n onClick: (evt:any, index:number) => this.deleteViewpoint(this.workPackage, index),\n titleText: this.text.delete_viewpoint\n }\n ];\n }\n\n public galleryPreviewOpen():void {\n jQuery('#top-menu').addClass('-no-z-index');\n }\n\n public galleryPreviewClose():void {\n jQuery('#top-menu').removeClass('-no-z-index');\n }\n\n public selectViewpointInGallery() {\n setTimeout(() => this.gallery?.show(this.showIndex), 250);\n }\n\n public onGalleryChanged(event:{ index:number }) {\n this.showIndex = event.index;\n }\n\n protected set showIndex(value:number) {\n const options = [...this.galleryOptions];\n options[0].startIndex = value;\n this.galleryOptions = options;\n }\n\n protected get showIndex():number {\n return this.galleryOptions[0].startIndex!;\n }\n\n protected setViewpointsOnGallery(viewpoints:BcfViewpointItem[]) {\n const length = viewpoints.length;\n\n this.setThumbnailProperties(length);\n\n if (this.showIndex < 0 || length < 1) {\n this.showIndex = 0;\n } else if (this.showIndex >= length) {\n this.showIndex = length - 1;\n }\n\n this.galleryImages = viewpoints.map(viewpoint => {\n return {\n small: viewpoint.snapshotURL,\n medium: viewpoint.snapshotURL,\n big: viewpoint.snapshotURL\n };\n });\n this.cdRef.detectChanges();\n }\n\n protected setThumbnailProperties(viewpointCount:number) {\n const options = [...this.galleryOptions];\n\n options[0].thumbnailsColumns = viewpointCount < 5 ? viewpointCount : 4;\n options[1].thumbnailsColumns = viewpointCount < 5 ? viewpointCount : 4;\n options[2].thumbnailsColumns = viewpointCount < 4 ? viewpointCount : 3;\n\n options[0].height = `${this.dynamicThumbnailHeight(viewpointCount)}px`;\n options[1].height = `${this.dynamicThumbnailHeight(viewpointCount)}px`;\n options[2].height = `${this.dynamicThumbnailHeight(viewpointCount)}px`;\n\n this.galleryOptions = options;\n }\n\n protected dynamicThumbnailHeight(viewpointCount:number):number {\n return Math.max(Math.round(300 / viewpointCount), 120);\n }\n}\n","import {ChangeDetectionStrategy, Component} from \"@angular/core\";\nimport {BcfWpAttributeGroupComponent} from \"core-app/modules/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component\";\nimport {take, switchMap} from \"rxjs/operators\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {forkJoin} from \"rxjs\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {BcfViewpointItem} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint-item.interface\";\n\n\n@Component({\n templateUrl: './bcf-wp-attribute-group.component.html',\n styleUrls: ['./bcf-wp-attribute-group.component.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BcfNewWpAttributeGroupComponent extends BcfWpAttributeGroupComponent {\n galleryViewpoints:BcfViewpointItem[] = [];\n\n ngAfterViewInit():void {\n if (this.viewerVisible) {\n super.ngAfterViewInit();\n\n // Save any leftover viewpoints when saving the work package\n if (this.workPackage.isNew) {\n this.observeCreation();\n }\n }\n }\n\n // Because this is a new WorkPackage, in order to save the\n // viewpoints on it we need to:\n // - Wait until the WorkPackage is created\n // - Create the BCFTopic on it to save the viewpoints\n private observeCreation() {\n this.wpCreate\n .onNewWorkPackage()\n .pipe(\n this.untilDestroyed(),\n take(1),\n switchMap((wp:WorkPackageResource) => this.viewpointsService.setBcfTopic$(wp), (wp) => wp),\n switchMap((wp:WorkPackageResource) => {\n this.workPackage = wp;\n const observables = this.galleryViewpoints\n .filter(viewPointItem => !viewPointItem.href && viewPointItem.viewpoint)\n .map(viewPointItem => this.viewpointsService.saveViewpoint$(this.workPackage, viewPointItem.viewpoint)); \n\n return forkJoin(observables);\n })\n )\n .subscribe((viewpoints: BcfViewpointInterface[]) => {\n this.showIndex = this.galleryViewpoints.length - 1;\n });\n }\n\n // Disable show viewpoint functionality\n showViewpoint(workPackage:WorkPackageResource, index:number) {\n return;\n }\n\n deleteViewpoint(workPackage:WorkPackageResource, index:number) {\n this.galleryViewpoints = this.galleryViewpoints.filter((_, i) => i !== index);\n\n this.setViewpointsOnGallery(this.galleryViewpoints);\n \n return;\n }\n\n saveViewpoint() {\n this.viewerBridge\n .getViewpoint$() \n .subscribe(viewpoint => { \n const newViewpoint = {\n snapshotURL: viewpoint.snapshot.snapshot_data,\n viewpoint: viewpoint\n };\n\n this.galleryViewpoints = [\n ...this.galleryViewpoints,\n newViewpoint\n ];\n\n this.setViewpointsOnGallery(this.galleryViewpoints);\n\n // Select the last created viewpoint and show it\n this.showIndex = this.galleryViewpoints.length - 1;\n this.selectViewpointInGallery();\n });\n }\n\n shouldShowGroup() {\n return this.createAllowed && this.viewerVisible;\n }\n protected actions() {\n // Show only delete button\n return super\n .actions()\n .filter(el => el.icon === 'icon-delete');\n }\n}\n","import {Injectable, Injector} from '@angular/core';\nimport {Observable, Subject, BehaviorSubject} from \"rxjs\";\nimport {distinctUntilChanged, filter, first, map, mapTo} from \"rxjs/operators\";\nimport {BcfViewpointInterface} from \"core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface\";\nimport {ViewerBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {ViewpointsService} from \"core-app/modules/bim/bcf/helper/viewpoints.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\n\ndeclare global {\n interface Window {\n RevitBridge:any;\n }\n}\n\n@Injectable()\nexport class RevitBridgeService extends ViewerBridgeService {\n public shouldShowViewer = false;\n public viewerVisible$ = new BehaviorSubject(false);\n private revitMessageReceivedSource = new Subject<{ messageType:string, trackingId:string, messagePayload:any }>();\n private trackingIdNumber = 0;\n\n @InjectField() viewpointsService:ViewpointsService;\n\n revitMessageReceived$ = this.revitMessageReceivedSource.asObservable();\n\n constructor(readonly injector:Injector) {\n super(injector);\n\n if (window.RevitBridge) {\n this.hookUpRevitListener();\n } else {\n window.addEventListener('revit.plugin.ready', () => {\n this.hookUpRevitListener();\n }, { once: true });\n }\n }\n\n public viewerVisible() {\n return this.viewerVisible$.getValue();\n }\n\n public getViewpoint$():Observable {\n const trackingId = this.newTrackingId();\n\n this.sendMessageToRevit('ViewpointGenerationRequest', trackingId, '');\n\n return this.revitMessageReceived$\n .pipe(\n distinctUntilChanged(),\n filter(message => message.messageType === 'ViewpointData' && message.trackingId === trackingId),\n first()\n )\n .pipe(\n map((message) => {\n let viewpointJson = message.messagePayload;\n\n viewpointJson.snapshot = {\n snapshot_type: 'png',\n snapshot_data: viewpointJson.snapshot,\n };\n\n return viewpointJson;\n })\n );\n }\n\n public showViewpoint(workPackage:WorkPackageResource, index:number) {\n this.viewpointsService\n .getViewPoint$(workPackage, index)\n .subscribe((viewpoint:BcfViewpointInterface) => this.sendMessageToRevit('ShowViewpoint', this.newTrackingId(), JSON.stringify(viewpoint)));\n }\n\n sendMessageToRevit(messageType:string, trackingId:string, messagePayload?:any) {\n if (!this.viewerVisible()) {\n return;\n }\n\n const jsonPayload = messagePayload != null ? JSON.stringify(messagePayload) : null;\n window.RevitBridge.sendMessageToRevit(messageType, trackingId, jsonPayload);\n }\n\n private hookUpRevitListener() {\n window.RevitBridge.sendMessageToOpenProject = (messageString:string) => {\n const message = JSON.parse(messageString);\n const messageType = message.messageType;\n const trackingId = message.trackingId;\n const messagePayload = JSON.parse(message.messagePayload);\n\n this.revitMessageReceivedSource.next({\n messageType: messageType,\n trackingId: trackingId,\n messagePayload: messagePayload\n });\n };\n this.viewerVisible$.next(true);\n }\n\n newTrackingId():string {\n this.trackingIdNumber = this.trackingIdNumber + 1;\n return String(this.trackingIdNumber);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injector, NgModule} from '@angular/core';\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {NgxGalleryModule} from \"@kolkov/ngx-gallery\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {BcfThumbnailDisplayField} from \"core-app/modules/bim/bcf/fields/display/bcf-thumbnail-field.module\";\nimport {HTTP_INTERCEPTORS} from \"@angular/common/http\";\nimport {OpenProjectHeaderInterceptor} from \"core-app/modules/hal/http/openproject-header-interceptor\";\nimport {BcfDetectorService} from \"core-app/modules/bim/bcf/helper/bcf-detector.service\";\nimport {BcfPathHelperService} from \"core-app/modules/bim/bcf/helper/bcf-path-helper.service\";\nimport {ViewpointsService} from \"core-app/modules/bim/bcf/helper/viewpoints.service\";\nimport {BcfImportButtonComponent} from \"core-app/modules/bim/ifc_models/toolbar/import-export-bcf/bcf-import-button.component\";\nimport {BcfExportButtonComponent} from \"core-app/modules/bim/ifc_models/toolbar/import-export-bcf/bcf-export-button.component\";\nimport {IFCViewerService} from \"core-app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service\";\nimport {ViewerBridgeService} from \"core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {BcfWpAttributeGroupComponent} from \"core-app/modules/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component\";\nimport {BcfNewWpAttributeGroupComponent} from \"core-app/modules/bim/bcf/bcf-wp-attribute-group/bcf-new-wp-attribute-group.component\";\nimport {RevitBridgeService} from \"core-app/modules/bim/revit_add_in/revit-bridge.service\";\n\n/**\n * Determines based on the current user agent whether\n * we're running in Revit or not.\n *\n * Depending on that, we use the IFC viewer service for showing/saving viewpoints.\n */\nexport const viewerBridgeServiceFactory = (injector:Injector) => {\n if (window.navigator.userAgent.search('Revit') > -1) {\n return new RevitBridgeService(injector);\n } else {\n return injector.get(IFCViewerService, new IFCViewerService(injector));\n }\n};\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n NgxGalleryModule,\n ],\n providers: [\n { provide: HTTP_INTERCEPTORS, useClass: OpenProjectHeaderInterceptor, multi: true },\n {\n provide: ViewerBridgeService,\n useFactory: viewerBridgeServiceFactory,\n deps: [Injector]\n },\n BcfDetectorService,\n BcfPathHelperService,\n ViewpointsService,\n ],\n declarations: [\n BcfWpAttributeGroupComponent,\n BcfNewWpAttributeGroupComponent,\n BcfImportButtonComponent,\n BcfExportButtonComponent,\n ],\n exports: [\n BcfImportButtonComponent,\n BcfExportButtonComponent,\n ]\n})\nexport class OpenprojectBcfModule {\n static bootstrapCalled = false;\n\n constructor(injector:Injector) {\n OpenprojectBcfModule.bootstrap(injector);\n }\n\n // The static property prevents running the function\n // multiple times. This happens e.g. when the module is included\n // into a plugin's module.\n public static bootstrap(injector:Injector):void {\n if (this.bootstrapCalled) {\n return;\n }\n\n this.bootstrapCalled = true;\n\n const displayFieldService = injector.get(DisplayFieldService);\n displayFieldService\n .addFieldType(BcfThumbnailDisplayField, 'bcfThumbnail', [\n 'BCF Thumbnail'\n ]);\n\n\n const hookService = injector.get(HookService);\n hookService.register('prependedAttributeGroups', (workPackage:WorkPackageResource) => {\n if (!window.OpenProject.isBimEdition) {\n return;\n }\n\n if (workPackage.isNew) {\n return BcfNewWpAttributeGroupComponent;\n } else {\n return BcfWpAttributeGroupComponent;\n }\n });\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","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 = { ...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 this.reloadWorkPackageAndClose();\n }\n\n public get saveText() {\n return this.i18n.t('js.label_create');\n }\n}\n","import { Injectable, Injector } from \"@angular/core\";\nimport { OpModalService } from \"app/components/op-modals/op-modal.service\";\nimport { HalResourceService } from \"app/modules/hal/services/hal-resource.service\";\nimport { I18nService } from \"core-app/modules/common/i18n/i18n.service\";\nimport { TimeEntryResource } from 'core-app/modules/hal/resources/time-entry-resource';\nimport { take } from 'rxjs/operators';\nimport { FormResource } from \"core-app/modules/hal/resources/form-resource\";\nimport { ResourceChangeset } from \"core-app/modules/fields/changeset/resource-changeset\";\nimport { HalResourceEditingService } from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport { Moment } from 'moment';\nimport { TimeEntryCreateModal } from \"core-app/modules/time_entries/create/create.modal\";\nimport { WorkPackageResource } from 'core-app/modules/hal/resources/work-package-resource';\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Injectable()\nexport class TimeEntryCreateService {\n\n constructor(readonly opModalService:OpModalService,\n readonly injector:Injector,\n readonly halResource:HalResourceService,\n readonly apiV3Service:APIV3Service,\n readonly schemaCache:SchemaCacheService,\n protected halEditing:HalResourceEditingService,\n readonly i18n:I18nService) {\n }\n\n public create(date:Moment, wp?:WorkPackageResource, showWorkPackageField:boolean = true) {\n return new Promise<{ entry:TimeEntryResource, action:'create' }>((resolve, reject) => {\n this\n .createNewTimeEntry(date, wp)\n .then(changeset => {\n const modal = this.opModalService.show(TimeEntryCreateModal, this.injector, { changeset: changeset, showWorkPackageField: showWorkPackageField });\n\n modal\n .closingEvent\n .pipe(take(1))\n .subscribe(() => {\n if (modal.createdEntry) {\n resolve({ entry: modal.createdEntry, action: 'create' });\n } else {\n reject();\n }\n });\n });\n });\n }\n\n public createNewTimeEntry(date:Moment, wp?:WorkPackageResource) {\n let payload:any = {\n spentOn: date.format('YYYY-MM-DD')\n };\n\n if (wp) {\n payload['_links'] = {\n workPackage: {\n href: wp.href\n }\n };\n }\n\n return this\n .apiV3Service\n .time_entries\n .form\n .post(payload)\n .toPromise()\n .then(form => {\n return this.fromCreateForm(form);\n });\n }\n\n public fromCreateForm(form:FormResource):ResourceChangeset {\n let entry = this.initializeNewResource(form);\n\n return this.halEditing.edit>(entry, form);\n }\n\n private initializeNewResource(form:FormResource) {\n let entry = this.halResource.createHalResourceOfType('TimeEntry', form.payload.$plain());\n\n entry.$links['schema'] = { href: 'new' };\n\n entry['_type'] = 'TimeEntry';\n entry['id'] = 'new';\n entry['hours'] = 'PT1H';\n\n // Set update link to form\n entry['update'] = entry.$links['update'] = form.$links.self;\n // Use POST /work_packages for saving link\n entry['updateImmediately'] = entry.$links['updateImmediately'] = (payload:{}) => {\n return this\n .apiV3Service\n .time_entries\n .post(payload)\n .toPromise();\n };\n\n entry.state.putValue(entry);\n // We need to provide the schema to the cache so that it is available in the html form to e.g. determine\n // the editability.\n // It would be better if the edit field could simply rely on the changeset if it exists.\n this.schemaCache.update(entry, form.schema);\n\n return entry;\n }\n}","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {NgModule} from '@angular/core';\n\nimport {OpenprojectCommonModule} from 'core-app/modules/common/openproject-common.module';\nimport {AttachmentsComponent} from \"core-app/modules/attachments/attachments.component\";\nimport {AttachmentListComponent} from \"core-app/modules/attachments/attachment-list/attachment-list.component\";\nimport {AttachmentListItemComponent} from \"core-app/modules/attachments/attachment-list/attachment-list-item.component\";\nimport {AttachmentsUploadComponent} from \"core-app/modules/attachments/attachments-upload/attachments-upload.component\";\n\n@NgModule({\n imports: [\n OpenprojectCommonModule,\n ],\n declarations: [\n AttachmentsComponent,\n AttachmentListComponent,\n AttachmentListItemComponent,\n AttachmentsUploadComponent,\n ],\n exports: [\n AttachmentsUploadComponent,\n AttachmentListComponent,\n AttachmentsComponent,\n ]\n})\nexport class OpenprojectAttachmentsModule {\n}\n\n","import {Injector} from '@angular/core';\nimport {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';\nimport {SingleRowBuilder} from \"core-components/wp-fast-table/builders/rows/single-row-builder\";\nimport {WorkPackageTable} from \"core-components/wp-fast-table/wp-fast-table\";\nimport {States} from \"core-components/states.service\";\nimport {\n collapsedGroupClass,\n hierarchyGroupClass,\n hierarchyRootClass\n} from \"core-components/wp-fast-table/helpers/wp-table-hierarchy-helpers\";\nimport {WorkPackageViewHierarchiesService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-hierarchy.service\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\n\nexport const indicatorCollapsedClass = '-hierarchy-collapsed';\nexport const hierarchyCellClassName = 'wp-table--hierarchy-span';\nexport const additionalHierarchyRowClassName = 'wp-table--hierarchy-aditional-row';\nexport const hierarchyIndentation = 20;\nexport const hierarchyBaseIndentation = 25;\n\nexport class SingleHierarchyRowBuilder extends SingleRowBuilder {\n // Injected\n @InjectField() public wpTableHierarchies:WorkPackageViewHierarchiesService;\n @InjectField() public states:States;\n\n // Retain a map of hierarchy elements present in the table\n // with at least a visible child\n public parentsWithVisibleChildren:{ [id:string]:boolean };\n\n public text:{\n leaf:(level:number) => string;\n expanded:(level:number) => string;\n collapsed:(level:number) => string;\n };\n\n constructor(public readonly injector:Injector,\n protected workPackageTable:WorkPackageTable) {\n\n super(injector, workPackageTable);\n\n this.text = {\n leaf: (level:number) => this.I18n.t('js.work_packages.hierarchy.leaf', {level: level}),\n expanded: (level:number) => this.I18n.t('js.work_packages.hierarchy.children_expanded',\n {level: level}),\n collapsed: (level:number) => this.I18n.t('js.work_packages.hierarchy.children_collapsed',\n {level: level}),\n };\n }\n\n /**\n * Refresh a single row after structural changes.\n * Remembers and re-adds the hierarchy indicator if neccessary.\n */\n public refreshRow(workPackage:WorkPackageResource, jRow:JQuery):JQuery {\n // Remove any old hierarchy\n const newRow = super.refreshRow(workPackage, jRow);\n newRow.find(`.wp-table--hierarchy-span`).remove();\n this.appendHierarchyIndicator(workPackage, newRow);\n\n return newRow;\n }\n\n /**\n * Build the columns on the given empty row\n */\n public buildEmpty(workPackage:WorkPackageResource):[HTMLTableRowElement, boolean] {\n let [element, _] = super.buildEmpty(workPackage);\n let [classes, hidden] = this.ancestorRowData(workPackage);\n element.classList.add(...classes);\n\n this.appendHierarchyIndicator(workPackage, jQuery(element));\n return [element, hidden];\n }\n\n /**\n * Returns a set of\n * @param workPackage\n */\n public ancestorRowData(workPackage:WorkPackageResource):[string[], boolean] {\n const state = this.wpTableHierarchies.current;\n const rowClasses:string[] = [];\n let hidden = false;\n\n if (this.parentsWithVisibleChildren[workPackage.id!]) {\n rowClasses.push(hierarchyRootClass(workPackage.id!));\n }\n\n if (_.isArray(workPackage.ancestors)) {\n workPackage.ancestors.forEach((ancestor) => {\n rowClasses.push(hierarchyGroupClass(ancestor.id!));\n\n if (state.collapsed[ancestor.id!]) {\n hidden = true;\n rowClasses.push(collapsedGroupClass(ancestor.id!));\n }\n\n });\n }\n\n return [rowClasses, hidden];\n }\n\n /**\n * Append an additional ancestor row that is not yet loaded\n */\n public buildAncestorRow(ancestor:WorkPackageResource,\n ancestorGroups:string[],\n index:number):[HTMLTableRowElement, boolean] {\n\n const workPackage = this.states.workPackages.get(ancestor.id!).value!;\n const [tr, hidden] = this.buildEmpty(workPackage);\n tr.classList.add(additionalHierarchyRowClassName);\n return [tr, hidden];\n }\n\n /**\n * Append to the row of hierarchy level a hierarchy indicator.\n * @param workPackage\n * @param jRow jQuery row element\n * @param level Indentation level\n */\n private appendHierarchyIndicator(workPackage:WorkPackageResource, jRow:JQuery, level?:number):void {\n const hierarchyLevel = level === undefined || null ? workPackage.ancestors.length : level;\n const hierarchyElement = this.buildHierarchyIndicator(workPackage, jRow, hierarchyLevel);\n\n jRow.find('td.subject')\n .addClass('-with-hierarchy')\n .prepend(hierarchyElement);\n\n // Assure that the content is still visible when the hierarchy indentation is very large\n jRow.find('td.subject').css('minWidth', 125 + (hierarchyIndentation * hierarchyLevel) + 'px');\n jRow.find('td.subject .wp-table--cell-container')\n .css('width', 'calc(100% - ' + hierarchyBaseIndentation + 'px - ' + (hierarchyIndentation * hierarchyLevel) + 'px)');\n }\n\n /**\n * Build the hierarchy indicator at the given indentation level.\n */\n private buildHierarchyIndicator(workPackage:WorkPackageResource, jRow:JQuery|null, level:number):HTMLElement {\n const hierarchyIndicator = document.createElement('span');\n const collapsed = this.wpTableHierarchies.collapsed(workPackage.id!);\n const indicatorWidth = hierarchyBaseIndentation + (hierarchyIndentation * level) + 'px';\n hierarchyIndicator.classList.add(hierarchyCellClassName);\n hierarchyIndicator.style.width = indicatorWidth;\n hierarchyIndicator.dataset.indentation = indicatorWidth;\n\n if (this.parentsWithVisibleChildren[workPackage.id!]) {\n const className = collapsed ? indicatorCollapsedClass : '';\n hierarchyIndicator.innerHTML = `\n \n \n ${this.text.expanded(\n level)}\n ${this.text.collapsed(\n level)}\n \n `;\n } else {\n hierarchyIndicator.innerHTML = `\n \n ${this.text.leaf(level)}\n \n `;\n }\n\n return hierarchyIndicator;\n }\n\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 import_hover: this.I18n.t('js.bcf.import_bcf_xml_file')\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 {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Directive()\nexport abstract class TimeEntryBaseModal extends OpModalComponent {\n @ViewChild('editForm', { static: true }) editForm:TimeEntryFormComponent;\n\n public text:{ [key:string]:string } = {\n title: this.i18n.t('js.time_entry.title'),\n cancel: this.i18n.t('js.button_cancel'),\n close: this.i18n.t('js.button_close'),\n delete: this.i18n.t('js.button_delete'),\n areYouSure: this.i18n.t('js.text_are_you_sure'),\n };\n\n public closeOnEscape = false;\n public closeOnOutsideClick = false;\n public formInFlight:boolean;\n\n @InjectField() apiV3Service:APIV3Service;\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) readonly locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly i18n:I18nService,\n readonly injector:Injector) {\n super(locals, cdRef, elementRef);\n }\n\n public abstract setModifiedEntry($event:{savedResource:HalResource, isInital:boolean}):void;\n\n public get changeset() {\n return this.locals.changeset;\n }\n\n public get entry() {\n return this.changeset.projectedResource;\n }\n\n public get showWorkPackageField() {\n return this.locals.showWorkPackageField !== undefined ? this.locals.showWorkPackageField : true;\n }\n\n public saveEntry() {\n this.formInFlight = true;\n\n this.editForm.save()\n .then(() => this.reloadWorkPackageAndClose())\n .catch(() => {\n this.formInFlight = false;\n this.cdRef.detectChanges();\n });\n }\n\n public get saveText() {\n return this.i18n.t('js.button_save');\n }\n\n public get saveAllowed() {\n return true;\n }\n\n public get deleteAllowed() {\n return true;\n }\n\n protected reloadWorkPackageAndClose() {\n // reload workPackage\n if (this.entry.workPackage) {\n this\n .apiV3Service\n .work_packages\n .id(this.entry.workPackage)\n .refresh();\n }\n this.service.close();\n this.formInFlight = false;\n this.cdRef.detectChanges();\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {MainMenuNavigationService} from \"core-components/main-menu/main-menu-navigation.service\";\nimport {map} from \"rxjs/operators\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\nexport const boardsMenuSelector = 'boards-menu';\n\n@Component({\n selector: boardsMenuSelector,\n templateUrl: './boards-menu.component.html'\n})\n\nexport class BoardsMenuComponent extends UntilDestroyedMixin implements OnInit {\n trackById = AngularTrackingHelpers.compareByAttribute('id');\n\n currentProjectIdentifier = this.currentProject.identifier;\n\n selectedBoardId:string;\n\n public boards$:Observable = this\n .apiV3Service\n .boards\n .observeAll()\n .pipe(\n map((boards:Board[]) => {\n return boards.sort(function (a, b) {\n if (a.name < b.name) {\n return -1;\n }\n if (a.name > b.name) {\n return 1;\n }\n return 0;\n });\n })\n );\n\n constructor(private readonly boardService:BoardService,\n private readonly apiV3Service:APIV3Service,\n private readonly currentProject:CurrentProjectService,\n private readonly mainMenuService:MainMenuNavigationService) {\n super();\n }\n\n ngOnInit() {\n // When activating the boards submenu,\n // either initially or through click on the toggle, load the results\n this.mainMenuService\n .onActivate('board_view')\n .subscribe(() => {\n this.focusBackArrow();\n this.boardService.loadAllBoards();\n });\n\n this\n .boardService\n .currentBoard$\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((id:string|null) => {\n this.selectedBoardId = id ? id : '';\n });\n }\n\n private focusBackArrow() {\n let buttonArrowLeft = jQuery('*[data-name=\"board_view\"] .main-menu--arrow-left-to-project');\n buttonArrowLeft.focus();\n }\n}\n","
    \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';\nimport {DateKeys} from \"core-components/datepicker/datepicker.modal\";\nimport {DatePicker} from \"core-app/modules/common/op-date-picker/datepicker\";\nimport {DateOption} from \"flatpickr/dist/types/options\";\n\n@Injectable({ providedIn: 'root' })\nexport class DatePickerModalHelper {\n public currentlyActivatedDateField:DateKeys;\n\n /**\n * Map the date to the internal format,\n * setting to null if it's empty.\n * @param key\n */\n public mappedDate(date:string):string|null {\n return date === '' ? null : date;\n }\n\n public parseDate(date:Date|string):Date|'' {\n if (date instanceof Date) {\n return new Date(date.setHours(0,0,0,0));\n } else if (date === '') {\n return '';\n } else {\n return new Date(new Date(date).setHours(0,0,0,0));\n }\n }\n\n public validDate(date:Date|string) {\n return (date instanceof Date) ||\n (date === '') ||\n !!new Date(date).valueOf();\n }\n\n public sortDates(dates:Date[]):Date[] {\n return dates.sort(function(a:Date, b:Date) {\n return a.getTime() - b.getTime();\n });\n }\n\n public areDatesEqual(firstDate:Date|string, secondDate:Date|string) {\n let parsedDate1 = this.parseDate(firstDate);\n let parsedDate2 = this.parseDate(secondDate);\n\n if ((typeof(parsedDate1) === 'string') || (typeof(parsedDate2) === 'string')) {\n return false;\n } else {\n return parsedDate1.getTime() === parsedDate2.getTime();\n }\n }\n\n public setCurrentActivatedField(val:DateKeys) {\n this.currentlyActivatedDateField = val;\n }\n\n public toggleCurrentActivatedField(dates:{ [key in DateKeys]:string }, datePicker:DatePicker) {\n this.currentlyActivatedDateField = this.currentlyActivatedDateField === 'start' ? 'end' : 'start';\n this.setDatepickerRestrictions(dates, datePicker);\n }\n\n public isStateOfCurrentActivatedField(val:DateKeys):boolean {\n return this.currentlyActivatedDateField === val;\n }\n\n public setDates(dates:DateOption|DateOption[], datePicker:DatePicker, enforceDate?:Date) {\n let currentMonth = datePicker.datepickerInstance.currentMonth;\n let currentYear = datePicker.datepickerInstance.currentYear;\n datePicker.setDates(dates);\n\n if (enforceDate) {\n datePicker.datepickerInstance.currentMonth = enforceDate.getMonth();\n datePicker.datepickerInstance.currentYear = enforceDate.getFullYear();\n } else {\n // Keep currently active month and avoid jump because of two-month layout\n datePicker.datepickerInstance.currentMonth = currentMonth;\n datePicker.datepickerInstance.currentYear = currentYear;\n }\n\n datePicker.datepickerInstance.redraw();\n }\n\n public setDatepickerRestrictions(dates:{ [key in DateKeys]:string }, datePicker:DatePicker) {\n if (!dates.start && !dates.end) {\n return;\n }\n\n let disableFunction:Function = (date:Date) => {\n return false;\n };\n\n if (this.isStateOfCurrentActivatedField('start') && dates.end) {\n disableFunction = (date:Date) => {\n return date.getTime() > new Date(dates.end).setHours(0,0,0,0);\n };\n } else if (this.isStateOfCurrentActivatedField('end') && dates.start) {\n disableFunction = (date:Date) => {\n return date.getTime() < new Date(dates.start).setHours(0,0,0,0);\n };\n }\n\n datePicker.datepickerInstance.set('disable', [disableFunction]);\n }\n\n public setRangeClasses(dates:{ [key in DateKeys]:string }) {\n if (!dates.start || !dates.end || (dates.start === dates.end)) {\n return;\n }\n\n var monthContainer = document.getElementsByClassName('dayContainer');\n // For each container of the two-month layout, set the highlighting classes\n for (let i = 0; i < monthContainer.length; i++) {\n this.highlightRangeInSingleMonth(monthContainer[i], dates);\n }\n }\n\n private highlightRangeInSingleMonth(container:Element, dates:{ [key in DateKeys]:string }) {\n var selectedElements = jQuery(container).find('.flatpickr-day.selected');\n if (selectedElements.length === 2) {\n // Both dates are in the same month\n selectedElements[0].classList.add('startRange');\n selectedElements[1].classList.add('endRange');\n\n this.selectRangeFromUntil(selectedElements[0], selectedElements[1]);\n } else if (selectedElements.length === 1) {\n // Only one date is in this month\n if (this.datepickerShowsDate(dates.start, selectedElements[0])) {\n selectedElements[0].classList.add('startRange');\n this.selectRangeFromUntil(selectedElements[0], '');\n } else if (this.datepickerShowsDate(dates.end, selectedElements[0])) {\n let firstDay = jQuery(container).find('.flatpickr-day')[0];\n\n selectedElements[0].classList.add('endRange');\n firstDay.classList.add('inRange');\n\n this.selectRangeFromUntil(firstDay, selectedElements[0]);\n }\n } else if (this.datepickerIsInDateRange(container, dates)) {\n // No date is in this month, but the month is completely between start and end date\n jQuery(container).find('.flatpickr-day').addClass('inRange');\n }\n }\n\n private datepickerShowsDate(date:string, selectedElement:Element):boolean {\n return new Date(selectedElement.getAttribute('aria-label')!).toDateString() === new Date(date).toDateString();\n }\n\n private datepickerIsInDateRange(container:Element, dates:{ [key in DateKeys]:string }):boolean {\n var firstDayOfMonthElement = jQuery(container).find('.flatpickr-day:not(.hidden)')[0];\n var firstDayOfMonth = new Date(firstDayOfMonthElement.getAttribute('aria-label')!);\n\n return firstDayOfMonth <= new Date(dates.end) &&\n firstDayOfMonth >= new Date(dates.start);\n }\n\n private selectRangeFromUntil(from:Element, until:string|Element) {\n jQuery(from).nextUntil(until).addClass('inRange');\n }\n}\n","
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n \n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n\n \n
    \n \n
    \n
    \n \n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n

    \n
    \n \n

    \n
    \n
    \n
    \n
    \n \n \n \n\n
    \n \n \n
    \n
    \n
    \n
    \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n Inject,\n Injector, ViewChild,\n ViewEncapsulation\n} from \"@angular/core\";\nimport {OpModalComponent} from \"core-components/op-modals/op-modal.component\";\nimport {InjectField} from \"core-app/helpers/angular/inject-field.decorator\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {OpModalLocalsMap} from \"core-components/op-modals/op-modal.types\";\nimport {OpModalLocalsToken} from \"core-components/op-modals/op-modal.service\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {DatePicker} from \"core-app/modules/common/op-date-picker/datepicker\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {ResourceChangeset} from \"core-app/modules/fields/changeset/resource-changeset\";\nimport {DatePickerModalHelper} from \"core-components/datepicker/datepicker.modal.helper\";\nimport {BrowserDetector} from \"core-app/modules/common/browser/browser-detector.service\";\nimport {ConfigurationService} from \"core-app/modules/common/config/configuration.service\";\n\nexport type DateKeys = 'date'|'start'|'end';\n\n@Component({\n templateUrl: './datepicker.modal.html',\n styleUrls: ['./datepicker.modal.sass', './datepicker_mobile.modal.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None\n})\nexport class DatePickerModal extends OpModalComponent implements AfterViewInit {\n @InjectField() I18n:I18nService;\n @InjectField() timezoneService:TimezoneService;\n @InjectField() halEditing:HalResourceEditingService;\n @InjectField() datepickerHelper:DatePickerModalHelper;\n @InjectField() browserDetector:BrowserDetector;\n\n @ViewChild('modalContainer') modalContainer:ElementRef;\n\n text = {\n save: this.I18n.t('js.button_save'),\n cancel: this.I18n.t('js.button_cancel'),\n clear: this.I18n.t('js.work_packages.button_clear'),\n manualScheduling: this.I18n.t('js.scheduling.manual'),\n date: this.I18n.t('js.work_packages.properties.date'),\n startDate: this.I18n.t('js.work_packages.properties.startDate'),\n endDate: this.I18n.t('js.work_packages.properties.dueDate'),\n placeholder: this.I18n.t('js.placeholders.default'),\n today: this.I18n.t('js.label_today'),\n isParent: this.I18n.t('js.work_packages.scheduling.is_parent'),\n isSwitchedFromManualToAutomatic: this.I18n.t('js.work_packages.scheduling.is_switched_from_manual_to_automatic')\n };\n public onDataUpdated = new EventEmitter();\n\n public singleDate = false;\n\n public scheduleManually = false;\n\n public htmlId:string = '';\n\n public dates:{ [key in DateKeys]:string } = {\n date: '',\n start: '',\n end: ''\n };\n\n private changeset:ResourceChangeset;\n\n private datePickerInstance:DatePicker;\n\n constructor(readonly injector:Injector,\n @Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly elementRef:ElementRef,\n readonly configurationService:ConfigurationService) {\n super(locals, cdRef, elementRef);\n this.changeset = locals.changeset;\n this.htmlId = `wp-datepicker-${locals.fieldName}`;\n\n this.singleDate = this.changeset.isWritable('date');\n this.scheduleManually = this.changeset.value('scheduleManually');\n\n if (this.singleDate) {\n this.dates.date = this.changeset.value('date');\n this.datepickerHelper.setCurrentActivatedField('date');\n } else {\n this.dates.start = this.changeset.value('startDate');\n this.dates.end = this.changeset.value('dueDate');\n this.datepickerHelper.setCurrentActivatedField(this.initialActivatedField());\n }\n }\n\n ngAfterViewInit():void {\n if (this.isSchedulable) {\n this.showDateSelection();\n }\n\n this.onDataChange();\n }\n\n changeSchedulingMode() {\n this.scheduleManually = !this.scheduleManually;\n this.cdRef.detectChanges();\n\n if (this.scheduleManually) {\n this.showDateSelection();\n } else if (this.isParent) {\n this.removeDateSelection();\n }\n }\n\n save():void {\n if (!this.isSavable) {\n return;\n }\n\n // Apply the changed scheduling mode if any\n this.changeset.setValue('scheduleManually', this.scheduleManually);\n\n // Apply the dates if they could be changed\n if (this.isSchedulable) {\n if (this.singleDate) {\n this.changeset.setValue('date', this.datepickerHelper.mappedDate(this.dates.date));\n } else {\n this.changeset.setValue('startDate', this.datepickerHelper.mappedDate(this.dates.start));\n this.changeset.setValue('dueDate', this.datepickerHelper.mappedDate(this.dates.end));\n }\n }\n\n this.closeMe();\n }\n\n cancel():void {\n this.closeMe();\n }\n\n clear(key:DateKeys):void {\n this.dates[key] = '';\n this.enforceManualChangesToDatepicker();\n }\n\n updateDate(key:DateKeys, val:string) {\n // Expected minimal format YYYY-M-D => 8 characters OR empty\n if (val.length >= 8 || val.length === 0) {\n this.dates[key] = val;\n if (this.datepickerHelper.validDate(val) && this.datePickerInstance) {\n this.enforceManualChangesToDatepicker(false);\n }\n }\n }\n\n setToday(key:DateKeys) {\n let today = this.datepickerHelper.parseDate(new Date());\n this.dates[key] = this.timezoneService.formattedISODate(today);\n\n (today instanceof Date) ? this.enforceManualChangesToDatepicker(true, today) : this.enforceManualChangesToDatepicker();\n }\n\n reposition(element:JQuery, target:JQuery) {\n element.position({\n my: 'left top',\n at: 'left bottom',\n of: target,\n collision: 'flipfit'\n });\n }\n\n setCurrentActivatedField(key:DateKeys) {\n this.datepickerHelper.setCurrentActivatedField(key);\n this.datepickerHelper.setDatepickerRestrictions(this.dates, this.datePickerInstance);\n this.datepickerHelper.setRangeClasses(this.dates);\n }\n\n showTodayLink(key:DateKeys):boolean {\n if (!this.isSchedulable) {\n return false;\n }\n\n if (key === 'start') {\n return this.datepickerHelper.parseDate(new Date()) <= this.datepickerHelper.parseDate(this.dates.end);\n } else {\n return this.datepickerHelper.parseDate(new Date()) >= this.datepickerHelper.parseDate(this.dates.start);\n }\n }\n\n /**\n * Returns whether the user can alter the dates of the work package.\n * The work package is always schedulable if the work package scheduled manually.\n * But it might also be altered in automatic scheduling mode if it does not have children and if there was\n * no switch from manual to automatic scheduling.\n * The later is necessary as we cannot correctly calculate the resulting dates in the frontend.\n */\n get isSchedulable():boolean {\n return this.scheduleManually || (!this.isParent && !this.isSwitchedFromManualToAutomatic);\n }\n\n get isSavable():boolean {\n return this.isSchedulable || this.isSwitchedFromManualToAutomatic;\n }\n\n /**\n * Determines whether the work package is a parent. It does so\n * by checking the children links.\n */\n get isParent():boolean {\n return this.changeset.projectedResource.$links.children && this.changeset.projectedResource.$links.children.length > 0;\n }\n\n get isSwitchedFromManualToAutomatic():boolean {\n return !this.scheduleManually && this.changeset.value('scheduleManually');\n }\n\n private showDateSelection() {\n this.initializeDatepicker();\n this.datepickerHelper.setDatepickerRestrictions(this.dates, this.datePickerInstance);\n this.datepickerHelper.setRangeClasses(this.dates);\n }\n\n private removeDateSelection() {\n this.datePickerInstance.destroy();\n }\n\n private initializeDatepicker() {\n this.datePickerInstance?.destroy();\n this.datePickerInstance = new DatePicker(\n '#flatpickr-input',\n this.singleDate ? this.dates.date : [this.dates.start, this.dates.end],\n {\n mode: this.singleDate ? 'single' : 'multiple',\n showMonths: this.browserDetector.isMobile ? 1 : 2,\n inline: true,\n onChange: (dates:Date[]) => {\n this.handleDatePickerChange(dates);\n\n this.onDataChange();\n },\n onMonthChange: () => { this.datepickerHelper.setRangeClasses(this.dates); },\n onYearChange: () => { this.datepickerHelper.setRangeClasses(this.dates); },\n },\n undefined,\n this.configurationService\n );\n }\n\n private enforceManualChangesToDatepicker(toggleField:boolean = true, enforceDate?:Date) {\n if (this.singleDate) {\n let date = this.datepickerHelper.parseDate(this.dates.date);\n this.datepickerHelper.setDates(date, this.datePickerInstance, enforceDate);\n } else {\n let dates = [this.datepickerHelper.parseDate(this.dates.start), this.datepickerHelper.parseDate(this.dates.end)];\n this.datepickerHelper.setDates(dates, this.datePickerInstance, enforceDate);\n\n this.setRangeClassesAndToggleActiveField(toggleField);\n }\n }\n\n private handleDatePickerChange(dates:Date[]) {\n switch (dates.length) {\n case 0: {\n // In case we removed the only value by clicking on a already selected date within the datepicker:\n if (this.dates.start || this.dates.end) {\n this.setDateAndToggleActiveField(this.dates.start || this.dates.end);\n }\n\n break;\n }\n case 1: {\n if (this.singleDate) {\n this.dates.date = this.timezoneService.formattedISODate(dates[0]);\n } else {\n // In case we removed a value by clicking on a already selected date within the datepicker:\n if (this.dates.start && this.dates.end) {\n // Both dates are the same, so it is correct to only highlight one date\n if (this.dates.start === this.dates.end) {\n return;\n }\n\n // I wanted to set the new start date to the preselected endDate OR\n // I wanted to set the new end date to the preselected startDate\n if ((this.datepickerHelper.isStateOfCurrentActivatedField('start') && this.datepickerHelper.areDatesEqual(this.dates.start, dates[0])) ||\n (this.datepickerHelper.isStateOfCurrentActivatedField('end') && this.datepickerHelper.areDatesEqual(this.dates.end, dates[0]))) {\n\n let otherDateIndex:DateKeys = this.datepickerHelper.isStateOfCurrentActivatedField('start') ? 'end' : 'start';\n this.setDateAndToggleActiveField(this.dates[otherDateIndex]);\n } else {\n // I clicked on the already set start or end date (and thus removed it):\n // We restore both values\n this.enforceManualChangesToDatepicker(true);\n }\n } else {\n // It is the first value we set (either start or end date)\n this.setDateAndToggleActiveField(this.timezoneService.formattedISODate(dates[0]), false);\n }\n }\n\n break;\n }\n case 2: {\n if ((!this.dates.end && this.datepickerHelper.isStateOfCurrentActivatedField('start')) ||\n (!this.dates.start && this.datepickerHelper.isStateOfCurrentActivatedField('end'))) {\n // If we change a start date when no end date is set, we keep only the newly clicked value and not both\n this.overwriteDatePickerWithNewDates([dates[1]]);\n } else {\n // Sort dates so that the start date is always first\n if (dates[0] > dates[1]) {\n dates = this.datepickerHelper.sortDates(dates);\n this.datepickerHelper.setDates(dates, this.datePickerInstance);\n }\n\n let index = this.datepickerHelper.isStateOfCurrentActivatedField('start') ? 0 : 1;\n this.dates[this.datepickerHelper.currentlyActivatedDateField] = this.timezoneService.formattedISODate(dates[index]);\n\n this.setRangeClassesAndToggleActiveField();\n }\n\n break;\n }\n default: {\n // Reset the date picker with the two new values\n if (this.datepickerHelper.isStateOfCurrentActivatedField('start')) {\n this.overwriteDatePickerWithNewDates([dates[2], dates[1]]);\n } else {\n this.overwriteDatePickerWithNewDates([dates[0], dates[2]]);\n }\n\n break;\n }\n }\n\n this.cdRef.detectChanges();\n }\n\n private overwriteDatePickerWithNewDates(dates:Date[]) {\n this.datepickerHelper.setDates(dates, this.datePickerInstance);\n this.handleDatePickerChange(dates);\n }\n\n private setDateAndToggleActiveField(newDate:string, forceDatePickerUpdate:boolean = true) {\n this.dates[this.datepickerHelper.currentlyActivatedDateField] = newDate;\n if (forceDatePickerUpdate) {\n this.datepickerHelper.setDates([this.datepickerHelper.parseDate(newDate)], this.datePickerInstance);\n }\n this.datepickerHelper.toggleCurrentActivatedField(this.dates, this.datePickerInstance);\n }\n\n private setRangeClassesAndToggleActiveField(toggleField:boolean = true) {\n if (toggleField) {\n this.datepickerHelper.toggleCurrentActivatedField(this.dates, this.datePickerInstance);\n }\n this.datepickerHelper.setRangeClasses(this.dates);\n }\n\n private onDataChange() {\n let date = this.dates.date || '';\n let start = this.dates.start || '';\n let end = this.dates.end || '';\n\n let output = this.singleDate ? date : start + ' - ' + end;\n this.onDataUpdated.emit(output);\n }\n\n private initialActivatedField():DateKeys {\n return this.locals.fieldName === 'dueDate' || (this.dates.start && !this.dates.end) ? 'end' : 'start';\n }\n\n}\n","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 {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {WorkPackageWatchersService} from 'core-components/wp-single-view-tabs/watchers-tab/wp-watchers.service';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {AngularTrackingHelpers} from \"core-components/angular/tracking-functions\";\nimport {WorkPackageNotificationService} from \"core-app/modules/work_packages/notifications/work-package-notification.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './watchers-tab.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'wp-watchers-tab',\n})\nexport class WorkPackageWatchersTabComponent extends UntilDestroyedMixin implements OnInit {\n public workPackageId:string;\n public workPackage:WorkPackageResource;\n public trackByHref = AngularTrackingHelpers.trackByHref;\n\n public error = false;\n public noResults:boolean = false;\n public allowedToView = false;\n public allowedToAdd = false;\n public allowedToRemove = false;\n public availableWatchersPath:string;\n private $element:JQuery;\n\n public watching:any[] = [];\n public text = {\n loading: this.I18n.t('js.watchers.label_loading'),\n loadingError: this.I18n.t('js.watchers.label_error_loading'),\n autocomplete: {\n placeholder: this.I18n.t('js.watchers.typeahead_placeholder')\n }\n };\n\n public constructor(readonly I18n:I18nService,\n readonly elementRef:ElementRef,\n readonly wpWatchersService:WorkPackageWatchersService,\n readonly $transition:Transition,\n readonly notificationService:WorkPackageNotificationService,\n readonly loadingIndicator:LoadingIndicatorService,\n readonly cdRef:ChangeDetectorRef,\n readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service) {\n super();\n }\n\n public ngOnInit() {\n this.$element = jQuery(this.elementRef.nativeElement);\n\n this.workPackageId = this.$transition.params('to').workPackageId;\n this\n .apiV3Service\n .work_packages\n .id(this.workPackageId)\n .requireAndStream()\n .pipe(\n this.untilDestroyed()\n )\n .subscribe((wp:WorkPackageResource) => {\n this.workPackage = wp;\n this.loadCurrentWatchers();\n });\n\n this.availableWatchersPath = this.apiV3Service.work_packages.id(this.workPackageId).available_watchers.path;\n }\n\n public loadCurrentWatchers() {\n this.error = false;\n this.allowedToView = !!this.workPackage.watchers;\n this.allowedToAdd = !!this.workPackage.addWatcher;\n this.allowedToRemove = !!this.workPackage.removeWatcher;\n\n if (!this.allowedToView) {\n this.error = true;\n return;\n }\n\n this.wpWatchersService.require(this.workPackage)\n .then((watchers:HalResource[]) => {\n this.watching = watchers;\n this.cdRef.detectChanges();\n })\n .catch((error:any) => {\n this.notificationService.showError(error, this.workPackage);\n });\n }\n\n public set loadingPromise(promise:Promise) {\n this.loadingIndicator.wpDetails.promise = promise;\n }\n\n\n public addWatcher(user:any) {\n this.loadingPromise = this.workPackage.addWatcher.$link.$fetch({ user: { href: user.href } })\n .then(() => {\n // Forcefully reload the resource to update the watch/unwatch links\n // should the current user have been added\n this.wpWatchersService.require(this.workPackage, true);\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .refresh();\n\n this.cdRef.detectChanges();\n })\n .catch((error:any) => this.notificationService.showError(error, this.workPackage));\n }\n\n public removeWatcher(watcher:any) {\n this.workPackage.removeWatcher.$link.$prepare({ user_id: watcher.id })()\n .then(() => {\n _.remove(this.watching, (other:HalResource) => {\n return other.href === watcher.href;\n });\n\n // Forcefully reload the resource to update the watch/unwatch links\n // should the current user have been removed\n this.wpWatchersService.require(this.workPackage, true);\n this\n .apiV3Service\n .work_packages\n .id(this.workPackage)\n .refresh();\n this.cdRef.detectChanges();\n })\n .catch((error:any) => this.notificationService.showError(error, this.workPackage));\n }\n}\n","
    \n
    \n
    \n

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

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

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

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

      Total:

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

      \n \n \n

      \n

      \n \n

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

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

      Total:

      \n
      \n\n
      \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
      \n
      \n
      \n \n
      \n
      \n
      \n
      \n
      \n \n
      \n
      \n
      \n
      \n
      \n \n
      \n
      \n
      \n
      \n
      \n \n
      \n
      \n
      \n \n \n \n {{projectName(item.entry)}} - \n \n \n \n \n \n \n \n \n \n \n \n \n
      \n
      \n
      \n","import {Component, OnInit, Injector, ChangeDetectorRef} from \"@angular/core\";\nimport {FilterOperator} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {WidgetTimeEntriesListComponent} from \"core-app/modules/grids/widgets/time-entries/list/time-entries-list.component\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {ConfirmDialogService} from \"core-components/modals/confirm-dialog/confirm-dialog.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\n\n@Component({\n templateUrl: '../list/time-entries-list.component.html',\n})\nexport class WidgetTimeEntriesProjectComponent extends WidgetTimeEntriesListComponent implements OnInit {\n constructor(readonly injector:Injector,\n readonly timezone:TimezoneService,\n readonly i18n:I18nService,\n readonly pathHelper:PathHelperService,\n readonly confirmDialog:ConfirmDialogService,\n protected readonly cdr:ChangeDetectorRef,\n protected readonly currentProject:CurrentProjectService) {\n super(injector, timezone, i18n, pathHelper, confirmDialog, cdr);\n }\n protected dmFilters():Array<[string, FilterOperator, [string]]> {\n return [['spentOn', '>t-', ['7']] as [string, FilterOperator, [string]],\n ['project_id', '=', [this.currentProject.id]] as [string, FilterOperator, [string]]];\n }\n}\n","\n\n \n \n\n\n
      \n \n \n \n \n \n , \n \n
      \n","import {AbstractWidgetComponent} from \"core-app/modules/grids/widgets/abstract-widget.component\";\nimport {Component, OnInit, ChangeDetectorRef, Injector, ChangeDetectionStrategy} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {TimezoneService} from \"core-components/datetime/timezone.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3ListParameters} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\n\n@Component({\n templateUrl: './subprojects.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WidgetSubprojectsComponent extends AbstractWidgetComponent implements OnInit {\n public text = {\n noResults: this.i18n.t('js.grid.widgets.subprojects.no_results'),\n };\n\n public projects:ProjectResource[];\n\n constructor(readonly halResource:HalResourceService,\n readonly pathHelper:PathHelperService,\n readonly i18n:I18nService,\n protected readonly injector:Injector,\n readonly timezone:TimezoneService,\n readonly apiV3Service:APIV3Service,\n readonly currentProject:CurrentProjectService,\n readonly cdr:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .projects\n .list(this.projectListParams)\n .subscribe((collection) => {\n this.projects = collection.elements as ProjectResource[];\n\n this.cdr.detectChanges();\n });\n }\n\n public get isEditable() {\n return false;\n }\n\n public projectPath(project:ProjectResource) {\n return this.pathHelper.projectPath(project.identifier);\n }\n\n public projectName(project:ProjectResource) {\n return project.name;\n }\n\n public get noEntries() {\n return this.projects && !this.projects.length;\n }\n\n private get projectListParams():Apiv3ListParameters {\n return { sortBy: [['name', 'asc']],\n filters: [['parent_id', '=', [this.currentProject.id!]]] };\n }\n}\n","\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 {MembershipResource} from \"core-app/modules/hal/resources/membership-resource\";\nimport {RoleResource} from \"core-app/modules/hal/resources/role-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Apiv3ListParameters} from \"core-app/modules/apiv3/paths/apiv3-list-resource.interface\";\n\nconst DISPLAYED_MEMBERS_LIMIT = 100;\n\n@Component({\n templateUrl: './members.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n styleUrls: ['./members.component.sass']\n})\nexport class WidgetMembersComponent extends AbstractWidgetComponent implements OnInit {\n public text = {\n add: this.i18n.t('js.grid.widgets.members.add'),\n noResults: this.i18n.t('js.grid.widgets.members.no_results'),\n viewAll: this.i18n.t('js.grid.widgets.members.view_all_members'),\n };\n\n public totalMembers:number;\n public entriesByRoles:{[roleId:string]:{role:RoleResource, users:UserResource[]}} = {};\n private entriesLoaded = false;\n public membersAddable:boolean = false;\n\n constructor(readonly pathHelper:PathHelperService,\n readonly apiV3Service:APIV3Service,\n readonly i18n:I18nService,\n protected readonly injector:Injector,\n readonly currentProject:CurrentProjectService,\n readonly cdr:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this\n .apiV3Service\n .memberships\n .list(this.listMembersParams)\n .subscribe(collection => {\n this.partitionEntriesByRole(collection.elements);\n this.sortUsersByName();\n this.totalMembers = collection.total;\n\n this.entriesLoaded = true;\n this.cdr.detectChanges();\n });\n\n this.apiV3Service\n .memberships\n .available_projects\n .list(this.listAvailableProjectsParams)\n .subscribe(collection => {\n this.membersAddable = collection.total > 0;\n });\n }\n\n public get isEditable() {\n return false;\n }\n\n public 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.apiV3Service.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:Apiv3ListParameters = { sortBy: [['created_at', 'desc']], pageSize: DISPLAYED_MEMBERS_LIMIT };\n\n if (this.currentProject.id) {\n params['filters'] = [['project_id', '=', [this.currentProject.id]]];\n }\n\n return params;\n }\n\n private get listAvailableProjectsParams() {\n // It would make sense to set the pageSize but the backend for projects\n // returns an upaginated list which does not support that.\n let params:Apiv3ListParameters = {};\n\n if (this.currentProject.id) {\n params['filters'] = [['id', '=', [this.currentProject.id]]];\n }\n\n return params;\n }\n}\n","\n\n \n\n \n \n\n\n
      \n \n
      \n \n \n
      \n
      \n \n \n
      \n
      \n
      \n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Injector,\n OnInit,\n ViewChild\n} from '@angular/core';\nimport {AbstractWidgetComponent} from \"app/modules/grids/widgets/abstract-widget.component\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {ProjectResource} from \"core-app/modules/hal/resources/project-resource\";\nimport {WorkPackageViewHighlightingService} from \"core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-highlighting.service\";\nimport {IsolatedQuerySpace} from \"core-app/modules/work_packages/query-space/isolated-query-space\";\nimport {Observable} from \"rxjs\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\n\n@Component({\n templateUrl: './project-status.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n WorkPackageViewHighlightingService,\n IsolatedQuerySpace,\n HalResourceEditingService\n ]\n})\nexport class WidgetProjectStatusComponent extends AbstractWidgetComponent implements OnInit {\n\n @ViewChild('contentContainer', { static: true }) readonly contentContainer:ElementRef;\n\n public currentStatusCode:string = 'not set';\n public explanation:String = '';\n public project$:Observable;\n\n constructor(protected readonly i18n:I18nService,\n protected readonly injector:Injector,\n protected readonly apiV3Service:APIV3Service,\n protected readonly currentProject:CurrentProjectService,\n protected readonly cdRef:ChangeDetectorRef) {\n super(i18n, injector);\n }\n\n ngOnInit() {\n this.project$ = this\n .apiV3Service\n .projects\n .id(this.currentProject.id!)\n .get();\n\n this.cdRef.detectChanges();\n }\n\n public get isEditable() {\n return false;\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Injector, NgModule} from '@angular/core';\nimport {DynamicModule} from 'ng-dynamic-component';\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {BrowserModule} from '@angular/platform-browser';\nimport {FormsModule} from '@angular/forms';\nimport {DragDropModule} from '@angular/cdk/drag-drop';\nimport {OpenprojectWorkPackagesModule} from \"core-app/modules/work_packages/openproject-work-packages.module\";\nimport {WidgetWpCalendarComponent} from \"core-app/modules/grids/widgets/wp-calendar/wp-calendar.component.ts\";\nimport {WidgetTimeEntriesCurrentUserComponent} from \"core-app/modules/grids/widgets/time-entries/current-user/time-entries-current-user.component\";\nimport {GridWidgetsService} from \"core-app/modules/grids/widgets/widgets.service\";\nimport {GridComponent} from \"core-app/modules/grids/grid/grid.component\";\nimport {AddGridWidgetModal} from \"core-app/modules/grids/widgets/add/add.modal\";\nimport {OpenprojectCalendarModule} from \"core-app/modules/calendar/openproject-calendar.module\";\nimport {WidgetDocumentsComponent} from \"core-app/modules/grids/widgets/documents/documents.component\";\nimport {WidgetNewsComponent} from \"core-app/modules/grids/widgets/news/news.component\";\nimport {WidgetWpTableComponent} from \"core-app/modules/grids/widgets/wp-table/wp-table.component\";\nimport {WidgetMenuComponent} from \"core-app/modules/grids/widgets/menu/widget-menu.component\";\nimport {WidgetWpTableMenuComponent} from \"core-app/modules/grids/widgets/wp-table/wp-table-menu.component\";\nimport {GridInitializationService} from \"core-app/modules/grids/grid/initialization.service\";\nimport {WidgetWpGraphComponent} from \"core-app/modules/grids/widgets/wp-graph/wp-graph.component\";\nimport {WidgetWpGraphMenuComponent} from \"core-app/modules/grids/widgets/wp-graph/wp-graph-menu.component\";\nimport {WidgetWpTableQuerySpaceComponent} from \"core-app/modules/grids/widgets/wp-table/wp-table-qs.component\";\nimport {OpenprojectWorkPackageGraphsModule} from \"core-app/modules/work-package-graphs/openproject-work-package-graphs.module\";\nimport {ApiV3FilterBuilder} from \"core-components/api/api-v3/api-v3-filter-builder\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WidgetProjectDescriptionComponent} from \"core-app/modules/grids/widgets/project-description/project-description.component\";\nimport {WidgetHeaderComponent} from \"core-app/modules/grids/widgets/header/header.component\";\nimport {WidgetWpOverviewComponent} from \"core-app/modules/grids/widgets/wp-overview/wp-overview.component\";\nimport {WidgetCustomTextComponent} from \"core-app/modules/grids/widgets/custom-text/custom-text.component\";\nimport {OpenprojectFieldsModule} from \"core-app/modules/fields/openproject-fields.module\";\nimport {WidgetProjectDetailsComponent} from \"core-app/modules/grids/widgets/project-details/project-details.component\";\nimport {WidgetTimeEntriesProjectComponent} from \"core-app/modules/grids/widgets/time-entries/project/time-entries-project.component\";\nimport {WidgetSubprojectsComponent} from \"core-app/modules/grids/widgets/subprojects/subprojects.component\";\nimport {OpenprojectAttachmentsModule} from \"core-app/modules/attachments/openproject-attachments.module\";\nimport {WidgetMembersComponent} from \"core-app/modules/grids/widgets/members/members.component\";\nimport {WidgetProjectStatusComponent} from \"core-app/modules/grids/widgets/project-status/project-status.component\";\nimport {OpenprojectTimeEntriesModule} from \"core-app/modules/time_entries/openproject-time-entries.module\";\nimport {WidgetTimeEntriesCurrentUserMenuComponent} from \"core-app/modules/grids/widgets/time-entries/current-user/time-entries-current-user-menu.component\";\nimport { TimeEntriesCurrentUserConfigurationModalComponent } from './widgets/time-entries/current-user/time-entries-current-user-configuration.modal';\n\n@NgModule({\n imports: [\n BrowserModule,\n FormsModule,\n DragDropModule,\n\n OpenprojectCommonModule,\n OpenprojectWorkPackagesModule,\n OpenprojectWorkPackageGraphsModule,\n OpenprojectCalendarModule,\n OpenprojectTimeEntriesModule,\n\n OpenprojectAttachmentsModule,\n\n DynamicModule.withComponents([\n WidgetCustomTextComponent,\n WidgetDocumentsComponent,\n WidgetMembersComponent,\n WidgetNewsComponent,\n WidgetWpTableQuerySpaceComponent,\n WidgetWpGraphComponent,\n WidgetWpCalendarComponent,\n WidgetWpOverviewComponent,\n WidgetProjectDescriptionComponent,\n WidgetProjectDetailsComponent,\n WidgetProjectStatusComponent,\n WidgetSubprojectsComponent,\n WidgetTimeEntriesCurrentUserComponent,\n WidgetTimeEntriesProjectComponent]),\n\n // Support for inline editig fields\n OpenprojectFieldsModule,\n\n ],\n providers: [\n GridWidgetsService,\n GridInitializationService,\n ],\n declarations: [\n GridComponent,\n\n // Widgets\n WidgetCustomTextComponent,\n WidgetDocumentsComponent,\n WidgetMembersComponent,\n WidgetNewsComponent,\n WidgetWpCalendarComponent,\n WidgetWpOverviewComponent,\n WidgetWpTableComponent,\n WidgetWpTableQuerySpaceComponent,\n WidgetWpGraphComponent,\n WidgetProjectDescriptionComponent,\n WidgetProjectDetailsComponent,\n WidgetProjectStatusComponent,\n WidgetSubprojectsComponent,\n WidgetTimeEntriesCurrentUserComponent,\n WidgetTimeEntriesProjectComponent,\n\n // Widget menus\n WidgetMenuComponent,\n WidgetWpTableMenuComponent,\n WidgetWpGraphMenuComponent,\n WidgetTimeEntriesCurrentUserMenuComponent,\n TimeEntriesCurrentUserConfigurationModalComponent,\n\n AddGridWidgetModal,\n\n WidgetHeaderComponent,\n ],\n exports: [\n GridComponent\n ]\n})\nexport class OpenprojectGridsModule {\n constructor(injector:Injector) {\n registerWidgets(injector);\n }\n}\n\nexport function registerWidgets(injector:Injector) {\n const hookService = injector.get(HookService);\n const i18n = injector.get(I18nService);\n\n hookService.register('gridWidgets', () => {\n\n let defaultColumns = [\"id\", \"project\", \"type\", \"subject\"];\n\n let assignedFilters = new ApiV3FilterBuilder();\n assignedFilters.add('assignee', '=', [\"me\"]);\n assignedFilters.add('status', 'o', []);\n\n let assignedProps = {\n \"columns[]\": defaultColumns,\n \"filters\": assignedFilters.toJson()\n };\n\n let accountableFilters = new ApiV3FilterBuilder();\n accountableFilters.add('responsible', '=', [\"me\"]);\n accountableFilters.add('status', 'o', []);\n\n let accountableProps = {\n \"columns[]\": defaultColumns,\n \"filters\": accountableFilters.toJson()\n };\n\n let createdFilters = new ApiV3FilterBuilder();\n createdFilters.add('author', '=', [\"me\"]);\n createdFilters.add('status', 'o', []);\n\n let createdProps = {\n \"columns[]\": defaultColumns,\n \"filters\": createdFilters.toJson()\n };\n\n let watchedFilters = new ApiV3FilterBuilder();\n watchedFilters.add('watcher', '=', [\"me\"]);\n watchedFilters.add('status', 'o', []);\n\n let watchedProps = {\n \"columns[]\": defaultColumns,\n \"filters\": watchedFilters.toJson()\n };\n\n return [\n {\n identifier: 'work_packages_assigned',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_assigned.title`),\n properties: {\n queryProps: assignedProps,\n name: i18n.t('js.grid.widgets.work_packages_assigned.title')\n }\n },\n {\n identifier: 'work_packages_accountable',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_accountable.title`),\n properties: {\n queryProps: accountableProps,\n name: i18n.t('js.grid.widgets.work_packages_accountable.title')\n }\n },\n {\n identifier: 'work_packages_created',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_created.title`),\n properties: {\n queryProps: createdProps,\n name: i18n.t('js.grid.widgets.work_packages_created.title')\n }\n },\n {\n identifier: 'work_packages_watched',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_watched.title`),\n properties: {\n queryProps: watchedProps,\n name: i18n.t('js.grid.widgets.work_packages_watched.title')\n }\n },\n {\n identifier: 'work_packages_table',\n component: WidgetWpTableQuerySpaceComponent,\n title: i18n.t(`js.grid.widgets.work_packages_table.title`),\n properties: {\n name: i18n.t('js.grid.widgets.work_packages_table.title')\n }\n },\n {\n identifier: 'work_packages_graph',\n component: WidgetWpGraphComponent,\n title: i18n.t(`js.grid.widgets.work_packages_graph.title`),\n properties: {\n name: i18n.t('js.grid.widgets.work_packages_graph.title')\n }\n },\n {\n identifier: 'work_packages_calendar',\n component: WidgetWpCalendarComponent,\n title: i18n.t(`js.grid.widgets.work_packages_calendar.title`),\n properties: {\n name: i18n.t('js.grid.widgets.work_packages_calendar.title')\n }\n },\n {\n identifier: 'work_packages_overview',\n component: WidgetWpOverviewComponent,\n title: i18n.t(`js.grid.widgets.work_packages_overview.title`),\n properties: {\n name: i18n.t('js.grid.widgets.work_packages_overview.title')\n }\n },\n {\n identifier: 'time_entries_current_user',\n component: WidgetTimeEntriesCurrentUserComponent,\n title: i18n.t(`js.grid.widgets.time_entries_current_user.title`),\n properties: {\n name: i18n.t('js.grid.widgets.time_entries_current_user.title'),\n days: [true, true, true, true, true, true, true]\n }\n },\n {\n identifier: 'time_entries_project',\n component: WidgetTimeEntriesProjectComponent,\n title: i18n.t(`js.grid.widgets.time_entries_list.title`),\n properties: {\n name: i18n.t('js.grid.widgets.time_entries_list.title'),\n }\n },\n {\n identifier: 'documents',\n component: WidgetDocumentsComponent,\n title: i18n.t(`js.grid.widgets.documents.title`),\n properties: {\n name: i18n.t('js.grid.widgets.documents.title')\n }\n },\n {\n identifier: 'members',\n component: WidgetMembersComponent,\n title: i18n.t(`js.grid.widgets.members.title`),\n properties: {\n name: i18n.t('js.grid.widgets.members.title')\n }\n },\n {\n identifier: 'news',\n component: WidgetNewsComponent,\n title: i18n.t(`js.grid.widgets.news.title`),\n properties: {\n name: i18n.t('js.grid.widgets.news.title')\n }\n },\n {\n identifier: 'project_description',\n component: WidgetProjectDescriptionComponent,\n title: i18n.t(`js.grid.widgets.project_description.title`),\n properties: {\n name: i18n.t('js.grid.widgets.project_description.title')\n }\n },\n {\n identifier: 'custom_text',\n component: WidgetCustomTextComponent,\n title: i18n.t(`js.grid.widgets.custom_text.title`),\n properties: {\n name: i18n.t('js.grid.widgets.custom_text.title'),\n text: {\n raw: ''\n }\n }\n },\n {\n identifier: 'project_details',\n component: WidgetProjectDetailsComponent,\n title: i18n.t(`js.grid.widgets.project_details.title`),\n properties: {\n name: i18n.t('js.grid.widgets.project_details.title')\n }\n },\n {\n identifier: 'project_status',\n component: WidgetProjectStatusComponent,\n title: i18n.t(`js.grid.widgets.project_status.title`),\n properties: {\n name: i18n.t('js.grid.widgets.project_status.title')\n }\n },\n {\n identifier: 'subprojects',\n component: WidgetSubprojectsComponent,\n title: i18n.t(`js.grid.widgets.subprojects.title`),\n properties: {\n name: i18n.t('js.grid.widgets.subprojects.title')\n }\n }\n ];\n });\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 name: 'backlogs.**',\n parent: 'root',\n url: '/backlogs',\n loadChildren: () => import('../backlogs/openproject-backlogs.module').then(m => m.OpenprojectBacklogsModule)\n },\n {\n name: 'backlogs_sprint.**',\n parent: 'root',\n url: '/sprints',\n loadChildren: () => import('../backlogs/openproject-backlogs.module').then(m => m.OpenprojectBacklogsModule)\n },\n {\n name: 'reporting.**',\n parent: 'root',\n url: '/cost_reports',\n loadChildren: () => import('../reporting/openproject-reporting.module').then(m => m.OpenprojectReportingModule)\n },\n {\n name: 'job-statuses.**',\n parent: 'root',\n url: '/job_statuses',\n loadChildren: () => import('../job-status/openproject-job-status.module').then(m => m.OpenProjectJobStatusModule)\n },\n];\n\n/**\n * Add or remove a body class. Helper for ui-router body classes functionality\n *\n * @param className\n * @param action\n */\nexport function bodyClass(className:string[]|string|null|undefined, action:'add'|'remove' = 'add') {\n if (className) {\n if (Array.isArray(className)) {\n className.forEach((cssClass:string) => {\n document.body.classList[action](cssClass);\n });\n } else {\n document.body.classList[action](className);\n }\n }\n}\n\nexport function updateMenuItem(menuItemClass:string|undefined, action:'add'|'remove' = 'add') {\n if (!menuItemClass) {\n return;\n }\n\n let menuItem = jQuery('#main-menu .' + menuItemClass)[0];\n\n if (!menuItem) {\n return;\n }\n\n // Update Class\n menuItem.classList[action]('selected');\n\n // Update accessibility label\n let menuItemTitle = (menuItem.getAttribute('title') || '').split(':').slice(-1)[0];\n if (action === 'add') {\n menuItemTitle = I18n.t('js.description_current_position') + menuItemTitle;\n }\n\n menuItem.setAttribute('title', menuItemTitle);\n}\n\nexport function uiRouterConfiguration(uiRouter:UIRouter, injector:Injector, module:StatesModule) {\n // Allow optional trailing slashes\n uiRouter.urlService.config.strictMode(false);\n\n // Register custom URL params type\n // to ensure query props are correctly set\n uiRouter.urlService.config.type(\n 'opQueryString',\n {\n encode: encodeURIComponent,\n decode: decodeURIComponent,\n raw: true,\n dynamic: true,\n is: (val:unknown) => typeof (val) === 'string',\n equals: (a:any, b:any) => _.isEqual(a, b),\n }\n );\n}\n\nexport function initializeUiRouterListeners(injector:Injector) {\n const $transitions:TransitionService = injector.get(TransitionService);\n const stateService = injector.get(StateService);\n const notificationsService:NotificationsService = injector.get(NotificationsService);\n const currentProject:CurrentProjectService = injector.get(CurrentProjectService);\n const firstRoute:FirstRouteService = injector.get(FirstRouteService);\n const backRoutingService:BackRoutingService = injector.get(BackRoutingService);\n\n // Check whether we are running within our complete app, or only within some other bootstrapped\n // component\n let wpBase = document.querySelector(appBaseSelector);\n\n // Uncomment to trace route changes\n // const uiRouter = injector.get(UIRouter);\n // uiRouter.trace.enable();\n\n // Apply classes from bodyClasses in each state definition\n // This was defined as onEnter, onExit functions in each state before\n // but since AOT doesn't allow anonymous functions, we can't re-use them now.\n // The transition will only return the target state on `transition.to()`,\n // however the second parameter has the currently (e.g., parent) entering state chain.\n $transitions.onEnter({}, function (transition:Transition, state:StateDeclaration) {\n // Add body class when entering this state\n bodyClass(_.get(state, 'data.bodyClasses'), 'add');\n if (transition.from().data && _.get(state, 'data.menuItem') !== transition.from().data.menuItem) {\n updateMenuItem(_.get(state, 'data.menuItem'), 'add');\n }\n\n // Reset scroll position, mostly relevant for mobile\n window.scrollTo(0, 0);\n });\n\n $transitions.onExit({}, function (transition:Transition, state:StateDeclaration) {\n // Remove body class when leaving this state\n bodyClass(_.get(state, 'data.bodyClasses'), 'remove');\n if (transition.to().data && _.get(state, 'data.menuItem') !== transition.to().data.menuItem) {\n updateMenuItem(_.get(state, 'data.menuItem'), 'remove');\n }\n });\n\n $transitions.onStart({}, function (transition:Transition) {\n const $state = transition.router.stateService;\n const toParams = transition.params('to');\n const fromState = transition.from();\n const toState = transition.to();\n\n // Remove start_onboarding_tour param if set\n if (toParams.start_onboarding_tour && toState.name !== 'work-packages.partitioned.list') {\n const paramsCopy = Object.assign({}, transition.params());\n paramsCopy.start_onboarding_tour = undefined;\n return $state.target(transition.to(), paramsCopy);\n }\n\n // Set backRoute to know where we came from\n backRoutingService.sync(transition);\n\n // Reset profiler, if we're actually profiling\n const profiler:any = (window as any).MiniProfiler;\n profiler && profiler.pageTransition();\n\n const projectIdentifier = toParams.projectPath || currentProject.identifier;\n if (!toParams.projects && projectIdentifier) {\n const newParams = _.clone(toParams);\n _.assign(newParams, { projectPath: projectIdentifier, projects: 'projects' });\n return $state.target(toState, newParams, { location: 'replace' });\n }\n\n // Abort the transition and move to the url instead\n // Only move to the URL if we're not coming from an initial URL load\n // (cases like /work_packages/invalid/activity which render a 403 without frontend,\n // but trigger the ui-router state)\n //\n // The FirstRoute service remembers the first angular route we went to\n // but for pages without any angular routes, this will stay empty.\n // So we also allow routes to happen after some delay\n if (wpBase === null) {\n\n // Get the current path and compare\n const path = window.location.pathname;\n const pathWithSearch = path + window.location.search;\n const target = stateService.href(toState, toParams);\n\n if (target && path !== target && pathWithSearch !== target) {\n window.location.href = target;\n return false;\n }\n }\n\n // Remove and add any body class definitions for entering\n // and exiting states.\n bodyClass(_.get(toState, 'data.bodyClasses'), 'add');\n\n // We need to distinguish between actions that should run on the initial page load\n // (ie. openining a new tab in the details view should focus on the element in the table)\n // so we need to know which route we visited initially\n firstRoute.setIfFirst(toState.name, toParams);\n\n // Clear all notifications when actually moving between states.\n if (transition.to().name !== transition.from().name) {\n notificationsService.clear();\n }\n\n // Add new notifications if passed to params\n if (toParams.flash_message) {\n notificationsService.add(toParams.flash_message as INotification);\n }\n\n return true;\n });\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 private _currentTab = new BehaviorSubject('all');\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'&& this.currentTab !== 'work_packages') {\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 {AfterViewInit, Component, ElementRef, OnInit} from '@angular/core';\nimport {TypeBannerService} from 'core-app/modules/admin/types/type-banner.service';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {NotificationsService} from 'core-app/modules/common/notifications/notifications.service';\nimport {ExternalRelationQueryConfigurationService} from 'core-components/wp-table/external-configuration/external-relation-query-configuration.service';\nimport {DomAutoscrollService} from 'core-app/modules/common/drag-and-drop/dom-autoscroll.service';\nimport {DragulaService, DrakeWithModels} from 'ng2-dragula';\nimport {ConfirmDialogService} from 'core-components/modals/confirm-dialog/confirm-dialog.service';\nimport {Drake} from 'dragula';\nimport {GonService} from \"core-app/modules/common/gon/gon.service\";\nimport {UntilDestroyedMixin} from \"core-app/helpers/angular/until-destroyed.mixin\";\nimport {install_menu_logic} from \"core-app/globals/global-listeners/action-menu\";\n\nexport type TypeGroupType = 'attribute'|'query';\n\nexport interface TypeFormAttribute {\n key:string;\n translation:string;\n is_cf:boolean;\n}\n\nexport interface TypeGroup {\n /** original internal key, if any */\n key:string|null|undefined;\n /** Localized / given name */\n name:string;\n attributes:TypeFormAttribute[];\n query?:any;\n type:TypeGroupType;\n}\n\nexport const adminTypeFormConfigurationSelector = 'admin-type-form-configuration';\nexport const emptyTypeGroup = '__empty';\n\n@Component({\n selector: adminTypeFormConfigurationSelector,\n templateUrl: './type-form-configuration.html',\n providers: [\n TypeBannerService,\n ]\n})\nexport class TypeFormConfigurationComponent extends UntilDestroyedMixin implements OnInit, AfterViewInit {\n\n public text = {\n drag_to_activate: this.I18n.t('js.admin.type_form.drag_to_activate'),\n reset: this.I18n.t('js.admin.type_form.reset_to_defaults'),\n label_group: this.I18n.t('js.label_group'),\n new_group: this.I18n.t('js.admin.type_form.new_group'),\n label_inactive: this.I18n.t('js.admin.type_form.inactive'),\n custom_field: this.I18n.t('js.admin.type_form.custom_field'),\n add_group: this.I18n.t('js.admin.type_form.add_group'),\n add_table: this.I18n.t('js.admin.type_form.add_table'),\n };\n\n private autoscroll:any;\n private element:HTMLElement;\n private form:JQuery;\n private submit:JQuery;\n\n public groups:TypeGroup[] = [];\n public inactives:TypeFormAttribute[] = [];\n\n private attributeDrake:DrakeWithModels;\n private groupsDrake:DrakeWithModels;\n\n private no_filter_query:string;\n\n constructor(private elementRef:ElementRef,\n private I18n:I18nService,\n private Gon:GonService,\n private dragula:DragulaService,\n private confirmDialog:ConfirmDialogService,\n private notificationsService:NotificationsService,\n private externalRelationQuery:ExternalRelationQueryConfigurationService) {\n super();\n }\n\n ngOnInit():void {\n // Hook on form submit\n this.element = this.elementRef.nativeElement;\n this.no_filter_query = this.element.dataset.noFilterQuery!;\n this.form = jQuery(this.element).closest('form');\n this.submit = this.form.find('.form-configuration--save');\n\n // In the following we are triggering the form submit ourselves to work around\n // a firefox shortcoming. But to avoid double submits which are sometimes not canceled fast\n // enough, we need to memoize whether we have already submitted.\n let submitted = false;\n\n this.form.on('submit', (event) => {\n submitted = true;\n });\n\n // Capture mousedown on button because firefox breaks blur on click\n this.submit.on('mousedown', (event) => {\n setTimeout(() => {\n if (!submitted) {\n this.form.trigger('submit');\n }\n }, 50);\n return true;\n });\n\n // Capture regular form submit\n this.form.on('submit.typeformupdater', () => {\n this.updateHiddenFields();\n return true;\n });\n\n // Setup groups\n this.groupsDrake = this\n .dragula\n .createGroup('groups', {\n moves: (el, source, handle:HTMLElement) => handle.classList.contains('group-handle')\n })\n .drake;\n\n // Setup attributes\n this.attributeDrake = this\n .dragula\n .createGroup('attributes', {\n moves: (el, source, handle:HTMLElement) => handle.classList.contains('attribute-handle')\n })\n .drake;\n\n // Get attribute id\n this.groups = JSON\n .parse(this.element.dataset.activeGroups!)\n .filter((group:TypeGroup) => group?.key !== emptyTypeGroup);\n this.inactives = JSON.parse(this.element.dataset.inactiveAttributes!);\n\n // Setup autoscroll\n const that = this;\n this.autoscroll = new DomAutoscrollService(\n [\n document.getElementById('content-wrapper')!\n ],\n {\n margin: 25,\n maxSpeed: 10,\n scrollWhenOutside: true,\n autoScroll: function (this:any) {\n const groups = that.groupsDrake && that.groupsDrake.dragging;\n const attributes = that.attributeDrake && that.attributeDrake.dragging;\n\n return groups || attributes;\n }\n });\n }\n\n ngAfterViewInit() {\n const menu = jQuery(this.elementRef.nativeElement).find('.toolbar-items');\n install_menu_logic(menu);\n }\n\n public deactivateAttribute(attribute:TypeFormAttribute) {\n this.updateInactives(this.inactives.concat(attribute));\n }\n\n public addGroupAndOpenQuery():void {\n let newGroup = this.createGroup('query');\n this.editQuery(newGroup);\n }\n\n public editQuery(group:TypeGroup) {\n // Disable display mode and timeline for now since we don't want users to enable it\n const disabledTabs = {\n 'display-settings': I18n.t('js.work_packages.table_configuration.embedded_tab_disabled'),\n 'timelines': I18n.t('js.work_packages.table_configuration.embedded_tab_disabled')\n };\n\n this.externalRelationQuery.show({\n currentQuery: JSON.parse(group.query),\n callback: (queryProps:any) => group.query = JSON.stringify(queryProps),\n disabledTabs\n });\n }\n\n public deleteGroup(group:TypeGroup) {\n if (group.type === 'attribute') {\n this.updateInactives(this.inactives.concat(group.attributes));\n }\n\n this.groups = this.groups.filter(el => el !== group);\n\n return group;\n }\n\n public createGroup(type:TypeGroupType, groupName:string = '') {\n let group:TypeGroup = {\n type: type,\n name: '',\n key: null,\n query: this.no_filter_query,\n attributes: [],\n };\n\n this.groups.unshift(group);\n return group;\n }\n\n public resetToDefault($event:Event):boolean {\n this.confirmDialog\n .confirm({\n text: {\n title: this.I18n.t('js.types.attribute_groups.reset_title'),\n text: this.I18n.t('js.types.attribute_groups.confirm_reset'),\n button_continue: this.I18n.t('js.label_reset')\n }\n })\n .then(() => {\n this.form.find('input#type_attribute_groups').val(JSON.stringify([]));\n\n // Disable our form handler that updates the attribute groups\n this.form.off('submit.typeformupdater');\n this.form.trigger('submit');\n });\n\n $event.preventDefault();\n return false;\n }\n\n private updateInactives(newValue:TypeFormAttribute[]) {\n this.inactives = [...newValue].sort((a, b) => a.translation.localeCompare(b.translation));\n }\n\n // We maintain an empty group\n // that gets hidden in the frontend in case the user\n // decides to remove all groups\n // This was necessary since the \"default\" is actually an empty array of groups\n private get emptyGroup():TypeGroup {\n return { type: 'attribute', key: emptyTypeGroup, name: 'empty', attributes: [] };\n }\n\n private updateHiddenFields() {\n const hiddenField = this.form.find('.admin-type-form--hidden-field');\n if (this.groups.length === 0) {\n // Ensure we're adding an empty group if deliberately removing\n // all values.\n hiddenField.val(JSON.stringify([this.emptyGroup]));\n } else {\n hiddenField.val(JSON.stringify(this.groups));\n }\n }\n}\n\n","
      \n
      \n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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","import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {ExternalQueryConfigurationService} from \"core-components/wp-table/external-configuration/external-query-configuration.service\";\nimport {UrlParamsHelperService} from \"core-components/wp-query/url-params-helper\";\n\nexport const editableQueryPropsSelector = 'editable-query-props';\n\n@Component({\n selector: editableQueryPropsSelector,\n templateUrl: './editable-query-props.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class EditableQueryPropsComponent implements OnInit {\n id:string|null;\n name:string|null;\n urlParams:boolean = false;\n\n queryProps:string;\n\n text = {\n edit_query: this.I18n.t('js.admin.type_form.edit_query')\n };\n\n constructor(private elementRef:ElementRef,\n private I18n:I18nService,\n private cdRef:ChangeDetectorRef,\n private urlParamsHelper:UrlParamsHelperService,\n private externalQuery:ExternalQueryConfigurationService) {\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement;\n this.id = element.dataset.id;\n this.name = element.dataset.name;\n this.urlParams = element.dataset.urlParams === 'true';\n\n this.queryProps = element.dataset.query;\n }\n\n public editQuery() {\n let queryProps:any = this.queryProps;\n\n if (!this.urlParams) {\n try {\n queryProps = JSON.parse(this.queryProps);\n } catch (e) {\n console.error(`Failed to parse query props from ${this.queryProps}: ${e}`);\n queryProps = {};\n }\n }\n\n this.externalQuery.show({\n currentQuery: queryProps,\n urlParams: this.urlParams,\n callback: (queryProps:any) => {\n this.queryProps = this.urlParams ? queryProps : JSON.stringify(queryProps);\n this.cdRef.detectChanges();\n }\n });\n }\n}","\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {NgModule} from '@angular/core';\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {TypeFormConfigurationComponent} from 'core-app/modules/admin/types/type-form-configuration.component';\nimport {GroupEditInPlaceComponent} from 'core-app/modules/admin/types/group-edit-in-place.component';\nimport {TypeFormAttributeGroupComponent} from 'core-app/modules/admin/types/attribute-group.component';\nimport {DragulaModule} from 'ng2-dragula';\nimport {TypeFormQueryGroupComponent} from \"core-app/modules/admin/types/query-group.component\";\nimport {OpenprojectAccessibilityModule} from \"core-app/modules/a11y/openproject-a11y.module\";\nimport {EditableQueryPropsComponent} from \"core-app/modules/admin/editable-query-props/editable-query-props.component\";\n\n@NgModule({\n imports: [\n DragulaModule.forRoot(),\n OpenprojectCommonModule,\n OpenprojectAccessibilityModule\n ],\n providers: [\n ],\n declarations: [\n TypeFormAttributeGroupComponent,\n TypeFormQueryGroupComponent,\n TypeFormConfigurationComponent,\n GroupEditInPlaceComponent,\n EditableQueryPropsComponent,\n ]\n})\nexport class OpenprojectAdminModule { }\n","
      \n
      \n
      \n \n \n \n \n

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

      \n
      \n\n
        \n
      • \n \n
      • \n
      • \n \n
      • \n
      \n
      \n
      \n\n\n","import {Component} from '@angular/core';\nimport {GridPageComponent} from \"core-app/modules/grids/grid/page/grid-page.component\";\nimport {GRID_PROVIDERS} from \"core-app/modules/grids/grid/grid.component\";\n\n@Component({\n selector: 'dashboard',\n templateUrl: '../../grids/grid/page/grid-page.component.html',\n styleUrls: ['../../grids/grid/page/grid-page.component.sass'],\n providers: GRID_PROVIDERS\n})\nexport class DashboardComponent extends GridPageComponent {\n protected i18nNamespace():string {\n return 'dashboards';\n }\n\n protected gridScopePath():string {\n return this.pathHelper.projectDashboardsPath(this.currentProject.identifier!);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {StateService} from \"@uirouter/core\";\n\n@Component({\n templateUrl: './wp-preview.modal.html',\n styleUrls: ['./wp-preview.modal.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class WpPreviewModal extends OpModalComponent implements OnInit {\n public workPackage:WorkPackageResource;\n\n public text = {\n created_by: this.i18n.t('js.label_created_by'),\n };\n\n constructor(readonly elementRef:ElementRef,\n @Inject(OpModalLocalsToken) readonly locals:OpModalLocalsMap,\n readonly cdRef:ChangeDetectorRef,\n readonly i18n:I18nService,\n readonly apiV3Service:APIV3Service,\n readonly opModalService:OpModalService,\n readonly $state:StateService) {\n super(locals, cdRef, elementRef);\n }\n\n ngOnInit() {\n super.ngOnInit();\n const workPackageLink = this.locals.workPackageLink;\n const workPackageId = HalResource.idFromLink(workPackageLink);\n\n this\n .apiV3Service\n .work_packages\n .id(workPackageId)\n .requireAndStream()\n .subscribe((workPackage:WorkPackageResource) => {\n this.workPackage = workPackage;\n this.cdRef.detectChanges();\n\n const modal = jQuery(this.elementRef.nativeElement).find('.preview-modal--container');\n this.reposition(modal, this.locals.event.target);\n });\n }\n\n public reposition(element:JQuery, target:JQuery) {\n element.position({\n my: 'right top',\n at: 'right bottom',\n of: target,\n collision: 'flipfit'\n });\n }\n\n public openStateLink(event:{ workPackageId:string; requestedState:string }) {\n const params = { workPackageId: event.workPackageId };\n\n this.$state.go(event.requestedState, params);\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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 '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\";\nimport {ImageHelpers} from \"core-app/helpers/images/path-helper\";\nimport imagePath = ImageHelpers.imagePath;\n\nexport const homescreenNewFeaturesBlockSelector = 'homescreen-new-features-block';\n\n@Component({\n template: `\n

      \n {{ text.descriptionNewFeatures }}\n

      \n
      \n

      \n \n \n
      \n\n {{ text.learnAbout }}\n `,\n selector: homescreenNewFeaturesBlockSelector,\n styleUrls: ['./new-features.component.sass'],\n})\n\n\n/**\n * Component for the homescreen block to promote new features.\n * When updating this for the next release, be sure to cleanup stuff is not needed any more:\n * Locals (js-en.yml), Styles (new-features.component.sass), HTML (above), TS (below)\n */\nexport class HomescreenNewFeaturesBlockComponent {\n public isStandardEdition:boolean;\n new_features_image = ImageHelpers.imagePath('new_features.png');\n public text = {\n newFeatures: this.i18n.t('js.label_new_features'),\n descriptionNewFeatures: this.i18n.t('js.homescreen.blocks.new_features.text_new_features'),\n learnAbout: this.i18n.t('js.homescreen.blocks.new_features.learn_about'),\n };\n\n constructor(\n readonly i18n:I18nService,\n readonly domSanitizer:DomSanitizer\n ) {\n this.isStandardEdition = window.OpenProject.isStandardEdition;\n }\n\n public get teaserWebsiteUrl() {\n let url = this.translated('learn_about_link');\n return this.domSanitizer.bypassSecurityTrustResourceUrl(url);\n }\n\n public get currentNewFeatureHtml():string {\n return this.translated('current_new_feature_html');\n }\n\n private translated(key:string):string {\n return this.i18n.t(this.i18nBase + this.i18nPrefix + '.' + key, { list_styling_class: 'widget-box--arrow-links', bcf_api_link: BcfRestApi});\n }\n\n private i18nBase:string = 'js.homescreen.blocks.new_features.';\n\n private get i18nPrefix():string {\n return this.isStandardEdition ? \"standard\" : \"bim\";\n }\n}\n","export const BcfRestApi = \"https://github.com/opf/openproject/blob/dev/docs/api/bcf/bcf-rest-api.md\";\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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, { defaultValue: tab.label }),\n path: tab.path\n };\n });\n\n // highlight current tab\n this.currentTabId = this.currentTab.name;\n }\n}\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public 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 \n
      \n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostListener,\n OnDestroy,\n OnInit,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport {ContainHelpers} from 'core-app/modules/common/focus/contain-helpers';\nimport {I18nService} from 'core-app/modules/common/i18n/i18n.service';\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {HalResourceService} from \"core-app/modules/hal/services/hal-resource.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {GlobalSearchService} from \"core-app/modules/global_search/services/global-search.service\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\nimport {DeviceService} from \"core-app/modules/common/browser/device.service\";\nimport {NgSelectComponent} from \"@ng-select/ng-select\";\nimport {Observable, of} from \"rxjs\";\nimport {Highlighting} from \"core-components/wp-fast-table/builders/highlighting/highlighting.functions\";\nimport {HalResourceNotificationService} from \"core-app/modules/hal/services/hal-resource-notification.service\";\nimport {DebouncedRequestSwitchmap, errorNotificationHandler} from \"core-app/helpers/rxjs/debounced-input-switchmap\";\nimport {LinkHandling} from \"core-app/modules/common/link-handling/link-handling\";\nimport {filter, map, take, tap} from \"rxjs/operators\";\nimport {APIV3Service} from \"../../apiv3/api-v3.service\";\nimport { HalResource } from 'core-app/modules/hal/resources/hal-resource';\n\nexport const globalSearchSelector = 'global-search-input';\n\ninterface SearchResultItem {\n id:string;\n subject:string;\n status:string;\n statusId:string;\n $href:string;\n project:string;\n author:HalResource;\n}\n\ninterface SearchOptionItem {\n projectScope:string;\n text:string;\n}\n\n@Component({\n selector: globalSearchSelector,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './global-search-input.component.html',\n styleUrls: ['./global-search-input.component.sass', \"./global-search-input-mobile.component.sass\"],\n // Necessary because of ng-select\n encapsulation: ViewEncapsulation.None\n})\nexport class GlobalSearchInputComponent implements OnInit, OnDestroy {\n @ViewChild('btn', { static: true }) btn:ElementRef;\n @ViewChild(NgSelectComponent, { static: true }) public ngSelectComponent:NgSelectComponent;\n\n public expanded:boolean = false;\n public markable = false;\n\n /** Keep a switchmap for search term and loading state */\n public requests = new DebouncedRequestSwitchmap(\n (searchTerm:string) => this.autocompleteWorkPackages(searchTerm).pipe(\n tap(() => {\n setTimeout(() => this.setMarkedOption(), 50);\n })\n ),\n errorNotificationHandler(this.halNotification)\n );\n\n /** Remember the current value */\n public currentValue:string = '';\n\n /** Remember the item that best matches the query.\n * That way, it will be highlighted (as we manually mark the selected item) and we can handle enter.\n * */\n public selectedItem:SearchResultItem|SearchOptionItem|null;\n\n private unregisterGlobalListener:Function|undefined;\n\n public text:{ [key:string]:string } = {\n all_projects: this.I18n.t('js.global_search.all_projects'),\n current_project: this.I18n.t('js.global_search.current_project'),\n current_project_and_all_descendants: this.I18n.t('js.global_search.current_project_and_all_descendants'),\n search: this.I18n.t('js.global_search.search'),\n search_dots: this.I18n.t('js.global_search.search') + ' ...',\n close_search: this.I18n.t('js.global_search.close_search')\n };\n\n constructor(readonly elementRef:ElementRef,\n readonly I18n:I18nService,\n readonly apiV3Service:APIV3Service,\n readonly PathHelperService:PathHelperService,\n readonly halResourceService:HalResourceService,\n readonly globalSearchService:GlobalSearchService,\n readonly currentProjectService:CurrentProjectService,\n readonly deviceService:DeviceService,\n readonly cdRef:ChangeDetectorRef,\n readonly halNotification:HalResourceNotificationService) {\n }\n\n ngOnInit() {\n // check searchterm on init, expand / collapse search bar and set correct classes\n this.ngSelectComponent.searchTerm = this.currentValue = this.globalSearchService.searchTerm;\n this.expanded = (this.ngSelectComponent.searchTerm.length > 0);\n this.toggleTopMenuClass();\n }\n\n ngOnDestroy() {\n this.unregister();\n }\n\n // detect if click is outside or inside the element\n @HostListener('click', ['$event'])\n public handleClick(event:JQuery.TriggeredEvent):void {\n event.stopPropagation();\n event.preventDefault();\n\n // handle click on search button\n if (ContainHelpers.insideOrSelf(this.btn.nativeElement, event.target)) {\n if (this.deviceService.isMobile) {\n this.toggleMobileSearch();\n // open ng-select menu on default\n jQuery('.ng-input input').focus();\n } else if (this.ngSelectComponent.searchTerm.length === 0) {\n this.ngSelectComponent.focus();\n } else {\n this.submitNonEmptySearch();\n }\n }\n }\n\n // open or close mobile search\n public toggleMobileSearch() {\n this.expanded = !this.expanded;\n this.toggleTopMenuClass();\n }\n\n public redirectToWp(id:string, event:MouseEvent) {\n event.stopImmediatePropagation();\n if (LinkHandling.isClickedWithModifier(event)) {\n return true;\n }\n\n window.location.href = this.wpPath(id);\n event.preventDefault();\n return false;\n }\n\n public wpPath(id:string) {\n return this.PathHelperService.workPackagePath(id);\n }\n\n public search($event:any) {\n this.currentValue = this.ngSelectComponent.searchTerm;\n this.openCloseMenu($event.term);\n }\n\n // close menu when input field is empty\n public openCloseMenu(searchedTerm:string) {\n this.ngSelectComponent.isOpen = (searchedTerm.trim().length > 0);\n }\n\n public onFocus() {\n this.expanded = true;\n this.toggleTopMenuClass();\n this.openCloseMenu(this.currentValue);\n }\n\n public onFocusOut() {\n if (!this.deviceService.isMobile) {\n this.expanded = (this.ngSelectComponent.searchTerm.length > 0);\n this.ngSelectComponent.isOpen = false;\n this.toggleTopMenuClass();\n }\n }\n\n public clearSearch() {\n this.currentValue = this.ngSelectComponent.searchTerm = '';\n this.openCloseMenu(this.currentValue);\n }\n\n // If Enter key is pressed before result list is loaded, wait for the results to come\n // in and then decide what to do. If a direct hit is present, follow that. Otherwise,\n // go to the search in the current scope.\n public onEnterBeforeResultsLoaded() {\n this.requests.loading$.pipe(\n filter(value => value === false),\n take(1)\n )\n .subscribe(() => {\n if (this.selectedItem) {\n this.followSelectedItem();\n } else {\n this.searchInScope(this.currentScope);\n }\n });\n }\n\n public statusHighlighting(statusId:string) {\n return Highlighting.inlineClass('status', statusId);\n }\n\n private get isDirectHit() {\n return this.selectedItem && this.selectedItem.hasOwnProperty('id');\n }\n\n public followItem(item:SearchResultItem|SearchOptionItem) {\n if (item.hasOwnProperty('id')) {\n window.location.href = this.wpPath((item as SearchResultItem).id);\n } else {\n // update embedded table and title when new search is submitted\n this.globalSearchService.searchTerm = this.currentValue;\n this.searchInScope((item as SearchOptionItem).projectScope);\n }\n }\n\n public followSelectedItem() {\n if (this.selectedItem) {\n this.followItem(this.selectedItem);\n }\n }\n\n // return all project scope items and all items which contain the search term\n public customSearchFn(term:string, item:any):boolean {\n return item.id === undefined || item.subject.toLowerCase().indexOf(term.toLowerCase()) !== -1;\n }\n\n private autocompleteWorkPackages(query:string):Observable<(SearchResultItem|SearchOptionItem)[]> {\n if (!query) {\n return of([]);\n }\n\n // Reset the currently selected item.\n // We do not follow the typical goal of an autocompleter of \"setting a value\" here.\n this.selectedItem = null;\n // Hide highlighting of ng-option\n this.markable = false;\n\n\n let hashFreeQuery = this.queryWithoutHash(query);\n\n return this\n .fetchSearchResults(hashFreeQuery, hashFreeQuery !== query)\n .get()\n .pipe(\n map((collection) => {\n return this.searchResultsToOptions(collection.elements, hashFreeQuery);\n })\n );\n }\n\n // Remove ID marker # when searching for #\n private queryWithoutHash(query:string) {\n if (query.match(/^#(\\d+)/)) {\n return query.substr(1);\n } else {\n return query;\n }\n }\n\n private fetchSearchResults(query:string, idOnly:boolean) {\n return this\n .apiV3Service\n .work_packages\n .filterBySubjectOrId(query, idOnly);\n }\n\n private searchResultsToOptions(results:WorkPackageResource[], query:string) {\n let searchItems = results.map((wp) => {\n let item = {\n id: wp.id!,\n subject: wp.subject,\n status: wp.status.name,\n statusId: wp.status.idFromLink,\n $href: wp.$href,\n project: wp.project.name,\n author: wp.author\n } as SearchResultItem;\n\n // If we have a direct hit, we choose it to be the selected element.\n if (query === wp.id!.toString()) {\n this.selectedItem = item;\n }\n\n return item;\n });\n\n let searchOptions = this.detailedSearchOptions();\n\n if (!this.selectedItem) {\n this.selectedItem = searchOptions[0];\n }\n\n return (searchOptions as (SearchResultItem|SearchOptionItem)[]).concat(searchItems);\n }\n\n // set the possible 'search in scope' options for the current project path\n private detailedSearchOptions() {\n let searchOptions = [];\n // add all options when searching within a project\n // otherwise search in 'all projects'\n if (this.currentProjectService.path) {\n searchOptions.push('current_project_and_all_descendants');\n searchOptions.push('current_project');\n }\n if (this.globalSearchService.projectScope === 'current_project') {\n searchOptions.reverse();\n }\n searchOptions.push('all_projects');\n\n return searchOptions.map((suggestion:string) => {\n return { projectScope: suggestion, text: this.text[suggestion] };\n });\n }\n\n /*\n * Set the marked ng-option within ng-select and apply the class to highlight marked options.\n *\n * ng-select differentiates between the selected and the marked option. The selected optinon is the option\n * that is binded via ng-model. The marked option is the one that the user is currently selecting (via mouse or keyboard up/down).\n * When hitting enter, the marked option is taken to be the new selected option. Ng-select will retain the index of the marked\n * option between individual searches. The selected option has no influence on the marked option. This is problematic\n * in our use case as the user might have:\n * * the mouse hovering (deliberately or not) over the search options which will mark that option.\n * * marked an option for a previous search but might then have decided to add/remove additional characters to the search.\n *\n * In both cases, whenever the user presses enter then, ng-select assigns the marked option to the ng-model.\n *\n * Our goal however is to either:\n * * mark the direct hit (id matches) if it available\n * * mark the first item if there is no direct hit\n *\n * And we need to update the marked option after every search.\n *\n * There is no way of doing this via the interface provided in the template. There is only [markFirst] and it neither allows us\n * to mark a direct hit, nor does it reset after a search. We handle this then by selecting the desired element once the\n * search results are back. We then set the marked option to be the selected option.\n *\n * In order to avoid flickering, a -markable modifyer class is unset/set before/after searching. This will unset the background until we\n * have marked the element we wish to.\n */\n private setMarkedOption() {\n this.markable = true;\n this.ngSelectComponent.itemsList.markItem(this.ngSelectComponent.itemsList.selectedItems[0]);\n\n this.cdRef.detectChanges();\n }\n\n private searchInScope(scope:string) {\n switch (scope) {\n case 'all_projects': {\n let forcePageLoad = false;\n if (this.globalSearchService.projectScope !== 'all') {\n forcePageLoad = true;\n this.globalSearchService.resultsHidden = true;\n }\n this.globalSearchService.projectScope = 'all';\n this.submitNonEmptySearch(forcePageLoad);\n break;\n }\n case 'current_project': {\n this.globalSearchService.projectScope = 'current_project';\n this.submitNonEmptySearch();\n break;\n }\n case 'current_project_and_all_descendants': {\n this.globalSearchService.projectScope = '';\n this.submitNonEmptySearch();\n break;\n }\n }\n }\n\n public submitNonEmptySearch(forcePageLoad:boolean = false) {\n this.globalSearchService.searchTerm = this.currentValue;\n if (this.currentValue.length > 0) {\n this.ngSelectComponent.close();\n // Work package results can update without page reload.\n if (!forcePageLoad &&\n this.globalSearchService.isAfterSearch() &&\n this.globalSearchService.currentTab === 'work_packages') {\n window.history\n .replaceState({},\n `${I18n.t('global_search.search')}: ${this.ngSelectComponent.searchTerm}`,\n this.globalSearchService.searchPath());\n\n return;\n }\n this.globalSearchService.submitSearch();\n }\n }\n\n public blur() {\n this.ngSelectComponent.searchTerm = '';\n (document.activeElement).blur();\n }\n\n private get currentScope():string {\n let serviceScope = this.globalSearchService.projectScope;\n return (serviceScope === '') ? 'current_project_and_all_descendants' : serviceScope;\n }\n\n private unregister() {\n if (this.unregisterGlobalListener) {\n this.unregisterGlobalListener();\n this.unregisterGlobalListener = undefined;\n }\n }\n\n private toggleTopMenuClass() {\n jQuery('#top-menu').toggleClass('-global-search-expanded', this.expanded);\n }\n}\n\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\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 let element = document.getElementById(selector) as HTMLElement|HTMLInputElement;\n\n if (element instanceof HTMLInputElement) {\n element.value = val;\n } else if (element) {\n element.textContent = val;\n }\n });\n }\n });\n }\n}\n\n","//-- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free 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\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\n\nexport const membersAutocompleterSelector = 'members-autocompleter';\n\n@Component({\n templateUrl: '/app/modules/common/autocomplete/user-autocompleter.component.html',\n selector: membersAutocompleterSelector\n})\nexport class MembersAutocompleterComponent extends UserAutocompleterComponent {\n @InjectField() http:HttpClient;\n @InjectField() pathHelper:PathHelperService;\n\n protected getAvailableUsers(url:string, searchTerm:any):Observable<{ [key:string]:string|null }[]> {\n return this.http\n .get(url,\n {\n params: new HttpParams({ encoder: new URLParamsEncoder(), fromObject: { q: searchTerm } }),\n responseType: 'json',\n headers: { 'Content-Type': 'application/json; charset=utf-8' }\n },\n )\n .pipe(\n map((res:any) => {\n return res.results.items.map((el:any) => {\n const href = /^\\d+$/.test(el.id.toString()) ? this.pathHelper.userPath(el.id) : null;\n return { name: el.name, id: el.id, href: href };\n });\n })\n );\n }\n}\n","import {Injectable} from \"@angular/core\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {HttpClient, HttpErrorResponse, HttpHeaders} from \"@angular/common/http\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {FormGroup} from \"@angular/forms\";\nimport {input} from \"reactivestates\";\n\nexport interface EnterpriseTrialData {\n id?:string;\n company:string;\n first_name:string;\n last_name:string;\n email:string;\n domain:string;\n general_consent?:boolean;\n newsletter_consent?:boolean;\n}\n\n@Injectable()\nexport class EnterpriseTrialService {\n // user data needs to be sync in ee-active-trial.component.ts\n userData$ = input();\n\n public readonly baseUrlAugur:string;\n public readonly tokenVersion:string;\n\n public trialLink:string;\n public resendLink:string;\n\n public modalOpen = false;\n public confirmed:boolean;\n public cancelled = false;\n public status:'mailSubmitted'|'startTrial'|undefined;\n public error:HttpErrorResponse|undefined;\n public emailInvalid:boolean = false;\n public text = {\n invalid_email: this.I18n.t('js.admin.enterprise.trial.form.invalid_email'),\n taken_email: this.I18n.t('js.admin.enterprise.trial.form.taken_email'),\n taken_domain: this.I18n.t('js.admin.enterprise.trial.form.taken_domain'),\n };\n\n constructor(readonly I18n:I18nService,\n protected http:HttpClient,\n readonly pathHelper:PathHelperService,\n protected notificationsService:NotificationsService) {\n let gon = (window as any).gon;\n this.baseUrlAugur = gon.augur_url;\n this.tokenVersion = gon.token_version;\n\n if ((window as any).gon.ee_trial_key) {\n this.setMailSubmittedStatus();\n }\n }\n\n // send POST request with form object\n // receive an enterprise trial link to access a token\n public sendForm(form:FormGroup) {\n const request = { ...form.value, token_version: this.tokenVersion};\n this.http.post(this.baseUrlAugur + '/public/v1/trials', request)\n .toPromise()\n .then((enterpriseTrial:any) => {\n this.userData$.putValue(form.value);\n this.cancelled = false;\n\n this.trialLink = enterpriseTrial._links.self.href;\n this.saveTrialKey(this.trialLink);\n\n this.retryConfirmation();\n })\n .catch((error:HttpErrorResponse) => {\n // mail is invalid or user already created a trial\n if (error.status === 422 || error.status === 400) {\n this.error = error;\n } else {\n this.notificationsService.addWarning(error.error.description || I18n.t('js.error.internal'));\n }\n });\n }\n\n // get a token from the trial link if user confirmed mail\n public getToken() {\n // 2) GET /public/v1/trials/:id\n this.http\n .get(this.trialLink)\n .toPromise()\n .then(async (res:any) => {\n // show confirmed status and enable continue btn\n this.confirmed = true;\n\n // returns token if mail was confirmed\n // -> if token is new (token_retrieved: false) save token in backend\n if (!res.token_retrieved) {\n await this.saveToken(res.token);\n }\n })\n .catch((error:HttpErrorResponse) => {\n // returns error 422 while waiting of confirmation\n if (error.status === 422 && error.error.identifier === 'waiting_for_email_verification') {\n // get resend button link\n this.resendLink = error.error._links.resend.href;\n // save a key for the requested trial\n if (!this.status || this.cancelled) { // only do it once\n this.saveTrialKey(this.resendLink);\n }\n // open next modal window -> status waiting\n this.setMailSubmittedStatus();\n this.confirmed = false;\n } else if (_.get(error, 'error._type') === 'Error') {\n this.notificationsService.addError(error.error.message);\n } else {\n this.notificationsService.addError(error.error || I18n.t('js.error.internal'));\n }\n });\n }\n\n // save a part of the resend link in db\n // which allows to remember if a user has already requested a trial token\n // and to ask for the corresponding user data saved in Augur\n private saveTrialKey(resendlink:string) {\n // extract token from resend link\n let trialKey = resendlink.split('/')[6];\n return this.http.post(\n this.pathHelper.appBasePath + '/admin/enterprise/save_trial_key',\n { trial_key: trialKey },\n { withCredentials: true }\n )\n .toPromise()\n .catch((e:any) => {\n this.notificationsService.addError(e.error.message || e.message || e);\n });\n }\n\n // save received token in controller\n private saveToken(token:string) {\n return this.http.post(\n this.pathHelper.appBasePath + '/admin/enterprise',\n { enterprise_token: { encoded_token: token } },\n { withCredentials: true }\n )\n .toPromise()\n .then(() => {\n // load page if mail was confirmed and modal window is not open\n if (!this.modalOpen) {\n setTimeout(() => { // display confirmed status before reloading\n window.location.reload();\n }, 500);\n }\n })\n .catch((error:HttpErrorResponse) => {\n // Delete the trial key as the token could not be saved and thus something is wrong with the token.\n // Without this deletion, we run into an endless loop of an confirmed mail, but no saved token.\n this.http\n .delete(\n this.pathHelper.api.v3.apiV3Base + '/admin/enterprise/delete_trial_key',\n { withCredentials: true }\n )\n .toPromise();\n\n this.notificationsService.addError(error.error.description || I18n.t('js.error.internal'));\n });\n }\n\n // retry request while waiting for mail confirmation\n public retryConfirmation(delay:number = 5000, retries:number = 60) {\n if (this.cancelled || this.confirmed) {\n return;\n } else if (retries === 0) {\n this.cancelled = true;\n } else {\n this.getToken();\n setTimeout(() => {\n this.retryConfirmation(delay, retries - 1);\n }, delay);\n }\n }\n\n public setStartTrialStatus() {\n this.status = 'startTrial';\n }\n\n public setMailSubmittedStatus() {\n this.status = 'mailSubmitted';\n }\n\n public get trialStarted():boolean {\n return this.status === 'startTrial';\n }\n\n public get mailSubmitted():boolean {\n return this.status === 'mailSubmitted';\n }\n\n public get domainTaken():boolean {\n return this.error ? this.error.error.identifier === 'domain_taken' : false;\n }\n\n public get emailTaken():boolean {\n return this.error ? this.error.error.identifier === 'user_already_created_trial' : false;\n }\n\n public get emailError():boolean {\n if (this.emailInvalid) {\n return true;\n } else if (this.error) {\n return this.emailTaken;\n } else {\n return false;\n }\n }\n\n public get errorMsg() {\n let error:string = '';\n if (this.emailInvalid) {\n error = this.text.invalid_email;\n } else if (this.domainTaken) {\n error = this.text.taken_domain;\n } else if (this.emailTaken) {\n error = this.text.taken_email;\n }\n\n return error;\n }\n}\n","export namespace I18nHelpers {\n\n export interface LocalizedLinkMap {\n [key:string]:string;\n\n en:string;\n }\n\n /**\n * Return the matching link for the current locale\n *\n * @param map A hash of locale => URL to use\n */\n export function localizeLink(map:LocalizedLinkMap) {\n const locale = I18n.locale;\n\n return map[locale] || map.en;\n }\n}\n","
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        {{ eeTrialService.errorMsg }}
        \n
        \n
        \n \n
        \n
        \n \n
        \n
        \n
        {{ eeTrialService.errorMsg }}
        \n
        \n
        \n
        \n \n
        \n
        \n
        \n
        \n \n
        \n
        \n
        ","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {Component, ElementRef} from \"@angular/core\";\nimport {FormBuilder, Validators} from \"@angular/forms\";\nimport {I18nService} from \"app/modules/common/i18n/i18n.service\";\nimport {EnterpriseTrialData, EnterpriseTrialService} from \"core-components/enterprise/enterprise-trial.service\";\nimport {CurrentUserService} from \"core-components/user/current-user.service\";\nimport {I18nHelpers} from \"core-app/helpers/i18n/localized-link\";\n\nconst newsletterURL = 'https://www.openproject.com/newsletter/';\n\n@Component({\n selector: 'enterprise-trial-form',\n templateUrl: './ee-trial-form.component.html',\n styleUrls: ['./ee-trial-form.component.sass']\n})\nexport class EETrialFormComponent {\n // Retain used values\n userData:Partial = this.eeTrialService.userData$.getValueOr({});\n\n trialForm = this.formBuilder.group({\n company: [this.userData.company, Validators.required],\n first_name: [this.userData.first_name, Validators.required],\n last_name: [this.userData.last_name, Validators.required],\n email: ['', [Validators.required, Validators.email]],\n domain: [this.userData.domain || window.location.host, Validators.required],\n general_consent: [null, Validators.required],\n newsletter_consent: null,\n language: this.currentUserService.language\n });\n\n public text = {\n general_consent: this.I18n.t('js.admin.enterprise.trial.form.general_consent', {\n link_terms: I18nHelpers.localizeLink({\n en: 'https://www.openproject.com/terms-of-service/',\n de: 'https://www.openproject.org/de/nutzungsbedingungen/',\n }),\n link_privacy: I18nHelpers.localizeLink({\n en: 'https://www.openproject.org/data-privacy-and-security/',\n de: 'https://www.openproject.org/de/datenschutz/'\n })\n }),\n label_test_ee: this.I18n.t('js.admin.enterprise.trial.form.test_ee'),\n label_company: this.I18n.t('js.admin.enterprise.trial.form.label_company'),\n label_first_name: this.I18n.t('js.admin.enterprise.trial.form.label_first_name'),\n label_last_name: this.I18n.t('js.admin.enterprise.trial.form.label_last_name'),\n label_email: this.I18n.t('js.admin.enterprise.trial.form.label_email'),\n label_domain: this.I18n.t('js.admin.enterprise.trial.form.label_domain'),\n privacy_policy: this.I18n.t('js.admin.enterprise.trial.form.privacy_policy'),\n receive_newsletter: this.I18n.t('js.admin.enterprise.trial.form.receive_newsletter', { link: newsletterURL }),\n terms_of_service: this.I18n.t('js.admin.enterprise.trial.form.terms_of_service')\n };\n\n constructor(readonly elementRef:ElementRef,\n readonly I18n:I18nService,\n private formBuilder:FormBuilder,\n readonly currentUserService:CurrentUserService,\n public eeTrialService:EnterpriseTrialService) {\n\n }\n\n // checks if mail is valid after input field was edited by the user\n // displays message for user\n public checkMailField() {\n if (this.trialForm.value.email !== '' && this.trialForm.controls.email.errors) {\n this.eeTrialService.emailInvalid = true;\n } else {\n this.eeTrialService.emailInvalid = false;\n this.eeTrialService.error = undefined;\n }\n }\n}\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {NotificationsService} from \"core-app/modules/common/notifications/notifications.service\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {TimeEntryResource} from \"core-app/modules/hal/resources/time-entry-resource\";\n\nexport const triggerActionsEntryComponentSelector = 'time-entry--trigger-actions-entry';\n\n@Component({\n selector: triggerActionsEntryComponentSelector,\n template: `\n \n \n \n \n \n \n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService,\n TimeEntryEditService\n ]\n})\nexport class TriggerActionsEntryComponent {\n @InjectField() readonly timeEntryEditService:TimeEntryEditService;\n @InjectField() readonly apiv3Service:APIV3Service;\n @InjectField() readonly notificationsService:NotificationsService;\n @InjectField() readonly elementRef:ElementRef;\n @InjectField() 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\n .apiv3Service\n .time_entries\n .id(entry)\n .delete()\n .subscribe(\n () => window.location.reload(),\n error => this.notificationsService.addError(error || this.text.error)\n );\n });\n }\n\n protected loadEntry():Promise {\n let timeEntryId = this.elementRef.nativeElement.dataset['entry'];\n\n return this\n .apiv3Service\n .time_entries\n .id(timeEntryId)\n .get()\n .toPromise();\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++ Ng1FieldControlsWrapper,\n\nimport {Injectable} from \"@angular/core\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {NEVER, Observable, throwError} from \"rxjs\";\nimport {map, take, tap} from \"rxjs/operators\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {multiInput} from \"reactivestates\";\nimport {TransitionService} from \"@uirouter/core\";\nimport {SchemaResource} from \"core-app/modules/hal/resources/schema-resource\";\nimport {CurrentProjectService} from \"core-components/projects/current-project.service\";\n\nexport type SupportedAttributeModels = 'project'|'workPackage';\n\n@Injectable({ providedIn: \"root\" })\nexport class AttributeModelLoaderService {\n\n text = {\n not_found: this.I18n.t('js.editor.macro.attribute_reference.not_found')\n };\n\n // Cache the required model/id values because\n // we may need to expensively filter for them\n private cache$ = multiInput();\n\n constructor(readonly apiV3Service:APIV3Service,\n readonly transitions:TransitionService,\n readonly currentProject:CurrentProjectService,\n readonly I18n:I18nService) {\n\n // Clear cached values whenever leaving the page\n transitions.onStart({}, () => {\n this.cache$.clear();\n return true;\n });\n }\n\n /**\n * Require a given model with an id reference to be loaded.\n * This might be a singular resource identified by an actual integer ID or\n * another (e.g., work package subject) reference.\n *\n * @param model\n * @param id\n */\n require(model:SupportedAttributeModels, id:string):Promise {\n const identifier = `${model}-${id}`;\n const state = this.cache$.get(identifier);\n\n if (state.isPristine()) {\n const promise = this.load(model, id).toPromise();\n state.clearAndPutFromPromise(promise);\n\n return promise;\n }\n\n return state\n .values$()\n .pipe(\n take(1),\n tap(val => console.log(\"VAL \" + val), err => console.error('ERR ' + err))\n )\n .toPromise();\n }\n\n private load(model:SupportedAttributeModels, id?:string|undefined|null):Observable {\n switch (model) {\n case 'workPackage':\n return this.loadWorkPackage(id);\n case 'project':\n return this.loadProject(id);\n default:\n return NEVER;\n }\n }\n\n private loadProject(id:string|undefined|null) {\n id = id || this.currentProject.id;\n\n if (!id) {\n return throwError(this.text.not_found);\n }\n\n return this\n .apiV3Service\n .projects\n .id(id)\n .get()\n .pipe(\n take(1)\n );\n }\n\n private loadWorkPackage(id?:string|undefined|null) {\n if (!id) {\n return throwError(this.text.not_found);\n }\n\n // Return global reference to the subject\n if (/^[1-9]\\d*$/.test(id)) {\n return this\n .apiV3Service\n .work_packages\n .id(id)\n .get()\n .pipe(\n take(1)\n );\n }\n\n // Otherwise, look for subject IN the current project (if we're in project context)\n return this\n .apiV3Service\n .withOptionalProject(this.currentProject.id)\n .work_packages\n .filterBySubjectOrId(id, false, { pageSize: '1' })\n .get()\n .pipe(\n take(1),\n map(collection => collection.elements[0] || null)\n );\n }\n}\n","import {ChangeDetectionStrategy, Component, ElementRef, Injector, Input, OnInit, ViewChild} from '@angular/core';\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {Constructor} from \"@angular/cdk/table\";\nimport {DisplayField} from \"core-app/modules/fields/display/display-field.module\";\n\n@Component({\n selector: 'display-field',\n template: '',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DisplayFieldComponent implements OnInit {\n @Input() resource:HalResource;\n @Input() fieldName:string;\n @Input() displayClass?:Constructor;\n\n @Input() containerType:'table'|'single-view'|'timeline' = 'table';\n @Input() displayFieldOptions:{[key:string]:unknown} = {};\n\n @ViewChild('displayFieldContainer') container:ElementRef;\n\n constructor(private injector:Injector,\n private displayFieldService:DisplayFieldService,\n private schemaCache:SchemaCacheService) {\n }\n\n ngOnInit() {\n this.schemaCache\n .ensureLoaded(this.resource)\n .then(schema => {\n this.render(schema[this.fieldName]);\n });\n }\n\n render(fieldSchema:IFieldSchema) {\n const field = this.getDisplayFieldInstance(fieldSchema);\n\n const container = this.container.nativeElement;\n container.hidden = false;\n\n // Default the field to a placeholder when rendering\n if (field.isEmpty()) {\n container.textContent = '-';\n } else {\n field.render(container, field.valueString);\n }\n }\n\n private getDisplayFieldInstance(fieldSchema:IFieldSchema) {\n if (this.displayClass) {\n let instance = new this.displayClass(this.fieldName, this.displayFieldContext);\n instance.apply(this.resource, fieldSchema);\n return instance;\n }\n\n return this.displayFieldService.getField(\n this.resource,\n this.fieldName,\n fieldSchema,\n this.displayFieldContext\n );\n }\n\n private get displayFieldContext() {\n return { injector: this.injector, container: this.containerType, options: this.displayFieldOptions }\n }\n}\n","\n \n \n\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++ Ng1FieldControlsWrapper,\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostBinding,\n Injector,\n ViewChild\n} from \"@angular/core\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {NEVER, Observable} from \"rxjs\";\nimport {filter, map, take, tap} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n AttributeModelLoaderService,\n SupportedAttributeModels\n} from \"core-app/modules/fields/macros/attribute-model-loader.service\";\n\nexport const attributeValueMacro = 'macro.macro--attribute-value';\n\n@Component({\n selector: attributeValueMacro,\n templateUrl: './attribute-value-macro.html',\n styleUrls: ['./attribute-macro.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class AttributeValueMacroComponent {\n @ViewChild('displayContainer') private displayContainer:ElementRef;\n\n // Whether the value could not be loaded\n error:string|null = null;\n\n text = {\n help: this.I18n.t('js.editor.macro.attribute_reference.macro_help_tooltip'),\n placeholder: this.I18n.t('js.placeholders.default'),\n not_found: this.I18n.t('js.editor.macro.attribute_reference.not_found'),\n invalid_attribute: (attr:string) =>\n this.I18n.t('js.editor.macro.attribute_reference.invalid_attribute', { name: attr }),\n };\n\n @HostBinding('title') hostTitle = this.text.help;\n\n resource:HalResource;\n fieldName:string;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly resourceLoader:AttributeModelLoaderService,\n readonly schemaCache:SchemaCacheService,\n readonly displayField:DisplayFieldService,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef) {\n\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement as HTMLElement;\n const model:SupportedAttributeModels = element.dataset.model as any;\n const id:string = element.dataset.id!;\n const attributeName:string = element.dataset.attribute!;\n\n this.loadAndRender(model, id, attributeName);\n }\n\n private async loadAndRender(model:SupportedAttributeModels, id:string, attributeName:string) {\n let resource:HalResource|null;\n\n try {\n resource = await this.resourceLoader.require(model, id);\n } catch (e) {\n console.error(\"Failed to render macro \" + e);\n return this.markError(this.text.not_found);\n }\n\n if (!resource) {\n this.markError(this.text.not_found);\n return;\n }\n\n const schema = await this.schemaCache.ensureLoaded(resource);\n const attribute = schema.attributeFromLocalizedName(attributeName) || attributeName;\n const fieldSchema = schema[attribute] as IFieldSchema|undefined;\n\n if (fieldSchema) {\n this.resource = resource;\n this.fieldName = attribute;\n } else {\n this.markError(this.text.invalid_attribute(attributeName));\n }\n\n this.cdRef.detectChanges();\n }\n\n markError(message:string) {\n this.error = this.I18n.t('js.editor.macro.error', { message: message });\n this.cdRef.detectChanges();\n }\n}\n","export namespace StringHelpers {\n\n /**\n * Capitalize\n * @param value\n */\n export function capitalize(value:string):string {\n return value.charAt(0).toUpperCase() + value.slice(1);\n }\n}","\n \n \n \n\n\n\n \n \n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++ Ng1FieldControlsWrapper,\n\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostBinding,\n Injector,\n ViewChild\n} from \"@angular/core\";\nimport {HalResource} from \"core-app/modules/hal/resources/hal-resource\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {NEVER, Observable} from \"rxjs\";\nimport {filter, map, take, tap} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {IFieldSchema} from \"core-app/modules/fields/field.base\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {\n AttributeModelLoaderService,\n SupportedAttributeModels\n} from \"core-app/modules/fields/macros/attribute-model-loader.service\";\nimport {StringHelpers} from \"core-app/helpers/string-helpers\";\n\nexport const attributeLabelMacro = 'macro.macro--attribute-label';\n\n@Component({\n selector: attributeLabelMacro,\n templateUrl: './attribute-label-macro.html',\n styleUrls: ['./attribute-macro.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class AttributeLabelMacroComponent {\n\n // Whether the value could not be loaded\n error:string|null = null;\n\n text = {\n help: this.I18n.t('js.editor.macro.attribute_reference.macro_help_tooltip'),\n not_found: this.I18n.t('js.editor.macro.attribute_reference.not_found'),\n invalid_attribute: (attr:string) =>\n this.I18n.t('js.editor.macro.attribute_reference.invalid_attribute', { name: attr }),\n };\n\n @HostBinding('title') hostTitle = this.text.help;\n\n // The loaded resource, required for help text\n resource:HalResource|null = null;\n // The scope to load for attribute help text\n attributeScope:string;\n // The attribute name, normalized from schema\n attribute:string;\n // The label to render\n label:string;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly resourceLoader:AttributeModelLoaderService,\n readonly schemaCache:SchemaCacheService,\n readonly displayField:DisplayFieldService,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef) {\n\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement as HTMLElement;\n const model:SupportedAttributeModels = element.dataset.model as any;\n const id:string = element.dataset.id!;\n const attributeName:string = element.dataset.attribute!;\n this.attributeScope = StringHelpers.capitalize(model);\n\n this.loadResourceAttribute(model, id, attributeName);\n }\n\n private async loadResourceAttribute(model:SupportedAttributeModels, id:string, attributeName:string) {\n let resource:HalResource|null;\n\n try {\n this.resource = resource = await this.resourceLoader.require(model, id);\n } catch (e) {\n console.error(\"Failed to render macro \" + e);\n return this.markError(this.text.not_found);\n }\n\n if (!resource) {\n this.markError(this.text.not_found);\n return;\n }\n\n const schema = await this.schemaCache.ensureLoaded(resource);\n this.attribute = schema.attributeFromLocalizedName(attributeName) || attributeName;\n this.label = schema[this.attribute]?.name;\n\n if (!this.label) {\n this.markError(this.text.invalid_attribute(attributeName));\n }\n\n this.cdRef.detectChanges();\n }\n\n markError(message:string) {\n this.error = this.I18n.t('js.editor.macro.error', { message: message });\n this.cdRef.detectChanges();\n }\n}\n","\n \n \n \n \n \n #{{workPackage.id}}:\n \n \n \n \n (\n \n \n )\n \n\n\n \n \n\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++ Ng1FieldControlsWrapper,\n\nimport {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, HostBinding, Injector} from \"@angular/core\";\nimport {APIV3Service} from \"core-app/modules/apiv3/api-v3.service\";\nimport {Observable} from \"rxjs\";\nimport {tap} from \"rxjs/operators\";\nimport {SchemaCacheService} from \"core-components/schemas/schema-cache.service\";\nimport {HalResourceEditingService} from \"core-app/modules/fields/edit/services/hal-resource-editing.service\";\nimport {DisplayFieldService} from \"core-app/modules/fields/display/display-field.service\";\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\nimport {WorkPackageResource} from \"core-app/modules/hal/resources/work-package-resource\";\nimport {DateDisplayField} from \"core-app/modules/fields/display/field-types/date-display-field.module\";\nimport {CombinedDateDisplayField} from \"core-app/modules/fields/display/field-types/combined-date-display.field\";\nimport {PathHelperService} from \"core-app/modules/common/path-helper/path-helper.service\";\n\nexport const quickInfoMacroSelector = 'macro.macro--wp-quickinfo';\n\n@Component({\n selector: quickInfoMacroSelector,\n templateUrl: './work-package-quickinfo-macro.html',\n styleUrls: ['./work-package-quickinfo-macro.sass'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n HalResourceEditingService\n ]\n})\nexport class WorkPackageQuickinfoMacroComponent {\n // Whether the value could not be loaded\n error:string|null = null;\n\n text = {\n not_found: this.I18n.t('js.editor.macro.attribute_reference.not_found'),\n help: this.I18n.t('js.editor.macro.attribute_reference.macro_help_tooltip')\n };\n\n @HostBinding('title') hostTitle = this.text.help;\n\n /** Work package to be shown */\n workPackage$:Observable;\n dateDisplayField = CombinedDateDisplayField;\n workPackageLink:string;\n detailed:boolean = false;\n\n constructor(readonly elementRef:ElementRef,\n readonly injector:Injector,\n readonly apiV3Service:APIV3Service,\n readonly schemaCache:SchemaCacheService,\n readonly displayField:DisplayFieldService,\n readonly pathHelper:PathHelperService,\n readonly I18n:I18nService,\n readonly cdRef:ChangeDetectorRef) {\n\n }\n\n ngOnInit() {\n const element = this.elementRef.nativeElement as HTMLElement;\n const id:string = element.dataset.id!;\n this.detailed = element.dataset.detailed === 'true';\n this.workPackageLink = this.pathHelper.workPackagePath(id);\n\n this.workPackage$ = this\n .apiV3Service\n .work_packages\n .id(id)\n .get()\n .pipe(\n tap({ error: (e) => this.markError(this.text.not_found) })\n );\n }\n\n markError(message:string) {\n console.error(\"Failed to render macro \" + message);\n this.error = this.I18n.t('js.editor.macro.error', { message: message });\n this.cdRef.detectChanges();\n }\n}\n","import {OptionalBootstrapDefinition} from \"core-app/globals/dynamic-bootstrapper\";\nimport {appBaseSelector, ApplicationBaseComponent} from \"core-app/modules/router/base/application-base.component\";\nimport {\n EmbeddedTablesMacroComponent,\n wpEmbeddedTableMacroSelector\n} from \"core-components/wp-table/embedded/embedded-tables-macro.component\";\nimport {\n ColorsAutocompleter,\n colorsAutocompleterSelector\n} from \"core-app/modules/common/colors/colors-autocompleter.component\";\nimport {\n ZenModeButtonComponent,\n zenModeComponentSelector\n} from \"core-components/wp-buttons/zen-mode-toggle-button/zen-mode-toggle-button.component\";\nimport {AttachmentsComponent, attachmentsSelector} from \"core-app/modules/attachments/attachments.component\";\nimport {\n UserAutocompleterComponent,\n usersAutocompleterSelector\n} from \"core-app/modules/common/autocomplete/user-autocompleter.component\";\nimport {\n GlobalSearchWorkPackagesComponent,\n globalSearchWorkPackagesSelector\n} from \"core-app/modules/global_search/global-search-work-packages.component\";\nimport {\n HomescreenNewFeaturesBlockComponent,\n homescreenNewFeaturesBlockSelector\n} from \"core-components/homescreen/blocks/new-features.component\";\nimport {\n CustomDateActionAdminComponent,\n customDateActionAdminSelector\n} from \"core-components/wp-custom-actions/date-action/custom-date-action-admin.component\";\nimport {BoardsMenuComponent, boardsMenuSelector} from \"core-app/modules/boards/boards-sidebar/boards-menu.component\";\nimport {\n GlobalSearchWorkPackagesEntryComponent,\n globalSearchWorkPackagesSelectorEntry\n} from \"core-app/modules/global_search/global-search-work-packages-entry.component\";\nimport {\n NotificationsContainerComponent,\n notificationsContainerSelector\n} from \"core-app/modules/common/notifications/notifications-container.component\";\nimport {\n adminTypeFormConfigurationSelector,\n TypeFormConfigurationComponent\n} from \"core-app/modules/admin/types/type-form-configuration.component\";\nimport {\n CkeditorAugmentedTextareaComponent,\n ckeditorAugmentedTextareaSelector\n} from \"core-app/ckeditor/ckeditor-augmented-textarea.component\";\nimport {\n PersistentToggleComponent,\n persistentToggleSelector\n} from \"core-app/modules/common/persistent-toggle/persistent-toggle.component\";\nimport {UserAvatarComponent, userAvatarSelector} from \"core-components/user/user-avatar/user-avatar.component\";\nimport {\n HideSectionLinkComponent,\n hideSectionLinkSelector\n} from \"core-app/modules/common/hide-section/hide-section-link/hide-section-link.component\";\nimport {\n ShowSectionDropdownComponent,\n showSectionDropdownSelector\n} from \"core-app/modules/common/hide-section/show-section-dropdown.component\";\nimport {\n AddSectionDropdownComponent,\n addSectionDropdownSelector\n} from \"core-app/modules/common/hide-section/add-section-dropdown/add-section-dropdown.component\";\nimport {\n AutocompleteSelectDecorationComponent,\n autocompleteSelectDecorationSelector\n} from \"core-app/modules/common/autocomplete/autocomplete-select-decoration.component\";\nimport {\n ContentTabsComponent,\n contentTabsSelector\n} from \"core-app/modules/common/tabs/content-tabs/content-tabs.component\";\nimport {\n CopyToClipboardDirective,\n copyToClipboardSelector\n} from \"core-app/modules/common/copy-to-clipboard/copy-to-clipboard.directive\";\nimport {\n ConfirmFormSubmitController,\n confirmFormSubmitSelector\n} from \"core-components/modals/confirm-form-submit/confirm-form-submit.directive\";\nimport {MainMenuResizerComponent, mainMenuResizerSelector} from \"core-components/resizer/main-menu-resizer.component\";\nimport {\n GlobalSearchInputComponent,\n globalSearchSelector\n} from \"core-app/modules/global_search/input/global-search-input.component\";\nimport {\n collapsibleSectionAugmentSelector,\n CollapsibleSectionComponent\n} from \"core-app/modules/common/collapsible-section/collapsible-section.component\";\nimport {\n EnterpriseBannerBootstrapComponent,\n enterpriseBannerSelector\n} from \"core-components/enterprise-banner/enterprise-banner-bootstrap.component\";\nimport {\n ProjectMenuAutocompleteComponent,\n projectMenuAutocompleteSelector\n} from \"core-components/projects/project-menu-autocomplete/project-menu-autocomplete.component\";\nimport {\n RemoteFieldUpdaterComponent,\n remoteFieldUpdaterSelector\n} from \"core-app/modules/common/remote-field-updater/remote-field-updater.component\";\nimport {\n WorkPackageOverviewGraphComponent,\n wpOverviewGraphSelector\n} from \"core-app/modules/work-package-graphs/overview/wp-overview-graph.component\";\nimport {\n WorkPackageQuerySelectDropdownComponent,\n wpQuerySelectSelector\n} from \"core-components/wp-query-select/wp-query-select-dropdown.component\";\nimport {\n GlobalSearchTitleComponent,\n globalSearchTitleSelector\n} from \"core-app/modules/global_search/title/global-search-title.component\";\nimport {\n GlobalSearchTabsComponent,\n globalSearchTabsSelector\n} from \"core-app/modules/global_search/tabs/global-search-tabs.component\";\nimport {MainMenuToggleComponent, mainMenuToggleSelector} from \"core-components/main-menu/main-menu-toggle.component\";\nimport {\n MembersAutocompleterComponent,\n membersAutocompleterSelector\n} from \"core-app/modules/members/members-autocompleter.component\";\nimport {EnterpriseBaseComponent, enterpriseBaseSelector} from \"core-components/enterprise/enterprise-base.component\";\nimport {\n EEActiveSavedTrialComponent,\n enterpriseActiveSavedTrialSelector\n} from \"core-components/enterprise/enterprise-active-trial/ee-active-saved-trial.component\";\nimport {\n TriggerActionsEntryComponent,\n triggerActionsEntryComponentSelector\n} from \"core-app/modules/time_entries/edit/trigger-actions-entry.component\";\nimport {\n BacklogsPageComponent,\n backlogsPageComponentSelector\n} from \"core-app/modules/backlogs/backlogs-page/backlogs-page.component\";\nimport {\n attributeValueMacro,\n AttributeValueMacroComponent\n} from \"core-app/modules/fields/macros/attribute-value-macro.component\";\nimport {\n attributeLabelMacro,\n AttributeLabelMacroComponent\n} from \"core-app/modules/fields/macros/attribute-label-macro.component\";\nimport {\n AttributeHelpTextComponent,\n attributeHelpTextSelector\n} from \"core-app/modules/fields/help-texts/attribute-help-text.component\";\nimport {\n quickInfoMacroSelector,\n WorkPackageQuickinfoMacroComponent\n} from \"core-app/modules/fields/macros/work-package-quickinfo-macro.component\";\nimport {\n EditableQueryPropsComponent,\n editableQueryPropsSelector\n} from \"core-app/modules/admin/editable-query-props/editable-query-props.component\";\nimport {SlideToggleComponent, slideToggleSelector} from \"core-app/modules/common/slide-toggle/slide-toggle.component\";\n\nexport const globalDynamicComponents:OptionalBootstrapDefinition[] = [\n { selector: appBaseSelector, cls: ApplicationBaseComponent },\n { selector: attributeHelpTextSelector, cls: AttributeHelpTextComponent },\n { selector: wpEmbeddedTableMacroSelector, cls: EmbeddedTablesMacroComponent, embeddable: true },\n { selector: colorsAutocompleterSelector, cls: ColorsAutocompleter },\n { selector: zenModeComponentSelector, cls: ZenModeButtonComponent },\n { selector: attachmentsSelector, cls: AttachmentsComponent, embeddable: true },\n { selector: usersAutocompleterSelector, cls: UserAutocompleterComponent },\n { selector: membersAutocompleterSelector, cls: MembersAutocompleterComponent },\n { selector: globalSearchTabsSelector, cls: GlobalSearchTabsComponent },\n { selector: globalSearchWorkPackagesSelector, cls: GlobalSearchWorkPackagesComponent },\n { selector: homescreenNewFeaturesBlockSelector, cls: HomescreenNewFeaturesBlockComponent },\n { selector: customDateActionAdminSelector, cls: CustomDateActionAdminComponent },\n { selector: boardsMenuSelector, cls: BoardsMenuComponent },\n { selector: globalSearchWorkPackagesSelectorEntry, cls: GlobalSearchWorkPackagesEntryComponent },\n { selector: notificationsContainerSelector, cls: NotificationsContainerComponent },\n { selector: adminTypeFormConfigurationSelector, cls: TypeFormConfigurationComponent, },\n { selector: ckeditorAugmentedTextareaSelector, cls: CkeditorAugmentedTextareaComponent, embeddable: true },\n { selector: persistentToggleSelector, cls: PersistentToggleComponent },\n { selector: userAvatarSelector, cls: UserAvatarComponent },\n { selector: hideSectionLinkSelector, cls: HideSectionLinkComponent },\n { selector: showSectionDropdownSelector, cls: ShowSectionDropdownComponent },\n { selector: addSectionDropdownSelector, cls: AddSectionDropdownComponent },\n { selector: autocompleteSelectDecorationSelector, cls: AutocompleteSelectDecorationComponent },\n { selector: contentTabsSelector, cls: ContentTabsComponent },\n { selector: globalSearchTitleSelector, cls: GlobalSearchTitleComponent },\n { selector: copyToClipboardSelector, cls: CopyToClipboardDirective },\n { selector: confirmFormSubmitSelector, cls: ConfirmFormSubmitController },\n { selector: mainMenuResizerSelector, cls: MainMenuResizerComponent },\n { selector: mainMenuToggleSelector, cls: MainMenuToggleComponent },\n { selector: globalSearchSelector, cls: GlobalSearchInputComponent },\n { selector: collapsibleSectionAugmentSelector, cls: CollapsibleSectionComponent },\n { selector: enterpriseBannerSelector, cls: EnterpriseBannerBootstrapComponent },\n { selector: enterpriseBaseSelector, cls: EnterpriseBaseComponent },\n { selector: enterpriseActiveSavedTrialSelector, cls: EEActiveSavedTrialComponent },\n { selector: projectMenuAutocompleteSelector, cls: ProjectMenuAutocompleteComponent },\n { selector: remoteFieldUpdaterSelector, cls: RemoteFieldUpdaterComponent },\n { selector: wpOverviewGraphSelector, cls: WorkPackageOverviewGraphComponent },\n { selector: wpQuerySelectSelector, cls: WorkPackageQuerySelectDropdownComponent },\n { selector: triggerActionsEntryComponentSelector, cls: TriggerActionsEntryComponent, embeddable: true },\n { selector: backlogsPageComponentSelector, cls: BacklogsPageComponent },\n { selector: attributeValueMacro, cls: AttributeValueMacroComponent, embeddable: true },\n { selector: attributeLabelMacro, cls: AttributeLabelMacroComponent, embeddable: true },\n { selector: quickInfoMacroSelector, cls: WorkPackageQuickinfoMacroComponent, embeddable: true },\n { selector: editableQueryPropsSelector, cls: EditableQueryPropsComponent },\n { selector: slideToggleSelector, cls: SlideToggleComponent }\n];\n\n\n\n\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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\n\nimport {Inject, Injectable, Injector} from \"@angular/core\";\nimport {DOCUMENT} from \"@angular/common\";\nimport {DynamicContentModal} from \"core-components/modals/modal-wrapper/dynamic-content.modal\";\nimport {OpModalService} from \"core-components/op-modals/op-modal.service\";\n\nconst iframeSelector = '.iframe-target-wrapper';\n\n@Injectable({ providedIn: 'root' })\nexport class ModalWrapperAugmentService {\n\n constructor(@Inject(DOCUMENT) protected documentElement:Document,\n protected injector:Injector,\n protected opModalService:OpModalService) {\n }\n\n /**\n * Create initial listeners for Rails-rendered modals\n */\n public setupListener() {\n const matches = this.documentElement.querySelectorAll('section[data-augmented-model-wrapper]');\n for (let i = 0; i < matches.length; ++i) {\n this.wrapElement(jQuery(matches[i]) as JQuery);\n }\n }\n\n /**\n * Wrap a section[data-augmented-modal-wrapper] element\n */\n public wrapElement(element:JQuery) {\n // Find activation link\n let activationLink = element.find('.modal-wrapper--activation-link');\n let activationSelector = element.data('activationSelector');\n\n if (activationSelector) {\n activationLink = jQuery(activationSelector);\n }\n\n const initializeNow = element.data('modalInitializeNow');\n\n if (initializeNow) {\n this.show(element);\n } else {\n activationLink.click((evt:JQuery.TriggeredEvent) => {\n this.show(element);\n evt.preventDefault();\n });\n }\n }\n\n private show(element:JQuery) {\n // Set modal class name\n const modalClassName = element.data('modalClassName');\n // Append CSP-whitelisted IFrame for onboarding\n const iframeUrl = element.data('modalIframeUrl');\n\n // Set template from wrapped element\n const wrappedElement = element.find('.modal-wrapper--content');\n let modalBody = wrappedElement.html();\n\n if (iframeUrl) {\n modalBody = this.appendIframe(modalBody, iframeUrl);\n }\n\n this.opModalService.show(\n DynamicContentModal,\n this.injector,\n {\n modalBody: modalBody,\n modalClassName: modalClassName\n }\n );\n }\n\n private appendIframe(body:string, url:string) {\n let subdom = jQuery(body);\n let iframe = jQuery('');\n iframe.attr('src', url);\n\n subdom.find(iframeSelector).append(iframe);\n\n return subdom.html();\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\n\nimport {Inject, Injectable} from \"@angular/core\";\nimport {DOCUMENT} from \"@angular/common\";\nimport {debugLog} from \"core-app/helpers/debug_output\";\n\n@Injectable({ providedIn: 'root' })\nexport class PathScriptAugmentService {\n\n constructor(@Inject(DOCUMENT) protected documentElement:Document) {\n }\n\n /**\n * Import required javascript paths from backend-rendered pages\n * This provides a replacement for the asset pipeline that was previously used\n * to load javascripts in the backend.\n *\n * This approach retains the ability to dynamically load code (from a specific set of paths only)\n * while defining the dependency in the rails template to ensure developer visibility.\n */\n public loadRequiredScripts() {\n const matches = this.documentElement.querySelectorAll('meta[name=\"required_script\"]');\n for (let i = 0; i < matches.length; ++i) {\n const name = matches[i].content;\n debugLog(\"Loading required script \" + name);\n import('../dynamic-scripts/' + name);\n }\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {NgModule} from '@angular/core';\nimport {ModalWrapperAugmentService} from \"core-app/modules/augmenting/services/modal-wrapper.augment.service\";\nimport {PathScriptAugmentService} from \"core-app/modules/augmenting/services/path-script.augment.service\";\n\n@NgModule({\n providers: [\n ModalWrapperAugmentService,\n PathScriptAugmentService\n ],\n})\nexport class OpenprojectAugmentingModule {\n constructor(modalWrapper:ModalWrapperAugmentService,\n pathScript:PathScriptAugmentService) {\n // Setup augmenting services\n modalWrapper.setupListener();\n pathScript.loadRequiredScripts();\n }\n}\n\n","import {Injectable, Injector} from '@angular/core';\nimport {I18nService} from \"core-app/modules/common/i18n/i18n.service\";\n\n/*\n * This service conditionally creates two settings buttons (on the user menu and on\n * the login menu) that give access to the Revit Plugin settings.\n */\n@Injectable()\nexport class RevitAddInSettingsButtonService {\n private readonly labelText:string;\n private readonly groupLabelText:string;\n\n constructor(readonly injector:Injector,\n readonly i18n:I18nService) {\n const onRevitAddInEnvironment = window.navigator.userAgent.search('Revit') > -1;\n\n if (onRevitAddInEnvironment) {\n this.labelText = i18n.t('js.revit.revit_add_in_settings');\n this.groupLabelText = i18n.t('js.revit.revit_add_in');\n\n this.addUserMenuItem();\n this.addLoginMenuItem();\n }\n }\n\n public addUserMenuItem():void {\n const userMenu = document.getElementById('user-menu');\n\n if (userMenu) {\n const menuItem:HTMLElement = document.createElement('li');\n menuItem.dataset.name = this.labelText;\n menuItem.innerHTML = `\n \n ${this.labelText}\n \n `;\n\n menuItem.addEventListener('click', () => this.goToSettings());\n userMenu.appendChild(menuItem);\n }\n }\n\n public addLoginMenuItem() {\n const loginModal = document.querySelector('#nav-login-content');\n\n if (loginModal) {\n const loginMenuItem:HTMLElement = document.createElement('div');\n\n loginMenuItem.dataset.name = this.labelText;\n loginMenuItem.innerHTML = `\n
        \n

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

        \n
        \n
        \n ${this.labelText}\n
        \n
        \n
        \n `;\n loginModal.appendChild(loginMenuItem);\n\n const settingsButton = loginModal.querySelector('.revit-add-in-button');\n\n settingsButton!.addEventListener('click', () => this.goToSettings());\n }\n }\n\n goToSettings() {\n window.RevitBridge.sendMessageToRevit('GoToSettings', '1', '');\n }\n}\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n//\n// See docs/COPYRIGHT.rdoc for more details.\n// ++\n\nimport {APP_INITIALIZER, ApplicationRef, Injector, NgModule} from '@angular/core';\nimport {ReactiveFormsModule} from '@angular/forms';\nimport {OpenprojectHalModule} from 'core-app/modules/hal/openproject-hal.module';\n\nimport {OpContextMenuTrigger} from 'core-components/op-context-menu/handlers/op-context-menu-trigger.directive';\nimport {States} from 'core-components/states.service';\nimport {PaginationService} from 'core-components/table-pagination/pagination-service';\nimport {MainMenuResizerComponent} from 'core-components/resizer/main-menu-resizer.component';\nimport {ExternalQueryConfigurationService} from 'core-components/wp-table/external-configuration/external-query-configuration.service';\nimport {ExternalRelationQueryConfigurationService} from 'core-components/wp-table/external-configuration/external-relation-query-configuration.service';\nimport {ConfirmDialogModal} from \"core-components/modals/confirm-dialog/confirm-dialog.modal\";\nimport {ConfirmDialogService} from \"core-components/modals/confirm-dialog/confirm-dialog.service\";\nimport {DynamicContentModal} from \"core-components/modals/modal-wrapper/dynamic-content.modal\";\nimport {PasswordConfirmationModal} from \"core-components/modals/request-for-confirmation/password-confirmation.modal\";\nimport {OpenprojectFieldsModule} from \"core-app/modules/fields/openproject-fields.module\";\nimport {OpenprojectCommonModule} from \"core-app/modules/common/openproject-common.module\";\nimport {CommentService} from \"core-components/wp-activity/comment-service\";\nimport {OpDragScrollDirective} from \"core-app/modules/common/ui/op-drag-scroll.directive\";\nimport {OpenprojectPluginsModule} from \"core-app/modules/plugins/openproject-plugins.module\";\nimport {ConfirmFormSubmitController} from \"core-components/modals/confirm-form-submit/confirm-form-submit.directive\";\nimport {ProjectMenuAutocompleteComponent} from \"core-components/projects/project-menu-autocomplete/project-menu-autocomplete.component\";\nimport {OpenProjectFileUploadService} from \"core-components/api/op-file-upload/op-file-upload.service\";\nimport {OpenProjectDirectFileUploadService} from './components/api/op-file-upload/op-direct-file-upload.service';\nimport {LinkedPluginsModule} from \"core-app/modules/plugins/linked-plugins.module\";\nimport {HookService} from \"core-app/modules/plugins/hook-service\";\nimport {DynamicBootstrapper} from \"core-app/globals/dynamic-bootstrapper\";\nimport {OpenprojectWorkPackagesModule} from 'core-app/modules/work_packages/openproject-work-packages.module';\nimport {OpenprojectAttachmentsModule} from 'core-app/modules/attachments/openproject-attachments.module';\nimport {OpenprojectEditorModule} from 'core-app/modules/editor/openproject-editor.module';\nimport {OpenprojectGridsModule} from \"core-app/modules/grids/openproject-grids.module\";\nimport {OpenprojectRouterModule} from \"core-app/modules/router/openproject-router.module\";\nimport {OpenprojectWorkPackageRoutesModule} from \"core-app/modules/work_packages/openproject-work-package-routes.module\";\nimport {BrowserModule} from \"@angular/platform-browser\";\nimport {OpenprojectCalendarModule} from \"core-app/modules/calendar/openproject-calendar.module\";\nimport {OpenprojectGlobalSearchModule} from \"core-app/modules/global_search/openproject-global-search.module\";\nimport {MainMenuToggleComponent} from \"core-components/main-menu/main-menu-toggle.component\";\nimport {MainMenuNavigationService} from \"core-components/main-menu/main-menu-navigation.service\";\nimport {OpenprojectAdminModule} from \"core-app/modules/admin/openproject-admin.module\";\nimport {OpenprojectDashboardsModule} from \"core-app/modules/dashboards/openproject-dashboards.module\";\nimport {OpenprojectWorkPackageGraphsModule} from \"core-app/modules/work-package-graphs/openproject-work-package-graphs.module\";\nimport {WpPreviewModal} from \"core-components/modals/preview-modal/wp-preview-modal/wp-preview.modal\";\nimport {PreviewTriggerService} from \"core-app/globals/global-listeners/preview-trigger.service\";\nimport {OpenprojectOverviewModule} from \"core-app/modules/overview/openproject-overview.module\";\nimport {OpenprojectMyPageModule} from \"core-app/modules/my-page/openproject-my-page.module\";\nimport {OpenprojectProjectsModule} from \"core-app/modules/projects/openproject-projects.module\";\nimport {KeyboardShortcutService} from \"core-app/modules/a11y/keyboard-shortcut-service\";\nimport {globalDynamicComponents} from \"core-app/global-dynamic-components.const\";\nimport {OpenprojectMembersModule} from \"core-app/modules/members/members.module\";\nimport {OpenprojectEnterpriseModule} from \"core-components/enterprise/openproject-enterprise.module\";\nimport {OpenprojectAugmentingModule} from \"core-app/modules/augmenting/openproject-augmenting.module\";\nimport {RevitAddInSettingsButtonService} from \"core-app/modules/bim/revit_add_in/revit-add-in-settings-button.service\";\n\n@NgModule({\n imports: [\n // The BrowserModule must only be loaded here!\n BrowserModule,\n // Commons\n OpenprojectCommonModule,\n // Router module\n OpenprojectRouterModule,\n // Hal Module\n OpenprojectHalModule,\n\n // CKEditor\n OpenprojectEditorModule,\n // Display + Edit field functionality\n OpenprojectFieldsModule,\n OpenprojectGridsModule,\n OpenprojectAttachmentsModule,\n\n // Project module\n OpenprojectProjectsModule,\n\n // Work packages and their routes\n OpenprojectWorkPackagesModule,\n OpenprojectWorkPackageRoutesModule,\n\n // Work packages in graph representation\n OpenprojectWorkPackageGraphsModule,\n\n // Calendar module\n OpenprojectCalendarModule,\n\n // Dashboards\n OpenprojectDashboardsModule,\n\n // Overview\n OpenprojectOverviewModule,\n\n // MyPage\n OpenprojectMyPageModule,\n\n // Global Search\n OpenprojectGlobalSearchModule,\n\n // Admin module\n OpenprojectAdminModule,\n OpenprojectEnterpriseModule,\n\n // Plugin hooks and modules\n OpenprojectPluginsModule,\n // Linked plugins dynamically generated by bundler\n LinkedPluginsModule,\n\n // Members\n OpenprojectMembersModule,\n\n // Angular Forms\n ReactiveFormsModule,\n\n // Augmenting Module\n OpenprojectAugmentingModule,\n ],\n providers: [\n { provide: States, useValue: new States() },\n { provide: APP_INITIALIZER, useFactory: initializeServices, deps: [Injector], multi: true },\n PaginationService,\n OpenProjectFileUploadService,\n OpenProjectDirectFileUploadService,\n // Split view\n CommentService,\n ConfirmDialogService,\n RevitAddInSettingsButtonService,\n ],\n declarations: [\n OpContextMenuTrigger,\n\n // Modals\n ConfirmDialogModal,\n DynamicContentModal,\n PasswordConfirmationModal,\n WpPreviewModal,\n\n // Main menu\n MainMenuResizerComponent,\n MainMenuToggleComponent,\n\n // Project autocompleter\n ProjectMenuAutocompleteComponent,\n\n // Form configuration\n OpDragScrollDirective,\n ConfirmFormSubmitController,\n ]\n})\nexport class OpenProjectModule {\n\n // noinspection JSUnusedGlobalSymbols\n ngDoBootstrap(appRef:ApplicationRef) {\n\n // Register global dynamic components\n // this is necessary to ensure they are not tree-shaken\n // (if they are not used anywhere in Angular, they would be removed)\n DynamicBootstrapper.register(...globalDynamicComponents);\n\n // Perform global dynamic bootstrapping of our entry components\n // that are in the current DOM response.\n DynamicBootstrapper.bootstrapOptionalDocument(appRef, document);\n\n // Call hook service to allow modules to bootstrap additional elements.\n // We can't use ngDoBootstrap in nested modules since they are not called.\n const hookService = (appRef as any)._injector.get(HookService);\n hookService\n .call('openProjectAngularBootstrap')\n .forEach((results:{ selector:string, cls:any }[]) => {\n DynamicBootstrapper.bootstrapOptionalDocument(appRef, document, results);\n });\n }\n}\n\nexport function initializeServices(injector:Injector) {\n return () => {\n const PreviewTrigger = injector.get(PreviewTriggerService);\n const mainMenuNavigationService = injector.get(MainMenuNavigationService);\n const keyboardShortcuts = injector.get(KeyboardShortcutService);\n // Conditionally add the Revit Add-In settings button\n injector.get(RevitAddInSettingsButtonService);\n\n mainMenuNavigationService.register();\n\n PreviewTrigger.setupListener();\n\n keyboardShortcuts.register();\n };\n}\n","import {OpenProjectModule} from 'core-app/angular4-modules';\nimport {enableProdMode} from '@angular/core';\nimport * as jQuery from \"jquery\";\nimport {environment} from './environments/environment';\nimport {platformBrowserDynamic} from '@angular/platform-browser-dynamic';\nimport {SentryReporter} from \"core-app/sentry/sentry-reporter\";\nimport {whenDebugging} from \"core-app/helpers/debug_output\";\nimport {enableReactiveStatesLogging} from \"reactivestates\";\n\n(window as any).global = window;\n\n// Ensure we set the correct dynamic frontend path\n// based on the RAILS_RELATIVE_URL_ROOT setting\n// https://webpack.js.org/guides/public-path/\nconst ASSET_BASE_PATH = '/assets/frontend/';\n\n// Sets the relative base path\nwindow.appBasePath = jQuery('meta[name=app_base_path]').attr('content') || '';\n\n// Ensure to set the asset base for dynamic code loading\n// https://webpack.js.org/guides/public-path/\n__webpack_public_path__ = window.appBasePath + ASSET_BASE_PATH;\n\nwindow.ErrorReporter = new SentryReporter();\n\nrequire('core-app/init-vendors');\nrequire('core-app/init-globals');\n\nconst meta = jQuery('meta[name=openproject_initializer]');\nI18n.locale = meta.data('locale') || 'en';\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// Import the correct locale early on\nimport(`./locales/${I18n.locale}.js`)\n .then(() => {\n jQuery(function () {\n // Due to the behaviour of the Edge browser we need to wait for 'DOM ready'\n platformBrowserDynamic()\n .bootstrapModule(OpenProjectModule)\n .then(platformRef => {\n jQuery('body').addClass('__ng2-bootstrap-has-run');\n });\n });\n});\n","// -- copyright\n// OpenProject is an open source project management software.\n// Copyright (C) 2012-2020 the OpenProject GmbH\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License version 3.\n//\n// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:\n// Copyright (C) 2006-2013 Jean-Philippe Lang\n// Copyright (C) 2010-2013 the ChiliProject Team\n//\n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// 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 /** Internal state to push non-persisted updates */\n protected updatesState = input();\n\n /** Internal pristine state filled during +initialize+ only */\n protected pristineState = input();\n\n constructor(protected readonly querySpace:IsolatedQuerySpace) {\n }\n\n /**\n * Get the state value from the current query.\n *\n * @param {QueryResource} query\n * @returns {T} Instance of the state value for this type.\n */\n public abstract valueFromQuery(query:QueryResource, results:WorkPackageCollectionResource):T|undefined;\n\n /**\n * Initialize this table state from the given query resource,\n * and possibly the associated schema.\n *\n * @param {QueryResource} query\n * @param {QuerySchemaResource} schema\n */\n public initialize(query:QueryResource, results:WorkPackageCollectionResource, schema?:QuerySchemaResource) {\n const initial = this.valueFromQuery(query, results)!;\n this.pristineState.putValue(initial);\n }\n\n public update(value:T) {\n this.updatesState.putValue(value);\n }\n\n public clear(reason:string) {\n this.pristineState.clear(reason);\n this.updatesState.clear(reason);\n }\n\n /**\n * Get the combined pristine and update value changes\n * @param unsubscribe\n */\n public live$():Observable {\n return merge(\n this.pristineState.values$(),\n this.updatesState.values$(),\n );\n }\n\n /**\n * Get pristine upstream changes\n *\n * @param unsubscribe\n */\n public pristine$():Observable {\n return this\n .pristineState\n .values$();\n }\n\n /**\n * Get only the local update changes\n *\n * @param unsubscribe\n */\n public updates$():Observable {\n return this\n .updatesState\n .values$();\n }\n\n /**\n * Get only the local update changes\n *\n * @param unsubscribe\n */\n public changes$():Observable {\n return this\n .updatesState\n .changes$();\n }\n\n public onReady() {\n return this\n .pristineState\n .values$()\n .pipe(\n take(1),\n mapTo(null)\n )\n .toPromise();\n }\n\n /** Get the last updated value from either pristine or update state */\n protected get lastUpdatedState():State {\n const combinedRaw = combine(this.pristineState, this.updatesState);\n\n return deriveRaw(combinedRaw,\n ($) => $\n .pipe(\n map(([pristine, current]) => {\n if (current === undefined) {\n return pristine;\n }\n return current;\n })\n )\n );\n }\n\n /**\n * Helper to set the value of the current state\n * @param val\n */\n protected set current(val:T|undefined) {\n if (val) {\n this.updatesState.putValue(val);\n } else {\n this.updatesState.clear();\n }\n }\n\n /**\n * Get the value of the current state, if any.\n */\n protected get current():T|undefined {\n return this.lastUpdatedState.value;\n }\n}\n\n@Injectable()\nexport abstract class WorkPackageQueryStateService extends WorkPackageViewBaseService {\n /**\n * Check whether the state value does not match the query resource's value.\n * @param query The current query resource\n */\n abstract hasChanged(query:QueryResource):boolean;\n\n /**\n * Apply the current state value to query\n *\n * @return Whether the query should be visibly updated.\n */\n abstract applyToQuery(query:QueryResource):boolean;\n}\n"],"sourceRoot":"webpack:///"}