Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into fix-view-status-action

This commit is contained in:
satyaprakash10
2019-11-14 19:57:14 +05:30
51 changed files with 447 additions and 181127 deletions

View File

@ -35,9 +35,7 @@ class EnvironmentController extends Controller
{
$results = $this->EnvironmentManager->saveDatabaseVariables($request);
if(array_key_exists("success", $results)) {
Artisan::call('config:clear');
Artisan::call('migrate --seed');
Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations']);
@ -57,13 +55,30 @@ class EnvironmentController extends Controller
*/
public function saveMailEnvironment(MailEnvironmentRequest $request)
{
$setting = Setting::getSetting('profile_complete');
$results = $this->EnvironmentManager->saveMailVariables($request);
Setting::setSetting('profile_complete', 4);
if ($setting !== 'COMPLETED')
{
Setting::setSetting('profile_complete', 4);
}
return response()->json($results);
}
public function getMailEnvironment()
{
$MailData = [
'mail_driver' => config('mail.driver'),
'mail_host' => config('mail.host'),
'mail_port' => config('mail.port'),
'mail_username' => config('mail.username'),
'mail_password' => config('mail.password'),
'mail_encryption' => config('mail.encryption')
];
return response()->json($MailData);
}
/**
*

View File

@ -203,7 +203,7 @@ class OnboardingController extends Controller
);
}
Setting::setSetting('version','1.0.0');
Setting::setSetting('version', config('crater.version'));
Artisan::call('passport:install --force');

View File

@ -49,12 +49,20 @@ class EnvironmentManager
'DB_PASSWORD='.$request->database_password."\n\n";
if (! $this->checkDatabaseConnection($request)) {
return [
'error' => 'connection_failed'
];
} else {
if(count(DB::connection()->select('SHOW TABLES'))) {
return [
'error' => 'database_should_be_empty'
];
}
}
try {
file_put_contents($this->envPath, str_replace(
$oldDatabaseData,
$newDatabaseData,
@ -101,7 +109,7 @@ class EnvironmentManager
'MAIL_USERNAME='.$request->mail_username."\n".
'MAIL_PASSWORD='.$request->mail_password."\n".
'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n";
// dd($newMailData);
try {
file_put_contents($this->envPath, str_replace(

14
config/crater.php Normal file
View File

@ -0,0 +1,14 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Crater Requirements
|--------------------------------------------------------------------------
|
*/
'version' => '1.0.0',
];

View File

@ -4636,57 +4636,6 @@ input[type=button].btn-block {
display: none;
}
.navbar-light .navbar-brand {
color: rgba(0, 0, 0, 0.9);
}
.navbar-light .navbar-brand:hover,
.navbar-light .navbar-brand:focus {
color: rgba(0, 0, 0, 0.9);
}
.navbar-light .navbar-nav .nav-link {
color: rgba(0, 0, 0, 0.5);
}
.navbar-light .navbar-nav .nav-link:hover,
.navbar-light .navbar-nav .nav-link:focus {
color: rgba(0, 0, 0, 0.7);
}
.navbar-light .navbar-nav .nav-link.disabled {
color: rgba(0, 0, 0, 0.3);
}
.navbar-light .navbar-nav .show > .nav-link,
.navbar-light .navbar-nav .active > .nav-link,
.navbar-light .navbar-nav .nav-link.show,
.navbar-light .navbar-nav .nav-link.active {
color: rgba(0, 0, 0, 0.9);
}
.navbar-light .navbar-toggler {
color: rgba(0, 0, 0, 0.5);
border-color: rgba(0, 0, 0, 0.1);
}
.navbar-light .navbar-toggler-icon {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}
.navbar-light .navbar-text {
color: rgba(0, 0, 0, 0.5);
}
.navbar-light .navbar-text a {
color: rgba(0, 0, 0, 0.9);
}
.navbar-light .navbar-text a:hover,
.navbar-light .navbar-text a:focus {
color: rgba(0, 0, 0, 0.9);
}
.navbar-dark .navbar-brand {
color: #fff;
}
@ -11504,10 +11453,6 @@ code,
align-items: center;
}
.swal-icon--custom {
height: 70px !important;
}
.site-header {
background-color: #5851D8;
height: 60px;
@ -15112,10 +15057,6 @@ fieldset[disabled] .multiselect {
color: #FB7178;
}
.dashboard .dashboard-table .table-component .dashboard-recent-invoice-options .dropdown-container {
margin: 10px 5px 0 -75px;
}
.dashbox {
background-color: #fff;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
@ -18325,6 +18266,8 @@ fieldset[disabled] .multiselect {
.customer-create .same-address-checkbox-container {
display: flex;
justify-content: flex-end;
padding-left: 12px;
margin-bottom: 1.5rem;
align-items: center;
justify-content: flex-end;
@ -18375,6 +18318,7 @@ fieldset[disabled] .multiselect {
.customer-create .same-address-checkbox-container {
display: flex;
justify-content: flex-start;
padding-left: 15px;
margin-bottom: 0rem;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,29 @@
<template>
<button :type="type" :class="btnClass" :disabled="disabled" @click="handleClick">
<font-awesome-icon v-if="icon && !loading && !rightIcon" :class="iconClass" :icon="icon" class="vue-icon icon-left" />
<font-awesome-icon v-if="loading" :class="iconClass" icon="spinner" class="fa-spin"/>
<button
:type="type"
:class="btnClass"
:disabled="disabled || loading"
@click="handleClick"
>
<font-awesome-icon
v-if="icon && !loading && !rightIcon"
:class="iconClass"
:icon="icon"
class="vue-icon icon-left"
/>
<font-awesome-icon
v-if="loading"
:class="iconClass"
icon="spinner"
class="fa-spin"
/>
<slot />
<font-awesome-icon v-if="icon && !loading && rightIcon" :class="iconClass" :icon="icon" class="vue-icon icon-right" />
<font-awesome-icon
v-if="icon && !loading && rightIcon"
:class="iconClass"
:icon="icon"
class="vue-icon icon-right"
/>
</button>
</template>

View File

@ -4,7 +4,7 @@
<input
ref="baseInput"
v-model="inputValue"
:type="type"
:type="toggleType"
:disabled="disabled"
:readonly="readOnly"
:name="name"
@ -19,6 +19,9 @@
@keydown="handleKeyDownEnter"
@blur="handleFocusOut"
>
<div v-if="showPassword && isAlignLeftIcon" style="cursor: pointer" @click="showPass = !showPass" >
<font-awesome-icon :icon="!showPass ?'eye-slash': 'eye'" class="right-icon" />
</div>
<font-awesome-icon v-if="icon && !isAlignLeftIcon" :icon="icon" class="right-icon" />
</div>
</template>
@ -77,12 +80,17 @@ export default {
autocomplete: {
type: String,
default: 'on'
},
showPassword: {
type: Boolean,
default: false
}
},
data () {
return {
inputValue: this.value,
focus: false
focus: false,
showPass: false
}
},
computed: {
@ -94,6 +102,12 @@ export default {
return true
}
return false
},
toggleType () {
if (this.showPass) {
return 'text'
}
return this.type
}
},
watch: {

View File

@ -3,7 +3,7 @@
<form action="" @submit.prevent="submitCategoryData">
<div class="card-body">
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('expenses.category') }}<span class="required text-danger">*</span></label>
<label class="col-sm-4 col-form-label input-label">{{ $t('expenses.category') }}<span class="required text-danger">*</span></label>
<div class="col-sm-7">
<base-input
ref="name"

View File

@ -7,7 +7,7 @@
<tab id="basic-home" :name="$t('customers.basic_info')">
<div class="basic-info">
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.display_name') }} <span class="required">*</span></label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.display_name') }} <span class="required">*</span></label>
<div class="col-sm-7">
<base-input
ref="name"
@ -25,7 +25,7 @@
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.primary_display_name') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.primary_display_name') }}</label>
<div class="col-sm-7">
<base-input
v-model="formData.contact_name"
@ -34,7 +34,7 @@
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('login.email') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('login.email') }}</label>
<div class="col-sm-7">
<base-input
:invalid="$v.formData.email.$error"
@ -49,7 +49,7 @@
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $tc('settings.currencies.currency') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $tc('settings.currencies.currency') }}</label>
<div class="col-sm-7">
<base-select
v-model="currency"
@ -64,7 +64,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.phone') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.phone') }}</label>
<div class="col-sm-7">
<base-input
:invalid="$v.formData.phone.$error"
@ -79,7 +79,7 @@
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.website') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.website') }}</label>
<div class="col-sm-7">
<base-input
v-model="formData.website"
@ -100,7 +100,7 @@
<tab id="basic-profile" :name="$t('customers.billing_address')">
<div class="basic-info">
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.name') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.name') }}</label>
<div class="col-sm-7">
<base-input
v-model="billing.name"
@ -110,7 +110,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.phone') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.phone') }}</label>
<div class="col-sm-7">
<base-input
:invalid="$v.billing.phone.$error"
@ -126,7 +126,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.address') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.address') }}</label>
<div class="col-sm-7">
<base-text-area
v-model="billing.address_street_1"
@ -155,7 +155,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.country') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.country') }}</label>
<div class="col-sm-7">
<base-select
v-model="billingCountry"
@ -171,7 +171,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.state') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.state') }}</label>
<div class="col-sm-7">
<base-select
v-model="billingState"
@ -187,7 +187,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.city') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.city') }}</label>
<div class="col-sm-7">
<base-select
v-model="billingCity"
@ -213,7 +213,7 @@
</div> -->
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.zip_code') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.zip_code') }}</label>
<div class="col-sm-7">
<base-input
v-model="billing.zip"
@ -236,7 +236,7 @@
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.name') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.name') }}</label>
<div class="col-sm-7">
<base-input
v-model="shipping.name"
@ -246,7 +246,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.phone') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.phone') }}</label>
<div class="col-sm-7">
<base-input
:invalid="$v.shipping.phone.$error"
@ -262,7 +262,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.address') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.address') }}</label>
<div class="col-sm-7">
<base-text-area
v-model="shipping.address_street_1"
@ -291,7 +291,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.country') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.country') }}</label>
<div class="col-sm-7">
<base-select
v-model="shippingCountry"
@ -307,7 +307,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.state') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.state') }}</label>
<div class="col-sm-7">
<base-select
v-model="shippingState"
@ -323,7 +323,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.city') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.city') }}</label>
<div class="col-sm-7">
<base-select
v-model="shippingCity"
@ -339,7 +339,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.zip_code') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.zip_code') }}</label>
<div class="col-sm-7">
<base-input
v-model="shipping.zip"

