45 changed files with 13765 additions and 0 deletions
Split View
Diff Options
-
18webapp/.eslintrc.js
-
88webapp/.gitignore
-
22webapp/README.md
-
7webapp/assets/README.md
-
1webapp/assets/variables.scss
-
106webapp/components/FormGen/FormGen.vue
-
118webapp/components/MediaUploader.vue
-
7webapp/components/README.md
-
168webapp/components/SelectApi.vue
-
166webapp/components/TemplateEditor/TemplateEditor.vue
-
94webapp/components/TemplateEditor/modals/TeAddSection.vue
-
14webapp/components/TemplateEditor/widgets/TeImg.vue
-
113webapp/components/TemplateEditor/widgets/TeSection.vue
-
12webapp/components/TemplateEditor/widgets/TeText.vue
-
5webapp/config.js
-
7webapp/layouts/README.md
-
100webapp/layouts/admin.vue
-
117webapp/layouts/default.ori.vue
-
74webapp/layouts/default.vue
-
44webapp/layouts/error.vue
-
8webapp/middleware/README.md
-
6webapp/middleware/renderer.js
-
92webapp/nuxt.config.js
-
11467webapp/package-lock.json
-
29webapp/package.json
-
6webapp/pages/README.md
-
40webapp/pages/admin/index.vue
-
33webapp/pages/admin/landingpage/_id.vue
-
94webapp/pages/admin/landingpage/index.vue
-
99webapp/pages/admin/resources/_rsc/_id.vue
-
199webapp/pages/admin/resources/_rsc/index.vue
-
53webapp/pages/admin/resources/index.vue
-
217webapp/pages/index.vue
-
19webapp/pages/inspire.vue
-
7webapp/plugins/README.md
-
19webapp/plugins/vuetify-confirm.js
-
11webapp/static/README.md
-
BINwebapp/static/favicon.ico
-
BINwebapp/static/v.png
-
10webapp/store/README.md
-
5webapp/store/admin/landingpage.js
-
5webapp/store/admin/resources.js
-
43webapp/store/admin/ui.js
-
13webapp/store/index.js
-
9webapp/store/ui/index.js
@ -0,0 +1,18 @@ |
|||
module.exports = { |
|||
root: true, |
|||
env: { |
|||
browser: true, |
|||
node: true |
|||
}, |
|||
parserOptions: { |
|||
parser: 'babel-eslint' |
|||
}, |
|||
extends: [ |
|||
'@nuxtjs', |
|||
'plugin:nuxt/recommended' |
|||
], |
|||
// add your custom rules here
|
|||
rules: { |
|||
"vue/attribute-hyphenation": "never" |
|||
} |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
# Created by .ignore support plugin (hsz.mobi) |
|||
### Node template |
|||
# Logs |
|||
logs |
|||
*.log |
|||
npm-debug.log* |
|||
yarn-debug.log* |
|||
yarn-error.log* |
|||
|
|||
# Runtime data |
|||
pids |
|||
*.pid |
|||
*.seed |
|||
*.pid.lock |
|||
|
|||
# Directory for instrumented libs generated by jscoverage/JSCover |
|||
lib-cov |
|||
|
|||
# Coverage directory used by tools like istanbul |
|||
coverage |
|||
|
|||
# nyc test coverage |
|||
.nyc_output |
|||
|
|||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) |
|||
.grunt |
|||
|
|||
# Bower dependency directory (https://bower.io/) |
|||
bower_components |
|||
|
|||
# node-waf configuration |
|||
.lock-wscript |
|||
|
|||
# Compiled binary addons (https://nodejs.org/api/addons.html) |
|||
build/Release |
|||
|
|||
# Dependency directories |
|||
node_modules/ |
|||
jspm_packages/ |
|||
|
|||
# TypeScript v1 declaration files |
|||
typings/ |
|||
|
|||
# Optional npm cache directory |
|||
.npm |
|||
|
|||
# Optional eslint cache |
|||
.eslintcache |
|||
|
|||
# Optional REPL history |
|||
.node_repl_history |
|||
|
|||
# Output of 'npm pack' |
|||
*.tgz |
|||
|
|||
# Yarn Integrity file |
|||
.yarn-integrity |
|||
|
|||
# dotenv environment variables file |
|||
.env |
|||
|
|||
# parcel-bundler cache (https://parceljs.org/) |
|||
.cache |
|||
|
|||
# next.js build output |
|||
.next |
|||
|
|||
# nuxt.js build output |
|||
.nuxt |
|||
|
|||
# Nuxt generate |
|||
dist |
|||
|
|||
# vuepress build output |
|||
.vuepress/dist |
|||
|
|||
# Serverless directories |
|||
.serverless |
|||
|
|||
# IDE / Editor |
|||
.idea |
|||
.editorconfig |
|||
|
|||
# Service worker |
|||
sw.* |
|||
|
|||
# Mac OSX |
|||
.DS_Store |
|||
@ -0,0 +1,22 @@ |
|||
# artifex |
|||
|
|||
> An artifex world for noob |
|||
|
|||
## Build Setup |
|||
|
|||
``` bash |
|||
# install dependencies |
|||
$ npm run install |
|||
|
|||
# serve with hot reload at localhost:3000 |
|||
$ npm run dev |
|||
|
|||
# build for production and launch server |
|||
$ npm run build |
|||
$ npm run start |
|||
|
|||
# generate static project |
|||
$ npm run generate |
|||
``` |
|||
|
|||
For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org). |
|||
@ -0,0 +1,7 @@ |
|||
# ASSETS |
|||
|
|||
**This directory is not required, you can delete it if you don't want to use it.** |
|||
|
|||
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. |
|||
|
|||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked). |
|||
@ -0,0 +1 @@ |
|||
$font-size-root: 20px; |
|||
@ -0,0 +1,106 @@ |
|||
<template> |
|||
<v-form ref="formGen" lazy-loading> |
|||
<v-layout> |
|||
<v-flex v-for="(row, idx) in form" :key="`row-${idx}`"> |
|||
<v-layout column mx-3> |
|||
<v-flex v-for="input in row.list" :key="input.field"> |
|||
<v-text-field |
|||
v-if="input.type === 'text'" |
|||
v-model="doc[input.field]" |
|||
:label="input.label" |
|||
:disabled="input.disabled || disabled" |
|||
:rules="getRules(input)" |
|||
@change="triggerUp()" |
|||
/> |
|||
|
|||
<v-select |
|||
v-if="input.type === 'select'" |
|||
v-model="doc[input.field]" |
|||
:label="input.label" |
|||
:items="input.items" |
|||
:disabled="input.disabled || disabled" |
|||
:multiple="input.multiple" |
|||
item-text="label" |
|||
@change="triggerUp()" |
|||
/> |
|||
|
|||
<media-uploader |
|||
v-if="input.type === 'media'" |
|||
v-model="doc[input.field]" |
|||
:disabled="input.disabled || disabled" |
|||
:doc-coll="coll.type" |
|||
:doc-id="coll.id" |
|||
:doc-path="input.field" |
|||
@change="triggerUp()" |
|||
/> |
|||
|
|||
<select-api |
|||
v-if="input.type === 'select-api'" |
|||
v-model="doc[input.field]" |
|||
:label="input.label" |
|||
:collection="input.items" |
|||
:multiple="input.multiple" |
|||
@change="triggerUp()" |
|||
/> |
|||
|
|||
<v-textarea |
|||
v-if="input.type === 'textarea'" |
|||
v-model="doc[input.field]" |
|||
:label="input.label" |
|||
:disabled="input.disabled || disabled" |
|||
@change="triggerUp()" |
|||
/> |
|||
</v-flex> |
|||
</v-layout> |
|||
</v-flex> |
|||
</v-layout> |
|||
</v-form> |
|||
</template> |
|||
|
|||
<script> |
|||
import MediaUploader from '@/components/MediaUploader.vue' |
|||
import SelectApi from '@/components/SelectApi.vue' |
|||
|
|||
export default { |
|||
name: 'FormGen', |
|||
components: { MediaUploader, SelectApi }, |
|||
props: { |
|||
value: { type: Object, default: () => {} }, |
|||
more: { type: String, default: null }, |
|||
form: { type: Array, default: () => {} }, |
|||
coll: { type: Object, default: null }, |
|||
disabled: { type: Boolean, default: false } |
|||
}, |
|||
data: () => ({ |
|||
doc: {} |
|||
}), |
|||
mounted () { |
|||
if (this.more) { |
|||
this.value[this.more] = this.value[this.more] || {} |
|||
this.doc = this.value[this.more] |
|||
} else { |
|||
this.doc = this.value |
|||
} |
|||
}, |
|||
methods: { |
|||
getRules (input) { |
|||
if (!input.rules) { return [] } |
|||
const rules = [] |
|||
if (input.rules.required) { |
|||
rules.push(v => !!v || input.rules.required) |
|||
} |
|||
if (input.rules.regex) { |
|||
const aRegex = input.rules.regex.split(';') |
|||
const nRegex = new RegExp(aRegex[0], aRegex[1]) |
|||
rules.push(v => nRegex.test(v) || aRegex[2] || 'Field must be valid') |
|||
} |
|||
return rules |
|||
}, |
|||
triggerUp () { |
|||
const valid = this.$refs.formGen.validate() |
|||
this.$emit('update') |
|||
this.$emit('valid', valid) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,118 @@ |
|||
<template> |
|||
<div> |
|||
<v-layout |
|||
ref="upload-area" |
|||
class="upload-area" |
|||
:style="{cursor: disabled ? 'not-allowed' : 'pointer'}" |
|||
align-center |
|||
justify-center |
|||
row |
|||
fill-height |
|||
@click="selectMedia" |
|||
> |
|||
<v-flex xs12 style="text-align: center"> |
|||
<span v-if="disabled" /> |
|||
<span v-else-if="!uploadOnGoing">Upload one media</span> |
|||
<span v-else>Uploading {{ percent }}%</span> |
|||
</v-flex> |
|||
</v-layout> |
|||
<div class="upload-note"> |
|||
{{ note }} |
|||
</div> |
|||
<input ref="uploader" type="file" style="display:none" @change="onMediaSelected"> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import cfg from '@/config' |
|||
|
|||
export default { |
|||
model: { prop: 'mid', event: 'change' }, |
|||
props: { |
|||
mid: { type: String, default: '' }, |
|||
docColl: { type: String, default: '' }, |
|||
docId: { type: String, default: '' }, |
|||
docPath: { type: String, default: '' }, |
|||
disabled: { type: Boolean, default: false } |
|||
}, |
|||
data: () => ({ |
|||
uploadOnGoing: false, |
|||
percent: 0, |
|||
selectedMedia: null, |
|||
mediaId: null, |
|||
mediaInfo: null |
|||
}), |
|||
computed: { |
|||
note () { |
|||
return this.mediaInfo ? this.mediaInfo.originalName : '' |
|||
} |
|||
}, |
|||
watch: { |
|||
mid (val) { |
|||
if (!val) { return } |
|||
this.mediaId = val |
|||
this.updateBg() |
|||
} |
|||
}, |
|||
mounted () {}, |
|||
methods: { |
|||
updateBg () { |
|||
if (!this.mediaId) { return } |
|||
this.$refs['upload-area'].style.backgroundImage = `url('${cfg.serverUrl}/media/preview/${this.mediaId}?height=120×tamp=${(new Date()).getTime()}')` |
|||
this.$axios |
|||
.get(`${cfg.serverUrl}/api/media/${this.mediaId}`) |
|||
.then((res) => { |
|||
this.mediaInfo = res.data.data |
|||
}) |
|||
}, |
|||
onMediaSelected (event) { |
|||
this.selectedMedia = event.target.files[0] |
|||
this.uploadOnGoing = true |
|||
this.percent = 0 |
|||
|
|||
const formData = new FormData() |
|||
formData.append('media', this.selectedMedia, this.selectedMedia.name) |
|||
formData.append('docColl', this.docColl || '') |
|||
formData.append('docId', this.docId || '') |
|||
formData.append('docPath', this.docPath || '') |
|||
|
|||
this.$axios |
|||
.post(`${cfg.serverUrl}/media/upload`, formData, { |
|||
onUploadProgress: (progressEvent) => { |
|||
this.percent = Math.ceil(progressEvent.loaded / progressEvent.total * 100) |
|||
} |
|||
}) |
|||
.then((pRes) => { |
|||
this.uploadOnGoing = false |
|||
this.selectedMedia = null |
|||
this.mediaId = pRes.data.mediaId |
|||
this.$emit('change', this.mediaId) |
|||
this.updateBg() |
|||
}) |
|||
.catch((pRes) => { |
|||
this.uploadOnGoing = false |
|||
this.selectedMedia = null |
|||
}) |
|||
}, |
|||
selectMedia () { |
|||
if (this.disabled) { return } |
|||
if (this.uploadOnGoing) { return } |
|||
this.$refs.uploader.click() |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.upload-area { |
|||
height: 120px; |
|||
background: #CCC; |
|||
box-shadow: 0 0 8px #666 inset; |
|||
background-repeat: no-repeat; |
|||
background-position: center; |
|||
background-size: contain; |
|||
} |
|||
.upload-note { |
|||
color: #AAA; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,7 @@ |
|||
# COMPONENTS |
|||
|
|||
**This directory is not required, you can delete it if you don't want to use it.** |
|||
|
|||
The components directory contains your Vue.js Components. |
|||
|
|||
_Nuxt.js doesn't supercharge these components._ |
|||
@ -0,0 +1,168 @@ |
|||
<template> |
|||
<v-layout column> |
|||
<v-flex> |
|||
<v-subheader>{{ label }}</v-subheader> |
|||
</v-flex> |
|||
<v-flex> |
|||
<v-list dense> |
|||
<v-list-item |
|||
v-for="item in doc" |
|||
:key="item.key" |
|||
> |
|||
<v-list-item-content> |
|||
<v-list-item-title v-text="item.label" /> |
|||
</v-list-item-content> |
|||
|
|||
<v-list-item-action style="margin:0"> |
|||
<v-layout> |
|||
<v-flex> |
|||
<v-btn small icon @click="viewItem(item)"> |
|||
<v-icon>mdi-eye</v-icon> |
|||
</v-btn> |
|||
</v-flex> |
|||
<v-flex> |
|||
<v-btn small icon @click="deleteItem(item)"> |
|||
<v-icon>mdi-delete</v-icon> |
|||
</v-btn> |
|||
</v-flex> |
|||
</v-layout> |
|||
</v-list-item-action> |
|||
</v-list-item> |
|||
</v-list> |
|||
</v-flex> |
|||
<v-flex class="text-center"> |
|||
<v-btn v-if="mode !== 'adding' && canAdd" @click="add()"> |
|||
<v-icon>mdi-plus-circle-outline</v-icon> |
|||
</v-btn> |
|||
|
|||
<v-autocomplete |
|||
v-if="mode === 'adding'" |
|||
v-model="selectedItem" |
|||
:items="items" |
|||
:search-input.sync="search" |
|||
:loading="isLoading" |
|||
cache-items |
|||
item-text="name" |
|||
item-value="_id" |
|||
hide-no-data |
|||
hide-details |
|||
label="Find" |
|||
@change="addItem" |
|||
/> |
|||
</v-flex> |
|||
</v-layout> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
model: { prop: 'value', event: 'change' }, |
|||
props: { |
|||
value: { type: Array, default: () => [] }, |
|||
label: { type: String, default: 'SelectApi' }, |
|||
collection: { type: String, default: '', required: true }, |
|||
multiple: { type: [Number, Boolean], default: false } |
|||
}, |
|||
data: () => ({ |
|||
mode: '', |
|||
items: [], |
|||
isLoading: false, |
|||
selectedItem: null, |
|||
search: '', |
|||
doc: [], |
|||
byId: {}, |
|||
fromValueDone: false |
|||
}), |
|||
computed: { |
|||
canAdd () { |
|||
if (this.multiple) { |
|||
if (typeof this.multiple === 'number') { |
|||
return this.doc.length < this.multiple |
|||
} else { |
|||
return true |
|||
} |
|||
} else { |
|||
return this.doc.length === 0 |
|||
} |
|||
} |
|||
}, |
|||
watch: { |
|||
search (val) { |
|||
val && val.length >= 3 && val !== this.select && this.querySelections(val) |
|||
}, |
|||
value (val) { |
|||
if (!val || this.fromValueDone) { return } |
|||
this.doc = val.map(id => ({ id, label: null, key: null })) |
|||
this.updateLabelFromId() |
|||
this.fromValueDone = true |
|||
} |
|||
}, |
|||
methods: { |
|||
add () { |
|||
this.mode = 'adding' |
|||
}, |
|||
viewItem (item) { |
|||
window.open(`/admin/resources/${this.collection}/${item.id}`, '_blank') |
|||
}, |
|||
deleteItem (item) { |
|||
this |
|||
.$confirm(`Supprimer <b>${item.label}</b> ?`) |
|||
.then((res) => { |
|||
if (res) { |
|||
this.doc = this.doc.filter(val => val.id !== item.id) |
|||
this.updateLabelFromId() |
|||
this.$emit('change', this.doc.map(item => item.id)) |
|||
} |
|||
}) |
|||
}, |
|||
addItem () { |
|||
this.doc.push({ id: this.selectedItem, label: null, key: null }) |
|||
this.selectedItem = null |
|||
this.mode = '' |
|||
this.search = '' |
|||
this.updateLabelFromId() |
|||
this.$emit('change', this.doc.map(item => item.id)) |
|||
}, |
|||
querySelections (val) { |
|||
this.isLoading = true |
|||
this.$axios.get(`/cloud/api/${this.collection}?name__regex=${val},i&projection=name:1`) |
|||
.then((res) => { |
|||
this.items = res.data.data |
|||
}) |
|||
.finally(() => (this.isLoading = false)) |
|||
}, |
|||
getTitle (item) { |
|||
return this.byId[item] || item |
|||
}, |
|||
updateLabelFromId () { |
|||
const idsToGet = [] |
|||
this.doc.forEach((item) => { |
|||
if (!this.byId[item.id]) { |
|||
item.key = this.__generateKey(item.id) |
|||
item.label = item.id |
|||
this.byId[item.id] = item |
|||
} |
|||
}) |
|||
|
|||
for (const key in this.byId) { |
|||
if (this.byId[key].label === key) { |
|||
idsToGet.push(key) |
|||
} |
|||
} |
|||
|
|||
if (!idsToGet.length) { return } |
|||
|
|||
this.$axios.get(`/cloud/api/${this.collection}?_id__in=${idsToGet.join(',')}&projection=name:1`) |
|||
.then((res) => { |
|||
res.data.data.forEach((doc) => { |
|||
this.byId[doc._id].label = doc.name |
|||
}) |
|||
}) |
|||
}, |
|||
__generateKey (id) { |
|||
const ts = (new Date()).getTime() |
|||
return `${id}${ts}` |
|||
} |
|||
|
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,166 @@ |
|||
<template> |
|||
<v-container fluid> |
|||
<draggable :list="template"> |
|||
<transition-group> |
|||
<div v-for="section in template" :key="section.uid" :style="section.sectionStyle" style="position: relative"> |
|||
<v-layout column class="text-xs-center te-section--menu"> |
|||
<v-flex class="te-section--btn" elevation-4> |
|||
<v-icon dark> |
|||
mdi-cursor-move |
|||
</v-icon> |
|||
</v-flex> |
|||
<v-flex class="te-section--btn" elevation-4 @click.stop="editSection(section)"> |
|||
<v-icon dark> |
|||
mdi-pencil |
|||
</v-icon> |
|||
</v-flex> |
|||
<v-flex class="te-section--btn" elevation-4 @click.stop="removeSection(section)"> |
|||
<v-icon dark> |
|||
mdi-delete |
|||
</v-icon> |
|||
</v-flex> |
|||
</v-layout> |
|||
<te-section :colls="section.colls" :style="section.containerStyle" /> |
|||
</div> |
|||
</transition-group> |
|||
</draggable> |
|||
<v-layout |
|||
text-xs-center |
|||
align-center |
|||
justify-center |
|||
row |
|||
fill-height |
|||
@click="openAddSection()" |
|||
> |
|||
<v-flex class="lp-add-row"> |
|||
<v-card> |
|||
<v-card-text>ADD SECTION</v-card-text> |
|||
</v-card> |
|||
</v-flex> |
|||
</v-layout> |
|||
<te-add-section @newsection="addSection" /> |
|||
<v-navigation-drawer |
|||
v-model="rightDrawer" |
|||
temporary |
|||
right |
|||
fixed |
|||
:width="500" |
|||
> |
|||
<h1 /> |
|||
<v-tabs fixed-tabs> |
|||
<v-tab key="setting"> |
|||
Settings |
|||
</v-tab> |
|||
|
|||
<v-tab-item key="settings" /> |
|||
</v-tabs> |
|||
</v-navigation-drawer> |
|||
</v-container> |
|||
</template> |
|||
|
|||
<script> |
|||
import draggable from 'vuedraggable' |
|||
import TeSection from './widgets/TeSection.vue' |
|||
import TeAddSection from './modals/TeAddSection.vue' |
|||
|
|||
export default { |
|||
components: { draggable, TeSection, TeAddSection }, |
|||
model: { prop: 'src', event: 'change' }, |
|||
props: { |
|||
src: { type: Array, default: () => [] } |
|||
}, |
|||
data: () => ({ |
|||
template: [], |
|||
rightDrawer: false |
|||
}), |
|||
mounted () { |
|||
this.addSection([4, 4, 4]) |
|||
this.addSection([6, 6]) |
|||
// console.log(this.template) |
|||
// setInterval(() => { |
|||
// console.log(JSON.stringify(this.myArray)) |
|||
// }, 3000) |
|||
}, |
|||
methods: { |
|||
openAddSection () { |
|||
this.$emit('section:add') |
|||
}, |
|||
editSection (section) { |
|||
this.rightDrawer = true |
|||
}, |
|||
removeSection (section) { |
|||
this.$confirm('Do you really want to remove this section?', { title: 'Remove Section' }) |
|||
.then((res) => { |
|||
if (res) { this.template = this.template.filter(sec => sec.name !== section.name) } |
|||
}) |
|||
}, |
|||
addSection (pTemplate) { |
|||
const uid = Math.random().toString(36).slice(2, 10) |
|||
const section = { |
|||
name: `Section ${uid}`, |
|||
sectionStyle: { |
|||
backgroundColor: 'red', |
|||
margin: '1em 0' |
|||
}, |
|||
containerStyle: { |
|||
color: 'blue' |
|||
}, |
|||
uid, |
|||
colls: [] |
|||
} |
|||
pTemplate.forEach((size, idx) => { |
|||
section.colls.push({ |
|||
size, |
|||
style: {}, |
|||
uid: `${uid}-${idx}`, |
|||
list: [ |
|||
{ |
|||
type: 'TeImg', |
|||
uid: '123456700' + uid + idx, |
|||
data: { |
|||
src: 'https://picsum.photos/id/370/200/200' |
|||
} |
|||
}, |
|||
{ |
|||
type: 'TeText', |
|||
uid: '1234567' + uid + idx, |
|||
data: { |
|||
text: size === '2' ? 'Cupidatat enim id consequat deserunt elit eiusmod ullamco ipsum irure ullamco proident. Enim consectetur commodo incididunt in ad esse. Voluptate proident et aliquip est tempor est duis reprehenderit consequat. Ad cupidatat nisi sit incididunt tempor amet laborum adipisicing incididunt nostrud minim.' : 'Sunt mollit ut quis adipisicing consectetur pariatur laboris Lorem sunt quis deserunt id.' |
|||
} |
|||
}, |
|||
{ |
|||
type: 'TeText', |
|||
uid: '12345678' + uid + idx, |
|||
data: { |
|||
text: size === '2' ? 'Cupidatat enim id consequat deserunt elit eiusmod ullamco ipsum irure ullamco proident. Enim consectetur commodo incididunt in ad esse. Voluptate proident et aliquip est tempor est duis reprehenderit consequat. Ad cupidatat nisi sit incididunt tempor amet laborum adipisicing incididunt nostrud minim.' : 'Sunt mollit ut quis adipisicing consectetur pariatur laboris Lorem sunt quis deserunt id.' |
|||
} |
|||
} |
|||
] |
|||
}) |
|||
}) |
|||
this.template.push(section) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.lp-add-row { |
|||
margin: 10px; |
|||
cursor: pointer; |
|||
} |
|||
.te-section--menu { |
|||
position: absolute; |
|||
width:30px; |
|||
left:-30px; |
|||
} |
|||
.te-section--btn { |
|||
background: #888; |
|||
margin: 2px 0; |
|||
height: 30px; |
|||
cursor: pointer; |
|||
} |
|||
.te-section--btn:hover { |
|||
background: #555; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,94 @@ |
|||
<template> |
|||
<div class="text-xs-center"> |
|||
<v-dialog |
|||
v-model="dialog" |
|||
scrollable |
|||
width="500" |
|||
> |
|||
<v-card> |
|||
<v-card-title |
|||
class="headline grey lighten-2" |
|||
primary-title |
|||
> |
|||
Select new section format |
|||
</v-card-title> |
|||
|
|||
<v-card-text> |
|||
<div v-for="(format, fIdx) in formats" :key="format.join()"> |
|||
<h4 v-if="showTitle(fIdx)"> |
|||
{{ format.length }} Column(s) |
|||
</h4> |
|||
<v-layout row ma-2 elevation-3 class="add-section" @click="selectSection(format)"> |
|||
<v-flex v-for="(size, idx) in format" :key="format.join()+idx" :[`xs${size}`]="true" class="add-section--coll" /> |
|||
</v-layout> |
|||
</div> |
|||
</v-card-text> |
|||
|
|||
<v-divider /> |
|||
|
|||
<v-card-actions> |
|||
<v-spacer /> |
|||
<v-btn |
|||
color="primary" |
|||
text |
|||
@click="dialog = false" |
|||
> |
|||
Fermer |
|||
</v-btn> |
|||
</v-card-actions> |
|||
</v-card> |
|||
</v-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data: () => ({ |
|||
dialog: false, |
|||
formats: [ |
|||
[12], |
|||
[6, 6], |
|||
[4, 8], |
|||
[8, 4], |
|||
[4, 4, 4], |
|||
[3, 6, 3], |
|||
[3, 3, 3, 3] |
|||
] |
|||
}), |
|||
created () { |
|||
this.$parent.$on('section:add', this.openDialog) |
|||
}, |
|||
methods: { |
|||
selectSection (format) { |
|||
this.$emit('newsection', format) |
|||
this.dialog = false |
|||
}, |
|||
openDialog () { |
|||
this.dialog = true |
|||
}, |
|||
showTitle (idx) { |
|||
if (idx === 0) { |
|||
return true |
|||
} else { |
|||
const cLength = this.formats[idx].length |
|||
const nLength = this.formats[idx - 1].length |
|||
return cLength !== nLength |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.add-section--coll { |
|||
outline: 1px dashed; |
|||
} |
|||
.add-section { |
|||
cursor: pointer; |
|||
min-height: 30px; |
|||
margin: 0.5em 0; |
|||
} |
|||
.add-section:hover { |
|||
background: #CCC; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,14 @@ |
|||
<template> |
|||
<div> |
|||
<v-img height="100" :src="src" aspect-ratio="2" :contain="true" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'TeImg', |
|||
props: { |
|||
src: { type: String, default: '' } |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,113 @@ |
|||
<template> |
|||
<v-container style="position: relative"> |
|||
<v-layout justify-space-around row wrap> |
|||
<v-flex |
|||
v-for="coll in colls" |
|||
:key="coll.uid" |
|||
:style="coll.style" |
|||
xs12 |
|||
:[getSize(coll)]="true" |
|||
xxxclass="te-coll" |
|||
> |
|||
<!-- <div class="te-coll--menu"> |
|||
MOVE |
|||
</div> --> |
|||
<draggable |
|||
class="te-section" |
|||
:list="coll.list" |
|||
:group="{name: 'te-widget'}" |
|||
v-bind="dragOptions" |
|||
@start="drag = true" |
|||
@end="drag = false" |
|||
> |
|||
<transition-group |
|||
type="transition" |
|||
:name="!drag ? 'flip-list' : null" |
|||
tag="v-layout" |
|||
class="column" |
|||
> |
|||
<v-flex v-for="widget in coll.list" :key="widget.uid"> |
|||
<component :is="widget.type" v-bind="widget.data" /> |
|||
</v-flex> |
|||
<v-flex v-if="!coll.list.length" :key="`${coll.uid}--more`"> |
|||
--- |
|||
</v-flex> |
|||
</transition-group> |
|||
</draggable> |
|||
</v-flex> |
|||
</v-layout> |
|||
</v-container> |
|||
</template> |
|||
|
|||
<script> |
|||
// :grow="coll.size === 'g'" :shrink="coll.size === 's'" |
|||
import draggable from 'vuedraggable' |
|||
import TeText from './TeText.vue' |
|||
import TeImg from './TeImg.vue' |
|||
|
|||
export default { |
|||
components: { draggable, TeText, TeImg }, |
|||
props: { |
|||
colls: { type: Array, default: () => [] } |
|||
}, |
|||
data: () => ({ |
|||
fullText: false, |
|||
text: 'Nisi ex cillum ut mollit. Eiusmod velit ea labore do esse magna commodo occaecat. Irure ex velit culpa elit excepteur incididunt dolore fugiat esse veniam amet. Cupidatat duis voluptate quis dolor dolor veniam duis aliqua eu proident ipsum tempor cupidatat. Occaecat ea officia anim exercitation officia enim quis mollit id veniam id eiusmod qui in. Proident eu do cillum eu quis occaecat ex ipsum adipisicing exercitation ad elit sunt.', |
|||
drag: false |
|||
}), |
|||
computed: { |
|||
dragOptions () { |
|||
return { |
|||
animation: 200, |
|||
group: 'description', |
|||
disabled: false, |
|||
ghostClass: 'ghost' |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
}, |
|||
methods: { |
|||
getSize (coll) { |
|||
return `md${coll.size}` |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.te-section { |
|||
min-height: 100px; |
|||
outline: 1px dashed; |
|||
margin-bottom: 1em; |
|||
/* position: relative; */ |
|||
} |
|||
.te-coll { |
|||
/* position: relative; */ |
|||
} |
|||
.te-coll--menu { |
|||
position: absolute; |
|||
height:30px; |
|||
top:-30px; |
|||
background: blue; |
|||
} |
|||
.item { |
|||
min-width: 100px; |
|||
min-height: 30px; |
|||
margin: 10px; |
|||
text-align: center; |
|||
} |
|||
.ghost { |
|||
opacity: 0.5; |
|||
background: #c8ebfb; |
|||
} |
|||
</style> |
|||
|
|||
<style scoped> |
|||
@media (min-width: 1904px) { |
|||
.container { |
|||
max-width: 1300px!important; |
|||
padding: 0; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,12 @@ |
|||
<template> |
|||
<div>{{ text }}</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'TeText', |
|||
props: { |
|||
text: { type: String, default: '' } |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,5 @@ |
|||
const CFG = { |
|||
serverUrl: 'http://localhost:3009' |
|||
} |
|||
|
|||
export default CFG |
|||
@ -0,0 +1,7 @@ |
|||
# LAYOUTS |
|||
|
|||
**This directory is not required, you can delete it if you don't want to use it.** |
|||
|
|||
This directory contains your Application Layouts. |
|||
|
|||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts). |
|||
@ -0,0 +1,100 @@ |
|||
<template> |
|||
<v-app dark> |
|||
<v-navigation-drawer |
|||
v-model="drawer" |
|||
:mini-variant="miniVariant" |
|||
clipped |
|||
fixed |
|||
app |
|||
> |
|||
<v-list> |
|||
<v-list-item |
|||
v-for="(item, i) in menu" |
|||
:key="i" |
|||
:to="item.to" |
|||
router |
|||
exact |
|||
> |
|||
<v-list-item-action> |
|||
<v-icon>{{ item.icon }}</v-icon> |
|||
</v-list-item-action> |
|||
<v-list-item-content> |
|||
<v-list-item-title v-text="item.title" /> |
|||
</v-list-item-content> |
|||
</v-list-item> |
|||
</v-list> |
|||
</v-navigation-drawer> |
|||
<v-app-bar |
|||
clipped-left |
|||
fixed |
|||
app |
|||
> |
|||
<v-app-bar-nav-icon @click.stop="drawer = !drawer" /> |
|||
<v-btn |
|||
icon |
|||
@click.stop="miniVariant = !miniVariant" |
|||
> |
|||
<v-icon>mdi-{{ `chevron-${miniVariant ? 'right' : 'left'}` }}</v-icon> |
|||
</v-btn> |
|||
|
|||
<v-toolbar-title v-text="title" /> |
|||
<v-spacer /> |
|||
</v-app-bar> |
|||
<v-content> |
|||
<v-breadcrumbs :items="breadcrumbs"> |
|||
<template v-slot:divider> |
|||
<v-icon>mdi-chevron-right</v-icon> |
|||
</template> |
|||
</v-breadcrumbs> |
|||
<h2 class="display-1 grey lighten-4 font-weight-thin"> |
|||
<v-container> |
|||
{{ title }} |
|||
</v-container> |
|||
</h2> |
|||
<nuxt /> |
|||
</v-content> |
|||
<v-footer |
|||
fixed |
|||
app |
|||
> |
|||
<span>Nubium Artifex © 2019</span> |
|||
</v-footer> |
|||
<v-snackbar |
|||
:value="snackbar.showIt" |
|||
:timeout="snackbar.timeout" |
|||
:color="snackbar.color" |
|||
> |
|||
{{ snackbar.msg }} |
|||
<v-btn |
|||
text |
|||
@click="$store.commit('admin/ui/snackClose')" |
|||
> |
|||
Fermer |
|||
</v-btn> |
|||
</v-snackbar> |
|||
</v-app> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data: () => ({ |
|||
drawer: true, |
|||
miniVariant: false |
|||
}), |
|||
computed: { |
|||
title () { |
|||
return this.$store.state.admin.ui.title |
|||
}, |
|||
breadcrumbs () { |
|||
return this.$store.state.admin.ui.breadcrumbs |
|||
}, |
|||
menu () { |
|||
return this.$store.state.admin.ui.menu |
|||
}, |
|||
snackbar () { |
|||
return this.$store.state.admin.ui.snackbar |
|||
} |
|||
}, |
|||
methods: {} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,117 @@ |
|||
<template> |
|||
<v-app dark> |
|||
<v-navigation-drawer |
|||
v-model="drawer" |
|||
:mini-variant="miniVariant" |
|||
:clipped="clipped" |
|||
fixed |
|||
app |
|||
> |
|||
<v-list> |
|||
<v-list-item |
|||
v-for="(item, i) in items" |
|||
:key="i" |
|||
:to="item.to" |
|||
router |
|||
exact |
|||
> |
|||
<v-list-item-action> |
|||
<v-icon>{{ item.icon }}</v-icon> |
|||
</v-list-item-action> |
|||
<v-list-item-content> |
|||
<v-list-item-title v-text="item.title" /> |
|||
</v-list-item-content> |
|||
</v-list-item> |
|||
</v-list> |
|||
</v-navigation-drawer> |
|||
<v-app-bar |
|||
:clipped-left="clipped" |
|||
fixed |
|||
app |
|||
> |
|||
<v-app-bar-nav-icon @click.stop="drawer = !drawer" /> |
|||
<v-btn |
|||
icon |
|||
@click.stop="miniVariant = !miniVariant" |
|||
> |
|||
<v-icon>mdi-{{ `chevron-${miniVariant ? 'right' : 'left'}` }}</v-icon> |
|||
</v-btn> |
|||
<v-btn |
|||
icon |
|||
@click.stop="clipped = !clipped" |
|||
> |
|||
<v-icon>mdi-application</v-icon> |
|||
</v-btn> |
|||
<v-btn |
|||
icon |
|||
@click.stop="fixed = !fixed" |
|||
> |
|||
<v-icon>mdi-minus</v-icon> |
|||
</v-btn> |
|||
<v-toolbar-title v-text="title" /> |
|||
<v-spacer /> |
|||
<v-btn |
|||
icon |
|||
@click.stop="rightDrawer = !rightDrawer" |
|||
> |
|||
<v-icon>mdi-menu</v-icon> |
|||
</v-btn> |
|||
</v-app-bar> |
|||
<v-content> |
|||
<v-container> |
|||
<nuxt /> |
|||
</v-container> |
|||
</v-content> |
|||
<v-navigation-drawer |
|||
v-model="rightDrawer" |
|||
:right="right" |
|||
temporary |
|||
fixed |
|||
> |
|||
<v-list> |
|||
<v-list-item @click.native="right = !right"> |
|||
<v-list-item-action> |
|||
<v-icon light> |
|||
mdi-repeat |
|||
</v-icon> |
|||
</v-list-item-action> |
|||
<v-list-item-title>Switch drawer (click me)</v-list-item-title> |
|||
</v-list-item> |
|||
</v-list> |
|||
</v-navigation-drawer> |
|||
<v-footer |
|||
:fixed="fixed" |
|||
app |
|||
> |
|||
<span>© 2019</span> |
|||
</v-footer> |
|||
</v-app> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data () { |
|||
return { |
|||
clipped: false, |
|||
drawer: false, |
|||
fixed: false, |
|||
items: [ |
|||
{ |
|||
icon: 'mdi-apps', |
|||
title: 'Welcome', |
|||
to: '/' |
|||
}, |
|||
{ |
|||
icon: 'mdi-chart-bubble', |
|||
title: 'Inspire', |
|||
to: '/inspire' |
|||
} |
|||
], |
|||
miniVariant: false, |
|||
right: true, |
|||
rightDrawer: false, |
|||
title: 'Vuetify.js' |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,74 @@ |
|||
<template> |
|||
<v-app> |
|||
<v-app-bar |
|||
fixed |
|||
app |
|||
> |
|||
<v-toolbar-title v-text="title" /> |
|||
<v-spacer /> |
|||
<v-btn |
|||
icon |
|||
nuxt |
|||
to="/admin" |
|||
> |
|||
<v-icon>mdi-account</v-icon> |
|||
</v-btn> |
|||
</v-app-bar> |
|||
<v-content> |
|||
<v-container> |
|||
<nuxt /> |
|||
</v-container> |
|||
</v-content> |
|||
<v-navigation-drawer |
|||
v-model="rightDrawer" |
|||
:right="right" |
|||
temporary |
|||
fixed |
|||
> |
|||
<v-list> |
|||
<v-list-item @click.native="right = !right"> |
|||
<v-list-item-action> |
|||
<v-icon light> |
|||
mdi-repeat |
|||
</v-icon> |
|||
</v-list-item-action> |
|||
<v-list-item-title>Switch drawer (click me)</v-list-item-title> |
|||
</v-list-item> |
|||
</v-list> |
|||
</v-navigation-drawer> |
|||
<v-footer |
|||
:fixed="fixed" |
|||
app |
|||
> |
|||
<span>Nubium Artifex © 2019</span> |
|||
</v-footer> |
|||
</v-app> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data () { |
|||
return { |
|||
clipped: false, |
|||
drawer: false, |
|||
fixed: false, |
|||
items: [ |
|||
{ |
|||
icon: 'mdi-apps', |
|||
title: 'Welcome', |
|||
to: '/' |
|||
}, |
|||
{ |
|||
icon: 'mdi-chart-bubble', |
|||
title: 'Inspire', |
|||
to: '/inspire' |
|||
} |
|||
], |
|||
miniVariant: false, |
|||
right: true, |
|||
rightDrawer: false, |
|||
title: 'Vuetify.js' |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,44 @@ |
|||
<template> |
|||
<v-app dark> |
|||
<h1 v-if="error.statusCode === 404"> |
|||
{{ pageNotFound }} |
|||
</h1> |
|||
<h1 v-else> |
|||
{{ otherError }} |
|||
</h1> |
|||
<NuxtLink to="/"> |
|||
Home page |
|||
</NuxtLink> |
|||
</v-app> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
layout: 'empty', |
|||
props: { |
|||
error: { |
|||
type: Object, |
|||
default: null |
|||
} |
|||
}, |
|||
head () { |
|||
const title = |
|||
this.error.statusCode === 404 ? this.pageNotFound : this.otherError |
|||
return { |
|||
title |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
pageNotFound: '404 Not Found', |
|||
otherError: 'An error occurred' |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
h1 { |
|||
font-size: 20px; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,8 @@ |
|||
# MIDDLEWARE |
|||
|
|||
**This directory is not required, you can delete it if you don't want to use it.** |
|||
|
|||
This directory contains your application middleware. |
|||
Middleware let you define custom functions that can be run before rendering either a page or a group of pages. |
|||
|
|||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware). |
|||
@ -0,0 +1,6 @@ |
|||
export default function ({ store }) { |
|||
if (store.state.ssr === process.server) { |
|||
return |
|||
} |
|||
store.commit('setRenderer', process.server) |
|||
} |
|||
@ -0,0 +1,92 @@ |
|||
import colors from 'vuetify/es5/util/colors' |
|||
|
|||
export default { |
|||
mode: 'universal', |
|||
/* |
|||
** Headers of the page |
|||
*/ |
|||
head: { |
|||
titleTemplate: '%s - ' + process.env.npm_package_name, |
|||
title: process.env.npm_package_name || '', |
|||
meta: [ |
|||
{ charset: 'utf-8' }, |
|||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }, |
|||
{ hid: 'description', name: 'description', content: process.env.npm_package_description || '' } |
|||
], |
|||
link: [ |
|||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } |
|||
] |
|||
}, |
|||
/* |
|||
** Customize the progress-bar color |
|||
*/ |
|||
loading: { color: '#f0f' }, |
|||
/* |
|||
** Global CSS |
|||
*/ |
|||
css: [ |
|||
], |
|||
/* |
|||
** Plugins to load before mounting the App |
|||
*/ |
|||
plugins: [ |
|||
{ src: '~/plugins/vuetify-confirm', mode: 'client' } |
|||
], |
|||
/* |
|||
** Nuxt.js dev-modules |
|||
*/ |
|||
devModules: [ |
|||
// Doc: https://github.com/nuxt-community/eslint-module
|
|||
'@nuxtjs/eslint-module', |
|||
'@nuxtjs/vuetify' |
|||
], |
|||
/* |
|||
** Nuxt.js modules |
|||
*/ |
|||
modules: [ |
|||
// Doc: https://axios.nuxtjs.org/usage
|
|||
'@nuxtjs/axios' |
|||
], |
|||
/* |
|||
** Axios module configuration |
|||
** See https://axios.nuxtjs.org/options
|
|||
*/ |
|||
axios: { |
|||
proxy: true // Can be also an object with default options,
|
|||
// debug: true
|
|||
}, |
|||
proxy: { |
|||
'/cloud': { target: 'http://localhost:3009', pathRewrite: { '/cloud': '' } } |
|||
}, |
|||
/* |
|||
** vuetify module configuration |
|||
** https://github.com/nuxt-community/vuetify-module
|
|||
*/ |
|||
vuetify: { |
|||
customVariables: ['~/assets/variables.scss'], |
|||
theme: { |
|||
dark: false, |
|||
themes: { |
|||
dark: { |
|||
primary: colors.blue.darken2, |
|||
accent: colors.grey.darken3, |
|||
secondary: colors.amber.darken3, |
|||
info: colors.teal.lighten1, |
|||
warning: colors.amber.base, |
|||
error: colors.deepOrange.accent4, |
|||
success: colors.green.accent3 |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
/* |
|||
** Build configuration |
|||
*/ |
|||
build: { |
|||
/* |
|||
** You can extend webpack config here |
|||
*/ |
|||
extend (config, ctx) { |
|||
} |
|||
} |
|||
} |
|||
11467
webapp/package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,29 @@ |
|||
{ |
|||
"name": "artifex", |
|||
"version": "1.0.0", |
|||
"description": "An artifex world for noob", |
|||
"author": "P.BARRY", |
|||
"private": true, |
|||
"scripts": { |
|||
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .", |
|||
"dev": "nuxt", |
|||
"build": "nuxt build", |
|||
"start": "nuxt start", |
|||
"generate": "nuxt generate" |
|||
}, |
|||
"dependencies": { |
|||
"@nuxtjs/axios": "^5.3.6", |
|||
"nuxt": "^2.0.0", |
|||
"vuedraggable": "^2.23.0", |
|||
"vuetify-confirm": "^1.0.0-alpha.0" |
|||
}, |
|||
"devDependencies": { |
|||
"@nuxtjs/vuetify": "^1.0.0", |
|||
"@nuxtjs/eslint-config": "^1.0.1", |
|||
"@nuxtjs/eslint-module": "^0.2.1", |
|||
"babel-eslint": "^10.0.1", |
|||
"eslint": "^5.15.1", |
|||
"eslint-plugin-nuxt": ">=0.4.2", |
|||
"nodemon": "^1.18.9" |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
# PAGES |
|||
|
|||
This directory contains your Application Views and Routes. |
|||
The framework reads all the `*.vue` files inside this directory and creates the router of your application. |
|||
|
|||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing). |
|||
@ -0,0 +1,40 @@ |
|||
<template> |
|||
<v-layout column justify-center align-center> |
|||
<v-flex xs12 sm8 md6> |
|||
<div class="text-center"> |
|||
<img src="/assets/vuetify.png" alt="Vuetify.js" class="mb-5"> |
|||
</div> |
|||
<v-card> |
|||
<v-card-title class="headline"> |
|||
Welcome to the Vuetify + Nuxt.js template |
|||
</v-card-title> |
|||
<v-card-text> |
|||
<p>Vuetify is a progressive Material Design component framework for Vue.js. It was designed to empower developers to create amazing applications.</p> |
|||
<p>For more information on Vuetify, check out the <a href="https://vuetifyjs.com" target="_blank">documentation</a>.</p> |
|||
<p>If you have questions, please join the official <a href="https://chat.vuetifyjs.com/" target="_blank" title="chat">discord</a>.</p> |
|||
<p>Find a bug? Report it on the github <a href="https://github.com/vuetifyjs/vuetify/issues" target="_blank" title="contribute">issue board</a>.</p> |
|||
<p>Thank you for developing with Vuetify and I look forward to bringing more exciting features in the future.</p> |
|||
<div class="text-xs-right"> |
|||
<em><small>— John Leider</small></em> |
|||
</div> |
|||
<hr class="my-3"> |
|||
<a href="https://nuxtjs.org/" target="_blank">Nuxt Documentation</a> |
|||
<br> |
|||
<a href="https://github.com/nuxt/nuxt.js" target="_blank">Nuxt GitHub</a> |
|||
</v-card-text> |
|||
<v-card-actions> |
|||
<v-spacer /> |
|||
<v-btn color="primary" text nuxt to="/inspire"> |
|||
Continue |
|||
</v-btn> |
|||
</v-card-actions> |
|||
</v-card> |
|||
</v-flex> |
|||
</v-layout> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
layout: 'admin' |
|||
} |
|||
</script> |
|||
@ -0,0 +1,33 @@ |
|||
<template> |
|||
<template-editor v-model="lp" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import TemplateEditor from '@/components/TemplateEditor/TemplateEditor.vue' |
|||
|
|||
export default { |
|||
layout: 'admin', |
|||
components: { TemplateEditor }, |
|||
data: () => ({ |
|||
doc: {}, |
|||
lp: [] |
|||
}), |
|||
mounted () { |
|||
this.$store.commit('admin/ui/setBreadcrumbs', [ |
|||
{ text: 'Admin', to: '/admin' }, |
|||
{ text: 'Landing Page', to: '/admin/landingpage' }, |
|||
{ text: 'Edit', to: `/admin/landingpage/${this.$route.params.id}` } |
|||
]) |
|||
this.getDoc() |
|||
}, |
|||
methods: { |
|||
getDoc () { |
|||
this.$axios.get(`/cloud/api/landingpages/${this.$route.params.id}`) |
|||
.then((res) => { |
|||
this.doc = res.data.data |
|||
this.$store.commit('admin/ui/setTitle', this.doc.name) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,94 @@ |
|||
<template> |
|||
<v-container> |
|||
<v-layout> |
|||
<v-flex xs6> |
|||
<p class="caption font-weight-light font-italic"> |
|||
Choisir la landing page à afficher sur la page d'accueil. |
|||
</p> |
|||
<v-select |
|||
v-model="currentLP" |
|||
:items="docs" |
|||
item-text="name" |
|||
item-value="_id" |
|||
label="Landing page" |
|||
solo |
|||
@change="updateCurrentLP()" |
|||
/> |
|||
</v-flex> |
|||
</v-layout> |
|||
|
|||
<v-layout> |
|||
<v-flex xs6> |
|||
<p class="caption font-weight-light font-italic"> |
|||
Editer une landing page. |
|||
Pour ajouter une nouvelle landing page, passer par <b>Resources > Landing Page</b> |
|||
</p> |
|||
</v-flex> |
|||
</v-layout> |
|||
|
|||
<v-list dense two-line class="elevation-2"> |
|||
<template v-for="item in docs"> |
|||
<v-list-item |
|||
:key="`item-${item.coll}`" |
|||
link |
|||
nuxt |
|||
:to="`/admin/landingpage/${item._id}`" |
|||
> |
|||
<v-list-item-content> |
|||
<v-list-item-title v-text="item.name" /> |
|||
<v-list-item-subtitle v-text="item.description" /> |
|||
</v-list-item-content> |
|||
|
|||
<v-list-item-action /> |
|||
</v-list-item> |
|||
<v-divider :key="`divider-${item.name}`" /> |
|||
</template> |
|||
</v-list> |
|||
</v-container> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
layout: 'admin', |
|||
data: () => ({ |
|||
currentLP: '', |
|||
docs: [], |
|||
switch1: false |
|||
}), |
|||
mounted () { |
|||
this.$store.commit('admin/ui/setTitle', 'Landing Page') |
|||
this.$store.commit('admin/ui/setBreadcrumbs', [ |
|||
{ text: 'Admin', to: '/admin' }, |
|||
{ text: 'Landing Page', to: '/admin/landingpage' } |
|||
]) |
|||
this.getDocs() |
|||
this.getCurrentLP() |
|||
}, |
|||
methods: { |
|||
getDocs () { |
|||
this.$axios |
|||
.get('/cloud/api/landingpages?projection=name:1,description:1') |
|||
.then((res) => { |
|||
this.docs = res.data.data |
|||
}) |
|||
}, |
|||
getCurrentLP () { |
|||
this.$axios |
|||
.get('/cloud/api/config/home:landing-page') |
|||
.then((res) => { |
|||
try { this.currentLP = res.data.data.value } catch (e) {} |
|||
}) |
|||
}, |
|||
updateCurrentLP () { |
|||
this.$axios |
|||
.put('/cloud/api/config/home:landing-page', { value: this.currentLP }) |
|||
.then((res) => { |
|||
this.$store.commit('admin/ui/snack', { msg: 'Enregistré avec succès', color: 'success' }) |
|||
}) |
|||
.then((res) => { |
|||
this.$store.commit('admin/ui/snack', { msg: 'Echec', color: 'error' }) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,99 @@ |
|||
<template> |
|||
<v-container> |
|||
<v-tabs v-model="currentTab" centered grow> |
|||
<v-tab v-for="tab in jsonForm" :key="tab.label" :href="`#tab-${tab.label}`"> |
|||
{{ tab.label }} |
|||
</v-tab> |
|||
</v-tabs> |
|||
|
|||
<v-tabs-items v-model="currentTab" class="my-4"> |
|||
<v-tab-item v-for="tab in jsonForm" :key="tab.label" :value="`tab-${tab.label}`"> |
|||
<form-gen |
|||
v-if="doc" |
|||
:value="doc" |
|||
:more="tab.field" |
|||
:form="tab.form" |
|||
:coll="{type: $route.params.rsc, id: doc._id}" |
|||
:disabled="disabled" |
|||
@update="hasUpdate()" |
|||
/> |
|||
</v-tab-item> |
|||
</v-tabs-items> |
|||
|
|||
<v-fab-transition> |
|||
<v-btn |
|||
v-show="canSave" |
|||
class="mx-2" |
|||
fab |
|||
dark |
|||
large |
|||
color="success ma-3" |
|||
absolute |
|||
bottom |
|||
right |
|||
@click="save()" |
|||
> |
|||
<v-icon dark> |
|||
mdi-content-save |
|||
</v-icon> |
|||
</v-btn> |
|||
</v-fab-transition> |
|||
</v-container> |
|||
</template> |
|||
|
|||
<script> |
|||
import FormGen from '@/components/FormGen/FormGen' |
|||
|
|||
export default { |
|||
layout: 'admin', |
|||
components: { FormGen }, |
|||
data: () => ({ |
|||
jsonForm: [], |
|||
currentTab: '', |
|||
doc: null, |
|||
canSave: false, |
|||
disabled: true |
|||
}), |
|||
mounted () { |
|||
this.$store.commit('admin/ui/setBreadcrumbs', [ |
|||
{ text: 'Resources', href: '/admin/resources' }, |
|||
{ text: this.$route.params.rsc, href: `/admin/resources/${this.$route.params.rsc}` }, |
|||
{ text: 'Edit', href: `/admin/resources/${this.$route.params.rsc}/${this.$route.params.id}` } |
|||
]) |
|||
this.getForm() |
|||
this.getDoc() |
|||
}, |
|||
methods: { |
|||
hasUpdate () { |
|||
this.canSave = true |
|||
}, |
|||
getForm () { |
|||
this.$axios.get(`/cloud/api/${this.$route.params.rsc}/private/json-form`) |
|||
.then((res) => { |
|||
this.jsonForm = res.data |
|||
this.jsonForm.forEach((tab) => { |
|||
if (!this.currentTab) { this.currentTab = `#tab-${tab.label}` } |
|||
}) |
|||
this.disabled = false |
|||
}) |
|||
}, |
|||
getDoc () { |
|||
this.$axios.get(`/cloud/api/${this.$route.params.rsc}/${this.$route.params.id}`) |
|||
.then((res) => { |
|||
this.doc = res.data.data |
|||
this.$store.commit('admin/ui/setTitle', this.doc.name) |
|||
}) |
|||
}, |
|||
save () { |
|||
this.$axios.put(`/cloud/api/${this.$route.params.rsc}/${this.$route.params.id}`, this.doc) |
|||
.then((res) => { |
|||
this.canSave = false |
|||
this.$store.commit('admin/ui/snack', { msg: 'Enregistré avec succès', color: 'success' }) |
|||
}) |
|||
.catch((res) => { |
|||
this.$store.commit('admin/ui/snack', { msg: 'Impossible de sauvegarder', color: 'error' }) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,199 @@ |
|||
<template> |
|||
<v-container> |
|||
<v-toolbar flat color="white"> |
|||
<v-text-field |
|||
v-model="search" |
|||
append-icon="mdi-magnify" |
|||
label="Recherche" |
|||
single-line |
|||
hide-details |
|||
@change="searchDoc" |
|||
/> |
|||
<v-spacer /> |
|||
<v-btn color="primary" @click="createDoc()"> |
|||
<v-icon>mdi-plus</v-icon> |
|||
</v-btn> |
|||
</v-toolbar> |
|||
|
|||
<v-data-table |
|||
:headers="headers" |
|||
:items="docs" |
|||
:loading="loading" |
|||
:options.sync="options" |
|||
:server-items-length="nbDocs" |
|||
class="elevation-2" |
|||
> |
|||
<template v-slot:items="props"> |
|||
<td>{{ props.item.name }}</td> |
|||
<td> |
|||
<v-icon small class="mr-2" @click="editDoc(props.item)"> |
|||
edit |
|||
</v-icon> |
|||
<v-icon small @click="deleteDoc(props.item)"> |
|||
delete |
|||
</v-icon> |
|||
</td> |
|||
</template> |
|||
<template v-slot:item.action="{ item }"> |
|||
<v-icon |
|||
small |
|||
class="mr-2" |
|||
@click="editDoc(item)" |
|||
> |
|||
mdi-pencil |
|||
</v-icon> |
|||
<v-icon |
|||
small |
|||
@click="deleteDoc(item)" |
|||
> |
|||
mdi-delete |
|||
</v-icon> |
|||
</template> |
|||
</v-data-table> |
|||
|
|||
<v-dialog v-model="openCreateDialog" persistent max-width="600px"> |
|||
<v-card> |
|||
<v-card-title> |
|||
<span class="headline">Create new item</span> |
|||
</v-card-title> |
|||
<v-card-text> |
|||
<v-container v-if="newItem.form" grid-list-md> |
|||
<form-gen |
|||
:value="newItem.doc" |
|||
:form="newItem.form" |
|||
:coll="{type: $route.params.rsc, id: null}" |
|||
@valid="newItemIsValid" |
|||
/> |
|||
|
|||
<v-alert :value="newItem.hasError" type="error"> |
|||
{{ newItem.hasError }} |
|||
</v-alert> |
|||
</v-container> |
|||
</v-card-text> |
|||
<v-card-actions> |
|||
<v-spacer /> |
|||
<v-btn color="blue darken-1" text @click="openCreateDialog = false"> |
|||
Cancel |
|||
</v-btn> |
|||
<v-btn color="primary" text :disabled="!newItem.isValid" @click="newItemCreate"> |
|||
Create |
|||
</v-btn> |
|||
</v-card-actions> |
|||
</v-card> |
|||
</v-dialog> |
|||
</v-container> |
|||
</template> |
|||
|
|||
<script> |
|||
import FormGen from '@/components/FormGen/FormGen' |
|||
export default { |
|||
layout: 'admin', |
|||
components: { FormGen }, |
|||
data: () => ({ |
|||
docs: [], |
|||
jsonForm: null, |
|||
openCreateDialog: false, |
|||
loading: false, |
|||
nbDocs: 0, |
|||
options: {}, |
|||
search: '', |
|||
newItem: { |
|||
doc: {}, |
|||
form: null, |
|||
hasError: null, |
|||
isValid: false |
|||
}, |
|||
headers: [ |
|||
{ text: 'Name', align: 'left', value: 'name' }, |
|||
{ text: 'Actions', value: 'action', align: 'right', sortable: false } |
|||
] |
|||
}), |
|||
watch: { |
|||
options: { |
|||
handler () { |
|||
this.getDataFromApi() |
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.$store.commit('admin/ui/setTitle', 'Resources') |
|||
this.$store.commit('admin/ui/setBreadcrumbs', [ |
|||
{ text: 'Admin', to: '/admin' }, |
|||
{ text: 'Resources', to: '/admin/resources' }, |
|||
{ text: this.$route.params.rsc, to: `/admin/resources/${this.$route.params.rsc}` } |
|||
]) |
|||
this.getListingHeader() |
|||
}, |
|||
methods: { |
|||
editDoc (item) { |
|||
this.$router.push({ path: `/admin/resources/${this.$route.params.rsc}/${item._id}` }) |
|||
}, |
|||
deleteDoc (item) {}, |
|||
createDoc () { |
|||
this.getCreateForm() |
|||
}, |
|||
searchDoc () { |
|||
this.getDataFromApi() |
|||
}, |
|||
getCreateForm () { |
|||
this.$axios.get(`/cloud/api/${this.$route.params.rsc}/private/json-form-create`) |
|||
.then((res) => { |
|||
this.newItem.doc = {} |
|||
this.newItem.form = res.data |
|||
this.openCreateDialog = true |
|||
}) |
|||
}, |
|||
getListingHeader () { |
|||
this.$axios.get(`/cloud/api/${this.$route.params.rsc}/private/listing-header`) |
|||
.then((res) => { |
|||
this.headers = res.data |
|||
this.headers.push({ text: 'Actions', value: 'action', align: 'right', sortable: false }) |
|||
}) |
|||
}, |
|||
newItemIsValid (pVal) { |
|||
this.newItem.isValid = pVal |
|||
}, |
|||
newItemCreate () { |
|||
this.newItem.hasError = null |
|||
if (!this.newItem.isValid) { return } |
|||
this.$axios.post(`/cloud/api/${this.$route.params.rsc}`, this.newItem.doc) |
|||
.then((res) => { |
|||
this.$router.push({ path: `/admin/resources/${this.$route.params.rsc}/${res.data.doc._id}` }) |
|||
}) |
|||
.catch((res) => { |
|||
this.newItem.hasError = 'Impossible de créer le nouvel item' |
|||
}) |
|||
}, |
|||
newItemCancel () { |
|||
this.newItem.doc = {} |
|||
this.newItem.form = null |
|||
this.newItem.isValid = false |
|||
this.openCreateDialog = true |
|||
}, |
|||
getDataFromApi () { |
|||
const { sortBy, sortDesc, page, itemsPerPage } = this.options |
|||
this.loading = true |
|||
const queries = [] |
|||
const sort = sortBy.length ? sortBy[0] : 'name' |
|||
const desc = sortDesc.length ? sortDesc[0] : true |
|||
const search = this.search |
|||
|
|||
queries.push(`limit=${itemsPerPage}`) |
|||
queries.push(`skip=${itemsPerPage * (page - 1)}`) |
|||
queries.push(`sort=${desc ? '' : '-'}${sort}`) |
|||
if (search) { |
|||
queries.push(`name__regex=${search},i`) |
|||
} |
|||
|
|||
this.$axios.get(`/cloud/api/${this.$route.params.rsc}?${queries.join('&')}`) |
|||
.then((res) => { |
|||
this.$store.commit('admin/ui/setTitle', res.data.label) |
|||
this.nbDocs = res.data.count |
|||
this.docs = res.data.data |
|||
this.loading = false |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,53 @@ |
|||
<template> |
|||
<v-container> |
|||
<v-list two-line dense class="elevation-2"> |
|||
<template v-for="item in collections"> |
|||
<v-list-item |
|||
:key="`item-${item.coll}`" |
|||
link |
|||
nuxt |
|||
:to="`/admin/resources/${item.coll}`" |
|||
> |
|||
<v-list-item-avatar> |
|||
<v-icon |
|||
v-text="item.icon" |
|||
/> |
|||
</v-list-item-avatar> |
|||
|
|||
<v-list-item-content> |
|||
<v-list-item-title v-text="item.label" /> |
|||
<v-list-item-subtitle v-text="item.description" /> |
|||
</v-list-item-content> |
|||
|
|||
<v-list-item-action /> |
|||
</v-list-item> |
|||
<v-divider :key="`divider-${item.coll}`" /> |
|||
</template> |
|||
</v-list> |
|||
</v-container> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
layout: 'admin', |
|||
data: () => ({ |
|||
collections: [] |
|||
}), |
|||
mounted () { |
|||
this.$store.commit('admin/ui/setTitle', 'Resources') |
|||
this.$store.commit('admin/ui/setBreadcrumbs', [ |
|||
{ text: 'Admin', to: '/admin' }, |
|||
{ text: 'Resources', to: '/admin/resources' } |
|||
]) |
|||
this.getCollections() |
|||
}, |
|||
methods: { |
|||
getCollections () { |
|||
this.$axios.get('/cloud/api/__intern/collections') |
|||
.then((res) => { |
|||
this.collections = res.data |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,217 @@ |
|||
<template> |
|||
<v-content> |
|||
<section> |
|||
<v-parallax src="assets/hero.jpeg" height="600"> |
|||
<v-layout |
|||
column |
|||
align-center |
|||
justify-center |
|||
class="white--text" |
|||
> |
|||
<img src="assets/vuetify.png" alt="Vuetify.js" height="200"> |
|||
<h1 class="white--text mb-2 display-1 text-center"> |
|||
Parallax Template |
|||
</h1> |
|||
<div class="subheading mb-4 text-center"> |
|||
Powered by Vuetify |
|||
</div> |
|||
<v-btn |
|||
class="mt-12" |
|||
color="blue lighten-2" |
|||
dark |
|||
large |
|||
href="/pre-made-themes" |
|||
> |
|||
Get Started |
|||
</v-btn> |
|||
</v-layout> |
|||
</v-parallax> |
|||
</section> |
|||
|
|||
<section> |
|||
<v-layout |
|||
column |
|||
wrap |
|||
class="my-12" |
|||
align-center |
|||
> |
|||
<v-flex xs12 sm4 class="my-4"> |
|||
<div class="text-center"> |
|||
<h2 class="headline"> |
|||
The best way to start developing |
|||
</h2> |
|||
<span class="subheading"> |
|||
Cras facilisis mi vitae nunc |
|||
</span> |
|||
</div> |
|||
</v-flex> |
|||
<v-flex xs12> |
|||
<v-container grid-list-xl> |
|||
<v-layout row wrap align-center> |
|||
<v-flex xs12 md4> |
|||
<v-card flat class="transparent"> |
|||
<v-card-text class="text-center"> |
|||
<v-icon x-large class="blue--text text--lighten-2"> |
|||
mdi-palette |
|||
</v-icon> |
|||
</v-card-text> |
|||
<v-card-title primary-title class="layout justify-center"> |
|||
<div class="headline text-center"> |
|||
Material Design |
|||
</div> |
|||
</v-card-title> |
|||
<v-card-text> |
|||
Cras facilisis mi vitae nunc lobortis pharetra. Nulla volutpat tincidunt ornare. |
|||
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. |
|||
Nullam in aliquet odio. Aliquam eu est vitae tellus bibendum tincidunt. Suspendisse potenti. |
|||
</v-card-text> |
|||
</v-card> |
|||
</v-flex> |
|||
<v-flex xs12 md4> |
|||
<v-card flat class="transparent"> |
|||
<v-card-text class="text-center"> |
|||
<v-icon x-large class="blue--text text--lighten-2"> |
|||
mdi-flash |
|||
</v-icon> |
|||
</v-card-text> |
|||
<v-card-title primary-title class="layout justify-center"> |
|||
<div class="headline"> |
|||
Fast development |
|||
</div> |
|||
</v-card-title> |
|||
<v-card-text> |
|||
Cras facilisis mi vitae nunc lobortis pharetra. Nulla volutpat tincidunt ornare. |
|||
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. |
|||
Nullam in aliquet odio. Aliquam eu est vitae tellus bibendum tincidunt. Suspendisse potenti. |
|||
</v-card-text> |
|||
</v-card> |
|||
</v-flex> |
|||
<v-flex xs12 md4> |
|||
<v-card flat class="transparent"> |
|||
<v-card-text class="text-center"> |
|||
<v-icon x-large class="blue--text text--lighten-2"> |
|||
mdi-wrench |
|||
</v-icon> |
|||
</v-card-text> |
|||
<v-card-title primary-title class="layout justify-center"> |
|||
<div class="headline text-center"> |
|||
Completely Open Sourced |
|||
</div> |
|||
</v-card-title> |
|||
<v-card-text> |
|||
Cras facilisis mi vitae nunc lobortis pharetra. Nulla volutpat tincidunt ornare. |
|||
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. |
|||
Nullam in aliquet odio. Aliquam eu est vitae tellus bibendum tincidunt. Suspendisse potenti. |
|||
</v-card-text> |
|||
</v-card> |
|||
</v-flex> |
|||
</v-layout> |
|||
</v-container> |
|||
</v-flex> |
|||
</v-layout> |
|||
</section> |
|||
|
|||
<section> |
|||
<v-parallax src="assets/section.jpg" height="380"> |
|||
<v-layout column align-center justify-center> |
|||
<div class="headline white--text mb-4 text-center"> |
|||
Web development has never been easier |
|||
</div> |
|||
<em>Kick-start your application today</em> |
|||
<v-btn |
|||
class="mt-12" |
|||
color="blue lighten-2" |
|||
dark |
|||
large |
|||
href="/pre-made-themes" |
|||
> |
|||
Get Started |
|||
</v-btn> |
|||
</v-layout> |
|||
</v-parallax> |
|||
</section> |
|||
|
|||
<section> |
|||
<v-container grid-list-xl> |
|||
<v-layout row wrap justify-center class="my-12"> |
|||
<v-flex xs12 sm4> |
|||
<v-card flat class="transparent"> |
|||
<v-card-title primary-title class="layout justify-center"> |
|||
<div class="headline"> |
|||
Company info |
|||
</div> |
|||
</v-card-title> |
|||
<v-card-text> |
|||
Cras facilisis mi vitae nunc lobortis pharetra. Nulla volutpat tincidunt ornare. |
|||
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. |
|||
Nullam in aliquet odio. Aliquam eu est vitae tellus bibendum tincidunt. Suspendisse potenti. |
|||
</v-card-text> |
|||
</v-card> |
|||
</v-flex> |
|||
<v-flex xs12 sm4 offset-sm1> |
|||
<v-card flat class="transparent"> |
|||
<v-card-title primary-title class="layout justify-center"> |
|||
<div class="headline"> |
|||
Contact us |
|||
</div> |
|||
</v-card-title> |
|||
<v-card-text> |
|||
Cras facilisis mi vitae nunc lobortis pharetra. Nulla volutpat tincidunt ornare. |
|||
</v-card-text> |
|||
<v-list class="transparent"> |
|||
<v-list-item> |
|||
<v-list-item-action> |
|||
<v-icon class="blue--text text--lighten-2"> |
|||
mdi-phone |
|||
</v-icon> |
|||
</v-list-item-action> |
|||
<v-list-item-content> |
|||
<v-list-item-title>777-867-5309</v-list-item-title> |
|||
</v-list-item-content> |
|||
</v-list-item> |
|||
<v-list-item> |
|||
<v-list-item-action> |
|||
<v-icon class="blue--text text--lighten-2"> |
|||
mdi-map-marker |
|||
</v-icon> |
|||
</v-list-item-action> |
|||
<v-list-item-content> |
|||
<v-list-item-title>Chicago, US</v-list-item-title> |
|||
</v-list-item-content> |
|||
</v-list-item> |
|||
<v-list-item> |
|||
<v-list-item-action> |
|||
<v-icon class="blue--text text--lighten-2"> |
|||
mdi-email |
|||
</v-icon> |
|||
</v-list-item-action> |
|||
<v-list-item-content> |
|||
<v-list-item-title>john@vuetifyjs.com</v-list-item-title> |
|||
</v-list-item-content> |
|||
</v-list-item> |
|||
</v-list> |
|||
</v-card> |
|||
</v-flex> |
|||
</v-layout> |
|||
</v-container> |
|||
</section> |
|||
</v-content> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapState } from 'vuex' |
|||
|
|||
export default { |
|||
computed: mapState({ |
|||
sidebar: state => state.ui.sidebar |
|||
}), |
|||
mounted () { |
|||
console.log(this.$store) |
|||
}, |
|||
methods: { |
|||
toggle () { |
|||
this.$store.commit('ui/toggleSidebar') |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,19 @@ |
|||
<template> |
|||
<v-layout> |
|||
<v-flex class="text-center"> |
|||
<img |
|||
src="/v.png" |
|||
alt="Vuetify.js" |
|||
class="mb-5" |
|||
> |
|||
<blockquote class="blockquote"> |
|||
“First, solve the problem. Then, write the code.” |
|||
<footer> |
|||
<small> |
|||
<em>—John Johnson</em> |
|||
</small> |
|||
</footer> |
|||
</blockquote> |
|||
</v-flex> |
|||
</v-layout> |
|||
</template> |
|||
@ -0,0 +1,7 @@ |
|||
# PLUGINS |
|||
|
|||
**This directory is not required, you can delete it if you don't want to use it.** |
|||
|
|||
This directory contains Javascript plugins that you want to run before mounting the root Vue.js application. |
|||
|
|||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins). |
|||
@ -0,0 +1,19 @@ |
|||
// import Vue from 'vue'
|
|||
// import VuetifyConfirm from './vuetify-confirm.plugin'
|
|||
|
|||
// Vue.prototype.$confirm =
|
|||
// Vue.use(VuetifyConfirm)
|
|||
|
|||
import Vue from 'vue' |
|||
import VuetifyConfirm from 'vuetify-confirm' |
|||
|
|||
export default ({ app }) => { |
|||
Vue.use(VuetifyConfirm, { |
|||
vuetify: app.vuetify, |
|||
buttonTrueText: 'Confirmer', |
|||
buttonFalseText: 'Annuler', |
|||
color: 'warning', |
|||
icon: 'mdi-information', |
|||
title: 'Attention' |
|||
}) |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
# STATIC |
|||
|
|||
**This directory is not required, you can delete it if you don't want to use it.** |
|||
|
|||
This directory contains your static files. |
|||
Each file inside this directory is mapped to `/`. |
|||
Thus you'd want to delete this README.md before deploying to production. |
|||
|
|||
Example: `/static/robots.txt` is mapped as `/robots.txt`. |
|||
|
|||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static). |
|||
@ -0,0 +1,10 @@ |
|||
# STORE |
|||
|
|||
**This directory is not required, you can delete it if you don't want to use it.** |
|||
|
|||
This directory contains your Vuex Store files. |
|||
Vuex Store option is implemented in the Nuxt.js framework. |
|||
|
|||
Creating a file in this directory automatically activates the option in the framework. |
|||
|
|||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store). |
|||
@ -0,0 +1,5 @@ |
|||
export const menu = { icon: 'mdi-home', title: 'Landing Page', to: '/admin/landingpage' } |
|||
|
|||
export const state = () => ({ |
|||
list: ['users'] |
|||
}) |
|||
@ -0,0 +1,5 @@ |
|||
export const menu = { icon: 'mdi-database', title: 'Resources', to: '/admin/resources' } |
|||
|
|||
export const state = () => ({ |
|||
list: ['users'] |
|||
}) |
|||
@ -0,0 +1,43 @@ |
|||
|
|||
export const state = () => ({ |
|||
breadcrumbs: [], |
|||
title: '---', |
|||
menu: [ |
|||
{ icon: 'mdi-apps', title: 'Welcome', to: '/admin' }, |
|||
require('./landingpage').menu, |
|||
require('./resources').menu |
|||
], |
|||
snackbar: { |
|||
timeout: 6000, |
|||
color: 'error', |
|||
showIt: false, |
|||
msg: '' |
|||
} |
|||
}) |
|||
|
|||
export const mutations = { |
|||
addItem (state, item) { |
|||
state.items.push(item) |
|||
}, |
|||
setTitle (state, data) { |
|||
state.title = data |
|||
}, |
|||
setBreadcrumbs (state, data) { |
|||
data.forEach((item) => { |
|||
item.replace = true |
|||
item.nuxt = true |
|||
}) |
|||
data[data.length - 1].disabled = true |
|||
state.breadcrumbs = data |
|||
}, |
|||
snack (state, data) { |
|||
state.snackbar.showIt = true |
|||
state.snackbar.msg = data.msg |
|||
state.snackbar.color = data.color || '' |
|||
}, |
|||
snackClose (state, data) { |
|||
state.snackbar.showIt = false |
|||
} |
|||
} |
|||
|
|||
export const actions = {} |
|||
@ -0,0 +1,13 @@ |
|||
export const state = () => ({ |
|||
ssr: null, |
|||
sidebar: false |
|||
}) |
|||
|
|||
export const mutations = { |
|||
setRenderer (state, value) { |
|||
state.ssr = value |
|||
}, |
|||
toggleSidebar (state) { |
|||
state.sidebar = !state.sidebar |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
export const state = () => ({ |
|||
sidebar: false |
|||
}) |
|||
|
|||
export const mutations = { |
|||
toggleSidebar (state) { |
|||
state.sidebar = !state.sidebar |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save