2
0
mirror of https://github.com/frappe/books.git synced 2025-02-04 13:08:29 +00:00

Merge pull request #75 from surajshetty3416/master

[Feature] Form links and Report onload filtes
This commit is contained in:
Faris Ansari 2018-07-14 23:31:10 +05:30 committed by GitHub
commit 4a242426c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 138 additions and 67 deletions

3
.prettierrc Normal file
View File

@ -0,0 +1,3 @@
{
"singleQuote": true
}

View File

@ -2,8 +2,7 @@
<button type="button" <button type="button"
:class="['btn btn-sm', 'btn-' + Object.keys(props).find(key => ['primary', 'secondary', 'light', 'dark', 'danger'].includes(key))]" :class="['btn btn-sm', 'btn-' + Object.keys(props).find(key => ['primary', 'secondary', 'light', 'dark', 'danger'].includes(key))]"
v-bind="data.attrs" v-bind="data.attrs"
v-on="listeners" v-on="listeners">
>
<slot></slot> <slot></slot>
</button> </button>
</template> </template>

View File

@ -0,0 +1,29 @@
<template>
<div class="dropdown show">
<a class="btn btn-sm btn-secondary dropdown-toggle"
href="#"
role="button"
:id="_uid"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
{{ label }}
</a>
<div class="dropdown-menu dropdown-menu-right" :aria-labelledby="_uid">
<a class="dropdown-item"
v-for="option in options"
:key="option.label"
@click="option.handler">
{{ option.label }}
</a>
</div>
</div>
</template>
<script>
export default {
props: ['label', 'options']
};
</script>
<style>
</style>

View File

@ -3,6 +3,7 @@
<form-actions <form-actions
v-if="shouldRenderForm" v-if="shouldRenderForm"
:doc="doc" :doc="doc"
:links="links"
@save="save" @save="save"
@submit="submit" @submit="submit"
@revert="revert" @revert="revert"
@ -37,8 +38,9 @@ export default {
docLoaded: false, docLoaded: false,
notFound: false, notFound: false,
invalid: false, invalid: false,
invalidFields: [] invalidFields: [],
} links: []
};
}, },
computed: { computed: {
meta() { meta() {
@ -70,6 +72,8 @@ export default {
} catch (e) { } catch (e) {
this.notFound = true; this.notFound = true;
} }
this.setLinks();
this.doc.on('change', this.setLinks);
}, },
methods: { methods: {
async save() { async save() {
@ -91,6 +95,21 @@ export default {
} }
}, },
setLinks() {
if (this.meta.links) {
let links = [];
for (let link of this.meta.links) {
if (link.condition(this)) {
link.handler = () => {
link.action(this);
};
links.push(link);
}
}
this.links = links;
}
},
async submit() { async submit() {
this.doc.set('submitted', 1); this.doc.set('submitted', 1);
await this.save(); await this.save();
@ -105,7 +124,9 @@ export default {
if (!isValid && !this.invalidFields.includes(fieldname)) { if (!isValid && !this.invalidFields.includes(fieldname)) {
this.invalidFields.push(fieldname); this.invalidFields.push(fieldname);
} else if (isValid) { } else if (isValid) {
this.invalidFields = this.invalidFields.filter(invalidField => invalidField !== fieldname) this.invalidFields = this.invalidFields.filter(
invalidField => invalidField !== fieldname
);
} }
}, },
@ -113,7 +134,7 @@ export default {
const form = this.$el.querySelector('form'); const form = this.$el.querySelector('form');
let validity = form.checkValidity(); let validity = form.checkValidity();
this.invalid = !validity; this.invalid = !validity;
}, }
} }
}; };
</script> </script>

View File

