Documents: Fix ui

pull/3890/head
Julio Montoya 4 years ago
parent 8840d3eb7e
commit dba1fed569
  1. 8
      assets/css/app.scss
  2. 62
      assets/vue/components/ActionCell.vue
  3. 183
      assets/vue/components/Toolbar.vue
  4. 11
      assets/vue/components/documents/Form.vue
  5. 8
      assets/vue/hooks/useState.js
  6. 20
      assets/vue/mixins/ListMixin.js
  7. 4
      assets/vue/store/index.js
  8. 1
      assets/vue/store/modules/crud.js
  9. 3
      assets/vue/utils/fetch.js
  10. 149
      assets/vue/views/documents/List.vue

@ -40,7 +40,7 @@
//@import "~bootstrap-select/sass/bootstrap-select"; //@import "~bootstrap-select/sass/bootstrap-select";
//@import '~pretty-checkbox/src/pretty-checkbox.scss'; //@import '~pretty-checkbox/src/pretty-checkbox.scss';
//@import '~jquery-ui/themes/base/all.css'; //@import '~jquery-ui/themes/base/all.css';
/*
@layer components { @layer components {
.card { .card {
@apply bg-white rounded shadow-lg; @apply bg-white rounded shadow-lg;
@ -62,6 +62,10 @@
@apply text-white bg-blue-700 hover:bg-blue-800; @apply text-white bg-blue-700 hover:bg-blue-800;
} }
.btn-success {
@apply text-white bg-green-700 hover:bg-green-800;
}
.btn-danger { .btn-danger {
@apply text-white bg-red-700 hover:bg-red-800; @apply text-white bg-red-700 hover:bg-red-800;
} }
@ -135,7 +139,7 @@
} }
@import "scss/index.scss"; @import "scss/index.scss";
}*/ }
a.router-link-exact-active { a.router-link-exact-active {
//@apply border-b-2 bg-gray-100 border-gray-500 text-gray-500 rounded-t; //@apply border-b-2 bg-gray-100 border-gray-500 text-gray-500 rounded-t;

@ -1,32 +1,38 @@
<template> <template>
<q-td slot="body-cell-action" auto-width> <!-- auto-width-->
<q-btn <q-td slot="body-cell-action" >
v-if="handleShow" <div class="p-4 flex flex-row gap-1">
dense <q-btn
color="secondary" v-if="handleShow"
@click="handleShow" no-caps
label="Show" dense
/> color="secondary"
<q-btn @click="handleShow"
v-if="handleEdit" label="Show"
dense />
color="secondary" <q-btn
@click="handleEdit" v-if="handleEdit"
label="Edit" no-caps
/> dense
<q-btn color="secondary"
v-if="handleDelete" @click="handleEdit"
label="Delete" label="Edit"
dense />
color="red" <q-btn
@click="confirmDeleteClick = true" v-if="handleDelete"
/> no-caps
<ConfirmDelete label="Delete"
v-if="handleDelete" dense
:show="confirmDeleteClick" color="red"
:handle-delete="handleDelete" @click="confirmDeleteClick = true"
:handle-cancel="() => (confirmDeleteClick = false)" />
/> <ConfirmDelete
v-if="handleDelete"
:show="confirmDeleteClick"
:handle-delete="handleDelete"
:handle-cancel="() => (confirmDeleteClick = false)"
/>
</div>
</q-td> </q-td>
</template> </template>

@ -1,98 +1,109 @@
<template> <template>
<q-toolbar class="q-my-md"> <div class="q-card">
<slot name="left" /> <slot name="left" />
<q-space /> <!-- <q-space />-->
<div class="p-4 flex flex-row gap-1">
<q-btn
v-if="handleList"
:loading="isLoading"
color="primary"
@click="listItem"
unelevated
>
{{ $t('List') }}
</q-btn>
<q-btn <q-btn
v-if="handleList" v-if="handleEdit"
:loading="isLoading" no-caps
color="primary" class="btn btn-primary"
@click="listItem" :loading="isLoading"
unelevated @click="editItem"
> unelevated
{{ $t('List') }} >
</q-btn> {{ $t('Edit') }}
<q-btn </q-btn>
v-if="handleEdit"
:loading="isLoading"
color="primary"
@click="editItem"
unelevated
>
{{ $t('Edit') }}
</q-btn>
<q-btn <q-btn
v-if="handleSubmit" v-if="handleSubmit"
:loading="isLoading" no-caps
color="primary" class="btn btn-primary"
@click="submitItem" :loading="isLoading"
unelevated @click="submitItem"
> unelevated
<font-awesome-icon icon="save" /> >
{{ $t('Submit') }} <font-awesome-icon icon="save" />
</q-btn> {{ $t('Submit') }}
<!-- <v-btn--> </q-btn>
<!-- v-if="handleReset"--> <!-- <v-btn-->
<!-- color="primary"--> <!-- v-if="handleReset"-->
<!-- class="ml-sm-2"--> <!-- color="primary"-->
<!-- @click="resetItem"--> <!-- class="ml-sm-2"-->
<!-- >--> <!-- @click="resetItem"-->
<!-- {{ $t('Reset') }}--> <!-- >-->
<!-- </v-btn>--> <!-- {{ $t('Reset') }}-->
<q-btn <!-- </v-btn>-->
v-if="handleDelete" <q-btn
color="red" v-if="handleDelete"
unelevated no-caps
class="ml-sm-2" class="btn btn-danger"
@click="confirmDelete = true" unelevated
> @click="confirmDelete = true"
{{ $t('Delete') }} >
</q-btn> {{ $t('Delete') }}
</q-btn>
<q-btn
v-if="handleAdd"
color="primary"
@click="addItem"
>
<font-awesome-icon icon="folder-plus" /> New folder
</q-btn>
<q-btn <!-- color="primary"-->
v-if="handleAddDocument"
color="primary"
@click="addDocument"
>
<font-awesome-icon icon="file-alt" /> New document
</q-btn>
<q-btn <q-btn
v-if="handleUploadDocument" v-if="handleAdd"
color="primary" no-caps
@click="uploadDocument" class="btn btn-primary"
> @click="addItem"
<font-awesome-icon icon="cloud-upload-alt" /> File upload >
</q-btn> <font-awesome-icon icon="folder-plus" />
New folder
</q-btn>
<!-- <DataFilter--> <q-btn
<!-- v-if="filters"--> no-caps
<!-- :handle-filter="onSendFilter"--> class="btn btn-primary"
<!-- :handle-reset="resetFilter"--> v-if="handleAddDocument"
<!-- >--> @click="addDocument"
<!-- <DocumentsFilterForm--> >
<!-- ref="filterForm"--> <font-awesome-icon icon="file-alt" /> New document
<!-- slot="filter"--> </q-btn>
<!-- :values="filters"-->
<!-- />-->
<!-- </DataFilter>-->
<ConfirmDelete <q-btn
v-if="handleDelete" no-caps
:visible="confirmDelete" class="btn btn-primary"
:handle-delete="handleDelete" v-if="handleUploadDocument"
@close="confirmDelete = false" @click="uploadDocument"
/> >
</q-toolbar> <font-awesome-icon icon="cloud-upload-alt" /> File upload
</q-btn>
<!-- <DataFilter-->
<!-- v-if="filters"-->
<!-- :handle-filter="onSendFilter"-->
<!-- :handle-reset="resetFilter"-->
<!-- >-->
<!-- <DocumentsFilterForm-->
<!-- ref="filterForm"-->
<!-- slot="filter"-->
<!-- :values="filters"-->
<!-- />-->
<!-- </DataFilter>-->
<ConfirmDelete
v-if="handleDelete"
:visible="confirmDelete"
:handle-delete="handleDelete"
@close="confirmDelete = false"
/>
</div>
</div>
</template> </template>
<script> <script>

@ -1,15 +1,13 @@
<template> <template>
<!-- @input="$v.item.title.$touch()"-->
<!-- @blur="$v.item.title.$touch()"-->
<q-input <q-input
id="item_title" id="item_title"
v-model="item.title" v-model="item.title"
:error-messages="titleErrors" :error-messages="titleErrors"
:placeholder="$t('Title')" :placeholder="$t('Title')"
required required
@input="$v.item.title.$touch()"
@blur="$v.item.title.$touch()"
/> />
</template> </template>
<script> <script>
@ -45,16 +43,15 @@ export default {
}; };
}, },
computed: { computed: {
// eslint-disable-next-line
item() { item() {
return this.initialValues || this.values; return this.initialValues || this.values;
}, },
titleErrors() { titleErrors() {
const errors = []; const errors = [];
if (!this.$v.item.title.$dirty) return errors; /*if (!this.$v.item.title.$dirty) return errors;
has(this.violations, 'title') && errors.push(this.violations.title); has(this.violations, 'title') && errors.push(this.violations.title);
!this.$v.item.title.required && errors.push(this.$t('Field is required')); !this.$v.item.title.required && errors.push(this.$t('Field is required'));*/
return errors; return errors;
}, },

@ -5,11 +5,9 @@ const toggleSidebar = () => {
isSidebarOpen.value = !isSidebarOpen.value isSidebarOpen.value = !isSidebarOpen.value
} }
const isSettingsPanelOpen = ref(false) const isSettingsPanelOpen = ref(false);
const isSearchPanelOpen = ref(false);
const isSearchPanelOpen = ref(false) const isNotificationsPanelOpen = ref(false);
const isNotificationsPanelOpen = ref(false)
export default function useState() { export default function useState() {
return { return {

@ -15,7 +15,7 @@ export default {
sortBy: 'resourceNode.title', sortBy: 'resourceNode.title',
descending: false, descending: false,
page: 1, // page to be displayed page: 1, // page to be displayed
rowsPerPage: 3, // maximum displayed rows rowsPerPage: 10, // maximum displayed rows
rowsNumber: 10, // max number of rows rowsNumber: 10, // max number of rows
}, },
nextPage: null, nextPage: null,
@ -26,7 +26,7 @@ export default {
//sortBy: [], vuetify //sortBy: [], vuetify
//sortDesc: [], , vuetify //sortDesc: [], , vuetify
page: 1, page: 1,
itemsPerPage: 3 itemsPerPage: 10
}, },
//filters: {} //filters: {}
}; };
@ -66,10 +66,13 @@ export default {
onRequest(props) { onRequest(props) {
console.log('onRequest'); console.log('onRequest');
console.log(props); console.log(props);
const { page, rowsPerPage: itemsPerPage, sortBy, descending } = props.pagination; const { page, rowsPerPage: itemsPerPage, sortBy, descending } = props.pagination;
const filter = props.filter; const filter = props.filter;
this.nextPage = page; this.nextPage = page;
if (isEmpty(this.nextPage)) {
this.nextPage = 1;
}
let params = {}; let params = {};
if (itemsPerPage > 0) { if (itemsPerPage > 0) {
@ -133,12 +136,14 @@ export default {
onSendFilter() { onSendFilter() {
this.resetList = true; this.resetList = true;
this.onUpdateOptions(this.options); this.pagination.page = 1;
this.onRequest({pagination: this.pagination})
}, },
resetFilter() { resetFilter() {
this.filters = {}; this.filters = {};
this.onUpdateOptions(this.options); this.pagination.page = 1;
this.onRequest({pagination: this.pagination})
}, },
addHandler() { addHandler() {
@ -216,7 +221,10 @@ export default {
}, },
deleteHandler(item) { deleteHandler(item) {
console.log(item); console.log(item);
this.deleteItem(item).then(() => this.onUpdateOptions(this.options)); this.pagination.page = 1;
this.deleteItem(item).then(() =>
this.onRequest({pagination: this.pagination})
);
}, },
formatDateTime formatDateTime
} }

@ -2,9 +2,9 @@ import { createStore, createLogger } from "vuex";
import notifications from './modules/notifications'; import notifications from './modules/notifications';
import SecurityModule from "./security"; import SecurityModule from "./security";
import createPersistedState from "vuex-persistedstate"; import createPersistedState from "vuex-persistedstate";
//createLogger(),
export default createStore({ export default createStore({
plugins: [createLogger(), createPersistedState()], plugins: [createPersistedState()],
modules: { modules: {
notifications, notifications,
security: SecurityModule, security: SecurityModule,

@ -94,7 +94,6 @@ export default function makeCrudModule({
.catch(e => handleError(commit, e)); .catch(e => handleError(commit, e));
}, },
del: ({ commit }, item) => { del: ({ commit }, item) => {
console.log('del'); console.log('del');
commit(ACTIONS.TOGGLE_LOADING); commit(ACTIONS.TOGGLE_LOADING);

@ -52,7 +52,6 @@ export default function(id, options = {}) {
.join('&'); .join('&');
id = `${id}?${queryString}`; id = `${id}?${queryString}`;
console.log(id, 'id'); console.log(id, 'id');
} }
@ -124,6 +123,8 @@ export default function(id, options = {}) {
}*/ }*/
return global.fetch(new URL(id, entryPoint), options).then(response => { return global.fetch(new URL(id, entryPoint), options).then(response => {
console.log(response);
if (response.ok) return response; if (response.ok) return response;
return response.json().then(json => { return response.json().then(json => {

@ -1,81 +1,80 @@
<template> <template>
<div class="q-pa-md"> <Toolbar
<Toolbar :handle-add="addHandler"
:handle-add="addHandler" :handle-add-document="addDocumentHandler"
:handle-add-document="addDocumentHandler" :handle-upload-document="uploadDocumentHandler"
:handle-upload-document="uploadDocumentHandler" :filters="filters"
:filters="filters" :on-send-filter="onSendFilter"
:on-send-filter="onSendFilter" :reset-filter="resetFilter"
:reset-filter="resetFilter" />
/>
<q-table <q-table
dense dense
flat :rows="items"
:rows="items" :columns="columns"
:columns="columns" row-key="@id"
row-key="@id" :filter="filter"
:filter="filter" @request="onRequest"
@request="onRequest" v-model:pagination="pagination"
v-model:pagination="pagination" :no-data-label="$t('Data unavailable')"
:no-data-label="$t('Data unavailable')" :no-results-label="$t('No results')"
:no-results-label="$t('No results')" :loading-label="$t('Loading...')"
:loading-label="$t('Loading...')" :rows-per-page-label="$t('Records per page:')"
:rows-per-page-label="$t('Records per page:')" :rows-per-page-options="[10, 20, 50, 0]"
:loading="isLoading" :loading="isLoading"
selection="multiple" selection="multiple"
v-model:selected="selectedItems" v-model:selected="selectedItems"
> >
<template v-slot:body="props"> <template v-slot:body="props">
<q-tr :props="props"> <q-tr :props="props">
<q-td auto-width> <q-td auto-width>
<q-checkbox dense v-model="props.selected" /> <q-checkbox dense v-model="props.selected" />
</q-td> </q-td>
<q-td key="resourceNode.title" :props="props"> <q-td key="resourceNode.title" :props="props">
<div v-if="props.row.resourceNode.resourceFile"> <div v-if="props.row.resourceNode.resourceFile">
<a <a
data-fancybox="gallery" data-fancybox="gallery"
:href="props.row.contentUrl" :href="props.row.contentUrl"
> >
<ResourceFileIcon :file="props.row" /> <ResourceFileIcon :file="props.row" />
{{ props.row.title }} {{ props.row.title }}
</a> </a>
</div> </div>
<div v-else> <div v-else>
<a @click="handleClick(props.row)" class="cursor-pointer" > <a @click="handleClick(props.row)" class="cursor-pointer" >
<font-awesome-icon <font-awesome-icon
icon="folder" icon="folder"
size="lg" size="lg"
/> />
{{ props.row.resourceNode.title }} {{ props.row.resourceNode.title }}
</a> </a>
</div> </div>
</q-td> </q-td>
<q-td key="resourceNode.updatedAt" :props="props"> <q-td key="resourceNode.updatedAt" :props="props">
{{$luxonDateTime.fromISO(props.row.resourceNode.updatedAt).toRelative() }} {{$luxonDateTime.fromISO(props.row.resourceNode.updatedAt).toRelative() }}
</q-td> </q-td>
<q-td key="resourceNode.resourceFile.size" :props="props"> <q-td key="resourceNode.resourceFile.size" :props="props">
<span v-if="props.row.resourceNode.resourceFile"> <span v-if="props.row.resourceNode.resourceFile">
{{ {{
$filters.prettyBytes(props.row.resourceNode.resourceFile.size) $filters.prettyBytes(props.row.resourceNode.resourceFile.size)
}} }}
</span> </span>
</q-td> </q-td>
<q-td key="action" :props="props">
<ActionCell
:handle-show="() => showHandler(props.row)"
:handle-edit="() => editHandler(props.row)"
:handle-delete="() => deleteHandler(props.row)"
/>
</q-td>
</q-tr>
</template>
</q-table>
<q-td key="action" :props="props">
<ActionCell
:handle-show="() => showHandler(props.row)"
:handle-edit="() => editHandler(props.row)"
:handle-delete="() => deleteHandler(props.row)"
/>
</q-td>
</q-tr>
</template>
</q-table>
</div>
</template> </template>
<script> <script>
@ -87,12 +86,8 @@ import Toolbar from '../../components/Toolbar.vue';
import ResourceFileIcon from './ResourceFileIcon.vue'; import ResourceFileIcon from './ResourceFileIcon.vue';
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
//import { useToast } from 'primevue/usetoast';
import { ref, reactive, onMounted, computed } from 'vue'; import { ref, reactive, onMounted, computed } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
/*const servicePrefix = 'documents';
const { getters, actions } = list(servicePrefix);*/
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
export default { export default {
@ -114,7 +109,7 @@ export default {
{name: 'resourceNode.resourceFile.size', label: this.$i18n.t('Size'), field: 'resourceNode.resourceFile.size', sortable: true}, {name: 'resourceNode.resourceFile.size', label: this.$i18n.t('Size'), field: 'resourceNode.resourceFile.size', sortable: true},
{name: 'action', label: this.$i18n.t('Actions'), field: 'action', sortable: false} {name: 'action', label: this.$i18n.t('Actions'), field: 'action', sortable: false}
], ],
pageOptions: [5, 10, 15, 20, this.$i18n.t('All')], //pageOptions: [5, 10, 15, 20, this.$i18n.t('All')],
selected: [], selected: [],
isBusy: false, isBusy: false,
options: [], options: [],

Loading…
Cancel
Save