瀏覽代碼

feat: new page UI + db fixes + installer improvements

Nicolas Giard 6 年之前
父節點
當前提交
4bb522f9d9

+ 2 - 3
client/components/login.vue

@@ -223,7 +223,7 @@ export default {
 <style lang="scss">
   .login {
     background-color: mc('blue', '800');
-    background-image: url('../static/svg/login-bg-motif.svg');
+    background-image: url('../static/svg/motif-blocks.svg');
     background-repeat: repeat;
     background-size: 200px;
     width: 100%;
@@ -246,10 +246,9 @@ export default {
       content: '';
       position: absolute;
       background-color: #0d47a1;
-      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='100%25' viewBox='0 0 1600 800'%3E%3Cg %3E%3Cpath fill='%231356b1' d='M486 705.8c-109.3-21.8-223.4-32.2-335.3-19.4C99.5 692.1 49 703 0 719.8V800h843.8c-115.9-33.2-230.8-68.1-347.6-92.2C492.8 707.1 489.4 706.5 486 705.8z'/%3E%3Cpath fill='%231866c1' d='M1600 0H0v719.8c49-16.8 99.5-27.8 150.7-33.5c111.9-12.7 226-2.4 335.3 19.4c3.4 0.7 6.8 1.4 10.2 2c116.8 24 231.7 59 347.6 92.2H1600V0z'/%3E%3Cpath fill='%231c75d2' d='M478.4 581c3.2 0.8 6.4 1.7 9.5 2.5c196.2 52.5 388.7 133.5 593.5 176.6c174.2 36.6 349.5 29.2 518.6-10.2V0H0v574.9c52.3-17.6 106.5-27.7 161.1-30.9C268.4 537.4 375.7 554.2 478.4 581z'/%3E%3Cpath fill='%231f86e2' d='M0 0v429.4c55.6-18.4 113.5-27.3 171.4-27.7c102.8-0.8 203.2 22.7 299.3 54.5c3 1 5.9 2 8.9 3c183.6 62 365.7 146.1 562.4 192.1c186.7 43.7 376.3 34.4 557.9-12.6V0H0z'/%3E%3Cpath fill='%232196f3' d='M181.8 259.4c98.2 6 191.9 35.2 281.3 72.1c2.8 1.1 5.5 2.3 8.3 3.4c171 71.6 342.7 158.5 531.3 207.7c198.8 51.8 403.4 40.8 597.3-14.8V0H0v283.2C59 263.6 120.6 255.7 181.8 259.4z'/%3E%3Cpath fill='%2355a4f5' d='M1600 0H0v136.3c62.3-20.9 127.7-27.5 192.2-19.2c93.6 12.1 180.5 47.7 263.3 89.6c2.6 1.3 5.1 2.6 7.7 3.9c158.4 81.1 319.7 170.9 500.3 223.2c210.5 61 430.8 49 636.6-16.6V0z'/%3E%3Cpath fill='%2374b2f7' d='M454.9 86.3C600.7 177 751.6 269.3 924.1 325c208.6 67.4 431.3 60.8 637.9-5.3c12.8-4.1 25.4-8.4 38.1-12.9V0H288.1c56 21.3 108.7 50.6 159.7 82C450.2 83.4 452.5 84.9 454.9 86.3z'/%3E%3Cpath fill='%238ec0f8' d='M1600 0H498c118.1 85.8 243.5 164.5 386.8 216.2c191.8 69.2 400 74.7 595 21.1c40.8-11.2 81.1-25.2 120.3-41.7V0z'/%3E%3Cpath fill='%23a5cffa' d='M1397.5 154.8c47.2-10.6 93.6-25.3 138.6-43.8c21.7-8.9 43-18.8 63.9-29.5V0H643.4c62.9 41.7 129.7 78.2 202.1 107.4C1020.4 178.1 1214.2 196.1 1397.5 154.8z'/%3E%3Cpath fill='%23bbdefb' d='M1315.3 72.4c75.3-12.6 148.9-37.1 216.8-72.4h-723C966.8 71 1144.7 101 1315.3 72.4z'/%3E%3C/g%3E%3C/svg%3E");
+      background-image: url('../static/svg/motif-overlay.svg');
       background-attachment: fixed;
       background-size: cover;
-      /* background by SVGBackgrounds.com */
       opacity: .5;
       top: 0;
       left: 0;

+ 1 - 0
client/scss/app.scss

@@ -18,6 +18,7 @@
 @import '~xterm/dist/xterm.css';
 // @import 'node_modules/diff2html/dist/diff2html.min';
 
+@import 'pages/new';
 @import 'pages/welcome';
 @import 'pages/error';
 

+ 81 - 0
client/scss/pages/_new.scss

@@ -0,0 +1,81 @@
+.newpage {
+  background: linear-gradient(to bottom, mc('blue', '900') 0%, mc('blue', '800') 100%);
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  color: mc('grey', '50');
+
+  &::before {
+    content: '';
+    display:block;
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+    background-image: url('../static/svg/motif-circuit.svg');
+    background-position: center center;
+    background-repeat: repeat;
+    background-size: 200px;
+    z-index: 0;
+    opacity: .75;
+    animation: onboardingBgReveal 80s linear infinite;
+
+    @include keyframes(onboardingBgReveal) {
+      0% {
+        background-position-y: 0;
+      }
+      100% {
+        background-position-y: -2000px;
+      }
+    }
+  }
+
+  &::after {
+    content: '';
+    position: absolute;
+    background-color: #0d47a1;
+    background-image: url('../static/svg/motif-overlay.svg');
+    background-attachment: fixed;
+    background-size: cover;
+    opacity: .5;
+    top: 0;
+    left: 0;
+    width: 100vw;
+    height: 100vh;
+  }
+
+  &-content {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    z-index: 2;
+  }
+
+  img {
+    height: 250px;
+    margin-bottom: 3rem;
+    z-index: 2;
+    animation-duration: 3s;
+
+    @include until($tablet) {
+      height: 200px;
+    }
+  }
+
+  h1 {
+    font-size: 1.5rem;
+    margin-bottom: 1rem;
+    z-index: 2;
+  }
+  h2 {
+    margin-bottom: 3rem;
+    z-index: 2;
+  }
+  .v-btn {
+    z-index: 2;
+  }
+}

+ 7 - 15
client/scss/pages/_welcome.scss

@@ -15,7 +15,7 @@
     position: absolute;
     top: 0;
     left: 0;
-    background-image: url('../static/svg/login-bg-motif.svg');
+    background-image: url('../static/svg/motif-blocks.svg');
     background-position: center center;
     background-repeat: repeat;
     background-size: 500px;
@@ -33,20 +33,12 @@
     }
   }
 
-  &::after {
-    content: '';
-    display: block;
-    width: 95vw;
-    height: 95vh;
-    border: 3px dotted rgba(255,255,255,.2);
-    border-radius: 50px;
-    position: absolute;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    margin: auto;
-    z-index: 1;
+  &-content {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    z-index: 2;
   }
 
   img {

File diff suppressed because it is too large
+ 3 - 0
client/static/svg/henry-thinking.svg


+ 0 - 7
client/static/svg/login-bg.svg

@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg width="100%" height="100%" viewBox="0 0 1500 1000" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
-    <path d="M1500,543c0,0 -135.753,54.677 -252.197,101.577c-106.023,42.702 -223.596,47.2 -332.571,12.724c-56.088,-17.745 -118.404,-37.46 -173.999,-55.048c-103.773,-32.831 -216.376,-22.709 -312.631,28.103c0,0 0,0.001 0,0.001c-94.821,50.055 -206.441,57.476 -307.053,20.415c-63.317,-23.322 -121.549,-44.772 -121.549,-44.772l0,417l1500,0l0,-480Z" style="fill:#fff;fill-opacity:0.282609;"/>
-    <path d="M1510,580c0,0 -144.155,47.882 -252.311,83.806c-74.651,24.796 -156.199,17.958 -225.679,-18.923c0,0 0,0 0,0c-62.207,-33.021 -133.629,-44.415 -203.023,-32.389c-98.381,17.051 -244.859,42.438 -352.664,61.121c-92.259,15.99 -187.076,8.079 -275.41,-22.977c-93.342,-32.818 -200.913,-70.638 -200.913,-70.638l0,466l1500,0l10,-466Z" style="fill:#fff;fill-opacity:0.550725;"/>
-    <path d="M1500,650c0,0 -143.367,28.581 -239.425,47.731c-56.087,11.181 -113.694,12.508 -170.237,3.922c-74.75,-11.351 -183.318,-27.838 -261.719,-39.743c-65.252,-9.909 -131.707,-8.759 -196.577,3.4c-49.655,9.308 -109.704,20.564 -158.992,29.803c-63.125,11.833 -127.839,12.479 -191.188,1.911c-111.875,-18.665 -281.862,-47.024 -281.862,-47.024l0,430l1500,0l0,-430Z" style="fill:#fff;"/>
-</svg>

+ 0 - 0
client/static/svg/login-bg-motif.svg → client/static/svg/motif-blocks.svg


File diff suppressed because it is too large
+ 1 - 0
client/static/svg/motif-circuit.svg


+ 0 - 0
client/static/svg/config-bg.svg → client/static/svg/motif-grid.svg


+ 15 - 0
client/static/svg/motif-overlay.svg

@@ -0,0 +1,15 @@
+<!-- background by SVGBackgrounds.com -->
+<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='0 0 1600 800'>
+  <g>
+    <path fill='#1356b1' d='M486 705.8c-109.3-21.8-223.4-32.2-335.3-19.4C99.5 692.1 49 703 0 719.8V800h843.8c-115.9-33.2-230.8-68.1-347.6-92.2C492.8 707.1 489.4 706.5 486 705.8z'/>
+    <path fill='#1866c1' d='M1600 0H0v719.8c49-16.8 99.5-27.8 150.7-33.5c111.9-12.7 226-2.4 335.3 19.4c3.4 0.7 6.8 1.4 10.2 2c116.8 24 231.7 59 347.6 92.2H1600V0z'/>
+    <path fill='#1c75d2' d='M478.4 581c3.2 0.8 6.4 1.7 9.5 2.5c196.2 52.5 388.7 133.5 593.5 176.6c174.2 36.6 349.5 29.2 518.6-10.2V0H0v574.9c52.3-17.6 106.5-27.7 161.1-30.9C268.4 537.4 375.7 554.2 478.4 581z'/>
+    <path fill='#1f86e2' d='M0 0v429.4c55.6-18.4 113.5-27.3 171.4-27.7c102.8-0.8 203.2 22.7 299.3 54.5c3 1 5.9 2 8.9 3c183.6 62 365.7 146.1 562.4 192.1c186.7 43.7 376.3 34.4 557.9-12.6V0H0z'/>
+    <path fill='#2196f3' d='M181.8 259.4c98.2 6 191.9 35.2 281.3 72.1c2.8 1.1 5.5 2.3 8.3 3.4c171 71.6 342.7 158.5 531.3 207.7c198.8 51.8 403.4 40.8 597.3-14.8V0H0v283.2C59 263.6 120.6 255.7 181.8 259.4z'/>
+    <path fill='#55a4f5' d='M1600 0H0v136.3c62.3-20.9 127.7-27.5 192.2-19.2c93.6 12.1 180.5 47.7 263.3 89.6c2.6 1.3 5.1 2.6 7.7 3.9c158.4 81.1 319.7 170.9 500.3 223.2c210.5 61 430.8 49 636.6-16.6V0z'/>
+    <path fill='#74b2f7' d='M454.9 86.3C600.7 177 751.6 269.3 924.1 325c208.6 67.4 431.3 60.8 637.9-5.3c12.8-4.1 25.4-8.4 38.1-12.9V0H288.1c56 21.3 108.7 50.6 159.7 82C450.2 83.4 452.5 84.9 454.9 86.3z'/>
+    <path fill='#8ec0f8' d='M1600 0H498c118.1 85.8 243.5 164.5 386.8 216.2c191.8 69.2 400 74.7 595 21.1c40.8-11.2 81.1-25.2 120.3-41.7V0z'/>
+    <path fill='#a5cffa' d='M1397.5 154.8c47.2-10.6 93.6-25.3 138.6-43.8c21.7-8.9 43-18.8 63.9-29.5V0H643.4c62.9 41.7 129.7 78.2 202.1 107.4C1020.4 178.1 1214.2 196.1 1397.5 154.8z'/>
+    <path fill='#bbdefb' d='M1315.3 72.4c75.3-12.6 148.9-37.1 216.8-72.4h-723C966.8 71 1144.7 101 1315.3 72.4z'/>
+  </g>
+</svg>

+ 78 - 72
dev/installer/main.go

@@ -3,100 +3,106 @@ package main
 import (
 	"fmt"
 	"runtime"
-	"time"
 
-	"github.com/gosuri/uiprogress"
-	"github.com/manifoldco/promptui"
-	"github.com/ttacon/chalk"
+	"github.com/bugsnag/bugsnag-go"
+	"github.com/fatih/color"
+	"gopkg.in/AlecAivazis/survey.v1"
 )
 
-var logo = `
- __    __ _ _    _    _
-/ / /\ \ (_) | _(_)  (_)___
-\ \/  \/ / | |/ / |  | / __|
- \  /\  /| |   <| |_ | \__ \
-  \/  \/ |_|_|\_\_(_)/ |___/
-                   |__/
-`
-
-var finish = `
->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-|                                                   |
-|    Open http://localhost:3000/ in your browser    |
-|    to complete the installation!                  |
-|                                                   |
-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-`
+var qs = []*survey.Question{
+	{
+		Name: "location",
+		Prompt: &survey.Input{
+			Message: "Where do you want to install Wiki.js?",
+			Default: "./wiki",
+		},
+		Validate: survey.Required,
+	},
+	{
+		Name: "dbtype",
+		Prompt: &survey.Select{
+			Message: "Select a DB Driver:",
+			Options: []string{"MariabDB", "MS SQL Server", "MySQL", "PostgreSQL", "SQLite"},
+			Default: "PostgreSQL",
+		},
+	},
+	{
+		Name: "port",
+		Prompt: &survey.Input{
+			Message: "Server Port:",
+			Default: "3000",
+		},
+	},
+}
 
 func main() {
-	fmt.Println(chalk.Yellow.Color(logo))
-	fmt.Println(chalk.Bold.TextStyle("Installer for Wiki.js 2.x"))
+	bugsnag.Configure(bugsnag.Configuration{
+		APIKey:       "37770b3b08864599fd47c4edba5aa656",
+		ReleaseStage: "dev",
+	})
+
+	bold := color.New(color.FgWhite).Add(color.Bold)
+
+	logo := `
+  __    __ _ _    _    _
+ / / /\ \ (_) | _(_)  (_)___
+ \ \/  \/ / | |/ / |  | / __|
+  \  /\  /| |   <| |_ | \__ \
+   \/  \/ |_|_|\_\_(_)/ |___/
+                    |__/
+  `
+	color.Yellow(logo)
+
+	bold.Println("\nInstaller for Wiki.js 2.x")
 	fmt.Printf("%s-%s\n\n", runtime.GOOS, runtime.GOARCH)
 
 	// Check system requirements
 
-	fmt.Println(chalk.Bold.TextStyle("Verifying system requirements..."))
+	bold.Println("Verifying system requirements...")
 	CheckNodeJs()
 	CheckRAM()
-	fmt.Println(chalk.Bold.TextStyle("\nSetup"))
-
-	// Prompt for build to install
+	fmt.Println()
 
-	promptBuild := promptui.Select{
-		Label: "Select Build to install",
-		Items: []string{"Stable", "Dev"},
-		Templates: &promptui.SelectTemplates{
-			Help:     " ",
-			Selected: chalk.Green.Color("✔") + " Build: {{ . }}",
-		},
-	}
-
-	_, _, err := promptBuild.Run()
+	// the answers will be written to this struct
+	answers := struct {
+		Location string
+		DBType   string `survey:"dbtype"`
+		Port     int
+	}{}
 
+	// perform the questions
+	err := survey.Ask(qs, &answers)
 	if err != nil {
-		fmt.Printf("Prompt failed %v\n", err)
+		fmt.Println(err.Error())
 		return
 	}
 
-	// Choose database driver
-
-	promptDB := promptui.Select{
-		Label: "Select database driver",
-		Items: []string{"MariaDB", "MySQL", "MS SQL Server", "PostgreSQL", "SQLite"},
-		Templates: &promptui.SelectTemplates{
-			Help:     " ",
-			Selected: chalk.Green.Color("✔") + " Database Driver: {{ . }}",
-		},
-		Size: 10,
-	}
-
-	_, _, err = promptDB.Run()
-
-	// Port
-
-	promptPort := promptui.Prompt{
-		Label:   "Port",
-		Default: "3000",
-		Templates: &promptui.PromptTemplates{
-			Success: chalk.Green.Color("✔") + " Port: {{ . }}",
-		},
-	}
-
-	_, err = promptPort.Run()
+	fmt.Printf("%s chose %d.", answers.Location, answers.Port)
 
 	// Download archives...
 
-	fmt.Println(chalk.Bold.TextStyle("\nDownloading packages..."))
+	bold.Println("\nDownloading packages...")
 
-	uiprogress.Start()
-	bar := uiprogress.AddBar(100)
+	// uiprogress.Start()
+	// bar := uiprogress.AddBar(100)
 
-	bar.AppendCompleted()
-	bar.PrependElapsed()
+	// bar.AppendCompleted()
+	// bar.PrependElapsed()
 
-	for bar.Incr() {
-		time.Sleep(time.Millisecond * 20)
-	}
+	// for bar.Incr() {
+	// 	time.Sleep(time.Millisecond * 20)
+	// }
+
+	finish := `
+  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+  |                                                   |
+  |    Open http://localhost:3000/ in your browser    |
+  |    to complete the installation!                  |
+  |                                                   |
+  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+  `
+	color.Yellow("\n\n" + finish)
 
-	fmt.Println("\n" + chalk.Yellow.Color(finish))
+	fmt.Println("Press any key to continue.")
+	fmt.Scanln()
 }

+ 6 - 9
dev/installer/syscheck.go

@@ -3,15 +3,14 @@ package main
 import (
 	"fmt"
 	"log"
-	"os"
 	"os/exec"
 
 	"github.com/blang/semver"
+	"github.com/fatih/color"
 	"github.com/pbnjay/memory"
-	"github.com/ttacon/chalk"
 )
 
-const nodejsSemverRange = ">=8.11.3 <10.0.0"
+const nodejsSemverRange = ">=8.11.4 <11.0.0"
 const ramMin = 768
 
 // CheckNodeJs checks if Node.js is installed and has minimal supported version
@@ -25,11 +24,10 @@ func CheckNodeJs() bool {
 	validRange := semver.MustParseRange(nodejsSemverRange)
 	nodeVersion, err := semver.ParseTolerant(string(cmdOutput[:]))
 	if !validRange(nodeVersion) {
-		fmt.Printf(chalk.Red.Color("Error: Installed Node.js version is not supported! %s"), nodejsSemverRange)
-		os.Exit(1)
+		panic(fmt.Errorf(color.RedString("Error: Installed Node.js version %s is not supported! %s\n"), nodeVersion, nodejsSemverRange))
 	}
 
-	fmt.Printf(chalk.Green.Color("✔")+" Node.js %s: OK\n", nodeVersion.String())
+	fmt.Printf(color.GreenString("✔")+" Node.js %s: OK\n", nodeVersion.String())
 
 	return true
 }
@@ -38,11 +36,10 @@ func CheckNodeJs() bool {
 func CheckRAM() bool {
 	var totalRAM = memory.TotalMemory() / 1024 / 1024
 	if totalRAM < ramMin {
-		fmt.Printf(chalk.Red.Color("Error: System does not meet RAM requirements. %s MB minimum."), ramMin)
-		os.Exit(1)
+		panic(fmt.Errorf(color.RedString("Error: System does not meet RAM requirements. %s MB minimum.\n"), ramMin))
 	}
 
-	fmt.Printf(chalk.Green.Color("✔")+" Total System RAM %d MB: OK\n", totalRAM)
+	fmt.Printf(color.GreenString("✔")+" Total System RAM %d MB: OK\n", totalRAM)
 
 	return true
 }

+ 4 - 0
server/app/data.yml

@@ -66,6 +66,10 @@ jobs:
     onInit: true
     cron: '*/15 * * * *'
     concurrency: 0
+  renderPage:
+    onInit: false
+    cron: false
+    concurrency: 1
   syncGraphLocales:
     onInit: true
     cron: '0 0 * * *'

+ 17 - 9
server/controllers/common.js

@@ -1,5 +1,8 @@
 const express = require('express')
 const router = express.Router()
+const pageHelper = require('../helpers/page')
+
+/* global WIKI */
 
 /**
  * Create/Edit document
@@ -25,15 +28,20 @@ router.get(['/p', '/p/*'], (req, res, next) => {
 /**
  * View document
  */
-router.get('/', (req, res, next) => {
-  res.render('welcome')
-})
-
-/**
- * View document
- */
-router.get('/*', (req, res, next) => {
-  res.render('page')
+router.get('/*', async (req, res, next) => {
+  const pageArgs = pageHelper.parsePath(req.path)
+  const page = await WIKI.models.pages.getPage({
+    path: pageArgs.path,
+    locale: pageArgs.locale,
+    userId: req.user.id
+  })
+  if (page) {
+    res.render('page')
+  } else if (pageArgs.path === 'home') {
+    res.render('welcome')
+  } else {
+    res.render('new')
+  }
 })
 
 module.exports = router

+ 1 - 0
server/db/migrations/2.0.0.js

@@ -87,6 +87,7 @@ exports.up = knex => {
       table.string('description')
       table.boolean('isPrivate').notNullable().defaultTo(false)
       table.boolean('isPublished').notNullable().defaultTo(false)
+      table.string('privateNS')
       table.string('publishStartDate')
       table.string('publishEndDate')
       table.text('content')

+ 0 - 60
server/helpers/entry.js

@@ -1,60 +0,0 @@
-/* global appdata, ROOTPATH */
-
-const crypto = require('crypto')
-const path = require('path')
-const qs = require('querystring')
-const _ = require('lodash')
-
-module.exports = {
-  /**
-   * Parse raw url path and make it safe
-   *
-   * @param      {String}  urlPath  The url path
-   * @return     {String}  Safe entry path
-   */
-  parsePath (urlPath) {
-    urlPath = qs.unescape(urlPath)
-    let wlist = new RegExp('[^a-z0-9' + appdata.regex.cjk + appdata.regex.arabic + '/-]', 'g')
-
-    urlPath = _.toLower(urlPath).replace(wlist, '')
-
-    if (urlPath === '/') {
-      urlPath = 'home'
-    }
-
-    let urlParts = _.filter(_.split(urlPath, '/'), (p) => { return !_.isEmpty(p) })
-
-    return _.join(urlParts, '/')
-  },
-
-  /**
-   * Gets the full original path of a document.
-   *
-   * @param      {String}  entryPath  The entry path
-   * @return     {String}  The full path.
-   */
-  getFullPath (entryPath) {
-    return path.join(appdata.repoPath, entryPath + '.md')
-  },
-
-  /**
-   * Gets the full cache path of a document.
-   *
-   * @param      {String}    entryPath  The entry path
-   * @return     {String}  The full cache path.
-   */
-  getCachePath (entryPath) {
-    return path.join(appdata.cachePath, crypto.createHash('md5').update(entryPath).digest('hex') + '.json')
-  },
-
-  /**
-   * Gets the entry path from full path.
-   *
-   * @param      {String}  fullPath  The full path
-   * @return     {String}  The entry path
-   */
-  getEntryPathFromFullPath (fullPath) {
-    let absRepoPath = path.resolve(ROOTPATH, appdata.repoPath)
-    return _.chain(fullPath).replace(absRepoPath, '').replace('.md', '').replace(new RegExp('\\\\', 'g'), '/').value()
-  }
-}

+ 30 - 0
server/helpers/page.js

@@ -0,0 +1,30 @@
+const qs = require('querystring')
+const _ = require('lodash')
+
+module.exports = {
+  /**
+   * Parse raw url path and make it safe
+   */
+  parsePath (rawPath) {
+    let pathObj = {
+      locale: 'en',
+      path: 'home',
+      private: false,
+      privateNS: ''
+    }
+
+    // Clean Path
+    rawPath = _.trim(qs.unescape(rawPath))
+    if (_.startsWith(rawPath, '/')) { rawPath = rawPath.substring(1) }
+    if (rawPath === '') { rawPath = 'home' }
+
+    // Extract Info
+    let pathParts = _.filter(_.split(rawPath, '/'), p => !_.isEmpty(p))
+    if (pathParts[0].length === 2) {
+      pathObj = pathParts[0]
+      pathParts.shift()
+    }
+    pathObj.path = _.join(pathParts, '/')
+    return pathObj
+  }
+}

+ 0 - 1
server/jobs/render-page.js

@@ -6,7 +6,6 @@ module.exports = async (job) => {
   WIKI.logger.info(`Rendering page ${job.data.path}...`)
 
   try {
-
     WIKI.logger.info(`Rendering page ${job.data.path}: [ COMPLETED ]`)
   } catch (err) {
     WIKI.logger.error(`Rendering page ${job.data.path}: [ FAILED ]`)

+ 23 - 0
server/models/pages.js

@@ -1,4 +1,5 @@
 const Model = require('objection').Model
+const _ = require('lodash')
 
 /* global WIKI */
 
@@ -19,6 +20,7 @@ module.exports = class Page extends Model {
         title: {type: 'string'},
         description: {type: 'string'},
         isPublished: {type: 'boolean'},
+        privateNS: {type: 'string'},
         publishStartDate: {type: 'string'},
         publishEndDate: {type: 'string'},
         content: {type: 'string'},
@@ -87,6 +89,27 @@ module.exports = class Page extends Model {
     this.updatedAt = new Date().toISOString()
   }
 
+  static async getPage(opts) {
+    const page = await WIKI.models.pages.query().where({
+      path: opts.path,
+      localeCode: opts.locale
+    }).andWhere(builder => {
+      builder.where({
+        isPublished: true
+      }).orWhere({
+        isPublished: false,
+        authorId: opts.userId
+      })
+    }).andWhere(builder => {
+      if (opts.private) {
+        builder.where({ isPrivate: true, privateNS: opts.privateNS })
+      } else {
+        builder.where({ isPrivate: false })
+      }
+    }).first()
+    return page
+  }
+
   static async createPage(opts) {
     await WIKI.models.pages.renderPage(opts)
     const page = await WIKI.models.pages.query().insertAndFetch({

+ 16 - 0
server/views/new.pug

@@ -0,0 +1,16 @@
+extends master.pug
+
+block body
+  #root.is-fullscreen
+    v-app
+      .newpage
+        .newpage-content
+          img.animated.fadeIn(src='/svg/henry-thinking.svg', alt='Henry')
+          .headline= t('newpage.title')
+          .subheading.mt-3= t('newpage.subtitle')
+          v-btn.mt-5(href='/e/home', large)
+            v-icon(left) add
+            span= t('newpage.create')
+          v-btn.mt-2(color='blue lighten-4', href='javascript:window.history.go(-1);', large, outline)
+            v-icon(left) arrow_back
+            span= t('newpage.goback')

+ 7 - 6
server/views/welcome.pug

@@ -4,9 +4,10 @@ block body
   #root.is-fullscreen
     v-app
       .onboarding
-        img.animated.fadeIn(src='/svg/logo-wikijs.svg', alt='Wiki.js')
-        .headline= t('welcome.title')
-        .subheading.mt-3= t('welcome.subtitle')
-        v-btn.mt-5(color='primary', href='/e/home', large)
-          v-icon(left) add
-          span= t('welcome.createhome')
+        .onboarding-content
+          img.animated.fadeIn(src='/svg/logo-wikijs.svg', alt='Wiki.js')
+          .headline= t('welcome.title')
+          .subheading.mt-3= t('welcome.subtitle')
+          v-btn.mt-5(color='primary', href='/e/home', large)
+            v-icon(left) add
+            span= t('welcome.createhome')

Some files were not shown because too many files changed in this diff