2024.12.01 02:42:24

This commit is contained in:
Christian Moser 2024-12-01 02:42:24 +01:00
parent c59655e513
commit d3385bfb05
9 changed files with 259 additions and 254 deletions

View File

@ -271,7 +271,8 @@ input[type=number]
}
input[type=submit],
button
button,
.button
{
background-color: var(--color-button-background);
border: 1px solid var(--color-button-border);
@ -284,7 +285,9 @@ button
input[type=submit]:disabled,
input[type=submit]:invalid,
button:disabled,
button:invalid
button:invalid,
.button:disabled,
.button:invalid
{
background-color: var(--color-button-background-disabled);
}

View File

@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20241127204952 extends AbstractMigration
final class Version20241201011651 extends AbstractMigration
{
public function getDescription(): string
{

View File

@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20241201012357 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE mydevel_webroot_file (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
owner_id INTEGER NOT NULL,
url CLOB NOT NULL,
abspath CLOB NOT NULL,
description CLOB DEFAULT NULL,
CONSTRAINT FK_A7B135127E3C61F9 FOREIGN KEY (owner_id) REFERENCES mydevel_webroot_user (id) NOT DEFERRABLE INITIALLY IMMEDIATE
)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_A7B135127E3C61F9 ON mydevel_webroot_file (owner_id)');
$this->addSql('CREATE TABLE mydevel_webroot_file_permission (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
role_id INTEGER NOT NULL,
webroot_file_id INTEGER NOT NULL,
is_readable BOOLEAN DEFAULT 1 NOT NULL,
is_writeable BOOLEAN DEFAULT 0 NOT NULL,
is_deleteable BOOLEAN DEFAULT 0 NOT NULL,
CONSTRAINT FK_4D56CEFD60322AC FOREIGN KEY (role_id) REFERENCES mydevel_webroot_role (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT FK_4D56CEF2800AFC9 FOREIGN KEY (webroot_file_id) REFERENCES mydevel_webroot_file (id) NOT DEFERRABLE INITIALLY IMMEDIATE
)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_4D56CEFD60322AC ON mydevel_webroot_file_permission (role_id)');
$this->addSql('CREATE INDEX IDX_4D56CEF2800AFC9 ON mydevel_webroot_file_permission (webroot_file_id)');
$this->addSql('CREATE TABLE mydevel_webroot_role (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
role VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
description VARCHAR(1023) DEFAULT NULL
)');
$this->addSql('CREATE TABLE mydevel_webroot_user (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
username VARCHAR(180) NOT NULL,
roles CLOB NOT NULL --(DC2Type:json)
,
password VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
is_admin BOOLEAN DEFAULT 0 NOT NULL
)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_A6BDD54BE7927C74 ON mydevel_webroot_user (email)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_USERNAME ON mydevel_webroot_user (username)');
$this->addSql('CREATE TABLE messenger_messages (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
body CLOB NOT NULL,
headers CLOB NOT NULL,
queue_name VARCHAR(190) NOT NULL,
created_at DATETIME NOT NULL --(DC2Type:datetime_immutable)
,
available_at DATETIME NOT NULL --(DC2Type:datetime_immutable)
,
delivered_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
)');
$this->addSql('CREATE INDEX IDX_75EA56E0FB7336F0 ON messenger_messages (queue_name)');
$this->addSql('CREATE INDEX IDX_75EA56E0E3BD61CE ON messenger_messages (available_at)');
$this->addSql('CREATE INDEX IDX_75EA56E016BA31DB ON messenger_messages (delivered_at)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE mydevel_webroot_file');
$this->addSql('DROP TABLE mydevel_webroot_file_permission');
$this->addSql('DROP TABLE mydevel_webroot_role');
$this->addSql('DROP TABLE mydevel_webroot_user');
$this->addSql('DROP TABLE messenger_messages');
}
}

View File

@ -1,14 +0,0 @@
locale: de_AT
tempdir: \xampp\tmp\webroot
site:
name: webroot.cmoser.eu
email: webroot.cmoser.eu
rootdir: 'c:/msys64/home/c9mos/www/webroot'
user:
username: c9mos
email: christian@cmoser.eu
password: $2y$13$N2WGRMc/oEoaE5jdXBiYUejZjefjVTQwGNmdRCpIM5KT1Pv8kt.ku
email:
backend: dsn
address: christian@cmoser.eu
dsn: 'null://null'

View File

@ -28,10 +28,12 @@ class SetupController extends WebrootSetupController
EntityManagerInterface $em,
UserPasswordHasherInterface $passwd_hasher): Response
{
$lang= getenv("LANG");
$dotenv_file = join(DIRECTORY_SEPARATOR,[$this->getProjectDir(),".env"]);
$dotenvlocal_file = join(DIRECTORY_SEPARATOR,[$this->getProjectDir(),".env.local"]);
$errors = [];
$debug=null;
if (!file_exists($dotenv_file)) {
$file = fopen($dotenv_file, "w", false);
fclose($file);
@ -47,6 +49,12 @@ class SetupController extends WebrootSetupController
$form = $this->createSetupForm();
$this->setSetupFormDefaultsFromEnv($form);
if ($this->hasInitialSetupDataCookie($request)) {
$data = $this->getDataFromInitialSetupDataCookie($request);
if ($data) {
$this->setSetupFormFromData($form, $data);
}
}
$form->handleRequest($request);
@ -69,10 +77,11 @@ class SetupController extends WebrootSetupController
"have_migration_output"=>false,
]);
}
$response = $this->redirectToRoute("webroot.initial-setup.run");
$response = $this->redirectToRoute("webroot.initial-setup.run",['step'=>0]);
$this->setInitialSetupDataCookie($request,$form,$response);
$this->writeDotEnvLocal($this->getDataFromSetupForm($form),true);
(new Dotenv())->loadEnv(join(DIRECTORY_SEPARATOR,[$this->getProjectDir(),".env"]));
return $response;
return $response;
}
foreach ($form->getErrors() as $error) {
$errors[] = $error;
@ -102,127 +111,82 @@ class SetupController extends WebrootSetupController
]);
}
#[ROUTE('/setup/inital/run',name:'webroot.initial-setup.run')]
public function setupInitialRun() : Response
#[ROUTE('/setup/initial/run/{step}',name:'webroot.initial-setup.run')]
public function setupInitialRun(Request $request,int $step) : Response
{
//if (!$this->hasInitialSetupDataCookie()) {
// return new AccessDeniedHttpException();
//}
if (!$this->hasInitialSetupDataCookie($request)) {
return new AccessDeniedHttpException();
}
$output = "";
$data= $this->getDataFromInitialSetupDataCookie($request);
$commands=$data["__commands__"];
if ($step >= count($commands)) {
return $this->redirectToRoute("app_login");
}
$status="SUCCESS";
$status_message=$this->trans("command.success",domain:"mydevel.webroot.setup");
if ($commands[$step] === "create-database") {
$output = $this->trans("command.createdb",domain:"mydevel.webroot.setup");
try {
$this->runCreateDatabase();
} catch (\Throwable $ex) {
$status = "FAILED";
$status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup");
}
} elseif ($commands[$step] === "make-migrations") {
$output = $this->trans("command.makemigrations",domain:"mydevel.webroot.setup");
try {
$this->runMakeMigration();
} catch (\Throwable $ex) {
$status = "FAILED";
$status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup");
}
} elseif ($commands[$step] === "migrate") {
$output = $this->trans("command.migrate",domain:"mydevel.webroot.setup");
try {
$this->runMigrate();
} catch (\Throwable $ex) {
$status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup");
}
} elseif ($commands[$step] === "populate-database") {
$output = $this->trans("command.populatedb",domain:"mydevel.webroot.setup");
//try {
$this->addRoles();
$this->addAdministrator($data);
$this->addRootDir($data);
$status = "SUCCESS";
$status_message = $this->trans("command.success",domain:"mydevel.webroot.setup");
// } catch (\Throwable $ex) {
// $status = "FAILED";
// $status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup");
// }
} else {
$output = "Unknown command \"" . $commands[$step] . "\"";
$status = "FAILED";
$status_message = $status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup");
}
return $this->render('setup/initial-setup.run.html.twig', [
'setup_commands'=>[],
'extra' => print_r($_COOKIE),
'setup_url' => $this->generateUrl("webroot.initial-setup"),
'success_url' => $this->generateUrl("app_login"),
'next_url' => $this->generateUrl("webroot.initial-setup.run",['step'=>($step + 1)]),
'status' => $status,
'status_message' => $status_message,
'output' => $output,
'failed_button' => $this->trans("button.return-setup",domain:"mydevel.webroot.setup"),
]);
}
#[ROUTE('/setup/initial/reste',name:'webroot.initial-setup.reset')]
public function setupInitialReset(): Response
#[ROUTE('/setup/initial/end',name:'webroot.initial-setup.end')]
public function setupInitialReset(Request $request): Response
{
if (!$this->hasInitialSetupDataCookie()) {
if (!$this->hasInitialSetupDataCookie($request)) {
throw new AccessDeniedHttpException();
}
unlink(join(DIRECTORY_SEPARATOR,[$this->getProjectDir(),'.env.local']));
$this->redirectToRoute('webroot.initial-setup');
}
#[Route('/setup/run/make-migration',name:'webroot.setup.run.make-migrations')]
public function setupInitialRunMakeMigrations(): Response
{
if ($this->hasAdministrator()) {
$user = getUser();
if (!$user.isAdmin()) {
return redirectToRoute("app_login");
}
} elseif (!$this->hasInitialSetupDataCookie()) {
throw AccessDeniedException("You do not seem to be the Administrator");
}
try {
$this->runMakeMigration();
$result="SUCCESS";
} catch (\Exception $ex) {
$result="FAILED";
}
$ret = "<!DOCTYPE html>"
. "<html>"
. "<head>"
. "<meta charset=\"utf-8\">"
. "</head>"
. "<body>"
. "<span id=\"run-result\">" . $result ."</span>"
. "<body>"
. "</html>";
return new Response($ret);
}
#[Route('/setup/run/migrate',name:'webroot.setup.run.migrate')]
public function setupRunMigrate()
{
if ($this->hasAdministrator()) {
$user = getUser();
if (!$user.isAdmin()) {
return redirectToRoute("app_login");
}
} elseif ($this->hasInitialSetupDataCookie()) {
throw AccessDeniedException("You do not seem to be the Administrator");
}
try {
$this->runMigrate();
$result = "SUCCESS";
} catch (\Exception $ex) {
$result = "FAILED";
}
$ret = "<!DOCTYPE html>"
. "<html>"
. "<head>"
. "<meta charset=\"utf-8\">"
. "</head>"
. "<body>"
. "<span id=\"run-result\">" . $result ."</span>"
. "<body>"
. "</html>";
return new Response($ret);
}
#[Route('/setup/run/createdb',name:'webroot.initial-setup.run.createdb')]
public function createDatabase(): Response
{
if ($this->hasAdministrator()) {
$user = getUser();
if (!$user.isAdmin()) {
return redirectToRoute("app_login");
}
}
if (!$this->hasInitialSetupDataCookie()) {
throw new AccessDeniedHttpException();
}
try {
$this->$this->runCreateDatabase();;
$retsult = "SUCCESS";
} catch (\Exception $ex) {
$result = "FAILED";
}
$ret = "<!DOCTYPE html>"
. "<html>"
. "<head>"
. "<meta charset=\"utf-8\">"
. "</head>"
. "<body>"
. "<span id=\"run-result\">" . $result ."</span>"
. "<body>"
. "</html>";
return new Response($ret);
}
#[Route('/setup/login',name:'webroot.setup.login')]
public function login(): Response
{
return $this->redirectToRoute("app_login");
}
}

