From ad67e459325d1bd2bdc0bd4a2901b7e0746718d6 Mon Sep 17 00:00:00 2001 From: Yogi_Wang Date: Fri, 27 Dec 2019 16:27:15 +0800 Subject: [PATCH] Refine the tabs in ellipsis code Signed-off-by: AllForNothing Signed-off-by: Yogi_Wang --- .../member/add-group/add-group.component.html | 2 +- .../project-detail.component.html | 2 +- .../project-detail.component.scss | 13 --- .../project-detail.component.ts | 95 ++++++++++++++++--- .../project-detail/project-detail.const.ts | 3 + src/portal/src/css/common.scss | 11 +++ src/portal/src/css/dark-theme.scss | 6 +- src/portal/src/css/light-theme.scss | 6 +- 8 files changed, 107 insertions(+), 31 deletions(-) create mode 100644 src/portal/src/app/project/project-detail/project-detail.const.ts create mode 100644 src/portal/src/css/common.scss diff --git a/src/portal/src/app/project/member/add-group/add-group.component.html b/src/portal/src/app/project/member/add-group/add-group.component.html index 0432901e5..cb265b8a4 100644 --- a/src/portal/src/app/project/member/add-group/add-group.component.html +++ b/src/portal/src/app/project/member/add-group/add-group.component.html @@ -105,4 +105,4 @@ - \ No newline at end of file + diff --git a/src/portal/src/app/project/project-detail/project-detail.component.html b/src/portal/src/app/project/project-detail/project-detail.component.html index 69b5bd842..248973f18 100644 --- a/src/portal/src/app/project/project-detail/project-detail.component.html +++ b/src/portal/src/app/project/project-detail/project-detail.component.html @@ -6,7 +6,7 @@ - + diff --git a/src/portal/src/app/project/project-detail/project-detail.component.scss b/src/portal/src/app/project/project-detail/project-detail.component.scss index 8e771e1d4..0e7e8ab29 100644 --- a/src/portal/src/app/project/project-detail/project-detail.component.scss +++ b/src/portal/src/app/project/project-detail/project-detail.component.scss @@ -42,16 +42,3 @@ button { padding: 0; } } - -.in-overflow { - ::ng-deep { - .tabs-overflow { - > .nav-item { - > button { - box-shadow: 0 -3px 0 #0077b8 inset; - color: 0077b8; - } - } - } - } -} diff --git a/src/portal/src/app/project/project-detail/project-detail.component.ts b/src/portal/src/app/project/project-detail/project-detail.component.ts index 2422f8041..e6ea1cd1c 100644 --- a/src/portal/src/app/project/project-detail/project-detail.component.ts +++ b/src/portal/src/app/project/project-detail/project-detail.component.ts @@ -11,21 +11,24 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, HostListener, AfterViewInit, OnDestroy, ChangeDetectorRef } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { Project } from '../project'; import { SessionService } from '../../shared/session.service'; import { AppConfigService } from "../../app-config.service"; -import { forkJoin } from "rxjs"; -import { ProjectService, UserPermissionService, USERSTATICPERMISSION } from "../../../lib/services"; +import { forkJoin, Subject, Subscription } from "rxjs"; +import { UserPermissionService, USERSTATICPERMISSION } from "../../../lib/services"; import { ErrorHandler } from "../../../lib/utils/error-handler"; +import { debounceTime } from 'rxjs/operators'; +import { DOWN, SHOW_ELLIPSIS_WIDTH, UP } from './project-detail.const'; + + @Component({ selector: 'project-detail', templateUrl: 'project-detail.component.html', styleUrls: ['project-detail.component.scss'] }) -export class ProjectDetailComponent implements OnInit { - +export class ProjectDetailComponent implements OnInit, AfterViewInit, OnDestroy { hasSignedIn: boolean; currentProject: Project; @@ -89,29 +92,32 @@ export class ProjectDetailComponent implements OnInit { }, { linkName: "tag-strategy", - tabLinkInOverflow: true, + tabLinkInOverflow: false, showTabName: "PROJECT_DETAIL.TAG_STRATEGY", permissions: () => this.hasTagRetentionPermission }, { linkName: "robot-account", - tabLinkInOverflow: true, + tabLinkInOverflow: false, showTabName: "PROJECT_DETAIL.ROBOT_ACCOUNTS", permissions: () => this.hasRobotListPermission }, { linkName: "webhook", - tabLinkInOverflow: true, + tabLinkInOverflow: false, showTabName: "PROJECT_DETAIL.WEBHOOKS", permissions: () => this.hasWebhookListPermission }, { linkName: "logs", - tabLinkInOverflow: true, + tabLinkInOverflow: false, showTabName: "PROJECT_DETAIL.LOGS", permissions: () => this.hasLogListPermission } ]; + previousWindowWidth: number; + private _subject = new Subject(); + private _subscription: Subscription; constructor( private route: ActivatedRoute, private router: Router, @@ -119,8 +125,7 @@ export class ProjectDetailComponent implements OnInit { private appConfigService: AppConfigService, private userPermissionService: UserPermissionService, private errorHandler: ErrorHandler, - private projectService: ProjectService) { - + private cdf: ChangeDetectorRef) { this.hasSignedIn = this.sessionService.getCurrentUser() !== null; this.route.data.subscribe(data => { this.currentProject = data['projectResolver']; @@ -131,6 +136,32 @@ export class ProjectDetailComponent implements OnInit { ngOnInit() { this.projectId = this.route.snapshot.params['id']; this.getPermissionsList(this.projectId); + if (!this._subscription) { + this._subscription = this._subject.pipe( + debounceTime(100) + ).subscribe( + type => { + if (type === DOWN) { + this.resetTabsForDownSize(); + } else { + this.resetTabsForUpSize(); + } + } + ); + } + } + + ngAfterViewInit() { + this.previousWindowWidth = window.innerWidth; + setTimeout(() => { + this.resetTabsForDownSize(); + }, 0); + } + ngOnDestroy() { + if (this._subscription) { + this._subscription.unsubscribe(); + this._subscription = null; + } } getPermissionsList(projectId: number): void { let permissionsList = []; @@ -153,17 +184,17 @@ export class ProjectDetailComponent implements OnInit { permissionsList.push(this.userPermissionService.getPermission(projectId, USERSTATICPERMISSION.LABEL.KEY, USERSTATICPERMISSION.LABEL.VALUE.CREATE)); permissionsList.push(this.userPermissionService.getPermission(projectId, - USERSTATICPERMISSION.TAG_RETENTION.KEY, USERSTATICPERMISSION.TAG_RETENTION.VALUE.READ)); + USERSTATICPERMISSION.TAG_RETENTION.KEY, USERSTATICPERMISSION.TAG_RETENTION.VALUE.READ)); permissionsList.push(this.userPermissionService.getPermission(projectId, USERSTATICPERMISSION.WEBHOOK.KEY, USERSTATICPERMISSION.WEBHOOK.VALUE.LIST)); permissionsList.push(this.userPermissionService.getPermission(projectId, - USERSTATICPERMISSION.SCANNER.KEY, USERSTATICPERMISSION.SCANNER.VALUE.READ)); + USERSTATICPERMISSION.SCANNER.KEY, USERSTATICPERMISSION.SCANNER.VALUE.READ)); forkJoin(...permissionsList).subscribe(Rules => { [this.hasProjectReadPermission, this.hasLogListPermission, this.hasConfigurationListPermission, this.hasMemberListPermission , this.hasLabelListPermission, this.hasRepositoryListPermission, this.hasHelmChartsListPermission, this.hasRobotListPermission , this.hasLabelCreatePermission, this.hasTagRetentionPermission, this.hasWebhookListPermission, - this.hasScannerReadPermission] = Rules; + this.hasScannerReadPermission] = Rules; }, error => this.errorHandler.error(error)); } @@ -188,10 +219,46 @@ export class ProjectDetailComponent implements OnInit { isDefaultTab(tab, index) { return this.route.snapshot.children[0].routeConfig.path !== tab.linkName && index === 0; } + isTabLinkInOverFlow() { return this.tabLinkNavList.some(tab => { return tab.tabLinkInOverflow && this.route.snapshot.children[0].routeConfig.path === tab.linkName; }); } + @HostListener('window:resize', ['$event']) + onResize(event) { + if (this.previousWindowWidth) { + // down size + if (this.previousWindowWidth > event.target.innerWidth) { + this._subject.next(DOWN); + } else { // up size + this._subject.next(UP); + } + } + this.previousWindowWidth = event.target.innerWidth; + } + + resetTabsForDownSize(): void { + this.tabLinkNavList.filter(item => !item.tabLinkInOverflow).forEach((item, index) => { + const tabEle: HTMLElement = document.getElementById('project-' + item.linkName); + // strengthen code + if (tabEle && tabEle.getBoundingClientRect) { + const right: number = window.innerWidth - document.getElementById('project-' + item.linkName).getBoundingClientRect().right; + if (right < SHOW_ELLIPSIS_WIDTH) { + this.tabLinkNavList[index].tabLinkInOverflow = true; + } + } + }); + } + resetTabsForUpSize() { + // 1.Set tabLinkInOverflow to false for all tabs(show all tabs) + for ( let i = 0; i < this.tabLinkNavList.length; i++) { + this.tabLinkNavList[i].tabLinkInOverflow = false; + } + // 2.Manually detect changes to rerender dom + this.cdf.detectChanges(); + // 3. Hide overflowed tabs + this.resetTabsForDownSize(); + } } diff --git a/src/portal/src/app/project/project-detail/project-detail.const.ts b/src/portal/src/app/project/project-detail/project-detail.const.ts new file mode 100644 index 000000000..9d195ecb5 --- /dev/null +++ b/src/portal/src/app/project/project-detail/project-detail.const.ts @@ -0,0 +1,3 @@ +export const SHOW_ELLIPSIS_WIDTH = 80; +export const DOWN: string = "down"; +export const UP: string = "up"; diff --git a/src/portal/src/css/common.scss b/src/portal/src/css/common.scss new file mode 100644 index 000000000..06c40fdf5 --- /dev/null +++ b/src/portal/src/css/common.scss @@ -0,0 +1,11 @@ +// styles for dark and light theme should be defined here. +.in-overflow { + .tabs-overflow { + > .nav-item { + > button { + box-shadow: 0 -3px 0 $dark-active-tab-color inset; + color: 0077b8; + } + } + } +} \ No newline at end of file diff --git a/src/portal/src/css/dark-theme.scss b/src/portal/src/css/dark-theme.scss index 53999bf2e..2ecf4eb2c 100644 --- a/src/portal/src/css/dark-theme.scss +++ b/src/portal/src/css/dark-theme.scss @@ -1,7 +1,9 @@ +// Variables for dark theme should be defined here. @import "../../node_modules/@clr/ui/clr-ui-dark.min.css"; $dark-background-color: rgb(27, 42, 50) !important; $dark-font-color1: #acbac3 !important; $dark-font-color-title1: #eaedf0 !important; +$dark-active-tab-color: #4aaed9; .label-form { background-color: #212129 !important; @@ -110,4 +112,6 @@ clr-dg-action-overflow { color: #1b2a32; } } -} \ No newline at end of file +} + +@import "./common.scss"; \ No newline at end of file diff --git a/src/portal/src/css/light-theme.scss b/src/portal/src/css/light-theme.scss index b09e7465a..8d93ad912 100644 --- a/src/portal/src/css/light-theme.scss +++ b/src/portal/src/css/light-theme.scss @@ -1 +1,5 @@ -@import "../../node_modules/@clr/ui/clr-ui.min.css"; \ No newline at end of file +// Variables for dark theme should be defined here. +@import "../../node_modules/@clr/ui/clr-ui.min.css"; + +$dark-active-tab-color: #0077b8; +@import "./common.scss"; \ No newline at end of file