Better design and lots of little fixes all over.

master
Zed A. Shaw 4 years ago
parent 1d3e9cefb7
commit c0456f84c3
  1. 8
      sass/_variables.scss
  2. 9
      src/components/Footer.svelte
  3. 48
      src/components/Nav.svelte
  4. 8
      src/components/Sidebar.svelte
  5. 9
      src/node_modules/buttons.js
  6. 24
      src/routes/_layout.svelte
  7. 122
      src/routes/index.svelte
  8. 10
      src/service-worker.js
  9. 2
      static/css/spectre-exp.min.css
  10. 2
      static/css/spectre.min.css

@ -37,9 +37,9 @@ $bg-color-dark: darken($bg-color, 10%) !default;
$bg-color-light: lighten($bg-color, 10%) !default; $bg-color-light: lighten($bg-color, 10%) !default;
// Control colors // Control colors
$success-color: #32b643 !default; $success-color: $green !default;
$warning-color: $green !default; $warning-color: $yellow !default;
$error-color: #e85600 !default; $error-color: $red !default;
// Other colors // Other colors
$code-color: $green !default; $code-color: $green !default;
@ -74,7 +74,7 @@ $unit-12: 2.4rem !default;
$unit-16: 3.2rem !default; $unit-16: 3.2rem !default;
// Font sizes // Font sizes
$html-font-size: 25px !default; $html-font-size: 16px !default;
$html-line-height: 1.5 !default; $html-line-height: 1.5 !default;
$font-size: 1rem !default; $font-size: 1rem !default;
$font-size-sm: .9rem !default; $font-size-sm: .9rem !default;

@ -7,7 +7,7 @@
#footer { #footer {
border-top: 1px solid $primary-color; border-top: 1px solid $primary-color;
background-color: $gray-color-light; background-color: $gray-color;
} }
#right-column { #right-column {
@ -17,7 +17,8 @@
#footer .panel { #footer .panel {
border: 0px; border: 0px;
border-radius: 0px; border-radius: 0px;
font-size: $font-size-sm; font-size: 20px !important;
text-shadow: 2px 2px $gray-color-dark;
} }
</style> </style>
@ -33,7 +34,7 @@
</div> </div>
<div class="column col-3" id="right-column"> <div class="column col-3" id="right-column">
<a alt="Twitter @lzsthw" aria-label="Twitter @lzsthw" rel="external" href="https://twitter.com/lzsthw"><Icon size="48" name="twitter" /></a> <a alt="Twitter @lzsthw" aria-label="Twitter @lzsthw" rel="external" href="https://twitter.com/lzsthw"><Icon size="48" name="twitter" light={true} /></a>
<a alt="The git repository" aria-label="The git repository" rel="external" href="https://git.learnjsthehardway.com/zedshaw/buttons-computer"><Icon size="48" name="code" /></a> <a alt="The git repository" aria-label="The git repository" rel="external" href="https://git.learnjsthehardway.com/zedshaw/buttons-computer"><Icon size="48" name="code" light={true} /></a>
</div> </div>
</div> </div>

@ -0,0 +1,48 @@
<script>
export let segment;
import { goto } from '@sapper/app';
import Icon from './Icon.svelte';
</script>
<style lang="scss">
@import "sass/_variables";
#logo {
font-size: 24px;
text-shadow: 2px 2px $gray-color-dark;
}
.menu-item .active {
background-color: $red;
}
.btn {
background-color: $red !important;
margin-left: 4px;
border: 1px solid $black;
height: 40px;
}
.navbar {
background-color: $gray-color;
min-height: 50px;
}
</style>
<header class="navbar">
<section class="navbar-section">
<a class="navbar-brand mr-2" href="/">
<div id="logo">BUTTONS</div>
</a>
</section>
<section class="navbar-section">
<a data-testid='nav-home-icon' rel="prefetch" class:btn-link="{ segment != undefined }" class="btn" href="/" alt="Home" aria-label="Home">
<Icon name="home" size="32" tooltip="Home" tooltip_bottom={true} light={true}/>
</a>
<a data-testid='nav-blog-icon' rel="external" class:btn-link="{ segment != 'blog' }" class="btn" href="https://learnjsthehardway.com/blog" alt="Read the blog" aria-label="Read the blog">
<Icon name="book-open" size="32" tooltip="Blog" tooltip_bottom={true} light={true} />
</a>
</section>
</header>