View File

@ -10,8 +10,7 @@ use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
@ -40,7 +39,7 @@ abstract class WebrootSetupController extends AbstractController
private ?TranslatorInterface $translator=null;
private ?EntityManagerInterface $entitymanager=null;
private ?NullTranslator $nulltranslator=null;
private const INITIAL_SETUP_COOKIE = "--webroot-initial-setup--";
public function __construct(KernelInterface $kernel,
@ -75,7 +74,11 @@ abstract class WebrootSetupController extends AbstractController
*/
protected function hasAdministrator(): bool
{
$repos = $this->getRpository(WebrootUser::class);
try {
$repos = $this->entitymanager->getRepository(WebrootUser::class);
} catch (\Throwable $ex) {
return false;
}
return $repos->hasAdministrator();
}
@ -420,6 +423,9 @@ abstract class WebrootSetupController extends AbstractController
public function setSetupFormFromData(Form $form,array $values)
{
if (array_key_exists("env", values)) {
$form->get("env")->setData($values["env"]);
}
if (array_key_exists("locale",$values)) {
$form->get("locale")->setData($values["locale"]);
}
@ -434,6 +440,9 @@ abstract class WebrootSetupController extends AbstractController
if (array_key_exists("email",$site)) {
$form->get("site_email")->setData($site["email"]);
}
if (array_key_exists("rootdir", $site)) {
$form->set("site_rootdir")->setData($site["rootdir"]);
}
}
if (array_key_exists("database",$values)) {
$db = $values["database"];
@ -452,7 +461,7 @@ abstract class WebrootSetupController extends AbstractController
if (array_key_exists("user",$db)) {
$form->get("db_user")->setData($db["user"]);
}
if (array_key_exists("password", $db["password"])) {
if (array_key_exists("password", $db)) {
$form->get("db_password")->setData($db["password"]);
}
if (array_key_exists("url",$db)) {
@ -479,7 +488,7 @@ abstract class WebrootSetupController extends AbstractController
if (array_key_exists("user", $email)) {
$form->get("email_user")->setData($email["user"]);
}
if (array_key_exists("password", $email["password"])) {
if (array_key_exists("password", $email)) {
$form->get("email_password")->setData($email["password"]);
}
if (array_key_exists("host",$email)) {
@ -534,7 +543,8 @@ abstract class WebrootSetupController extends AbstractController
public function getDataFromSetupForm(Form $form) : array
{
$data=array();
$data=[];
$data['env'] = $form->get('env')->getNormData();
$locale = $form->get('locale')->getNormData();
if ($locale && strlen($locale)) {
@ -548,12 +558,12 @@ abstract class WebrootSetupController extends AbstractController
$site=[
"name" => $form->get("site_name")->getNormData(),
"email" => $form->get("site_name")->getNormData(),
"email" => $form->get("site_email")->getNormData(),
"rootdir" => $form->get("site_rootdir")->getNormData(),
];
$data["site"] = $site;
$user = array();
$user = [];
$tmp_user = new WebrootUser();
$user_username = $form->get('user_username')->getNormData();
@ -585,7 +595,7 @@ abstract class WebrootSetupController extends AbstractController
$db["backend"] = $form->get("db_backend")->getNormData();
$db["make_migrations"] = $form->get("db_mkmigrations")->getNormData();
$db["migrate"] = $form->get("db_migrate")->getNormData();
$db["create"] = $form->get("db_create")->getNormData();
$db["create_database"] = $form->get("db_create")->getNormData();
$db_url = $form->get('db_url')->getNormData();
if ($db_url && strlen($db_url)) {
$db['url'] = $db_url;
@ -611,7 +621,7 @@ abstract class WebrootSetupController extends AbstractController
if ($db_password && strlen($db_password)) {
$db['password'] = $db_password;
}
$data["user"] = $user;
$data["database"] = $db;
$email = [
"backend" => $form->get("email_backend")->getNormData(),
@ -643,15 +653,32 @@ abstract class WebrootSetupController extends AbstractController
$email["dsn"] = $email_dsn;
}
$data["email"] = $email;
if (count($data) == 0) {
throw \Exception("No Data!!!!");
}
$commands=[];
if ($data["database"]["create_database"]) {
$commands[] = "create-database";
}
if ($data["database"]["make_migrations"]) {
$commands[] = "make-migrations";
}
if ($data["database"]["migrate"]) {
$commands[] = "migrate";
}
$commands[] = "populate-database";
$data["__commands__"] = $commands;
return $data;
}
public function exportSetupFormToFile(Form $form,string $yaml_file)
public function exportSetupFormToFile(Form $form,string $filename)
{
$data = (new Yaml())->dump($this->getDataFromSetupForm($form));
$file = fopen("yaml_file","w");
fwrite($file, $data);
$file = fopen($filename,"w");
fwrite($file, (new Yaml)->dump($this->getDataFromSetupForm($form)));
fsync($file);
fclose($file);
}
@ -667,15 +694,11 @@ abstract class WebrootSetupController extends AbstractController
return ret;
}
protected function getDataFromFile(string $filename) {
}
protected function setInitialSetupDataCookie(Request $request,Form $form,Response $response)
{
if ($this->hasInitialSetupDataCookie()) {
$old_file = filter_input($_COOKIE["webroot-inital-setup"], FILTER_DEFAULT);
if ($old_file && strlen($old_file)) {
if ($this->hasInitialSetupDataCookie($request)) {
$old_file = $request->cookies->get(WebrootSetupController::INITIAL_SETUP_COOKIE);
if ($old_file && strlen($old_file) && file_exists($old_file)) {
unlink($old_file);
}
}
@ -685,7 +708,7 @@ abstract class WebrootSetupController extends AbstractController
}
$filename = tempnam($tempdir,"wis");
$cookie = new Cookie(
"webroot-initial-setup",
WebrootSetupController::INITIAL_SETUP_COOKIE,
$filename,
0,
"/setup/",
@ -698,28 +721,35 @@ abstract class WebrootSetupController extends AbstractController
$response->headers->setCookie($cookie);
}
protected function getDataFromInitialSetupDataCookie(): ?array
protected function getDataFromInitialSetupDataCookie(Request $request): ?array
{
if (!$this->hasInitialSetupDataCookie()) {
if (!$this->hasInitialSetupDataCookie($request)) {
return null;
}
$data_cookie = filter_input($_COOKIE["webroot-initial-setup"],FILTER_DEFAULT);
if (!$data_cookie || !strlen($data_cookie)) {
$data_cookie = $request->cookies->get(WebrootSetupController::INITIAL_SETUP_COOKIE);
if (!file_exists($data_cookie)) {
return null;
}
return (new Yaml)->parseFile($data_cookie);
$data = (new Yaml)->parseFile($data_cookie);
return $data;
}
protected function hasInitialSetupDataCookie(): bool
protected function hasInitialSetupDataCookie(Request $request): bool
{
if (key_exists("webroot-initial-setup", $_COOKIE)) {
$data_cookie = filter_input($_COOKIE["--webroot-initial-setup--"],FILTER_DEFAULT);
return ($data_cookie && strlen($data_cookie));
}
return false;
return $request->cookies->has(WebrootSetupController::INITIAL_SETUP_COOKIE);
}
public function writePrivEnv(array $data,bool $generate_app_secret=true) {
protected function removeInitialSetupDataCookie(Request $request, Response $response)
{
if ($this->hasInitialSetupDataCookie($request)) {
$filename = $request->cookies->get(WebrootSetupController::INITIAL_SETUP_COOKIE);
if (file_exists($filename)) {
unlink($filename);
}
$response->headers->removeCookie(WebrootSetupController::INITIAL_SETUP_COOKIE,"/setup/");
}
}
public function writeDotEnvLocal(array $data,bool $generate_app_secret=true) {
$file = fopen(join(DIRECTORY_SEPARATOR,[$this->project_dir,".env.local"]));
fwrite($file,"ENV=" . $data["env"] . "\n");
@ -785,7 +815,7 @@ abstract class WebrootSetupController extends AbstractController
->findByUsername($setup_data['user']['username']);
$wrf = new WebrootFile();
$wrf->setUrl('/root');
$wrf->setPath($setup_data["site"]["rootdir"]);
$wrf->setAbspath($setup_data["site"]["rootdir"]);
$wrf->setOwner($admin);
$this->entitymanager->persist($wrf);

View File

@ -5,6 +5,6 @@ class NullTranslator
{
public function trans(string $message,array $args=[],?string $locale=null, ?string $domain=null): string
{
return message;
return $message;
}
}

View File

@ -127,6 +127,6 @@
</fieldset>
<div class="full-width right">{{ form_widget(form.submit) }}</div>
{{ form_end(form) }}
<div>
</div>
<script>initializeWebrootSetupForm();</script>
{% endblock %}

View File

@ -1,92 +1,28 @@
{% extends 'base.html.twig' %}
{% block body %}
{% block javascripts %}
{% block importmap %}{{ importmap('app') }}{% endblock %}
<script>
const setup_commands = [
{% for cmd in setup_commands %}
{ "url":{{ cmd.url }}, "output": {{ cmd.output }} },
{% endfor %}
];
redirect_error="{{ setup_url }}";
let command_n = 0;
function endCommands(success) {
let button = document.getElementById("commands-finished-button");
element = document.getElementById("command-code");
p = document.createElement("p");
if (success) {
p.innerText = "Commands executed successfully!";
button.onclick = onCommandsSuccess;
function initializeSetup() {
if ("{{ status }}" === "SUCCESS") {
window.setTimeout(function() {
location.replace("{{ next_url }}");
},2000);
} else {
p.innerText = "Executing commands failed!";
button.onclick = onCommandsFailed;
button.innerText = "Return to setup";
}
element.appendChild(p);
console.log("Button Settings");
button.disabled=false;
}
function appendCommand(n) {
element = document.getElementById("command-code");
p = document.createElement("p");
span = document.createElement("span");
span.innerText = setup_commands[n]["output"];
iframe = document.createElement("iframe");
iframe.setAttribute("id","setup-command-" + n);
iframe.setAttribute("onload","onCommandLoaded");
iframe.setAttribute("src",setup_commands[n]["url"]);
p.appendChild(span);
p.appendChild(iframe);
command_n = n;
}
function onCommandLoaded() {
let element = document.getElementById("command-code");
let cmd_iframe = document.getElementById("setup-command-" + n);
let cmd_result = iframe.contentWindow.document.getElementById("command-result");
if (cmd_result === "SUCCESS") {
next = command_n + 1;
if (n < setup_commands.length) {
appendCommand(next);
} else {
endCommands(true);
}
} else {
endCommands(false);
}
}
function onCommandsSuccess()
{
location.replace('{{ success_url }}');
}
function onCommandsFailed()
{
location.replace('{{ setup_url }}');
}
function onCommandInit()
{
if (setup_commands.length > 0) {
appendCommand(0);
} else {
document.getElementById('commands-finished-button').disabled=true;
endCommands(true);
let elem = document.getElementById("main-div");
let a = document.createElement("a");
a.setAttribute('href',"{{ setup_url }}");
a.setAttribute('class','button');
a.innerText = "{{ failed_button }}"
elem.appendChild(a);
console.log("LOADED")
}
}
</script>
<h1>Running Setup</h1>
<div class="command-output">
<code id="command-code" onload="">
<p id="null-command">Running commands...</p>
</code>
</div>
<button id="commands-finished-button" onclick="onCommandsSuccess;">Finish</button>
<script>onCommandInit();</script>
{% endblock %}
{% block body %}
<div id="main-div">
<h1>Running Setup</h1>
<p>{{ output }} ... {{ status_message }}</p>
</div>
<script>initializeSetup();</script>
{% endblock %}