mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-18 14:47:38 +01:00
Refine the tabs in ellipsis code
Signed-off-by: AllForNothing <sshijun@vmware.com> Signed-off-by: Yogi_Wang <yawang@vmware.com>
This commit is contained in:
parent
6571135cbf
commit
ad67e45932
@ -105,4 +105,4 @@
|
||||
<button type="button" class="btn btn-primary" [disabled]="!isValid" (click)="onSave()">{{'BUTTON.SAVE' | translate}}</button>
|
||||
</div>
|
||||
|
||||
</clr-modal>
|
||||
</clr-modal>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<clr-tabs id="project-tabs" class="tabs" [class.in-overflow]="isTabLinkInOverFlow()">
|
||||
<ng-container *ngFor="let tab of tabLinkNavList;let i=index">
|
||||
<ng-container *ngIf="tab.permissions()">
|
||||
<clr-tab >
|
||||
<clr-tab>
|
||||
<button [class.clear-default-active]="isDefaultTab(tab, i)" [clrTabLinkInOverflow]="tab.tabLinkInOverflow" id="{{'project-'+tab.linkName}}" clrTabLink
|
||||
routerLink="{{tab.linkName}}" routerLinkActive="active" type="button">
|
||||
<a class="nav-link">{{tab.showTabName | translate}}</a></button>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<string>();
|
||||
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 = <Project>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();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
export const SHOW_ELLIPSIS_WIDTH = 80;
|
||||
export const DOWN: string = "down";
|
||||
export const UP: string = "up";
|
11
src/portal/src/css/common.scss
Normal file
11
src/portal/src/css/common.scss
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@import "./common.scss";
|
@ -1 +1,5 @@
|
||||
@import "../../node_modules/@clr/ui/clr-ui.min.css";
|
||||
// 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";
|
Loading…
Reference in New Issue
Block a user