wip
7
frontend/src/app.component.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
template: '<router-outlet></router-outlet>',
|
||||
})
|
||||
export class AppComponent { }
|
||||
@@ -5,20 +5,13 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { RouterModule } from '@angular/router'
|
||||
import { HttpClientModule, HttpClientXsrfModule, HTTP_INTERCEPTORS } from '@angular/common/http'
|
||||
import { ClipboardModule } from '@angular/cdk/clipboard'
|
||||
import { TransferHttpCacheModule } from '@nguniversal/common'
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'
|
||||
import { HttpClientModule } from '@angular/common/http'
|
||||
|
||||
import { BackendXsrfInterceptor, UniversalInterceptor } from './interceptor'
|
||||
import { AppComponent } from './components/app.component'
|
||||
import { MainComponent } from './components/main.component'
|
||||
import { ConfigModalComponent } from './components/configModal.component'
|
||||
import { SettingsModalComponent } from './components/settingsModal.component'
|
||||
import { LoginComponent } from './components/login.component'
|
||||
import { ConnectionListComponent } from './components/connectionList.component'
|
||||
import { UpgradeModalComponent } from './components/upgradeModal.component'
|
||||
import { InstanceInfoResolver } from './api'
|
||||
import { AppComponent } from './app.component'
|
||||
import { CommonAppModule } from 'src/common'
|
||||
|
||||
import '@fortawesome/fontawesome-svg-core/styles.css'
|
||||
|
||||
@@ -29,17 +22,11 @@ const ROUTES = [
|
||||
},
|
||||
{
|
||||
path: 'app',
|
||||
component: MainComponent,
|
||||
resolve: {
|
||||
instanceInfo: InstanceInfoResolver,
|
||||
},
|
||||
loadChildren: () => import(/* webpackChunkName: "app" */'./app').then(m => m.ApplicationModule),
|
||||
},
|
||||
{
|
||||
path: 'login',
|
||||
component: LoginComponent,
|
||||
resolve: {
|
||||
instanceInfo: InstanceInfoResolver,
|
||||
},
|
||||
loadChildren: () => import(/* webpackChunkName: "login" */'./login').then(m => m.LoginModule),
|
||||
},
|
||||
]
|
||||
|
||||
@@ -48,30 +35,20 @@ const ROUTES = [
|
||||
BrowserModule.withServerTransition({
|
||||
appId: 'tabby',
|
||||
}),
|
||||
CommonAppModule.forRoot(),
|
||||
TransferHttpCacheModule,
|
||||
BrowserAnimationsModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
HttpClientModule,
|
||||
HttpClientXsrfModule,
|
||||
NgbDropdownModule,
|
||||
NgbModalModule,
|
||||
FontAwesomeModule,
|
||||
ClipboardModule,
|
||||
HttpClientModule,
|
||||
RouterModule.forRoot(ROUTES),
|
||||
],
|
||||
providers: [
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: UniversalInterceptor, multi: true },
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: BackendXsrfInterceptor, multi: true },
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
MainComponent,
|
||||
LoginComponent,
|
||||
ConfigModalComponent,
|
||||
SettingsModalComponent,
|
||||
ConnectionListComponent,
|
||||
UpgradeModalComponent,
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server'
|
||||
import { AppModule } from './app.module'
|
||||
import { AppComponent } from './components/app.component'
|
||||
import { AppComponent } from './app.component'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
// The AppServerModule should import your AppModule followed
|
||||
// by the ServerModule from @angular/platform-server.
|
||||
AppModule,
|
||||
ServerModule,
|
||||
ServerTransferStateModule,
|
||||
],
|
||||
// Since the bootstrapped component is not inherited from your
|
||||
// imported AppModule, it needs to be repeated here.
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppServerModule {}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { AppConnectorService } from '../services/appConnector.service'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
import { ConfigService } from 'src/common'
|
||||
import { faCopy, faFile, faPlus, faTrash } from '@fortawesome/free-solid-svg-icons'
|
||||
import { Config, Version } from '../api'
|
||||
import { Config, Version } from 'src/api'
|
||||
|
||||
@Component({
|
||||
selector: 'config-modal',
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../theme/vars";
|
||||
@import "theme/vars";
|
||||
|
||||
:host {
|
||||
position: absolute;
|
||||
@@ -4,13 +4,12 @@ import { Title } from '@angular/platform-browser'
|
||||
import { AppConnectorService } from '../services/appConnector.service'
|
||||
|
||||
import { faCog, faFile, faPlus, faSignOutAlt } from '@fortawesome/free-solid-svg-icons'
|
||||
import { LoginService } from '../services/login.service'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { SettingsModalComponent } from './settingsModal.component'
|
||||
import { ConfigModalComponent } from './configModal.component'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
import { ConfigService, LoginService } from 'src/common'
|
||||
import { combineLatest } from 'rxjs'
|
||||
import { Config, Version } from '../api'
|
||||
import { Config, Version } from 'src/api'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
@Component({
|
||||
@@ -19,7 +18,7 @@ import { Router } from '@angular/router'
|
||||
styleUrls: ['./main.component.scss'],
|
||||
})
|
||||
export class MainComponent {
|
||||
_logo = require('../assets/logo.svg')
|
||||
_logo = require('assets/logo.svg')
|
||||
_settingsIcon = faCog
|
||||
_logoutIcon = faSignOutAlt
|
||||
_addIcon = faPlus
|
||||
@@ -1,17 +1,14 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { LoginService } from '../services/login.service'
|
||||
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { User } from '../api'
|
||||
import { User } from 'src/api'
|
||||
import { CommonService, LoginService } from 'src/common'
|
||||
import { AppConnectorService } from '../services/appConnector.service'
|
||||
import { CommonService } from '../services/common.service'
|
||||
import { faGithub } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faCheck, faCopy } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
@Component({
|
||||
selector: 'settings-modal',
|
||||
templateUrl: './settingsModal.component.pug',
|
||||
// styleUrls: ['./settingsModal.component.scss'],
|
||||
})
|
||||
export class SettingsModalComponent {
|
||||
user: User
|
||||
@@ -3,10 +3,9 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { faGithub } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faGift, faHeart } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import { LoginService } from '../services/login.service'
|
||||
import { AppConnectorService } from '../services/appConnector.service'
|
||||
import { CommonService } from '../services/common.service'
|
||||
import { User } from '../api'
|
||||
import { CommonService, LoginService } from 'src/common'
|
||||
import { User } from 'src/api'
|
||||
|
||||
@Component({
|
||||
selector: 'upgrade-modal',
|
||||
46
frontend/src/app/index.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { NgbDropdownModule, NgbModalModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { RouterModule } from '@angular/router'
|
||||
import { ClipboardModule } from '@angular/cdk/clipboard'
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'
|
||||
|
||||
import { MainComponent } from './components/main.component'
|
||||
import { ConfigModalComponent } from './components/configModal.component'
|
||||
import { SettingsModalComponent } from './components/settingsModal.component'
|
||||
import { ConnectionListComponent } from './components/connectionList.component'
|
||||
import { UpgradeModalComponent } from './components/upgradeModal.component'
|
||||
import { InstanceInfoResolver } from 'src/api'
|
||||
import { CommonAppModule } from 'src/common'
|
||||
|
||||
const ROUTES = [
|
||||
{
|
||||
path: '',
|
||||
component: MainComponent,
|
||||
resolve: {
|
||||
instanceInfo: InstanceInfoResolver,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonAppModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
NgbDropdownModule,
|
||||
NgbModalModule,
|
||||
ClipboardModule,
|
||||
FontAwesomeModule,
|
||||
RouterModule.forChild(ROUTES),
|
||||
],
|
||||
declarations: [
|
||||
MainComponent,
|
||||
ConfigModalComponent,
|
||||
SettingsModalComponent,
|
||||
ConnectionListComponent,
|
||||
UpgradeModalComponent,
|
||||
],
|
||||
})
|
||||
export class ApplicationModule { }
|
||||
@@ -5,9 +5,8 @@ import { HttpClient } from '@angular/common/http'
|
||||
import { Injectable, Injector, NgZone } from '@angular/core'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { UpgradeModalComponent } from '../components/upgradeModal.component'
|
||||
import { Config, Gateway, Version } from '../api'
|
||||
import { LoginService } from './login.service'
|
||||
import { CommonService } from './common.service'
|
||||
import { Config, Gateway, Version } from 'src/api'
|
||||
import { LoginService, CommonService } from 'src/common'
|
||||
|
||||
export class SocketProxy {
|
||||
connect$ = new Subject<void>()
|
||||
|
Before Width: | Height: | Size: 3.6 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" x="0" y="0" version="1.1" viewBox="0 0 1024 1024" xml:space="preserve" style="enable-background:new 0 0 1024 1024"><style type="text/css">.st0{fill:url(#SVGID_1_)}.st1{opacity:.16;fill:url(#SVGID_2_)}.st2{fill:url(#SVGID_3_)}.st3{opacity:.16;fill:url(#SVGID_4_)}.st4{fill:url(#SVGID_5_)}.st5{opacity:.15;fill:url(#SVGID_6_)}.st6{fill:url(#SVGID_7_)}</style><g><linearGradient id="SVGID_1_" x1="260.967" x2="919.184" y1="871.181" y2="491.16" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#669abd"/><stop offset="1" style="stop-color:#77dbdb"/></linearGradient><polygon points="297.54 934.52 882.6 596.72 882.61 427.82 297.54 765.65" class="st0"/><linearGradient id="SVGID_2_" x1="553.505" x2="626.647" y1="617.828" y2="744.513" gradientUnits="userSpaceOnUse"><stop offset=".559" style="stop-color:#000;stop-opacity:0"/><stop offset="1" style="stop-color:#000"/></linearGradient><polygon points="297.54 934.52 882.6 596.72 882.61 427.82 297.54 765.65" class="st1"/></g><g><linearGradient id="SVGID_3_" x1="114.663" x2="334.091" y1="744.528" y2="871.214" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#6a8fad"/><stop offset="1" style="stop-color:#669abd"/></linearGradient><polygon points="151.23 681.18 151.22 850.09 297.54 934.52 297.54 765.65" class="st2"/><linearGradient id="SVGID_4_" x1="260.948" x2="187.806" y1="744.528" y2="871.213" gradientUnits="userSpaceOnUse"><stop offset=".559" style="stop-color:#000;stop-opacity:0"/><stop offset="1" style="stop-color:#000"/></linearGradient><polygon points="151.23 681.18 151.22 850.09 297.54 934.52 297.54 765.65" class="st3"/></g><g><linearGradient id="SVGID_5_" x1="114.663" x2="553.503" y1="237.793" y2="491.157" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#6a8fad"/><stop offset="1" style="stop-color:#669abd"/></linearGradient><polygon points="151.23 174.45 151.21 343.36 443.79 512.27 590.08 427.81" class="st4"/><linearGradient id="SVGID_6_" x1="370.656" x2="297.509" y1="301.128" y2="427.822" gradientUnits="userSpaceOnUse"><stop offset=".559" style="stop-color:#000;stop-opacity:0"/><stop offset="1" style="stop-color:#000"/></linearGradient><polygon points="151.23 174.45 151.21 343.36 443.79 512.27 590.08 427.81" class="st5"/></g><linearGradient id="SVGID_7_" x1="78.091" x2="736.337" y1="554.498" y2="174.459" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#ccecff"/><stop offset="1" style="stop-color:#9feced"/></linearGradient><polygon points="297.51 765.64 151.23 681.18 590.08 427.81 151.23 174.45 297.5 90 882.61 427.82" class="st6"/></svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 909 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 260 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 314 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 383 KiB |
|
Before Width: | Height: | Size: 390 KiB |
|
Before Width: | Height: | Size: 614 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
24
frontend/src/common/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ModuleWithProviders, NgModule } from '@angular/core'
|
||||
import { HttpClientXsrfModule, HTTP_INTERCEPTORS } from '@angular/common/http'
|
||||
import { BackendXsrfInterceptor, UniversalInterceptor } from './interceptor'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
HttpClientXsrfModule,
|
||||
],
|
||||
})
|
||||
export class CommonAppModule {
|
||||
static forRoot (): ModuleWithProviders<CommonAppModule> {
|
||||
return {
|
||||
ngModule: CommonAppModule,
|
||||
providers: [
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: UniversalInterceptor, multi: true },
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: BackendXsrfInterceptor, multi: true },
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { LoginService } from './services/login.service'
|
||||
export { ConfigService } from './services/config.service'
|
||||
export { CommonService } from './services/common.service'
|
||||
@@ -3,7 +3,7 @@ import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpXsrfTokenExtr
|
||||
import { Observable } from 'rxjs'
|
||||
import { CommonService } from './services/common.service'
|
||||
|
||||
@Injectable()
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UniversalInterceptor implements HttpInterceptor {
|
||||
constructor (private commonService: CommonService) { }
|
||||
|
||||
@@ -19,7 +19,7 @@ export class UniversalInterceptor implements HttpInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class BackendXsrfInterceptor implements HttpInterceptor {
|
||||
constructor (
|
||||
private commonService: CommonService,
|
||||
@@ -2,7 +2,7 @@ import * as semverCompare from 'semver/functions/compare-loose'
|
||||
import { AsyncSubject, Subject } from 'rxjs'
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Config, User, Version } from '../api'
|
||||
import { Config, User, Version } from '../../api'
|
||||
import { LoginService } from './login.service'
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AsyncSubject } from 'rxjs'
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { User } from '../api'
|
||||
import { User } from '../../api'
|
||||
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
@@ -1 +0,0 @@
|
||||
router-outlet
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
templateUrl: './app.component.pug',
|
||||
// styleUrls: ['./app.component.scss'],
|
||||
})
|
||||
export class AppComponent {
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../theme/vars.scss";
|
||||
@import "theme/vars";
|
||||
|
||||
:host {
|
||||
display: flex;
|
||||
|
||||
@@ -2,8 +2,8 @@ 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'
|
||||
import { Version } from 'src/api'
|
||||
import { CommonService } from 'src/common'
|
||||
|
||||
class DemoConnector {
|
||||
constructor (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../theme/vars.scss";
|
||||
@import "theme/vars";
|
||||
@import "~@fontsource/fira-code/latin.css";
|
||||
|
||||
:host {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component } from '@angular/core'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import { faCoffee, faDownload, faSignInAlt } from '@fortawesome/free-solid-svg-icons'
|
||||
import { Waves } from '../vanta/vanta.waves.js'
|
||||
import { InstanceInfo } from '../../api'
|
||||
import { InstanceInfo } from 'src/api'
|
||||
|
||||
|
||||
@Component({
|
||||
@@ -15,7 +15,7 @@ export class HomeComponent {
|
||||
releaseURL = `${this.githubURL}/releases/latest`
|
||||
donationURL = 'https://ko-fi.com/eugeny'
|
||||
|
||||
_logo = require('../../assets/logo.svg')
|
||||
_logo = require('assets/logo.svg')
|
||||
_downloadIcon = faDownload
|
||||
_loginIcon = faSignInAlt
|
||||
_donateIcon = faCoffee
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.container.mt-5.mb-5
|
||||
h1 Features
|
||||
|
||||
.row.mb-5
|
||||
.row
|
||||
.col-12.col-md-4
|
||||
.card.bg-dark
|
||||
img.card-img-top([src]='screenshots.progress')
|
||||
@@ -23,7 +23,7 @@
|
||||
h5.card-title Customizable hotkeys
|
||||
.card-text Freely customizable single and multi-chord shortcuts.
|
||||
|
||||
.row.mb-5
|
||||
.row
|
||||
.col-12.col-md-4
|
||||
.card.bg-dark
|
||||
img.card-img-top([src]='screenshots.ssh2')
|
||||
@@ -45,7 +45,7 @@
|
||||
h5.card-title Zmodem transfers
|
||||
.card-text Send and receive files directly form the prompt in SSH, telnet and serial session.
|
||||
|
||||
.row.mb-5
|
||||
.row
|
||||
.col-12.col-md-4
|
||||
.card.bg-dark
|
||||
img.card-img-top([src]='screenshots.quake')
|
||||
@@ -67,7 +67,7 @@
|
||||
h5.card-title Profile manager
|
||||
.card-text Every option configurable combined in a profile startable a hotkey.
|
||||
|
||||
.row.mb-5
|
||||
.row
|
||||
.col-12.col-md-4
|
||||
.card.bg-dark
|
||||
img.card-img-top([src]='screenshots.fonts')
|
||||
|
||||
@@ -6,3 +6,7 @@
|
||||
aspect-ratio: 2;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
@@ -7,17 +7,17 @@ import { Component } from '@angular/core'
|
||||
})
|
||||
export class HomeFeaturesComponent {
|
||||
screenshots = {
|
||||
progress: require('../../assets/screenshots/progress.png'),
|
||||
zmodem: require('../../assets/screenshots/zmodem.png'),
|
||||
colors: require('../../assets/screenshots/colors.png'),
|
||||
hotkeys: require('../../assets/screenshots/hotkeys.png'),
|
||||
ports: require('../../assets/screenshots/ports.png'),
|
||||
ssh2: require('../../assets/screenshots/ssh2.png'),
|
||||
fonts: require('../../assets/screenshots/fonts.png'),
|
||||
history: require('../../assets/screenshots/history.png'),
|
||||
paste: require('../../assets/screenshots/paste.png'),
|
||||
quake: require('../../assets/screenshots/quake.png'),
|
||||
split: require('../../assets/screenshots/split.png'),
|
||||
profiles: require('../../assets/screenshots/profiles.png'),
|
||||
progress: require('assets/screenshots/progress.png'),
|
||||
zmodem: require('assets/screenshots/zmodem.png'),
|
||||
colors: require('assets/screenshots/colors.png'),
|
||||
hotkeys: require('assets/screenshots/hotkeys.png'),
|
||||
ports: require('assets/screenshots/ports.png'),
|
||||
ssh2: require('assets/screenshots/ssh2.png'),
|
||||
fonts: require('assets/screenshots/fonts.png'),
|
||||
history: require('assets/screenshots/history.png'),
|
||||
paste: require('assets/screenshots/paste.png'),
|
||||
quake: require('assets/screenshots/quake.png'),
|
||||
split: require('assets/screenshots/split.png'),
|
||||
profiles: require('assets/screenshots/profiles.png'),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../theme/vars.scss";
|
||||
@import "theme/vars";
|
||||
|
||||
h1 {
|
||||
font-family: $font-family-monospace;
|
||||
|
||||
@@ -15,10 +15,10 @@ export class HomeIndexComponent {
|
||||
_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'),
|
||||
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'),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { RouterModule } from '@angular/router'
|
||||
import { HttpClientModule } from '@angular/common/http'
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'
|
||||
import { NgxImageZoomModule } from 'ngx-image-zoom'
|
||||
|
||||
@@ -11,9 +10,8 @@ import { HomeComponent } from './components/home.component'
|
||||
import { HomeIndexComponent } from './components/homeIndex.component'
|
||||
import { DemoTerminalComponent } from './components/demoTerminal.component'
|
||||
import { HomeFeaturesComponent } from './components/homeFeatures.component'
|
||||
import { InstanceInfoResolver } from '../api'
|
||||
|
||||
import '@fortawesome/fontawesome-svg-core/styles.css'
|
||||
import { InstanceInfoResolver } from 'src/api'
|
||||
import { CommonAppModule } from 'src/common'
|
||||
|
||||
const ROUTES = [
|
||||
{
|
||||
@@ -37,9 +35,9 @@ const ROUTES = [
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonAppModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
HttpClientModule,
|
||||
NgbNavModule,
|
||||
FontAwesomeModule,
|
||||
NgxImageZoomModule,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1, minimal-ui, shrink-to-fit=no">
|
||||
<link rel="icon" type="image/png">
|
||||
<link rel="shortcut icon" type="image/png" href="./assets/favicon.png">
|
||||
<link rel="shortcut icon" type="image/png" href="../assets/favicon.png">
|
||||
<title>Tabby - a terminal for a more modern age</title>
|
||||
<meta name="title" content="Tabby - a terminal for a more modern age">
|
||||
<meta name="description" content="Tabby is a free and open source SSH, local and Telnet terminal with everything you'll ever need.">
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { LoginService } from '../services/login.service'
|
||||
import { CommonService } from '../services/common.service'
|
||||
import { LoginService, CommonService } from 'src/common'
|
||||
|
||||
import { faGithub, faGitlab, faGoogle, faMicrosoft } from '@fortawesome/free-brands-svg-icons'
|
||||
|
||||
37
frontend/src/login/index.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { RouterModule } from '@angular/router'
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'
|
||||
import { NgxImageZoomModule } from 'ngx-image-zoom'
|
||||
|
||||
import { LoginComponent } from './components/login.component'
|
||||
import { InstanceInfoResolver } from 'src/api'
|
||||
import { CommonAppModule } from 'src/common'
|
||||
|
||||
const ROUTES = [
|
||||
{
|
||||
path: '',
|
||||
component: LoginComponent,
|
||||
resolve: {
|
||||
instanceInfo: InstanceInfoResolver,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonAppModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
NgbNavModule,
|
||||
FontAwesomeModule,
|
||||
NgxImageZoomModule,
|
||||
RouterModule.forChild(ROUTES),
|
||||
],
|
||||
declarations: [
|
||||
LoginComponent,
|
||||
],
|
||||
})
|
||||
export class LoginModule { }
|
||||
@@ -9,4 +9,4 @@ body {
|
||||
@import "~source-code-pro/source-code-pro.css";
|
||||
@import "~source-sans-pro/source-sans-pro.css";
|
||||
|
||||
@import "./theme/index.scss"
|
||||
@import "theme/index"
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
@import "vars";
|
||||
|
||||
@import "~bootstrap/scss/functions";
|
||||
@import "~bootstrap/scss/variables";
|
||||
@import "~bootstrap/scss/mixins";
|
||||
@import "~bootstrap/scss/utilities";
|
||||
|
||||
@import "~bootstrap/scss/root";
|
||||
@import "~bootstrap/scss/reboot";
|
||||
@import "~bootstrap/scss/type";
|
||||
// @import "~bootstrap/scss/images";
|
||||
@import "~bootstrap/scss/containers";
|
||||
@import "~bootstrap/scss/grid";
|
||||
// @import "~bootstrap/scss/tables";
|
||||
@import "~bootstrap/scss/forms";
|
||||
@import "~bootstrap/scss/buttons";
|
||||
@import "~bootstrap/scss/transitions";
|
||||
@import "~bootstrap/scss/dropdown";
|
||||
@import "~bootstrap/scss/button-group";
|
||||
@import "~bootstrap/scss/nav";
|
||||
// @import "~bootstrap/scss/navbar";
|
||||
@import "~bootstrap/scss/card";
|
||||
// @import "~bootstrap/scss/accordion";
|
||||
// @import "~bootstrap/scss/breadcrumb";
|
||||
// @import "~bootstrap/scss/pagination";
|
||||
@import "~bootstrap/scss/badge";
|
||||
@import "~bootstrap/scss/alert";
|
||||
// @import "~bootstrap/scss/progress";
|
||||
@import "~bootstrap/scss/list-group";
|
||||
// @import "~bootstrap/scss/close";
|
||||
// @import "~bootstrap/scss/toasts";
|
||||
@import "~bootstrap/scss/modal";
|
||||
// @import "~bootstrap/scss/tooltip";
|
||||
// @import "~bootstrap/scss/popover";
|
||||
// @import "~bootstrap/scss/carousel";
|
||||
// @import "~bootstrap/scss/spinners";
|
||||
// @import "~bootstrap/scss/offcanvas";
|
||||
|
||||
// Helpers
|
||||
@import "~bootstrap/scss/helpers";
|
||||
@import "~bootstrap/scss/utilities/api";
|
||||
|
||||
::-webkit-scrollbar-track
|
||||
{
|
||||
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
|
||||
background-color: $gray-900;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar
|
||||
{
|
||||
height: 6px;
|
||||
width: 6px;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb
|
||||
{
|
||||
background-color: $gray-700;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
|
||||
.dropdown-menu {
|
||||
box-shadow: $dropdown-box-shadow;
|
||||
}
|
||||
|
||||
.modal-header, .modal-body {
|
||||
padding: $modal-inner-padding $modal-inner-padding * 2;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
background: #00000030;
|
||||
}
|
||||
|
||||
a, button {
|
||||
fa-icon {
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
fa-icon + * {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
$white: #fff;
|
||||
$gray-100: #f8f9fa;
|
||||
$gray-200: #e9ecef;
|
||||
$gray-300: #dee2e6;
|
||||
$gray-400: #ced4da;
|
||||
$gray-500: #adb5bd;
|
||||
$gray-600: #6c757d;
|
||||
$gray-700: #495057;
|
||||
$gray-800: #343a40;
|
||||
$gray-900: #212529;
|
||||
$black: #000;
|
||||
|
||||
|
||||
$red: #d9534f !default;
|
||||
$orange: #f0ad4e !default;
|
||||
$yellow: #ffd500 !default;
|
||||
$green: #5cb85c !default;
|
||||
$blue: #0275d8 !default;
|
||||
$teal: #5bc0de !default;
|
||||
$pink: #ff5b77 !default;
|
||||
$purple: #613d7c !default;
|
||||
$semi: rgba(0,0,0, .5);
|
||||
|
||||
|
||||
@import "~bootstrap/scss/functions";
|
||||
|
||||
$table-bg: rgba(255,255,255,.05);
|
||||
$table-bg-hover: rgba(255,255,255,.1);
|
||||
$table-border-color: rgba(255,255,255,.1);
|
||||
|
||||
$theme-colors: (
|
||||
primary: $blue,
|
||||
secondary: #38434e,
|
||||
success: $green,
|
||||
info: $blue,
|
||||
warning: $orange,
|
||||
danger: $red,
|
||||
light: $gray-300,
|
||||
dark: #0e151d,
|
||||
rare: $purple,
|
||||
semi: $semi
|
||||
);
|
||||
|
||||
$body-color: #ccc;
|
||||
$body-bg: #0c131b;
|
||||
|
||||
$font-family-sans-serif: "Source Sans Pro";
|
||||
$font-family-monospace: "Source Code Pro";
|
||||
$font-size-base: 14rem / 16;
|
||||
$font-size-lg: 1.28rem;
|
||||
$font-size-sm: .85rem;
|
||||
|
||||
$line-height-base: 1.6;
|
||||
|
||||
$border-radius: .35rem;
|
||||
$border-radius-lg: .35rem;
|
||||
$border-radius-sm: .2rem;
|
||||
|
||||
$box-shadow: 0 .5rem 1rem rgba($black, .5) !default;
|
||||
|
||||
// -----
|
||||
|
||||
$headings-color: #ced9e2;
|
||||
$headings-font-weight: lighter;
|
||||
|
||||
$input-btn-padding-y: .3rem;
|
||||
$input-btn-padding-x: .9rem;
|
||||
$input-btn-line-height: 1.6;
|
||||
$input-btn-line-height-sm: 1.8;
|
||||
$input-btn-line-height-lg: 1.8;
|
||||
$btn-focus-width: 1px;
|
||||
|
||||
$h4-font-size: 18px;
|
||||
|
||||
$link-color: $gray-400;
|
||||
$link-hover-color: $white;
|
||||
$link-hover-decoration: none;
|
||||
|
||||
$component-active-color: $white;
|
||||
$component-active-bg: $blue;
|
||||
|
||||
$list-group-color: $body-color;
|
||||
$list-group-bg: $table-bg;
|
||||
$list-group-border-color: $table-border-color;
|
||||
|
||||
$list-group-item-padding-y: 0.8rem;
|
||||
$list-group-item-padding-x: 1rem;
|
||||
|
||||
$list-group-hover-bg: $table-bg-hover;
|
||||
$list-group-active-bg: rgba(255,255,255,.2);
|
||||
$list-group-active-color: $component-active-color;
|
||||
$list-group-active-border-color: translate;
|
||||
|
||||
$list-group-action-color: $body-color;
|
||||
$list-group-action-hover-color: white;
|
||||
|
||||
$list-group-action-active-color: $component-active-color;
|
||||
$list-group-action-active-bg: $list-group-active-bg;
|
||||
|
||||
$alert-padding-y: 0.9rem;
|
||||
$alert-padding-x: 1.25rem;
|
||||
|
||||
$transition-base: all .15s ease-in-out;
|
||||
$transition-fade: opacity .1s linear;
|
||||
$transition-collapse: height .35s ease;
|
||||
$btn-transition: all .15s ease-in-out;
|
||||
|
||||
$popover-bg: $body-bg;
|
||||
$popover-body-color: $body-color;
|
||||
$popover-header-bg: $table-bg-hover;
|
||||
$popover-header-color: $headings-color;
|
||||
$popover-arrow-color: $popover-bg;
|
||||
$popover-max-width: 360px;
|
||||
|
||||
$btn-border-width: 2px;
|
||||
|
||||
$input-bg: $black;
|
||||
$input-disabled-bg: #2e3235;
|
||||
|
||||
$input-color: #ddd;
|
||||
$input-border-color: $input-bg;
|
||||
$input-border-width: 2px;
|
||||
|
||||
$input-focus-bg: $input-bg;
|
||||
$input-focus-border-color: rgba(171, 171, 171, 0.61);
|
||||
$input-focus-color: $input-color;
|
||||
|
||||
$input-group-addon-color: $input-color;
|
||||
$input-group-addon-bg: $input-bg;
|
||||
$input-group-addon-border-color: transparent;
|
||||
$input-group-btn-border-color: $input-bg;
|
||||
|
||||
$form-switch-color: rgba(255,255,255, .25);
|
||||
|
||||
$nav-tabs-border-radius: 0;
|
||||
$nav-tabs-border-color: transparent;
|
||||
$nav-tabs-border-width: 2px;
|
||||
$nav-tabs-link-hover-border-color: transparent;
|
||||
$nav-tabs-link-active-color: #eee;
|
||||
$nav-tabs-link-active-bg: transparent;
|
||||
$nav-tabs-link-active-border-color: #eee;
|
||||
|
||||
$nav-pills-link-active-bg: rgba(255, 255, 255, .125);
|
||||
|
||||
$navbar-padding-y: 0;
|
||||
$navbar-padding-x: 0;
|
||||
|
||||
$dropdown-bg: $body-bg;
|
||||
$dropdown-color: $body-color;
|
||||
$dropdown-border-width: 1px;
|
||||
$dropdown-border-color: #ffffff24;
|
||||
$dropdown-header-color: $gray-500;
|
||||
|
||||
$dropdown-link-color: $body-color;
|
||||
$dropdown-link-hover-color: #eee;
|
||||
$dropdown-link-hover-bg: rgba(255,255,255,.04);
|
||||
$dropdown-link-active-color: white;
|
||||
$dropdown-link-active-bg: rgba(0, 0, 0, .2);
|
||||
$dropdown-item-padding-y: 0.5rem;
|
||||
$dropdown-item-padding-x: 1.5rem;
|
||||
|
||||
|
||||
$code-color: $orange;
|
||||
$code-bg: rgba(0, 0, 0, .25);
|
||||
$code-padding-y: 3px;
|
||||
$code-padding-x: 5px;
|
||||
$pre-bg: $dropdown-bg;
|
||||
$pre-color: $dropdown-link-color;
|
||||
|
||||
$badge-font-size: 0.75rem;
|
||||
$badge-font-weight: bold;
|
||||
$badge-padding-y: 4px;
|
||||
$badge-padding-x: 6px;
|
||||
|
||||
|
||||
$custom-control-indicator-size: 1.2rem;
|
||||
$custom-control-indicator-bg: $body-bg;
|
||||
$custom-control-indicator-border-color: lighten($body-bg, 25%);
|
||||
$custom-control-indicator-checked-bg: theme-color("primary");
|
||||
$custom-control-indicator-checked-color: $body-bg;
|
||||
$custom-control-indicator-checked-border-color: transparent;
|
||||
$custom-control-indicator-active-bg: rgba(255, 255, 0, 0.5);
|
||||
|
||||
|
||||
$modal-content-bg: $body-bg;
|
||||
$modal-content-border-color: $body-bg;
|
||||
$modal-header-border-width: 0;
|
||||
$modal-footer-border-width: 0;
|
||||
|
||||
$modal-content-border-color: #ffffff24;
|
||||
$modal-content-border-width: 1px;
|
||||
|
||||
|
||||
$progress-bg: $table-bg;
|
||||
$progress-height: 3px;
|
||||
|
||||
$alert-bg-scale: 90%;
|
||||
$alert-border-scale: 50%;
|
||||
$alert-color-scale: 50%;
|
||||