Compare commits

..
Author SHA1 Message Date
raciborski f768b74893 Merge pull request #55 from avatao-content/message-buttons
Change message active button colors
2020-07-01 13:23:31 +02:00
Gabor PEK 670ac0f3dc Use global variables for shadow colors 2020-06-30 15:48:04 +02:00
Gabor PEK bca9861a4d Change message active button colors 2020-06-29 17:17:05 +02:00
ni-richard 3da348efca Merge pull request #54 from avatao-content/message-buttons
Message button support in bot messages
2020-06-23 08:17:13 +02:00
Gabor PEK 2f9aa9c298 Change message button type in send message 2020-06-22 13:43:55 +02:00
Gabor PEK d92f3da04d Refactor message buttons using Records for mapping 2020-06-22 12:19:33 +02:00
Gabor PEK aacd8aea60 Fix active message button style 2020-06-17 17:58:31 +02:00
Gabor PEK fb2735ccc7 Fix style of message buttons 2020-06-17 17:47:57 +02:00
Gabor PEK 31cf75f63b Add message buttons to control the user flow 2020-06-17 17:19:22 +02:00
Gabor PEK 0f324a108b Change look and UI of messages, add new Avatao logo 2020-06-12 17:04:29 +02:00
Gabor PEK 2b301edccc Redefine color palette 2020-06-08 11:24:39 +02:00
Gergo Turcsanyi 96d27a7d2d Fix iframe reload polling 2020-05-29 11:54:26 +02:00
R. Richard 4f3a6057a4 Prevent IDE reload race condition 2020-05-26 15:34:54 +02:00
R. Richard ea5bf30a95 Reconnect websockets automatically 2020-05-21 17:44:01 +02:00
R. Richard d8545c48be Stop filtering JS code in bot messages 2020-05-18 18:01:30 +02:00
ni-richard 031a9916a0 Make webservice optional 2020-05-15 14:46:33 +02:00
29 changed files with 7098 additions and 139 deletions
+2 -1
View File
@@ -5,7 +5,8 @@
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json", "start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build --prod --aot --build-optimizer" "build": "ng build --prod --aot --build-optimizer",
"lint": "ng lint --fix"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
+4 -1
View File
@@ -17,7 +17,7 @@ import { TerminalComponent } from './terminal/terminal.component';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { TestmessengerComponent } from './testmessenger/testmessenger.component'; import { TestmessengerComponent } from './testmessenger/testmessenger.component';
import { DeploymentNotificationService } from './services/deployment-notification.service'; import { DeploymentNotificationService } from './services/deployment-notification.service';
import { SafePipe } from './pipes/safe.pipe'; import { SafePipe, SafeHtmlPipe } from './pipes/safe.pipe';
import { ConsoleComponent } from './console/console.component'; import { ConsoleComponent } from './console/console.component';
import { MonacoEditorModule } from 'ngx-monaco-editor'; import { MonacoEditorModule } from 'ngx-monaco-editor';
import { import {
@@ -28,6 +28,7 @@ import {
} from './services/config.service'; } from './services/config.service';
import { FSMUpdateService } from './services/fsmupdate.service'; import { FSMUpdateService } from './services/fsmupdate.service';
import { LoaderComponent } from './loader/loader.component'; import { LoaderComponent } from './loader/loader.component';
import {CapitalizePipe} from './pipes/capitalize.pipe';
@NgModule({ @NgModule({
@@ -41,6 +42,8 @@ import { LoaderComponent } from './loader/loader.component';
DashboardComponent, DashboardComponent,
TestmessengerComponent, TestmessengerComponent,
SafePipe, SafePipe,
SafeHtmlPipe,
CapitalizePipe,
ConsoleComponent, ConsoleComponent,
LoaderComponent LoaderComponent
], ],
+1 -1
View File
@@ -1,9 +1,9 @@
<div [attr.class]="layout | async"> <div [attr.class]="layout | async">
<div class="tfw-grid-main-components"> <div class="tfw-grid-main-components">
<div class="tfw-header"><app-header></app-header></div>
<div [ngClass]="{'hide-attribute': hideMessages | async}" class="tfw-messages"> <div [ngClass]="{'hide-attribute': hideMessages | async}" class="tfw-messages">
<app-messages></app-messages> <app-messages></app-messages>
</div> </div>
<div class="tfw-header"><app-header></app-header></div>
<div class="tfw-web tao-grid-top-left" <div class="tfw-web tao-grid-top-left"
[ngClass]="{'deploy-blur': deploying || (iframeReloadPoller.isPolling | async)}"> [ngClass]="{'deploy-blur': deploying || (iframeReloadPoller.isPolling | async)}">
<div *ngIf="iframeUrl | async" class="iframe-container"> <div *ngIf="iframeUrl | async" class="iframe-container">
+6 -7
View File
@@ -57,7 +57,7 @@
.tfw-messages { .tfw-messages {
// Check whether the layout contains a web component // Check whether the layout contains a web component
div[class*="web"] & { div[class*="web"] & {
border: 2px solid $tao-gray-100; border: 2px solid $tao-base-color;
border-top: 0; border-top: 0;
border-left: 0; border-left: 0;
border-bottom: 0; border-bottom: 0;
@@ -65,17 +65,16 @@
} }
.tfw-header { .tfw-header {
padding: $small; padding: $tiny;
padding-top: $tiny; padding-top: $hair;
background-color: $tao-gray-50; background-color: $tao-base-color;
} }
@include set-scrollbar-style('dark', '.tfw-messages'); @include set-scrollbar-style('dark', '.tfw-messages');
.tfw-messages { .tfw-messages {
padding: $space; padding: $tiny;
padding-top: $hair; background-color: $tao-base-color;
background-color: $tao-gray-50;
overflow-y: scroll; overflow-y: scroll;
max-height: 95vmin; max-height: 95vmin;
+2 -1
View File
@@ -103,7 +103,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
} }
reloadIframeHandler(message: WebSocketMessage) { reloadIframeHandler(message: WebSocketMessage) {
setTimeout(() => this.reloadIframe(), 200); this.iframeReloadPoller.ok.subscribe(() => this.reloadIframe());
this.iframeReloadPoller.start();
} }
setLayout(layout: string) { setLayout(layout: string) {
+2 -3
View File
@@ -1,4 +1,3 @@
<div class="tfw-grid-navbar tao-grid-center-center"> <div>
<img src="images/avatao_logo.svg" routerLink="/" class="tao-grid-center-left tfw-company-logo" alt=""> <img src="images/avatao-tutorial-framework-logo.svg" routerLink="/" class="tao-grid-center-left tfw-company-logo" alt="">
<span class="tfw-header-title">Tutorials</span>
</div> </div>
+2 -13
View File
@@ -1,19 +1,8 @@
@import "../../assets/scss/variables.scss"; @import "../../assets/scss/variables.scss";
.tfw-header-title {
color: $tao-blue-500;
font-size: $font-size-h3;
}
.tfw-grid-navbar {
display: grid;
grid-template-columns: $company-logo-width 1fr;
grid-column-gap: 8px;
width: 100%;
}
.tfw-company-logo { .tfw-company-logo {
display: block; display: block;
width: $company-logo-width; padding: $tiny;
width: 80%;
} }
+11 -1
View File
@@ -32,6 +32,7 @@ export class IdeComponent implements OnInit {
files: string[]; files: string[];
filename = ''; filename = '';
lastFilename = ''; lastFilename = '';
reloadFile = false;
code = 'Loading your file...'; code = 'Loading your file...';
codeState = CodeState.SAVED; codeState = CodeState.SAVED;
@@ -85,10 +86,18 @@ export class IdeComponent implements OnInit {
} }
reloadHandler(message: WebSocketMessage) { reloadHandler(message: WebSocketMessage) {
if (!this.reloadFile) {
this.reloadFile = true;
this.requestCode(); this.requestCode();
} }
}
readHandler(message: IDEMessage) { readHandler(message: IDEMessage) {
if (!this.reloadFile && message.reload) {
return;
}
this.reloadFile = false;
if (this.codeState === CodeState.SAVED) { if (this.codeState === CodeState.SAVED) {
if (this.filename !== message.filename) { if (this.filename !== message.filename) {
this.filename = message.filename; this.filename = message.filename;
@@ -189,7 +198,8 @@ export class IdeComponent implements OnInit {
requestCode() { requestCode() {
this.webSocketService.send({ this.webSocketService.send({
'key': 'ide.read', 'key': 'ide.read',
'filename': this.filename 'filename': this.filename,
'reload': this.reloadFile
}); });
} }
} }
+4
View File
@@ -1,9 +1,13 @@
import { WebSocketMessage } from './websocket-message'; import { WebSocketMessage } from './websocket-message';
export type MessageButton = 'yes' | 'no' | 'fix' | 'hint' | 'solution' | 'next';
export type MessageButtonMap = Record<MessageButton, {caption: string}>;
export interface MessageData { export interface MessageData {
originator?: string; originator?: string;
timestamp?: Date; timestamp?: Date;
typing?: boolean; typing?: boolean;
buttons?: MessageButton[];
command?: any; command?: any;
message: string; message: string;
} }
+1
View File
@@ -4,4 +4,5 @@ export interface IDEMessage extends WebSocketMessage {
filename: string; filename: string;
content?: string; content?: string;
files?: string[]; files?: string[];
reload?: boolean;
} }
+12 -2
View File
@@ -4,11 +4,21 @@
[class.highlighted-message]="last" [class.highlighted-message]="last"
(click)="sendMessageCommand(message)"> (click)="sendMessageCommand(message)">
<div class="tfw-grid-message-header"> <div class="tfw-grid-message-header">
<img class="tao-grid-center-left" src="images/avataobot.svg"/>
<div class="tao-grid-center-left originator">{{message.originator}}</div> <div class="tao-grid-center-left originator">{{message.originator}}</div>
<div class="timestamp tao-grid-center-right">{{message.timestamp | date:'HH:mm:ss'}}</div> <div class="timestamp tao-grid-center-right">{{message.timestamp | date:'HH:mm:ss'}}</div>
</div> </div>
<div class="tfw-grid-message-body" [innerHtml]="message.message"></div> <div class="tfw-grid-message-body" [innerHtml]="message.message | safeHtml"></div>
<div *ngIf="message.buttons !== undefined">
<div class="tfw-message-btn-divider"></div>
<div class="tfw-message-btn">
<button *ngFor="let messageButton of message.buttons"
class="{{messageButton}}"
(click)="sendButtonCommand(messageButton)">
{{buttonMap[messageButton].caption}}
</button>
</div>
</div>
</div> </div>
<div *ngIf="showTypingIndicator" <div *ngIf="showTypingIndicator"
class="tfw-grid-message jumping-circle-container" class="tfw-grid-message jumping-circle-container"
+70 -17
View File
@@ -1,29 +1,73 @@
@import "../../assets/scss/variables.scss"; @import "../../assets/scss/variables.scss";
@import "../../assets/scss/mixins/layout"; @import "../../assets/scss/mixins/layout";
@import "../../assets/scss/mixins/button";
.tfw-next-button {
text-align: center;
}
.tfw-grid-message { .tfw-grid-message {
font-family: "Roboto";
font-style: normal;
display: grid; display: grid;
grid-template-rows: 1fr auto; grid-template-rows: 1fr auto;
grid-row-gap: $hair; grid-row-gap: $nano;
width: 100%; width: 100%;
padding: $hair;
background-color: $tao-gray-100;
border-radius: $tao-panel-border-radius-sm; border-radius: $tao-panel-border-radius-sm;
padding: $tiny;
font-size: $font-size-base; font-size: $font-size-base;
margin-bottom: $hair; margin-bottom: $hair;
animation-name: inflate; animation-name: inflate;
animation-duration: 0.5s; animation-duration: 0.5s;
animation-timing-function: cubic-bezier(0.01, 0.1, 0, 1); animation-timing-function: cubic-bezier(0.01, 0.1, 0, 1);
color: white;
background-color: $tao-card-color;
.tfw-message-btn-divider {
opacity: 0.25;
border: 1px solid $tao-gray-color;
}
.tfw-message-btn {
color: $tao-btn-font-color;
padding-top: $tiny;
padding-bottom: $hair;
display: flex;
align-items: center;
text-align: center;
.no {
@include set-button-style($tao-red-color, $tao-shadow-red-color);
width: $xlarge;
}
.yes {
@include set-button-style($tao-green-color, $tao-shadow-green-color);
width: $xlarge;
}
.solution {
@include set-button-style(white, $tao-shadow-color);
width: $xlarge + $medium + $tiny;
}
.hint {
@include set-button-style($tao-blue-color, $tao-shadow-blue-color);
width: $xlarge;
}
.fix {
@include set-button-style($tao-yellow-color, $tao-shadow-yellow-color);
width: $xlarge + $medium + $tiny;
}
.next {
@include set-button-style($tao-blue-color, $tao-shadow-blue-color);
width: $xlarge;
}
}
} }
.highlighted-message { .highlighted-message {
box-shadow: 0px 0px 3px 0px rgba($tao-gray-300,0.65); // box-shadow: 0px 0px 8px 0px $tao-blue-color;
border: 3px single $tao-blue-color;
} }
@keyframes inflate { @keyframes inflate {
@@ -65,24 +109,33 @@
.tfw-grid-message-header { .tfw-grid-message-header {
display: grid; display: grid;
grid-template-columns: 1fr 5fr 8fr; grid-template-columns: 5fr 8fr;
grid-column-gap: 4px; grid-column-gap: 4px;
width: 100%; width: 100%;
img {
width: 12px;
}
.originator { .originator {
font-weight: 500; font-style: normal;
font-weight: bold;
font-size: $font-size-base;
line-height: 26px;
display: flex;
align-items: center;
color: $tao-message-originator-color;
} }
.timestamp { .timestamp {
font-size: $font-size-tiny; font-size: $font-size-base;
color: $tao-gray-color;
opacity: 0.37; opacity: 0.37;
} }
} }
.tfw-grid-message-body { .tfw-grid-message-body {
@include word-break() @include word-break();
line-height: 26px;
& p {
margin-bottom: $tiny !important;
}
} }
+16 -2
View File
@@ -1,5 +1,5 @@
import { ChangeDetectorRef, Component, OnInit, EventEmitter, Output, ElementRef } from '@angular/core'; import { ChangeDetectorRef, Component, OnInit, EventEmitter, Output, ElementRef } from '@angular/core';
import { MessageData, Message } from '../message-types/bot-messages'; import {MessageData, Message, MessageButton, MessageButtonMap} from '../message-types/bot-messages';
import { MarkdownService } from '../services/markdown.service'; import { MarkdownService } from '../services/markdown.service';
import { WebSocketService } from '../services/websocket.service'; import { WebSocketService } from '../services/websocket.service';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@@ -13,8 +13,15 @@ export class MessagesComponent implements OnInit {
@Output() newMessageEvent: EventEmitter<any> = new EventEmitter(); @Output() newMessageEvent: EventEmitter<any> = new EventEmitter();
newMessage: Subject<MessageData> = new Subject<MessageData>(); newMessage: Subject<MessageData> = new Subject<MessageData>();
showTypingIndicator = false; showTypingIndicator = false;
messages: MessageData[] = []; messages: MessageData[] = [];
buttonMap: MessageButtonMap = {
fix: {caption: 'Ready to fix'},
solution: {caption: 'Show solution'},
hint: {caption: 'Hint'},
next: {caption: 'Next'},
yes: {caption: 'Yes'},
no: {caption: 'No'},
};
constructor( constructor(
private markdownService: MarkdownService, private markdownService: MarkdownService,
@@ -71,4 +78,11 @@ export class MessagesComponent implements OnInit {
this.websocketService.send(message.command); this.websocketService.send(message.command);
} }
} }
sendButtonCommand(messageButton: MessageButton) {
this.websocketService.send({
'key': 'message.button.click',
'value': messageButton
});
}
} }
+13
View File
@@ -0,0 +1,13 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'capitalize',
})
export class CapitalizePipe implements PipeTransform {
transform(value: string): string {
if (!value) {
return '';
}
return value[0].toLocaleUpperCase() + value.toLocaleLowerCase().slice(1);
}
}
+11
View File
@@ -11,3 +11,14 @@ export class SafePipe implements PipeTransform {
return this.sanitizer.bypassSecurityTrustResourceUrl(value); return this.sanitizer.bypassSecurityTrustResourceUrl(value);
} }
} }
@Pipe({
name: 'safeHtml'
})
export class SafeHtmlPipe implements PipeTransform {
constructor(private sanitized: DomSanitizer) {}
transform(value) {
return this.sanitized.bypassSecurityTrustHtml(value);
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ export class DashboardConfigService extends ConfigServiceBase {
layout = new BehaviorSubject<string>('terminal-ide-web'); layout = new BehaviorSubject<string>('terminal-ide-web');
hideMessages = new BehaviorSubject<boolean>(false); hideMessages = new BehaviorSubject<boolean>(false);
iframeUrl = new BehaviorSubject<string>('/webservice'); iframeUrl = new BehaviorSubject<string>('');
showUrlBar = new BehaviorSubject<boolean>(false); showUrlBar = new BehaviorSubject<boolean>(false);
terminalMenuItem = new BehaviorSubject<string>('terminal'); terminalMenuItem = new BehaviorSubject<string>('terminal');
reloadIframeOnDeploy = new BehaviorSubject<boolean>(false); reloadIframeOnDeploy = new BehaviorSubject<boolean>(false);
+44 -13
View File
@@ -8,11 +8,16 @@ export class TerminadoService {
xterm: Terminal; xterm: Terminal;
ws: WebSocket; ws: WebSocket;
attached = false; attached = false;
private dataListener: any;
private resizeListener: any;
constructor() { constructor() {
Terminal.applyAddon(fit); Terminal.applyAddon(fit);
Terminal.applyAddon(terminado); this.xterm = this.createTerminal();
this.xterm = new Terminal({ }
createTerminal() {
return new Terminal({
theme: { theme: {
foreground: '#ffffff', foreground: '#ffffff',
background: '#0C0C0C', // $tao-gray-800 background: '#0C0C0C', // $tao-gray-800
@@ -21,8 +26,8 @@ export class TerminadoService {
black: '#000000', black: '#000000',
red: '#FF5252', // $tao-red-500 red: '#FF5252', // $tao-red-500
brightRed: '#FF7171', // $tao-red-400 brightRed: '#FF7171', // $tao-red-400
green: '#2fd19f', // $tao-bright-green-500 green: '#60FDEB', // $tao-bright-green-500
brightGreen: '#2fd19f', // $tao-bright-green-500 brightGreen: '#60FDEB', // $tao-bright-green-500
brightYellow: '#FFD283', // $tao-warm-yellow-300 brightYellow: '#FFD283', // $tao-warm-yellow-300
yellow: '#FFB83B', // $tao-warm-yellow-500 yellow: '#FFB83B', // $tao-warm-yellow-500
magenta: '#FF8FC6', // $tao-pink-200 magenta: '#FF8FC6', // $tao-pink-200
@@ -37,26 +42,52 @@ export class TerminadoService {
}, },
fontSize: 14 fontSize: 14
}); });
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
this.ws = new WebSocket(wsproto + window.location.host + '/terminal');
} }
attach(element: HTMLElement) { attach(element: HTMLElement) {
if (this.attached) {
return;
}
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
this.ws = new WebSocket(wsproto + window.location.host + '/terminal');
this.ws.onopen = () => { this.ws.onopen = () => {
(<any>this.xterm).terminadoAttach(this.ws); this.attached = true;
this.xterm = this.createTerminal();
this.xterm.open(element); this.xterm.open(element);
this.fit(); this.fit();
this.xterm.blur(); // In order to reset the terminal state after a broken socket, we need to register the listeners manually.
this.attached = true; (<any>this.xterm)._core.register(this.dataListener = this.xterm.onData(data => {
this.ws.send(JSON.stringify(['stdin', data]));
}));
(<any>this.xterm)._core.register(this.resizeListener = this.xterm.onResize((size: { rows: number, cols: number }) => {
this.ws.send(JSON.stringify(['set_size', size.rows, size.cols]));
}));
};
this.ws.onclose = () => {
this.detach();
this.xterm.destroy();
this.attach(element);
};
this.ws.onmessage = msg => {
const data = JSON.parse(msg.data);
if (data[0] === 'stdout') {
this.xterm.write(data[1]);
}
}; };
} }
detach() { detach() {
(<any>this.xterm).terminadoDetach(this.ws); if (!this.attached) {
this.xterm.destroy(); return;
this.ws.close(); }
this.attached = false; this.attached = false;
this.dataListener.dispose();
this.resizeListener.dispose();
} }
fit() { fit() {
+17 -3
View File
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable, Subject, Subscription } from 'rxjs';
import { webSocket, WebSocketSubject } from 'rxjs/webSocket'; import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
import { filter, map } from 'rxjs/operators'; import { filter, map } from 'rxjs/operators';
import { WebSocketMessage } from '../message-types/websocket-message'; import { WebSocketMessage } from '../message-types/websocket-message';
@@ -17,14 +17,28 @@ export enum Intent {
@Injectable() @Injectable()
export class WebSocketService { export class WebSocketService {
private ws: WebSocketSubject<WebSocketMessage>; private ws: WebSocketSubject<WebSocketMessage>;
private subject: Subject<WebSocketMessage> = new Subject<WebSocketMessage>();
private subscription: Subscription;
constructor() {} constructor() {}
public connect() { public connect() {
if (!this.ws) { if (!this.ws) {
if (this.subscription) {
this.subscription.unsubscribe();
}
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://'; const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
const connAddr = wsproto + window.location.host + '/ws'; const connAddr = wsproto + window.location.host + '/ws';
this.ws = webSocket<WebSocketMessage>(connAddr); this.ws = webSocket<WebSocketMessage>({
url: connAddr,
closeObserver: {
next: closeEvent => {
this.ws = null;
this.connect();
}
}
});
this.subscription = this.ws.subscribe(msg => this.subject.next(msg));
} }
} }
@@ -35,7 +49,7 @@ export class WebSocketService {
} }
public observeAll<T extends WebSocketMessage>(key: string): Observable<T> { public observeAll<T extends WebSocketMessage>(key: string): Observable<T> {
return this.ws.pipe( return this.subject.pipe(
filter(message => message.key.startsWith(key)), filter(message => message.key.startsWith(key)),
map(message => <T> message) map(message => <T> message)
); );
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.0 KiB

-1
View File
@@ -1 +0,0 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11.98 16.98"><defs><style>.cls-1{fill:none;stroke:#277eec;stroke-linecap:round;stroke-linejoin:round;stroke-width:2px;}</style></defs><title>avataobot</title><rect class="cls-1" x="2.46" y="7.47" width="7.05" height="7.05" transform="translate(9.53 -1.01) rotate(45)"/><polyline class="cls-1" points="10.98 1 5.99 5.99 1 1"/></svg>

Before

Width:  |  Height:  |  Size: 417 B

+1
View File
@@ -3,6 +3,7 @@
'grid'; 'grid';
@import @import
'mixins/button',
'mixins/scrollbar'; 'mixins/scrollbar';
@import @import
+20 -48
View File
@@ -2,7 +2,7 @@
// Spaces // Spaces
// //
$space: 24px; $space: 32px;
$sxlarge: 9 * $space; $sxlarge: 9 * $space;
$xxxlarge: 6 * $space; $xxxlarge: 6 * $space;
@@ -30,30 +30,6 @@ $tao-blue-700: #195684;
$tao-blue-800: #103B5B; $tao-blue-800: #103B5B;
$tao-blue-900: #081A2B; $tao-blue-900: #081A2B;
// Tao sky palette
$tao-sky-50: #F1FAFD;
$tao-sky-100: #C5E9F5;
$tao-sky-200: #9AD8EE;
$tao-sky-300: #6EC7E6;
$tao-sky-400: #42B7DF;
$tao-sky-500: #19A7D8;
$tao-sky-600: #0E8BA8;
$tao-sky-700: #04647A;
$tao-sky-800: #004251;
$tao-sky-900: #002028;
// Tao phtalo palette
$tao-phtalo-50: #F2FBFC;
$tao-phtalo-100: #C8EDF1;
$tao-phtalo-200: #9FDFE6;
$tao-phtalo-300: #75D1DB;
$tao-phtalo-400: #4CC3D0;
$tao-phtalo-500: #24B6C6;
$tao-phtalo-600: #16989E;
$tao-phtalo-700: #0C7575;
$tao-phtalo-800: #034C4F;
$tao-phtalo-900: #002426;
// Tao turqoise palette // Tao turqoise palette
$tao-turqoise-50: #F1FBFB; $tao-turqoise-50: #F1FBFB;
$tao-turqoise-100: #C3EFEF; $tao-turqoise-100: #C3EFEF;
@@ -90,29 +66,6 @@ $tao-warm-yellow-700: #CC8B36;
$tao-warm-yellow-800: #B2762F; $tao-warm-yellow-800: #B2762F;
$tao-warm-yellow-900: #996526; $tao-warm-yellow-900: #996526;
// Tao plum palette
$tao-plum-50: #F6F8FD;
$tao-plum-100: #DADFF8;
$tao-plum-200: #BEC7F3;
$tao-plum-300: #A2AFED;
$tao-plum-400: #8797E8;
$tao-plum-500: #6C80E3;
$tao-plum-600: #5E77BF;
$tao-plum-700: #4B5E99;
$tao-plum-800: #384672;
$tao-plum-900: #272F4C;
// Tao pink palette
$tao-pink-50: #FFF0F7;
$tao-pink-100: #FFBFDF;
$tao-pink-200: #FF8FC6;
$tao-pink-300: #FF5EAE;
$tao-pink-400: #FF2E95;
$tao-pink-500: #FF007E;
$tao-pink-600: #D8007C;
$tao-pink-700: #B20066;
$tao-pink-800: #8C0050;
$tao-pink-900: #66003A;
// Tao red palette // Tao red palette
$tao-red-50: #FFF5F5; $tao-red-50: #FFF5F5;
@@ -138,6 +91,25 @@ $tao-gray-700: #232323;
$tao-gray-800: #0C0C0C; $tao-gray-800: #0C0C0C;
$tao-gray-900: #000000; $tao-gray-900: #000000;
// Tao messages
$tao-base-color: #2A324C;
$tao-btn-font-color: #1F2836;
$tao-card-color: #363E56;
$tao-message-originator-color: #6697FF;
$tao-copy-color: #FFFFFF;
$tao-timestamp-color: #94A6B9;
$tao-gray-color: #94A6B9; // @25% opacity
$tao-shadow-color: rgba(255, 255, 255, 0.5);
$tao-yellow-color: #FFD68F;
$tao-shadow-yellow-color: rgba(255, 214, 143, 0.5);
$tao-blue-color: #6697FF;
$tao-shadow-blue-color: rgba(102, 151, 255, 0.5);
$tao-green-color: #48BEB0;
$tao-shadow-green-color: rgba(72, 190, 176, 0.5);
$tao-cyan-color: #60FDEB;
$tao-red-color: #FF4583;
$tao-shadow-red-color: rgba(255, 69, 131, 0.5);
// Panel border radius // Panel border radius
$tao-panel-border-radius: 14px; $tao-panel-border-radius: 14px;
+27
View File
@@ -0,0 +1,27 @@
@import "../variables.scss";
@mixin set-button-style($color, $shadow-color) {
box-sizing: border-box;
border-radius: 10px;
background: $color;
border: 1.5px solid $color;
font-style: normal;
font-weight: bold;
font-size: 14px;
line-height: 26px;
height: $space;
margin-right: $tiny;
color: $tao-btn-font-color;
outline: none;
&:active {
opacity: 0.5;
box-shadow: none;
}
&:hover {
box-shadow: 0 0 8px $shadow-color;
}
}
+16 -16
View File
@@ -2,8 +2,8 @@ $grid-columns-count: 100;
$grid-rows-count: 30; $grid-rows-count: 30;
$terminal-ide-web-layout: ( $terminal-ide-web-layout: (
'header': (0, 20, 0, 8), 'messages': (0, 20, 0, 52),
'messages': (0, 20, 8, 60), 'header': (0, 20, 52, 60),
'ide': (56, 96, 0, 100), 'ide': (56, 96, 0, 100),
'terminal': (0, 56, 60, 100), 'terminal': (0, 56, 60, 100),
'web': (20, 56, 0, 60), 'web': (20, 56, 0, 60),
@@ -11,8 +11,8 @@ $terminal-ide-web-layout: (
); );
$terminal-web-layout: ( $terminal-web-layout: (
'header': (0, 20, 0, 8), 'messages': (0, 20, 0, 92),
'messages': (0, 20, 8, 100), 'header': (0, 20, 92, 100),
'ide': (), 'ide': (),
'terminal': (56, 96, 0, 100), 'terminal': (56, 96, 0, 100),
'web': (20, 56, 0, 100), 'web': (20, 56, 0, 100),
@@ -20,8 +20,8 @@ $terminal-web-layout: (
); );
$terminal-ide-vertical-layout: ( $terminal-ide-vertical-layout: (
'header': (0, 20, 0, 8), 'messages': (0, 20, 0, 92),
'messages': (0, 20, 8, 100), 'header': (0, 20, 92, 100),
'ide': (56, 96, 0, 100), 'ide': (56, 96, 0, 100),
'terminal': (20, 56, 0, 100), 'terminal': (20, 56, 0, 100),
'web': (), 'web': (),
@@ -29,8 +29,8 @@ $terminal-ide-vertical-layout: (
); );
$terminal-ide-horizontal-layout: ( $terminal-ide-horizontal-layout: (
'header': (0, 20, 0, 8), 'messages': (0, 20, 0, 92),
'messages': (0, 20, 8, 100), 'header': (0, 20, 92, 100),
'ide': (20, 96, 0, 60), 'ide': (20, 96, 0, 60),
'terminal': (20, 96, 60, 100), 'terminal': (20, 96, 60, 100),
'web': (), 'web': (),
@@ -38,8 +38,8 @@ $terminal-ide-horizontal-layout: (
); );
$ide-web-vertical-layout: ( $ide-web-vertical-layout: (
'header': (0, 20, 0, 8), 'messages': (0, 20, 0, 92),
'messages': (0, 20, 8, 100), 'header': (0, 20, 92, 100),
'ide': (56, 96, 0, 100), 'ide': (56, 96, 0, 100),
'terminal': (), 'terminal': (),
'web': (20, 56, 0, 100), 'web': (20, 56, 0, 100),
@@ -47,8 +47,8 @@ $ide-web-vertical-layout: (
); );
$terminal-only-layout: ( $terminal-only-layout: (
'header': (0, 20, 0, 8), 'messages': (0, 20, 0, 92),
'messages': (0, 20, 8, 100), 'header': (0, 20, 92, 100),
'ide': (), 'ide': (),
'terminal': (20, 96, 0, 100), 'terminal': (20, 96, 0, 100),
'web': (), 'web': (),
@@ -56,8 +56,8 @@ $terminal-only-layout: (
); );
$ide-only-layout: ( $ide-only-layout: (
'header': (0, 20, 0, 8), 'messages': (0, 20, 0, 92),
'messages': (0, 20, 8, 100), 'header': (0, 20, 92, 100),
'ide': (20, 96, 0, 100), 'ide': (20, 96, 0, 100),
'terminal': (), 'terminal': (),
'web': (), 'web': (),
@@ -65,8 +65,8 @@ $ide-only-layout: (
); );
$web-only-layout: ( $web-only-layout: (
'header': (0, 20, 0, 8), 'messages': (0, 20, 0, 92),
'messages': (0, 20, 8, 100), 'header': (0, 20, 92, 100),
'ide': (), 'ide': (),
'terminal': (), 'terminal': (),
'web': (20, 96, 0, 100), 'web': (20, 96, 0, 100),
+5 -4
View File
@@ -1,10 +1,10 @@
@mixin set-scrollbar-style($style, $selctor) { @mixin set-scrollbar-style($style, $selector) {
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 3px !important; width: 3px !important;
height: 3px !important; height: 3px !important;
} }
#{$selctor}::-webkit-scrollbar-track { #{$selector}::-webkit-scrollbar-track {
border-radius: 10px !important; border-radius: 10px !important;
width: 3px !important; width: 3px !important;
@if ($style == 'light') { @if ($style == 'light') {
@@ -15,7 +15,7 @@
}; };
} }
#{$selctor}::-webkit-scrollbar-thumb { #{$selector}::-webkit-scrollbar-thumb {
@if ($style == 'dark') { @if ($style == 'dark') {
background: #8a8a8a !important; background: #8a8a8a !important;
@@ -25,7 +25,7 @@
border-radius: 10px !important; border-radius: 10px !important;
} }
#{$selctor}::-webkit-scrollbar-thumb:hover { #{$selector}::-webkit-scrollbar-thumb:hover {
@if ($style == 'dark') { @if ($style == 'dark') {
background: #424242 !important; background: #424242 !important;
@@ -35,3 +35,4 @@
cursor: pointer !important; cursor: pointer !important;
} }
} }
+1
View File
@@ -5,6 +5,7 @@
<base href="/"> <base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="images/favicon.ico"> <link rel="icon" type="image/x-icon" href="images/favicon.ico">
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap" rel="stylesheet" type="text/css">
</head> </head>
<body> <body>
<app-root></app-root> <app-root></app-root>
+1
View File
@@ -8,5 +8,6 @@ body, html {
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
overflow: hidden; overflow: hidden;
@include set-scrollbar-style('light', ''); @include set-scrollbar-style('light', '');
} }
+6796
View File
File diff suppressed because it is too large Load Diff