View File

@ -3,7 +3,7 @@
<form action="" @submit.prevent="submitItemData">
<div class="card-body">
<div class="form-group row">
<label class="col-sm-4 col-form-label">
<label class="col-sm-4 col-form-label input-label">
{{ $t('items.name') }}<span class="required">*</span>
</label>
<div class="col-sm-7">
@ -22,7 +22,7 @@
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('items.price') }}<span class="required">*</span></label>
<label class="col-sm-4 col-form-label input-label">{{ $t('items.price') }}<span class="required">*</span></label>
<div class="col-sm-7">
<div class="base-input">
<money
@ -41,7 +41,7 @@
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('items.unit') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('items.unit') }}</label>
<div class="col-sm-7">
<base-select
v-model="formData.unit"
@ -54,7 +54,7 @@
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('items.description') }}</label>
<label class="col-sm-4 col-form-label input-label">{{ $t('items.description') }}</label>
<div class="col-sm-7">
<base-text-area
v-model="formData.description"
@ -121,7 +121,8 @@ export default {
{ name: 'kg', value: 'kg' },
{ name: 'km', value: 'km' },
{ name: 'lb', value: 'lb' },
{ name: 'mg', value: 'mg' }
{ name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
],
formData: {
name: null,

View File

@ -529,7 +529,8 @@ export default {
preferences: 'Preferences',
notifications: 'Notifications',
tax_types: 'Tax Types',
expense_category: 'Expense Categories'
expense_category: 'Expense Categories',
update_app: 'Update App'
},
title: 'Settings',
setting: 'Settings | Settings',
@ -611,8 +612,6 @@ export default {
estimate_viewed_desc: 'When your customer views the estimate sent via crater dashboard.',
save: 'Save',
email_save_message: 'Email saved successfully',
// invoice_viewed_message: 'Invoice viewed updated successfully',
// estimate_viewed_message: 'Estimate viewed updated successfully',
please_enter_email: 'Please Enter Email'
},
tax_types: {
@ -622,7 +621,6 @@ export default {
add_new_tax: 'Add New Tax',
tax_settings: 'Tax Settings',
tax_per_item: 'Tax Per Item',
// tax_per_item_switch: 'Tax Per Item updated successfully',
tax_name: 'Tax Name',
compound_tax: 'Compound Tax',
percent: 'Percent',
@ -660,11 +658,15 @@ export default {
preference: 'Preference | Preferences',
general_settings: 'Default preferences for the system.',
updated_message: 'Preferences updated successfully',
// set_discount_per_item_message: 'Discount set per item updated successfully',
select_language: 'select language',
select_time_zone: 'select Time Zone',
select_date_formate: 'select Date Formate',
select_financial_year: 'select financial year'
},
update_app: {
title: 'Update App',
description: 'update app description',
update: 'Update'
}
},
wizard: {
@ -735,7 +737,8 @@ export default {
migrate_failed: 'Migrate Failed',
database_variables_save_error: 'Unable to connect to the DB with Provided Values.',
mail_variables_save_error: 'Email configuration failed.',
connection_failed: 'Database Connection Failed'
connection_failed: 'Database connection failed',
database_should_be_empty: 'Database should be empty'
},
success: {
mail_variables_save_successfully: 'Email configured successfully',

View File

@ -529,7 +529,8 @@ export default {
preferences: 'Preferencias',
notifications: 'Notificaciones',
tax_types: 'Tipos de impuestos',
expense_category: 'Categorías de gastos'
expense_category: 'Categorías de gastos',
update_app: 'Actualizar aplicación'
},
title: 'Configuraciones',
setting: 'Configuraciones | Configuraciones',
@ -556,6 +557,16 @@ export default {
action: 'Acción',
add_currency: 'Agregar moneda'
},
mail: {
host: 'Host de correo',
port: 'Puerto de correo',
driver: 'Conductor de correo',
password: 'Contraseña de correo',
username: 'Nombre de usuario de correo',
mail_config: 'Configuración de correo',
encryption: 'Cifrado de correo',
mail_config_desc: 'Los detalles a continuación se utilizarán para actualizar el entorno de correo. También puede cambiar los detalles en cualquier momento después de iniciar sesión.'
},
pdf: {
title: 'Configuración de PDF',
footer_text: 'Texto de pie de página',
@ -651,6 +662,11 @@ export default {
select_time_zone: 'selecciona la zona horaria',
select_date_formate: 'seleccione formato de fecha',
select_financial_year: 'seleccione año financiero'
},
update_app: {
title: 'Actualizar aplicación',
description: 'actualizar la descripción de la aplicación',
update: 'Actualizar'
}
},
wizard: {
@ -749,7 +765,7 @@ export default {
numbers_only: 'Solo numeros.',
characters_only: 'Solo personajes.',
password_incorrect: 'Las contraseñas deben ser idénticas',
password_length: 'La contraseña debe tener 6 caracteres de longitud.',
password_length: 'La contraseña debe tener 5 caracteres de longitud.',
qty_must_greater_than_zero: 'La cantidad debe ser mayor que cero.',
price_greater_than_zero: 'El precio debe ser mayor que cero.',
payment_greater_than_zero: 'El pago debe ser mayor que cero.',

View File

@ -529,7 +529,8 @@ export default {
preferences: 'Préférences',
notifications: 'Les notifications',
tax_types: 'Types de taxe',
expense_category: 'Catégories de dépenses'
expense_category: 'Catégories de dépenses',
update_app: "Mise à jour de l'application"
},
title: 'Paramètres',
setting: 'Paramètres | Paramètres',
@ -554,7 +555,17 @@ export default {
right: 'Droite',
left: 'La gauche',
action: 'action',
add_currency: 'Ajouter une devise',
add_currency: 'Ajouter une devise'
},
mail: {
host: 'Mail Host',
port: 'Port mail',
driver: 'Pilote de courrier',
password: 'Mot de passe mail',
username: "Mail Nom d'utilisateur",
mail_config: 'Configuration du courrier',
encryption: 'Chiffrement du courrier',
mail_config_desc: "Les détails ci-dessous seront utilisés pour mettre à jour l'environnement de messagerie. Aussi, vous pouvez modifier les détails à tout moment après la connexion."
},
pdf: {
title: 'Paramètre PDF',
@ -654,6 +665,11 @@ export default {
select_time_zone: 'sélectionnez le fuseau horaire',
select_date_formate: 'sélectionnez Date Formate',
select_financial_year: 'sélectionner lexercice'
},
update_app: {
title: "Mise à jour de l'application",
description: "mettre à jour la description de l'application",
update: 'Mise à jour'
}
},
wizard: {
@ -752,7 +768,7 @@ export default {
numbers_only: 'Chiffres uniquement.',
characters_only: 'Caractères seulement.',
password_incorrect: 'Les mots de passe doivent être identiques',
password_length: 'Le mot de passe doit comporter 6 caractères.',
password_length: 'Le mot de passe doit comporter 5 caractères.',
qty_must_greater_than_zero: 'La quantité doit être supérieure à zéro.',
price_greater_than_zero: 'Le prix doit être supérieur à zéro.',
payment_greater_than_zero: 'Le paiement doit être supérieur à zéro.',

View File

@ -72,6 +72,7 @@ import UserProfile from './views/settings/UserProfile.vue'
import TaxTypes from './views/settings/TaxTypes.vue'
import ExpenseCategory from './views/settings/ExpenseCategory.vue'
import MailConfig from './views/settings/MailConfig.vue'
import UpdateApp from './views/settings/UpdateApp.vue'
import Wizard from './views/wizard/Index.vue'
@ -337,6 +338,11 @@ const routes = [
path: 'notifications',
name: 'notifications',
component: Notifications
},
{
path: 'update-app',
name: 'updateapp',
component: UpdateApp
}
]
}

View File

@ -98,7 +98,7 @@ export default {
},
password: {
required,
minLength: minLength(8)
minLength: minLength(5)
}
}
},

View File

@ -168,7 +168,7 @@
>
<table-column :label="$t('dashboard.recent_invoices_card.due_on')" show="formattedDueDate" />
<table-column :label="$t('dashboard.recent_invoices_card.customer')" show="user.name" />
<table-column :label="$t('dashboard.recent_invoices_card.amount_due')" sort-as="due_amount">
<table-column :label="$t('dashboard.recent_invoices_card.amount_due')" show="due_amount" sort-as="due_amount">
<template slot-scope="row">
<span>{{ $t('dashboard.recent_invoices_card.amount_due') }}</span>
<div v-html="$utils.formatMoney(row.due_amount, row.user.currency)"/>
@ -242,7 +242,7 @@
>
<table-column :label="$t('dashboard.recent_estimate_card.date')" show="formattedExpiryDate" />
<table-column :label="$t('dashboard.recent_estimate_card.customer')" show="user.name" />
<table-column :label="$t('dashboard.recent_estimate_card.amount_due')" sort-as="total">
<table-column :label="$t('dashboard.recent_estimate_card.amount_due')" show="total" sort-as="total">
<template slot-scope="row">
<span>{{ $t('dashboard.recent_estimate_card.amount_due') }}</span>
<div v-html="$utils.formatMoney(row.total, row.user.currency)"/>

View File

@ -553,6 +553,8 @@ export default {
if (response.data) {
this.selectCustomer(response.data.estimate.user_id)
this.newEstimate = response.data.estimate
this.newEstimate.estimate_date = moment(response.data.estimate.estimate_date, 'YYYY-MM-DD').toString()
this.newEstimate.expiry_date = moment(response.data.estimate.expiry_date, 'YYYY-MM-DD').toString()
this.discountPerItem = response.data.discount_per_item
this.taxPerItem = response.data.tax_per_item
this.selectedCurrency = this.defaultCurrency

View File

@ -261,13 +261,13 @@
{{ $t('estimates.send_estimate') }}
</a>
</v-dropdown-item>
<v-dropdown-item v-if="row.status === 'DRAFT' || row.status === 'REJECTED'">
<v-dropdown-item v-if="row.status !== 'ACCEPTED'">
<a class="dropdown-item" href="#" @click.self="onMarkAsAccepted(row.id)">
<font-awesome-icon icon="check-circle" class="dropdown-item-icon" />
{{ $t('estimates.mark_as_accepted') }}
</a>
</v-dropdown-item>
<v-dropdown-item v-if="row.status === 'ACCEPTED' || row.status === 'DRAFT'">
<v-dropdown-item v-if="row.status !== 'REJECTED'">
<a class="dropdown-item" href="#" @click.self="onMarkAsRejected(row.id)">
<font-awesome-icon icon="times-circle" class="dropdown-item-icon" />
{{ $t('estimates.mark_as_rejected') }}
@ -514,8 +514,8 @@ export default {
icon: '/assets/icon/envelope-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willDelete) => {
if (willDelete) {
}).then(async (willConvertInToinvoice) => {
if (willConvertInToinvoice) {
let res = await this.convertToInvoice(id)
if (res.data) {
window.toastr['success'](this.$t('estimates.conversion_message'))
@ -562,8 +562,8 @@ export default {
icon: '/assets/icon/check-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willDelete) => {
if (willDelete) {
}).then(async (willMarkAsSent) => {
if (willMarkAsSent) {
const data = {
id: id
}
@ -582,8 +582,8 @@ export default {
icon: '/assets/icon/paper-plane-solid.svg',
buttons: true,
dangerMode: true
}).then(async (sendEstimate) => {
if (sendEstimate) {
}).then(async (willSendEstimate) => {
if (willSendEstimate) {
const data = {
id: id
}

View File

@ -222,12 +222,22 @@ export default {
return true
},
async onMarkAsSent () {
this.isRequestOnGoing = true
let response = await this.markAsSent({id: this.estimate.id})
this.isRequestOnGoing = false
if (response.data) {
window.toastr['success'](this.$tc('estimates.mark_as_sent'))
}
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('estimates.confirm_mark_as_sent'),
icon: '/assets/icon/check-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willMarkAsSent) => {
if (willMarkAsSent) {
this.isRequestOnGoing = true
let response = await this.markAsSent({id: this.estimate.id})
this.isRequestOnGoing = false
if (response.data) {
window.toastr['success'](this.$tc('estimates.mark_as_sent'))
}
}
})
},
async removeEstimate (id) {
this.selectEstimate([parseInt(id)])
@ -235,7 +245,7 @@ export default {
swal({
title: 'Deleted',
text: 'you will not be able to recover this estimate!',
icon: 'error',
icon: '/assets/icon/trash-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willDelete) => {

View File

@ -554,6 +554,8 @@ export default {
if (response.data) {
this.selectCustomer(response.data.invoice.user_id)
this.newInvoice = response.data.invoice
this.newInvoice.invoice_date = moment(response.data.invoice.invoice_date, 'YYYY-MM-DD').toString()
this.newInvoice.due_date = moment(response.data.invoice.due_date, 'YYYY-MM-DD').toString()
this.discountPerItem = response.data.discount_per_item
this.taxPerItem = response.data.tax_per_item
this.selectedCurrency = this.defaultCurrency

View File

@ -286,7 +286,7 @@ export default {
swal({
title: 'Deleted',
text: 'you will not be able to recover this invoice!',
icon: 'error',
icon: '/assets/icon/trash-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willDelete) => {

View File

@ -112,7 +112,8 @@ export default {
{ name: 'kg', value: 'kg' },
{ name: 'km', value: 'km' },
{ name: 'lb', value: 'lb' },
{ name: 'mg', value: 'mg' }
{ name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
],
formData: {
name: '',

View File

@ -245,7 +245,8 @@ export default {
{ name: 'kg', value: 'kg' },
{ name: 'km', value: 'km' },
{ name: 'lb', value: 'lb' },
{ name: 'mg', value: 'mg' }
{ name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
],
isRequestOngoing: true,
filtersApplied: false,

View File

@ -196,7 +196,14 @@ export default {
return true
},
downloadReport () {
this.url += '&download=true'
if (!this.getReports()) {
return false
}
if (navigator.appVersion.indexOf('Mac') !== -1) {
this.url += '&download=true'
} else {
window.open(this.getReportUrl + '&download=true')
}
setTimeout(() => {
this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
}, 200)

View File

@ -200,7 +200,14 @@ export default {
return true
},
downloadReport () {
this.url += '&download=true'
if (!this.getReports()) {
return false
}
if (navigator.appVersion.indexOf('Mac') !== -1) {
this.url += '&download=true'
} else {
window.open(this.getReportUrl + '&download=true')
}
setTimeout(() => {
this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
}, 200)

View File

@ -238,7 +238,14 @@ export default {
return true
},
downloadReport () {
this.url += '&download=true'
if (!this.getReports()) {
return false
}
if (navigator.appVersion.indexOf('Mac') !== -1) {
this.url += '&download=true'
} else {
window.open(this.getReportUrl + '&download=true')
}
setTimeout(() => {
if (this.selectedType === 'By Customer') {
this.url = `${this.customerSiteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`

View File

@ -189,14 +189,21 @@ export default {
this.$v.formData.$touch()
if (this.$v.$invalid) {
return true
return false
}
this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
return true
},
downloadReport () {
this.url += '&download=true'
if (!this.getReports()) {
return false
}
if (navigator.appVersion.indexOf('Mac') !== -1) {
this.url += '&download=true'
} else {
window.open(this.url + '&download=true')
}
setTimeout(() => {
this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
}, 200)

View File

@ -66,8 +66,9 @@
<base-input
:invalid="$v.mailConfigData.mail_password.$error"
v-model.trim="mailConfigData.mail_password"
type="mail_password"
type="password"
name="name"
show-password
@input="$v.mailConfigData.mail_password.$touch()"
/>
<div v-if="$v.mailConfigData.mail_password.$error">
@ -141,12 +142,12 @@ export default {
data () {
return {
mailConfigData: {
mail_driver: 'smtp',
mail_host: 'mailtrap.io',
mail_port: 2525,
mail_username: 'cc3c64516febd4',
mail_password: 'e6a0176301f587',
mail_encryption: 'tls'
mail_driver: '',
mail_host: '',
mail_port: null,
mail_username: '',
mail_password: '',
mail_encryption: ''
},
loading: false,
mail_drivers: []
@ -176,18 +177,22 @@ export default {
}
},
mounted () {
// this.getMailDrivers()
this.loadData()
},
methods: {
async getMailDrivers () {
async loadData () {
this.loading = true
let response = await window.axios.get('/api/admin/onboarding/environment/mail')
let mailDrivers = await window.axios.get('/api/settings/environment/mail')
let mailData = await window.axios.get('/api/settings/environment/mail-env')
if (response.data) {
this.mail_drivers = response.data
this.loading = false
if (mailDrivers.data) {
this.mail_drivers = mailDrivers.data
}
if (mailData.data) {
this.mailConfigData = mailData.data
}
this.loading = false
},
async saveEmailConfig () {
this.$v.mailConfigData.$touch()
@ -196,7 +201,7 @@ export default {
}
this.loading = true
try {
let response = await window.axios.post('/api/admin/onboarding/environment/mail', this.mailConfigData)
let response = await window.axios.post('/api/settings/environment/mail', this.mailConfigData)
if (response.data.success) {
window.toastr['success'](this.$t('wizard.success.' + response.data.success))
} else {

View File

@ -29,16 +29,9 @@
>
<table-column
:sortable="true"
:filterable="true"
:label="$t('settings.tax_types.tax_name')"
>
<template slot-scope="row">
<span>{{ $t('settings.tax_types.tax_name') }}</span>
<span class="tax-name mt-3">
{{ row.name }}
</span>
</template>
</table-column>
show="name"
/>
<table-column
:sortable="true"
:filterable="true"

View File

@ -0,0 +1,55 @@
<template>
<div class="setting-main-container">
<div class="card setting-card">
<div class="page-header">
<h3 class="page-title">{{ $t('settings.update_app.title') }}</h3>
<p class="page-sub-title">
{{ $t('settings.update_app.description') }}
</p>
<base-button size="large" icon="sync-alt" color="theme" @click="onUpdateApp">
{{ $t('settings.update_app.update') }}
</base-button>
<div v-if="isShowProgressBar" class="progress mt-4">
<div
:style="[{'width': progress+'%'}]"
class="progress-bar progress-bar-striped progress-bar-animated"
role="progressbar"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
isShowProgressBar: false,
progress: 10,
interval: null
}
},
watch: {
},
mounted () {
},
methods: {
onUpdateApp () {
this.isShowProgressBar = true
this.interval = setInterval(() => {
if (this.progress >= 100) {
clearInterval(this.interval)
setTimeout(() => {
this.isShowProgressBar = false
}, 1000)
}
this.progress += 10
}, 250)
}
}
}
</script>

View File

@ -106,7 +106,7 @@ export default {
email
},
password: {
minLength: minLength(8)
minLength: minLength(5)
},
confirm_password: {
required: requiredIf('isRequired'),

View File

@ -74,6 +74,12 @@ export default {
title: 'settings.menu_title.notifications',
icon: 'bell',
iconType: 'far'
},
{
link: '/admin/settings/update-app',
title: 'settings.menu_title.update_app',
icon: 'sync-alt',
iconType: 'fas'
}
]
}

View File

@ -94,17 +94,27 @@
<div class="col-md-6">
<label class="form-label">{{ $t('wizard.address') }}</label>
<base-text-area
:invalid="$v.companyData.address_street_1.$error"
v-model.trim="companyData.address_street_1"
:placeholder="$t('general.street_1')"
name="billing_street1"
rows="2"
@input="$v.companyData.address_street_1.$touch()"
/>
<div v-if="$v.companyData.address_street_1.$error">
<span v-if="!$v.companyData.address_street_1.maxLength" class="text-danger">{{ $t('validation.description_maxlength') }}</span>
</div>
<base-text-area
:invalid="$v.companyData.address_street_2.$error"
v-model="companyData.address_street_2"
:placeholder="$t('general.street_2')"
name="billing_street2"
rows="2"
@input="$v.companyData.address_street_2.$touch()"
/>
<div v-if="$v.companyData.address_street_2.$error">
<span v-if="!$v.companyData.address_street_2.maxLength" class="text-danger">{{ $t('validation.description_maxlength') }}</span>
</div>
</div>
<div class="col-md-6">
<div class="row">
@ -146,7 +156,7 @@ import MultiSelect from 'vue-multiselect'
import AvatarCropper from 'vue-avatar-cropper'
import { validationMixin } from 'vuelidate'
import Ls from '../../services/ls'
const { required, minLength, email } = require('vuelidate/lib/validators')
const { required, minLength, email, maxLength } = require('vuelidate/lib/validators')
export default {
components: {
@ -197,6 +207,12 @@ export default {
},
country_id: {
required
},
address_street_1: {
maxLength: maxLength(255)
},
address_street_2: {
maxLength: maxLength(255)
}
}
},

View File

@ -97,7 +97,6 @@
</div>
<div class="col-md-6">
<label class="form-label">{{ $t('wizard.database.password') }}</label>
<span class="text-danger"> *</span>
<base-input
v-model.trim="databaseData.database_password"
type="password"
@ -154,7 +153,7 @@ export default {
database_name: null,
database_username: null,
database_password: null,
app_url: null
app_url: window.location.origin
},
loading: false,
connections: [
@ -207,8 +206,8 @@ export default {
}
this.loading = false
} catch (e) {
console.log(e)
window.toastr['error']('Something went wrong')
console.log(e.response)
window.toastr['error'](e.response.data.message)
}
}
}

View File

@ -61,7 +61,8 @@
<base-input
:invalid="$v.mailConfigData.mail_password.$error"
v-model.trim="mailConfigData.mail_password"
type="mail_password"
type="password"
show-password
name="name"
@input="$v.mailConfigData.mail_password.$touch()"
/>

View File

@ -67,8 +67,8 @@ export default {
data () {
return {
loading: false,
tab: 'step_1',
step: 1
tab: 'step_3',
step: 3
}
},
created () {

View File

@ -35,7 +35,7 @@
</div>
</div>
<base-button
v-if="requirements"
v-if="hasNext"
:loading="loading"
class="pull-right mt-4"
icon="arrow-right"
@ -46,7 +46,7 @@
{{ $t('wizard.continue') }}
</base-button>
<base-button
v-else
v-if="!requirements"
:loading="loading"
class="pull-right mt-4"
color="theme"
@ -74,6 +74,20 @@ export default {
isShow: true
}
},
computed: {
hasNext () {
if (this.requirements) {
let isRequired = true
for (const key in this.requirements) {
if (!this.requirements[key]) {
isRequired = false
}
}
return this.requirements && this.phpSupportInfo.supported && isRequired
}
return false
}
},
methods: {
listToggle () {
this.isShow = !this.isShow

View File

@ -108,7 +108,7 @@ export default {
},
password: {
required,
minLength: minLength(8)
minLength: minLength(5)
},
confirm_password: {
required: requiredIf('isRequired'),

View File

@ -50,7 +50,9 @@ import {
faShare,
faEllipsisH,
faCopy,
faPaperPlane
faPaperPlane,
faEyeSlash,
faSyncAlt
} from '@fortawesome/free-solid-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
@ -108,10 +110,12 @@ library.add(
faFilePdf,
faEnvelope,
faEye,
faEyeSlash,
faShare,
faEllipsisH,
faCopy,
faPaperPlane
faPaperPlane,
faSyncAlt
)
Vue.component('font-awesome-icon', FontAwesomeIcon)

View File

@ -19,3 +19,19 @@
}
}
@media(max-width: $x-small-breakpoint ) {
.base-modal {
.category-modal {
.input-label {
text-align: left;
}
}
}
}

View File

@ -34,3 +34,20 @@
}
}
@media(max-width: $x-small-breakpoint ) {
.base-modal {
.customer-modal {
.input-label {
text-align: left;
}
}
}
}

View File

@ -19,3 +19,20 @@
}
}
@media(max-width: $x-small-breakpoint ) {
.base-modal {
.item-modal {
.input-label {
text-align: left;
}
}
}
}

View File

@ -58,6 +58,7 @@
.content {
display: flex;
flex:1;
flex-direction: column;
label {
@ -445,6 +446,9 @@
.estimate-amount {
font-size: 18px;
color: #55547A;
display: flex;
justify-content: center;
align-items: center;
}
.total {
@ -491,7 +495,6 @@
font-weight: 300;
font-size: 12px;
padding-top: 2px;
padding-left: 10px;
textarea {

View File

@ -38,7 +38,7 @@
}
.filter-date {
flex: 1;
flex: 2;
display: flex;
margin-right: 40px;
align-items: center;
@ -60,7 +60,7 @@
margin-top: 28px;
}
@media(max-width: $medium-breakpoint ) {
@media(max-width: $large-breakpoint ) {
.filter-container {
flex-direction: column;
}

View File

@ -58,6 +58,7 @@
.content {
display: flex;
flex: 1;
flex-direction: column;
label {
@ -445,6 +446,9 @@
.invoice-amount {
font-size: 18px;
color: #55547A;
display: flex;
justify-content: center;
align-items: center;
}
.total {

View File

@ -33,7 +33,7 @@
}
.filter-date {
flex: 1;
flex: 2;
display: flex;
margin-right: 40px;
align-items: center;
@ -55,7 +55,7 @@
margin-top: 28px;
}
@media(max-width: $medium-breakpoint ) {
@media(max-width: $large-breakpoint ) {
.filter-container {
flex-direction: column;
}

View File

@ -1,6 +1,6 @@
// Invoice statuses
.inv-status-due {
.inv-status-overdue {
background: #FED7D7;
font-size: 13px;
color: #9B2C2C;
@ -15,9 +15,9 @@
}
.inv-status-unpaid {
background: rgba(246, 208, 154, 0.4);
background: #F8EDCB;
font-size: 13px;
color: #A96E1A;
color: #6C432E;
padding: 5px 10px;
}
@ -50,9 +50,9 @@
}
.inv-status-partially_paid {
background: #E1E0EA;
background: #C9E3EC;
font-size: 13px;
color: #312F57;
color: #1E576C;
padding: 5px 10px;
}

View File

@ -323,6 +323,21 @@ Route::group(['middleware' => 'api'], function () {
'uses' => 'CompanyController@updateSetting'
]);
Route::get('/environment/mail', [
'as' => 'admin.environment.mail',
'uses' => 'EnvironmentController@getMailDrivers'
]);
Route::get('/environment/mail-env', [
'as' => 'admin.mail.env',
'uses' => 'EnvironmentController@getMailEnvironment'
]);
Route::post('/environment/mail', [
'as' => 'admin.environment.mail.save',
'uses' => 'EnvironmentController@saveMailEnvironment'
]);
});
});