mirror of
				https://github.com/avatao-content/frontend-tutorial-framework
				synced 2025-11-04 12:12:55 +00:00 
			
		
		
		
	Merge branch 'frontend_fixes'
This commit is contained in:
		@@ -21,6 +21,7 @@ export const config = {
 | 
			
		||||
      'web-only'
 | 
			
		||||
      ],
 | 
			
		||||
    iframeUrl: '/webservice',
 | 
			
		||||
    showUrlBar: false,
 | 
			
		||||
    hideMessages: false
 | 
			
		||||
  },
 | 
			
		||||
  ide: {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,15 +10,25 @@
 | 
			
		||||
      <app-messages (newMessageEvent)="scrollMessagesToBottom()"></app-messages>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="tfw-web tao-grid-top-left"
 | 
			
		||||
         [ngClass]="{'deploy-blur': deploying}">
 | 
			
		||||
         [ngClass]="{'deploy-blur': deploying || polling}">
 | 
			
		||||
         <app-web *ngIf="!iframeUrl"></app-web>
 | 
			
		||||
         <div *ngIf="showUrlBar" class="urlbar-container">
 | 
			
		||||
           <button class="refresh btn btn-sm rounded-circle" (click)="reloadIframe()">↻</button>
 | 
			
		||||
           <input type="text"
 | 
			
		||||
                  #urlbar
 | 
			
		||||
                  class="urlbar form-control"
 | 
			
		||||
                  value="{{actualIframeUrl}}"
 | 
			
		||||
                  (keyup.enter)="changeIframeURL()">
 | 
			
		||||
           <button class="go btn btn-sm rounded-circle" (click)="changeIframeURL()">⇨</button>
 | 
			
		||||
         </div>
 | 
			
		||||
         <div *ngIf="iframeUrl" class="iframe-container">
 | 
			
		||||
          <iframe class="iframe"
 | 
			
		||||
                  #webiframe
 | 
			
		||||
                  scrolling="yes"
 | 
			
		||||
                  frameborder="0"
 | 
			
		||||
                  [src]="iframeUrl | safe">
 | 
			
		||||
          </iframe>
 | 
			
		||||
            <iframe class="iframe"
 | 
			
		||||
                    #webiframe
 | 
			
		||||
                    scrolling="yes"
 | 
			
		||||
                    frameborder="0"
 | 
			
		||||
                    (load)="iframeLoad()"
 | 
			
		||||
                    [src]="iframeUrl | safe">
 | 
			
		||||
            </iframe>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="tfw-ide">
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,13 @@
 | 
			
		||||
 | 
			
		||||
@import "../../assets/scss/variables.scss";
 | 
			
		||||
@import "../../assets/scss/mixins/layout.scss";
 | 
			
		||||
@import "../../assets/scss/mixins/scrollbar";
 | 
			
		||||
 | 
			
		||||
@mixin set-tfw-web($layouts-key) {
 | 
			
		||||
  .tfw-web {
 | 
			
		||||
    .iframe-container {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      @include set-component-size($layouts-key, 'web');
 | 
			
		||||
    }
 | 
			
		||||
@@ -18,6 +20,30 @@
 | 
			
		||||
      margin: 0;
 | 
			
		||||
      padding: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .urlbar-container {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      height: 37px;
 | 
			
		||||
      background: #353535;
 | 
			
		||||
 | 
			
		||||
      .btn {
 | 
			
		||||
        background: #353535;
 | 
			
		||||
        color: white;
 | 
			
		||||
        align-self: center;
 | 
			
		||||
        margin: 5px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .btn:hover{
 | 
			
		||||
        background: lighten(#353535, 10);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .urlbar {
 | 
			
		||||
      flex-grow: 1;
 | 
			
		||||
      height: 30px;
 | 
			
		||||
      align-self: center;
 | 
			
		||||
      border-radius: 15px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -46,6 +72,8 @@
 | 
			
		||||
    background-color: $tao-gray-50;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @include set-scrollbar-style('dark', '.tfw-messages');
 | 
			
		||||
 | 
			
		||||
  .tfw-messages {
 | 
			
		||||
    padding: $space;
 | 
			
		||||
    padding-top: $hair;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@ import { config } from '../config';
 | 
			
		||||
import { ProcessLogService } from '../services/processlog.service';
 | 
			
		||||
import { LogMessage } from '../message-types/log-message';
 | 
			
		||||
import { CommandMessage } from '../message-types/command-message';
 | 
			
		||||
import { HttpClient } from '@angular/common/http';
 | 
			
		||||
import { delay, retryWhen, tap } from 'rxjs/operators';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-dashboard',
 | 
			
		||||
@@ -18,14 +20,19 @@ import { CommandMessage } from '../message-types/command-message';
 | 
			
		||||
})
 | 
			
		||||
export class DashboardComponent implements OnInit, OnDestroy {
 | 
			
		||||
  deploying = false;
 | 
			
		||||
  polling = false;
 | 
			
		||||
  deploymentNotificationSubscription: Subscription;
 | 
			
		||||
  @ViewChild('webiframe') webiframe: ElementRef;
 | 
			
		||||
  @ViewChild('tfwmessages') messages: ElementRef;
 | 
			
		||||
  @ViewChild('urlbar') urlbar: ElementRef;
 | 
			
		||||
 | 
			
		||||
  layout: string = config.dashboard.currentLayout;
 | 
			
		||||
  hideMessages: boolean = config.dashboard.hideMessages;
 | 
			
		||||
  iframeUrl: string = config.dashboard.iframeUrl;
 | 
			
		||||
  showUrlBar = config.dashboard.showUrlBar;
 | 
			
		||||
  actualIframeUrl: string = this.iframeUrl;
 | 
			
		||||
  selectedTerminalMenuItem: string = config.dashboard.terminalOrConsole;
 | 
			
		||||
  iframeReloadSubscription: Subscription;
 | 
			
		||||
 | 
			
		||||
  command_handlers = {
 | 
			
		||||
    'layout':           this.layoutHandler.bind(this),
 | 
			
		||||
@@ -38,7 +45,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
 | 
			
		||||
  constructor(private deploymentNotificationService: DeploymentNotificationService,
 | 
			
		||||
              private webSocketService: WebSocketService,
 | 
			
		||||
              private changeDetectorRef: ChangeDetectorRef,
 | 
			
		||||
              private processLogService: ProcessLogService) {}
 | 
			
		||||
              private processLogService: ProcessLogService,
 | 
			
		||||
              private http: HttpClient) {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.webSocketService.connect();
 | 
			
		||||
@@ -60,7 +68,10 @@ export class DashboardComponent implements OnInit, OnDestroy {
 | 
			
		||||
      (deploying) => {
 | 
			
		||||
        this.deploying = deploying;
 | 
			
		||||
        if (!deploying && config.ide.reloadIframeOnDeploy) {
 | 
			
		||||
          this.reloadIframe();
 | 
			
		||||
          if (this.polling) {
 | 
			
		||||
            this.iframeReloadSubscription.unsubscribe();
 | 
			
		||||
          }
 | 
			
		||||
          this.pollingServerForIframeReload();
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
@@ -113,12 +124,6 @@ export class DashboardComponent implements OnInit, OnDestroy {
 | 
			
		||||
    setTimeout(() => window.dispatchEvent(new Event('resize', {force: true} as any)), 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    if (this.deploymentNotificationSubscription) {
 | 
			
		||||
      this.deploymentNotificationSubscription.unsubscribe();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  reloadIframe() {
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      this.webiframe.nativeElement.contentWindow.location.reload(true);
 | 
			
		||||
@@ -152,4 +157,44 @@ export class DashboardComponent implements OnInit, OnDestroy {
 | 
			
		||||
    // change detection (not in the template like ConsoleComponent does)
 | 
			
		||||
    element.scrollTop = element.scrollHeight;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  iframeLoad(): void {
 | 
			
		||||
    if (this.webiframe) {
 | 
			
		||||
      this.actualIframeUrl = this.webiframe.nativeElement.contentWindow.frames.location.pathname;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  changeIframeURL() {
 | 
			
		||||
    this.webiframe.nativeElement.contentWindow.frames.location.pathname = this.urlbar.nativeElement.value;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pollingServerForIframeReload() {
 | 
			
		||||
    this.polling = true;
 | 
			
		||||
    this.iframeReloadSubscription = this.http.get(this.actualIframeUrl, {observe: 'response'}).pipe(
 | 
			
		||||
      retryWhen(errors =>
 | 
			
		||||
        errors.pipe(
 | 
			
		||||
          tap(
 | 
			
		||||
            response => {
 | 
			
		||||
              if (response.status === 200) {
 | 
			
		||||
                this.iframeReloadSubscription.unsubscribe();
 | 
			
		||||
                this.polling = false;
 | 
			
		||||
                this.reloadIframe();
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ),
 | 
			
		||||
          delay(1000)
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    ).subscribe();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    if (this.deploymentNotificationSubscription) {
 | 
			
		||||
      this.deploymentNotificationSubscription.unsubscribe();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this.iframeReloadSubscription) {
 | 
			
		||||
      this.iframeReloadSubscription.unsubscribe();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,6 @@
 | 
			
		||||
 | 
			
		||||
<ngx-monaco-editor [(ngModel)]="code"
 | 
			
		||||
                   class="tfw-ide-editor"
 | 
			
		||||
                   (keyup)="editorWriteHanlder()"
 | 
			
		||||
                   (ngModelChange)="editorWriteHanlder()"
 | 
			
		||||
                   [options]="editorOptions"
 | 
			
		||||
></ngx-monaco-editor>
 | 
			
		||||
 
 | 
			
		||||
@@ -4,13 +4,12 @@
 | 
			
		||||
@import "../../assets/scss/variables.scss";
 | 
			
		||||
 | 
			
		||||
.tfw-grid-ide-statusbar {
 | 
			
		||||
  display: grid;
 | 
			
		||||
  grid-template-columns: 8fr 1fr;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  background-color: #353535;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tfw-ide-editor {
 | 
			
		||||
  height: calc(100% - 67px);
 | 
			
		||||
  height: calc(100% - 25px);
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
@@ -37,13 +36,20 @@
 | 
			
		||||
 | 
			
		||||
.tfw-deploy-btn-group {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: flex-end;  
 | 
			
		||||
  justify-content: flex-end;
 | 
			
		||||
  flex-grow: 1;
 | 
			
		||||
 | 
			
		||||
  .tfw-deploy-btn {
 | 
			
		||||
    background: $tao-bright-green-200;
 | 
			
		||||
    padding: 0.3em 0.7em 0.7em 1.5em;
 | 
			
		||||
    border-radius: 0;
 | 
			
		||||
    border-bottom-left-radius: 2.2em;
 | 
			
		||||
    border-radius: 0 0 0 2.2em;
 | 
			
		||||
    color: black;
 | 
			
		||||
 | 
			
		||||
    &:first-child {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      justify-content: center;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    img {
 | 
			
		||||
      padding-right: 0.5em;
 | 
			
		||||
@@ -71,9 +77,8 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    .loader {
 | 
			
		||||
      border: 2px solid $tao-warm-yellow-600;
 | 
			
		||||
      border-radius: 50%;
 | 
			
		||||
      border-top: 2px solid $tao-warm-yellow-200;
 | 
			
		||||
      border: 2px solid;
 | 
			
		||||
      width: 15px;
 | 
			
		||||
      height: 15px;
 | 
			
		||||
      animation: spin 2s linear infinite;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
      <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>
 | 
			
		||||
    <div [innerHtml]="message.message"></div>
 | 
			
		||||
    <div class="tfw-grid-message-body" [innerHtml]="message.message"></div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div *ngIf="messageInQueue" class="tfw-grid-message jumping-circle-container">
 | 
			
		||||
      <div class="jumping-circle" id="jc1"></div>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
// All Rights Reserved. See LICENSE file for details.
 | 
			
		||||
 | 
			
		||||
@import "../../assets/scss/variables.scss";
 | 
			
		||||
@import "../../assets/scss/mixins/layout";
 | 
			
		||||
 | 
			
		||||
.tfw-next-button {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
@@ -84,3 +85,7 @@
 | 
			
		||||
    opacity: 0.37;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tfw-grid-message-body {
 | 
			
		||||
  @include word-break()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@
 | 
			
		||||
@import "../../app/dashboard/dashboard.component.scss";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
::ng-deep .xterm .xterm-viewport {
 | 
			
		||||
  overflow-y: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tfw-xterm {
 | 
			
		||||
  max-height: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/favicon.ico
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/images/favicon.ico
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 15 KiB  | 
@@ -1,79 +1,79 @@
 | 
			
		||||
// Copyright (C) 2018 Avatao.com Innovative Learning Kft.
 | 
			
		||||
// All Rights Reserved. See LICENSE file for details.
 | 
			
		||||
 | 
			
		||||
$grid-columns-count: 25;
 | 
			
		||||
$grid-rows-count: 25;
 | 
			
		||||
$grid-columns-count: 100;
 | 
			
		||||
$grid-rows-count: 30;
 | 
			
		||||
 | 
			
		||||
$terminal-ide-web-layout: (
 | 
			
		||||
  'header': (1, 6, 1, 2),
 | 
			
		||||
  'messages': (1, 6, 2, 16),
 | 
			
		||||
  'ide': (15,$grid-columns-count, 1, $grid-rows-count+1),
 | 
			
		||||
  'terminal': (1, 15, 16, $grid-rows-count+1),
 | 
			
		||||
  'web': (6, 15, 1, 16),
 | 
			
		||||
  'sidebar': ($grid-columns-count,$grid-columns-count+1, 1,$grid-rows-count+1)
 | 
			
		||||
  'header': (0, 20, 0, 4),
 | 
			
		||||
  'messages': (0, 20, 4, 60),
 | 
			
		||||
  'ide': (56, 96, 0, 100),
 | 
			
		||||
  'terminal': (0, 56, 60, 100),
 | 
			
		||||
  'web': (20, 56, 0, 60),
 | 
			
		||||
  'sidebar': (96, 100, 0, 100)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$terminal-web-layout: (
 | 
			
		||||
  'header': (1, 6, 1, 2),
 | 
			
		||||
  'messages': (1, 6, 2, $grid-columns-count+1),
 | 
			
		||||
  'header': (0, 20, 0, 4),
 | 
			
		||||
  'messages': (0, 20, 2, 100),
 | 
			
		||||
  'ide': (),
 | 
			
		||||
  'terminal': (15, $grid-columns-count, 1, $grid-rows-count+1),
 | 
			
		||||
  'web': (6, 15, 1, $grid-rows-count+1),
 | 
			
		||||
  'sidebar': ($grid-columns-count,$grid-columns-count+1, 1,$grid-rows-count+1)
 | 
			
		||||
  'terminal': (56, 96, 0, 100),
 | 
			
		||||
  'web': (20, 56, 0, 100),
 | 
			
		||||
  'sidebar': (96, 100, 0, 100)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$terminal-ide-vertical-layout: (
 | 
			
		||||
  'header': (1, 6, 1, 2),
 | 
			
		||||
  'messages': (1, 6, 2,$grid-rows-count+1),
 | 
			
		||||
  'ide': (15, $grid-columns-count, 1,$grid-rows-count+1),
 | 
			
		||||
  'terminal': (6, 15, 1, $grid-rows-count+1),
 | 
			
		||||
  'header': (0, 20, 0, 4),
 | 
			
		||||
  'messages': (0, 20, 2, 100),
 | 
			
		||||
  'ide': (56, 96, 0, 100),
 | 
			
		||||
  'terminal': (20, 56, 0, 100),
 | 
			
		||||
  'web': (),
 | 
			
		||||
  'sidebar': ($grid-columns-count,$grid-columns-count+1, 1,$grid-rows-count+1)
 | 
			
		||||
  'sidebar': (96, 100, 0, 100)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$terminal-ide-horizontal-layout: (
 | 
			
		||||
  'header': (1, 6, 1, 2),
 | 
			
		||||
  'messages': (1, 6, 2,$grid-rows-count+1),
 | 
			
		||||
  'ide': (6,$grid-columns-count, 1, 16),
 | 
			
		||||
  'terminal': (6, $grid-columns-count, 16, $grid-rows-count+1),
 | 
			
		||||
  'header': (0, 20, 0, 4),
 | 
			
		||||
  'messages': (0, 20, 2, 100),
 | 
			
		||||
  'ide': (20, 96, 0, 60),
 | 
			
		||||
  'terminal': (20, 96, 60, 100),
 | 
			
		||||
  'web': (),
 | 
			
		||||
  'sidebar': ($grid-columns-count,$grid-columns-count+1, 1,$grid-rows-count+1),
 | 
			
		||||
  'sidebar': (96, 100, 0, 100)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$ide-web-vertical-layout: (
 | 
			
		||||
  'header': (1, 6, 1, 2),
 | 
			
		||||
  'messages': (1, 6, 2, $grid-rows-count+1),
 | 
			
		||||
  'ide': (15, $grid-columns-count, 1,$grid-rows-count+1),
 | 
			
		||||
  'header': (0, 20, 0, 4),
 | 
			
		||||
  'messages': (0, 20, 4, 100),
 | 
			
		||||
  'ide': (56, 96, 0, 100),
 | 
			
		||||
  'terminal': (),
 | 
			
		||||
  'web': (6, 15, 1, $grid-rows-count+1),
 | 
			
		||||
  'sidebar': ($grid-columns-count,$grid-columns-count+1, 1,$grid-rows-count+1)
 | 
			
		||||
  'web': (20, 56, 0, 100),
 | 
			
		||||
  'sidebar': (96, 100, 0, 100)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$terminal-only-layout: (
 | 
			
		||||
  'header': (1, 6, 1, 2),
 | 
			
		||||
  'messages': (1, 6, 2,$grid-rows-count+1),
 | 
			
		||||
  'header': (0, 20, 0, 4),
 | 
			
		||||
  'messages': (0, 20, 4, 100),
 | 
			
		||||
  'ide': (),
 | 
			
		||||
  'terminal': (6, $grid-columns-count, 1,$grid-rows-count+1),
 | 
			
		||||
  'terminal': (20, 96, 0, 100),
 | 
			
		||||
  'web': (),
 | 
			
		||||
  'sidebar': ($grid-columns-count,$grid-columns-count+1, 1,$grid-rows-count+1)
 | 
			
		||||
  'sidebar': (96, 100, 0, 100)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$ide-only-layout: (
 | 
			
		||||
  'header': (1, 6, 1, 2),
 | 
			
		||||
  'messages': (1, 6, 2,$grid-rows-count+1),
 | 
			
		||||
  'ide': (6, $grid-columns-count,  1,$grid-rows-count+1),
 | 
			
		||||
  'header': (0, 20, 0, 4),
 | 
			
		||||
  'messages': (0, 20, 4, 100),
 | 
			
		||||
  'ide': (20, 96, 0, 100),
 | 
			
		||||
  'terminal': (),
 | 
			
		||||
  'web': (),
 | 
			
		||||
  'sidebar': ($grid-columns-count,$grid-columns-count+1, 1,$grid-rows-count+1)
 | 
			
		||||
  'sidebar': (96, 100, 0, 100)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$web-only-layout: (
 | 
			
		||||
  'header': (1, 6, 1, 2),
 | 
			
		||||
  'messages': (1, 6, 2,$grid-rows-count+1),
 | 
			
		||||
  'header': (0, 20, 0, 4),
 | 
			
		||||
  'messages': (0, 20, 4, 100),
 | 
			
		||||
  'ide': (),
 | 
			
		||||
  'terminal': (),
 | 
			
		||||
  'web': (6, $grid-columns-count, 1,$grid-rows-count+1),
 | 
			
		||||
  'sidebar': ($grid-columns-count,$grid-columns-count+1, 1,$grid-rows-count+1)
 | 
			
		||||
  'web': (20, 96, 0, 100),
 | 
			
		||||
  'sidebar': (96, 100, 0, 100)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$layouts: (
 | 
			
		||||
@@ -111,6 +111,10 @@ $layouts: (
 | 
			
		||||
  @return map_get($layouts, $layouts-key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@function convert-ratio($ratio, $max) {
 | 
			
		||||
  @return round(($ratio * $max) / 100) + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin position-grid-items($map, $sel) {
 | 
			
		||||
  $sel: if($sel == '' and &, &, $sel);
 | 
			
		||||
 | 
			
		||||
@@ -120,11 +124,18 @@ $layouts: (
 | 
			
		||||
        @include hide-component();
 | 
			
		||||
      }
 | 
			
		||||
      @else {
 | 
			
		||||
        grid-column-start: nth($v, 1);
 | 
			
		||||
        grid-column-end: nth($v, 2);
 | 
			
		||||
        grid-row-start: nth($v, 3);
 | 
			
		||||
        grid-row-end: nth($v, 4);
 | 
			
		||||
        grid-column-start: convert-ratio(nth($v, 1), $grid-columns-count);
 | 
			
		||||
        grid-column-end: convert-ratio(nth($v, 2), $grid-columns-count);
 | 
			
		||||
        grid-row-start: convert-ratio(nth($v, 3), $grid-rows-count);
 | 
			
		||||
        grid-row-end: convert-ratio(nth($v, 4), $grid-rows-count);
 | 
			
		||||
        max-width: calc(100vw / #{$grid-columns-count} * (#{convert-ratio(nth($v, 2), $grid-columns-count)} - #{convert-ratio(nth($v, 1), $grid-columns-count)}));
 | 
			
		||||
      }
 | 
			
		||||
      /* A hack for Chrome, without this there is a white 1px strip on the left of the terminal */
 | 
			
		||||
      /* You have been warned: don't try to understand this */
 | 
			
		||||
      @if($sel == 'terminal-ide-web' & & $k == 'terminal') {
 | 
			
		||||
        transform: translateX(-1px);
 | 
			
		||||
      }
 | 
			
		||||
      /* End of hack */
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -133,10 +144,18 @@ $layouts: (
 | 
			
		||||
  $tfw-component: map_get(get-layout($layouts-key), $layout-key);
 | 
			
		||||
 | 
			
		||||
  @if (length($tfw-component) > 0) {
 | 
			
		||||
    $columns-count: nth($tfw-component,2) - nth($tfw-component,1);
 | 
			
		||||
    $rows-count: nth($tfw-component,4) - nth($tfw-component,3);
 | 
			
		||||
    $columns-count: convert-ratio(nth($tfw-component,2), $grid-columns-count) - convert-ratio(nth($tfw-component,1), $grid-columns-count);
 | 
			
		||||
    $rows-count: convert-ratio(nth($tfw-component,4), $grid-columns-count) - convert-ratio(nth($tfw-component,3), $grid-columns-count);
 | 
			
		||||
 | 
			
		||||
    min-width: #{$columns-count / $grid-columns-count * 100}vw;
 | 
			
		||||
    min-height: #{$rows-count / $grid-rows-count * 100}vh;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin word-break() {
 | 
			
		||||
  /* For Firefox */
 | 
			
		||||
  white-space: pre-wrap;
 | 
			
		||||
  word-break: break-all;
 | 
			
		||||
  /* For Chrome and IE */
 | 
			
		||||
  word-wrap: break-word;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,36 @@
 | 
			
		||||
@mixin set-scrollbar-style() {
 | 
			
		||||
  ::-webkit-scrollbar-track
 | 
			
		||||
  {
 | 
			
		||||
    background-color: #F5F5F5;
 | 
			
		||||
@mixin set-scrollbar-style($style, $selctor) {
 | 
			
		||||
  ::-webkit-scrollbar {
 | 
			
		||||
    width: 3px !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ::-webkit-scrollbar
 | 
			
		||||
  {
 | 
			
		||||
    width: 4px;
 | 
			
		||||
    background-color: #F5F5F5;
 | 
			
		||||
  #{$selctor}::-webkit-scrollbar-track {
 | 
			
		||||
    border-radius: 10px !important;
 | 
			
		||||
    width: 3px !important;
 | 
			
		||||
    @if ($style == 'light') {
 | 
			
		||||
      background: #8a8a8a !important;
 | 
			
		||||
 | 
			
		||||
    } @else if ($style == 'dark') {
 | 
			
		||||
      background: white !important;
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ::-webkit-scrollbar-thumb
 | 
			
		||||
  {
 | 
			
		||||
    background-color: gray;
 | 
			
		||||
  #{$selctor}::-webkit-scrollbar-thumb {
 | 
			
		||||
    @if ($style == 'dark') {
 | 
			
		||||
      background: #8a8a8a !important;
 | 
			
		||||
 | 
			
		||||
    } @else if ($style == 'light') {
 | 
			
		||||
      background: white !important;
 | 
			
		||||
    };
 | 
			
		||||
    border-radius: 10px !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #{$selctor}::-webkit-scrollbar-thumb:hover {
 | 
			
		||||
    @if ($style == 'dark') {
 | 
			
		||||
      background: #424242 !important;
 | 
			
		||||
 | 
			
		||||
    } @else if ($style == 'light') {
 | 
			
		||||
      background: #9d9d9d !important;
 | 
			
		||||
    };
 | 
			
		||||
    cursor: pointer !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,4 +8,5 @@ body, html {
 | 
			
		||||
  height: 100vh;
 | 
			
		||||
  width: 100vw;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  @include set-scrollbar-style('light', '');
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "../tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "paths": {
 | 
			
		||||
      "*": [
 | 
			
		||||
        "types/*"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "outDir": "../out-tsc/app",
 | 
			
		||||
    "baseUrl": "./",
 | 
			
		||||
    "module": "es2015",
 | 
			
		||||
    "types": []
 | 
			
		||||
    "module": "esNext",
 | 
			
		||||
    "types": [],
 | 
			
		||||
    "resolveJsonModule": true
 | 
			
		||||
  },
 | 
			
		||||
  "exclude": [
 | 
			
		||||
    "test.ts",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user