feat: onboarding polish, splash screen, controller nav, dev script
Onboarding flow: - Intro: improved layout and transitions - DID: better card styling and responsiveness - Path: added visual enhancements - Backup/Identity/Verify: streamlined markup - SplashScreen component added UI: - Controller navigation improvements (useControllerNav) - Style.css refinements Backend: - Runtime package fix Dev: - dev-start.sh improvements Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
82eeb915a3
commit
7f03e39f58
@ -7,7 +7,7 @@ use anyhow::{Context, Result};
|
|||||||
/// Per-container graceful shutdown timeout in seconds.
|
/// Per-container graceful shutdown timeout in seconds.
|
||||||
/// Bitcoin Core needs 600s to flush UTXO set, LND 330s for channel state,
|
/// Bitcoin Core needs 600s to flush UTXO set, LND 330s for channel state,
|
||||||
/// indexers 300s for index flush, databases 120s for WAL/transaction commit.
|
/// indexers 300s for index flush, databases 120s for WAL/transaction commit.
|
||||||
fn stop_timeout_secs(container_name: &str) -> &'static str {
|
pub fn stop_timeout_secs(container_name: &str) -> &'static str {
|
||||||
let id = container_name.strip_prefix("archy-").unwrap_or(container_name);
|
let id = container_name.strip_prefix("archy-").unwrap_or(container_name);
|
||||||
match id {
|
match id {
|
||||||
"bitcoin-knots" | "bitcoin-core" | "bitcoin" => "600",
|
"bitcoin-knots" | "bitcoin-core" | "bitcoin" => "600",
|
||||||
|
|||||||
@ -82,7 +82,7 @@ define(['./workbox-21a80088'], (function (workbox) { 'use strict';
|
|||||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||||
}, {
|
}, {
|
||||||
"url": "index.html",
|
"url": "index.html",
|
||||||
"revision": "0.ld9oh2eb91o"
|
"revision": "0.huo00jkc7v4"
|
||||||
}], {});
|
}], {});
|
||||||
workbox.cleanupOutdatedCaches();
|
workbox.cleanupOutdatedCaches();
|
||||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||||
|
|||||||
@ -277,6 +277,13 @@ if (!storedSeenIntro && isOnDashboard) {
|
|||||||
localStorage.setItem('neode_intro_seen', '1')
|
localStorage.setItem('neode_intro_seen', '1')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleEnterKey(e: KeyboardEvent) {
|
||||||
|
if (e.key === 'Enter' && showTapToStart.value && !tapStartTransitioning.value) {
|
||||||
|
e.preventDefault()
|
||||||
|
handleTapToStart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onIntroLogoHover() {
|
function onIntroLogoHover() {
|
||||||
introLogoHover.value = true
|
introLogoHover.value = true
|
||||||
if (!tapStartTransitioning.value) playKeyboardTypingSound()
|
if (!tapStartTransitioning.value) playKeyboardTypingSound()
|
||||||
@ -465,10 +472,13 @@ onMounted(() => {
|
|||||||
showSplash.value = false
|
showSplash.value = false
|
||||||
document.body.classList.add('splash-complete')
|
document.body.classList.add('splash-complete')
|
||||||
emit('complete')
|
emit('complete')
|
||||||
|
} else {
|
||||||
|
window.addEventListener('keydown', handleEnterKey)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('keydown', handleEnterKey)
|
||||||
if (introTypingTimeout) {
|
if (introTypingTimeout) {
|
||||||
clearTimeout(introTypingTimeout)
|
clearTimeout(introTypingTimeout)
|
||||||
introTypingTimeout = null
|
introTypingTimeout = null
|
||||||
|
|||||||
@ -115,7 +115,14 @@ function findNearestInDirection(
|
|||||||
|
|
||||||
scored.sort((a, b) => {
|
scored.sort((a, b) => {
|
||||||
if (b.overlap !== a.overlap) return b.overlap - a.overlap
|
if (b.overlap !== a.overlap) return b.overlap - a.overlap
|
||||||
return a.dist - b.dist
|
if (a.dist !== b.dist) return a.dist - b.dist
|
||||||
|
// Tiebreaker for up/down: prefer leftmost element in grid layouts
|
||||||
|
if (direction === 'up' || direction === 'down') {
|
||||||
|
const aLeft = a.el.getBoundingClientRect().left
|
||||||
|
const bLeft = b.el.getBoundingClientRect().left
|
||||||
|
return aLeft - bLeft
|
||||||
|
}
|
||||||
|
return 0
|
||||||
})
|
})
|
||||||
return scored[0]?.el ?? null
|
return scored[0]?.el ?? null
|
||||||
}
|
}
|
||||||
@ -149,7 +156,7 @@ export function useControllerNav(containerRef?: { value: HTMLElement | null }) {
|
|||||||
|
|
||||||
const target = e.target as HTMLElement
|
const target = e.target as HTMLElement
|
||||||
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
|
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
|
||||||
// Enter in text field: blur and move to next focusable element (e.g., submit button)
|
// Enter in text field: find next focusable — if it's a button, click it directly (submit)
|
||||||
if (e.key === 'Enter' && target.tagName === 'INPUT' && (target as HTMLInputElement).type !== 'submit') {
|
if (e.key === 'Enter' && target.tagName === 'INPUT' && (target as HTMLInputElement).type !== 'submit') {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const root = containerRef?.value ?? document
|
const root = containerRef?.value ?? document
|
||||||
@ -157,12 +164,24 @@ export function useControllerNav(containerRef?: { value: HTMLElement | null }) {
|
|||||||
const idx = all.indexOf(target as HTMLElement)
|
const idx = all.indexOf(target as HTMLElement)
|
||||||
const next = idx >= 0 ? all[idx + 1] : undefined
|
const next = idx >= 0 ? all[idx + 1] : undefined
|
||||||
if (next) {
|
if (next) {
|
||||||
next.focus()
|
if (next.tagName === 'BUTTON' || next.getAttribute('role') === 'button') {
|
||||||
next.scrollIntoView({ block: 'nearest', behavior: 'smooth' })
|
next.focus()
|
||||||
|
next.click()
|
||||||
|
} else {
|
||||||
|
next.focus()
|
||||||
|
next.scrollIntoView({ block: 'nearest', behavior: 'smooth' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (e.key !== 'Escape') return
|
// Up/Down arrows: exit field and navigate to element above/below
|
||||||
|
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
||||||
|
e.preventDefault()
|
||||||
|
;(target as HTMLElement).blur()
|
||||||
|
// Fall through to arrow key handling below
|
||||||
|
} else if (e.key !== 'Escape') {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const root = containerRef?.value ?? document
|
const root = containerRef?.value ?? document
|
||||||
|
|||||||
@ -46,11 +46,12 @@
|
|||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Controller / keyboard navigation - soft glow only (no box outline) */
|
/* Controller / keyboard navigation - orange border (Archipelago brand) */
|
||||||
*:focus-visible {
|
*:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0 0 16px rgba(120, 180, 255, 0.2), 0 0 32px rgba(100, 160, 255, 0.1);
|
border-color: rgba(251, 146, 60, 0.8) !important;
|
||||||
transition: box-shadow 0.2s ease;
|
box-shadow: 0 0 0 2px rgba(251, 146, 60, 0.7), 0 0 16px rgba(251, 146, 60, 0.25);
|
||||||
|
transition: box-shadow 0.2s ease, border-color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mobile touch targets — ensure tappable elements meet 44px minimum */
|
/* Mobile touch targets — ensure tappable elements meet 44px minimum */
|
||||||
@ -98,12 +99,12 @@ input[type="radio"]:active + * {
|
|||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Containers get subtle grow + inner glow when focused (gamepad selection) */
|
/* Containers get subtle grow + orange glow when focused (gamepad selection) */
|
||||||
[data-controller-container]:focus-visible {
|
[data-controller-container]:focus-visible {
|
||||||
transform: scale(1.02);
|
transform: scale(1.02);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 24px rgba(120, 180, 255, 0.15),
|
0 0 0 2px rgba(251, 146, 60, 0.7),
|
||||||
0 0 48px rgba(100, 160, 255, 0.08),
|
0 0 24px rgba(251, 146, 60, 0.2),
|
||||||
inset 0 0 24px rgba(255, 255, 255, 0.03);
|
inset 0 0 24px rgba(255, 255, 255, 0.03);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -978,8 +979,8 @@ input[type="radio"]:active + * {
|
|||||||
.sidebar-nav-item:focus-visible {
|
.sidebar-nav-item:focus-visible {
|
||||||
transform: scale(1.02) !important;
|
transform: scale(1.02) !important;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 24px rgba(120, 180, 255, 0.15),
|
0 0 0 2px rgba(251, 146, 60, 0.7),
|
||||||
0 0 48px rgba(100, 160, 255, 0.08),
|
0 0 24px rgba(251, 146, 60, 0.2),
|
||||||
inset 0 0 24px rgba(255, 255, 255, 0.03) !important;
|
inset 0 0 24px rgba(255, 255, 255, 0.03) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1302,7 +1303,7 @@ html:has(body.video-background-active)::before {
|
|||||||
background: rgba(255, 255, 255, 0.1);
|
background: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
.cloud-file-item:focus-visible {
|
.cloud-file-item:focus-visible {
|
||||||
box-shadow: 0 0 16px rgba(120, 180, 255, 0.2), 0 0 32px rgba(100, 160, 255, 0.1);
|
box-shadow: 0 0 0 2px rgba(251, 146, 60, 0.7), 0 0 16px rgba(251, 146, 60, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cloud-file-item-thumb {
|
.cloud-file-item-thumb {
|
||||||
@ -1480,7 +1481,7 @@ html:has(body.video-background-active)::before {
|
|||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
.cloud-grid-card:focus-visible {
|
.cloud-grid-card:focus-visible {
|
||||||
box-shadow: 0 0 16px rgba(120, 180, 255, 0.2), 0 0 32px rgba(100, 160, 255, 0.1);
|
box-shadow: 0 0 0 2px rgba(251, 146, 60, 0.7), 0 0 16px rgba(251, 146, 60, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cloud-grid-card-cover {
|
.cloud-grid-card-cover {
|
||||||
|
|||||||
@ -74,13 +74,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex gap-3 sm:gap-4 max-w-[600px] mx-auto flex-shrink-0 px-3 sm:px-4 pb-4 sm:pb-6">
|
<div class="flex justify-center max-w-[600px] mx-auto flex-shrink-0 px-3 sm:px-4 pb-4 sm:pb-6">
|
||||||
<button
|
|
||||||
@click="skipForNow"
|
|
||||||
class="path-action-button path-action-button--skip"
|
|
||||||
>
|
|
||||||
Skip
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
@click="proceed"
|
@click="proceed"
|
||||||
:disabled="!downloaded"
|
:disabled="!downloaded"
|
||||||
@ -149,8 +143,5 @@ function proceed() {
|
|||||||
router.push('/onboarding/verify').catch(() => {})
|
router.push('/onboarding/verify').catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
function skipForNow() {
|
|
||||||
router.push('/onboarding/verify').catch(() => {})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -98,15 +98,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex gap-4 max-w-[600px] mx-auto flex-shrink-0">
|
<div class="flex justify-center max-w-[600px] mx-auto flex-shrink-0">
|
||||||
<button
|
|
||||||
@click="skipForNow"
|
|
||||||
class="path-action-button path-action-button--skip"
|
|
||||||
>
|
|
||||||
Skip
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
v-if="generatedDid"
|
v-if="generatedDid"
|
||||||
|
ref="continueButton"
|
||||||
@click="proceed"
|
@click="proceed"
|
||||||
class="path-action-button path-action-button--continue"
|
class="path-action-button path-action-button--continue"
|
||||||
>
|
>
|
||||||
@ -118,11 +113,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onUnmounted } from 'vue'
|
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { rpcClient } from '@/api/rpc-client'
|
import { rpcClient } from '@/api/rpc-client'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const continueButton = ref<HTMLButtonElement | null>(null)
|
||||||
const generatedDid = ref<string>('')
|
const generatedDid = ref<string>('')
|
||||||
const nostrNpub = ref<string>('')
|
const nostrNpub = ref<string>('')
|
||||||
const isGenerating = ref(false)
|
const isGenerating = ref(false)
|
||||||
@ -185,6 +181,16 @@ async function fetchDid() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(generatedDid, (did) => {
|
||||||
|
if (did) {
|
||||||
|
nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
continueButton.value?.focus({ preventScroll: true })
|
||||||
|
}, 100)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const cached = localStorage.getItem('neode_did')
|
const cached = localStorage.getItem('neode_did')
|
||||||
const cachedNpub = localStorage.getItem('neode_nostr_npub')
|
const cachedNpub = localStorage.getItem('neode_nostr_npub')
|
||||||
@ -205,11 +211,6 @@ function proceed() {
|
|||||||
router.push('/onboarding/identity').catch(() => {})
|
router.push('/onboarding/identity').catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
function skipForNow() {
|
|
||||||
stopTimers()
|
|
||||||
router.push('/onboarding/identity').catch(() => {})
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyDid() {
|
function copyDid() {
|
||||||
if (!generatedDid.value) return
|
if (!generatedDid.value) return
|
||||||
navigator.clipboard.writeText(generatedDid.value).catch(() => {})
|
navigator.clipboard.writeText(generatedDid.value).catch(() => {})
|
||||||
|
|||||||
@ -60,13 +60,7 @@
|
|||||||
<p v-else-if="errorMessage" class="text-red-400 text-sm text-center mb-4">{{ errorMessage }}</p>
|
<p v-else-if="errorMessage" class="text-red-400 text-sm text-center mb-4">{{ errorMessage }}</p>
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex gap-3 sm:gap-4 max-w-[600px] mx-auto flex-shrink-0 px-3 sm:px-4 pb-4 sm:pb-6">
|
<div class="flex justify-center max-w-[600px] mx-auto flex-shrink-0 px-3 sm:px-4 pb-4 sm:pb-6">
|
||||||
<button
|
|
||||||
@click="skip"
|
|
||||||
class="path-action-button path-action-button--skip"
|
|
||||||
>
|
|
||||||
Skip
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
@click="createIdentity"
|
@click="createIdentity"
|
||||||
:disabled="isCreating"
|
:disabled="isCreating"
|
||||||
@ -127,7 +121,4 @@ async function createIdentity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function skip() {
|
|
||||||
router.push('/onboarding/backup').catch(() => {})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
ref="ctaButton"
|
||||||
@click="goToOptions"
|
@click="goToOptions"
|
||||||
class="glass-button px-6 py-3 sm:px-8 sm:py-4 rounded-lg text-base sm:text-lg font-medium transition-all hover:bg-black/70 hover:border-white/30 onb-cta"
|
class="glass-button px-6 py-3 sm:px-8 sm:py-4 rounded-lg text-base sm:text-lg font-medium transition-all hover:bg-black/70 hover:border-white/30 onb-cta"
|
||||||
>
|
>
|
||||||
@ -65,12 +66,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import AnimatedLogo from '@/components/AnimatedLogo.vue'
|
import AnimatedLogo from '@/components/AnimatedLogo.vue'
|
||||||
import { rpcClient } from '@/api/rpc-client'
|
import { rpcClient } from '@/api/rpc-client'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const ctaButton = ref<HTMLButtonElement | null>(null)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// Auto-focus after entry animation completes (1.4s animation delay + 0.6s duration)
|
||||||
|
setTimeout(() => {
|
||||||
|
ctaButton.value?.focus({ preventScroll: true })
|
||||||
|
}, 2100)
|
||||||
|
})
|
||||||
|
|
||||||
function goToOptions() {
|
function goToOptions() {
|
||||||
router.push('/onboarding/path').catch(() => {})
|
router.push('/onboarding/path').catch(() => {})
|
||||||
|
|||||||
@ -82,6 +82,7 @@
|
|||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex justify-center max-w-[600px] mx-auto flex-shrink-0 px-3 sm:px-4 pb-4 sm:pb-6">
|
<div class="flex justify-center max-w-[600px] mx-auto flex-shrink-0 px-3 sm:px-4 pb-4 sm:pb-6">
|
||||||
<button
|
<button
|
||||||
|
ref="continueButton"
|
||||||
@click="proceed"
|
@click="proceed"
|
||||||
class="path-action-button path-action-button--continue"
|
class="path-action-button path-action-button--continue"
|
||||||
>
|
>
|
||||||
@ -93,9 +94,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const continueButton = ref<HTMLButtonElement | null>(null)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
continueButton.value?.focus({ preventScroll: true })
|
||||||
|
}, 400)
|
||||||
|
})
|
||||||
|
|
||||||
function proceed() {
|
function proceed() {
|
||||||
router.push('/onboarding/did').catch(() => {})
|
router.push('/onboarding/did').catch(() => {})
|
||||||
|
|||||||
@ -63,13 +63,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex gap-3 sm:gap-4 max-w-[600px] mx-auto flex-shrink-0 px-3 sm:px-4 pb-4 sm:pb-6">
|
<div class="flex justify-center max-w-[600px] mx-auto flex-shrink-0 px-3 sm:px-4 pb-4 sm:pb-6">
|
||||||
<button
|
|
||||||
@click="skipForNow"
|
|
||||||
class="path-action-button path-action-button--skip"
|
|
||||||
>
|
|
||||||
Skip
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
v-if="verified"
|
v-if="verified"
|
||||||
@click="proceed"
|
@click="proceed"
|
||||||
@ -152,13 +146,5 @@ async function proceed() {
|
|||||||
router.push('/onboarding/done').catch(() => {})
|
router.push('/onboarding/done').catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function skipForNow() {
|
|
||||||
try {
|
|
||||||
await completeOnboarding()
|
|
||||||
} catch {
|
|
||||||
/* localStorage fallback ensures we can proceed */
|
|
||||||
}
|
|
||||||
router.push('/onboarding/done').catch(() => {})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -48,8 +48,9 @@ echo " 5) Existing user (login screen — mock)"
|
|||||||
echo " 6) Boot mode (simulated 25s startup — mock)"
|
echo " 6) Boot mode (simulated 25s startup — mock)"
|
||||||
echo " 7) Testnet stack (signet Bitcoin + LND + ThunderHub via Podman)"
|
echo " 7) Testnet stack (signet Bitcoin + LND + ThunderHub via Podman)"
|
||||||
echo " 8) Manual instructions"
|
echo " 8) Manual instructions"
|
||||||
|
echo " 9) Container orchestration dev (live testing on .228)"
|
||||||
echo ""
|
echo ""
|
||||||
read -p "Enter choice [0-8]: " choice
|
read -p "Enter choice [0-9]: " choice
|
||||||
|
|
||||||
case $choice in
|
case $choice in
|
||||||
0)
|
0)
|
||||||
@ -278,6 +279,13 @@ case $choice in
|
|||||||
echo ""
|
echo ""
|
||||||
echo "Access: http://localhost:8100 (password: password123)"
|
echo "Access: http://localhost:8100 (password: password123)"
|
||||||
;;
|
;;
|
||||||
|
9)
|
||||||
|
echo ""
|
||||||
|
echo "Container Orchestration Dev (live testing on .228)"
|
||||||
|
echo "Syncs code, builds on server, runs orchestration smoke tests."
|
||||||
|
echo ""
|
||||||
|
exec "$SCRIPT_DIR/dev-container-test.sh"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Invalid choice"
|
echo "Invalid choice"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user