@ -1,16 +1,23 @@
<template> <template>
<div class="frappe-form-actions d-flex justify-content-between align-items-center p-3 border-bottom"> <div class="frappe-form-actions d-flex justify-content-between align-items-center p-3 border-bottom">
<h5 class="m-0">{{ title }}</h5> <h5 class="m-0">{{ title }}</h5>
<div class="d-flex">
<f-button primary v-if="isDirty" @click="$emit('save')">{{ _('Save') }}</f-button> <f-button primary v-if="isDirty" @click="$emit('save')">{{ _('Save') }}</f-button>
<f-button primary v-if="showSubmit" @click="$emit('submit')">{{ _('Submit') }}</f-button> <f-button primary v-if="showSubmit" @click="$emit('submit')">{{ _('Submit') }}</f-button>
<f-button secondary v-if="showRevert" @click="$emit('revert')">{{ _('Revert') }}</f-button> <f-button secondary v-if="showRevert" @click="$emit('revert')">{{ _('Revert') }}</f-button>
<dropdown class="ml-2" v-if="links.length" :label="'Next Action'" :options="links"></dropdown>
</div>
</div> </div>
</template> </template>
<script> <script>
import frappe from 'frappejs'; import frappe from 'frappejs';
import Dropdown from '../Dropdown';
export default { export default {
props: ['doc'], props: ['doc', 'links'],
components: {
Dropdown
},
data() { data() {
return { return {
isDirty: false, isDirty: false,

View File

@ -4,40 +4,49 @@
v-for="docfield in filters" v-for="docfield in filters"
:key="docfield.fieldname" :key="docfield.fieldname"
:docfield="docfield" :docfield="docfield"
:value="$data[docfield.fieldname]" :value="$data.filterValues[docfield.fieldname]"
@change="updateValue(docfield.fieldname, $event)"/> @change="updateValue(docfield.fieldname, $event)"/>
</div> </div>
</template> </template>
<script> <script>
import FrappeControl from 'frappejs/ui/components/controls/FrappeControl' import FrappeControl from 'frappejs/ui/components/controls/FrappeControl';
export default { export default {
props: ['filters'], props: ['filters', 'filterDefaults'],
data() { data() {
const filterValues = {}; const filterValues = {};
for (let filter of this.filters) { for (let filter of this.filters) {
filterValues[filter.fieldname] = ''; filterValues[filter.fieldname] =
this.filterDefaults[filter.fieldname] || null;
} }
return { filterValues }; return { filterValues };
}, },
created() {
const hasOnloadFilters = Object.values(this.filterValues).filter(
value => value !== null
).length;
if (hasOnloadFilters) {
this.$emit('change', this.filterValues);
}
},
provide() { provide() {
return { return {
dynamicLinkTarget: (reference) => { dynamicLinkTarget: reference => {
return this.filterValues[reference] return this.filterValues[reference];
} }
}; };
}, },
methods: { methods: {
updateValue(fieldname, value) { updateValue(fieldname, value) {
this.filterValues[fieldname] = value; this.filterValues[fieldname] = value;
this.$emit('change', this.filterValues) this.$emit('change', this.filterValues);
} }
}, },
components: { components: {
FrappeControl FrappeControl
} }
} };
</script> </script>
<style> <style>
</style> </style>

View File

@ -2,43 +2,46 @@
<div> <div>
<div class="p-4"> <div class="p-4">
<h4 class="pb-2">{{ reportConfig.title }}</h4> <h4 class="pb-2">{{ reportConfig.title }}</h4>
<report-filters v-if="reportConfig.filterFields.length" :filters="reportConfig.filterFields" @change="getReportData"></report-filters> <report-filters v-if="reportConfig.filterFields.length" :filters="reportConfig.filterFields" :filterDefaults="filters" @change="getReportData"></report-filters>
<div class="pt-2" ref="datatable" v-once></div> <div class="pt-2" ref="datatable" v-once></div>
</div> </div>
<not-found v-if="!reportConfig" /> <not-found v-if="!reportConfig" />
</div> </div>
</template> </template>
<script> <script>
import DataTable from 'frappe-datatable' import DataTable from 'frappe-datatable';
import frappe from 'frappejs' import frappe from 'frappejs';
import ReportFilters from './ReportFilters' import ReportFilters from './ReportFilters';
import utils from 'frappejs/client/ui/utils' import utils from 'frappejs/client/ui/utils';
export default { export default {
props: ['reportName', 'reportConfig'], name: 'Report',
props: ['reportName', 'reportConfig', 'filters'],
computed: { computed: {
reportColumns() { reportColumns() {
return utils.convertFieldsToDatatableColumns(this.reportConfig.getColumns()) return utils.convertFieldsToDatatableColumns(
this.reportConfig.getColumns()
);
} }
}, },
methods: { methods: {
getReportData(filters) { getReportData(filters) {
frappe.methods[this.reportConfig.method](filters).then(data => { frappe.methods[this.reportConfig.method](filters).then(data => {
if (this.datatable) { if (this.datatable) {
this.datatable.refresh(data || []) this.datatable.refresh(data || []);
} else { } else {
this.datatable = new DataTable(this.$refs.datatable, { this.datatable = new DataTable(this.$refs.datatable, {
columns: this.reportColumns, columns: this.reportColumns,
data: data || [], data: data || []
}); });
} }
}) });
} }
}, },
components: { components: {
ReportFilters, ReportFilters
}
} }
};
</script> </script>
<style> <style>
</style> </style>