mirror of https://github.com/nocodb/nocodb
20 changed files with 1905 additions and 42 deletions
@ -0,0 +1,47 @@
|
||||
<template> |
||||
<v-list dense height="20px"> |
||||
<v-list-item dense> |
||||
<v-list-item-subtitle> |
||||
<span class="caption">Categories</span> |
||||
</v-list-item-subtitle> |
||||
</v-list-item> |
||||
<v-list-item-group v-model="category"> |
||||
<v-list-item v-for="c in categories" :key="c.title" :value="c.title" dense> |
||||
<v-list-item-title> |
||||
<span |
||||
:class="{'font-weight-black' : category === c.title } " |
||||
> |
||||
{{ |
||||
c.title |
||||
}}<span /> |
||||
</span> |
||||
</v-list-item-title> |
||||
</v-list-item> |
||||
</v-list-item-group> |
||||
</v-list> |
||||
</template> |
||||
|
||||
<script> |
||||
import categories from './templates.categories' |
||||
export default { |
||||
name: "categories", |
||||
props:{value:String}, |
||||
data:()=>({ |
||||
categories |
||||
}), |
||||
computed:{ |
||||
category:{ |
||||
get(){ |
||||
return this.value; |
||||
}, |
||||
set(v){ |
||||
this.$emit('input', v) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
</style> |
@ -0,0 +1,59 @@
|
||||
<template> |
||||
<v-container class="py-0"> |
||||
<div class="d-flex"> |
||||
<v-navigation-drawer height="calc(100vh - 40px)"> |
||||
<categories @input="v => $emit('load-category', v)"/> |
||||
</v-navigation-drawer> |
||||
<v-container v-if="templateData" fluid style="height: calc(100vh - 40px ); overflow: auto"> |
||||
<v-img |
||||
:src="templateData.thumbnail" |
||||
height="200px" |
||||
/> |
||||
<div class="d-flex align-center mt-10"> |
||||
<h2 class="display-2 font-weight-bold my-0 flex-grow-1"> |
||||
{{ templateData.title }} |
||||
</h2> |
||||
<v-btn class="primary" x-large @click="useTemplate">Use template</v-btn> |
||||
</div> |
||||
<p class="caption mt-10"> |
||||
{{ templateData.description }} |
||||
</p> |
||||
|
||||
|
||||
<templat-editor view-mode :templateData="templateData"></templat-editor> |
||||
|
||||
</v-container> |
||||
</div> |
||||
</v-container> |
||||
</template> |
||||
|
||||
<script> |
||||
import categories from '~/components/templates/templates.categories' |
||||
import TemplatEditor from "~/components/templates/editor"; |
||||
import Categories from "~/components/templates/categories"; |
||||
|
||||
export default { |
||||
name: 'ProjectTemplateDetailed', |
||||
components: {Categories, TemplatEditor}, |
||||
props: { |
||||
modal: Boolean, id: [String, Number] |
||||
}, |
||||
data: () => ({categories, templateData: null}), |
||||
async mounted() { |
||||
this.templateData = (await import(`./templates.${this.modal ? this.id : this.$route.params.id}`)).default |
||||
}, methods: { |
||||
useTemplate() { |
||||
if (this.modal) { |
||||
this.$emit('import', this.templateData) |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
/deep/ .v-list-item { |
||||
min-height: 30px; |
||||
} |
||||
</style> |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,93 @@
|
||||
<template> |
||||
<v-container v-if="!modal || selectedId === null " class="py-0"> |
||||
<div class="d-flex"> |
||||
<v-navigation-drawer height="calc(100vh - 40px)"> |
||||
<categories v-model="category"></categories> |
||||
</v-navigation-drawer> |
||||
<v-container fluid style="height: calc(100vh - 40px ); overflow: auto"> |
||||
<v-row |
||||
v-if="templateList && templateList.length"> |
||||
<v-col |
||||
v-for="(template,i) in templateList" |
||||
:key="i" |
||||
sm="8" |
||||
offset-sm="2" |
||||
offset-md="0" |
||||
md="6" |
||||
lg="4" |
||||
xl="3" |
||||
@click="openTemplate(template.id)" |
||||
> |
||||
<v-card |
||||
class="mx-auto" |
||||
> |
||||
<v-img |
||||
:src="template.thumbnail" |
||||
height="200px" |
||||
/> |
||||
|
||||
<v-card-title> |
||||
{{ template.title }} |
||||
</v-card-title> |
||||
|
||||
<v-card-subtitle> |
||||
<span class="caption"> |
||||
{{ getShortDescription(template.description) }} |
||||
</span> |
||||
</v-card-subtitle> |
||||
</v-card> |
||||
</v-col> |
||||
</v-row> |
||||
<div v-else class="d-flex justify-center mt-10 "> |
||||
<v-alert class="flex-shrink-1" type="info" outlined dense > |
||||
No templates found |
||||
</v-alert> |
||||
</div> |
||||
</v-container> |
||||
</div> |
||||
</v-container> |
||||
<project-template-detailed v-else @load-category="v =>{ category = v; selectedId = null }" :id="selectedId" :modal="modal" v-on="$listeners" /> |
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
import templateList from './templates.list' |
||||
import ProjectTemplateDetailed from '~/components/templates/detailed' |
||||
import Categories from "~/components/templates/categories"; |
||||
|
||||
export default { |
||||
name: 'ProjectTemplates', |
||||
components: {Categories, ProjectTemplateDetailed }, |
||||
props: { |
||||
modal: Boolean |
||||
}, |
||||
data: () => ({ |
||||
category: null, |
||||
selectedId: null |
||||
}), |
||||
computed: { |
||||
templateList() { |
||||
return templateList.filter(t => !this.category || t.category === this.category) |
||||
} |
||||
}, |
||||
methods: { |
||||
getShortDescription(str) { |
||||
if (str.length < 200) { return str } |
||||
return `${str.slice(0, 200)}...` |
||||
}, |
||||
openTemplate(id) { |
||||
if (this.modal) { |
||||
this.selectedId = id |
||||
} else { |
||||
this.$router.push(`/project/templates/${id}`) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
/deep/ .v-list-item{ |
||||
min-height: 30px; |
||||
} |
||||
</style> |
@ -0,0 +1,81 @@
|
||||
const templates = { |
||||
title: 'Art Gallery Management', |
||||
thumbnail: 'https://picsum.photos/200/300?1', |
||||
tables: [ |
||||
{ |
||||
tn: 'blog', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
}, |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [ |
||||
{ |
||||
tn: 'comment', |
||||
_cn: 'title3' |
||||
} |
||||
], |
||||
manyToMany: [ |
||||
{ |
||||
rtn: 'tag', |
||||
_cn: 'title4' |
||||
} |
||||
], |
||||
v: [ |
||||
{ |
||||
_cn: 'comments_count', |
||||
rl: { |
||||
rltn: 'comment', |
||||
rlcn: 'body', |
||||
type: 'hm', |
||||
fn: 'count' |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
tn: 'comment', |
||||
columns: [ |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [ |
||||
{ |
||||
_cn: 'blog_title', |
||||
lk: { |
||||
ltn: 'blog', |
||||
type: 'bt', |
||||
lcn: 'title' |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
tn: 'tag', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
} |
||||
], |
||||
category: 'test', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
|
||||
} |
||||
|
||||
export default templates |
@ -0,0 +1,62 @@
|
||||
const templates = { |
||||
title: 'Digital video production', |
||||
thumbnail: 'https://picsum.photos/200/300?2', |
||||
tables: [ |
||||
{ |
||||
tn: 'blog', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
}, |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [ |
||||
{ |
||||
tn: 'comment', |
||||
_cn: 'title3' |
||||
} |
||||
], |
||||
manyToMany: [ |
||||
{ |
||||
rtn: 'tag', |
||||
_cn: 'title4' |
||||
} |
||||
], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'comment', |
||||
columns: [ |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'tag', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
} |
||||
], |
||||
category: 'test', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
|
||||
} |
||||
|
||||
export default templates |
@ -0,0 +1,62 @@
|
||||
const templates = { |
||||
title: 'Content calendar', |
||||
thumbnail: 'https://picsum.photos/200/300?3', |
||||
tables: [ |
||||
{ |
||||
tn: 'blog', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
}, |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [ |
||||
{ |
||||
tn: 'comment', |
||||
_cn: 'title3' |
||||
} |
||||
], |
||||
manyToMany: [ |
||||
{ |
||||
rtn: 'tag', |
||||
_cn: 'title4' |
||||
} |
||||
], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'comment', |
||||
columns: [ |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'tag', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
} |
||||
], |
||||
category: 'test', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
|
||||
} |
||||
|
||||
export default templates |
@ -0,0 +1,62 @@
|
||||
const templates = { |
||||
title: 'Event Marketing', |
||||
thumbnail: 'https://picsum.photos/200/300?3', |
||||
tables: [ |
||||
{ |
||||
tn: 'blog', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
}, |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [ |
||||
{ |
||||
tn: 'comment', |
||||
_cn: 'title3' |
||||
} |
||||
], |
||||
manyToMany: [ |
||||
{ |
||||
rtn: 'tag', |
||||
_cn: 'title4' |
||||
} |
||||
], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'comment', |
||||
columns: [ |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'tag', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
} |
||||
], |
||||
category: 'test', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
|
||||
} |
||||
|
||||
export default templates |
@ -0,0 +1,62 @@
|
||||
const templates = { |
||||
title: 'Wedding Planning', |
||||
thumbnail: 'https://picsum.photos/200/300?5', |
||||
tables: [ |
||||
{ |
||||
tn: 'blog', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
}, |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [ |
||||
{ |
||||
tn: 'comment', |
||||
_cn: 'title3' |
||||
} |
||||
], |
||||
manyToMany: [ |
||||
{ |
||||
rtn: 'tag', |
||||
_cn: 'title4' |
||||
} |
||||
], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'comment', |
||||
columns: [ |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'tag', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
} |
||||
], |
||||
category: 'test', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
|
||||
} |
||||
|
||||
export default templates |
@ -0,0 +1,26 @@
|
||||
const categories = [ |
||||
{ title: 'Content production' }, |
||||
{ title: 'Featured' }, |
||||
{ title: 'Creative' }, |
||||
{ title: 'Event Planning' }, |
||||
{ title: 'Everyday Life' }, |
||||
{ title: 'Groups, Clubs & Hobbies' }, |
||||
{ title: 'HR & Recruiting' }, |
||||
{ title: 'Legal' }, |
||||
{ title: 'Local Business' }, |
||||
{ title: 'Marketing' }, |
||||
{ title: 'Nonprofit' }, |
||||
{ title: 'Personal' }, |
||||
{ title: 'PR & Communications' }, |
||||
{ title: 'Product, design, and UX' }, |
||||
{ title: 'Project Management' }, |
||||
{ title: 'Publishing' }, |
||||
{ title: 'Real Estate' }, |
||||
{ title: 'Remote work' }, |
||||
{ title: 'Sales & Customers' }, |
||||
{ title: 'Software Development' }, |
||||
{ title: 'Startup' }, |
||||
{ title: 'Venture Capital' } |
||||
] |
||||
|
||||
export default categories |
@ -0,0 +1,61 @@
|
||||
const templates = { |
||||
title: 'Project name', |
||||
tables: [ |
||||
{ |
||||
tn: 'blog', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
}, |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [ |
||||
{ |
||||
tn: 'comment', |
||||
_cn: 'title3' |
||||
} |
||||
], |
||||
manyToMany: [ |
||||
{ |
||||
rtn: 'tag', |
||||
_cn: 'title4' |
||||
} |
||||
], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'comment', |
||||
columns: [ |
||||
{ |
||||
cn: 'body', |
||||
uidt: 'LongText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
}, |
||||
{ |
||||
tn: 'tag', |
||||
columns: [ |
||||
{ |
||||
cn: 'title', |
||||
uidt: 'SingleLineText' |
||||
} |
||||
], |
||||
hasMany: [], |
||||
manyToMany: [], |
||||
v: [] |
||||
} |
||||
], |
||||
category: 'test', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
|
||||
} |
||||
|
||||
export default templates |
@ -0,0 +1,38 @@
|
||||
const templatesList = [{ |
||||
id: 1, |
||||
title: 'Art Gallery Management', |
||||
category: 'Creative', |
||||
thumbnail: 'https://picsum.photos/200/300?1', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
}, { |
||||
id: 2, |
||||
title: 'Digital video production', |
||||
category: 'Creative', |
||||
thumbnail: 'https://picsum.photos/200/300?2', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
}, { |
||||
id: 3, |
||||
title: 'Content calendar', |
||||
category: 'Creative', |
||||
thumbnail: 'https://picsum.photos/200/300?3', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
}, { |
||||
id: 4, |
||||
title: 'Event Marketing', |
||||
category: 'Event Planning', |
||||
thumbnail: 'https://picsum.photos/200/300?4', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
}, { |
||||
id: 5, |
||||
title: 'Wedding Planning', |
||||
category: 'Event Planning', |
||||
thumbnail: 'https://picsum.photos/200/300?5', |
||||
tags: 'a,b,c', |
||||
description: 'I\'m a thing. But, like most politicians, he promised more than he could deliver. You won\'t have time for sleeping, soldier, not with all the bed making you\'ll be doing. Then we\'ll go with that data file! Hey, you add a one and two zeros to that or we walk!' |
||||
}] |
||||
|
||||
export default templatesList |
@ -0,0 +1,42 @@
|
||||
<template> |
||||
<div> |
||||
<span class="caption font-weight-bold" @click="templatesModal = true">Templates</span> |
||||
<v-dialog v-model="templatesModal" v-if="templatesModal"> |
||||
<v-card> |
||||
<project-templates modal @import="importTemplate" /> |
||||
</v-card> |
||||
</v-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import ProjectTemplates from '~/components/templates/list' |
||||
export default { |
||||
name: 'TemplatesModal', |
||||
components: { ProjectTemplates }, |
||||
data: () => ({ |
||||
templatesModal: false |
||||
}), |
||||
methods: { |
||||
importTemplate(template) { |
||||
try { |
||||
this.$store.dispatch('sqlMgr/ActSqlOp', [{ |
||||
// todo: extract based on active |
||||
dbAlias: 'db', // this.nodes.dbAlias, |
||||
env: '_noco' |
||||
}, 'xcModelsCreateFromTemplate', { |
||||
template |
||||
}]) |
||||
this.$toast.success('Template imported successfully').goAway(3000); |
||||
this.templatesModal = false; |
||||
} catch (e) { |
||||
this.$toast.error(e.message).goAway(3000) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
</style> |
@ -0,0 +1,15 @@
|
||||
<template> |
||||
<project-template /> |
||||
</template> |
||||
|
||||
<script> |
||||
import ProjectTemplate from '~/components/templates/detailed' |
||||
export default { |
||||
name: '_id.vue', |
||||
components: { ProjectTemplate } |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
</style> |
@ -0,0 +1,16 @@
|
||||
<template> |
||||
<project-templates /> |
||||
</template> |
||||
<script> |
||||
|
||||
import ProjectTemplates from '~/components/templates/list' |
||||
export default { |
||||
components: { |
||||
ProjectTemplates |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
</style> |
Loading…
Reference in new issue