start first steps

This commit is contained in:
2020-03-30 17:11:56 +02:00
parent 2d2f00bcfd
commit f9c6a4e187
16 changed files with 430 additions and 74 deletions
+41
View File
@@ -0,0 +1,41 @@
namespace zero.Core.Entities.Setup
{
public sealed class SetupSave
{
public string AppName { get; set; }
public SetupUserSave User { get; set; }
public SetupDatabaseSave Database { get; set; }
public SetupSavePart Part { get; set; }
}
public sealed class SetupUserSave
{
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
public sealed class SetupDatabaseSave
{
public string Url { get; set; }
public string Name { get; set; }
}
public enum SetupSavePart
{
ValidateUser = 0,
ValidateApplication = 1,
ValidateDatabase = 2,
ValidateFolderAccess = 3,
WriteSettings = 4,
SaveData = 5
}
}
@@ -21,6 +21,18 @@ namespace zero.Core.Extensions
}
/// <summary>
/// Validate an email
/// </summary>
public static IRuleBuilderOptions<T, string> Url<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.Must((root, value, context) =>
{
return value.IsNullOrWhiteSpace() || Uri.IsWellFormedUriString(value, UriKind.Absolute);
}).WithMessage("@errors/invalid_uri");
}
/// <summary>
/// Validate an email
/// </summary>
@@ -0,0 +1,32 @@
using FluentValidation;
using zero.Core.Entities.Setup;
using zero.Core.Extensions;
namespace zero.Core.Validation
{
public class SetupSaveValidator : AbstractValidator<SetupSave>
{
public SetupSaveValidator()
{
When(x => x.Part == SetupSavePart.ValidateUser, () =>
{
RuleFor(x => x.User).NotNull();
RuleFor(x => x.User.Email).NotEmpty().Email();
RuleFor(x => x.User.Name).MaximumLength(40).NotEmpty();
RuleFor(x => x.User.Password).MaximumLength(1024); // TODO password policy
});
When(x => x.Part == SetupSavePart.ValidateApplication, () =>
{
RuleFor(x => x.AppName).MaximumLength(40).NotEmpty();
});
When(x => x.Part == SetupSavePart.ValidateDatabase, () =>
{
RuleFor(x => x.Database.Url).NotEmpty().Url();
RuleFor(x => x.Database.Name).NotEmpty();
});
}
}
}
+4 -4
View File
@@ -1,5 +1,5 @@
<template>
<button class="ui-button" :class="{ themeClass }">
<button class="ui-button" :class="typeClass">
<span v-html="label"></span>
</button>
</template>
@@ -18,7 +18,7 @@
type: String,
default: 'default'
},
theme: {
type: {
type: String,
default: 'action'
},
@@ -26,9 +26,9 @@
},
computed: {
themeClass()
typeClass()
{
return 'theme-' + this.theme;
return 'type-' + this.type;
}
},
+7 -7
View File
@@ -42,6 +42,13 @@
{
position: relative;
display: flex;
& + .ui-property
{
padding-top: 25px;
margin-top: 25px;
border-top: 1px solid var(--color-line);
}
}
.ui-property.is-vertical
@@ -91,11 +98,4 @@
{
flex: 1;
}
.ui-property + .ui-property
{
padding-top: 25px;
margin-top: 25px;
border-top: 1px solid var(--color-line);
}
</style>
+8
View File
@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using zero.Core;
using zero.Core.Entities.Setup;
using zero.Web.Controllers;
namespace zero.Web.Setup
@@ -17,5 +19,11 @@ namespace zero.Web.Setup
{
return View("/Views/Setup.cshtml");
}
[HttpPost]
public async Task<IActionResult> Save(SetupSave model)
{
return Ok();
}
}
}
+5
View File
@@ -15,4 +15,9 @@ input, textarea
vertical-align: middle;
box-sizing: border-box;
width: 100%;
&:focus
{
border: 1px solid var(--color-line-mid);
}
}
+1
View File
@@ -17,6 +17,7 @@
// line colors
--color-line: #eaebec;
--color-line-mid: #d7d8d9;
}
+18 -2
View File
@@ -15,9 +15,11 @@ button
display: inline-block;
color: white;
background: var(--color-primary);
padding: 0 30px;
padding: 0 20px;
min-width: 80px;
height: 40px;
line-height: 40px;
text-align: center;
border-radius: 3px;
font-size: 14px;
font-weight: 600;
@@ -28,7 +30,6 @@ button
cursor: pointer;
user-select: none;
border: none;
margin-top: 2rem;
will-change: transform, background, border-color;
transition: background .2s, transform .2s, opacity .2s;
overflow: hidden;
@@ -49,6 +50,21 @@ button
pointer-events: none;
//background: var(--color-dark);
}
&.type-outline
{
background: var(--color-bg);
color: var(--color-fg);
border: 1px solid var(--color-line);
box-sizing: border-box;
position: relative;
top: 1px;
}
& + .ui-button
{
margin-left: 10px;
}
}
+1 -3
View File
@@ -1,4 +1,2 @@
@import "canvas";
@import "steps";
@import "canvas";
-39
View File
@@ -1,39 +0,0 @@
.setup
{
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
}
.setup-step
{
}
.setup-step h2
{
text-align: center;
}
.setup-step p
{
color: var(--color-fg-mid);
font-size: 0.9rem;
line-height: 1.6;
margin: 0 0 2rem;
}
.setup-step p b
{
color: var(--color-fg);
font-weight: 600;
}
.setup-step .ui-property + .ui-property
{
padding-top: 0;
border-top: none;
}
+36
View File
@@ -0,0 +1,36 @@
<template>
<div class="setup-step setup-step-application">
<h2>your application</h2>
<p>With zero you can manage multiple applications with one installation. Start by adding your first application.</p>
<ui-property label="Application name" :vertical="true">
<input v-model="value" type="text" class="ui-input" maxlength="40" placeholder="Enter name" />
</ui-property>
</div>
</template>
<script>
import UiProperty from 'zerocomponents/forms/property.vue'
import UiButton from 'zerocomponents/buttons/button.vue'
export default {
name: 'setupStepApplication',
props: {
value: String
},
components: { UiProperty, UiButton },
mounted ()
{
},
methods: {
}
}
</script>
+40
View File
@@ -0,0 +1,40 @@
<template>
<div class="setup-step setup-step-database">
<h2>database configuration</h2>
<p>Zero uses <b>RavenDB</b> as its database. If you want a more sophisticated setup (i.e. cluster) you can override the IDocumentStore service which is registered as a singleton.</p>
<ui-property label="Instance URL" :vertical="true">
<input v-model="value.Url" type="text" class="ui-input" placeholder="Enter URL to the database" />
</ui-property>
<ui-property label="Database name" :vertical="true">
<input v-model="value.Name" type="text" class="ui-input" placeholder="Name of the database" />
</ui-property>
</div>
</template>
<script>
import UiProperty from 'zerocomponents/forms/property.vue'
import UiButton from 'zerocomponents/buttons/button.vue'
export default {
name: 'setupStepDatabase',
props: {
value: Object
},
components: { UiProperty, UiButton },
mounted ()
{
},
methods: {
}
}
</script>
+2 -2
View File
@@ -4,7 +4,7 @@
<p>First we need some basic credentials from you to create a login. This login is the solely <b>superadmin</b> which is required to change critical application data.</p>
<ui-property label="Name" :vertical="true">
<input type="text" class="ui-input" placeholder="What's your name?" />
<input type="text" class="ui-input" maxlength="40" placeholder="What's your name?" />
</ui-property>
<ui-property label="Email" :vertical="true">
@@ -12,7 +12,7 @@
</ui-property>
<ui-property label="Password" :vertical="true">
<input type="password" class="ui-input" autocomplete="off" placeholder="As long as you want, but at last 8 characters" />
<input type="password" class="ui-input" autocomplete="off" maxlength="1024" placeholder="As long as you want but at last 8 characters" />
</ui-property>
</div>
</template>
+57 -5
View File
@@ -1,25 +1,31 @@
<template>
<div class="app setup">
<step-user v-model="model.User" />
<ui-button label="Next" />
<step-database v-model="model.Database" />
<div class="setup-buttons">
<ui-button type="outline" label="Go back" />
<ui-button label="Next" />
</div>
</div>
</template>
<script>
import Vue from 'vue'
import StepUser from './Steps/step-user.vue'
import Sass from '../Sass/setup.scss'
import UiButton from 'zerocomponents/buttons/button.vue'
import StepUser from './Steps/step-user.vue'
import StepApplication from './Steps/step-application.vue'
import StepDatabase from './Steps/step-database.vue'
export default {
name: 'setup',
components: { StepUser, UiButton },
components: { UiButton, StepUser, StepApplication, StepDatabase },
data: () => ({
model: {
AppName: null,
Part: null,
User: {
Name: null,
Email: null,
@@ -39,7 +45,53 @@
methods: {
save()
{
}
}
}
</script>
</script>
<style lang="scss">
.setup
{
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
}
.setup-step
{
}
.setup-step h2
{
text-align: center;
}
.setup-step p
{
color: var(--color-fg-mid);
font-size: 0.9rem;
line-height: 1.6;
margin: 0 0 2rem;
}
.setup-step p b
{
color: var(--color-fg);
font-weight: 600;
}
.setup-step .ui-property + .ui-property
{
padding-top: 0;
border-top: none;
}
</style>
File diff suppressed because one or more lines are too long