Merge branch 'bulma-admin-interface' into develop

This commit is contained in:
mateuswetah 2018-02-09 09:42:04 -02:00
commit be2c280707
41 changed files with 15760 additions and 2708 deletions

41
package-lock.json generated
View File

@ -217,6 +217,7 @@
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.2.tgz",
"integrity": "sha1-t3WXIm6WJC+NUxwNRq4pX2JCK6Q=",
"dev": true,
"requires": {
"babel-runtime": "6.26.0"
}
@ -538,7 +539,8 @@
"babel-helper-vue-jsx-merge-props": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==",
"dev": true
},
"babel-helpers": {
"version": "6.24.1",
@ -1093,6 +1095,7 @@
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"dev": true,
"requires": {
"core-js": "2.5.1",
"regenerator-runtime": "0.11.0"
@ -1350,6 +1353,14 @@
"electron-to-chromium": "1.3.27"
}
},
"buefy": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/buefy/-/buefy-0.6.3.tgz",
"integrity": "sha512-ApYZo6USz1SjHyziSaZc2osxWYUkCLwfgzVDo7hTtFvqBAjin1xfzoHd7yb/7BTLqAZYwJuHqe44SnLhrU+9fg==",
"requires": {
"bulma": "0.6.2"
}
},
"buffer": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
@ -1385,6 +1396,11 @@
"integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
"dev": true
},
"bulma": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/bulma/-/bulma-0.6.2.tgz",
"integrity": "sha1-9LHRHVrMUaeWROsKKwsQZJ09cfU="
},
"bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
@ -1832,7 +1848,8 @@
"core-js": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz",
"integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs="
"integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=",
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@ -2121,7 +2138,8 @@
"deepmerge": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz",
"integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ=="
"integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==",
"dev": true
},
"define-properties": {
"version": "1.1.2",
@ -2284,6 +2302,7 @@
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.0.11.tgz",
"integrity": "sha512-jrBIuoHTx07RmgrdpkPQTj9KCFP+BNewUaVB2kkbH+MSGdurzXw8MPzH+o/RZCGIh+ODNfLa71h5veYKJysIpA==",
"dev": true,
"requires": {
"async-validator": "1.8.2",
"babel-helper-vue-jsx-merge-props": "2.0.3",
@ -4785,11 +4804,6 @@
"object-visit": "1.0.1"
}
},
"material-design-icons": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/material-design-icons/-/material-design-icons-3.0.1.tgz",
"integrity": "sha1-mnHEh0chjrylHlGmbaaCA4zct78="
},
"math-expression-evaluator": {
"version": "1.2.17",
"resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz",
@ -4818,6 +4832,11 @@
}
}
},
"mdi": {
"version": "2.1.19",
"resolved": "https://registry.npmjs.org/mdi/-/mdi-2.1.19.tgz",
"integrity": "sha512-WErwab4jq/jcCeo4aecQ5UH1WXu2Eto5Rdb0AiBFcUw8CHmF/UeV+hf9wKyH17X+c3Z+jaS3jDKW7fu0R0HmWQ=="
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@ -6630,7 +6649,8 @@
"regenerator-runtime": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz",
"integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A=="
"integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==",
"dev": true
},
"regenerator-transform": {
"version": "0.10.1",
@ -7504,7 +7524,8 @@
"throttle-debounce": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.0.1.tgz",
"integrity": "sha1-2tD+Ew+drzcZ/eoz3Dao5rp/MLU="
"integrity": "sha1-2tD+Ew+drzcZ/eoz3Dao5rp/MLU=",
"dev": true
},
"thunky": {
"version": "0.1.0",

View File

@ -9,8 +9,9 @@
},
"dependencies": {
"axios": "^0.17.1",
"element-ui": "^2.0.11",
"material-design-icons": "^3.0.1",
"buefy": "^0.6.3",
"bulma": "^0.6.2",
"mdi": "^2.1.19",
"vue": "^2.5.13",
"vuex": "^3.0.1"
},

View File

