nav tabs on admin dashboard

This commit is contained in:
2019-03-07 00:20:34 -06:00
parent f73d6ae228
commit e4f473f376
11661 changed files with 216240 additions and 1544253 deletions

View File

@@ -11,11 +11,12 @@ import type { ParsedTemplate } from './parse-template'
import type { AsyncFileMapper } from './create-async-file-mapper'
type TemplateRendererOptions = {
template: ?string;
template?: string | (content: string, context: any) => string;
inject?: boolean;
clientManifest?: ClientManifest;
shouldPreload?: (file: string, type: string) => boolean;
shouldPrefetch?: (file: string, type: string) => boolean;
serializer?: Function;
};
export type ClientManifest = {
@@ -41,26 +42,39 @@ type Resource = {
export default class TemplateRenderer {
options: TemplateRendererOptions;
inject: boolean;
parsedTemplate: ParsedTemplate | null;
parsedTemplate: ParsedTemplate | Function | null;
publicPath: string;
clientManifest: ClientManifest;
preloadFiles: Array<Resource>;
prefetchFiles: Array<Resource>;
mapFiles: AsyncFileMapper;
serialize: Function;
constructor (options: TemplateRendererOptions) {
this.options = options
this.inject = options.inject !== false
// if no template option is provided, the renderer is created
// as a utility object for rendering assets like preload links and scripts.
this.parsedTemplate = options.template
? parseTemplate(options.template)
const { template } = options
this.parsedTemplate = template
? typeof template === 'string'
? parseTemplate(template)
: template
: null
// function used to serialize initial state JSON
this.serialize = options.serializer || (state => {
return serialize(state, { isJSON: true })
})
// extra functionality with client manifest
if (options.clientManifest) {
const clientManifest = this.clientManifest = options.clientManifest
this.publicPath = clientManifest.publicPath.replace(/\/$/, '')
// ensure publicPath ends with /
this.publicPath = clientManifest.publicPath === ''
? ''
: clientManifest.publicPath.replace(/([^\/])$/, '$1/')
// preload/prefetch directives
this.preloadFiles = (clientManifest.initial || []).map(normalizeFile)
this.prefetchFiles = (clientManifest.async || []).map(normalizeFile)
@@ -79,12 +93,17 @@ export default class TemplateRenderer {
}
// render synchronously given rendered app content and render context
renderSync (content: string, context: ?Object) {
render (content: string, context: ?Object): string | Promise<string> {
const template = this.parsedTemplate
if (!template) {
throw new Error('renderSync cannot be called without a template.')
throw new Error('render cannot be called without a template.')
}
context = context || {}
if (typeof template === 'function') {
return template(content, context)
}
if (this.inject) {
return (
template.head(context) +
@@ -108,13 +127,13 @@ export default class TemplateRenderer {
}
renderStyles (context: Object): string {
const cssFiles = this.clientManifest
? this.clientManifest.all.filter(isCSS)
: []
const initial = this.preloadFiles || []
const async = this.getUsedAsyncFiles(context) || []
const cssFiles = initial.concat(async).filter(({ file }) => isCSS(file))
return (
// render links for css files
(cssFiles.length
? cssFiles.map(file => `<link rel="stylesheet" href="${this.publicPath}/${file}">`).join('')
? cssFiles.map(({ file }) => `<link rel="stylesheet" href="${this.publicPath}${file}">`).join('')
: '') +
// context.styles is a getter exposed by vue-style-loader which contains
// the inline component styles collected during SSR
@@ -153,7 +172,7 @@ export default class TemplateRenderer {
extra = ` type="font/${extension}" crossorigin`
}
return `<link rel="preload" href="${
this.publicPath}/${file
this.publicPath}${file
}"${
asType !== '' ? ` as="${asType}"` : ''
}${
@@ -179,7 +198,7 @@ export default class TemplateRenderer {
if (alreadyRendered(file)) {
return ''
}
return `<link rel="prefetch" href="${this.publicPath}/${file}">`
return `<link rel="prefetch" href="${this.publicPath}${file}">`
}).join('')
} else {
return ''
@@ -191,22 +210,23 @@ export default class TemplateRenderer {
contextKey = 'state',
windowKey = '__INITIAL_STATE__'
} = options || {}
const state = serialize(context[contextKey], { isJSON: true })
const state = this.serialize(context[contextKey])
const autoRemove = process.env.NODE_ENV === 'production'
? ';(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());'
: ''
const nonceAttr = context.nonce ? ` nonce="${context.nonce}"` : ''
return context[contextKey]
? `<script>window.${windowKey}=${state}${autoRemove}</script>`
? `<script${nonceAttr}>window.${windowKey}=${state}${autoRemove}</script>`
: ''
}
renderScripts (context: Object): string {
if (this.clientManifest) {
const initial = this.preloadFiles
const async = this.getUsedAsyncFiles(context)
const needed = [initial[0]].concat(async || [], initial.slice(1))
return needed.filter(({ file }) => isJS(file)).map(({ file }) => {
return `<script src="${this.publicPath}/${file}" defer></script>`
const initial = this.preloadFiles.filter(({ file }) => isJS(file))
const async = (this.getUsedAsyncFiles(context) || []).filter(({ file }) => isJS(file))
const needed = [initial[0]].concat(async, initial.slice(1))
return needed.map(({ file }) => {
return `<script src="${this.publicPath}${file}" defer></script>`
}).join('')
} else {
return ''