@ -1,7 +1,8 @@
<script> <script>
import { ButtonMachine } from 'buttons'; import { ButtonMachine } from 'buttons';
let ops = ButtonMachine.operations(); const ops = ButtonMachine.operations();
const registers = ButtonMachine.register_names();
</script> </script>
@ -16,5 +17,10 @@ OPERATIONS:
{#each ops as op} {#each ops as op}
{ op + '\n'} { op + '\n'}
{/each} {/each}
REGISTERS:
{#each registers as reg}
{ reg + '\n'}
{/each}
</code> </code>
</pre> </pre>

9
src/node_modules/buttons.js generated vendored

@ -27,6 +27,11 @@ class ButtonMachine {
return test; return test;
} }
/* Need to use a function because @babel/plugin-proposal-class-properties */
static register_names() {
return ['AX', 'BX', 'CX', 'DX'];
}
static operations() { static operations() {
return Object.getOwnPropertyNames(ButtonMachine.prototype) return Object.getOwnPropertyNames(ButtonMachine.prototype)
.filter(x => x.startsWith('op_')) .filter(x => x.startsWith('op_'))
@ -137,11 +142,15 @@ class ButtonMachine {
} }
op_STOR(reg) { op_STOR(reg) {
if(!this.assert(!reg.includes(reg), `Register ${reg} is not valid. Use ${ButtonMachine.registers_names()}`)) return;
this.registers[reg] = this.stack_top; this.registers[reg] = this.stack_top;
this.next(); this.next();
} }
op_RSTOR(reg) { op_RSTOR(reg) {
if(!this.assert(!reg.includes(reg), `Register ${reg} is not valid. Use ${ButtonMachine.registers_names()}`)) return;
let val = this.registers[reg]; let val = this.registers[reg];
this.assert(val !== undefined, `Invalid register ${reg}`); this.assert(val !== undefined, `Invalid register ${reg}`);

@ -1,10 +1,15 @@
<script> <script>
import Footer from '../components/Footer.svelte'; import Footer from '../components/Footer.svelte';
import Nav from '../components/Nav.svelte';
import Sidebar from '../components/Sidebar.svelte'; import Sidebar from '../components/Sidebar.svelte';
export let segment;
</script> </script>
<style> <style lang="scss">
#main {
@import "sass/_variables";
#main {
display: flex; display: flex;
flex: 1 0 auto; flex: 1 0 auto;
min-height: 100vh; min-height: 100vh;
@ -12,16 +17,18 @@
padding-left: 0px; padding-left: 0px;
padding-right: 0px; padding-right: 0px;
min-width: 340px; min-width: 340px;
} border: 1px solid darken($green, 10%) !important;
}
#main_content { #main_content {
flex-grow: 1; flex-grow: 1;
} }
</style> </style>
<div class="container grid-xl full-width" id="main"> <div class="container grid-lg" id="main">
<div class="columns" id="nav"> <div class="columns" id="nav">
<div class="column col-mx-auto"> <div class="column col-mx-auto">
<Nav {segment} />
</div> </div>
</div> </div>
@ -29,15 +36,12 @@
<div class="columns"> <div class="columns">
<div class="column col-mx-auto"> <div class="column col-mx-auto">
<div class="off-canvas"> <div class="off-canvas">
<a class="off-canvas-toggle btn btn-primary btn-action" href="#sidebar-id">
?¿
</a>
<div id="sidebar-id" class="off-canvas-sidebar"> <div id="sidebar-id" class="off-canvas-sidebar">
<Sidebar /> <Sidebar />
</div> </div>
<a class="off-canvas-overlay" href="#close"></a> <a alt="Close sidebar" aria-label="Close sidebar" class="off-canvas-overlay" href="#close">&nbsp;</a>
<div class="off-canvas-content"> <div class="off-canvas-content">
<slot></slot> <slot></slot>

