mirror of
https://github.com/Eugeny/tabby-web.git
synced 2025-07-27 00:48:33 +00:00
wip
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "terminus-web-container",
|
||||
"name": "tabby-web",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -17,6 +17,7 @@
|
||||
"@angular/forms": "^11.0.0",
|
||||
"@angular/platform-browser": "^11.0.0",
|
||||
"@angular/platform-browser-dynamic": "^11.0.0",
|
||||
"@angular/router": "^11.0.0",
|
||||
"@fortawesome/angular-fontawesome": "0.8",
|
||||
"@fortawesome/fontawesome-free": "^5.7.2",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.35",
|
||||
|
@@ -4,12 +4,21 @@ import { BrowserModule } from '@angular/platform-browser'
|
||||
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 } from '@angular/common/http'
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'
|
||||
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 { HomeComponent } from './components/home.component'
|
||||
import { LoginComponent } from './components/login.component'
|
||||
|
||||
const ROUTES = [
|
||||
{ path: '', component: HomeComponent },
|
||||
{ path: 'app', component: MainComponent },
|
||||
{ path: 'login', component: LoginComponent },
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -22,10 +31,13 @@ import { SettingsModalComponent } from './components/settingsModal.component'
|
||||
NgbDropdownModule,
|
||||
NgbModalModule,
|
||||
FontAwesomeModule,
|
||||
RouterModule.forRoot(ROUTES),
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
MainComponent,
|
||||
HomeComponent,
|
||||
LoginComponent,
|
||||
ConfigModalComponent,
|
||||
SettingsModalComponent,
|
||||
],
|
||||
|
BIN
src/assets/screenshots/serial.png
Normal file
BIN
src/assets/screenshots/serial.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 536 KiB |
BIN
src/assets/screenshots/ssh.png
Normal file
BIN
src/assets/screenshots/ssh.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 371 KiB |
BIN
src/assets/screenshots/tabs.png
Normal file
BIN
src/assets/screenshots/tabs.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 666 KiB |
BIN
src/assets/screenshots/window.png
Normal file
BIN
src/assets/screenshots/window.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 728 KiB |
@@ -1,10 +1 @@
|
||||
main(*ngIf='ready && loggedIn')
|
||||
.login-view(*ngIf='ready && !loggedIn')
|
||||
.buttons
|
||||
a.btn(
|
||||
*ngFor='let provider of providers',
|
||||
[class]='provider.cls',
|
||||
href='/api/1/auth/social/login/{{provider.id}}'
|
||||
)
|
||||
fa-icon([icon]='provider.icon', [fixedWidth]='true')
|
||||
span Log in with {{provider.name}}
|
||||
router-outlet
|
||||
|
@@ -1,33 +1,9 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { LoginService } from '../services/login.service'
|
||||
|
||||
import { faGithub, faGitlab, faGoogle, faMicrosoft } from '@fortawesome/free-brands-svg-icons'
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
templateUrl: './app.component.pug',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
// styleUrls: ['./app.component.scss'],
|
||||
})
|
||||
export class AppComponent {
|
||||
loggedIn: any
|
||||
ready = false
|
||||
|
||||
providers = [
|
||||
{ name: 'GitHub', icon: faGithub, cls: 'btn-primary', id: 'github' },
|
||||
{ name: 'GitLab', icon: faGitlab, cls: 'btn-warning', id: 'gitlab' },
|
||||
{ name: 'Google', icon: faGoogle, cls: 'btn-secondary', id: 'google-oauth2' },
|
||||
{ name: 'Microsoft', icon: faMicrosoft, cls: 'btn-light', id: 'microsoft-graph' },
|
||||
]
|
||||
|
||||
constructor (
|
||||
private loginService: LoginService,
|
||||
) {
|
||||
this.providers = [this.providers[0]] // only keep GH for now
|
||||
}
|
||||
|
||||
async ngOnInit () {
|
||||
await this.loginService.ready$.toPromise()
|
||||
this.loggedIn = !!this.loginService.user
|
||||
this.ready = true
|
||||
}
|
||||
}
|
||||
|
96
src/components/home.component.pug
Normal file
96
src/components/home.component.pug
Normal file
@@ -0,0 +1,96 @@
|
||||
.top-half
|
||||
.navbar
|
||||
img.brand(src='{{_logo}}')
|
||||
.me-auto
|
||||
a.btn.btn-primary([href]='releaseURL', target='_blank')
|
||||
fa-icon([icon]='_downloadIcon', [fixedWidth]='true')
|
||||
span Download
|
||||
a.btn.btn-secondary(routerLink='/login')
|
||||
fa-icon([icon]='_loginIcon', [fixedWidth]='true')
|
||||
span Login
|
||||
|
||||
.container
|
||||
.intro
|
||||
h1 Hey.
|
||||
div My name is Eugene and I've built a nice terminal app, #[em.ms-1 just for you].
|
||||
div Crossplatform, local, SSH, serial - it's all there.
|
||||
div Go on, try it out 👇
|
||||
|
||||
iframe(#iframe)
|
||||
|
||||
.bottom-half
|
||||
.container
|
||||
.d-flex.m-auto
|
||||
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
|
||||
img.screenshot([src]='screenshots.window')
|
||||
.col
|
||||
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
|
||||
h1 Terminal features
|
||||
ul
|
||||
li Multiple #[strong nested panes]
|
||||
li #[strong Progress bars] and activity notifications for tabs
|
||||
li Terminus 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
|
||||
img.screenshot([src]='screenshots.tabs')
|
||||
|
||||
.section.section-a
|
||||
.container
|
||||
.row
|
||||
.col
|
||||
img.screenshot([src]='screenshots.ssh')
|
||||
.col
|
||||
h1 SSH
|
||||
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
|
95
src/components/home.component.scss
Normal file
95
src/components/home.component.scss
Normal file
@@ -0,0 +1,95 @@
|
||||
@import "../theme/vars.scss";
|
||||
|
||||
:host {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.top-half {
|
||||
background: linear-gradient(#0c141c, #15202b);
|
||||
}
|
||||
|
||||
.navbar {
|
||||
display: flex;
|
||||
padding: 15px 30px;
|
||||
|
||||
a, button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.brand {
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: $font-family-monospace;
|
||||
font-weight: bold;
|
||||
font-size: 48px;
|
||||
text-shadow: 0 0 1px black;
|
||||
}
|
||||
|
||||
.intro {
|
||||
width: 60vw;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
iframe {
|
||||
display: block;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
top: 20vw;
|
||||
margin-top: -18vw;
|
||||
|
||||
width: 60vw;
|
||||
height: 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: 30px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
.quote {
|
||||
margin: 0 30px;
|
||||
|
||||
.text {
|
||||
font-size: 50px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.author {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strong {
|
||||
background: #9400ff57;
|
||||
font-weight: normal;
|
||||
padding: 2px 7px;
|
||||
text-shadow: 0 0 2px black;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 30px 0;
|
||||
|
||||
.screenshot {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.section-a {
|
||||
background: rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
.section-b {
|
||||
}
|
81
src/components/home.component.ts
Normal file
81
src/components/home.component.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import * as semverGT from 'semver/functions/gt'
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { Component, ElementRef, ViewChild } from '@angular/core'
|
||||
import { Version } from '../api'
|
||||
import { faDownload, faSignInAlt } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faGithub } from '@fortawesome/free-brands-svg-icons'
|
||||
|
||||
class DemoConnector {
|
||||
constructor (targetWindow: Window, private version: Version) {
|
||||
targetWindow['terminusWebDemoDataPath'] = `${this.getDistURL()}/${version.version}/terminus-web-demo/data`
|
||||
}
|
||||
|
||||
async loadConfig (): Promise<string> {
|
||||
return '{}'
|
||||
}
|
||||
|
||||
async saveConfig (content: string): Promise<void> {
|
||||
}
|
||||
|
||||
getAppVersion (): string {
|
||||
return this.version.version
|
||||
}
|
||||
|
||||
getDistURL (): string {
|
||||
return '/app-dist'
|
||||
}
|
||||
|
||||
getPluginsToLoad (): string[] {
|
||||
return [
|
||||
'terminus-core',
|
||||
'terminus-settings',
|
||||
'terminus-terminal',
|
||||
'terminus-community-color-schemes',
|
||||
'terminus-web',
|
||||
'terminus-web-demo',
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'home',
|
||||
templateUrl: './home.component.pug',
|
||||
styleUrls: ['./home.component.scss'],
|
||||
})
|
||||
export class HomeComponent {
|
||||
@ViewChild('iframe') iframe: ElementRef
|
||||
connector: DemoConnector
|
||||
githubURL = 'https://github.com/Eugeny/terminus'
|
||||
releaseURL = `${this.githubURL}/releases/latest`
|
||||
_logo = require('../assets/logo.svg')
|
||||
_downloadIcon = faDownload
|
||||
_loginIcon = faSignInAlt
|
||||
_githubIcon = faGithub
|
||||
screenshots = {
|
||||
window: require('../assets/screenshots/window.png'),
|
||||
tabs: require('../assets/screenshots/tabs.png'),
|
||||
ssh: require('../assets/screenshots/ssh.png'),
|
||||
}
|
||||
|
||||
constructor (private http: HttpClient) {
|
||||
window.addEventListener('message', this.connectorRequestHandler)
|
||||
}
|
||||
|
||||
connectorRequestHandler = event => {
|
||||
if (event.data === 'request-connector') {
|
||||
this.iframe.nativeElement.contentWindow['__connector__'] = this.connector
|
||||
this.iframe.nativeElement.contentWindow.postMessage('connector-ready', '*')
|
||||
}
|
||||
}
|
||||
|
||||
async ngAfterViewInit () {
|
||||
const versions = await this.http.get('/api/1/versions').toPromise()
|
||||
versions.sort((a, b) => semverGT(a, b))
|
||||
this.connector = new DemoConnector(this.iframe.nativeElement.contentWindow, versions[0])
|
||||
this.iframe.nativeElement.src = '/terminal'
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
window.removeEventListener('message', this.connectorRequestHandler)
|
||||
}
|
||||
}
|
10
src/components/login.component.pug
Normal file
10
src/components/login.component.pug
Normal file
@@ -0,0 +1,10 @@
|
||||
main(*ngIf='ready && loggedIn')
|
||||
.login-view(*ngIf='ready && !loggedIn')
|
||||
.buttons
|
||||
a.btn(
|
||||
*ngFor='let provider of providers',
|
||||
[class]='provider.cls',
|
||||
href='/api/1/auth/social/login/{{provider.id}}'
|
||||
)
|
||||
fa-icon([icon]='provider.icon', [fixedWidth]='true')
|
||||
span Log in with {{provider.name}}
|
33
src/components/login.component.ts
Normal file
33
src/components/login.component.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { LoginService } from '../services/login.service'
|
||||
|
||||
import { faGithub, faGitlab, faGoogle, faMicrosoft } from '@fortawesome/free-brands-svg-icons'
|
||||
|
||||
@Component({
|
||||
selector: 'login',
|
||||
templateUrl: './login.component.pug',
|
||||
styleUrls: ['./login.component.scss'],
|
||||
})
|
||||
export class LoginComponent {
|
||||
loggedIn: any
|
||||
ready = false
|
||||
|
||||
providers = [
|
||||
{ name: 'GitHub', icon: faGithub, cls: 'btn-primary', id: 'github' },
|
||||
{ name: 'GitLab', icon: faGitlab, cls: 'btn-warning', id: 'gitlab' },
|
||||
{ name: 'Google', icon: faGoogle, cls: 'btn-secondary', id: 'google-oauth2' },
|
||||
{ name: 'Microsoft', icon: faMicrosoft, cls: 'btn-light', id: 'microsoft-graph' },
|
||||
]
|
||||
|
||||
constructor (
|
||||
private loginService: LoginService,
|
||||
) {
|
||||
this.providers = [this.providers[0]] // only keep GH for now
|
||||
}
|
||||
|
||||
async ngOnInit () {
|
||||
await this.loginService.ready$.toPromise()
|
||||
this.loggedIn = !!this.loginService.user
|
||||
this.ready = true
|
||||
}
|
||||
}
|
@@ -10,6 +10,7 @@ import { ConfigModalComponent } from './configModal.component'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
import { combineLatest } from 'rxjs'
|
||||
import { Config, Version } from '../api'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
@Component({
|
||||
selector: 'main',
|
||||
@@ -35,16 +36,25 @@ export class MainComponent {
|
||||
public loginService: LoginService,
|
||||
private ngbModal: NgbModal,
|
||||
private config: ConfigService,
|
||||
private router: Router,
|
||||
) {
|
||||
window.addEventListener('message', event => {
|
||||
if (event.data === 'request-connector') {
|
||||
this.iframe.nativeElement.contentWindow['__connector__'] = this.appConnector
|
||||
this.iframe.nativeElement.contentWindow.postMessage('connector-ready', '*')
|
||||
}
|
||||
})
|
||||
window.addEventListener('message', this.connectorRequestHandler)
|
||||
}
|
||||
|
||||
connectorRequestHandler = event => {
|
||||
if (event.data === 'request-connector') {
|
||||
this.iframe.nativeElement.contentWindow['__connector__'] = this.appConnector
|
||||
this.iframe.nativeElement.contentWindow.postMessage('connector-ready', '*')
|
||||
}
|
||||
}
|
||||
|
||||
async ngAfterViewInit () {
|
||||
await this.loginService.ready$.toPromise()
|
||||
if (!this.loginService.user) {
|
||||
this.router.navigate(['/login'])
|
||||
return
|
||||
}
|
||||
|
||||
combineLatest(
|
||||
this.config.activeConfig$,
|
||||
this.config.activeVersion$
|
||||
@@ -58,6 +68,10 @@ export class MainComponent {
|
||||
await this.config.selectDefaultConfig()
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
window.removeEventListener('message', this.connectorRequestHandler)
|
||||
}
|
||||
|
||||
unloadApp () {
|
||||
this.showApp = false
|
||||
this.iframe.nativeElement.src = 'about:blank'
|
||||
|
@@ -1,8 +1,8 @@
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
base(href='/')
|
||||
meta(name='viewport', content='initial-scale=1, minimal-ui, shrink-to-fit=no')
|
||||
link(href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400", rel="stylesheet")
|
||||
script(src='/build/index.js', defer)
|
||||
title Terminus
|
||||
body
|
||||
|
@@ -119,6 +119,21 @@ export class AppConnectorService {
|
||||
return this.version.version
|
||||
}
|
||||
|
||||
getDistURL (): string {
|
||||
return '../app-dist'
|
||||
}
|
||||
|
||||
getPluginsToLoad (): string[] {
|
||||
return [
|
||||
'terminus-core',
|
||||
'terminus-settings',
|
||||
'terminus-terminal',
|
||||
'terminus-ssh',
|
||||
'terminus-community-color-schemes',
|
||||
'terminus-web',
|
||||
]
|
||||
}
|
||||
|
||||
createSocket () {
|
||||
return new SocketProxy(this)
|
||||
}
|
||||
|
@@ -6,4 +6,7 @@ body {
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
@import "~source-code-pro/source-code-pro.css";
|
||||
@import "~source-sans-pro/source-sans-pro.css";
|
||||
|
||||
@import "./theme/index.scss"
|
||||
|
@@ -27,35 +27,32 @@ async function start () {
|
||||
return window['module'].exports
|
||||
}
|
||||
|
||||
const baseUrl = `../app-dist/${appVersion}`
|
||||
const baseUrl = `${connector.getDistURL()}/${appVersion}`
|
||||
await webRequire(`${baseUrl}/web/dist/preload.js`)
|
||||
await webRequire(`${baseUrl}/web/dist/bundle.js`)
|
||||
|
||||
const terminus = window['Terminus']
|
||||
|
||||
const pluginModules = []
|
||||
for (const plugin of [
|
||||
'terminus-core',
|
||||
'terminus-settings',
|
||||
'terminus-terminal',
|
||||
'terminus-ssh',
|
||||
'terminus-community-color-schemes',
|
||||
'terminus-web',
|
||||
]) {
|
||||
for (const plugin of connector.getPluginsToLoad()) {
|
||||
pluginModules.push(await terminus.loadPlugin(`${baseUrl}/${plugin}`))
|
||||
}
|
||||
|
||||
document.querySelector('app-root')['style'].display = 'flex'
|
||||
|
||||
const config = connector.loadConfig()
|
||||
terminus.bootstrap(pluginModules, {
|
||||
config,
|
||||
executable: 'web',
|
||||
isFirstWindow: true,
|
||||
windowID: 1,
|
||||
installedPlugins: [],
|
||||
userPluginsPath: '/',
|
||||
terminus.bootstrap({
|
||||
packageModules: pluginModules,
|
||||
bootstrapData: {
|
||||
config,
|
||||
executable: 'web',
|
||||
isFirstWindow: true,
|
||||
windowID: 1,
|
||||
installedPlugins: [],
|
||||
userPluginsPath: '/',
|
||||
},
|
||||
debugMode: false,
|
||||
connector,
|
||||
})
|
||||
}
|
||||
|
||||
start()
|
||||
|
@@ -66,3 +66,13 @@
|
||||
.modal-footer {
|
||||
background: #00000030;
|
||||
}
|
||||
|
||||
a, button {
|
||||
fa-icon {
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
fa-icon + * {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
@@ -51,7 +51,6 @@ class AppVersionViewSet(ListModelMixin, GenericViewSet):
|
||||
lookup_field = 'id'
|
||||
lookup_value_regex = r'[\w\d.-]+'
|
||||
queryset = ''
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def _get_versions(self):
|
||||
return [AppVersion(version=x) for x in os.listdir(settings.APP_DIST_PATH)]
|
||||
|
@@ -14,7 +14,8 @@ urlpatterns = [
|
||||
path('api/1/auth/logout', api.LogoutView.as_view()),
|
||||
path('api/1/user', api.UserViewSet.as_view({'get': 'retrieve', 'put': 'update'})),
|
||||
|
||||
path('', views.IndexView.as_view()),
|
||||
re_path('^(|login|app)$', views.IndexView.as_view()),
|
||||
|
||||
path('terminal', views.TerminalView.as_view()),
|
||||
path('app-dist/<version>/<path:path>', views.AppDistView.as_view()),
|
||||
path('build/<path:path>', views.BuildView.as_view()),
|
||||
|
@@ -138,7 +138,7 @@ AUTHENTICATION_BACKENDS = (
|
||||
|
||||
SOCIAL_AUTH_GITHUB_SCOPE = ['read:user', 'user:email']
|
||||
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
LOGIN_REDIRECT_URL = '/app'
|
||||
|
||||
APP_DIST_PATH = BASE_DIR / 'app-dist'
|
||||
|
||||
|
@@ -72,6 +72,13 @@
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@angular/router@^11.0.0":
|
||||
version "11.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular/router/-/router-11.2.14.tgz#4a8eb6d010a1a45c8e7f0c3b5b705959bdb69294"
|
||||
integrity sha512-3aYBmj+zrEL9yf/ntIQxHIYaWShZOBKP3U07X2mX+TPMpGlvHDnR7L6bWhQVZwewzMMz7YVR16ldg50IFuAlfA==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@babel/code-frame@^7.14.5":
|
||||
version "7.14.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
|
||||
|
Reference in New Issue
Block a user