Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class ElementSelectAccountComponent implements OnInit, OnDestroy {
private _cdRef: ChangeDetectorRef
) {
this.usernamePlaceholder = this._i18n.instant('Username');
this.rememberAuthDisabled = !this._settingSvc.globalSetting.SECURITY_LUNA_REMEMBER_AUTH;
this.rememberAuthDisabled = false;
}

get noSecretAccounts() {
Expand Down
11 changes: 11 additions & 0 deletions src/app/elements/content/content-tab/content-tab.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,20 @@ li {
.view_icon {
margin-right: 5px;
font-style: normal;
display: flex;
width: 14px;
height: 14px;
align-items: center;
background-repeat: no-repeat;
background-position: center;
background-size: 14px 14px;
vertical-align: middle;

&::before {
display: inline-block;
width: 16px;
line-height: 16px;
text-align: center;
color: var(--el-icon-color);
font-family: FontAwesome;
}
Expand Down
70 changes: 64 additions & 6 deletions src/app/elements/content/content-tab/content-tab.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import {
ElementRef,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewChild
} from '@angular/core';
import { View, ViewAction } from '@app/model';
Expand All @@ -15,20 +17,23 @@ import { View, ViewAction } from '@app/model';
templateUrl: 'content-tab.component.html',
styleUrls: ['content-tab.component.scss']
})
export class ElementContentTabComponent implements OnInit {
export class ElementContentTabComponent implements OnInit, OnChanges {
@Input() view: View;
@Output() onAction: EventEmitter<ViewAction> = new EventEmitter<ViewAction>();
@ViewChild('inputElement', { static: false }) inputElement: ElementRef;

public iconCls: string;
public iconCls: string[] = [];
private shouldFocusInput = false;
private clickTimeout: any;
private static faIconCache = new Map<string, boolean>();

ngOnInit(): void {
if (!this.view.asset) {
this.iconCls = 'fa-linux';
} else {
this.iconCls = 'fa-' + this.view.asset.type.value;
this.updateIconClasses();
}

ngOnChanges(changes: SimpleChanges): void {
if (changes.view) {
this.updateIconClasses();
}
}

Expand Down Expand Up @@ -70,4 +75,57 @@ export class ElementContentTabComponent implements OnInit {
this.view.editable = false;
}, 200);
}

private updateIconClasses(): void {
const iconKey = this.view?.asset?.type?.value || 'linux';
const faClass = `fa-${iconKey}`;
const fallbackClass = this.getFallbackIconClass(iconKey);
const hasFontAwesome = this.hasFontAwesomeIcon(faClass);

this.iconCls = hasFontAwesome ? ['fa', faClass] : [fallbackClass];
}

private getFallbackIconClass(iconKey: string): string {
const normalizedKey = iconKey || 'linux';
const overrides: Record<string, string> = {
general: 'switch_ico_docu',
website: 'website_ico_docu',
sqlserver: 'sqlserver_ico_docu',
postgresql: 'postgresql_ico_docu',
mysql: 'mysql_ico_docu',
mariadb: 'mariadb_ico_docu',
mongodb: 'mongodb_ico_docu',
webcloud: 'WebCloud_ico_docu',
web_cloud: 'WebCloud_ico_docu',
'web-cloud': 'WebCloud_ico_docu'
};

return overrides[normalizedKey] || `${normalizedKey}_ico_docu`;
}

private hasFontAwesomeIcon(iconClass: string): boolean {
const cached = ElementContentTabComponent.faIconCache.get(iconClass);
if (cached !== undefined) {
return cached;
}

if (typeof document === 'undefined' || typeof window === 'undefined') {
return true;
}

const el = document.createElement('i');
el.className = `view_icon fa ${iconClass}`;
el.style.position = 'absolute';
el.style.opacity = '0';
el.style.pointerEvents = 'none';
document.body.appendChild(el);

const content = window.getComputedStyle(el, '::before').getPropertyValue('content');
document.body.removeChild(el);

const normalizedContent = (content || '').replace(/['"]/g, '');
const hasContent = normalizedContent !== '' && normalizedContent !== 'none' && normalizedContent !== 'normal';
ElementContentTabComponent.faIconCache.set(iconClass, hasContent);
return hasContent;
}
}
17 changes: 15 additions & 2 deletions src/app/elements/content/content.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
<span (click)="toggleMenu.emit()" class="mobile-menu-icon">
<i class="fa fa-sitemap"></i>
</span>

<div class="scroll-button">
<a (click)="scrollLeft()" class="left"><i class="fa fa-caret-left"></i></a>
<a (click)="scrollRight()" class="right"><i class="fa fa-caret-right"></i></a>
<a (click)="scrollLeft()" class="left action-btn"><i class="fa fa-caret-left"></i></a>
<a (click)="scrollRight()" class="right action-btn"><i class="fa fa-caret-right"></i></a>
</div>

<div #tabs class="tabs">
<ul
(cdkDropListDropped)="onItemDropped($event)"
Expand All @@ -27,6 +29,17 @@
</elements-content-tab>
</ul>
</div>

@if (viewList.length > 0) {
<nz-icon
nz-tooltip
[nzTooltipTitle]="'Full screen' | translate"
nzType="fullscreen"
nzTheme="outline"
class="action-btn fullscreen-icon"
(click)="handleFullscreen()"
/>
}
</div>
<div [ngClass]="{ 'batch-input': showBatchCommand }" id="winContainer">
<div
Expand Down
19 changes: 16 additions & 3 deletions src/app/elements/content/content.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@
border-left: 1px solid var(--el-border-color-x);

.tab-bar {
a {
color: white;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
width: 100%;
background-color: var(--el-tab-bg-color);

.action-btn {
cursor: pointer;
color: #fff;
}

.scroll-button {
Expand All @@ -30,6 +38,7 @@

.tabs {
display: flex;
flex: 1;
position: relative;
height: 30px;
overflow-y: hidden;
Expand All @@ -42,7 +51,7 @@
min-width: 100%;
padding-left: 0;
margin: 0;
background-color: var(--el-tab-bg-color);


.drag-box {
display: inline-flex;
Expand All @@ -60,6 +69,10 @@
}
}
}

.fullscreen-icon {
margin: 0 12px;
}
}

#winContainer {
Expand Down
22 changes: 20 additions & 2 deletions src/app/elements/content/content.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ export class ElementContentComponent implements OnInit, OnDestroy {
this.tabsRef.nativeElement.scrollLeft = this.tabsRef.nativeElement.scrollWidth;
}

trackByFn(index, item) {
return item.id;
trackByFn(index, id) {
return id;
}

rTabMenuItems() {
Expand Down Expand Up @@ -350,4 +350,22 @@ export class ElementContentComponent implements OnInit, OnDestroy {
onItemDropped(event: CdkDragDrop<string[]>) {
moveItemInArray(this.viewIds, event.previousIndex, event.currentIndex);
}

handleFullscreen() {
const ele: any = document.getElementsByClassName('window active')[0];

if (!ele) return;

const requestFullscreen =
ele.requestFullscreen ||
ele.webkitRequestFullscreen ||
ele.mozRequestFullScreen ||
ele.msRequestFullscreen;

if (!requestFullscreen) {
throw new Error('不支持全屏api');
}

requestFullscreen.call(ele);
}
}
1 change: 1 addition & 0 deletions src/app/elements/nav/setting/setting.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
</nz-form-item>
</div>
</div>

<div *ngIf="type === 'cli'">
<nz-form-item>
<nz-form-label [nzSm]="8" [nzXs]="24">
Expand Down
13 changes: 12 additions & 1 deletion src/app/services/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export class AppService {
private protocolPreferKey = 'ProtocolPreferLoginType';
private accountPreferKey = 'PreferAccount';
private protocolConnectTypesMap: object = {};
private connectMethodsRequestSeq = 0;
private connectMethodsAppliedSeq = 0;
private checkIntervalId: number;
private newLoginHasOpen = false; // 避免多次打开新登录页
private checkSecond = 120;
Expand Down Expand Up @@ -202,13 +204,21 @@ export class AppService {

getConnectMethods(): Promise<void> {
const url = '/api/v1/terminal/components/connect-methods/';
const requestSeq = ++this.connectMethodsRequestSeq;

// 当用户先打开 luna 并进行操作时如果后在 lina 中去设置连接方式的 ACL 此时并不生效,因此修改为在 toPromise 后直接赋值
return this._http
.get(url)
.toPromise()
.then(response => {
// 每次发起请求都自增 connectMethodsRequestSeq,记录当前请求序号 requestSeq
// 响应回来时,如果 requestSeq 小于已经应用过的 connectMethodsAppliedSeq,说明这是“过期响应”,直接丢弃
// 只有最新的响应才会更新 protocolConnectTypesMap,并把 connectMethodsAppliedSeq 同步为最新
if (requestSeq < this.connectMethodsAppliedSeq) {
return;
}
this.protocolConnectTypesMap = response;
this.connectMethodsAppliedSeq = requestSeq;
})
.catch(error => {
this._logger.error('Get connect methods error:', error);
Expand Down Expand Up @@ -258,6 +268,7 @@ export class AppService {
connectOption,
direct: connectData.direct
};

this.setAccountLocalAuth(asset, account, manualAuthInfo);
this._localStorage.set(key, saveData);
}
Expand Down Expand Up @@ -346,7 +357,7 @@ export class AppService {
newAuth.alias = account.alias;
}

if (!auth.secret || !auth.rememberAuth || !this._settingSvc.globalSetting.SECURITY_LUNA_REMEMBER_AUTH) {
if (!auth.secret || !auth.rememberAuth) {
newAuth.secret = '';
} else {
newAuth.secret = this.encrypt(auth.secret);
Expand Down
Loading