mirror of
https://github.com/Eugeny/tabby-web.git
synced 2025-06-23 20:59:58 +00:00
wip
This commit is contained in:
parent
e9738aed8d
commit
87748ab5ec
backend/tabby/app
frontend
package.json
src
app.module.ts
tsconfig.jsonwebpack.config.base.jswebpack.config.jsyarn.lockassets/screenshots
components
demoTerminal.component.scssdemoTerminal.component.tshome.component.pughome.component.scsshome.component.tshomeFeatures.component.pughomeFeatures.component.scsshomeFeatures.component.tshomeIndex.component.pughomeIndex.component.scsshomeIndex.component.ts
theme
@ -15,7 +15,7 @@ urlpatterns = [
|
|||||||
path('api/1/instance-info', api.InstanceInfoViewSet.as_view({'get': 'retrieve'})),
|
path('api/1/instance-info', api.InstanceInfoViewSet.as_view({'get': 'retrieve'})),
|
||||||
path('api/1/gateways/choose', api.ChooseGatewayViewSet.as_view({'post': 'retrieve'})),
|
path('api/1/gateways/choose', api.ChooseGatewayViewSet.as_view({'post': 'retrieve'})),
|
||||||
|
|
||||||
re_path('^(|login|app)$', views.IndexView.as_view()),
|
re_path('^(|login|app|about|features)$', views.IndexView.as_view()),
|
||||||
path('terminal', views.TerminalView.as_view()),
|
path('terminal', views.TerminalView.as_view()),
|
||||||
|
|
||||||
path('app-dist/<version>/<path:path>', views.AppDistView.as_view()),
|
path('app-dist/<version>/<path:path>', views.AppDistView.as_view()),
|
||||||
|
@ -69,9 +69,11 @@
|
|||||||
"throng": "^5.0.0",
|
"throng": "^5.0.0",
|
||||||
"typescript": "~4.1",
|
"typescript": "~4.1",
|
||||||
"val-loader": "^4.0.0",
|
"val-loader": "^4.0.0",
|
||||||
|
"vanta": "^0.5.21",
|
||||||
"webpack": "^5.38.1",
|
"webpack": "^5.38.1",
|
||||||
"webpack-bundle-analyzer": "^4.4.2",
|
"webpack-bundle-analyzer": "^4.4.2",
|
||||||
"webpack-cli": "^4.7.2",
|
"webpack-cli": "^4.7.2",
|
||||||
|
"three": "^0.119.0",
|
||||||
"zone.js": "^0.11.4"
|
"zone.js": "^0.11.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
import { NgbDropdownModule, NgbModalModule } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbDropdownModule, NgbModalModule, NgbNavModule } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { BrowserModule } from '@angular/platform-browser'
|
import { BrowserModule } from '@angular/platform-browser'
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
import { CommonModule } from '@angular/common'
|
import { CommonModule } from '@angular/common'
|
||||||
@ -16,10 +16,13 @@ import { AppComponent } from './components/app.component'
|
|||||||
import { MainComponent } from './components/main.component'
|
import { MainComponent } from './components/main.component'
|
||||||
import { ConfigModalComponent } from './components/configModal.component'
|
import { ConfigModalComponent } from './components/configModal.component'
|
||||||
import { SettingsModalComponent } from './components/settingsModal.component'
|
import { SettingsModalComponent } from './components/settingsModal.component'
|
||||||
import { HomeComponent } from './components/home.component'
|
import { HomeComponent, HomeComponentPreloadResolver } from './components/home.component'
|
||||||
import { LoginComponent } from './components/login.component'
|
import { LoginComponent } from './components/login.component'
|
||||||
import { ConnectionListComponent } from './components/connectionList.component'
|
import { ConnectionListComponent } from './components/connectionList.component'
|
||||||
import { UpgradeModalComponent } from './components/upgradeModal.component'
|
import { UpgradeModalComponent } from './components/upgradeModal.component'
|
||||||
|
import { HomeIndexComponent } from './components/homeIndex.component'
|
||||||
|
import { DemoTerminalComponent } from './components/demoTerminal.component'
|
||||||
|
import { HomeFeaturesComponent } from './components/homeFeatures.component'
|
||||||
import { InstanceInfoResolver } from './api'
|
import { InstanceInfoResolver } from './api'
|
||||||
|
|
||||||
import '@fortawesome/fontawesome-svg-core/styles.css'
|
import '@fortawesome/fontawesome-svg-core/styles.css'
|
||||||
@ -30,7 +33,18 @@ const ROUTES = [
|
|||||||
component: HomeComponent,
|
component: HomeComponent,
|
||||||
resolve: {
|
resolve: {
|
||||||
instanceInfo: InstanceInfoResolver,
|
instanceInfo: InstanceInfoResolver,
|
||||||
|
preload: HomeComponentPreloadResolver,
|
||||||
},
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: HomeIndexComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'features',
|
||||||
|
component: HomeFeaturesComponent,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'app',
|
path: 'app',
|
||||||
@ -61,6 +75,7 @@ const ROUTES = [
|
|||||||
HttpClientXsrfModule,
|
HttpClientXsrfModule,
|
||||||
NgbDropdownModule,
|
NgbDropdownModule,
|
||||||
NgbModalModule,
|
NgbModalModule,
|
||||||
|
NgbNavModule,
|
||||||
FontAwesomeModule,
|
FontAwesomeModule,
|
||||||
ClipboardModule,
|
ClipboardModule,
|
||||||
NgxImageZoomModule,
|
NgxImageZoomModule,
|
||||||
@ -74,11 +89,13 @@ const ROUTES = [
|
|||||||
AppComponent,
|
AppComponent,
|
||||||
MainComponent,
|
MainComponent,
|
||||||
HomeComponent,
|
HomeComponent,
|
||||||
|
HomeIndexComponent,
|
||||||
LoginComponent,
|
LoginComponent,
|
||||||
ConfigModalComponent,
|
ConfigModalComponent,
|
||||||
SettingsModalComponent,
|
SettingsModalComponent,
|
||||||
ConnectionListComponent,
|
ConnectionListComponent,
|
||||||
UpgradeModalComponent,
|
UpgradeModalComponent,
|
||||||
|
DemoTerminalComponent,
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
|
BIN
frontend/src/assets/screenshots/progress.png
Normal file
BIN
frontend/src/assets/screenshots/progress.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 73 KiB |
BIN
frontend/src/assets/screenshots/zmodem.png
Normal file
BIN
frontend/src/assets/screenshots/zmodem.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 23 KiB |
16
frontend/src/components/demoTerminal.component.scss
Normal file
16
frontend/src/components/demoTerminal.component.scss
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
@import "../theme/vars.scss";
|
||||||
|
|
||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: $body-bg;
|
||||||
|
box-shadow: 0 0 2px black, 0 0 50px #6ef2ff05, 0 0 150px #6854ff14;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
flex: auto;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
102
frontend/src/components/demoTerminal.component.ts
Normal file
102
frontend/src/components/demoTerminal.component.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { Subject } from 'rxjs'
|
||||||
|
import * as semverCompare from 'semver/functions/compare-loose'
|
||||||
|
import { HttpClient } from '@angular/common/http'
|
||||||
|
import { Component, ElementRef, ViewChild } from '@angular/core'
|
||||||
|
import { Version } from '../api'
|
||||||
|
import { CommonService } from '../services/common.service'
|
||||||
|
|
||||||
|
class DemoConnector {
|
||||||
|
constructor (
|
||||||
|
targetWindow: Window,
|
||||||
|
private commonService: CommonService,
|
||||||
|
private version: Version,
|
||||||
|
) {
|
||||||
|
targetWindow['tabbyWebDemoDataPath'] = `${this.getDistURL()}/${version.version}/tabby-web-demo/data`
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadConfig (): Promise<string> {
|
||||||
|
return `{
|
||||||
|
recoverTabs: false,
|
||||||
|
web: {
|
||||||
|
preventAccidentalTabClosure: false,
|
||||||
|
},
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
async saveConfig (_content: string): Promise<void> { }
|
||||||
|
|
||||||
|
getAppVersion (): string {
|
||||||
|
return this.version.version
|
||||||
|
}
|
||||||
|
|
||||||
|
getDistURL (): string {
|
||||||
|
return this.commonService.backendURL + '/app-dist'
|
||||||
|
}
|
||||||
|
|
||||||
|
getPluginsToLoad (): string[] {
|
||||||
|
return [
|
||||||
|
'tabby-core',
|
||||||
|
'tabby-settings',
|
||||||
|
'tabby-terminal',
|
||||||
|
'tabby-community-color-schemes',
|
||||||
|
'tabby-ssh',
|
||||||
|
'tabby-telnet',
|
||||||
|
'tabby-web',
|
||||||
|
'tabby-web-demo',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
createSocket () {
|
||||||
|
return new DemoSocketProxy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class DemoSocketProxy {
|
||||||
|
connect$ = new Subject<void>()
|
||||||
|
data$ = new Subject<Buffer>()
|
||||||
|
error$ = new Subject<Buffer>()
|
||||||
|
close$ = new Subject<Buffer>()
|
||||||
|
|
||||||
|
async connect (options) {
|
||||||
|
this.error$.next(new Error('This web demo can\'t actually access Internet, but feel free to download the release and try it out!'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'demo-terminal',
|
||||||
|
template: '<iframe #iframe></iframe>',
|
||||||
|
styleUrls: ['./demoTerminal.component.scss'],
|
||||||
|
})
|
||||||
|
export class DemoTerminalComponent {
|
||||||
|
@ViewChild('iframe') iframe: ElementRef
|
||||||
|
connector: DemoConnector
|
||||||
|
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private http: HttpClient,
|
||||||
|
private commonService: CommonService,
|
||||||
|
) {
|
||||||
|
window.addEventListener('message', this.connectorRequestHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
connectorRequestHandler = event => {
|
||||||
|
if (event.data === 'request-connector') {
|
||||||
|
this.iframe.nativeElement.contentWindow['__connector__'] = this.connector
|
||||||
|
this.iframe.nativeElement.contentWindow.postMessage('connector-ready', '*')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngAfterViewInit (): Promise<void> {
|
||||||
|
const versions = await this.http.get('/api/1/versions').toPromise()
|
||||||
|
versions.sort((a, b) => -semverCompare(a.version, b.version))
|
||||||
|
this.connector = new DemoConnector(this.iframe.nativeElement.contentWindow, this.commonService, versions[0])
|
||||||
|
this.iframe.nativeElement.src = '/terminal'
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy (): void {
|
||||||
|
window.removeEventListener('message', this.connectorRequestHandler)
|
||||||
|
}
|
||||||
|
}
|
@ -1,159 +1,32 @@
|
|||||||
.top-half
|
.top-half
|
||||||
.navbar
|
.container.overflow-hidden
|
||||||
img.brand(src='{{_logo}}')
|
.navbar
|
||||||
.me-auto
|
img.brand(src='{{_logo}}')
|
||||||
a.btn.btn-primary([href]='releaseURL', target='_blank')
|
.me-auto
|
||||||
fa-icon([icon]='_downloadIcon', [fixedWidth]='true')
|
a.btn.btn-primary([href]='releaseURL', target='_blank')
|
||||||
span Download
|
fa-icon([icon]='_downloadIcon', [fixedWidth]='true')
|
||||||
a.btn.btn-secondary([href]='donationURL', target='_blank')
|
span Download
|
||||||
fa-icon([icon]='_donateIcon', [fixedWidth]='true')
|
a.btn.btn-secondary([href]='donationURL', target='_blank')
|
||||||
span Donate
|
fa-icon([icon]='_donateIcon', [fixedWidth]='true')
|
||||||
a.btn.btn-secondary(routerLink='/login', *ngIf='instanceInfo.login_enabled')
|
span Donate
|
||||||
fa-icon([icon]='_loginIcon', [fixedWidth]='true')
|
a.btn.btn-secondary(routerLink='/login', *ngIf='instanceInfo.login_enabled')
|
||||||
span Login
|
fa-icon([icon]='_loginIcon', [fixedWidth]='true')
|
||||||
|
span Login
|
||||||
|
|
||||||
|
ul.nav-pills.mb-4(ngbNav, [activeId]='router.url')
|
||||||
|
li([ngbNavItem]='link.link', *ngFor='let link of navLinks')
|
||||||
|
a(ngbNavLink, routerLink='.', [routerLink]='link.link') {{ link.title }}
|
||||||
|
|
||||||
.container
|
.container
|
||||||
.intro
|
div(*ngIf='router.url == "/"')
|
||||||
h1 Hey.
|
.intro
|
||||||
div My name is Eugene and I've built a nice terminal app, #[em.ms-1 just for you].
|
h1 Hey.
|
||||||
div Crossplatform, local, SSH, serial, Telnet - it's all there.
|
div My name is Eugene and I've built a nice terminal app, #[em.ms-1 just for you].
|
||||||
div Here's a demo 👇
|
div Crossplatform, local, SSH, serial, Telnet - it's all there.
|
||||||
|
div Here's a demo 👇
|
||||||
|
|
||||||
iframe(#iframe)
|
demo-terminal
|
||||||
|
|
||||||
.bottom-half
|
.bottom-half
|
||||||
.container
|
.demo-offset(*ngIf='router.url == "/"')
|
||||||
.d-flex.m-auto.mb-5
|
router-outlet
|
||||||
a.btn.btn-lg.btn-primary.ms-auto.me-3([href]='releaseURL', target='_blank')
|
|
||||||
fa-icon([icon]='_downloadIcon', [fixedWidth]='true')
|
|
||||||
span Latest release
|
|
||||||
|
|
||||||
a.btn.btn-lg.btn-secondary.me-auto([href]='githubURL', target='_blank')
|
|
||||||
fa-icon([icon]='_githubIcon', [fixedWidth]='true')
|
|
||||||
span GitHub
|
|
||||||
|
|
||||||
.quotes
|
|
||||||
.quote
|
|
||||||
.text "reasonable"
|
|
||||||
.author — Michael
|
|
||||||
|
|
||||||
.quote
|
|
||||||
.text "cool"
|
|
||||||
.author — some dude on my ko-fi
|
|
||||||
|
|
||||||
.quote
|
|
||||||
.text "very cool"
|
|
||||||
.author — datsukan
|
|
||||||
|
|
||||||
.section.section-a
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-12.col-xl-6
|
|
||||||
lib-ngx-image-zoom(
|
|
||||||
[fullImage]='screenshots.window',
|
|
||||||
[thumbImage]='screenshots.window'
|
|
||||||
)
|
|
||||||
.col-12.col-xl-6
|
|
||||||
h1 The important stuff
|
|
||||||
ul
|
|
||||||
li Runs on #[strong Windows, Mac and Linux]
|
|
||||||
li Integrated #[strong SSH client] with a connection manager
|
|
||||||
li Integrated #[strong serial terminal]
|
|
||||||
li PowerShell, PS Core, WSL, Git-Bash, Cygwin, Cmder and CMD support
|
|
||||||
li Full #[strong Unicode support] including double-width characters
|
|
||||||
li File transfer from/to SSH sessions via #[strong SFTP and Zmodem]
|
|
||||||
li Theming and color schemes
|
|
||||||
li Fully #[strong configurable shortcuts] and multi-chord shortcuts
|
|
||||||
li #[strong Remembers your tabs] and split panes
|
|
||||||
li Proper shell experience on Windows including #[strong tab completion]
|
|
||||||
li Integrated #[strong encrypted container] for SSH secrets and configuration
|
|
||||||
|
|
||||||
.section.section-b
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-12.col-xl-6
|
|
||||||
h1 Terminal features
|
|
||||||
ul
|
|
||||||
li Multiple #[strong nested panes]
|
|
||||||
li #[strong Progress bars] and activity notifications for tabs
|
|
||||||
li Tabby remembers open tabs and panes where you left off
|
|
||||||
li Tabs on #[strong any side of the window]
|
|
||||||
li Optional #[strong quake mode] (terminal docked to a side of the screen)
|
|
||||||
li Optional #[strong global hotkey] to focus/hide the terminal
|
|
||||||
li Bracketed paste
|
|
||||||
.col-12.col-xl-6
|
|
||||||
lib-ngx-image-zoom(
|
|
||||||
[fullImage]='screenshots.tabs',
|
|
||||||
[thumbImage]='screenshots.tabs'
|
|
||||||
)
|
|
||||||
|
|
||||||
.section.section-a
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-12.col-xl-6
|
|
||||||
lib-ngx-image-zoom(
|
|
||||||
[fullImage]='screenshots.ssh',
|
|
||||||
[thumbImage]='screenshots.ssh'
|
|
||||||
)
|
|
||||||
.col-12.col-xl-6
|
|
||||||
h1 SSH Client
|
|
||||||
ul
|
|
||||||
li SSH2 client with a connection manager
|
|
||||||
li #[strong SFTP and Zmodem] file transfers
|
|
||||||
li #[strong X11] and #[strong port forwarding]
|
|
||||||
li Jump hosts
|
|
||||||
li #[strong Agent forwarding] - including Pageant and Windows native OpenSSH Agent
|
|
||||||
li Login scripts
|
|
||||||
li Optional built-in #[strong password manager] with a master passphrase
|
|
||||||
li #[strong Proxy command] support
|
|
||||||
|
|
||||||
.section.section-b
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-12.col-xl-6
|
|
||||||
h1 Windows, but nice
|
|
||||||
ul
|
|
||||||
li Support for #[strong different shells] in the same window
|
|
||||||
li Better tab completion #[strong cmd.exe] thanks to Clink.
|
|
||||||
li Explorer menu integration
|
|
||||||
li Optional #[strong portable mode]
|
|
||||||
li Current directory detection that works
|
|
||||||
.col-12.col-xl-6
|
|
||||||
lib-ngx-image-zoom(
|
|
||||||
[fullImage]='screenshots.win',
|
|
||||||
[thumbImage]='screenshots.win'
|
|
||||||
)
|
|
||||||
|
|
||||||
.section.section-a
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-12.col-xl-6
|
|
||||||
lib-ngx-image-zoom(
|
|
||||||
[fullImage]='screenshots.serial',
|
|
||||||
[thumbImage]='screenshots.serial'
|
|
||||||
)
|
|
||||||
.col-12.col-xl-6
|
|
||||||
h1 Serial Terminal
|
|
||||||
ul
|
|
||||||
li Multiple #[strong connection profiles]
|
|
||||||
li Newline conversion
|
|
||||||
li Text, #[strong readline] and #[strong byte-by-byte] input modes
|
|
||||||
li Text and #[strong hexdump] output modes
|
|
||||||
li Zmodem
|
|
||||||
li Non-standard baud rates
|
|
||||||
|
|
||||||
.section.section-a
|
|
||||||
.container
|
|
||||||
h1 And just too much stuff to mention here:
|
|
||||||
ul
|
|
||||||
li Themes #[strong customizable with CSS]
|
|
||||||
li Extensible via #[strong plugins] (in JS)
|
|
||||||
li A bunch of color schemes already included
|
|
||||||
li Telnet client
|
|
||||||
li #[strong Font ligatures] and font fallback
|
|
||||||
li #[strong Clickable URLs], IPs and paths
|
|
||||||
li #[strong WinSCP] integration
|
|
||||||
li Shell #[strong profiles]
|
|
||||||
li Simultaneous #[strong multi-pane input]
|
|
||||||
li Optional PuTTY style #[strong right-click paste] and #[strong copy on select]
|
|
||||||
li macOS vibrancy and Win 10 fluent background support
|
|
||||||
|
@ -4,18 +4,33 @@
|
|||||||
:host {
|
:host {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-family: 'Fira Code', monospace;
|
font-family: 'Fira Code', monospace;
|
||||||
|
position: absolute;
|
||||||
button, a, .quote {
|
width: 100vw;
|
||||||
font-family: $font-family-sans-serif;
|
height: 100vh;
|
||||||
}
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-half {
|
.top-half {
|
||||||
background: linear-gradient(#0c141c, #15202b);
|
background: linear-gradient(#0c141c00, #15202b);
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 80px;
|
font-size: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 0 35px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-offset {
|
||||||
|
padding-top: 24vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-half {
|
||||||
|
background: $body-bg;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar {
|
.navbar {
|
||||||
@ -31,87 +46,11 @@
|
|||||||
width: 32px;
|
width: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
demo-terminal {
|
||||||
font-family: $font-family-monospace;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 48px;
|
|
||||||
text-shadow: 0 0 1px black;
|
|
||||||
margin: 0 0 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.intro {
|
|
||||||
width: 60vw;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
iframe {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
width: calc(min(max(480px, 60vw), 100vw));
|
||||||
|
height: calc(max(460px, 42vw));
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 20vw;
|
top: 20vw;
|
||||||
margin-top: -16vw;
|
margin-top: -16vw;
|
||||||
|
|
||||||
width: calc(min(max(480px, 60vw), 100vw));
|
|
||||||
height: calc(max(460px, 42vw));
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 5px;
|
|
||||||
box-shadow: 0 0 2px black, 0 0 50px #6ef2ff05, 0 0 150px #6854ff14;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.bottom-half {
|
|
||||||
padding-top: 24vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quotes {
|
|
||||||
margin: 50px 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.quote {
|
|
||||||
margin: 0 30px;
|
|
||||||
|
|
||||||
.text {
|
|
||||||
font-size: 50px;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.author {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
& { display: none;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
background: #849dff;
|
|
||||||
font-weight: normal;
|
|
||||||
padding: 2px 7px;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section {
|
|
||||||
padding: 50px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-a {
|
|
||||||
background: rgba(0, 0, 0, .5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-b {
|
|
||||||
}
|
|
||||||
|
|
||||||
::ng-deep lib-ngx-image-zoom {
|
|
||||||
width: 100%;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
img {
|
|
||||||
min-width: 100px;
|
|
||||||
max-width: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,72 +1,7 @@
|
|||||||
import { Subject } from 'rxjs'
|
import { Component, Injectable } from '@angular/core'
|
||||||
import * as semverCompare from 'semver/functions/compare-loose'
|
import { ActivatedRoute, Router, Resolve } from '@angular/router'
|
||||||
import { HttpClient } from '@angular/common/http'
|
|
||||||
import { Component, ElementRef, ViewChild } from '@angular/core'
|
|
||||||
import { InstanceInfo, Version } from '../api'
|
|
||||||
import { faCoffee, faDownload, faSignInAlt } from '@fortawesome/free-solid-svg-icons'
|
import { faCoffee, faDownload, faSignInAlt } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { faGithub } from '@fortawesome/free-brands-svg-icons'
|
import { InstanceInfo } from '../api'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
|
||||||
import { CommonService } from '../services/common.service'
|
|
||||||
|
|
||||||
|
|
||||||
class DemoConnector {
|
|
||||||
constructor (
|
|
||||||
targetWindow: Window,
|
|
||||||
private commonService: CommonService,
|
|
||||||
private version: Version,
|
|
||||||
) {
|
|
||||||
targetWindow['tabbyWebDemoDataPath'] = `${this.getDistURL()}/${version.version}/tabby-web-demo/data`
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadConfig (): Promise<string> {
|
|
||||||
return `{
|
|
||||||
recoverTabs: false,
|
|
||||||
web: {
|
|
||||||
preventAccidentalTabClosure: false,
|
|
||||||
},
|
|
||||||
}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
||||||
async saveConfig (_content: string): Promise<void> { }
|
|
||||||
|
|
||||||
getAppVersion (): string {
|
|
||||||
return this.version.version
|
|
||||||
}
|
|
||||||
|
|
||||||
getDistURL (): string {
|
|
||||||
return this.commonService.backendURL + '/app-dist'
|
|
||||||
}
|
|
||||||
|
|
||||||
getPluginsToLoad (): string[] {
|
|
||||||
return [
|
|
||||||
'tabby-core',
|
|
||||||
'tabby-settings',
|
|
||||||
'tabby-terminal',
|
|
||||||
'tabby-community-color-schemes',
|
|
||||||
'tabby-ssh',
|
|
||||||
'tabby-telnet',
|
|
||||||
'tabby-web',
|
|
||||||
'tabby-web-demo',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
createSocket () {
|
|
||||||
return new DemoSocketProxy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export class DemoSocketProxy {
|
|
||||||
connect$ = new Subject<void>()
|
|
||||||
data$ = new Subject<Buffer>()
|
|
||||||
error$ = new Subject<Buffer>()
|
|
||||||
close$ = new Subject<Buffer>()
|
|
||||||
|
|
||||||
async connect (options) {
|
|
||||||
this.error$.next(new Error('This web demo can\'t actually access Internet, but feel free to download the release and try it out!'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -75,8 +10,6 @@ export class DemoSocketProxy {
|
|||||||
styleUrls: ['./home.component.scss'],
|
styleUrls: ['./home.component.scss'],
|
||||||
})
|
})
|
||||||
export class HomeComponent {
|
export class HomeComponent {
|
||||||
@ViewChild('iframe') iframe: ElementRef
|
|
||||||
connector: DemoConnector
|
|
||||||
githubURL = 'https://github.com/Eugeny/tabby'
|
githubURL = 'https://github.com/Eugeny/tabby'
|
||||||
releaseURL = `${this.githubURL}/releases/latest`
|
releaseURL = `${this.githubURL}/releases/latest`
|
||||||
donationURL = 'https://ko-fi.com/eugeny'
|
donationURL = 'https://ko-fi.com/eugeny'
|
||||||
@ -84,48 +17,55 @@ export class HomeComponent {
|
|||||||
_logo = require('../assets/logo.svg')
|
_logo = require('../assets/logo.svg')
|
||||||
_downloadIcon = faDownload
|
_downloadIcon = faDownload
|
||||||
_loginIcon = faSignInAlt
|
_loginIcon = faSignInAlt
|
||||||
_githubIcon = faGithub
|
|
||||||
_donateIcon = faCoffee
|
_donateIcon = faCoffee
|
||||||
|
|
||||||
screenshots = {
|
navLinks = [
|
||||||
window: require('../assets/screenshots/window.png'),
|
{
|
||||||
tabs: require('../assets/screenshots/tabs.png'),
|
title: 'About Tabby',
|
||||||
ssh: require('../assets/screenshots/ssh.png'),
|
link: '/'
|
||||||
serial: require('../assets/screenshots/serial.png'),
|
},
|
||||||
win: require('../assets/screenshots/win.png'),
|
{
|
||||||
}
|
title: 'Features',
|
||||||
|
link: '/features'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
instanceInfo: InstanceInfo
|
instanceInfo: InstanceInfo
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private http: HttpClient,
|
public route: ActivatedRoute,
|
||||||
private commonService: CommonService,
|
public router: Router,
|
||||||
route: ActivatedRoute,
|
|
||||||
router: Router,
|
|
||||||
) {
|
) {
|
||||||
window.addEventListener('message', this.connectorRequestHandler)
|
|
||||||
this.instanceInfo = route.snapshot.data.instanceInfo
|
this.instanceInfo = route.snapshot.data.instanceInfo
|
||||||
if (!this.instanceInfo.homepage_enabled) {
|
if (!this.instanceInfo.homepage_enabled) {
|
||||||
router.navigate(['/app'])
|
router.navigate(['/app'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static async preload () {
|
||||||
connectorRequestHandler = event => {
|
const three = await import(/* webpackChunkName: "gfx" */ 'three')
|
||||||
if (event.data === 'request-connector') {
|
window['THREE'] = three
|
||||||
this.iframe.nativeElement.contentWindow['__connector__'] = this.connector
|
await import(/* webpackChunkName: "gfx" */ 'vanta/src/vanta.waves.js')
|
||||||
this.iframe.nativeElement.contentWindow.postMessage('connector-ready', '*')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngAfterViewInit (): Promise<void> {
|
async ngAfterViewInit (): Promise<void> {
|
||||||
const versions = await this.http.get('/api/1/versions').toPromise()
|
window['VANTA'].WAVES({
|
||||||
versions.sort((a, b) => -semverCompare(a.version, b.version))
|
el: 'body',
|
||||||
this.connector = new DemoConnector(this.iframe.nativeElement.contentWindow, this.commonService, versions[0])
|
mouseControls: true,
|
||||||
this.iframe.nativeElement.src = '/terminal'
|
touchControls: true,
|
||||||
}
|
gyroControls: false,
|
||||||
|
minHeight: 200.00,
|
||||||
ngOnDestroy (): void {
|
minWidth: 200.00,
|
||||||
window.removeEventListener('message', this.connectorRequestHandler)
|
scale: 1.00,
|
||||||
|
scaleMobile: 1.00,
|
||||||
|
color: 0x70f
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class HomeComponentPreloadResolver implements Resolve<Promise<void>> {
|
||||||
|
resolve () {
|
||||||
|
return HomeComponent.preload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
frontend/src/components/homeFeatures.component.pug
Normal file
17
frontend/src/components/homeFeatures.component.pug
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
.container.mt-5.mb-5
|
||||||
|
h1 Features
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-12.col-md-4
|
||||||
|
.card.bg-dark
|
||||||
|
img.card-img-top([src]='screenshots.progress')
|
||||||
|
.card-body
|
||||||
|
h5.card-title Smart tabs
|
||||||
|
.card-text Tabs that detect progress and can notify you when a process is done.
|
||||||
|
|
||||||
|
.col-12.col-md-4
|
||||||
|
.card.bg-dark
|
||||||
|
img.card-img-top([src]='screenshots.zmodem')
|
||||||
|
.card-body
|
||||||
|
h5.card-title Zmodem transfers
|
||||||
|
.card-text Full support for Zmodem transfers in SSH, telnet and serial connections.
|
3
frontend/src/components/homeFeatures.component.scss
Normal file
3
frontend/src/components/homeFeatures.component.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
:host {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
13
frontend/src/components/homeFeatures.component.ts
Normal file
13
frontend/src/components/homeFeatures.component.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Component } from '@angular/core'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'home-features',
|
||||||
|
templateUrl: './homeFeatures.component.pug',
|
||||||
|
styleUrls: ['./homeFeatures.component.scss'],
|
||||||
|
})
|
||||||
|
export class HomeFeaturesComponent {
|
||||||
|
screenshots = {
|
||||||
|
progress: require('../assets/screenshots/progress.png'),
|
||||||
|
zmodem: require('../assets/screenshots/zmodem.png'),
|
||||||
|
}
|
||||||
|
}
|
135
frontend/src/components/homeIndex.component.pug
Normal file
135
frontend/src/components/homeIndex.component.pug
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
.container
|
||||||
|
.d-flex.m-auto.mb-5
|
||||||
|
a.btn.btn-lg.btn-primary.ms-auto.me-3([href]='releaseURL', target='_blank')
|
||||||
|
fa-icon([icon]='_downloadIcon', [fixedWidth]='true')
|
||||||
|
span Latest release
|
||||||
|
|
||||||
|
a.btn.btn-lg.btn-secondary.me-auto([href]='githubURL', target='_blank')
|
||||||
|
fa-icon([icon]='_githubIcon', [fixedWidth]='true')
|
||||||
|
span GitHub
|
||||||
|
|
||||||
|
.quotes
|
||||||
|
.quote
|
||||||
|
.text "reasonable"
|
||||||
|
.author — Michael
|
||||||
|
|
||||||
|
.quote
|
||||||
|
.text "cool"
|
||||||
|
.author — some dude on my ko-fi
|
||||||
|
|
||||||
|
.quote
|
||||||
|
.text "very cool"
|
||||||
|
.author — datsukan
|
||||||
|
|
||||||
|
.section.section-a
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col-12.col-xl-6
|
||||||
|
lib-ngx-image-zoom(
|
||||||
|
[fullImage]='screenshots.window',
|
||||||
|
[thumbImage]='screenshots.window'
|
||||||
|
)
|
||||||
|
.col-12.col-xl-6
|
||||||
|
h1 The important stuff
|
||||||
|
ul
|
||||||
|
li Runs on #[strong Windows, Mac and Linux]
|
||||||
|
li Integrated #[strong SSH client] with a connection manager
|
||||||
|
li Integrated #[strong serial terminal]
|
||||||
|
li PowerShell, PS Core, WSL, Git-Bash, Cygwin, Cmder and CMD support
|
||||||
|
li Full #[strong Unicode support] including double-width characters
|
||||||
|
li File transfer from/to SSH sessions via #[strong SFTP and Zmodem]
|
||||||
|
li Theming and color schemes
|
||||||
|
li Fully #[strong configurable shortcuts] and multi-chord shortcuts
|
||||||
|
li #[strong Remembers your tabs] and split panes
|
||||||
|
li Proper shell experience on Windows including #[strong tab completion]
|
||||||
|
li Integrated #[strong encrypted container] for SSH secrets and configuration
|
||||||
|
|
||||||
|
.section.section-b
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col-12.col-xl-6
|
||||||
|
h1 Terminal features
|
||||||
|
ul
|
||||||
|
li Multiple #[strong nested panes]
|
||||||
|
li #[strong Progress bars] and activity notifications for tabs
|
||||||
|
li Tabby remembers open tabs and panes where you left off
|
||||||
|
li Tabs on #[strong any side of the window]
|
||||||
|
li Optional #[strong quake mode] (terminal docked to a side of the screen)
|
||||||
|
li Optional #[strong global hotkey] to focus/hide the terminal
|
||||||
|
li Bracketed paste
|
||||||
|
.col-12.col-xl-6
|
||||||
|
lib-ngx-image-zoom(
|
||||||
|
[fullImage]='screenshots.tabs',
|
||||||
|
[thumbImage]='screenshots.tabs'
|
||||||
|
)
|
||||||
|
|
||||||
|
.section.section-a
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col-12.col-xl-6
|
||||||
|
lib-ngx-image-zoom(
|
||||||
|
[fullImage]='screenshots.ssh',
|
||||||
|
[thumbImage]='screenshots.ssh'
|
||||||
|
)
|
||||||
|
.col-12.col-xl-6
|
||||||
|
h1 SSH Client
|
||||||
|
ul
|
||||||
|
li SSH2 client with a connection manager
|
||||||
|
li #[strong SFTP and Zmodem] file transfers
|
||||||
|
li #[strong X11] and #[strong port forwarding]
|
||||||
|
li Jump hosts
|
||||||
|
li #[strong Agent forwarding] - including Pageant and Windows native OpenSSH Agent
|
||||||
|
li Login scripts
|
||||||
|
li Optional built-in #[strong password manager] with a master passphrase
|
||||||
|
li #[strong Proxy command] support
|
||||||
|
|
||||||
|
.section.section-b
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col-12.col-xl-6
|
||||||
|
h1 Windows, but nice
|
||||||
|
ul
|
||||||
|
li Support for #[strong different shells] in the same window
|
||||||
|
li Better tab completion #[strong cmd.exe] thanks to Clink.
|
||||||
|
li Explorer menu integration
|
||||||
|
li Optional #[strong portable mode]
|
||||||
|
li Current directory detection that works
|
||||||
|
.col-12.col-xl-6
|
||||||
|
lib-ngx-image-zoom(
|
||||||
|
[fullImage]='screenshots.win',
|
||||||
|
[thumbImage]='screenshots.win'
|
||||||
|
)
|
||||||
|
|
||||||
|
.section.section-a
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col-12.col-xl-6
|
||||||
|
lib-ngx-image-zoom(
|
||||||
|
[fullImage]='screenshots.serial',
|
||||||
|
[thumbImage]='screenshots.serial'
|
||||||
|
)
|
||||||
|
.col-12.col-xl-6
|
||||||
|
h1 Serial Terminal
|
||||||
|
ul
|
||||||
|
li Multiple #[strong connection profiles]
|
||||||
|
li Newline conversion
|
||||||
|
li Text, #[strong readline] and #[strong byte-by-byte] input modes
|
||||||
|
li Text and #[strong hexdump] output modes
|
||||||
|
li Zmodem
|
||||||
|
li Non-standard baud rates
|
||||||
|
|
||||||
|
.section.section-a
|
||||||
|
.container
|
||||||
|
h1 And just too much stuff to mention here:
|
||||||
|
ul
|
||||||
|
li Themes #[strong customizable with CSS]
|
||||||
|
li Extensible via #[strong plugins] (in JS)
|
||||||
|
li A bunch of color schemes already included
|
||||||
|
li Telnet client
|
||||||
|
li #[strong Font ligatures] and font fallback
|
||||||
|
li #[strong Clickable URLs], IPs and paths
|
||||||
|
li #[strong WinSCP] integration
|
||||||
|
li Shell #[strong profiles]
|
||||||
|
li Simultaneous #[strong multi-pane input]
|
||||||
|
li Optional PuTTY style #[strong right-click paste] and #[strong copy on select]
|
||||||
|
li macOS vibrancy and Win 10 fluent background support
|
71
frontend/src/components/homeIndex.component.scss
Normal file
71
frontend/src/components/homeIndex.component.scss
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
@import "../theme/vars.scss";
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-family: $font-family-monospace;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 48px;
|
||||||
|
text-shadow: 0 0 1px black;
|
||||||
|
margin: 0 0 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button, a, .quote {
|
||||||
|
font-family: $font-family-sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
width: 60vw;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quotes {
|
||||||
|
margin: 50px 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.quote {
|
||||||
|
margin: 0 30px;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: 50px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.author {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
& { display: none;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
background: #849dff;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 2px 7px;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
padding: 50px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-a {
|
||||||
|
background: rgba(0, 0, 0, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-b {
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep lib-ngx-image-zoom {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
img {
|
||||||
|
min-width: 100px;
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
24
frontend/src/components/homeIndex.component.ts
Normal file
24
frontend/src/components/homeIndex.component.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Component } from '@angular/core'
|
||||||
|
import { faDownload } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { faGithub } from '@fortawesome/free-brands-svg-icons'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'home-index',
|
||||||
|
templateUrl: './homeIndex.component.pug',
|
||||||
|
styleUrls: ['./homeIndex.component.scss'],
|
||||||
|
})
|
||||||
|
export class HomeIndexComponent {
|
||||||
|
githubURL = 'https://github.com/Eugeny/tabby'
|
||||||
|
releaseURL = `${this.githubURL}/releases/latest`
|
||||||
|
|
||||||
|
_downloadIcon = faDownload
|
||||||
|
_githubIcon = faGithub
|
||||||
|
|
||||||
|
screenshots = {
|
||||||
|
window: require('../assets/screenshots/window.png'),
|
||||||
|
tabs: require('../assets/screenshots/tabs.png'),
|
||||||
|
ssh: require('../assets/screenshots/ssh.png'),
|
||||||
|
serial: require('../assets/screenshots/serial.png'),
|
||||||
|
win: require('../assets/screenshots/win.png'),
|
||||||
|
}
|
||||||
|
}
|
@ -17,11 +17,11 @@
|
|||||||
@import "~bootstrap/scss/transitions";
|
@import "~bootstrap/scss/transitions";
|
||||||
@import "~bootstrap/scss/dropdown";
|
@import "~bootstrap/scss/dropdown";
|
||||||
@import "~bootstrap/scss/button-group";
|
@import "~bootstrap/scss/button-group";
|
||||||
// @import "~bootstrap/scss/nav";
|
@import "~bootstrap/scss/nav";
|
||||||
// @import "~bootstrap/scss/navbar";
|
// @import "~bootstrap/scss/navbar";
|
||||||
@import "~bootstrap/scss/card";
|
@import "~bootstrap/scss/card";
|
||||||
// @import "~bootstrap/scss/accordion";
|
// @import "~bootstrap/scss/accordion";
|
||||||
// @import "~bootstrap/scss/breadcrum/b";
|
// @import "~bootstrap/scss/breadcrumb";
|
||||||
// @import "~bootstrap/scss/pagination";
|
// @import "~bootstrap/scss/pagination";
|
||||||
@import "~bootstrap/scss/badge";
|
@import "~bootstrap/scss/badge";
|
||||||
@import "~bootstrap/scss/alert";
|
@import "~bootstrap/scss/alert";
|
||||||
@ -58,6 +58,10 @@
|
|||||||
background-color: $gray-700;
|
background-color: $gray-700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.dropdown-menu {
|
.dropdown-menu {
|
||||||
box-shadow: $dropdown-box-shadow;
|
box-shadow: $dropdown-box-shadow;
|
||||||
|
@ -140,6 +140,8 @@ $nav-tabs-link-active-color: #eee;
|
|||||||
$nav-tabs-link-active-bg: transparent;
|
$nav-tabs-link-active-bg: transparent;
|
||||||
$nav-tabs-link-active-border-color: #eee;
|
$nav-tabs-link-active-border-color: #eee;
|
||||||
|
|
||||||
|
$nav-pills-link-active-bg: rgba(255, 255, 255, .125);
|
||||||
|
|
||||||
$navbar-padding-y: 0;
|
$navbar-padding-y: 0;
|
||||||
$navbar-padding-x: 0;
|
$navbar-padding-x: 0;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src/",
|
"baseUrl": "src/",
|
||||||
"module": "es2015",
|
"module": "esnext",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
|
@ -59,5 +59,8 @@ module.exports = {
|
|||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
BACKEND_URL: JSON.stringify(process.env.BACKEND_URL || ''),
|
BACKEND_URL: JSON.stringify(process.env.BACKEND_URL || ''),
|
||||||
}),
|
}),
|
||||||
|
new webpack.ProvidePlugin({
|
||||||
|
THREE: 'three',
|
||||||
|
})
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ module.exports = {
|
|||||||
new AngularWebpackPlugin({
|
new AngularWebpackPlugin({
|
||||||
tsconfig: 'tsconfig.json',
|
tsconfig: 'tsconfig.json',
|
||||||
directTemplateLoading: false,
|
directTemplateLoading: false,
|
||||||
skipCodeGeneration: false,
|
jitMode: false,
|
||||||
}),
|
}),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
template: './src/index.html',
|
template: './src/index.html',
|
||||||
|
@ -953,11 +953,6 @@ async-foreach@^0.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
|
resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
|
||||||
integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=
|
integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=
|
||||||
|
|
||||||
async@~3.2.0:
|
|
||||||
version "3.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.1.tgz#d3274ec66d107a47476a4c49136aacdb00665fc8"
|
|
||||||
integrity sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==
|
|
||||||
|
|
||||||
asynckit@^0.4.0:
|
asynckit@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
@ -2903,13 +2898,6 @@ lru-cache@^6.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
|
|
||||||
lru-cache@~5.1.1:
|
|
||||||
version "5.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
|
|
||||||
integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
|
|
||||||
dependencies:
|
|
||||||
yallist "^3.0.2"
|
|
||||||
|
|
||||||
magic-string@^0.25.0:
|
magic-string@^0.25.0:
|
||||||
version "0.25.7"
|
version "0.25.7"
|
||||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
|
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
|
||||||
@ -3076,20 +3064,6 @@ ms@2.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
|
|
||||||
mustache-express@^1.3.1:
|
|
||||||
version "1.3.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/mustache-express/-/mustache-express-1.3.1.tgz#b5144513ab79a503c87aa8cb16fe019d2f61d9f9"
|
|
||||||
integrity sha512-RSSzrvM+CVAk9217dkWSNYyl6c2JnesNn6zaZ8+FvZSn8aLxY9l4kTnYqIoiE8GxdLyVQL2ak7XlMZS6t/l8YA==
|
|
||||||
dependencies:
|
|
||||||
async "~3.2.0"
|
|
||||||
lru-cache "~5.1.1"
|
|
||||||
mustache "^4.2.0"
|
|
||||||
|
|
||||||
mustache@^4.2.0:
|
|
||||||
version "4.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64"
|
|
||||||
integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==
|
|
||||||
|
|
||||||
nan@^2.13.2:
|
nan@^2.13.2:
|
||||||
version "2.14.2"
|
version "2.14.2"
|
||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
||||||
@ -4572,6 +4546,11 @@ text-table@^0.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||||
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
|
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
|
||||||
|
|
||||||
|
three@^0.119.0:
|
||||||
|
version "0.119.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/three/-/three-0.119.1.tgz#9d979a082c4cd9622af8e3498a8dfa026a619332"
|
||||||
|
integrity sha512-GHyh/RiUfQ5VTiWIVRRTANYoXc1PFB1y+jDVRTb649nif1uX1F06PT1TKU3k2+F/MN4UJ3PWvQB53fY2OqKqKw==
|
||||||
|
|
||||||
throng@^5.0.0:
|
throng@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/throng/-/throng-5.0.0.tgz#f9550c0221e579073f68a00be33a593d094e4d29"
|
resolved "https://registry.yarnpkg.com/throng/-/throng-5.0.0.tgz#f9550c0221e579073f68a00be33a593d094e4d29"
|
||||||
@ -4765,6 +4744,11 @@ validate-npm-package-license@^3.0.1:
|
|||||||
spdx-correct "^3.0.0"
|
spdx-correct "^3.0.0"
|
||||||
spdx-expression-parse "^3.0.0"
|
spdx-expression-parse "^3.0.0"
|
||||||
|
|
||||||
|
vanta@^0.5.21:
|
||||||
|
version "0.5.21"
|
||||||
|
resolved "https://registry.yarnpkg.com/vanta/-/vanta-0.5.21.tgz#f3548b531ac0a53ea0b161f12c880474f0d92b29"
|
||||||
|
integrity sha512-UYW6rYXVl8klFbQrhmgDMZ7SCys9hKROIuTlq5M+v6j346BPu1wqBwVRQPHiYsuooWkUYY6HSXV/9HrJBSuo6g==
|
||||||
|
|
||||||
vary@~1.1.2:
|
vary@~1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||||
@ -4976,11 +4960,6 @@ y18n@^5.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||||
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
||||||
|
|
||||||
yallist@^3.0.2:
|
|
||||||
version "3.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
|
||||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
|
||||||
|
|
||||||
yallist@^4.0.0:
|
yallist@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user