Merge branch 'akaunting:master' into master
This commit is contained in:
		| @@ -264,8 +264,8 @@ export default { | ||||
|         }, | ||||
|  | ||||
|         sendEmailShow: { | ||||
|             type: Number, | ||||
|             default: 1, | ||||
|             type: [String, Number, Array, Object, Boolean], | ||||
|             default: '1', | ||||
|             description: "Created recurring model send automatically option" | ||||
|         }, | ||||
|         sendEmailText: { | ||||
|   | ||||
| @@ -15,33 +15,34 @@ | ||||
|                 <span v-if="filter.operator" class="flex items-center bg-purple-lighter text-black border-2 border-body border-l border-r border-t-0 border-b-0 mt-3 px-3 py-4 text-sm cursor-pointer el-tag el-tag--small el-tag-operator" style="margin-left:0; margin-right:0;"> | ||||
|                     <span v-if="filter.operator == '='" class="material-icons text-2xl">drag_handle</span> | ||||
|                     <span v-else-if="filter.operator == '><'" class="material-icons text-2xl transform rotate-90">height</span> | ||||
|                     <span v-else class="w-5"> | ||||
|                         <img :src="not_equal_image" class="w-5 h-5 object-cover block" /> | ||||
|                     </span> | ||||
|  | ||||
|                     <img v-else :src="not_equal_image" class="w-5 h-5 object-cover block" /> | ||||
|  | ||||
|                     <i v-if="!filter.value" class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close " style="font-size: 16px;" @click="onFilterDelete(index)"></i> | ||||
|                     <i v-if="!filter.value" class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close" style="font-size: 16px;" @click="onFilterDelete(index)"></i> | ||||
|                 </span> | ||||
|  | ||||
|                 <span v-if="filter.value" class="flex items-center bg-purple-lighter text-black border-0 mt-3 px-3 py-4 text-sm cursor-pointer el-tag el-tag--small  el-tag-value"> | ||||
|                 <span v-if="filter.value" class="flex items-center bg-purple-lighter text-black border-0 mt-3 px-3 py-4 text-sm cursor-pointer el-tag el-tag--small el-tag-value"> | ||||
|                     {{ filter.value }} | ||||
|  | ||||
|                     <i class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close " style="font-size: 16px;" @click="onFilterDelete(index)"></i> | ||||
|                     <i class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close" style="font-size: 16px;" @click="onFilterDelete(index)"></i> | ||||
|                 </span> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="relative w-full h-full flex"> | ||||
|             <input | ||||
|             v-if="!show_date" | ||||
|             type="text" | ||||
|             class="w-full h-12 lg:h-auto bg-transparent text-black text-sm border-0 pb-0 focus:outline-none focus:ring-transparent focus:border-purple-100" | ||||
|             :class="!show_icon ? 'ltr:pr-4 rtl:pl-4' : 'ltr:pr-10 rtl:pl-10'" | ||||
|             :placeholder="dynamicPlaceholder" | ||||
|             :ref="'input-search-field-' + _uid" | ||||
|             v-model="search" | ||||
|             @focus="onInputFocus" | ||||
|             @input="onInput" | ||||
|             @blur="onBlur" | ||||
|             @keyup.enter="onInputConfirm" | ||||
|                 v-if="!show_date" | ||||
|                 type="text" | ||||
|                 class="w-full h-12 lg:h-auto bg-transparent text-black text-sm border-0 pb-0 focus:outline-none focus:ring-transparent focus:border-purple-100" | ||||
|                 :class="!show_icon ? 'ltr:pr-4 rtl:pl-4' : 'ltr:pr-10 rtl:pl-10'" | ||||
|                 :placeholder="dynamicPlaceholder" | ||||
|                 :ref="'input-search-field-' + _uid" | ||||
|                 v-model="search" | ||||
|                 @focus="onInputFocus" | ||||
|                 @input="onInput" | ||||
|                 @blur="onBlur" | ||||
|                 @keyup.enter="onInputConfirm" | ||||
|             /> | ||||
|  | ||||
|             <flat-picker | ||||
| @@ -148,47 +149,57 @@ export default { | ||||
|             default: 'Search or filter results...', | ||||
|             description: 'Input placeholder' | ||||
|         }, | ||||
|  | ||||
|         selectPlaceholder: { | ||||
|             type: String, | ||||
|         }, | ||||
|  | ||||
|         enterPlaceholder: { | ||||
|             type: String, | ||||
|         }, | ||||
|  | ||||
|         searchText: { | ||||
|             type: String, | ||||
|             default: 'Search for this text', | ||||
|             description: 'Input placeholder' | ||||
|         }, | ||||
|  | ||||
|         operatorIsText: { | ||||
|             type: String, | ||||
|             default: 'is', | ||||
|             description: 'Operator is "="' | ||||
|         }, | ||||
|  | ||||
|         operatorIsNotText: { | ||||
|             type: String, | ||||
|             default: 'is not', | ||||
|             description: 'Operator is not "!="' | ||||
|         }, | ||||
|  | ||||
|         noDataText: { | ||||
|             type: String, | ||||
|             default: 'No Data', | ||||
|             description: "Selectbox empty options message" | ||||
|         }, | ||||
|  | ||||
|         noMatchingDataText: { | ||||
|             type: String, | ||||
|             default: 'No Matchign Data', | ||||
|             description: "Selectbox search option not found item message" | ||||
|         }, | ||||
|  | ||||
|         value: { | ||||
|             type: String, | ||||
|             default: null, | ||||
|             description: 'Search attribute value' | ||||
|         }, | ||||
|  | ||||
|         filters: { | ||||
|             type: Array, | ||||
|             default: () => [], | ||||
|             description: 'List of filters' | ||||
|         }, | ||||
|  | ||||
|         defaultFiltered: { | ||||
|             type: Array, | ||||
|             default: () => [], | ||||
| @@ -196,7 +207,6 @@ export default { | ||||
|         }, | ||||
|  | ||||
|         dateConfig: null | ||||
|  | ||||
|     }, | ||||
|  | ||||
|     model: { | ||||
| @@ -317,7 +327,7 @@ export default { | ||||
|         onInput(evt) { | ||||
|             this.search = evt.target.value; | ||||
|             this.show_button = true; | ||||
|              | ||||
|  | ||||
|             let option_url = this.selected_options.length > 0 && this.selected_options[this.filter_index] !== undefined ? this.selected_options[this.filter_index].url : ''; | ||||
|  | ||||
|             if (this.search) { | ||||
| @@ -423,10 +433,12 @@ export default { | ||||
|  | ||||
|             let option = false; | ||||
|             let option_url = false; | ||||
|             let option_fields = {}; | ||||
|  | ||||
|             for (let i = 0; i < this.filter_list.length; i++) { | ||||
|                 if (this.filter_list[i].key == value) { | ||||
|                     option = this.filter_list[i].value; | ||||
|                     option_fields = (this.filter_list[i]['value_option_fields']) ? this.filter_list[i].value_option_fields : {}; | ||||
|  | ||||
|                     if (this.filter_list[i].values !== 'undefined' && Object.keys(this.filter_list[i].values).length) { | ||||
|                         this.option_values[value] = this.convertOption(this.filter_list[i].values); | ||||
| @@ -475,7 +487,7 @@ export default { | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (!this.option_values[value] && option_url) { | ||||
|             if (! this.option_values[value] && option_url) { | ||||
|                 if (option_url.indexOf('limit') === -1) { | ||||
|                     option_url += ' limit:10'; | ||||
|                 } | ||||
| @@ -487,11 +499,19 @@ export default { | ||||
|                     this.values = []; | ||||
|  | ||||
|                     data.forEach(function (item) { | ||||
|                         this.values.push({ | ||||
|                             key: (item.code) ? item.code : item.id, | ||||
|                             value: (item.title) ? item.title : (item.display_name) ? item.display_name : item.name, | ||||
|                             level: (item.level) ? item.level : null, | ||||
|                         }); | ||||
|                         if (Object.keys(option_fields).length) { | ||||
|                             this.values.push({ | ||||
|                                 key: (option_fields['key']) ? item[option_fields['key']] : (item.code) ? item.code : item.id, | ||||
|                                 value: (option_fields['value']) ? item[option_fields['value']] : (item.title) ? item.title : (item.display_name) ? item.display_name : item.name, | ||||
|                                 level: (option_fields['level']) ? item[option_fields['level']] : (item.level) ? item.level : null, | ||||
|                             }); | ||||
|                         } else { | ||||
|                             this.values.push({ | ||||
|                                 key: (item.code) ? item.code : item.id, | ||||
|                                 value: (item.title) ? item.title : (item.display_name) ? item.display_name : item.name, | ||||
|                                 level: (item.level) ? item.level : null, | ||||
|                             }); | ||||
|                         } | ||||
|                     }, this); | ||||
|  | ||||
|                     this.option_values[value] = this.values; | ||||
| @@ -617,7 +637,7 @@ export default { | ||||
|             this.selected_values.splice(index, 1); | ||||
|  | ||||
|             this.show_date = false; | ||||
|              | ||||
|  | ||||
|             if (this.filter_index == 0) { | ||||
|                 this.onChangeSearchAndFilterText(this.defaultPlaceholder, true); | ||||
|                 this.show_close_icon = false; | ||||
| @@ -647,7 +667,7 @@ export default { | ||||
|             let values = []; | ||||
|  | ||||
|             // Option set sort_option data | ||||
|             if (!Array.isArray(options)) { | ||||
|             if (! Array.isArray(options)) { | ||||
|                 for (const [key, value] of Object.entries(options)) { | ||||
|                     values.push({ | ||||
|                         key: (key).toString(), | ||||
| @@ -850,6 +870,7 @@ export default { | ||||
|             this.values.sort(function (a, b) { | ||||
|                 var nameA = a.value.toUpperCase(); // ignore upper and lowercase | ||||
|                 var nameB = b.value.toUpperCase(); // ignore upper and lowercase | ||||
|  | ||||
|                 if (nameA < nameB) { | ||||
|                     return -1; | ||||
|                 } | ||||
| @@ -857,6 +878,7 @@ export default { | ||||
|                 if (nameA > nameB) { | ||||
|                     return 1; | ||||
|                 } | ||||
|  | ||||
|                 // names must be equal | ||||
|                 return 0; | ||||
|             }); | ||||
| @@ -936,7 +958,7 @@ export default { | ||||
|  | ||||
|     .searh-field .btn:not(:disabled):not(.disabled):active:focus, | ||||
|     .searh-field .btn:not(:disabled):not(.disabled).active:focus { | ||||
|     -webkit-box-shadow: none !important; | ||||
|         -webkit-box-shadow: none !important; | ||||
|         box-shadow: none !important; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <template> | ||||
|   <div class="card-item relative w-2/4 lg:w-3/4 h-48 m-auto" :class="{ '-active' : isCardFlipped }"> | ||||
|   <div class="card-item relative w-2/4 lg:w-3/4 h-48 m-auto my-5" :class="{ '-active' : isCardFlipped }"> | ||||
|     <div class="card-item__side h-full rounded-lg shadow-lg overflow-hidden" style="transform: perspective(2000px) rotateY(0deg) rotateX(0deg) rotate(0deg); | ||||
|   transform-style: preserve-3d; | ||||
|   transition: all 0.8s cubic-bezier(0.71, 0.03, 0.56, 0.85); | ||||
|   | ||||
| @@ -1,204 +1,257 @@ | ||||
| <template> | ||||
|   <div | ||||
|     @click="tryClose" | ||||
|     data-notify="container" | ||||
|     class="alert alert-notify fixed w-full sm:w-500 flex items-center justify-between ltr:right-0 rtl:left-0 sm:ltr:right-4 sm:rtl:left-4 p-4 text-black font-bold rounded-lg z-30" | ||||
|     :class="[ | ||||
|       { 'alert-with-icon': icon }, | ||||
|       verticalAlign, | ||||
|       horizontalAlign, | ||||
|       alertType | ||||
|     ]" | ||||
|     role="alert" | ||||
|     :style="customPosition" | ||||
|     data-notify-position="top-center" | ||||
|   > | ||||
|   <div class="flex items-center ltr:pr-3 rtl:pl-3"> | ||||
|     <template v-if="icon || $slots.icon"> | ||||
|       <slot name="icon"> | ||||
|             <span class="alert-icon flex items-center ltr:mr-2 rtl:ml-2" data-notify="icon"> | ||||
|               <span class="material-icons text-2xl">{{ icon }}</span> | ||||
|     <div | ||||
|         @click="tryClose" | ||||
|         data-notify="container" | ||||
|         :class="[ | ||||
|             'alert alert-notify', | ||||
|             'fixed w-full sm:w-500 flex items-center justify-between', | ||||
|             { | ||||
|                 'rtl:right-0 ltr:left-0' : horizontalAlign == 'left', | ||||
|                 'sm:rtl:right-4 sm:ltr:left-4' : horizontalAlign == 'left', | ||||
|             }, | ||||
|             { | ||||
|                 'ltr:right-0 rtl:left-0' : horizontalAlign == 'right', | ||||
|                 'sm:ltr:right-4 sm:rtl:left-4' : horizontalAlign == 'right', | ||||
|             }, | ||||
|             'p-4', | ||||
|             'text-black font-bold', | ||||
|             'rounded-lg', | ||||
|             'z-30', | ||||
|             {  | ||||
|                 'alert-with-icon': icon | ||||
|             }, | ||||
|             verticalAlign, | ||||
|             horizontalAlign, | ||||
|             alertType | ||||
|         ]" | ||||
|         role="alert" | ||||
|         :style="customPosition" | ||||
|         data-notify-position="top-center" | ||||
|     > | ||||
|         <div class="flex items-center ltr:pr-3 rtl:pl-3"> | ||||
|             <template v-if="icon || $slots.icon"> | ||||
|                 <slot name="icon"> | ||||
|                     <span class="alert-icon flex items-center ltr:mr-2 rtl:ml-2" data-notify="icon"> | ||||
|                         <span class="material-icons text-2xl">{{ icon }}</span> | ||||
|                     </span> | ||||
|                 </slot> | ||||
|             </template> | ||||
|  | ||||
|             <span class="alert-text"> | ||||
|                 <span v-if="title" class="title"> | ||||
|                     <b>{{ title }}<br/></b> | ||||
|                 </span> | ||||
|  | ||||
|                 <span v-if="message" v-html="message"></span> | ||||
|  | ||||
|                 <content-render v-if="!message && component" :component="component"></content-render> | ||||
|             </span> | ||||
|       </slot> | ||||
|     </template> | ||||
|         </div> | ||||
|  | ||||
|     <span class="alert-text"> | ||||
|       <span v-if="title" class="title"> | ||||
|         <b>{{ title }}<br/></b> | ||||
|       </span> | ||||
|       <span v-if="message" v-html="message"></span> | ||||
|       <content-render | ||||
|         v-if="!message && component" | ||||
|         :component="component" | ||||
|       ></content-render> | ||||
|     </span> | ||||
|   </div> | ||||
|  | ||||
|     <slot name="dismiss-icon"> | ||||
|       <button type="button" | ||||
|               class="close text-2xl" | ||||
|               data-dismiss="alert" | ||||
|               aria-label="Close" | ||||
|               @click="close"> | ||||
|         <span aria-hidden="true">×</span> | ||||
|       </button> | ||||
|     </slot> | ||||
|   </div> | ||||
|         <slot name="dismiss-icon"> | ||||
|             <button type="button" | ||||
|                 class="close text-2xl" | ||||
|                 data-dismiss="alert" | ||||
|                 aria-label="Close" | ||||
|                 @click="close" | ||||
|             > | ||||
|                 <span aria-hidden="true">×</span> | ||||
|             </button> | ||||
|         </slot> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'notification', | ||||
|     components: { | ||||
|       contentRender: { | ||||
|         props: ['component'], | ||||
|         render: h => h(this.component) | ||||
|       } | ||||
|     }, | ||||
|     props: { | ||||
|       message: String, | ||||
|       title: { | ||||
|         type: String, | ||||
|         description: 'Notification title' | ||||
|       }, | ||||
|       icon: { | ||||
|         type: String, | ||||
|         description: 'Notification icon' | ||||
|       }, | ||||
|       verticalAlign: { | ||||
|         type: String, | ||||
|         default: 'top', | ||||
|         validator: value => { | ||||
|           let acceptedValues = ['top', 'bottom']; | ||||
|           return acceptedValues.indexOf(value) !== -1; | ||||
|     export default { | ||||
|         name: 'notification', | ||||
|  | ||||
|         components: { | ||||
|             contentRender: { | ||||
|                 props: ['component'], | ||||
|                 render: h => h(this.component) | ||||
|             } | ||||
|         }, | ||||
|         description: 'Vertical alignment of notification (top|bottom)' | ||||
|       }, | ||||
|       horizontalAlign: { | ||||
|         type: String, | ||||
|         default: 'right', | ||||
|         validator: value => { | ||||
|           let acceptedValues = ['left', 'center', 'right']; | ||||
|           return acceptedValues.indexOf(value) !== -1; | ||||
|  | ||||
|         props: { | ||||
|             message: String, | ||||
|  | ||||
|             title: { | ||||
|                 type: String, | ||||
|                 description: 'Notification title' | ||||
|             }, | ||||
|  | ||||
|             icon: { | ||||
|                 type: String, | ||||
|                 description: 'Notification icon' | ||||
|             }, | ||||
|  | ||||
|             verticalAlign: { | ||||
|                 type: String, | ||||
|                 default: 'top', | ||||
|                 validator: value => { | ||||
|                     let acceptedValues = ['top', 'bottom']; | ||||
|  | ||||
|                     return acceptedValues.indexOf(value) !== -1; | ||||
|                 }, | ||||
|                 description: 'Vertical alignment of notification (top|bottom)' | ||||
|             }, | ||||
|  | ||||
|             horizontalAlign: { | ||||
|                 type: String, | ||||
|                 default: 'right', | ||||
|                 validator: value => { | ||||
|                     let acceptedValues = ['left', 'center', 'right']; | ||||
|  | ||||
|                     return acceptedValues.indexOf(value) !== -1; | ||||
|                 }, | ||||
|                 description: 'Horizontal alignment of notification (left|center|right)' | ||||
|             }, | ||||
|  | ||||
|             type: { | ||||
|                 type: String, | ||||
|                 default: 'info', | ||||
|                 validator: value => { | ||||
|                     let acceptedValues = [ | ||||
|                         'default', | ||||
|                         'info', | ||||
|                         'primary', | ||||
|                         'danger', | ||||
|                         'warning', | ||||
|                         'success' | ||||
|                     ]; | ||||
|  | ||||
|                     return acceptedValues.indexOf(value) !== -1; | ||||
|                 }, | ||||
|                 description: 'Notification type of notification (gray-300|blue-300|gray-300|red-300|orange-300|green-300)' | ||||
|             }, | ||||
|  | ||||
|             timeout: { | ||||
|                 type: Number, | ||||
|                 default: 5000, | ||||
|                 validator: value => { | ||||
|                     return value >= 0; | ||||
|                 }, | ||||
|                 description: 'Notification timeout (closes after X milliseconds). Default is 5000 (5s)' | ||||
|             }, | ||||
|  | ||||
|             timestamp: { | ||||
|                 type: Date, | ||||
|                 default: () => new Date(), | ||||
|                 description: 'Notification timestamp (used internally to handle notification removal correctly)' | ||||
|             }, | ||||
|  | ||||
|             component: { | ||||
|                 type: [Object, Function], | ||||
|                 description: 'Custom content component. Cane be a `.vue` component or render function' | ||||
|             }, | ||||
|  | ||||
|             showClose: { | ||||
|                 type: Boolean, | ||||
|                 default: true, | ||||
|                 description: 'Whether to show close button' | ||||
|             }, | ||||
|  | ||||
|             closeOnClick: { | ||||
|                 type: Boolean, | ||||
|                 default: true, | ||||
|                 description: 'Whether to close notification when clicking it\' body' | ||||
|             }, | ||||
|  | ||||
|             clickHandler: { | ||||
|                 type: Function, | ||||
|                 description: 'Custom notification click handler' | ||||
|             } | ||||
|         }, | ||||
|         description: 'Horizontal alignment of notification (left|center|right)' | ||||
|       }, | ||||
|       type: { | ||||
|         type: String, | ||||
|         default: 'info', | ||||
|         validator: value => { | ||||
|           let acceptedValues = [ | ||||
|             'default', | ||||
|             'info', | ||||
|             'primary', | ||||
|             'danger', | ||||
|             'warning', | ||||
|             'success' | ||||
|           ]; | ||||
|           return acceptedValues.indexOf(value) !== -1; | ||||
|  | ||||
|         data() { | ||||
|             return { | ||||
|                 elmHeight: 0, | ||||
|  | ||||
|                 typeByClass: { | ||||
|                     'default': 'black-100', | ||||
|                     'info':    'blue-100', | ||||
|                     'primary': 'black-100', | ||||
|                     'danger':  'red-100', | ||||
|                     'warning': 'orange-100', | ||||
|                     'success': 'green-100', | ||||
|                 }, | ||||
|  | ||||
|                 textByClass: { | ||||
|                     'default': 'black-600', | ||||
|                     'info':    'blue-600', | ||||
|                     'primary': 'black-600', | ||||
|                     'danger':  'red-600', | ||||
|                     'warning': 'orange-600', | ||||
|                     'success': 'green-600', | ||||
|                 } | ||||
|             }; | ||||
|         }, | ||||
|         description: 'Notification type of notification (gray-300|blue-300|gray-300|red-300|orange-300|green-300)' | ||||
|       }, | ||||
|       timeout: { | ||||
|         type: Number, | ||||
|         default: 5000, | ||||
|         validator: value => { | ||||
|           return value >= 0; | ||||
|  | ||||
|         computed: { | ||||
|             hasIcon() { | ||||
|                 return this.icon && this.icon.length > 0; | ||||
|             }, | ||||
|  | ||||
|             alertType() { | ||||
|                 return `bg-${this.typeByClass[this.type]} text-${this.textByClass[this.type]}`; | ||||
|             }, | ||||
|  | ||||
|             customPosition() { | ||||
|                 let initialMargin = 20; | ||||
|                 let alertHeight = this.elmHeight + 10; | ||||
|  | ||||
|                 let sameAlertsCount = this.$notifications.state.filter(alert => { | ||||
|                     return ( | ||||
|                         alert.horizontalAlign === this.horizontalAlign && | ||||
|                         alert.verticalAlign === this.verticalAlign && | ||||
|                         alert.timestamp <= this.timestamp | ||||
|                     ); | ||||
|                 }).length; | ||||
|  | ||||
|                 if (this.$notifications.settings.overlap) { | ||||
|                     sameAlertsCount = 1; | ||||
|                 } | ||||
|  | ||||
|                 let pixels = (sameAlertsCount - 1) * alertHeight + initialMargin; | ||||
|  | ||||
|                 if (sameAlertsCount > 1) { | ||||
|                     pixels = 30 + this.$parent.children[sameAlertsCount - 2].elm.offsetHeight; | ||||
|                 } | ||||
|  | ||||
|                 let styles = {}; | ||||
|  | ||||
|                 if (this.verticalAlign === 'top') { | ||||
|                     styles.top = `${pixels}px`; | ||||
|                 } else { | ||||
|                     styles.bottom = `${pixels}px`; | ||||
|                 } | ||||
|  | ||||
|                 return styles; | ||||
|             } | ||||
|         }, | ||||
|         description: 'Notification timeout (closes after X milliseconds). Default is 5000 (5s)' | ||||
|       }, | ||||
|       timestamp: { | ||||
|         type: Date, | ||||
|         default: () => new Date(), | ||||
|         description: 'Notification timestamp (used internally to handle notification removal correctly)' | ||||
|       }, | ||||
|       component: { | ||||
|         type: [Object, Function], | ||||
|         description: 'Custom content component. Cane be a `.vue` component or render function' | ||||
|       }, | ||||
|       showClose: { | ||||
|         type: Boolean, | ||||
|         default: true, | ||||
|         description: 'Whether to show close button' | ||||
|       }, | ||||
|       closeOnClick: { | ||||
|         type: Boolean, | ||||
|         default: true, | ||||
|         description: 'Whether to close notification when clicking it\' body' | ||||
|       }, | ||||
|       clickHandler: { | ||||
|         type: Function, | ||||
|         description: 'Custom notification click handler' | ||||
|       } | ||||
|     }, | ||||
|     data() { | ||||
|       return { | ||||
|         elmHeight: 0, | ||||
|         typeByClass: { | ||||
|           'default': 'black-100', | ||||
|           'info':    'blue-100', | ||||
|           'primary': 'black-100', | ||||
|           'danger':  'red-100', | ||||
|           'warning': 'orange-100', | ||||
|           'success': 'green-100', | ||||
|  | ||||
|         methods: { | ||||
|             close() { | ||||
|                 this.$emit('close', this.timestamp); | ||||
|             }, | ||||
|  | ||||
|             tryClose(evt) { | ||||
|                 if (this.clickHandler) { | ||||
|                     this.clickHandler(evt, this); | ||||
|                 } | ||||
|  | ||||
|                 if (this.closeOnClick) { | ||||
|                     this.close(); | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         textByClass: { | ||||
|           'default': 'black-600', | ||||
|           'info':    'blue-600', | ||||
|           'primary': 'black-600', | ||||
|           'danger':  'red-600', | ||||
|           'warning': 'orange-600', | ||||
|           'success': 'green-600', | ||||
|         } | ||||
|       }; | ||||
|     }, | ||||
|     computed: { | ||||
|       hasIcon() { | ||||
|         return this.icon && this.icon.length > 0; | ||||
|       }, | ||||
|       alertType() { | ||||
|         return `bg-${this.typeByClass[this.type]} text-${this.textByClass[this.type]}`; | ||||
|       }, | ||||
|       customPosition() { | ||||
|         let initialMargin = 20; | ||||
|         let alertHeight = this.elmHeight + 10; | ||||
|         let sameAlertsCount = this.$notifications.state.filter(alert => { | ||||
|           return ( | ||||
|             alert.horizontalAlign === this.horizontalAlign && | ||||
|             alert.verticalAlign === this.verticalAlign && | ||||
|             alert.timestamp <= this.timestamp | ||||
|           ); | ||||
|         }).length; | ||||
|         if (this.$notifications.settings.overlap) { | ||||
|           sameAlertsCount = 1; | ||||
|         } | ||||
|         let pixels = (sameAlertsCount - 1) * alertHeight + initialMargin; | ||||
|         let styles = {}; | ||||
|         if (this.verticalAlign === 'top') { | ||||
|           styles.top = `${pixels}px`; | ||||
|         } else { | ||||
|           styles.bottom = `${pixels}px`; | ||||
|         } | ||||
|         return styles; | ||||
|       } | ||||
|     }, | ||||
|     methods: { | ||||
|       close() { | ||||
|         this.$emit('close', this.timestamp); | ||||
|       }, | ||||
|       tryClose(evt) { | ||||
|         if (this.clickHandler) { | ||||
|           this.clickHandler(evt, this); | ||||
|         } | ||||
|         if (this.closeOnClick) { | ||||
|           this.close(); | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     mounted() { | ||||
|       this.elmHeight = this.$el.clientHeight; | ||||
|       if (this.timeout) { | ||||
|         setTimeout(this.close, this.timeout); | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
| </script> | ||||
|  | ||||
|         mounted() { | ||||
|             this.elmHeight = this.$el.clientHeight; | ||||
|  | ||||
|             if (this.timeout) { | ||||
|                 setTimeout(this.close, this.timeout); | ||||
|             } | ||||
|         }, | ||||
|     }; | ||||
| </script> | ||||
|   | ||||
| @@ -1,55 +1,63 @@ | ||||
| <template> | ||||
|   <div class="notifications"> | ||||
|     <slide-y-up-transition :duration="transitionDuration" | ||||
|                              group | ||||
|                              mode="out-in"> | ||||
|       <notification | ||||
|         v-for="notification in notifications" | ||||
|         v-bind="notification" | ||||
|         :clickHandler="notification.onClick" | ||||
|         :key="notification.timestamp.getTime()" | ||||
|         @close="removeNotification" | ||||
|       > | ||||
|       </notification> | ||||
|     </slide-y-up-transition> | ||||
|   </div> | ||||
|     <div class="notifications"> | ||||
|         <slide-y-up-transition :duration="transitionDuration" | ||||
|             group | ||||
|             mode="out-in" | ||||
|         > | ||||
|             <notification | ||||
|                 v-for="notification in notifications" | ||||
|                 v-bind="notification" | ||||
|                 :clickHandler="notification.onClick" | ||||
|                 :key="notification.timestamp.getTime()" | ||||
|                 @close="removeNotification" | ||||
|             > | ||||
|             </notification> | ||||
|         </slide-y-up-transition> | ||||
|     </div> | ||||
| </template> | ||||
| <script> | ||||
|   import Notification from './Notification.vue'; | ||||
|   import { SlideYUpTransition } from 'vue2-transitions'; | ||||
|  | ||||
|   export default { | ||||
|     components: { | ||||
|       SlideYUpTransition, | ||||
|       Notification | ||||
|     }, | ||||
|     props: { | ||||
|       transitionDuration: { | ||||
|         type: Number, | ||||
|         default: 200 | ||||
|       }, | ||||
|       overlap: { | ||||
|         type: Boolean, | ||||
|         default: false | ||||
|       } | ||||
|     }, | ||||
|     data() { | ||||
|       return { | ||||
|         notifications: this.$notifications.state | ||||
|       }; | ||||
|     }, | ||||
|     methods: { | ||||
|       removeNotification(timestamp) { | ||||
|         this.$notifications.removeNotification(timestamp); | ||||
|       } | ||||
|     }, | ||||
|     created() { | ||||
|       this.$notifications.settings.overlap = this.overlap; | ||||
|     }, | ||||
|     watch: { | ||||
|       overlap: function (newVal) { | ||||
|         this.$notifications.settings.overlap = newVal; | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
| <script> | ||||
|     import Notification from './Notification.vue'; | ||||
|     import { SlideYUpTransition } from 'vue2-transitions'; | ||||
|  | ||||
|     export default { | ||||
|         components: { | ||||
|             SlideYUpTransition, | ||||
|             Notification | ||||
|         }, | ||||
|  | ||||
|         props: { | ||||
|             transitionDuration: { | ||||
|                 type: Number, | ||||
|                 default: 200 | ||||
|             }, | ||||
|  | ||||
|             overlap: { | ||||
|                 type: Boolean, | ||||
|                 default: false | ||||
|             } | ||||
|         }, | ||||
|  | ||||
|         data() { | ||||
|             return { | ||||
|                 notifications: this.$notifications.state | ||||
|             }; | ||||
|         }, | ||||
|  | ||||
|         methods: { | ||||
|             removeNotification(timestamp) { | ||||
|                 this.$notifications.removeNotification(timestamp); | ||||
|             } | ||||
|         }, | ||||
|  | ||||
|         created() { | ||||
|             this.$notifications.settings.overlap = this.overlap; | ||||
|         }, | ||||
|  | ||||
|         watch: { | ||||
|             overlap: function (newVal) { | ||||
|                 this.$notifications.settings.overlap = newVal; | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| </script> | ||||
|   | ||||
| @@ -1,66 +1,81 @@ | ||||
| import Notifications from './Notifications.vue'; | ||||
|  | ||||
| const NotificationStore = { | ||||
|   state: [], // here the notifications will be added | ||||
|   settings: { | ||||
|     overlap: false, | ||||
|     verticalAlign: 'top', | ||||
|     horizontalAlign: 'right', | ||||
|     type: 'info', | ||||
|     timeout: 5000, | ||||
|     closeOnClick: true, | ||||
|     showClose: true | ||||
|   }, | ||||
|   setOptions(options) { | ||||
|     this.settings = Object.assign(this.settings, options); | ||||
|   }, | ||||
|   removeNotification(timestamp) { | ||||
|     const indexToDelete = this.state.findIndex(n => n.timestamp === timestamp); | ||||
|     if (indexToDelete !== -1) { | ||||
|       this.state.splice(indexToDelete, 1); | ||||
|     state: [], // here the notifications will be added | ||||
|  | ||||
|     settings: { | ||||
|         overlap: false, | ||||
|         verticalAlign: 'top', | ||||
|         horizontalAlign: 'right', | ||||
|         type: 'info', | ||||
|         timeout: 5000, | ||||
|         closeOnClick: true, | ||||
|         showClose: true | ||||
|     }, | ||||
|  | ||||
|     setOptions(options) { | ||||
|         this.settings = Object.assign(this.settings, options); | ||||
|     }, | ||||
|  | ||||
|     removeNotification(timestamp) { | ||||
|         const indexToDelete = this.state.findIndex(n => n.timestamp === timestamp); | ||||
|  | ||||
|         if (indexToDelete !== -1) { | ||||
|             this.state.splice(indexToDelete, 1); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     addNotification(notification) { | ||||
|         if (typeof notification === 'string' || notification instanceof String) { | ||||
|             notification = {  | ||||
|                 message: notification | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         notification.timestamp = new Date(); | ||||
|  | ||||
|         notification.timestamp.setMilliseconds( | ||||
|             notification.timestamp.getMilliseconds() + this.state.length | ||||
|         ); | ||||
|  | ||||
|         notification = Object.assign({}, this.settings, notification); | ||||
|  | ||||
|         this.state.push(notification); | ||||
|     }, | ||||
|  | ||||
|     notify(notification) { | ||||
|         if (Array.isArray(notification)) { | ||||
|             notification.forEach(notificationInstance => { | ||||
|                 this.addNotification(notificationInstance); | ||||
|             }); | ||||
|         } else { | ||||
|             this.addNotification(notification); | ||||
|         } | ||||
|     } | ||||
|   }, | ||||
|   addNotification(notification) { | ||||
|     if (typeof notification === 'string' || notification instanceof String) { | ||||
|       notification = { message: notification }; | ||||
|     } | ||||
|     notification.timestamp = new Date(); | ||||
|     notification.timestamp.setMilliseconds( | ||||
|       notification.timestamp.getMilliseconds() + this.state.length | ||||
|     ); | ||||
|     notification = Object.assign({}, this.settings, notification); | ||||
|     this.state.push(notification); | ||||
|   }, | ||||
|   notify(notification) { | ||||
|     if (Array.isArray(notification)) { | ||||
|       notification.forEach(notificationInstance => { | ||||
|         this.addNotification(notificationInstance); | ||||
|       }); | ||||
|     } else { | ||||
|       this.addNotification(notification); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| const NotificationsPlugin = { | ||||
|   install(Vue, options) { | ||||
|     let app = new Vue({ | ||||
|       data: { | ||||
|         notificationStore: NotificationStore | ||||
|       }, | ||||
|       methods: { | ||||
|         notify(notification) { | ||||
|           this.notificationStore.notify(notification); | ||||
|     install(Vue, options) { | ||||
|         let app = new Vue({ | ||||
|             data: { | ||||
|                 notificationStore: NotificationStore | ||||
|             }, | ||||
|  | ||||
|             methods: { | ||||
|                 notify(notification) { | ||||
|                     this.notificationStore.notify(notification); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         Vue.prototype.$notify = app.notify; | ||||
|         Vue.prototype.$notifications = app.notificationStore; | ||||
|         Vue.component('Notifications', Notifications); | ||||
|  | ||||
|         if (options) { | ||||
|             NotificationStore.setOptions(options); | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|     Vue.prototype.$notify = app.notify; | ||||
|     Vue.prototype.$notifications = app.notificationStore; | ||||
|     Vue.component('Notifications', Notifications); | ||||
|     if (options) { | ||||
|       NotificationStore.setOptions(options); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| export default NotificationsPlugin; | ||||
|   | ||||
							
								
								
									
										25
									
								
								resources/assets/js/mixins/global.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								resources/assets/js/mixins/global.js
									
									
									
									
										vendored
									
									
								
							| @@ -271,6 +271,8 @@ export default { | ||||
|                 } | ||||
|  | ||||
|                 this.$notify({ | ||||
|                     verticalAlign: 'bottom', | ||||
|                     horizontalAlign: 'left', | ||||
|                     message: notify.message, | ||||
|                     timeout: timeout, | ||||
|                     icon: 'error_outline', | ||||
| @@ -467,6 +469,9 @@ export default { | ||||
|         onChangePaginationLimit(event) { | ||||
|             let path = ''; | ||||
|  | ||||
|             let split_href = window.location.href.split('#'); | ||||
|             let href = split_href[0]; | ||||
|  | ||||
|             if (window.location.search.length) { | ||||
|                 if (window.location.search.includes('limit')) { | ||||
|                     let queries = []; | ||||
| @@ -494,10 +499,14 @@ export default { | ||||
|                     }); | ||||
|  | ||||
|                 } else { | ||||
|                     path = window.location.href + '&limit=' + event.target.getAttribute("value"); | ||||
|                     path = href + '&limit=' + event.target.getAttribute("value"); | ||||
|                 } | ||||
|             } else { | ||||
|                 path = window.location.href + '?limit=' + event.target.getAttribute("value"); | ||||
|                 path = href + '?limit=' + event.target.getAttribute("value"); | ||||
|             } | ||||
|  | ||||
|             if (split_href[1]) { | ||||
|                 path +=  '#' + split_href[1]; | ||||
|             } | ||||
|  | ||||
|             window.location.href = path; | ||||
| @@ -505,6 +514,10 @@ export default { | ||||
|  | ||||
|         // Dynamic component get path view and show it. | ||||
|         onDynamicComponent(path) { | ||||
|             if (! path) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             axios.get(path) | ||||
|             .then(response => { | ||||
|                 let html = response.data.html; | ||||
| @@ -562,6 +575,10 @@ export default { | ||||
|         }, | ||||
|  | ||||
|         onDynamicFormParams(path, params) { | ||||
|             if (! path) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             let data = {}; | ||||
|  | ||||
|             for (const [key, value] of Object.entries(params)) { | ||||
| @@ -1001,7 +1018,7 @@ export default { | ||||
|  | ||||
|                 this.component = Vue.component('add-new-component', (resolve, reject) => { | ||||
|                     resolve({ | ||||
|                         template: '<div id="dynamic-email-component"><akaunting-modal-add-new modal-dialog-class="max-w-screen-md" :show="email.modal" @submit="onSubmit" @cancel="onCancel" :buttons="email.buttons" :title="email.title" :is_component=true :message="email.html"></akaunting-modal-add-new></div>', | ||||
|                         template: '<div id="dynamic-email-component"><akaunting-modal-add-new modal-dialog-class="max-w-screen-md" modal-position-top :show="email.modal" @submit="onSubmit" @cancel="onCancel" :buttons="email.buttons" :title="email.title" :is_component=true :message="email.html"></akaunting-modal-add-new></div>', | ||||
|  | ||||
|                         components: { | ||||
|                             AkauntingDropzoneFileUpload, | ||||
| @@ -1112,6 +1129,8 @@ export default { | ||||
|                                 document.execCommand('copy'); | ||||
|  | ||||
|                                 this.$notify({ | ||||
|                                     verticalAlign: 'bottom', | ||||
|                                     horizontalAlign: 'left', | ||||
|                                     message: this.share.success_message, | ||||
|                                     timeout: 5000, | ||||
|                                     icon: 'error_outline', | ||||
|   | ||||
							
								
								
									
										4
									
								
								resources/assets/js/mixins/wizardAction.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								resources/assets/js/mixins/wizardAction.js
									
									
									
									
										vendored
									
									
								
							| @@ -72,6 +72,8 @@ export default { | ||||
|             } | ||||
|  | ||||
|             this.$notify({ | ||||
|                 verticalAlign: 'bottom', | ||||
|                 horizontalAlign: 'left', | ||||
|                 message: response.data.message, | ||||
|                 timeout: timeout, | ||||
|                 icon: "error_outline", | ||||
| @@ -92,6 +94,8 @@ export default { | ||||
|             } | ||||
|  | ||||
|             this.$notify({ | ||||
|                 verticalAlign: 'bottom', | ||||
|                 horizontalAlign: 'left', | ||||
|                 message: event.message, | ||||
|                 timeout: timeout, | ||||
|                 icon: "error_outline", | ||||
|   | ||||
							
								
								
									
										2
									
								
								resources/assets/js/views/auth/common.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								resources/assets/js/views/auth/common.js
									
									
									
									
										vendored
									
									
								
							| @@ -54,6 +54,8 @@ const login = new Vue({ | ||||
|                 let type = notify.level; | ||||
|  | ||||
|                 this.$notify({ | ||||
|                     verticalAlign: 'bottom', | ||||
|                     horizontalAlign: 'left', | ||||
|                     message: notify.message, | ||||
|                     timeout: 5000, | ||||
|                     icon: '', | ||||
|   | ||||
							
								
								
									
										25
									
								
								resources/assets/js/views/banking/accounts.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								resources/assets/js/views/banking/accounts.js
									
									
									
									
										vendored
									
									
								
							| @@ -31,29 +31,4 @@ const app = new Vue({ | ||||
|             bulk_action: new BulkAction('accounts'), | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|         onType(event) { | ||||
|             return; | ||||
|             let type = event.target.value; | ||||
|  | ||||
|             switch(type) { | ||||
|                 case 'credit_card': | ||||
|                     this.onCreditCard(); | ||||
|                     break; | ||||
|                 case 'bank': | ||||
|                 default: | ||||
|                     this.onBank(); | ||||
|                     break; | ||||
|             } | ||||
|         }, | ||||
|  | ||||
|         onCreditCard() { | ||||
|  | ||||
|         }, | ||||
|  | ||||
|         onBank() { | ||||
|  | ||||
|         }, | ||||
|     } | ||||
| }); | ||||
|   | ||||
							
								
								
									
										2
									
								
								resources/assets/js/views/common/contacts.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								resources/assets/js/views/common/contacts.js
									
									
									
									
										vendored
									
									
								
							| @@ -69,6 +69,8 @@ const app = new Vue({ | ||||
|  | ||||
|                         if (response.data.error) { | ||||
|                             this.$notify({ | ||||
|                                 verticalAlign: 'bottom', | ||||
|                                 horizontalAlign: 'left', | ||||
|                                 message: response.data.message, | ||||
|                                 timeout: 0, | ||||
|                                 icon: 'fas fa-bell', | ||||
|   | ||||
| @@ -621,6 +621,7 @@ const app = new Vue({ | ||||
|         onChangeCurrency(currency_code) { | ||||
|             if (this.edit.status && this.edit.currency <= 2) { | ||||
|                 this.edit.currency++; | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								resources/assets/js/views/modules/apps.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								resources/assets/js/views/modules/apps.js
									
									
									
									
										vendored
									
									
								
							| @@ -106,6 +106,8 @@ const app = new Vue({ | ||||
|             add_to_cart_promise.then(response => { | ||||
|                 if (response.data.success) { | ||||
|                     this.$notify({ | ||||
|                         verticalAlign: 'bottom', | ||||
|                         horizontalAlign: 'left', | ||||
|                         message: response.data.message, | ||||
|                         timeout: 0, | ||||
|                         icon: "shopping_cart_checkout", | ||||
|   | ||||
| @@ -141,7 +141,7 @@ const app = new Vue({ | ||||
|             }); | ||||
|         }, | ||||
|  | ||||
|         // Change currency get money | ||||
|         // Change currency get money override because remove form currency_code and currency_rate column | ||||
|         onChangeCurrency(currency_code) { | ||||
|             if (! currency_code) { | ||||
|                 return; | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <template> | ||||
|     <div class="relative bg-body z-10 rounded-lg shadow-2xl p-5 ltr:pr-0 rtl:pl-0 sm:py-10 sm:ltr:pl-10 sm:rtl:pr-10 overflow-hidden"> | ||||
|     <div class="relative bg-body z-10 rounded-lg shadow-2xl p-5 sm:p-10 full-height-mobile overflow-hidden"> | ||||
|         <WizardSteps :active_state="active"></WizardSteps> | ||||
|  | ||||
|         <div class="flex flex-col justify-between -mt-5 sm:mt-0" style="height:565px;"> | ||||
| @@ -42,7 +42,7 @@ | ||||
|                     </div> | ||||
|                 </div> | ||||
|  | ||||
|                 <div class="relative w-1/2 right-0 ltr:pl-10 rtl:pr-10 mt-3 hidden lg:flex lg:flex-col"> | ||||
|                 <div class="absolute w-1/2 right-0 ltr:pl-10 rtl:pr-10 mt-3 hidden lg:flex lg:flex-col"> | ||||
|                     <div class="flex flex-col ltr:items-start rtl:items-end bg-purple ltr:rounded-tl-lg ltr:rounded-bl-lg rtl:rounded-tr-lg rtl:rounded-br-lg p-6"> | ||||
|                         <div class="w-48 text-white text-left text-2xl font-semibold leading-9"> | ||||
|                             {{ translations.finish.apps_managing }} | ||||
| @@ -50,7 +50,7 @@ | ||||
|  | ||||
|                         <div style="width:372px; height:372px;"></div> | ||||
|  | ||||
|                         <img :src="image_src" class="absolute top-3 right-2" alt="" /> | ||||
|                         <img :src="image_src" class="absolute top-3 right-2" alt="Akaunting" /> | ||||
|                     </div> | ||||
|  | ||||
|                     <base-button | ||||
| @@ -59,7 +59,7 @@ | ||||
|                         @click="finish()" | ||||
|                     > | ||||
|                         <i v-if="anchor_loading" class="animate-submit_second delay-[0.28s] absolute w-2 h-2 rounded-full left-0 right-0 -top-2.5 m-auto before:absolute before:w-2 before:h-2 before:rounded-full before:animate-submit_second before:delay-[0.14s] after:absolute after:w-2 after:h-2 after:rounded-full after:animate-submit_second before:-left-3.5 after:-right-3.5 after:delay-[0.42s]"></i>  | ||||
|                          | ||||
|  | ||||
|                         <span :class="[{'opacity-0': anchor_loading}]"> | ||||
|                             {{ translations.finish.create_first_invoice }} | ||||
|                         </span> | ||||
| @@ -112,6 +112,8 @@ export default { | ||||
|         }) | ||||
|         .catch((error) => { | ||||
|             this.$notify({ | ||||
|                 verticalAlign: 'bottom', | ||||
|                 horizontalAlign: 'left', | ||||
|                 message: this.translations.finish.error_message, | ||||
|                 timeout: 1000, | ||||
|                 icon: "", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user