CustomizationsModal.vue - add a way for users to customize css of their invoices and store it per team,

fix print styles for invoices,
add keys to translations with default English values
This commit is contained in:
Marek Fraczyk
2021-05-18 15:57:48 +03:00
parent 8846d52faf
commit 0f9f9d84a5
16 changed files with 173 additions and 10 deletions

View File

@ -0,0 +1,5 @@
{
"title": "Customize your invoices",
"textarea_label": "Insert your custom CSS",
"updated": "Updated"
}

View File

@ -1,6 +1,10 @@
{ {
"back": "ব্যাক", "back": "ব্যাক",
"book": "বুক", "book": "বুক",
"design_and_layout": "Design & layout",
"compact": "Compact",
"comfortable": "Comfortable",
"customize": "Customize",
"download_pdf": "ডাউনলোড পিডিএফ", "download_pdf": "ডাউনলোড পিডিএফ",
"delete": "ডিলিট", "delete": "ডিলিট",
"delete_modal": { "delete_modal": {

View File

@ -0,0 +1,5 @@
{
"title": "Customize your invoices",
"textarea_label": "Insert your custom CSS",
"updated": "Updated"
}

View File

@ -1,9 +1,10 @@
{ {
"back": "Back", "back": "Back",
"book": "Book", "book": "Book",
"density": "Density", "design_and_layout": "Design & layout",
"compact": "Compact", "compact": "Compact",
"comfortable": "Comfortable", "comfortable": "Comfortable",
"customize": "Customize",
"download_pdf": "Download PDF", "download_pdf": "Download PDF",
"delete": "Delete", "delete": "Delete",
"delete_modal": { "delete_modal": {

View File

@ -0,0 +1,5 @@
{
"title": "Customize your invoices",
"textarea_label": "Insert your custom CSS",
"updated": "Updated"
}

View File

@ -1,6 +1,10 @@
{ {
"back": "Atrás", "back": "Atrás",
"book": "Libro", "book": "Libro",
"design_and_layout": "Design & layout",
"compact": "Compact",
"comfortable": "Comfortable",
"customize": "Customize",
"download_pdf": "Descargar PDF", "download_pdf": "Descargar PDF",
"delete": "Eliminar", "delete": "Eliminar",
"delete_modal": { "delete_modal": {

View File

@ -0,0 +1,5 @@
{
"title": "Customize your invoices",
"textarea_label": "Insert your custom CSS",
"updated": "Updated"
}

View File

@ -1,6 +1,10 @@
{ {
"back": "Tagasi", "back": "Tagasi",
"book": "Kinnita", "book": "Kinnita",
"design_and_layout": "Design & layout",
"compact": "Compact",
"comfortable": "Comfortable",
"customize": "Customize",
"download_pdf": "Lae alla PDF", "download_pdf": "Lae alla PDF",
"delete": "Kustuta", "delete": "Kustuta",
"delete_modal": { "delete_modal": {

View File

@ -0,0 +1,5 @@
{
"title": "Customize your invoices",
"textarea_label": "Insert your custom CSS",
"updated": "Updated"
}

View File

@ -1,6 +1,10 @@
{ {
"back": "بازگشت", "back": "بازگشت",
"book": "کتاب", "book": "کتاب",
"design_and_layout": "Design & layout",
"compact": "Compact",
"comfortable": "Comfortable",
"customize": "Customize",
"download_pdf": "بارگیری PDF", "download_pdf": "بارگیری PDF",
"delete": "حذف", "delete": "حذف",
"delete_modal": { "delete_modal": {

View File

@ -10,7 +10,6 @@
box-shadow: $box-shadow-light-1; box-shadow: $box-shadow-light-1;
font-size: 16px; font-size: 16px;
line-height: 24px; line-height: 24px;
font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
} }
&__row { &__row {
@ -36,18 +35,26 @@
@page { @page {
size: A4; size: A4;
margin: 0; margin: 0;
//-webkit-print-color-adjust: exact;
} }
@media print { @media print {
html, body { html, body {
width: 210mm; width: 210mm;
height: 297mm; height: 297mm;
color: $dark; //color: $dark;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
} }
.table { .table {
color: $dark; //color: $dark;
td, th {
background-color: inherit !important;
}
} }
.invoice-box { .invoice-box {
box-shadow: none; box-shadow: none;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
} }
} }

View File

@ -0,0 +1,85 @@
<template>
<BModal v-model="isOpen"
centered
hide-footer
:title="$t('title')"
size="lg"
scrollable
content-class="bg-base dp--24 text-center">
<AppTextarea :value="team.custom_css"
@change="updateProp({ custom_css: $event })"
:label="$t('textarea_label')"
field="custom_css"
:errors="errors"
input-classes="min-vh-50 text-monospace"
class="text-left"/>
</BModal>
</template>
<script>
import { BModal } from 'bootstrap-vue';
import AppTextarea from '@/components/form/AppTextarea';
import Errors from '@/utils/errors';
import NotificationService from '@/services/notification.service';
import { mapGetters } from 'vuex';
export default {
i18nOptions: {
namespaces: 'customizations-modal',
},
data() {
return {
errors: new Errors(),
};
},
components: {
BModal,
AppTextarea,
},
computed: {
isOpen: {
get() {
return this.$store.state.invoices.isCustomizationsModalOpen;
},
set(val) {
this.$store.commit('invoices/isCustomizationsModalOpen', val);
},
},
...mapGetters({
team: 'teams/team',
}),
},
watch: {
team() {
this.updateStyleEl(this.team.custom_css);
}
},
created() {
this.initStyleEl();
},
methods: {
initStyleEl() {
const styleEl = document.createElement('style');
styleEl.setAttribute('id', 'custom-styles');
styleEl.setAttribute('type', 'text/css');
document.head.appendChild(styleEl);
},
updateStyleEl(styles) {
const styleEl = document.getElementById('custom-styles');
styleEl.innerHTML = styles;
},
close() {
this.isOpen = false;
},
updateProp(props) {
this.errors.clear();
this.$store.dispatch('teams/updateTeam', props)
.then(() => {
NotificationService.success(this.$t('updated'));
this.updateStyleEl(props.custom_css);
})
.catch(err => this.errors.set(err.errors));
},
},
};
</script>

View File

@ -20,10 +20,13 @@
<template slot="button-content"> <template slot="button-content">
<i class="material-icons">more_vert</i> <i class="material-icons">more_vert</i>
</template> </template>
<b-dropdown-group :header="$t('density')"> <b-dropdown-group :header="$t('design_and_layout')">
<b-dropdown-item-button @click="toggleCompact"> <b-dropdown-item-button @click="toggleCompact">
{{ invoice.is_compact ? $t('comfortable') : $t('compact') }} {{ invoice.is_compact ? $t('comfortable') : $t('compact') }}
</b-dropdown-item-button> </b-dropdown-item-button>
<b-dropdown-item-button @click="openCustomizationsModal">
{{ $t('customize') }}
</b-dropdown-item-button>
</b-dropdown-group> </b-dropdown-group>
<b-dropdown-divider/> <b-dropdown-divider/>
<b-dropdown-item-button @click="print">{{ $t('download_pdf') }}</b-dropdown-item-button> <b-dropdown-item-button @click="print">{{ $t('download_pdf') }}</b-dropdown-item-button>
@ -37,11 +40,18 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import NotificationService from '@/services/notification.service'; import NotificationService from '@/services/notification.service';
import { BDropdown, BDropdownDivider, BDropdownGroup, BDropdownItemButton } from 'bootstrap-vue'; import {
BDropdown,
BDropdownDivider,
BDropdownGroup,
BDropdownItemButton,
} from 'bootstrap-vue';
import AppSelect from '@/components/form/AppSelect'; import AppSelect from '@/components/form/AppSelect';
export default { export default {
i18nOptions: { namespaces: ['invoice-controls', 'statuses'] }, i18nOptions: {
namespaces: ['invoice-controls', 'statuses'],
},
components: { components: {
BDropdown, BDropdown,
BDropdownDivider, BDropdownDivider,
@ -106,6 +116,9 @@ export default {
toggleCompact() { toggleCompact() {
this.updateProp({ is_compact: !this.invoice.is_compact }); this.updateProp({ is_compact: !this.invoice.is_compact });
}, },
openCustomizationsModal() {
this.$store.commit('invoices/isCustomizationsModalOpen', true);
},
print() { print() {
window.print(); window.print();
}, },

View File

@ -16,14 +16,14 @@ export default {
state: { state: {
errors: new Errors(), errors: new Errors(),
invoiceId: null, invoiceId: null,
isSendModalOpen: false, isCustomizationsModalOpen: false,
}, },
mutations: { mutations: {
invoiceId(state, invoiceId) { invoiceId(state, invoiceId) {
state.invoiceId = invoiceId; state.invoiceId = invoiceId;
}, },
isSendModalOpen(state, isSendModalOpen) { isCustomizationsModalOpen(state, isCustomizationsModalOpen) {
state.isSendModalOpen = isSendModalOpen; state.isCustomizationsModalOpen = isCustomizationsModalOpen;
}, },
setErrors(state, errors) { setErrors(state, errors) {
state.errors.set(errors); state.errors.set(errors);

View File

@ -2,6 +2,18 @@ import { Model } from '@vuex-orm/core';
import { uuidv4 } from '@/utils/helpers'; import { uuidv4 } from '@/utils/helpers';
import TeamField from '@/store/models/team-field'; import TeamField from '@/store/models/team-field';
const customCSS = `
/* @import url('https://fonts.googleapis.com/css2?family=Work+Sans:wght@300&display=swap');
.invoice-box:after {
background: linear-gradient(to bottom, #1C7CE0, #150051);
}
.invoice-box {
font-family: 'Work Sans', sans-serif;
} */
`;
export default class Team extends Model { export default class Team extends Model {
// This is the name used as module name of the Vuex Store. // This is the name used as module name of the Vuex Store.
static entity = 'teams'; static entity = 'teams';
@ -25,6 +37,7 @@ export default class Team extends Model {
updated_at: this.attr(''), updated_at: this.attr(''),
created_at: this.attr(''), created_at: this.attr(''),
logo_url: this.attr(''), logo_url: this.attr(''),
custom_css: this.attr(customCSS),
}; };
} }
} }

View File

@ -10,6 +10,7 @@
</div> </div>
</div> </div>
</div> </div>
<CustomizationsModal/>
<ClientModal v-if="team"/> <ClientModal v-if="team"/>
<TeamModal v-if="team"/> <TeamModal v-if="team"/>
<BankAccountModal v-if="team"/> <BankAccountModal v-if="team"/>
@ -24,6 +25,7 @@ import BankAccountModal from '@/components/bank-accounts/BankAccountModal';
import { VBTooltip } from 'bootstrap-vue'; import { VBTooltip } from 'bootstrap-vue';
import TeamModal from '@/components/team/TeamModal'; import TeamModal from '@/components/team/TeamModal';
import TheFooter from '@/components/TheFooter'; import TheFooter from '@/components/TheFooter';
import CustomizationsModal from '@/components/invoices/CustomizationsModal';
import ImportModal from '../../components/ImportModal'; import ImportModal from '../../components/ImportModal';
export default { export default {
@ -36,6 +38,7 @@ export default {
ImportModal, ImportModal,
BankAccountModal, BankAccountModal,
ClientModal, ClientModal,
CustomizationsModal,
}, },
computed: { computed: {
...mapGetters({ ...mapGetters({