mirror of https://github.com/Requarks/wiki.git
31 changed files with 1015 additions and 71 deletions
Split View
Diff Options
-
57.babelrc
-
1.gitignore
-
93client/components/admin/admin-locale.vue
-
4client/components/admin/admin-utilities-auth.vue
-
4client/components/admin/admin-utilities-cache.vue
-
68client/components/admin/admin-utilities-content.vue
-
7client/components/admin/admin-utilities.vue
-
4client/components/common/search-results.vue
-
2client/components/editor/editor-markdown.vue
-
1client/graph/admin/locale/locale-query-list.gql
-
12client/graph/admin/utilities/utilities-mutation-content-migratelocale.gql
-
3client/index-legacy.js
-
3client/index-setup.js
-
2client/scss/app.scss
-
218client/scss/legacy.scss
-
2client/themes/default/components/page.vue
-
127dev/templates/legacy.pug
-
12dev/webpack/webpack.dev.js
-
12dev/webpack/webpack.prod.js
-
10package.json
-
10server/controllers/common.js
-
13server/db/migrations-sqlite/2.0.0-beta.217.js
-
13server/db/migrations/2.0.0-beta.217.js
-
2server/graph/resolvers/localization.js
-
10server/graph/resolvers/page.js
-
1server/graph/schemas/localization.graphql
-
2server/graph/schemas/page.graphql
-
27server/jobs/fetch-graph-locale.js
-
8server/jobs/sync-graph-locales.js
-
3server/models/locales.js
-
355yarn.lock
@ -0,0 +1,68 @@ |
|||
<template lang='pug'> |
|||
v-card |
|||
v-toolbar(flat, color='primary', dark, dense) |
|||
.subheading {{ $t('admin:utilities.contentTitle') }} |
|||
v-card-text |
|||
v-subheader.pl-0.primary--text Migrate all pages to base language |
|||
.body-1 If you created content before selecting a different locale and activating the namespacing capabilities, you may want to transfer all content to the base locale. |
|||
.body-1.red--text: strong This operation is destructive and cannot be reversed! Make sure you have proper backups! |
|||
.body-1.mt-3 Based on your current configuration, all pages will be migrated to the locale #[v-chip(label, small): strong {{currentLocale.toUpperCase()}}] |
|||
.body-1.mt-3 Pages that are already in the target locale will not be touched. If a page already exists at the target, the source page will not be modified as it would create a conflict. If you want to overwrite the target content, you must first delete that page. |
|||
v-btn(outline, color='primary', @click='migrateToLocale', :disabled='loading').ml-0.mt-3 |
|||
v-icon(left) build |
|||
span Proceed |
|||
</template> |
|||
|
|||
<script> |
|||
import _ from 'lodash' |
|||
import utilityContentMigrateLocaleMutation from 'gql/admin/utilities/utilities-mutation-content-migratelocale.gql' |
|||
|
|||
/* global siteLang */ |
|||
|
|||
export default { |
|||
data: () => { |
|||
return { |
|||
loading: false |
|||
} |
|||
}, |
|||
computed: { |
|||
currentLocale() { |
|||
return siteConfig.lang |
|||
} |
|||
}, |
|||
methods: { |
|||
async migrateToLocale() { |
|||
this.loading = true |
|||
this.$store.commit(`loadingStart`, 'admin-utilities-content-migratelocale') |
|||
|
|||
try { |
|||
const respRaw = await this.$apollo.mutate({ |
|||
mutation: utilityContentMigrateLocaleMutation, |
|||
variables: { |
|||
targetLocale: siteConfig.lang |
|||
} |
|||
}) |
|||
const resp = _.get(respRaw, 'data.pages.migrateToLocale.responseResult', {}) |
|||
if (resp.succeeded) { |
|||
this.$store.commit('showNotification', { |
|||
message: 'Migrated all content to target locale successfully.', |
|||
style: 'success', |
|||
icon: 'check' |
|||
}) |
|||
} else { |
|||
throw new Error(resp.message) |
|||
} |
|||
} catch (err) { |
|||
this.$store.commit('pushGraphError', err) |
|||
} |
|||
|
|||
this.$store.commit(`loadingStop`, 'admin-utilities-content-migratelocale') |
|||
this.loading = false |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang='scss'> |
|||
|
|||
</style> |
@ -0,0 +1,12 @@ |
|||
mutation { |
|||
pages { |
|||
migrateToLocale { |
|||
responseResult { |
|||
succeeded |
|||
errorCode |
|||
slug |
|||
message |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,3 @@ |
|||
require('./scss/legacy.scss') |
|||
|
|||
window.WIKI = null |
@ -0,0 +1,218 @@ |
|||
@import "global"; |
|||
|
|||
@import "./base/fonts.scss"; |
|||
@import "./base/icons.scss"; |
|||
|
|||
html { |
|||
box-sizing: border-box; |
|||
background-color: mc('grey', '50'); |
|||
font-size: 14px; |
|||
} |
|||
*, *:before, *:after { |
|||
box-sizing: inherit; |
|||
} |
|||
* { |
|||
margin: 0; |
|||
padding: 0; |
|||
} |
|||
|
|||
.is-hidden { |
|||
display: none; |
|||
} |
|||
|
|||
body { |
|||
margin: 0; |
|||
padding: 0; |
|||
font-family: "Roboto",sans-serif; |
|||
line-height: 1.5; |
|||
min-height: 100vh; |
|||
} |
|||
|
|||
.header { |
|||
background-color: #000; |
|||
color: #FFF; |
|||
height: 64px; |
|||
padding: 0 16px; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
|
|||
&-title { |
|||
margin: 0; |
|||
font-size: 16px; |
|||
font-weight: 500; |
|||
letter-spacing: .02em; |
|||
} |
|||
|
|||
&-deprecated { |
|||
color: mc('red', '100'); |
|||
|
|||
a { |
|||
color: mc('pink', '400'); |
|||
} |
|||
} |
|||
|
|||
&-login { |
|||
a { |
|||
text-decoration: none; |
|||
color: #FFF; |
|||
transition: color .3s ease; |
|||
|
|||
&:hover { |
|||
color: mc('blue', '500'); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.main { |
|||
display: flex; |
|||
align-items: stretch; |
|||
min-height: calc(100vh - 64px); |
|||
height: 50vh; |
|||
|
|||
&-container { |
|||
flex-grow: 1; |
|||
} |
|||
} |
|||
|
|||
.sidebar { |
|||
width: 300px; |
|||
background-color: mc('blue', '700'); |
|||
color: #FFF; |
|||
padding: 8px 0; |
|||
|
|||
.sidebar-link { |
|||
height: 40px; |
|||
font-size: 13px; |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 0 16px; |
|||
transition: background .3s cubic-bezier(.25,.8,.5,1); |
|||
font-weight: 400; |
|||
color: #FFF; |
|||
text-decoration: none; |
|||
|
|||
&:hover { |
|||
background: hsla(0,0%,100%,.08); |
|||
} |
|||
} |
|||
|
|||
i.material-icons { |
|||
width: 56px; |
|||
padding-left: 8px; |
|||
} |
|||
|
|||
.sidebar-divider { |
|||
border-top: 1px solid hsla(0,0%,100%,.12); |
|||
margin: 8px 0; |
|||
} |
|||
|
|||
.sidebar-title { |
|||
font-size: 13px; |
|||
height: 40px; |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 0 16px 0 24px; |
|||
font-weight: 500; |
|||
color: hsla(0,0%,100%,.7); |
|||
} |
|||
} |
|||
|
|||
.page-header { |
|||
background-color: mc('grey', '100'); |
|||
padding: 0 24px; |
|||
height: 90px; |
|||
display: flex; |
|||
align-items: center; |
|||
border-bottom: 1px solid mc('grey', '200'); |
|||
|
|||
h1 { |
|||
font-size: 24px; |
|||
font-weight: 400; |
|||
line-height: 32px; |
|||
color: mc('grey', '800'); |
|||
} |
|||
|
|||
h2 { |
|||
color: mc('grey', '600'); |
|||
font-size: 12px; |
|||
font-weight: 400; |
|||
} |
|||
|
|||
&-left { |
|||
flex-grow: 1; |
|||
} |
|||
|
|||
&-right { |
|||
flex: 0 0 324px; |
|||
padding-left: 16px; |
|||
|
|||
&-title { |
|||
color: mc('grey', '500'); |
|||
font-size: 12px; |
|||
} |
|||
&-author { |
|||
color: mc('grey', '800'); |
|||
font-weight: 500; |
|||
} |
|||
&-updated { |
|||
color: mc('grey', '600'); |
|||
font-size: 12px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.page-contents { |
|||
display: flex; |
|||
} |
|||
|
|||
.toc { |
|||
flex: 0 0 348px; |
|||
background-color: mc('grey', '200'); |
|||
padding: 4px 0; |
|||
|
|||
&-title { |
|||
font-size: 13px; |
|||
height: 40px; |
|||
display: flex; |
|||
color: mc('blue', '600'); |
|||
align-items: center; |
|||
font-weight: 500; |
|||
padding: 0 16px; |
|||
} |
|||
|
|||
&-tile { |
|||
text-decoration: none; |
|||
height: 40px; |
|||
display: flex; |
|||
font-size: 13px; |
|||
align-items: center; |
|||
padding: 0 16px; |
|||
color: mc('grey', '800'); |
|||
transition: background-color .3s ease; |
|||
|
|||
&.inset { |
|||
padding-left: 32px; |
|||
} |
|||
|
|||
&:hover { |
|||
background-color: rgba(0,0,0,.06); |
|||
} |
|||
} |
|||
|
|||
&-divider { |
|||
border-top: 1px solid rgba(0,0,0,.12); |
|||
margin: 0 0 0 24px; |
|||
|
|||
&.inset { |
|||
margin-left: 40px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@import "../themes/default/scss/app.scss"; |
|||
|
|||
.contents { |
|||
flex-grow: 1; |
|||
} |
@ -0,0 +1,127 @@ |
|||
doctype html |
|||
html |
|||
head |
|||
meta(http-equiv='X-UA-Compatible', content='IE=edge') |
|||
meta(charset='UTF-8') |
|||
meta(name='viewport', content='user-scalable=yes, width=device-width, initial-scale=1, maximum-scale=5') |
|||
meta(name='theme-color', content='#333333') |
|||
meta(name='msapplication-TileColor', content='#333333') |
|||
meta(name='msapplication-TileImage', content='/favicons/ms-icon-144x144.png') |
|||
|
|||
title= pageMeta.title + ' | ' + config.title |
|||
|
|||
//- SEO / OpenGraph |
|||
meta(name='description', content=pageMeta.description) |
|||
meta(property='og:title', content=pageMeta.title) |
|||
meta(property='og:type', content='website') |
|||
meta(property='og:description', content=pageMeta.description) |
|||
meta(property='og:image', content=pageMeta.image) |
|||
meta(property='og:url', content=pageMeta.url) |
|||
meta(property='og:site_name', content=config.title) |
|||
|
|||
//- Favicon |
|||
each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180] |
|||
link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href='/favicons/apple-icon-' + favsize + 'x' + favsize + '.png') |
|||
link(rel='icon', type='image/png', sizes='192x192', href='/favicons/android-icon-192x192.png') |
|||
each favsize in [32, 96, 16] |
|||
link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href='/favicons/favicon-' + favsize + 'x' + favsize + '.png') |
|||
link(rel='manifest', href='/manifest.json') |
|||
|
|||
//- CSS |
|||
<% for (var index in htmlWebpackPlugin.files.css) { %> |
|||
<% if (htmlWebpackPlugin.files.cssIntegrity) { %> |
|||
link( |
|||
type='text/css' |
|||
rel='stylesheet' |
|||
href='<%= htmlWebpackPlugin.files.css[index] %>' |
|||
integrity='<%= htmlWebpackPlugin.files.cssIntegrity[index] %>' |
|||
crossorigin='<%= webpackConfig.output.crossOriginLoading %>' |
|||
) |
|||
<% } else { %> |
|||
link( |
|||
type='text/css' |
|||
rel='stylesheet' |
|||
href='<%= htmlWebpackPlugin.files.css[index] %>' |
|||
) |
|||
<% } %> |
|||
<% } %> |
|||
|
|||
script( |
|||
crossorigin='anonymous' |
|||
src='https://polyfill.io/v3/polyfill.min.js?features=EventSource' |
|||
) |
|||
|
|||
//- JS |
|||
<% for (var index in htmlWebpackPlugin.files.js) { %> |
|||
<% if (htmlWebpackPlugin.files.cssIntegrity) { %> |
|||
script( |
|||
type='text/javascript' |
|||
src='<%= htmlWebpackPlugin.files.js[index] %>' |
|||
integrity='<%= htmlWebpackPlugin.files.jsIntegrity[index] %>' |
|||
crossorigin='<%= webpackConfig.output.crossOriginLoading %>' |
|||
) |
|||
<% } else { %> |
|||
script( |
|||
type='text/javascript' |
|||
src='<%= htmlWebpackPlugin.files.js[index] %>' |
|||
) |
|||
<% } %> |
|||
<% } %> |
|||
|
|||
!= analyticsCode.head |
|||
|
|||
if injectCode.css |
|||
style(type='text/css')!= injectCode.css |
|||
if injectCode.head |
|||
!= injectCode.head |
|||
|
|||
body |
|||
!= analyticsCode.bodyStart |
|||
#root |
|||
.header |
|||
span.header-title= siteConfig.title |
|||
span.header-deprecated Your browser is outdated. Upgrade to a #[a(href='https://bestvpn.org/outdatedbrowser/en', rel='nofollow') modern browser]. |
|||
span.header-login |
|||
a(href='/login') |
|||
i.material-icons account_circle |
|||
.main |
|||
.sidebar |
|||
each navItem in sidebar |
|||
if navItem.kind === 'link' |
|||
a.sidebar-link(href=navItem.target) |
|||
i.material-icons= navItem.icon |
|||
span= navItem.label |
|||
else if navItem.kind === 'divider' |
|||
.sidebar-divider |
|||
else if navItem.kind === 'header' |
|||
.sidebar-title= navItem.label |
|||
.main-container |
|||
.page-header |
|||
.page-header-left |
|||
h1= page.title |
|||
h2= page.description |
|||
.page-header-right |
|||
.page-header-right-title Last edited by |
|||
.page-header-right-author= page.authorName |
|||
.page-header-right-updated= page.updatedAt |
|||
.page-contents |
|||
.contents |
|||
div!= page.render |
|||
if page.toc.length |
|||
.toc |
|||
.toc-title Table of Contents |
|||
each tocItem, tocIdx in page.toc |
|||
a.toc-tile(href='#' + tocItem.anchor) |
|||
i.material-icons arrow_right |
|||
span= tocItem.title |
|||
if tocIdx < page.toc.length - 1 || tocItem.children.length |
|||
.toc-divider |
|||
each tocSubItem in tocItem.children |
|||
a.toc-tile.inset(href='#' + tocSubItem.anchor) |
|||
i.material-icons arrow_right |
|||
span= tocSubItem.title |
|||
if tocIdx < page.toc.length - 1 |
|||
.toc-divider.inset |
|||
if injectCode.body |
|||
!= injectCode.body |
|||
!= analyticsCode.bodyEnd |
@ -0,0 +1,13 @@ |
|||
exports.up = knex => { |
|||
return knex.schema |
|||
.table('locales', table => { |
|||
table.integer('availability').notNullable().defaultTo(0) |
|||
}) |
|||
} |
|||
|
|||
exports.down = knex => { |
|||
return knex.schema |
|||
.table('locales', table => { |
|||
table.dropColumn('availability') |
|||
}) |
|||
} |
@ -0,0 +1,13 @@ |
|||
exports.up = knex => { |
|||
return knex.schema |
|||
.table('locales', table => { |
|||
table.integer('availability').notNullable().defaultTo(0) |
|||
}) |
|||
} |
|||
|
|||
exports.down = knex => { |
|||
return knex.schema |
|||
.table('locales', table => { |
|||
table.dropColumn('availability') |
|||
}) |
|||
} |
Write
Preview
Loading…
Cancel
Save