mirror of
https://github.com/pterodactyl/documentation.git
synced 2025-12-10 00:09:39 -06:00
add versioning
This commit is contained in:
parent
01c8a1e8c0
commit
ee515d0129
@ -111,24 +111,51 @@ module.exports = {
|
||||
{
|
||||
title: 'Panel',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'/panel/getting_started',
|
||||
'/panel/webserver_configuration',
|
||||
'/panel/upgrading',
|
||||
'/panel/configuration',
|
||||
'/panel/troubleshooting',
|
||||
path: '/panel/',
|
||||
currentVersion: '0.7',
|
||||
versions: [
|
||||
{
|
||||
name: '0.6',
|
||||
status: 'deprecated',
|
||||
children: []
|
||||
},
|
||||
{
|
||||
name: '0.7',
|
||||
status: 'stable',
|
||||
children: [
|
||||
'/getting_started',
|
||||
'/webserver_configuration',
|
||||
'/upgrading',
|
||||
'/configuration',
|
||||
'/troubleshooting',
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '1.0',
|
||||
status: 'beta',
|
||||
children: [
|
||||
'/getting_started',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Daemon',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'/daemon/installing',
|
||||
'/daemon/upgrading',
|
||||
'/daemon/configuration',
|
||||
'/daemon/kernel_modifications',
|
||||
'/daemon/debian_8_docker',
|
||||
'/daemon/standalone_sftp',
|
||||
path: '/daemon/',
|
||||
currentVersion: '0.6',
|
||||
versions: [
|
||||
{
|
||||
name: '0.6',
|
||||
children: [
|
||||
'/installing',
|
||||
'/upgrading',
|
||||
'/configuration',
|
||||
'/kernel_modifications',
|
||||
'/debian_8_docker',
|
||||
'/standalone_sftp',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,28 +1,79 @@
|
||||
<template>
|
||||
<div class="sidebar-group" :class="{ first, collapsable }">
|
||||
<p class="sidebar-heading" :class="{ open }" @click="$emit('toggle')">
|
||||
<span>{{ item.title }}</span>
|
||||
<span class="arrow"
|
||||
v-if="collapsable"
|
||||
:class="open ? 'down' : 'right'"></span>
|
||||
</p>
|
||||
<DropdownTransition>
|
||||
<ul class="sidebar-group-items" ref="items" v-if="open || !collapsable">
|
||||
<li v-for="child in item.children">
|
||||
<SidebarLink :item="child"/>
|
||||
</li>
|
||||
</ul>
|
||||
</DropdownTransition>
|
||||
</div>
|
||||
<div class="sidebar-group" :class="{ first, collapsable }">
|
||||
<p class="sidebar-heading" :class="{ open }" @click="$emit('toggle')">
|
||||
<span>{{ item.title }}</span>
|
||||
<span class="arrow" v-if="collapsable" :class="open ? 'down' : 'right'"></span>
|
||||
<VersionSelect
|
||||
class="float-right"
|
||||
v-if="isVersioned"
|
||||
:versions="item.versions"
|
||||
v-model="versionSelect"
|
||||
/>
|
||||
</p>
|
||||
<DropdownTransition>
|
||||
<ul class="sidebar-group-items" ref="items" v-if="open || !collapsable">
|
||||
<li v-for="child in children">
|
||||
<SidebarLink :item="child" />
|
||||
</li>
|
||||
</ul>
|
||||
</DropdownTransition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SidebarLink from './SidebarLink.vue';
|
||||
import DropdownTransition from './DropdownTransition.vue';
|
||||
import SidebarLink from "./SidebarLink.vue";
|
||||
import DropdownTransition from "./DropdownTransition.vue";
|
||||
import VersionSelect from "./VersionSelect.vue";
|
||||
|
||||
export default {
|
||||
name: 'SidebarGroup',
|
||||
props: ['item', 'first', 'open', 'collapsable'],
|
||||
components: { SidebarLink, DropdownTransition }
|
||||
export default {
|
||||
name: "SidebarGroup",
|
||||
props: ["item", "first", "open", "collapsable"],
|
||||
components: { SidebarLink, DropdownTransition, VersionSelect },
|
||||
data: function() {
|
||||
let isVersioned = this.item.versions.length > 0;
|
||||
return {
|
||||
isVersioned,
|
||||
versionSelect: isVersioned ? getSelectedVersion(this.item) : ""
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
versionSelect(newVersion, oldVersion) {
|
||||
if (
|
||||
oldVersion !== newVersion &&
|
||||
this.$router.currentRoute.path.startsWith(this.item.path) &&
|
||||
this.selectedVersion.children.length > 0
|
||||
) {
|
||||
this.$router.push(this.selectedVersion.children[0]);
|
||||
}
|
||||
},
|
||||
$route(to, from) {
|
||||
if (this.isVersioned && to.path.startsWith(this.item.path)) {
|
||||
const pathVersion = to.path.split("/")[2];
|
||||
if (~this.item.versions.map(v => v.name).indexOf(pathVersion)) {
|
||||
this.versionSelect = pathVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedVersion: function() {
|
||||
return this.item.versions.find(v => v.name == this.versionSelect);
|
||||
},
|
||||
children: function() {
|
||||
return this.isVersioned
|
||||
? this.selectedVersion.children
|
||||
: this.item.children;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function getSelectedVersion(item) {
|
||||
if (window.location.pathname.startsWith(item.path)) {
|
||||
const pathVersion = window.location.pathname.split("/")[2];
|
||||
return ~item.versions.map(v => v.name).indexOf(pathVersion)
|
||||
? pathVersion
|
||||
: item.currentVersion;
|
||||
}
|
||||
return item.currentVersion;
|
||||
}
|
||||
</script>
|
||||
|
||||
63
.vuepress/theme/VersionSelect.vue
Normal file
63
.vuepress/theme/VersionSelect.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div class="version-select custom-select" :tabindex="tabindex" @blur="open = false">
|
||||
<div class="selected" :class="{open: open}" @click="open = !open">
|
||||
<VersionSelectItem :version="selected" />
|
||||
<span class="arrow down"></span>
|
||||
</div>
|
||||
<div class="items" :class="{hidden: !open}">
|
||||
<div
|
||||
class="item"
|
||||
v-for="version in versions"
|
||||
:key="version.name"
|
||||
@click="selected=version; open=false; $emit('input', version.name)"
|
||||
>
|
||||
<VersionSelectItem :version="version" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VersionSelectItem from "./VersionSelectItem.vue";
|
||||
|
||||
export default {
|
||||
name: "VersionSelect",
|
||||
components: { VersionSelectItem },
|
||||
props: {
|
||||
versions: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
tabindex: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
selected:
|
||||
this.versions.find(v => v.name === this.value) ||
|
||||
(this.versions.length > 0 ? this.versions[0] : null),
|
||||
open: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
let version = this.versions.find(v => v.name === this.value);
|
||||
if (version) {
|
||||
this.selected = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$emit("input", this.selected.name);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
32
.vuepress/theme/VersionSelectItem.vue
Normal file
32
.vuepress/theme/VersionSelectItem.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="inline-block">
|
||||
{{ version.name }}
|
||||
<span class="rounded-full px-2 ml-1" :class="classes">{{version.status}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VersionSelectItem from "./VersionSelectItem.vue";
|
||||
|
||||
export default {
|
||||
name: "VersionSelectItem",
|
||||
props: {
|
||||
version: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return (
|
||||
{
|
||||
deprecated: ["text-orange"],
|
||||
current: ["text-green-dark"],
|
||||
stable: ["text-green-dark"],
|
||||
beta: ["text-blue"]
|
||||
}[this.version.status] || ["text-grey"]
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@ -90,6 +90,55 @@ $arrow-bg: #000;
|
||||
&.open .arrow {
|
||||
top: -0.18em;
|
||||
}
|
||||
|
||||
.version-select {
|
||||
@apply .relative .inline-block .text-sm;
|
||||
|
||||
&:focus {
|
||||
@apply .outline-none;
|
||||
}
|
||||
|
||||
.selected {
|
||||
@apply .border .select-none .cursor-pointer .px-4;
|
||||
border-radius: 1rem;
|
||||
|
||||
&.open {
|
||||
@apply .border-blue .outline-none;
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: .5em;
|
||||
right: 10px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 4px solid transparent;
|
||||
border-color: #fff transparent transparent transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.items {
|
||||
@apply .absolute .pin-r .bg-white .border .p-1 .mt-1;
|
||||
border-radius: 1rem;
|
||||
z-index: 100;
|
||||
|
||||
.item {
|
||||
@apply .select-none .rounded-full .cursor-pointer .px-2 .border .border-white;
|
||||
white-space: nowrap;
|
||||
margin-top: .125rem;
|
||||
margin-bottom: .125rem;
|
||||
|
||||
&:hover, &:focus {
|
||||
@apply .bg-grey-lighter;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
@apply .mb-0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-group-items {
|
||||
|
||||
@ -3,32 +3,32 @@ export const extRE = /\.(md|html)$/
|
||||
export const endingSlashRE = /\/$/
|
||||
export const outboundRE = /^(https?:|mailto:|tel:)/
|
||||
|
||||
export function normalize (path) {
|
||||
export function normalize(path) {
|
||||
return decodeURI(path)
|
||||
.replace(hashRE, '')
|
||||
.replace(extRE, '')
|
||||
}
|
||||
|
||||
export function getHash (path) {
|
||||
export function getHash(path) {
|
||||
const match = path.match(hashRE)
|
||||
if (match) {
|
||||
return match[0]
|
||||
}
|
||||
}
|
||||
|
||||
export function isExternal (path) {
|
||||
export function isExternal(path) {
|
||||
return outboundRE.test(path)
|
||||
}
|
||||
|
||||
export function isMailto (path) {
|
||||
export function isMailto(path) {
|
||||
return /^mailto:/.test(path)
|
||||
}
|
||||
|
||||
export function isTel (path) {
|
||||
export function isTel(path) {
|
||||
return /^tel:/.test(path)
|
||||
}
|
||||
|
||||
export function ensureExt (path) {
|
||||
export function ensureExt(path) {
|
||||
if (isExternal(path)) {
|
||||
return path
|
||||
}
|
||||
@ -42,7 +42,7 @@ export function ensureExt (path) {
|
||||
return normalized + '.html' + hash
|
||||
}
|
||||
|
||||
export function isActive (route, path) {
|
||||
export function isActive(route, path) {
|
||||
const routeHash = route.hash
|
||||
const linkHash = getHash(path)
|
||||
if (linkHash && routeHash !== linkHash) {
|
||||
@ -53,7 +53,7 @@ export function isActive (route, path) {
|
||||
return routePath === pagePath
|
||||
}
|
||||
|
||||
export function resolvePage (pages, rawPath, base) {
|
||||
export function resolvePage(pages, rawPath, base) {
|
||||
if (base) {
|
||||
rawPath = resolvePath(rawPath, base)
|
||||
}
|
||||
@ -70,7 +70,7 @@ export function resolvePage (pages, rawPath, base) {
|
||||
return {}
|
||||
}
|
||||
|
||||
function resolvePath (relative, base, append) {
|
||||
function resolvePath(relative, base, append) {
|
||||
const firstChar = relative.charAt(0)
|
||||
if (firstChar === '/') {
|
||||
return relative
|
||||
@ -108,7 +108,7 @@ function resolvePath (relative, base, append) {
|
||||
return stack.join('/')
|
||||
}
|
||||
|
||||
export function resolveSidebarItems (page, route, site, localePath) {
|
||||
export function resolveSidebarItems(page, route, site, localePath) {
|
||||
const { pages, themeConfig } = site
|
||||
|
||||
const localeConfig = localePath && themeConfig.locales
|
||||
@ -131,7 +131,7 @@ export function resolveSidebarItems (page, route, site, localePath) {
|
||||
}
|
||||
}
|
||||
|
||||
function resolveHeaders (page) {
|
||||
function resolveHeaders(page) {
|
||||
const headers = groupHeaders(page.headers || [])
|
||||
return [{
|
||||
type: 'group',
|
||||
@ -147,7 +147,7 @@ function resolveHeaders (page) {
|
||||
}]
|
||||
}
|
||||
|
||||
export function groupHeaders (headers) {
|
||||
export function groupHeaders(headers) {
|
||||
// group h3s under h2
|
||||
headers = headers.map(h => Object.assign({}, h))
|
||||
let lastH2
|
||||
@ -161,13 +161,13 @@ export function groupHeaders (headers) {
|
||||
return headers.filter(h => h.level === 2)
|
||||
}
|
||||
|
||||
export function resolveNavLinkItem (linkItem) {
|
||||
export function resolveNavLinkItem(linkItem) {
|
||||
return Object.assign(linkItem, {
|
||||
type: linkItem.items && linkItem.items.length ? 'links' : 'link'
|
||||
})
|
||||
}
|
||||
|
||||
export function resolveMatchingConfig (route, config) {
|
||||
export function resolveMatchingConfig(route, config) {
|
||||
if (Array.isArray(config)) {
|
||||
return {
|
||||
base: '/',
|
||||
@ -185,13 +185,13 @@ export function resolveMatchingConfig (route, config) {
|
||||
return {}
|
||||
}
|
||||
|
||||
function ensureEndingSlash (path) {
|
||||
function ensureEndingSlash(path) {
|
||||
return /(\.html|\/)$/.test(path)
|
||||
? path
|
||||
: path + '/'
|
||||
}
|
||||
|
||||
function resolveItem (item, pages, base, isNested) {
|
||||
function resolveItem(item, pages, base, isNested) {
|
||||
if (typeof item === 'string') {
|
||||
return resolvePage(pages, item, base)
|
||||
} else if (Array.isArray(item)) {
|
||||
@ -206,11 +206,18 @@ function resolveItem (item, pages, base, isNested) {
|
||||
)
|
||||
}
|
||||
const children = item.children || []
|
||||
const versions = item.versions || []
|
||||
return {
|
||||
type: 'group',
|
||||
title: item.title,
|
||||
...item,
|
||||
children: children.map(child => resolveItem(child, pages, base, true)),
|
||||
collapsable: item.collapsable !== false
|
||||
collapsable: item.collapsable !== false,
|
||||
versions: versions.map(version => ({
|
||||
...version,
|
||||
status: version.name === item.currentVersion ? "current" : version.status,
|
||||
children: version.children.map(child => resolveItem(item.path + version.name + child, pages, base, true))
|
||||
})),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ Once you have done that there will be a tab called Configuration when you view t
|
||||
Simply copy and paste the code block and paste it into a file called `core.json` in `/srv/daemon/config` and save it.
|
||||
You may also use the Auto-Deployment feature rather than manually creating the files.
|
||||
|
||||

|
||||

|
||||
|
||||
## Starting the Daemon
|
||||
To start your daemon simply move into the daemon directory and run the command below which will start the daemon in
|
||||
@ -1,5 +1,7 @@
|
||||
# Getting Started
|
||||
|
||||
BETA
|
||||
|
||||
[[toc]]
|
||||
|
||||
Pterodactyl Panel is designed to run on your own web server. You will need to have root access to your server in order to run and use this panel.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user