@ -65,44 +65,38 @@
<style lang="scss"> <style lang="scss">
@import "sass/_variables"; @import "sass/_variables";
#status-panel {
font-size: 14px;
}
.active-line { .active-line {
background-color: $warning-color !important; background-color: $green !important;
} }
.empty-data { .empty-data {
width: 100%; width: 100%;
background-color: lighten($primary-color, 40%); background-color: lighten($primary-color, 40%);
} }
.off-canvas-toggle {
position: unset;
z-index: unset;
top: unset;
left: unset;
display: unset;
transition: unset;
padding: 5px;
}
</style> </style>
<div class="container grid-xl" id="content" data-testid="buttons-page"> <div class="container grid-lg" id="content" data-testid="buttons-page">
<div class="columns"> <div class="columns">
<div class="column col-12">
<table class="table">
<thead>
<tr>
<th>IP</th>
<th>TICK</th>
<th>HALT</th>
<th>ERROR</th>
</tr>
</thead>
<tbody>
<tr class="active">
<td>{ machine.ip }</td>
<td>{ machine.tick }</td>
<td>{ machine.halted }</td>
<td>{ machine.error }</td>
</tr>
</tbody>
</table>
</div>
</div>
<br/> <div class="column col-4 col-sm-12 col-md-12 col-xs-12">
<a alt="Open/Close help sidebar" aria-label="Open/Close help sidebar" class="off-canvas-toggle btn btn-primary btn-action" href="#sidebar-id">
?¿
</a>
<div class="columns">
<div class="column col-6">
<button class="btn btn-primary" on:click={ run_machine }> <button class="btn btn-primary" on:click={ run_machine }>
<Icon code="►" tooltip="Run it" tooltip_right={ true } light={ true }/> <Icon code="►" tooltip="Run it" tooltip_right={ true } light={ true }/>
</button> </button>
@ -113,19 +107,19 @@
<Icon code="■" tooltip="Reset" light={ true }/> <Icon code="■" tooltip="Reset" light={ true }/>
</button> </button>
<div class="divider"></div> <div class="divider"></div>
{#each code as [op, data], i} {#each code as [op, data], i}
<div class="input-group" class:has-error={ has_error }> <div class="input-group">
{#if has_error && machine.error_line == i} {#if has_error && machine.error_line == i}
<Icon name="alert-triangle" color="red" /> <Icon name="alert-triangle" color="red" />
{:else} {:else}
{i}: {i}:
{/if} {/if}
<button class:active-line={ machine.ip == i } <button class:active-line={ machine.ip == i }
on:click={ () => change_op(i, +1) } on:click={ () => change_op(i, +1) }
on:contextmenu|preventDefault={ () => change_op(i, -1) } on:contextmenu|preventDefault={ () => change_op(i, -1) }
class="btn btn-primary input-group-btn">{op}</button> class="btn btn-primary input-group-btn">{op}</button>
{#if op_has_data(op)} {#if op_has_data(op)}
{#if op === 'STOR' || op === 'RSTOR' || op == 'HALT'} {#if op === 'STOR' || op === 'RSTOR' || op == 'HALT'}
@ -150,12 +144,31 @@
</div> </div>
{/each} {/each}
</div> </div>
<div class="column col-2">
<div class="column col-8 col-sm-12 col-md-12 col-xs-12" id="status-panel">
<table class="table">
<thead>
<tr>
<th>IP</th>
<th>TICK</th>
<th>HALT</th>
<th>ERROR</th>
</tr>
</thead>
<tbody>
<tr class="active">
<td>{ machine.ip }</td>
<td>{ machine.tick }</td>
<td>{ machine.halted }</td>
<td>{ machine.error }</td>
</tr>
</tbody>
</table>
<table class="table"> <thead> <table class="table"> <thead>
<tr> <tr>
<th>STACK</th> <th>STACK</th>
</tr> </tr>
</thead> </thead>
{#each machine.stack as datum, i} {#each machine.stack as datum, i}
<tr> <tr>
@ -163,24 +176,23 @@
</tr> </tr>
{/each} {/each}
</table> </table>
</div>
<div class="column col-4"> <table class="table">
<table class="table"> <thead>
<thead> <tr>
<tr> <th>REGISTER</th>
<th>REGISTER</th> <th>VALUE</th>
<th>VALUE</th> </tr>
</tr> </thead>
</thead> <tbody>
<tbody> {#each machine.register_entries as [name, value] }
{#each machine.register_entries as [name, value] } <tr class="active">
<tr class="active"> <td>{ name }</td>
<td>{ name }</td> <td>{ value }</td>
<td>{ value }</td> </tr>
</tr> {/each}
{/each} </tbody>
</tbody> </table>
</table>
</div> </div>
</div> </div>
</div> </div>

@ -7,6 +7,8 @@ const ASSETS = `cache${timestamp}`;
const to_cache = shell.concat(files); const to_cache = shell.concat(files);
const cached = new Set(to_cache); const cached = new Set(to_cache);
self.skipWaiting();
self.addEventListener('install', event => { self.addEventListener('install', event => {
event.waitUntil( event.waitUntil(
caches caches
@ -31,6 +33,8 @@ self.addEventListener('activate', event => {
); );
}); });
if(false) {
self.addEventListener('fetch', event => { self.addEventListener('fetch', event => {
if (event.request.method !== 'GET' || event.request.headers.has('range')) return; if (event.request.method !== 'GET' || event.request.headers.has('range')) return;
@ -51,12 +55,10 @@ self.addEventListener('fetch', event => {
// for pages, you might want to serve a shell `service-worker-index.html` file, // for pages, you might want to serve a shell `service-worker-index.html` file,
// which Sapper has generated for you. It's not right for every // which Sapper has generated for you. It's not right for every
// app, but if it's right for yours then uncomment this section // app, but if it's right for yours then uncomment this section
/*
if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) {
event.respondWith(caches.match('/service-worker-index.html')); event.respondWith(caches.match('/service-worker-index.html'));
return; return;
} }
*/
if (event.request.cache === 'only-if-cached') return; if (event.request.cache === 'only-if-cached') return;
@ -69,7 +71,7 @@ self.addEventListener('fetch', event => {
.then(async cache => { .then(async cache => {
try { try {
const response = await fetch(event.request, {credentials: 'same-origin'}); const response = await fetch(event.request, {credentials: 'same-origin'});
// cache.put(event.request, response.clone()); cache.put(event.request, response.clone());
return response; return response;
} catch(err) { } catch(err) {
const response = await cache.match(event.request); const response = await cache.match(event.request);
@ -80,3 +82,5 @@ self.addEventListener('fetch', event => {
}) })
); );
}); });
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save