@ -1,16 +1,16 @@
<template>
<div id="tainacan-admin-app">
<el-container>
<el-header>
<router-link to="/">Home</router-link>
<router-link to="/collections">Coleções</router-link>
</el-header>
<el-container>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
<nav class="navbar is-transparent">
<div id="navbarExampleTransparentExample" class="navbar-menu">
<div class="navbar-start">
<router-link class="navbar-item" to="/">Home</router-link>
<router-link class="navbar-item" to="/collections">Coleções</router-link>
</div>
</div>
</nav>
<div class="container">
<router-view></router-view>
</div>
</div>
</template>
@ -19,35 +19,3 @@
name: "AdminPage"
}
</script>
<style scoped>
.el-header, .el-footer {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
line-height: 200px;
}
.el-main {
color: #333;
}
body > .el-container {
margin-bottom: 40px;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
</style>

View File

@ -1,30 +1,45 @@
<template>
<div>
<el-table
<router-link tag="button" class="button is-primary"
:to="{ path: `/collections/new` }">
Criar Coleção
</router-link>
<b-table
ref="multipleTable"
:data="collections"
style="width: 100%"
@selection-change="handleSelectionChange"
stripe>
<el-table-column type="selection" width="55">
</el-table-column>
<el-table-column width="55">
<template v-if="scope.row.featured_image" slot-scope="scope">
<img class="table-thumb" :src="`${scope.row.featured_image}`"/>
</template>
</el-table-column>
<el-table-column label="Nome" sortable prop="{{ scope.row.name }}" show-overflow-tooltip>
<template slot-scope="scope"><router-link :to="`/collections/${scope.row.id}`" tag="a">{{ scope.row.name }}</router-link></template>
</el-table-column>
<el-table-column property="description" label="Descrição" show-overflow-tooltip>
</el-table-column>
<el-table-column label="Ações" width="120">
<template slot-scope="scope">
<el-button size="small" type="text" @click.native="shareCollection(scope.row.id)"><i class="material-icons md-18">share</i></el-button>
<el-button size="small" type="text" @click.native="showMoreCollection(scope.row.id)"><i class="material-icons md-18">more_vert</i></el-button>
</template>
</el-table-column>
</el-table>
<template slot-scope="props">
<b-table-column field="featured_image" width="55">
<template v-if="props.row.featured_image" slot-scope="scope">
<img class="table-thumb" :src="`${props.row.featured_image}`"/>
</template>
</b-table-column>
<b-table-column label="Nome" field="props.row.name" sortable show-overflow-tooltip>
<router-link :to="`/collections/${props.row.id}`" tag="a">{{ props.row.name }}</router-link>
</b-table-column>
<b-table-column property="description" label="Descrição" field="props.row.description">
{{ props.row.description }}
</b-table-column>
<b-table-column label="Ações">
<router-link :to="`/collections/${props.row.id}/edit`" tag="a"><b-icon icon="pencil"></router-link>
<a @click.native="showMoreCollection(props.row.id)">
<b-icon icon="dots-vertical">
</a>
</b-table-column>
</template>
<!--b-table-column type="selection" width="55">
</b-table-column -->
</b-table>
</div>
</template>
@ -47,9 +62,6 @@ export default {
]),
handleSelectionChange(value) {
this.multipleSelection = value;
},
shareCollection(collectionId) {
},
showMoreCollection(collectionId) {

View File

@ -1,29 +1,43 @@
<template>
<div>
<el-table
<b-table
ref="multipleTable"
:data="items"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55">
</el-table-column>
<el-table-column width="55">
<template v-if="scope.row.featured_image" slot-scope="scope">
<img class="table-thumb" :src="`${scope.row.featured_image}`"/>
</template>
</el-table-column>
<el-table-column label="Nome" show-overflow-tooltip>
<template slot-scope="scope"><router-link :to="`/collections/${collectionId}/items/${scope.row.id}`" tag="a">{{ scope.row.title }}</router-link></template>
</el-table-column>
<el-table-column property="description" label="Descrição" show-overflow-tooltip>
</el-table-column>
<el-table-column label="Ações" width="120">
<template slot-scope="scope">
<el-button size="small" type="text" @click.native="shareItem(scope.row.id)"><i class="material-icons">share</i></el-button>
<el-button size="small" type="text" @click.native="showMoreItem(scope.row.id)"><i class="material-icons">more_vert</i></el-button>
</template>
</el-table-column>
</el-table>
@selection-change="handleSelectionChange"
stripe>
<template slot-scope="props">
<b-table-column field="featured_image" width="55">
<template v-if="props.row.featured_image" slot-scope="scope">
<img class="table-thumb" :src="`${props.row.featured_image}`"/>
</template>
</b-table-column>
<b-table-column label="Nome" field="title" sortable show-overflow-tooltip>
<router-link
:to="`/collections/${collectionId}/items/${props.row.id}`" tag="a">{{ props.row.title }}
</router-link>
</b-table-column>
<b-table-column field="description" label="Descrição">
{{ props.row.description }}
</b-table-column>
<b-table-column label="Ações">
<router-link :to="`/collections/${collectionId}/items/${props.row.id}/edit`" tag="a"><b-icon icon="pencil"></router-link>
<a @click.native="showMoreItem(props.row.id)">
<b-icon icon="dots-vertical">
</a>
</b-table-column>
</template>
<!--b-table-column type="selection" width="55">
</b-table-column -->
</b-table>
</div>
</template>

View File

@ -1,6 +1,7 @@
import Vue from 'vue'
import Buefy from 'buefy'
import ElementUI from 'element-ui'
Vue.use(Buefy);
import AdminPage from '../admin.vue'
//import { eventBus } from '../../js/event-bus-web-components'
@ -43,8 +44,6 @@ Vue.component('tainacan-form-item', TaincanFormItem);
//------------------------------------------------
Vue.use(ElementUI);
// eventBus.listener();
new Vue({

View File

@ -3,24 +3,24 @@ import VueRouter from 'vue-router'
import AdminPage from '../admin.vue'
import CollectionPage from '../pages/collection-page.vue'
import CollectionEditionPage from '../pages/collection-edition-page.vue'
import ItemPage from '../pages/item-page.vue'
import ItemEditionPage from '../pages/item-edition-page.vue'
import CollectionsList from '../components/collections-list.vue'
import ItemsList from '../components/items-list.vue'
Vue.use(VueRouter);
Vue.use(VueRouter);
const routes = [
{ path: '/', component: CollectionsList, meta: {title: 'Admin Page'} },
{ path: '/collections', component: CollectionsList, meta: {title: 'Collections List'} },
{ path: '/collections/:id', component: CollectionPage, children: [
{ path: 'items-list', component: ItemsList, meta: {title: 'Items List'} }
],
meta: { title: 'Collection Page' }
},
{ path: '/collections/new', component: CollectionEditionPage, meta: {title: 'Create Collection'} },
{ path: '/collections/:id', component: CollectionPage, meta: {title: 'Collections Page'} },
{ path: '/collections/:id/edit', component: CollectionEditionPage, meta: {title: 'Edit Collection'} },
{ path: '/collections/:id/items/new', component: ItemEditionPage, meta: {title: 'Create Item'} },
{ path: '/collections/:collection_id/items/:id/edit', component: ItemEditionPage, meta: {title: 'Edit Item'} },
{ path: '/collection/:collection_id/items', component: ItemsList, meta: {title: 'Items List'} },
{ path: '/collections/:collection_id/items/:id', component: ItemPage, meta: {title: 'Item Page'} },
{ path: '*', redirect: '/'}
]

View File

@ -0,0 +1,186 @@
<template>
<div>
<h1 class="is-size-3">Collection creation <b-tag v-if="collection != null && collection != undefined" :type="'is-' + getStatusColor(collection.status)" v-text="collection.status"></b-tag></h1>
<form label-width="120px">
<b-field label="Título">
<b-input
v-model="form.name">
</b-input>
</b-field>
<b-field label="Descrição">
<b-input
type="textarea"
v-model="form.description"
>
</b-input>
</b-field>
<b-field label="Status">
<b-select
v-model="form.status"
placeholder="Selecione um status">
<option
v-for="statusOption in statusOptions"
:key="statusOption.value"
:value="statusOption.value"
:disabled="statusOption.disabled">{{ statusOption.label }}
</option>
</b-select>
</b-field>
<b-field
label="Imagem">
<b-upload v-model="form.files"
multiple
drag-drop>
<section class="section">
<div class="content has-text-centered">
<p>
<b-icon
icon="upload"
size="is-large">
</b-icon>
</p>
<p>Arraste uma imagem aqui <em>ou clique para enviar</em></p>
</div>
</section>
</b-upload>
</b-field>
<button
class="button"
type="button"
@click="cancelBack">Cancelar</button>
<a
@click="onSubmit"
class="button is-success is-hovered">Salvar</a>
</form>
<b-loading :active.sync="isLoading" :canCancel="false">
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
name: 'CollectionEditionPage',
data(){
return {
collectionId: Number,
collection: null,
isLoading: false,
form: {
name: '',
status: '',
description: '',
files:[]
},
// Can be obtained from api later
statusOptions: [{
value: 'publish',
label: 'Publicado'
}, {
value: 'draft',
label: 'Rascunho'
}, {
value: 'private',
label: 'Privado'
}, {
value: 'trash',
label: 'Lixo'
}]
}
},
methods: {
...mapActions('collection', [
'sendCollection',
'updateCollection',
'fetchCollection'
]),
...mapGetters('collection',[
'getCollection'
]),
onSubmit() {
// Puts loading on Draft Collection creation
this.isLoading = true;
let data = {collection_id: this.collectionId, name: this.form.name, description: this.form.description, status: this.form.status};
this.updateCollection(data).then(updatedCollection => {
this.collection = updatedCollection;
// Fill this.form data with current data.
this.form.name = this.collection.name;
this.form.description = this.collection.description;
this.form.status = this.collection.status;
this.isLoading = false;
this.$router.push('/collections/' + this.collectionId);
});
},
getStatusColor(status) {
switch(status) {
case 'publish':
return 'success'
case 'draft':
return 'info'
case 'private':
return 'warning'
case 'trash':
return 'danger'
default:
return 'info'
}
},
createNewCollection() {
// Puts loading on Draft Collection creation
this.isLoading = true;
// Creates draft Collection
let data = { title: '', description: '', status: 'draft'};
this.sendCollection(data).then(res => {
this.collectionId = res.id;
this.collection = res;
// Fill this.form data with current data.
this.form.name = this.collection.name;
this.form.description = this.collection.description;
this.form.status = this.collection.status;
this.isLoading = false;
})
.catch(error => console.log(error));
},
cancelBack(){
this.$router.push('/collections/' + this.collectionId);
}
},
created(){
if (this.$route.fullPath.split("/").pop() == "new") {
this.createNewCollection();
} else if (this.$route.fullPath.split("/").pop() == "edit") {
this.isLoading = true;
// Obtains current Collection ID from URL
this.pathArray = this.$route.fullPath.split("/").reverse();
this.collectionId = this.pathArray[1];
this.fetchCollection(this.collectionId).then(res => {
this.collection = res;
// Fill this.form data with current data.
this.form.name = this.collection.name;
this.form.description = this.collection.description;
this.form.status = this.collection.status;
this.isLoading = false;
});
}
}
}
</script>

View File

@ -1,21 +1,39 @@
<template>
<div>
<el-row v-if="collection != null">
<el-card :body-style="{ padding: '0px' }" class="element-card">
<img :src="collection.featured_image" class="image" :alt="collection.name">
<div style="padding: 14px;">
<span>{{ collection.name }}</span>
<div class="bottom clearfix">
<time class="time">{{collection.description}}</time>
<router-link tag="el-button" class="primary" :to="{ path: `/collections/${collection.id}/items/new`, params: { collection_id: collection.id }}">Criar Item</router-link>
<section class="section" v-if="collection != null">
<div class="card">
<div class="card-image" v-if="collection.featured_image">
<figure class="image is-4by3">
<img :src="collection.featured_image" class="image" :alt="collection.name">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<p class="title is-4">{{ collection.name }}</p>
<!--p class="subtitle is-6">@johnsmith</p-->
</div>
</div>
<items-list :collectionId="collectionId"></items-list>
<div class="bottom clearfix">
<router-link tag="el-button" :to="{ path: `/collections/${collection.id}/items/`, params: { collection_id: collection.id }}">Ver todos os itens</router-link>
<div class="content">
{{collection.description}}
</div>
</div>
</el-card>
</el-row>
<footer class="card-footer">
<router-link
class="card-footer-item"
:to="{ path: `/collections/${collection.id}/items/new`, params: { collection_id: collection.id }}">
Criar Item
</router-link>
<router-link
class="card-footer-item"
:to="{ path: `/collection/${collection.id}/items/`, params: { collection_id: collection.id }}">
Ver todos os itens
</router-link>
</footer>
</div>
<items-list :collectionId="collectionId"></items-list>
</section>
</div>
</template>

View File

@ -1,42 +1,64 @@
<template>
<div>
<h2>Item creation</h2><el-tag v-if="item != null && item != undefined" :type="getStatusColor(item.status)" v-text="item.status"></el-tag>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form-item label="Título" prop="title">
<el-input v-model="form.title"></el-input>
</el-form-item>
<el-form-item label="Descrição">
<el-input type="textarea" v-model="form.description"></el-input>
</el-form-item>
<el-form-item label="Status">
<el-select v-model="form.status" placeholder="Selecione um status">
<el-option
v-for="statusOption in statusOptions"
:key="statusOption.value"
:label="statusOption.label"
:value="statusOption.value"
:disabled="statusOption.disabled">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="Imagem">
<el-upload
class="upload-demo"
drag
action="https://jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview"
:on-remove="handleRemove">
<i class="el-icon-upload"></i>
<div class="el-upload__text">Arraste uma imagem aqui <em>ou clique para enviar</em></div>
<div class="el-upload__tip" slot="tip">imagens em formato jpg/png</div>
</el-upload>
</el-form-item>
<tainacan-form-item v-for="(field, index) in fieldList" v-bind:key="index" :field="field"></tainacan-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">Salvar</el-button>
<el-button>Cancelar</el-button>
</el-form-item>
</el-form>
<h1 class="is-size-3">Item creation <b-tag v-if="item != null && item != undefined" :type="'is-' + getStatusColor(item.status)" v-text="item.status"></b-tag></h1>
<form label-width="120px">
<b-field label="Título">
<b-input
v-model="form.title"
>
</b-input>
</b-field>
<b-field label="Descrição">
<b-input
type="textarea"
v-model="form.description"
>
</b-input>
</b-field>
<b-field label="Status">
<b-select
v-model="form.status"
placeholder="Selecione um status">
<option
v-for="statusOption in statusOptions"
:key="statusOption.value"
:value="statusOption.value"
:disabled="statusOption.disabled">{{ statusOption.label }}
</option>
</b-select>
</b-field>
<b-field
label="Imagem">
<b-upload v-model="form.files"
multiple
drag-drop>
<section class="section">
<div class="content has-text-centered">
<p>
<b-icon
icon="upload"
size="is-large">
</b-icon>
</p>
<p>Arraste uma imagem aqui <em>ou clique para enviar</em></p>
</div>
</section>
</b-upload>
</b-field>
<tainacan-form-item
v-for="(field, index) in fieldList"
v-bind:key="index"
:field="field"></tainacan-form-item>
<button
class="button"
type="button"
@click="cancelBack">Cancelar</button>
<a
@click="onSubmit"
class="button is-success is-hovered">Salvar</a>
</form>
<b-loading :active.sync="isLoading" :canCancel="false">
</div>
</template>
@ -50,11 +72,13 @@ export default {
itemId: Number,
item: null,
collectionId: Number,
isLoading: false,
form: {
collectionId: Number,
title: '',
status: '',
description: ''
description: '',
files:[]
},
// Can be obtained from api later
statusOptions: [{
@ -69,12 +93,7 @@ export default {
}, {
value: 'trash',
label: 'Lixo'
}],
rules: {
title: [
{ required: true, message: 'Please input Activity name', trigger: 'blur' }
],
}
}]
}
},
methods: {
@ -83,7 +102,8 @@ export default {
'updateItem',
'fetchFields',
'sendField',
'fetchItem'
'fetchItem',
'cleanFields'
]),
...mapGetters('item',[
'getFields',
@ -91,7 +111,7 @@ export default {
]),
onSubmit() {
// Puts loading on Draft Item creation
let loadingInstance = this.$loading({ text: 'Salvando item ...' });
this.isLoading = true;
let data = {item_id: this.itemId, title: this.form.title, description: this.form.description, status: this.form.status};
this.updateItem(data).then(updatedItem => {
@ -103,7 +123,9 @@ export default {
this.form.description = this.item.description;
this.form.status = this.item.status;
loadingInstance.close();
this.isLoading = false;
this.$router.push('/collections/' + this.form.collectionId + '/items/' + this.itemId);
});
},
getStatusColor(status) {
@ -122,7 +144,7 @@ export default {
},
createNewItem() {
// Puts loading on Draft Item creation
let loadingInstance = this.$loading({ text: 'Criando item rascunho...' });
this.isLoading = true;
// Creates draft Item
let data = {collection_id: this.form.collectionId, title: '', description: '', status: 'draft'};
@ -136,17 +158,19 @@ export default {
this.form.description = this.item.description;
this.form.status = this.item.status;
this.loadMetadata(loadingInstance);
this.loadMetadata();
})
.catch(error => console.log(error));
},
loadMetadata(loadingInstance) {
loadingInstance = this.$loading({ text: 'Carregando metadados...'});
loadMetadata() {
// Obtains Item Field
this.fetchFields(this.itemId).then(res => {
loadingInstance.close();
this.isLoading = false;
});
},
cancelBack(){
this.$router.push('/collections/' + this.collectionId);
}
},
computed: {
@ -156,14 +180,15 @@ export default {
},
created(){
// Obtains collection ID
this.collectionId = this.$route.params.id;
this.cleanFields();
this.collectionId = ( this.$route.params.collection_id ) ? this.$route.params.collection_id : this.$route.params.id;
this.form.collectionId = this.collectionId;
if (this.$route.fullPath.split("/").pop() == "new") {
this.createNewItem();
} else if (this.$route.fullPath.split("/").pop() == "edit") {
let loadingInstance = this.$loading({ text: 'Carregando item...'});
this.isLoading = true;
// Obtains current Item ID from URL
this.pathArray = this.$route.fullPath.split("/").reverse();
@ -177,7 +202,7 @@ export default {
this.form.description = this.item.description;
this.form.status = this.item.status;
loadingInstance.close();
this.loadMetadata();
});
}

View File

@ -1,17 +1,33 @@
<template>
<div>
<el-row v-if="item != null">
<el-card :body-style="{ padding: '0px' }">
<img src="" class="image" :alt="item.title">
<div style="padding: 14px;">
<span>{{ item.title }}</span>
<div class="bottom clearfix">
<time class="time">{{item.description}}</time>
<router-link tag="el-button" class="primary" :to="{ path: `/collections/${collectionId}/items/${itemId}/edit`}">Editar Item</router-link>
<b-loading :active.sync="isLoading" :canCancel="false">
</b-loading>
<div class="card">
<div class="card-image" v-if="item.featured_image">
<figure class="image is-4by3">
<img :src="item.featured_image" class="image" :alt="item.title">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<p class="title is-4">{{ item.title }}</p>
<!--p class="subtitle is-6">@johnsmith</p-->
</div>
</div>
</el-card>
</el-row>
<div class="content">
{{item.description}}
</div>
</div>
<footer class="card-footer">
<router-link
class="card-footer-item" :to="{ path: `/collections/${collectionId}/items/${itemId}/edit`}">
Editar Item
</router-link>
</footer>
</div>
</div>
</template>
@ -23,7 +39,8 @@ export default {
data(){
return {
collectionId: Number,
itemId: Number
itemId: Number,
isLoading: false
}
},
methods: {
@ -45,11 +62,12 @@ export default {
this.itemId = this.$route.fullPath.split("/").pop();
// Puts loading on Item Loading
let loadingInstance = this.$loading({ text: 'Carregando item...' });
this.isLoading = true;
let loadingInstance = this;
// Obtains Item
this.fetchItem(this.itemId).then(res => {
loadingInstance.close();
loadingInstance.isLoading = false;
});
}

View File

@ -1,20 +1,34 @@
/* theme color */
$--color-primary:#25a189;
$--color-secondary: #01295c;
// Import Bulma's core
@import "../../../node_modules/bulma/sass/utilities/_all";
/* icon font path, required */
//$--font-path: '../../assets/css/fonts/material-icons.css';
// Tainacan custom colors
$primary: #25a189;
$primary-invert: findColorInvert($primary);
$secondary: #01295c;
$secondary-invert: findColorInvert($primary);
.el-select-dropdown, .el-popper {
z-index: 9999999 !important;
}
// Setup $colors to use as bulma classes
$colors: (
"white": ($white, $black),
"black": ($black, $white),
"light": ($light, $light-invert),
"dark": ($dark, $dark-invert),
"primary": ($primary, $primary-invert),
"info": ($info, $info-invert),
"success": ($success, $success-invert),
"warning": ($warning, $warning-invert),
"danger": ($danger, $danger-invert)
);
.el-loading-mask{
z-index: 99999999 !important;
}
// Links
$link: $primary;
$link-invert: $primary-invert;
$link-focus-border: $primary;
@import "../../assets/css/fonts/material-icons.css";
@import "../../../node_modules/element-ui/packages/theme-chalk/src/index";
// Import Bulma and Buefy styles
@import "../../assets/css/fonts/materialdesignicons.css";
@import "../../../node_modules/bulma/bulma";
@import "../../../node_modules/buefy/src/scss/buefy";
body.tainacan-admin-page #adminmenumain {
display: none;

View File

@ -190,7 +190,7 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
$field = $this->field_repository->fetch( $field_id );
$item_metadata = new Entities\Item_Metadata_Entity( $item, $field );
$item_metadata->set_value( $value );
$item_metadata->set_value( ( is_array($value) ) ? array_filter($value) : $value );
if ( $item_metadata->validate() ) {
$field_updated = $this->item_metadata_repository->update( $item_metadata );

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 275 KiB

View File

@ -1,36 +0,0 @@
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url(MaterialIcons-Regular.eot); /* For IE6-8 */
src: local('Material Icons'),
local('MaterialIcons-Regular'),
url(MaterialIcons-Regular.woff2) format('woff2'),
url(MaterialIcons-Regular.woff) format('woff'),
url(MaterialIcons-Regular.ttf) format('truetype');
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px; /* Preferred icon size */
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
}

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
<template>
<div>
<el-checkbox-group v-model="checked">
<el-checkbox
v-for="option,index in getOptions"
:key="index"
<div class="block">
<div
v-for="option,index in getOptions"
class="field">
<b-checkbox
v-model="checked"
@change="onChecked(option)"
:label="option"
border>{{ option }}</el-checkbox>
</el-checkbox-group>
:native-value="option"
>{{ option }}</b-checkbox>
</div>
</div>
</template>
@ -19,12 +19,23 @@
checked:[]
}
},
created(){
if(this.value instanceof Array)
this.checked = this.value;
},
props: {
field: {
type: Object
},
options: {
type: String
},
value: [String, Number, Array]
},
watch: {
checked: function(val){
this.checked = val;
this.onChecked();
}
},
computed: {
@ -40,7 +51,7 @@
}
},
methods: {
onChecked(option) {
onChecked() {
this.$emit('blur');
this.onInput(this.checked)
},

View File

@ -1,23 +1,15 @@
<template>
<el-date-picker
type="date"
format="dd/MM/yyyy"
value-format="dd/MM/yyyy"
:value="dateValue"
<b-datepicker
v-model="dateValue"
@blur="onBlur"
@input="onInput($event)"></el-date-picker>
@input="onInput($event)"></b-datepicker>
</template>
<script>
import lang from 'element-ui/lib/locale/lang/pt-br'
import locale from 'element-ui/lib/locale'
locale.use(lang)
export default {
data() {
return {
dateValue: ''
dateValue: new Date()
}
},
methods: {

View File

@ -1,10 +1,10 @@
<template>
<el-input-number
controls-position="right"
<b-input
type="number"
:value="inputValue"
@blur="onBlur"
@change="onBlur"
@input="onInput($event)"></el-input-number>
@input="onInput($event)"></b-input>
</template>
<script>

View File

@ -1,12 +1,13 @@
<template>
<div>
<el-radio
<b-radio
v-for="option,index in getOptions"
:key="index"
v-model="checked"
@change="onChecked(option)"
@input="onChecked(option)"
:label="option"
border>{{ option }}</el-radio>
:native-value="option"
border>{{ option }}</b-radio>
</div>
</template>

View File

@ -1,31 +1,25 @@
<template>
<div>
<el-select
<b-autocomplete
v-model="selected"
multiple
filterable
remote
reserve-keyword
:remote-method="search"
:data="options"
@input="search"
:loading="loading"
@change="onChecked()">
<el-option
v-for="option,index in options"
:key="option.value"
:label="option.label"
:value="option.value"
></el-option>
</el-select>
field="label"
@select="option => setResults(option) ">
</b-autocomplete>
</div>
</template>
<script>
import debounce from 'lodash/debounce'
import axios from '../../../js/axios/axios'
export default {
data(){
return {
selected:[],
results:'',
selected:'',
options: [],
loading: false,
collectionId: 0,
@ -41,15 +35,21 @@
}
},
methods: {
setResults(option){
if(!option)
return;
this.results = option.value;
this.onChecked()
},
onChecked() {
this.$emit('blur');
this.onInput(this.selected)
this.onInput(this.results)
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
},
search(query) {
search(query){
if (query !== '') {
this.loading = true;
this.options = [];

View File

@ -1,13 +1,13 @@
<template>
<div>
<el-select v-model="selected" @change="onChecked()">
<el-option
<b-select v-model="selected" @input="onChecked()">
<option
v-for="option,index in getOptions"
:key="index"
:label="option"
:value="option"
border>{{ option }}</el-option>
</el-select>
border>{{ option }}</option>
</b-select>
</div>
</template>
@ -25,7 +25,8 @@
},
options: {
type: String
}
},
value: [String, Number, Array],
},
computed: {
getOptions(){
@ -40,7 +41,7 @@
}
},
methods: {
onChecked(option) {
onChecked() {
this.$emit('blur');
this.onInput(this.selected)
},

View File

@ -1,15 +1,17 @@
<template>
<div>
<el-form-item :label="field.field.name" :prop="validateObject()">
<component :is="extractFieldType(field.field.field_type)" v-model="inputs[0]" :field="field" @blur="changeValue()"></component>
<div v-if="field.field.multiple == 'yes'">
<div v-if="index > 0" v-for="(input, index) in inputsList " v-bind:key="index" class="multiple-inputs">
<component :is="extractFieldType(field.field.field_type)" v-model="inputs[index]" :field="field" @blur="changeValue()"></component><el-button v-if="index > 0" @click="removeInput(index)">-</el-button>
</div>
<el-button @click="addInput">+</el-button>
<b-field :label="field.field.name"
:message="getErrorMessage"
:type="fieldTypeMessage">
<div>
<component :is="extractFieldType(field.field.field_type)" v-model="inputs[0]" :field="field" @blur="changeValue()"></component>
<div v-if="field.field.multiple == 'yes'">
<div v-if="index > 0" v-for="(input, index) in inputsList " v-bind:key="index" class="multiple-inputs">
<component :is="extractFieldType(field.field.field_type)" v-model="inputs[index]" :field="field" @blur="changeValue()"></component><a class="button" v-if="index > 0" @click="removeInput(index)">-</a>
</div>
<a class="button" @click="addInput">+</a>
</div>
</div>
</el-form-item>
</div>
</b-field>
</template>
<script>
@ -22,16 +24,31 @@
},
data(){
return {
inputs: []
inputs: [],
fieldTypeMessage:''
}
},
computed: {
inputsList() {
return this.inputs;
},
getErrorMessage() {
let msg = '';
let errors = eventBus.getErrors(this.field.field.id);
if ( errors) {
this.fieldTypeMessage = 'is-danger';
for (let index in errors) {
msg += errors[index] + '\n';
}
} else {
this.fieldTypeMessage = '';
}
return msg;
}
},
created(){
this.getValue();
},
methods: {
changeValue(){
@ -50,12 +67,6 @@
let parts = field_type.split('\\');
return 'tainacan-' + parts.pop().toLowerCase();
},
validateObject () {
return
[
{ required: this.field.field.required, message: this.message, trigger: 'blur' }
]
},
addInput(){
this.inputs.push('');
this.changeValue();

View File

@ -1,7 +1,7 @@
<template>
<el-input :value="inputValue"
<b-input :value="inputValue"
@blur="onBlur"
@input="onInput($event)"></el-input>
@input="onInput($event)"></b-input>
</template>
<script>
@ -11,6 +11,9 @@
inputValue: ''
}
},
props: {
value: [String, Number, Object],
},
methods: {
onBlur() {
this.$emit('blur');
@ -19,12 +22,9 @@
this.inputValue = $event;
this.$emit('input', this.inputValue);
}
},
created(){
this.inputValue = this.value;
}
}
</script>
<style scoped>
.multiple-inputs {
display: flex;
}
</style>
</script>

View File

@ -1,9 +1,8 @@
<template>
<el-input type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
<b-input type="textarea"
:value="inputValue"
@blur="onBlur"
@input="onInput($event)"></el-input>
@input="onInput($event)"></b-input>
</template>
<script>

View File

@ -5,7 +5,7 @@ export const eventBus = new Vue({
store,
data: {
componentsTag: [],
errors : store.getters['item/getError']
errors : []
},
created(){
if( wp_settings.components ){
@ -23,7 +23,7 @@ export const eventBus = new Vue({
const components = this.getAllComponents();
for (let eventElement of components){
eventElement.addEventListener('input', (event) => {
if ( event.detail[0] ){
if (event.detail && event.detail[0] ){
const promisse = this.$store.dispatch('item/updateMetadata',
{ item_id: $(eventElement).attr("item_id"), field_id: $(eventElement).attr("field_id"), values: event.detail });
@ -45,15 +45,30 @@ export const eventBus = new Vue({
const promisse = this.$store.dispatch('item/updateMetadata',
{ item_id: data.item_id, field_id: data.field_id, values: data.values });
promisse.then( response => {
data.instance.message = JSON.stringify( [] );
data.instance.value = response.value;
let index = this.errors.findIndex( errorItem => errorItem.field_id === data.field_id );
if ( index >= 0){
this.errors.splice( index, 1);
}
}, error => {
const field = this.errors.find(error => error.field_id === data.field_id );
eventElement.errorsMsg = JSON.stringify( field.error );
eventElement.value = data.values;
let index = this.errors.findIndex( errorItem => errorItem.field_id === data.field_id );
let messages = null;
for (let index in error) {
messages = error[index]
}
if ( index >= 0){
Vue.set( this.errors, index, { field_id: data.field_id, errors: messages });
}else{
this.errors.push( { field_id: data.field_id, errors: messages } );
}
});
}
},
getErrors(field_id){
let error = this.errors.find( errorItem => errorItem.field_id === field_id );
return ( error ) ? error.errors : false
},
setValues(){
const field = this.$store.getters['item/getMetadata'];
if( field ){
@ -92,7 +107,7 @@ export const eventBus = new Vue({
}
}
}
}
},
}
});

View File

@ -2,10 +2,12 @@ import Vue from 'vue'
// include vue-custom-element plugin to Vue
import VueCustomElement from 'vue-custom-element';
import ElementUI from 'element-ui'
import { eventBus } from './event-bus-web-components';
import Buefy from 'buefy'
Vue.use(Buefy)
Vue.use(ElementUI);
Vue.use(VueCustomElement);
import Text from '../classes/field-types/text/Text.vue';

View File

@ -19,10 +19,55 @@ export const fetchCollections = ({ commit }) => {
}
export const fetchCollection = ({ commit }, id) => {
axios.get('/collections/' + id)
return new Promise((resolve, reject) =>{
axios.get('/collections/' + id)
.then(res => {
console.log(res);
let collection = res.data;
commit('setCollection', collection);
resolve( res.data );
})
.catch(error => console.log(error));
}
.catch(error => {
console.log(error);
reject(error);
})
});
}
export const updateCollection = ({ commit }, { collection_id, name, description, status }) => {
return new Promise((resolve, reject) => {
axios.patch('/collections/' + collection_id, {
name: name,
description: description,
status: status
}).then( res => {
commit('setCollection', { id: collection_id, name: name, description: description, status: status });
resolve( res.data );
}).catch( error => {
commit('setCollection', { id: collection_id, name: name, description: description, status: status });
reject( error.response );
});
});
}
export const sendCollection = ( { commit }, { name, description, status }) => {
return new Promise(( resolve, reject ) => {
axios.post('/collections/', {
name: name,
description: description,
status: status
})
.then( res => {
commit('setCollection', { name: name, description: description, status: status });
//commit('removeError', { collection_id });
resolve( res.data );
})
.catch(error => {
console.log( 'error',error.response );
commit('setCollection', { name: name, description: description, status: status });
//commit('setError', { name: name, description: description, status: status, error: error.response.data.errors });
reject( error.response );
});
});
};

View File

@ -30,9 +30,10 @@ export const updateMetadata = ({ commit }, { item_id, field_id, values }) => {
.then( res => {
let field = res.data;
commit('setSingleField', field);
resolve(field)
})
.catch( error => {
console.log('error', error);
reject(error.response.data.errors);
})
});
};