From 7af56a66b5cc70afdff6e1cc5c822f5ac13a7ea5 Mon Sep 17 00:00:00 2001 From: Henriette Dinger Date: Mon, 21 Oct 2019 09:23:57 +0200 Subject: [PATCH] Extract a single card as separate component --- .../styles/wp-card-view-vertical.sass | 6 - .../styles/wp-card-view.component.sass | 79 ------------- .../wp-card-view/wp-card-view.component.html | 80 ++----------- .../wp-card-view/wp-card-view.component.ts | 70 ----------- .../wp-single-card.component.html | 69 +++++++++++ .../wp-single-card.component.sass | 87 ++++++++++++++ .../wp-single-card.component.ts | 110 ++++++++++++++++++ .../openproject-work-packages.module.ts | 4 + 8 files changed, 280 insertions(+), 225 deletions(-) create mode 100644 frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.html create mode 100644 frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.sass create mode 100644 frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts diff --git a/frontend/src/app/components/wp-card-view/styles/wp-card-view-vertical.sass b/frontend/src/app/components/wp-card-view/styles/wp-card-view-vertical.sass index 31b4ace9ba..40415060b1 100644 --- a/frontend/src/app/components/wp-card-view/styles/wp-card-view-vertical.sass +++ b/frontend/src/app/components/wp-card-view/styles/wp-card-view-vertical.sass @@ -10,9 +10,3 @@ // independently of whether we scroll or not. overflow-y: scroll @include styled-scroll-bar - - .wp-card - margin-top: 10px - // Take care that the shadow of the last element is still visible - &:last-of-type - margin-bottom: 3px diff --git a/frontend/src/app/components/wp-card-view/styles/wp-card-view.component.sass b/frontend/src/app/components/wp-card-view/styles/wp-card-view.component.sass index 9804b1b8dd..5628ea04dc 100644 --- a/frontend/src/app/components/wp-card-view/styles/wp-card-view.component.sass +++ b/frontend/src/app/components/wp-card-view/styles/wp-card-view.component.sass @@ -1,86 +1,7 @@ -@import 'helpers' - -.wp-card - display: flex - flex-direction: column - user-select: none - width: 100% - border: 1px solid var(--widget-box-block-border-color) - border-radius: 2px - padding: 10px - position: relative - box-shadow: 1px 1px 3px 0px lightgrey - background: var(--body-background) - font-size: var(--card-font-size) - max-width: 400px - - &:hover - box-shadow: 0px 0px 10px lightgrey - - &.-new - padding-right: 25px - - &.-checked - background-color: var(--table-row-highlighting-color) - -.wp-card--content:not(.-new) - display: grid - grid-template-columns: auto 1fr auto - grid-template-rows: auto 1fr auto - grid-row-gap: 10px - grid-template-areas: "type type type" "subject subject subject" "attributeTag avatar idlink" - overflow: hidden - flex-grow: 1 - - .wp-card--type - grid-area: type - .wp-card--subject - grid-area: subject - max-width: 230px - @include text-shortener - white-space: normal - .wp-card--assignee - grid-area: avatar - place-self: center left - .wp-card--id - grid-area: idlink - place-self: center right - .wp-card--status - grid-area: attributeTag - max-width: 120px - margin-right: 5px - overflow: hidden - -.wp-card--highlighting - width: 5px - height: 100% - position: absolute - top: 0 - left: 0 - border-radius: 2px 0 0 2px - .wp-inline-create-button font-size: 0.9rem padding-top: 1rem text-align: center -.wp-card--inline-buttons - position: absolute - right: 0 - top: 5px - opacity: 0 - - &.-show, .wp-card:hover & - opacity: 1 - .wp-inline-create--reference-container margin-bottom: 3rem - -.wp-card--cover-image - display: block - margin: -10px -10px 10px - width: calc(100% + 10px + 10px) - max-width: calc(100% + 10px + 10px) - - flex-basis: 200px - object-fit: cover diff --git a/frontend/src/app/components/wp-card-view/wp-card-view.component.html b/frontend/src/app/components/wp-card-view/wp-card-view.component.html index cdf5385b9b..a9221caaaa 100644 --- a/frontend/src/app/components/wp-card-view/wp-card-view.component.html +++ b/frontend/src/app/components/wp-card-view/wp-card-view.component.html @@ -8,76 +8,16 @@ -
- -
-
- -
- - - - - - - -
- - -
- - - - -
-
- - - -
- - - #{{wp.id}} - - - - - - -
-
+ +
diff --git a/frontend/src/app/components/wp-card-view/wp-card-view.component.ts b/frontend/src/app/components/wp-card-view/wp-card-view.component.ts index 38f2c7a166..a49233eaa3 100644 --- a/frontend/src/app/components/wp-card-view/wp-card-view.component.ts +++ b/frontend/src/app/components/wp-card-view/wp-card-view.component.ts @@ -5,7 +5,6 @@ import { Component, ElementRef, EventEmitter, - Inject, Injector, Input, OnInit, @@ -21,8 +20,6 @@ import {I18nService} from "core-app/modules/common/i18n/i18n.service"; import {WorkPackageInlineCreateService} from "core-components/wp-inline-create/wp-inline-create.service"; import {WorkPackageCreateService} from "core-components/wp-new/wp-create.service"; import {AngularTrackingHelpers} from "core-components/angular/tracking-functions"; -import {HalResourceNotificationService} from "core-app/modules/hal/services/hal-resource-notification.service"; -import {Highlighting} from "core-components/wp-fast-table/builders/highlighting/highlighting.functions"; import {CardHighlightingMode} from "core-components/wp-fast-table/builders/highlighting/highlighting-mode.const"; import {AuthorisationService} from "core-app/modules/common/model-auth/model-auth.service"; import {StateService} from "@uirouter/core"; @@ -35,7 +32,6 @@ import {WorkPackageViewSelectionService} from "core-app/modules/work_packages/ro import {CardViewHandlerRegistry} from "core-components/wp-card-view/event-handler/card-view-handler-registry"; import {WorkPackageCardViewService} from "core-components/wp-card-view/services/wp-card-view.service"; import {WorkPackageCardDragAndDropService} from "core-components/wp-card-view/services/wp-card-drag-and-drop.service"; -import {checkedClassName, uiStateLinkClass} from "core-components/wp-fast-table/builders/ui-state-link-builder"; import {WorkPackageNotificationService} from "core-app/modules/work_packages/notifications/work-package-notification.service"; export type CardViewOrientation = 'horizontal'|'vertical'; @@ -75,12 +71,8 @@ export class WorkPackageCardViewComponent implements OnInit, AfterViewInit { title: this.I18n.t('js.work_packages.no_results.title'), description: this.I18n.t('js.work_packages.no_results.description') }, - detailsView: this.I18n.t('js.button_open_details') }; - public uiStateLinkClass:string = uiStateLinkClass; - public checkedClassName:string = checkedClassName; - /** Inline create / reference properties */ public canAdd = false; public canReference = false; @@ -162,68 +154,6 @@ export class WorkPackageCardViewComponent implements OnInit, AfterViewInit { this.cardDragDrop.destroy(); } - public openSplitScreen(wp:WorkPackageResource) { - let classIdentifier = this.classIdentifier(wp); - this.wpTableSelection.setSelection(wp.id!, this.cardView.findRenderedCard(classIdentifier)); - this.$state.go( - 'work-packages.list.details', - {workPackageId: wp.id!} - ); - } - - public wpTypeAttribute(wp:WorkPackageResource) { - return wp.type.name; - } - - public wpSubject(wp:WorkPackageResource) { - return wp.subject; - } - - public isSelected(wp:WorkPackageResource):boolean { - return this.wpTableSelection.isSelected(wp.id!); - } - - public classIdentifier(wp:WorkPackageResource) { - return this.cardView.classIdentifier(wp); - } - - public bcfSnapshotPath(wp:WorkPackageResource) { - let vp = _.get(wp, 'bcf.viewpoints[0]'); - if (vp) { - return this.pathHelper.attachmentDownloadPath(vp.id, vp.file_name); - } else { - return null; - } - } - - - public cardClasses(wp:WorkPackageResource) { - let classes = this.isSelected(wp) ? checkedClassName : ''; - classes += this.canDragOutOf(wp) ? ' -draggable' : ''; - classes += wp.isNew ? ' -new' : ''; - classes += ' wp-card-' + wp.id; - return classes; - } - - public cardHighlightingClass(wp:WorkPackageResource) { - return this.cardHighlighting(wp); - } - - public typeHighlightingClass(wp:WorkPackageResource) { - return this.attributeHighlighting('type', wp); - } - - private cardHighlighting(wp:WorkPackageResource) { - if (['status', 'priority', 'type'].includes(this.highlightingMode)) { - return Highlighting.backgroundClass(this.highlightingMode, wp[this.highlightingMode].id); - } - return ''; - } - - private attributeHighlighting(type:string, wp:WorkPackageResource) { - return Highlighting.inlineClass(type, wp.type.id!); - } - public get workPackages():WorkPackageResource[] { return this.cardDragDrop.workPackages; } diff --git a/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.html b/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.html new file mode 100644 index 0000000000..ea2f998b79 --- /dev/null +++ b/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.html @@ -0,0 +1,69 @@ +
+ +
+
+ +
+ + + + + + + +
+ + +
+ + + + +
+
+ + + + +
\ No newline at end of file diff --git a/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.sass b/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.sass new file mode 100644 index 0000000000..df1687d8eb --- /dev/null +++ b/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.sass @@ -0,0 +1,87 @@ +@import 'helpers' + +.wp-card + display: flex + flex-direction: column + user-select: none + width: 100% + border: 1px solid var(--widget-box-block-border-color) + border-radius: 2px + padding: 10px + position: relative + box-shadow: 1px 1px 3px 0px lightgrey + background: var(--body-background) + font-size: var(--card-font-size) + max-width: 400px + + &:hover + box-shadow: 0px 0px 10px lightgrey + + &.-new + padding-right: 25px + + &.-checked + background-color: var(--table-row-highlighting-color) + + &.-horizontal + height: 100% + + &.-vertical + margin-top: 10px + // Take care that the shadow of the last element is still visible + &:last-of-type + margin-bottom: 3px + +.wp-card--content:not(.-new) + display: grid + grid-template-columns: auto 1fr auto + grid-template-rows: auto 1fr auto + grid-row-gap: 10px + grid-template-areas: "type type type" "subject subject subject" "attributeTag avatar idlink" + overflow: hidden + flex-grow: 1 + + .wp-card--type + grid-area: type + .wp-card--subject + grid-area: subject + max-width: 230px + @include text-shortener + white-space: normal + .wp-card--assignee + grid-area: avatar + place-self: center left + .wp-card--id + grid-area: idlink + place-self: center right + .wp-card--status + grid-area: attributeTag + max-width: 120px + margin-right: 5px + overflow: hidden + +.wp-card--highlighting + width: 5px + height: 100% + position: absolute + top: 0 + left: 0 + border-radius: 2px 0 0 2px + +.wp-card--inline-buttons + position: absolute + right: 0 + top: 5px + opacity: 0 + + &.-show, .wp-card:hover & + opacity: 1 + +.wp-card--cover-image + display: block + margin: -10px -10px 10px + width: calc(100% + 10px + 10px) + max-width: calc(100% + 10px + 10px) + + flex-basis: 200px + object-fit: cover diff --git a/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts b/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts new file mode 100644 index 0000000000..598d3acf49 --- /dev/null +++ b/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts @@ -0,0 +1,110 @@ +import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from "@angular/core"; +import {WorkPackageResource} from "core-app/modules/hal/resources/work-package-resource"; +import {checkedClassName, uiStateLinkClass} from "core-components/wp-fast-table/builders/ui-state-link-builder"; +import {PathHelperService} from "core-app/modules/common/path-helper/path-helper.service"; +import {Highlighting} from "core-components/wp-fast-table/builders/highlighting/highlighting.functions"; +import {StateService} from "@uirouter/core"; +import {WorkPackageViewSelectionService} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-selection.service"; +import {WorkPackageCardViewService} from "core-components/wp-card-view/services/wp-card-view.service"; +import {I18nService} from "core-app/modules/common/i18n/i18n.service"; +import {CardHighlightingMode} from "core-components/wp-fast-table/builders/highlighting/highlighting-mode.const"; +import {CardViewOrientation} from "core-components/wp-card-view/wp-card-view.component"; + + +@Component({ + selector: 'wp-single-card', + styleUrls: ['./wp-single-card.component.sass'], + templateUrl: './wp-single-card.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class WorkPackageSingleCardComponent { + @Input() public workPackage:WorkPackageResource; + @Input() public showInfoButton:boolean = false; + @Input() public showStatusButton:boolean = true; + @Input() public showRemoveButton:boolean = false; + @Input() public highlightingMode:CardHighlightingMode = 'inline'; + @Input() public draggable:boolean = false; + @Input() public orientation:CardViewOrientation = 'vertical'; + + @Output() public onRemove = new EventEmitter(); + + public uiStateLinkClass:string = uiStateLinkClass; + + public text = { + removeCard: this.I18n.t('js.card.remove_from_list'), + detailsView: this.I18n.t('js.button_open_details') + }; + + constructor(readonly pathHelper:PathHelperService, + readonly I18n:I18nService, + readonly $state:StateService, + readonly wpTableSelection:WorkPackageViewSelectionService, + readonly cardView:WorkPackageCardViewService,) { + } + + public classIdentifier(wp:WorkPackageResource) { + return this.cardView.classIdentifier(wp); + } + + public openSplitScreen(wp:WorkPackageResource) { + let classIdentifier = this.classIdentifier(wp); + this.wpTableSelection.setSelection(wp.id!, this.cardView.findRenderedCard(classIdentifier)); + this.$state.go( + 'work-packages.list.details', + {workPackageId: wp.id!} + ); + } + + public cardClasses(wp:WorkPackageResource) { + let classes = this.isSelected(wp) ? checkedClassName : ''; + classes += this.draggable ? ' -draggable' : ''; + classes += wp.isNew ? ' -new' : ''; + classes += ' wp-card-' + wp.id; + classes += ' -' + this.orientation; + return classes; + } + + public isSelected(wp:WorkPackageResource):boolean { + return this.wpTableSelection.isSelected(wp.id!); + } + + public wpTypeAttribute(wp:WorkPackageResource) { + return wp.type.name; + } + + public wpSubject(wp:WorkPackageResource) { + return wp.subject; + } + + public cardHighlightingClass(wp:WorkPackageResource) { + return this.cardHighlighting(wp); + } + + public typeHighlightingClass(wp:WorkPackageResource) { + return this.attributeHighlighting('type', wp); + } + + public onRemoved(wp:WorkPackageResource) { + this.onRemove.emit(wp); + } + + public bcfSnapshotPath(wp:WorkPackageResource) { + let vp = _.get(wp, 'bcf.viewpoints[0]'); + if (vp) { + return this.pathHelper.attachmentDownloadPath(vp.id, vp.file_name); + } else { + return null; + } + } + + private cardHighlighting(wp:WorkPackageResource) { + if (['status', 'priority', 'type'].includes(this.highlightingMode)) { + return Highlighting.backgroundClass(this.highlightingMode, wp[this.highlightingMode].id); + } + return ''; + } + + private attributeHighlighting(type:string, wp:WorkPackageResource) { + return Highlighting.inlineClass(type, wp.type.id!); + } +} diff --git a/frontend/src/app/modules/work_packages/openproject-work-packages.module.ts b/frontend/src/app/modules/work_packages/openproject-work-packages.module.ts index 03c7422cc1..96eb9caf8a 100644 --- a/frontend/src/app/modules/work_packages/openproject-work-packages.module.ts +++ b/frontend/src/app/modules/work_packages/openproject-work-packages.module.ts @@ -162,6 +162,7 @@ import {WorkPackageNotificationService} from "core-app/modules/work_packages/not import {WorkPackageEditActionsBarComponent} from "core-app/modules/common/edit-actions-bar/wp-edit-actions-bar.component"; import {HalResource} from "core-app/modules/hal/resources/hal-resource"; import {WorkPackageChangeset} from "core-components/wp-edit/work-package-changeset"; +import {WorkPackageSingleCardComponent} from "core-components/wp-card-view/wp-single-card/wp-single-card.component"; @NgModule({ @@ -375,6 +376,7 @@ import {WorkPackageChangeset} from "core-components/wp-edit/work-package-changes // Card view WorkPackageCardViewComponent, + WorkPackageSingleCardComponent, WorkPackageViewToggleButton, ], entryComponents: [ @@ -451,6 +453,7 @@ import {WorkPackageChangeset} from "core-components/wp-edit/work-package-changes // Card view WorkPackageCardViewComponent, + WorkPackageSingleCardComponent, CustomDateActionAdminComponent, ], @@ -460,6 +463,7 @@ import {WorkPackageChangeset} from "core-components/wp-edit/work-package-changes WorkPackageEmbeddedTableComponent, WorkPackageEmbeddedTableEntryComponent, WorkPackageCardViewComponent, + WorkPackageSingleCardComponent, WorkPackageFilterButtonComponent, WorkPackageFilterContainerComponent, WorkPackageIsolatedQuerySpaceDirective,