Rename First Time Wizard to Setup Assistant

This commit does not introduce functional changes, besides renaming
every mention of 'wizard' with 'setup assistant'. In order to run the
manager setup assistant use:

./flamenco-manager -setup-assistant

The change was introduced to favor more neutral and descriptive working
for this functionality. Thanks to Sybren for helping to get this done!
This commit is contained in:
Francesco Siddi 2022-07-25 16:15:08 +02:00 committed by Sybren A. Stüvel
parent a2bd8a5615
commit 9948fdab71
11 changed files with 54 additions and 54 deletions

@ -54,11 +54,11 @@ import (
) )
var cliArgs struct { var cliArgs struct {
version bool version bool
writeConfig bool writeConfig bool
delayResponses bool delayResponses bool
firstTimeWizard bool setupAssistant bool
pprof bool pprof bool
} }
const ( const (
@ -86,9 +86,9 @@ func main() {
for startFlamenco { for startFlamenco {
startFlamenco = runFlamencoManager() startFlamenco = runFlamencoManager()
// After the first run, the first-time wizard should not be forced any more. // After the first run, the setup assistant should not be forced any more.
// If the configuration is still incomplete it can still auto-trigger. // If the configuration is still incomplete it can still auto-trigger.
cliArgs.firstTimeWizard = false cliArgs.setupAssistant = false
if startFlamenco { if startFlamenco {
log.Info(). log.Info().
@ -113,7 +113,7 @@ func runFlamencoManager() bool {
log.Error().Err(err).Msg("loading configuration") log.Error().Err(err).Msg("loading configuration")
} }
if cliArgs.firstTimeWizard { if cliArgs.setupAssistant {
configService.ForceFirstRun() configService.ForceFirstRun()
} }
isFirstRun, err := configService.IsFirstRun() isFirstRun, err := configService.IsFirstRun()
@ -513,7 +513,7 @@ func parseCliArgs() {
flag.BoolVar(&cliArgs.writeConfig, "write-config", false, "Writes configuration to flamenco-manager.yaml, then exits.") flag.BoolVar(&cliArgs.writeConfig, "write-config", false, "Writes configuration to flamenco-manager.yaml, then exits.")
flag.BoolVar(&cliArgs.delayResponses, "delay", false, flag.BoolVar(&cliArgs.delayResponses, "delay", false,
"Add a random delay to any HTTP responses. This aids in development of Flamenco Manager's web frontend.") "Add a random delay to any HTTP responses. This aids in development of Flamenco Manager's web frontend.")
flag.BoolVar(&cliArgs.firstTimeWizard, "wizard", false, "Open a webbrowser with the first-time configuration wizard.") flag.BoolVar(&cliArgs.setupAssistant, "setup-assistant", false, "Open a webbrowser with the setup assistant.")
flag.BoolVar(&cliArgs.pprof, "pprof", false, "Expose profiler endpoints on /debug/pprof/.") flag.BoolVar(&cliArgs.pprof, "pprof", false, "Expose profiler endpoints on /debug/pprof/.")
flag.Parse() flag.Parse()

@ -166,7 +166,7 @@ type ConfigService interface {
IsFirstRun() (bool, error) IsFirstRun() (bool, error)
// ForceFirstRun forces IsFirstRun() to return true. This is used to force the // ForceFirstRun forces IsFirstRun() to return true. This is used to force the
// first-time wizard on a configured system. // setup assistant on a configured system.
ForceFirstRun() ForceFirstRun()
// Save writes the in-memory configuration to the config file. // Save writes the in-memory configuration to the config file.

@ -233,29 +233,29 @@ func (f *Flamenco) CheckBlenderExePath(e echo.Context) error {
return e.JSON(http.StatusOK, response) return e.JSON(http.StatusOK, response)
} }
func (f *Flamenco) SaveWizardConfig(e echo.Context) error { func (f *Flamenco) SaveSetupAssistantConfig(e echo.Context) error {
logger := requestLogger(e) logger := requestLogger(e)
var wizardCfg api.WizardConfig var setupAssistantCfg api.SetupAssistantConfig
if err := e.Bind(&wizardCfg); err != nil { if err := e.Bind(&setupAssistantCfg); err != nil {
logger.Warn().Err(err).Msg("first-time wizard: bad request received") logger.Warn().Err(err).Msg("setup assistant: bad request received")
return sendAPIError(e, http.StatusBadRequest, "invalid format") return sendAPIError(e, http.StatusBadRequest, "invalid format")
} }
logger = logger.With().Interface("config", wizardCfg).Logger() logger = logger.With().Interface("config", setupAssistantCfg).Logger()
if wizardCfg.StorageLocation == "" || if setupAssistantCfg.StorageLocation == "" ||
!wizardCfg.BlenderExecutable.IsUsable || !setupAssistantCfg.BlenderExecutable.IsUsable ||
wizardCfg.BlenderExecutable.Path == "" { setupAssistantCfg.BlenderExecutable.Path == "" {
logger.Warn().Msg("first-time wizard: configuration is incomplete, unable to accept") logger.Warn().Msg("setup assistant: configuration is incomplete, unable to accept")
return sendAPIError(e, http.StatusBadRequest, "configuration is incomplete") return sendAPIError(e, http.StatusBadRequest, "configuration is incomplete")
} }
conf := f.config.Get() conf := f.config.Get()
conf.SharedStoragePath = wizardCfg.StorageLocation conf.SharedStoragePath = setupAssistantCfg.StorageLocation
var executable string var executable string
switch wizardCfg.BlenderExecutable.Source { switch setupAssistantCfg.BlenderExecutable.Source {
case api.BlenderPathSourceFileAssociation: case api.BlenderPathSourceFileAssociation:
// The Worker will try to use the file association when the command is set // The Worker will try to use the file association when the command is set
// to the string "blender". // to the string "blender".
@ -263,10 +263,10 @@ func (f *Flamenco) SaveWizardConfig(e echo.Context) error {
case api.BlenderPathSourcePathEnvvar: case api.BlenderPathSourcePathEnvvar:
// The input command can be found on $PATH, and thus we don't need to save // The input command can be found on $PATH, and thus we don't need to save
// the absolute path to Blender here. // the absolute path to Blender here.
executable = wizardCfg.BlenderExecutable.Input executable = setupAssistantCfg.BlenderExecutable.Input
case api.BlenderPathSourceInputPath: case api.BlenderPathSourceInputPath:
// The path should be used as-is. // The path should be used as-is.
executable = wizardCfg.BlenderExecutable.Path executable = setupAssistantCfg.BlenderExecutable.Path
} }
if commandNeedsQuoting(executable) { if commandNeedsQuoting(executable) {
executable = strconv.Quote(executable) executable = strconv.Quote(executable)
@ -287,10 +287,10 @@ func (f *Flamenco) SaveWizardConfig(e echo.Context) error {
// Save the final configuration to disk. // Save the final configuration to disk.
if err := f.config.Save(); err != nil { if err := f.config.Save(); err != nil {
logger.Error().Err(err).Msg("error saving configuration file") logger.Error().Err(err).Msg("error saving configuration file")
return sendAPIError(e, http.StatusInternalServerError, "first-time wizard: error saving configuration file: %v", err) return sendAPIError(e, http.StatusInternalServerError, "setup assistant: error saving configuration file: %v", err)
} }
logger.Info().Msg("first-time wizard: updating configuration") logger.Info().Msg("setup assistant: updating configuration")
// Request the shutdown in a goroutine, so that this one can continue sending the response. // Request the shutdown in a goroutine, so that this one can continue sending the response.
go f.requestShutdown() go f.requestShutdown()

@ -122,11 +122,11 @@ func TestCheckSharedStoragePath(t *testing.T) {
} }
} }
func TestSaveWizardConfig(t *testing.T) { func TestSaveSetupAssistantConfig(t *testing.T) {
mf, finish := metaTestFixtures(t) mf, finish := metaTestFixtures(t)
defer finish() defer finish()
doTest := func(body api.WizardConfig) config.Conf { doTest := func(body api.SetupAssistantConfig) config.Conf {
// Always start the test with a clean configuration. // Always start the test with a clean configuration.
originalConfig := config.DefaultConfig(func(c *config.Conf) { originalConfig := config.DefaultConfig(func(c *config.Conf) {
c.SharedStoragePath = "" c.SharedStoragePath = ""
@ -142,7 +142,7 @@ func TestSaveWizardConfig(t *testing.T) {
// Call the API. // Call the API.
echoCtx := mf.prepareMockedJSONRequest(body) echoCtx := mf.prepareMockedJSONRequest(body)
err := mf.flamenco.SaveWizardConfig(echoCtx) err := mf.flamenco.SaveSetupAssistantConfig(echoCtx)
if !assert.NoError(t, err) { if !assert.NoError(t, err) {
t.FailNow() t.FailNow()
} }
@ -153,7 +153,7 @@ func TestSaveWizardConfig(t *testing.T) {
// Test situation where file association with .blend files resulted in a blender executable. // Test situation where file association with .blend files resulted in a blender executable.
{ {
savedConfig := doTest(api.WizardConfig{ savedConfig := doTest(api.SetupAssistantConfig{
StorageLocation: mf.tempdir, StorageLocation: mf.tempdir,
BlenderExecutable: api.BlenderPathCheckResult{ BlenderExecutable: api.BlenderPathCheckResult{
IsUsable: true, IsUsable: true,
@ -175,7 +175,7 @@ func TestSaveWizardConfig(t *testing.T) {
// Test situation where the given command could be found on $PATH. // Test situation where the given command could be found on $PATH.
{ {
savedConfig := doTest(api.WizardConfig{ savedConfig := doTest(api.SetupAssistantConfig{
StorageLocation: mf.tempdir, StorageLocation: mf.tempdir,
BlenderExecutable: api.BlenderPathCheckResult{ BlenderExecutable: api.BlenderPathCheckResult{
IsUsable: true, IsUsable: true,
@ -197,7 +197,7 @@ func TestSaveWizardConfig(t *testing.T) {
// Test a custom command given with the full path. // Test a custom command given with the full path.
{ {
savedConfig := doTest(api.WizardConfig{ savedConfig := doTest(api.SetupAssistantConfig{
StorageLocation: mf.tempdir, StorageLocation: mf.tempdir,
BlenderExecutable: api.BlenderPathCheckResult{ BlenderExecutable: api.BlenderPathCheckResult{
IsUsable: true, IsUsable: true,

@ -22,7 +22,7 @@ var defaultConfig = Conf{
DatabaseDSN: "flamenco-manager.sqlite", DatabaseDSN: "flamenco-manager.sqlite",
SSDPDiscovery: true, SSDPDiscovery: true,
LocalManagerStoragePath: "./flamenco-manager-storage", LocalManagerStoragePath: "./flamenco-manager-storage",
SharedStoragePath: "", // Empty string means "first run", and should trigger the config wizard. SharedStoragePath: "", // Empty string means "first run", and should trigger the config setup assistant.
Shaman: shaman_config.Config{ Shaman: shaman_config.Config{
// Enable Shaman by default, except on Windows where symlinks are still tricky. // Enable Shaman by default, except on Windows where symlinks are still tricky.

@ -20,7 +20,7 @@ import { MetaApi } from "@/manager-api";
import { apiClient } from '@/stores/api-query-count'; import { apiClient } from '@/stores/api-query-count';
export default { export default {
name: 'FirstTimeWizard', name: 'SetupAssistant',
components: { components: {
ApiSpinner, ApiSpinner,
}, },

@ -3,10 +3,10 @@ import { createPinia } from 'pinia'
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import App from '@/App.vue' import App from '@/App.vue'
import FirstTimeWizard from '@/FirstTimeWizard.vue' import SetupAssistant from '@/SetupAssistant.vue'
import autoreload from '@/autoreloader' import autoreload from '@/autoreloader'
import router from '@/router/index' import router from '@/router/index'
import wizardRouter from '@/router/first-time-wizard' import setupAssistantRouter from '@/router/setup-assistant'
import { ApiClient, MetaApi } from "@/manager-api"; import { ApiClient, MetaApi } from "@/manager-api";
import * as urls from '@/urls' import * as urls from '@/urls'
@ -31,11 +31,11 @@ function normalMode() {
app.mount('#app') app.mount('#app')
} }
function firstTimeWizardMode() { function setupAssistantMode() {
console.log("Flamenco First Time Wizard is starting"); console.log("Flamenco Setup Assistant is starting");
const app = createApp(FirstTimeWizard) const app = createApp(SetupAssistant)
app.use(pinia) app.use(pinia)
app.use(wizardRouter) app.use(setupAssistantRouter)
app.mount('#app') app.mount('#app')
} }
@ -47,7 +47,7 @@ const metaAPI = new MetaApi(apiClient);
metaAPI.getConfiguration() metaAPI.getConfiguration()
.then((config) => { .then((config) => {
console.log("Got config!", config); console.log("Got config!", config);
if (config.isFirstRun) firstTimeWizardMode(); if (config.isFirstRun) setupAssistantMode();
else normalMode(); else normalMode();
}) })
.catch((error) => { .catch((error) => {

@ -6,7 +6,7 @@ const router = createRouter({
{ {
path: "/", path: "/",
name: "index", name: "index",
component: () => import("../views/FirstTimeWizardView.vue"), component: () => import("../views/SetupAssistantView.vue"),
}, },
{ {
path: "/:pathMatch(.*)*", path: "/:pathMatch(.*)*",

@ -1,8 +1,8 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import FirstTimeWizard from '@/FirstTimeWizard.vue' import SetupAssistant from '@/SetupAssistant.vue'
import router from '@/router/first-time-wizard' import router from '@/router/setup-assistant'
// Ensure Tabulator can find `luxon`, which it needs for sorting by // Ensure Tabulator can find `luxon`, which it needs for sorting by
// date/time/datetime. // date/time/datetime.
@ -14,7 +14,7 @@ window.plain = (x) => JSON.parse(JSON.stringify(x));
// objectEmpty returns whether the object is empty or not. // objectEmpty returns whether the object is empty or not.
window.objectEmpty = (o) => !o || Object.entries(o).length == 0; window.objectEmpty = (o) => !o || Object.entries(o).length == 0;
const app = createApp(FirstTimeWizard) const app = createApp(SetupAssistant)
const pinia = createPinia() const pinia = createPinia()
app.use(pinia) app.use(pinia)

@ -208,7 +208,7 @@
<step-item <step-item
v-show="currentSetupStep == 4" v-show="currentSetupStep == 4"
@next-clicked="confirmWizard" @next-clicked="confirmSetupAssistant"
@back-clicked="prevStep" @back-clicked="prevStep"
next-label="Confirm" next-label="Confirm"
title="Review" title="Review"
@ -251,7 +251,7 @@ import 'microtip/microtip.css'
import NotificationBar from '@/components/footer/NotificationBar.vue' import NotificationBar from '@/components/footer/NotificationBar.vue'
import UpdateListener from '@/components/UpdateListener.vue' import UpdateListener from '@/components/UpdateListener.vue'
import StepItem from '@/components/steps/StepItem.vue'; import StepItem from '@/components/steps/StepItem.vue';
import { MetaApi, PathCheckInput, WizardConfig } from "@/manager-api"; import { MetaApi, PathCheckInput, SetupAssistantConfig } from "@/manager-api";
import { apiClient } from '@/stores/api-query-count'; import { apiClient } from '@/stores/api-query-count';
function debounce(func, wait, immediate) { function debounce(func, wait, immediate) {
@ -270,7 +270,7 @@ function debounce(func, wait, immediate) {
} }
export default { export default {
name: 'FirstTimeWizardView', name: 'SetupAssistantView',
components: { components: {
UpdateListener, UpdateListener,
StepItem, StepItem,
@ -440,23 +440,23 @@ export default {
} }
}, },
confirmWizard() { confirmSetupAssistant() {
const wizardConfig = new WizardConfig( const setupAssistantConfig = new SetupAssistantConfig(
this.sharedStorageCheckResult.path, this.sharedStorageCheckResult.path,
this.selectedBlender, this.selectedBlender,
); );
console.log("saving configuration:", wizardConfig); console.log("saving configuration:", setupAssistantConfig);
this.isConfirming = true; this.isConfirming = true;
this.isConfirmed = false; this.isConfirmed = false;
this.metaAPI.saveWizardConfig({ wizardConfig: wizardConfig }) this.metaAPI.saveSetupAssistantConfig({ setupAssistantConfig: setupAssistantConfig })
.then((result) => { .then((result) => {
console.log("Wizard config saved, reload the page"); console.log("Setup Assistant config saved, reload the page");
this.isConfirmed = true; this.isConfirmed = true;
// Give the Manager some time to restart. // Give the Manager some time to restart.
window.setTimeout(() => { window.location.reload() }, 2000); window.setTimeout(() => { window.location.reload() }, 2000);
}) })
.catch((error) => { .catch((error) => {
console.log("Error saving wizard config:", error); console.log("Error saving setup assistan config:", error);
// Only clear this flag on an error. // Only clear this flag on an error.
this.isConfirming = false; this.isConfirming = false;
}) })

@ -17,7 +17,7 @@ import (
var webStaticFS embed.FS var webStaticFS embed.FS
// WebAppHandler returns a HTTP handler to serve the static files of the Flamenco Manager web app. // WebAppHandler returns a HTTP handler to serve the static files of the Flamenco Manager web app.
// `appFilename` is either `index.html` for the main webapp, or `first-time-wizard.html`. // `appFilename` is either `index.html` for the main webapp, or `setup-assistant.html`.
func WebAppHandler(appFilename string) (http.Handler, error) { func WebAppHandler(appFilename string) (http.Handler, error) {
// Strip the 'static/' directory off of the embedded filesystem. // Strip the 'static/' directory off of the embedded filesystem.
fs, err := fs.Sub(webStaticFS, "static") fs, err := fs.Sub(webStaticFS, "static")