'Wizard edited for spa'

This commit is contained in:
Burak Civan 2021-05-20 15:18:43 +03:00
parent cdfe846d4b
commit 79f91eab7f
25 changed files with 1849 additions and 524 deletions

View File

@ -33,7 +33,7 @@ class Companies extends Controller
{ {
$company = Company::find(company_id()); $company = Company::find(company_id());
return view('wizard.companies.edit', compact('company')); return $this->response('wizard.companies.edit', compact('company'));
} }
/** /**

View File

@ -44,7 +44,7 @@ class Currencies extends Controller
$codes[$key] = $key; $codes[$key] = $key;
} }
return view('wizard.currencies.index', compact('currencies', 'codes')); return $this->response('wizard.currencies.index', compact('currencies', 'codes'));
} }
/** /**
@ -58,19 +58,21 @@ class Currencies extends Controller
{ {
$response = $this->ajaxDispatch(new CreateCurrency($request)); $response = $this->ajaxDispatch(new CreateCurrency($request));
$response['redirect'] = route('wizard.currencies.index'); //$response['redirect'] = route('wizard.currencies.index');
if ($response['success']) { if ($response['success']) {
$message = trans('messages.success.added', ['type' => trans_choice('general.currencies', 1)]); $message = trans('messages.success.added', ['type' => trans_choice('general.currencies', 1)]);
flash($message)->success(); //flash($message)->success();
} else { } else {
$message = $response['message']; $message = $response['message'];
flash($message)->error()->important(); //flash($message)->error()->important();
} }
$response['message'] = $message;
return response()->json($response); return response()->json($response);
} }
@ -86,18 +88,20 @@ class Currencies extends Controller
{ {
$response = $this->ajaxDispatch(new UpdateCurrency($currency, $request)); $response = $this->ajaxDispatch(new UpdateCurrency($currency, $request));
$response['redirect'] = route('wizard.currencies.index'); // $response['redirect'] = route('wizard.currencies.index');
if ($response['success']) { if ($response['success']) {
$message = trans('messages.success.updated', ['type' => $currency->name]); $message = trans('messages.success.updated', ['type' => $currency->name]);
flash($message)->success(); // flash($message)->success();
} else { } else {
$message = $response['message']; $message = $response['message'];
flash($message)->error()->important(); // flash($message)->error()->important();
} }
$response['message'] = $message;
return response()->json($response); return response()->json($response);
} }
@ -110,20 +114,19 @@ class Currencies extends Controller
*/ */
public function destroy(Currency $currency) public function destroy(Currency $currency)
{ {
$response = $this->ajaxDispatch(new DeleteCurrency($currency)); $currency_id = $currency->id;
$response['redirect'] = route('wizard.currencies.index'); $response = $this->ajaxDispatch(new DeleteCurrency($currency));
if ($response['success']) { if ($response['success']) {
$message = trans('messages.success.deleted', ['type' => $currency->name]); $message = trans('messages.success.deleted', ['type' => $currency->name]);
flash($message)->success();
} else { } else {
$message = $response['message']; $message = $response['message'];
flash($message)->error()->important();
} }
$response['currency_id'] = $currency_id;
$response['message'] = $message;
return response()->json($response); return response()->json($response);
} }
} }

View File

@ -0,0 +1,140 @@
<?php
namespace App\Http\Controllers\Wizard;
use App\Abstracts\Http\Controller;
use Akaunting\Money\Currency as MoneyCurrency;
use App\Models\Setting\Currency;
use App\Models\Setting\Tax;
use App\Traits\Modules;
use App\Models\Common\Company;
class Data extends Controller
{
use Modules;
/**
* Instantiate a new controller instance.
*/
public function __construct()
{
// Add CRUD permission check
$this->middleware('permission:create-common-companies')->only('create', 'store', 'duplicate', 'import');
$this->middleware('permission:read-common-companies')->only('index', 'show', 'edit', 'export');
$this->middleware('permission:update-common-companies')->only('update', 'enable', 'disable');
$this->middleware('permission:delete-common-companies')->only('destroy');
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function index()
{
$translations = [
'companies' => [
'title' => trans_choice('general.companies', 1),
'api_key' => trans('modules.api_key'),
'form_enter' => trans('general.form.enter'),
'get_api_key' => trans('modules.get_api_key'),
'tax_number' => trans('general.tax_number'),
'financial_start' => trans('settings.localisation.financial_start'),
'address' => trans('settings.company.address'),
'logo' => trans('settings.company.logo'),
'skip' => trans('general.skip'),
'save' => trans('general.save'),
],
'currencies' => [
'title' => trans_choice('general.currencies', 2),
'add_new' => trans('general.add_new'),
'name' => trans('general.name'),
'code' => trans('currencies.code'),
'rate' => trans('currencies.rate'),
'enabled' => trans('general.enabled'),
'actions' => trans('general.actions') ,
'yes' => trans('general.yes'),
'no' => trans('general.no'),
'edit' => trans('general.edit'),
'delete' => trans('general.delete'),
'save' => trans('general.save'),
'precision' => trans('currencies.precision'),
'symbol' => trans('currencies.symbol.symbol'),
'position' => trans('currencies.symbol.position'),
'decimal_mark' => trans('currencies.decimal_mark'),
'thousands_separator' => trans('currencies.thousands_separator'),
'previous' => trans('pagination.previous'),
'next' => trans('pagination.next'),
'delete_confirm' => trans('general.delete_confirm'),
'cancel' => trans('general.cancel'),
],
'taxes' => [
'title' => trans_choice('general.taxes', 2),
'add_new' => trans('general.add_new'),
'name' => trans('general.name'),
'rate_percent' => trans('taxes.rate_percent'),
'enabled' => trans('general.enabled'),
'actions' => trans('general.actions'),
'yes' => trans('general.yes'),
'no' => trans('general.no'),
'edit' => trans('general.edit'),
'delete' => trans('general.delete'),
'name' => trans('general.name'),
'rate' => trans('currencies.rate'),
'enabled' => trans('general.enabled'),
'save' => trans('general.save'),
'previous' => trans('pagination.previous'),
'next' => trans('pagination.next'),
'cancel' => trans('general.cancel'),
],
'finish' => [
'title' => trans_choice('general.finish', 1),
'recommended_apps' => trans('modules.recommended_apps'),
'no_apps' => trans('modules.no_apps'),
'developer' => trans('modules.developer'),
'previous' => trans('pagination.previous'),
'go_to_dashboard' => trans('general.go_to_dashboard'),
]
];
$currencies = Currency::collect();
// Prepare codes
$codes = [];
$money_currencies = MoneyCurrency::getCurrencies();
foreach ($money_currencies as $key => $item) {
$codes[$key] = $key;
}
$taxes = Tax::collect();
$data = [
'query' => [
'limit' => 4
]
];
$modules = $this->getFeaturedModules($data);
$company = Company::find(company_id());
return response()->json([
'success' => true,
'errors' => false,
'message' => 'Get languages text..',
'data' => [
'currencies' => $currencies,
'currency_codes' => $codes,
'taxes' => $taxes,
'modules' => $modules,
'translations' => $translations,
'companies' => $company,
],
]);
}
}

View File

@ -2,7 +2,7 @@
namespace App\Http\Controllers\Wizard; namespace App\Http\Controllers\Wizard;
use Illuminate\Routing\Controller; use App\Abstracts\Http\Controller;
use App\Traits\Modules; use App\Traits\Modules;
class Finish extends Controller class Finish extends Controller
@ -38,6 +38,21 @@ class Finish extends Controller
$modules = $this->getFeaturedModules($data); $modules = $this->getFeaturedModules($data);
return view('wizard.finish.index', compact('modules')); return $this->response('wizard.finish.index', compact('modules'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function update()
{
setting()->set('wizard.completed', 1);
// Save all settings
setting()->save();
return response()->json([]);
} }
} }

View File

@ -32,7 +32,7 @@ class Taxes extends Controller
{ {
$taxes = Tax::collect(); $taxes = Tax::collect();
return view('wizard.taxes.index', compact('taxes')); return $this->response('wizard.taxes.index', compact('taxes'));
} }
/** /**
@ -46,17 +46,18 @@ class Taxes extends Controller
{ {
$response = $this->ajaxDispatch(new CreateTax($request)); $response = $this->ajaxDispatch(new CreateTax($request));
$response['redirect'] = route('wizard.taxes.index'); // $response['redirect'] = route('wizard.taxes.index');
if ($response['success']) { if ($response['success']) {
$message = trans('messages.success.added', ['type' => trans_choice('general.taxes', 1)]); $message = trans('messages.success.added', ['type' => trans_choice('general.taxes', 1)]);
flash($message)->success(); // flash($message)->success();
} else { } else {
$message = $response['message']; $message = $response['message'];
flash($message)->error()->important(); // flash($message)->error()->important();
} }
$response['message'] = $message;
return response()->json($response); return response()->json($response);
} }
@ -73,18 +74,20 @@ class Taxes extends Controller
{ {
$response = $this->ajaxDispatch(new UpdateTax($tax, $request)); $response = $this->ajaxDispatch(new UpdateTax($tax, $request));
$response['redirect'] = route('wizard.taxes.index'); // $response['redirect'] = route('wizard.taxes.index');
if ($response['success']) { if ($response['success']) {
$message = trans('messages.success.updated', ['type' => $tax->name]); $message = trans('messages.success.updated', ['type' => $tax->name]);
flash($message)->success(); // flash($message)->success();
} else { } else {
$message = $response['message']; $message = $response['message'];
flash($message)->error()->important(); // flash($message)->error()->important();
} }
$response['message'] = $message;
return response()->json($response); return response()->json($response);
} }
@ -97,19 +100,23 @@ class Taxes extends Controller
*/ */
public function destroy(Tax $tax) public function destroy(Tax $tax)
{ {
$tax_id = $tax->id;
$response = $this->ajaxDispatch(new DeleteTax($tax)); $response = $this->ajaxDispatch(new DeleteTax($tax));
$response['redirect'] = route('wizard.taxes.index'); // $response['redirect'] = route('wizard.taxes.index');
if ($response['success']) { if ($response['success']) {
$message = trans('messages.success.deleted', ['type' => $tax->name]); $message = trans('messages.success.deleted', ['type' => $tax->name]);
flash($message)->success(); // flash($message)->success();
} else { } else {
$message = $response['message']; $message = $response['message'];
flash($message)->error()->important(); // flash($message)->error()->important();
} }
$response['tax_id'] = $tax_id;
$response['message'] = $message;
return response()->json($response); return response()->json($response);
} }

View File

@ -0,0 +1,102 @@
<?php
namespace App\Http\Controllers\Wizard;
use App\Abstracts\Http\Controller;
class Translations extends Controller
{
/**
* Instantiate a new controller instance.
*/
public function __construct()
{
// Add CRUD permission check
$this->middleware('permission:create-common-companies')->only('create', 'store', 'duplicate', 'import');
$this->middleware('permission:read-common-companies')->only('index', 'show', 'edit', 'export');
$this->middleware('permission:update-common-companies')->only('update', 'enable', 'disable');
$this->middleware('permission:delete-common-companies')->only('destroy');
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function index()
{
$translations = [
'companies' => [
'title' => trans_choice('general.companies', 1),
'api_key' => trans('modules.api_key'),
'form_enter' => trans('general.form.enter'),
'get_api_key' => trans('modules.get_api_key'),
'tax_number' => trans('general.tax_number'),
'financial_start' => trans('settings.localisation.financial_start'),
'address' => trans('settings.company.address'),
'logo' => trans('settings.company.logo'),
'skip' => trans('general.skip'),
'save' => trans('general.save'),
],
'currencies' => [
'title' => trans_choice('general.currencies', 2),
'add_new' => trans('general.add_new'),
'name' => trans('general.name'),
'code' => trans('currencies.code'),
'rate' => trans('currencies.rate'),
'enabled' => trans('general.enabled'),
'actions' => trans('general.actions') ,
'yes' => trans('general.yes'),
'no' => trans('general.no'),
'edit' => trans('general.edit'),
'delete' => trans('general.delete'),
'save' => trans('general.save'),
'precision' => trans('currencies.precision'),
'symbol' => trans('currencies.symbol.symbol'),
'position' => trans('currencies.symbol.position'),
'decimal_mark' => trans('currencies.decimal_mark'),
'thousands_separator' => trans('currencies.thousands_separator'),
'previous' => trans('pagination.previous'),
'next' => trans('pagination.next'),
'delete_confirm' => trans('general.delete_confirm'),
'cancel' => trans('general.cancel'),
],
'taxes' => [
'title' => trans_choice('general.taxes', 2),
'add_new' => trans('general.add_new'),
'name' => trans('general.name'),
'rate_percent' => trans('taxes.rate_percent'),
'enabled' => trans('general.enabled'),
'actions' => trans('general.actions'),
'yes' => trans('general.yes'),
'no' => trans('general.no'),
'edit' => trans('general.edit'),
'delete' => trans('general.delete'),
'name' => trans('general.name'),
'rate' => trans('currencies.rate'),
'enabled' => trans('general.enabled'),
'save' => trans('general.save'),
'previous' => trans('pagination.previous'),
'next' => trans('pagination.next'),
'cancel' => trans('general.cancel'),
],
'finish' => [
'title' => trans_choice('general.finish', 1),
'recommended_apps' => trans('modules.recommended_apps'),
'no_apps' => trans('modules.no_apps'),
'developer' => trans('modules.developer'),
'previous' => trans('pagination.previous'),
'go_to_dashboard' => trans('general.go_to_dashboard'),
]
];
return response()->json([
'success' => true,
'errors' => false,
'message' => 'Get languages text..',
'data' => $translations,
]);
}
}

View File

@ -3,7 +3,7 @@
<label :for="name" class="form-control-label">{{ text }}</label> <label :for="name" class="form-control-label">{{ text }}</label>
<div class="tab-pane tab-example-result fade show active" role="tabpanel" aria-labelledby="-component-tab"> <div class="tab-pane tab-example-result fade show active" role="tabpanel" aria-labelledby="-component-tab">
<div class="btn-group btn-group-toggle" data-toggle="buttons" v-on:click="onClick"> <div class="btn-group btn-group-toggle radio-yes-no" data-toggle="buttons" v-on:click="onClick">
<label class="btn btn-success" <label class="btn btn-success"
:class="[{'active': value === 1}]"> :class="[{'active': value === 1}]">
<input type="radio" <input type="radio"
@ -70,7 +70,7 @@ export default {
}, },
onClick(evt) { onClick(evt) {
let val = evt.target.control.value; let val = evt.target.control.value;
this.value= val; this.real_value = val;
this.$emit("change", val); this.$emit("change", val);
}, },

View File

@ -198,6 +198,8 @@ export default {
if (response.data.redirect) { if (response.data.redirect) {
window.location.href = response.data.redirect; window.location.href = response.data.redirect;
} }
this.$emit('deleted', response.data);
}) })
.catch(error => { .catch(error => {
this.success = false; this.success = false;

146
resources/assets/js/mixins/spa-global.js vendored Normal file
View File

@ -0,0 +1,146 @@
export default {
data: function () {
return {
currentTab: undefined,
newDatas: false,
model: {
name: "",
rate: "",
select: "",
enabled: 1
},
}
},
methods: {
addItem() {
this.newDatas = true;
this.currentTab = undefined;
if (this.model) {
this.model.name = '';
this.model.rate = '';
this.model.select = '';
}
},
handeClickEdit(item, index) {
this.newDatas = false;
this.currentTab = index;
if (this.model) {
this.model.name = item.name ? item.name : '';
this.model.rate = item.rate ? item.rate : '';
this.model.select = item.code ? item.code : '';
}
},
onEditEvent(form_method, form_url, plus_data, form_list, form_id) {
const formData = new FormData(this.$refs["form"]);
const data = {};
for (let [key, val] of formData.entries()) {
Object.assign(data, {
[key]: val,
['type']: 'normal'
});
}
if (!plus_data || plus_data == undefined) {
delete data.type;
}
window.axios({
method: form_method,
url: form_url,
data: data,
})
.then(response => {
form_list.forEach(item => {
if (item.id == form_id) {
item.name = response.data.data.name;
item.code = response.data.data.code;
item.rate = response.data.data.rate;
item.type = plus_data == undefined ? 'normal' : ''
}
});
let type = response.data.success ? 'success' : 'error';
let timeout = 1000;
if (response.data.important) {
timeout = 0;
}
this.$notify({
message: response.data.message,
timeout: timeout,
icon: "fas fa-bell",
type,
});
this.newDatas = false;
this.currentTab = undefined;
this.model.name = '';
this.model.rate = '';
this.model.select = '';
this.model.enabled = 1;
})
.catch(error => {
this.success = false;
});
},
onSubmitEvent(form_method, form_url, plus_data, form_list) {
const formData = new FormData(this.$refs["form"]);
const data = {};
for (let [key, val] of formData.entries()) {
Object.assign(data, {
[key]: val,
['type']: 'normal'
});
}
if (!plus_data || plus_data == undefined) {
delete data.type;
}
window.axios({
method: form_method,
url: form_url,
data: data,
})
.then(response => {
form_list.push({
"id": response.data.data.id,
"name": response.data.data.name,
"code": response.data.data.code,
"rate": response.data.data.rate,
"enabled": response.data.data.enabled != undefined ? response.data.data.enabled : 'true'
});
let type = response.data.success ? 'success' : 'error';
let timeout = 1000;
if (response.data.important) {
timeout = 0;
}
this.$notify({
message: response.data.message,
timeout: timeout,
icon: "fas fa-bell",
type,
});
this.newDatas = false;
this.currentTab = undefined;
this.model.name = '';
this.model.rate = '';
this.model.select = '';
this.model.enabled = 1;
})
.catch(error => {
this.success = false;
});
},
},
}

View File

@ -0,0 +1,86 @@
<template>
<router-view
:translations="translations"
:currencies="currencies"
:taxes="taxes"
:modules="modules.data"
:currency_codes="currency_codes"
:companies="companies"
></router-view>
</template>
<script>
export default {
name: 'Wizard',
created() {
let self = this;
window
.axios({
method: "GET",
url: url + "/wizard/data",
})
.then((response) => {
let data = response.data.data;
for (let item in data) {
self[item] = data[item];
}
Object.keys(data.currency_codes).map((key) => {
return data.currency_codes[key];
});
});
},
data() {
return {
currencies: [],
currency_codes: [],
taxes: [],
modules: {},
companies: {},
translations: {
companies: {},
currencies: {},
taxes: {},
finish: {},
},
};
},
};
</script>
<style>
.document-loading {
width: 1140px;
display: flex;
align-items: center;
justify-content: center;
}
.document-loading div {
margin-top: unset;
margin-left: unset;
}
.current-tab {
background-color: #f6f9fc;
}
.current-tab-btn {
text-align: right;
padding: 0 40px;
}
.form-container {
flex-flow: row wrap;
}
@media screen and (max-width: 991px) {
.current-tab-btn {
padding: 0 15px;
}
}
</style>

70
resources/assets/js/views/wizard.js vendored Normal file
View File

@ -0,0 +1,70 @@
require('./bootstrap');
import Vue from 'vue';
import VueRouter from 'vue-router';
import DashboardPlugin from './plugins/dashboard-plugin';
import Wizard from './Wizard.vue';
Vue.use(DashboardPlugin);
Vue.use(VueRouter);
import Company from './views/wizard/Company.vue';
import Currencies from './views/wizard/Currencies.vue';
import Taxes from './views/wizard/Taxes.vue';
import Finish from './views/wizard/Finish.vue';
var global_path = new URL(url).protocol + '//' + window.location.host;
var base_path = url.replace(global_path, '');
const router = new VueRouter({
mode: 'history',
base: base_path,
routes: [
{
path: '/wizard',
name: 'Wizard',
component: Company
},
{
path: '/wizard/companies',
name: 'Company',
component: Company
},
{
path: '/wizard/currencies',
name: 'Currencies',
component: Currencies
},
{
path: '/wizard/taxes',
name: 'Taxes',
component: Taxes
},
{
path: '/wizard/finish',
name: 'Finish',
component: Finish
}
],
linkActiveClass: 'active',
scrollBehavior: (to, from ,savedPosition) => {
if (savedPosition) {
return savedPosition;
}
if (to.hash) {
return { selector: to.hash };
}
return { x: 0, y: 0 };
}
});
new Vue({
el : '#app',
router,
render: h => h(Wizard),
});

View File

@ -0,0 +1,150 @@
<template>
<div>
<h1 class="text-white">{{ translations.companies.title }}</h1>
<div class="card">
<div class="card-header wizard-header p-3">
<el-steps :active="active" finish-status="success" align-center>
<el-step :title="translations.companies.title"></el-step>
<el-step :title="translations.currencies.title"></el-step>
<el-step :title="translations.taxes.title"></el-step>
<el-step :title="translations.finish.title"></el-step>
</el-steps>
</div>
<form
ref="form"
class="w-100"
>
<div class="card-body">
<div class="row mb-4">
<div class="col-12 mb-4">
<base-input
:label="translations.companies.api_key"
name="api_key"
data-name="api_key"
:placeholder="translations.companies.api_key"
prepend-icon="fas fa-key"
v-model="model.apiKey"
/>
<p class="mb-0 mt--3">
<small>
<div v-html="translations.companies.get_api_key"></div>
</small>
</p>
</div>
<div class="col-6 mb-4">
<base-input
type="text"
:label="translations.companies.tax_number"
name="tax_number"
data-name="tax_number"
:placeholder="translations.companies.tax_number"
prepend-icon="fas fa-percent"
v-model="companies.tax_number"
/>
</div>
<div class="col-6 mb-4">
<akaunting-date
:title="translations.companies.financial_start"
:placeholder="translations.companies.financial_start"
name="financial_start"
prepend-icon="fas fa-calendar"
:date-config="{
dateFormat: 'd-m',
allowInput: true,
altInput: true,
altFormat: 'j F',
}"
v-model="model.date"
></akaunting-date>
</div>
<div class="col-12 mb-4">
<base-input :label="translations.companies.address">
<textarea
class="form-control"
name="address"
data-name="address"
rows="3"
:placeholder="translations.companies.address"
v-model="companies.address"
></textarea>
</base-input>
</div>
<div class="col-6">
<base-input :label="translations.companies.logo">
<akaunting-dropzone-file-upload
preview="single"
dropzone-class="form-file"
>
</akaunting-dropzone-file-upload>
</base-input>
</div>
</div>
</div>
<div class="card-footer">
<div class="row">
<div class="col-md-12 text-right">
<base-button type="success" native-type="button" @click="onEditSave()">{{
translations.companies.save
}}</base-button>
<base-button type="white" native-type="submit" @click="next()">{{
translations.companies.skip
}}</base-button>
</div>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
import { Step, Steps } from "element-ui";
import AkauntingDropzoneFileUpload from "./../../components/AkauntingDropzoneFileUpload";
import AkauntingDate from "./../../components/AkauntingDate";
import MixinsSpaGlobal from "./../../mixins/spa-global";
export default {
name: "Company",
mixins: [MixinsSpaGlobal],
components: {
[Step.name]: Step,
[Steps.name]: Steps,
AkauntingDropzoneFileUpload,
AkauntingDate,
},
props: {
companies: {
type: [Object, Array],
},
translations: {
type: [Object, Array],
},
},
data() {
return {
active: 0,
model: {
apiKey: "503df039-d0bc-4f74-aba8-a6f1d38c645b",
taxNumber: "",
address: "",
date: "01.01",
},
};
},
methods: {
next() {
if (this.active++ > 2);
this.$router.push("/wizard/currencies");
},
onEditSave() {
this.onEditEvent("PATCH", url + "/wizard/companies", '', this.companies, '');
}
},
};
</script>
<style scoped>
form {
flex-flow: row wrap;
}
</style>

View File

@ -0,0 +1,416 @@
<template>
<div>
<h1 class="text-white">
{{ translations.currencies.title }}
</h1>
<div class="card">
<div class="card-header wizard-header p-3">
<el-steps :active="active" finish-status="success" align-center>
<el-step :title="translations.companies.title"></el-step>
<el-step :title="translations.currencies.title"></el-step>
<el-step :title="translations.taxes.title"></el-step>
<el-step :title="translations.finish.title"></el-step>
</el-steps>
</div>
<div class="card-body">
<div class="d-flex justify-content-end mb-3">
<base-button
type="success"
native-type="button"
class="btn-sm"
@click="addItem()"
>{{ translations.currencies.add_new }}</base-button>
</div>
<div class="row flex-column">
<form ref="form">
<table class="table table-flush table-hover" id="tbl-currencies">
<thead class="thead-light">
<tr class="row table-head-line">
<th class="col-xs-4 col-sm-4 col-md-3">
{{ translations.currencies.name }}
</th>
<th class="col-md-3 d-none d-md-block">
{{ translations.currencies.code }}
</th>
<th class="col-md-2 d-none d-md-block">
{{ translations.currencies.rate }}
</th>
<th class="col-xs-4 col-sm-4 col-md-2">
{{ translations.currencies.enabled }}
</th>
<th class="col-xs-4 col-sm-4 col-md-2 text-center">
{{ translations.currencies.actions }}
</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in currencies"
:key="index"
class="row align-items-center border-top-1"
>
<td class="col-xs-4 col-sm-4 col-md-3">
<a href="javascript:void(0);"> {{ item.name }} </a>
</td>
<td class="col-md-3 d-none d-md-block">{{ item.code }}</td>
<td class="col-md-2 d-none d-md-block">{{ item.rate }}</td>
<td class="col-xs-4 col-sm-4 col-md-2">
<label class="custom-toggle d-inline-block" name="staus-1">
<input
type="checkbox"
:checked="item.enabled"
@input="inputHandle(item)"
/>
<span
class="custom-toggle-slider rounded-circle status-green"
:data-label-on="translations.currencies.yes"
:data-label-off="translations.currencies.no"
>
</span>
</label>
</td>
<td class="col-xs-4 col-sm-4 col-md-2 text-center">
<div class="dropdown">
<a
class="btn btn-neutral btn-sm text-light items-align-center py-2"
href="#"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<i class="fa fa-ellipsis-h text-muted"></i>
</a>
<div
class="dropdown-menu dropdown-menu-right dropdown-menu-arrow"
>
<button
type="button"
class="dropdown-item"
@click="handeClickEdit(item, index)"
>
{{ translations.currencies.edit }}
</button>
<div class="dropdown-divider"></div>
<button
type="button"
class="dropdown-item"
@click="handleClickDelete(item)"
>
{{ translations.currencies.delete }}
</button>
</div>
</div>
</td>
<td class="w-100 p-0 current-tab" v-if="currentTab == index">
<div class="row pt-3 pb-3">
<div
class="form-container col-12 d-flex justify-content-between align-items-start"
>
<base-input
:label="translations.currencies.name"
name="name"
data-name="name"
:placeholder="translations.currencies.name"
prepend-icon="fas fa-font"
form-classes="col-md-3"
v-model="model.name"
/>
<base-input
:label="translations.currencies.code"
form-classes="col-md-3"
>
<el-select
name="code"
v-model="model.select"
required="required"
@change="onChangeCode(model.select)"
filterable
>
<template slot="prefix">
<span
class="el-input__suffix-inner el-select-icon"
>
<i
:class="'select-icon-position el-input__icon fa fa-code'"
></i>
</span>
</template>
<el-option
v-for="option in currency_codes"
:key="option"
:label="option"
:value="option"
>
</el-option> </el-select
></base-input>
<base-input
:label="translations.currencies.rate"
name="rate"
data-name="rate"
:placeholder="translations.currencies.rate"
prepend-icon="fas fa-percentage"
form-classes="col-md-3"
required="required"
v-model="model.rate"
/>
<div class="mt-4 col-md-3 current-tab-btn">
<base-button
type="success"
native-type="button"
@click="onEditSave(item)"
>
{{ translations.currencies.save }}</base-button
>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div class="mt-2" v-if="newDatas">
<div class="row p-3">
<div
class="form-container col-12 d-flex justify-content-between align-items-start"
>
<base-input
:label="translations.currencies.name"
name="name"
data-name="name"
:placeholder="translations.currencies.name"
prepend-icon="fas fa-font"
v-model="model.name"
/>
<base-input :label="translations.currencies.code">
<el-select
name="code"
v-model="model.select"
required="required"
@change="onChangeCode(model.select)"
filterable
>
<template slot="prefix">
<span class="el-input__suffix-inner el-select-icon">
<i
:class="'select-icon-position el-input__icon fa fa-code'"
></i>
</span>
</template>
<el-option
v-for="option in currency_codes"
:key="option"
:label="option"
:value="option"
>
</el-option> </el-select
></base-input>
<base-input
:label="translations.currencies.rate"
name="rate"
data-name="rate"
:placeholder="translations.currencies.rate"
prepend-icon="fas fa-percentage"
v-model="model.rate"
required="required"
/>
<div>
<div class="d-flex">
<akaunting-radio-group
name="enabled"
:text="translations.currencies.enabled"
:enable="translations.currencies.yes"
:disable="translations.currencies.no"
:value="model.enabled"
>
</akaunting-radio-group>
</div>
</div>
<div class="mt-4">
<base-button
type="success"
native-type="button"
@click="onSubmitForm()"
>{{ translations.currencies.save }}</base-button
>
</div>
</div>
</div>
</div>
</form>
</div>
<notifications></notifications>
<form id="form-dynamic-component" method="POST" action="#"></form>
<component
v-bind:is="component"
@deleted="deleteCurrency($event)"
></component>
</div>
<div class="card-footer">
<div class="row">
<div class="col-md-12 d-flex justify-content-between">
<base-button type="white" native-type="submit" @click="prev()">{{
translations.currencies.previous
}}</base-button>
<base-button type="white" native-type="submit" @click="next()">{{
translations.currencies.next
}}</base-button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Step, Steps, Select, Option } from "element-ui";
import AkauntingRadioGroup from "./../../components/forms/AkauntingRadioGroup";
import Form from "./../../plugins/form";
import BulkAction from "./../../plugins/bulk-action";
import MixinsGlobal from "./../../mixins/global";
import MixinsSpaGlobal from "./../../mixins/spa-global";
export default {
name: "Currencies",
mixins: [MixinsGlobal, MixinsSpaGlobal],
components: {
[Step.name]: Step,
[Steps.name]: Steps,
[Select.name]: Select,
[Option.name]: Option,
AkauntingRadioGroup,
},
props: {
currencies: {
type: [Object, Array],
},
currency_codes: {
type: [Object, Array],
},
translations: {
type: [Object, Array],
},
},
data() {
return {
active: 1,
bulk_action: new BulkAction(url + "/settings/currencies"),
};
},
methods: {
inputHandle(item) {
this.onStatus(item.id, event);
},
handleClickDelete(item) {
this.confirmDelete(
`${
new URL(url).protocol +
"//" +
location.host +
location.pathname +
"/" +
item.id
}`,
this.translations.currencies.title,
`Confirm Delete <strong>${item.name}</strong> ${this.translations.currencies.title}?`,
this.translations.currencies.cancel,
this.translations.currencies.delete
);
},
next() {
if (this.active++ > 2);
this.$router.push("/wizard/taxes");
},
prev() {
if (this.active-- > 2);
this.$router.push("/wizard/companies");
},
onChangeCode(code) {
let self = this;
const formData = new FormData(this.$refs["form"]);
const data = {
rate: "",
precision: "",
symbol: "",
symbol_first: "",
decimal_mark: "",
thousands_separator: "",
};
for (let [key, val] of formData.entries()) {
Object.assign(data, {
[key]: val,
});
}
window
.axios({
method: "GET",
url: url + "/settings/currencies/config",
params: {
code: code,
},
})
.then((response) => {
data.rate = response.data.rate;
data.precision = response.data.precision;
data.symbol = response.data.symbol;
data.symbol_first = response.data.symbol_first;
data.decimal_mark = response.data.decimal_mark;
data.thousands_separator = response.data.thousands_separator;
self.model.rate = response.data.rate;
});
},
onEditSave(item) {
this.onEditEvent("PATCH", url + "/wizard/currencies/" + item.id, '', this.currencies, item.id);
},
onSubmitForm() {
this.onSubmitEvent("POST", url + "/wizard/currencies", '', this.currencies);
},
deleteCurrency(event) {
this.currencies.forEach(function (currency, index) {
if (currency.id == event.currency_id) {
this.currencies.splice(index, 1);
return;
}
}, this);
this.component = "";
let type = event.success ? 'success' : 'error';
let timeout = 1000;
if (event.important) {
timeout = 0;
}
this.$notify({
message: event.message,
timeout: timeout,
icon: "fas fa-bell",
type,
});
},
},
};
</script>

View File

@ -0,0 +1,114 @@
<template>
<div>
<h1 class="text-white">{{ translations.finish.title }}</h1>
<div class="card">
<div class="card-header wizard-header p-3">
<el-steps :active="active" finish-status="success" align-center>
<el-step :title="translations.companies.title"></el-step>
<el-step :title="translations.currencies.title"></el-step>
<el-step :title="translations.taxes.title"></el-step>
<el-step :title="translations.finish.title"></el-step>
</el-steps>
</div>
<div class="card-body bg-default">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-12">
<div class="content-header">
<h3 class="text-white">{{ translations.finish.recommended_apps }}</h3>
</div>
<div class="row">
<div v-for="(item, index) in modules" :key="index" class="col-md-3">
<div class="card">
<div class="card-header py-2">
<h4 class="ml--3 mb-0 float-left">
<a
:href="item.slug"
>{{ item.name }}</a
>
</h4>
</div>
<a :href="route_url + '/' + item.slug"
><img
v-for="(file, indis) in item.files" :key="indis"
v-if="file.media_type == 'image' && file.pivot.zone == 'thumbnail'"
:src="file.path_string"
:alt="item.name"
class="card-img-top border-radius-none"
/></a>
<div class="card-footer py-2">
<div class="float-left ml--3 mt--1">
<i v-for="(stars, indis) in item.vote" :key="indis" class="fa fa-star text-xs text-yellow"></i>
<small class="text-xs"> {{ item.total_review }} </small>
</div>
<div class="float-right mr--3">
<small><strong> {{ item.price }} </strong></small>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12"><ul></ul></div>
</div>
</div>
</div>
<div class="card-footer">
<div class="row">
<div class="col-md-12 d-flex justify-content-between">
<base-button type="white" native-type="submit" @click="prev()"
>{{ translations.finish.previous }}</base-button
>
<base-button type="success" native-type="submit" @click="finish()"
>{{ translations.finish.go_to_dashboard }}</base-button
>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Step, Steps } from "element-ui";
export default {
name: "Finish",
components: {
[Step.name]: Step,
[Steps.name]: Steps,
},
created() {
window.axios({
method: 'GET',
url
}).then(response => {
}).catch(error => {
});
},
props: {
modules: {
type: [Object, Array]
},
translations: {
type: [Object, Array]
}
},
data() {
return {
active: 3,
route_url: url,
};
},
methods: {
finish() {
window.location.href = "";
},
prev() {
if (this.active-- > 2);
this.$router.push("/wizard/taxes");
},
},
};
</script>

View File

@ -0,0 +1,300 @@
<template>
<div>
<h1 class="text-white">{{ translations.taxes.title }}</h1>
<div class="card">
<div class="card-header wizard-header p-3">
<el-steps :active="active" finish-status="success" align-center>
<el-step :title="translations.companies.title"></el-step>
<el-step :title="translations.currencies.title"></el-step>
<el-step :title="translations.taxes.title"></el-step>
<el-step :title="translations.finish.title"></el-step>
</el-steps>
</div>
<div class="card-body">
<div class="d-flex justify-content-end mb-3">
<base-button
type="success"
native-type="button"
class="btn-sm"
@click="addItem()"
>{{ translations.taxes.add_new }}</base-button
>
</div>
<div class="row flex-column">
<form ref="form">
<table class="table table-flush table-hover" id="tbl-taxes">
<thead class="thead-light">
<tr class="row table-head-line">
<th class="col-xs-4 col-sm-4 col-md-3">
{{ translations.taxes.name }}
</th>
<th class="col-md-3 d-none d-md-block">
{{ translations.taxes.rate }}
</th>
<th class="col-xs-4 col-sm-4 col-md-3">
{{ translations.taxes.enabled }}
</th>
<th class="col-xs-4 col-sm-4 col-md-3 text-center">
{{ translations.taxes.actions }}
</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in taxes"
:key="index"
class="row align-items-center border-top-1"
>
<td class="col-xs-4 col-sm-4 col-md-3 tax-name">
<a href="javascript:void(0);"> {{ item.name }} </a>
</td>
<td class="col-md-3 d-none d-md-block">{{ item.rate }}</td>
<td class="col-xs-4 col-sm-4 col-md-3">
<label class="custom-toggle d-inline-block" name="staus-1">
<input
type="checkbox"
:checked="item.enabled"
@input="inputHandle(item)"
/>
<span
class="custom-toggle-slider rounded-circle status-green"
:data-label-on="translations.taxes.yes"
:data-label-off="translations.taxes.no"
>
</span>
</label>
</td>
<td class="col-xs-4 col-sm-4 col-md-3 text-center">
<div class="dropdown">
<a
class="btn btn-neutral btn-sm text-light items-align-center py-2"
href="#"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<i class="fa fa-ellipsis-h text-muted"></i>
</a>
<div
class="dropdown-menu dropdown-menu-right dropdown-menu-arrow"
>
<button
type="button"
class="dropdown-item"
@click="handeClickEdit(item, index)"
>
{{ translations.taxes.edit }}
</button>
<div class="dropdown-divider"></div>
<button
type="button"
class="dropdown-item"
@click="handleClickDelete(item)"
>
{{ translations.taxes.delete }}
</button>
</div>
</div>
</td>
<td class="w-100 p-0 current-tab" v-if="currentTab == index">
<div class="row pt-3 pb-3">
<div
class="form-container col-12 d-flex justify-content-between align-items-start"
>
<base-input
:label="translations.taxes.name"
name="name"
data-name="name"
:placeholder="translations.taxes.name"
prepend-icon="fas fa-font"
form-classes="col-md-4"
v-model="model.name"
/>
<base-input
:label="translations.taxes.rate"
name="rate"
data-name="rate"
:placeholder="translations.taxes.rate"
prepend-icon="fas fa-percentage"
form-classes="col-md-4"
v-model="model.rate"
rules="required"
/>
<div class="mt-4 col-md-4 current-tab-btn">
<base-button
type="success"
native-type="button"
@click="onEditSave(item)"
>{{ translations.taxes.save }}</base-button
>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div class="mt-2" v-if="newDatas">
<div class="row p-3">
<div
class="form-container col-12 d-flex justify-content-between align-items-start"
>
<base-input
:label="translations.taxes.name"
name="name"
data-name="name"
:placeholder="translations.taxes.name"
prepend-icon="fas fa-font"
v-model="model.name"
/>
<base-input
:label="translations.taxes.rate"
name="rate"
data-name="rate"
:placeholder="translations.taxes.rate"
prepend-icon="fas fa-percentage"
v-model="model.rate"
rules="required"
/>
<div>
<div class="d-flex">
<akaunting-radio-group
name="enabled"
:text="translations.taxes.enabled"
:enable="translations.taxes.yes"
:disable="translations.taxes.no"
:value="model.enabled"
>
</akaunting-radio-group>
</div>
</div>
<div class="mt-4">
<base-button
type="success"
native-type="button"
@click="onSubmitForm()"
>{{ translations.taxes.save }}</base-button
>
</div>
</div>
</div>
</div>
</form>
</div>
<notifications></notifications>
<form id="form-dynamic-component" method="POST" action="#"></form>
<component v-bind:is="component" @deleted="deleteCurrency($event)"></component>
</div>
<div class="card-footer">
<div class="row">
<div class="col-md-12 d-flex justify-content-between">
<base-button type="white" native-type="submit" @click="prev()">{{
translations.taxes.previous
}}</base-button>
<base-button type="white" native-type="submit" @click="next()">{{
translations.taxes.next
}}</base-button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Step, Steps } from "element-ui";
import AkauntingRadioGroup from "./../../components/forms/AkauntingRadioGroup";
import Form from "./../../plugins/form";
import BulkAction from "./../../plugins/bulk-action";
import MixinsGlobal from "./../../mixins/global";
import MixinsSpaGlobal from "./../../mixins/spa-global";
export default {
name: "Taxes",
mixins: [MixinsGlobal, MixinsSpaGlobal],
components: {
[Step.name]: Step,
[Steps.name]: Steps,
AkauntingRadioGroup,
},
props: {
taxes: {
type: [Object, Array],
},
translations: {
type: [Object, Array],
},
},
data() {
return {
active: 2,
bulk_action: new BulkAction(url + "/settings/taxes"),
};
},
methods: {
inputHandle(item) {
this.onStatus(item.id, event);
},
handleClickDelete(item) {
this.confirmDelete(
`${
new URL(url).protocol +
"//" +
location.host +
location.pathname +
"/" +
item.id
}`,
this.translations.taxes.title,
`${
this.translations.currencies.title +
"&nbsp;" +
this.translations.currencies.delete
} <strong>${item.name}</strong>?`,
this.translations.taxes.cancel,
this.translations.taxes.delete
);
},
next() {
if (this.active++ > 2);
this.$router.push("/wizard/finish");
},
prev() {
if (this.active-- > 2);
this.$router.push("/wizard/currencies");
},
onEditSave(item) {
this.onEditEvent("PATCH", url + "/wizard/taxes/" + item.id, 'type', this.taxes, item.id);
},
onSubmitForm() {
this.onSubmitEvent("POST", url + "/wizard/taxes", 'type', this.taxes);
},
deleteCurrency(event) {
this.taxes.forEach(function (tax, index) {
if (tax.id == event.tax_id) {
this.taxes.splice(index, 1);
return;
}
}, this);
this.component = "";
let type = event.success ? 'success' : 'error';
let timeout = 1000;
if (event.important) {
timeout = 0;
}
this.$notify({
message: event.message,
timeout: timeout,
icon: "fas fa-bell",
type,
});
},
},
};
</script>

View File

@ -4,83 +4,84 @@
* building robust, powerful web applications using Vue and Laravel. * building robust, powerful web applications using Vue and Laravel.
*/ */
require('../../bootstrap'); require('../../bootstrap');
import Vue from 'vue'; import Vue from 'vue';
import DashboardPlugin from './../../plugins/dashboard-plugin'; import DashboardPlugin from './../../plugins/dashboard-plugin';
import Global from '../../mixins/global'; import Global from '../../mixins/global';
import Form from '../../plugins/form'; import Form from '../../plugins/form';
import BulkAction from './../../plugins/bulk-action'; import BulkAction from './../../plugins/bulk-action';
import {Step, Steps} from 'element-ui'; import {Step, Steps} from 'element-ui';
// plugin setup // plugin setup
Vue.use(DashboardPlugin, Step, Steps); Vue.use(DashboardPlugin, Step, Steps);
const app = new Vue({ const app = new Vue({
el: '#app', el: '#app',
mixins: [ mixins: [
Global Global
], ],
components: { components: {
[Step.name]: Step, [Step.name]: Step,
[Steps.name]: Steps, [Steps.name]: Steps,
}, },
data: function () { data: function () {
return { return {
form: new Form('tax'), form: new Form('tax'),
active: 2, active: 2,
bulk_action: new BulkAction(url + '/settings/taxes'), bulk_action: new BulkAction(url + '/settings/taxes'),
show: false, show: false,
tax: { tax: {
name: '', name: '',
code: '', code: '',
type: 'normal', type: 'normal',
enabled: 1 enabled: 1
}, },
submit_function: '' submit_function: ''
} }
}, },
methods: { methods: {
onAddTax() { onAddTax() {
this.submit_function = 'onStoreTax'; this.submit_function = 'onStoreTax';
this.form.method = 'post'; this.form.method = 'post';
this.form.action = url + '/wizard/taxes'; this.form.action = url + '/wizard/taxes';
this.form.name = ''; this.form.name = '';
this.form.rate = ''; this.form.rate = '';
this.form.type = 'normal'; this.form.type = 'normal';
this.form.enabled = 1; this.form.enabled = 1;
this.show = true; this.show = true;
}, },
onEditTax(tax_id) { onEditTax(tax_id) {
this.submit_function = 'onUpdateTax'; this.submit_function = 'onUpdateTax';
this.form.method = 'patch'; this.form.method = 'patch';
this.form.action = url + '/wizard/taxes/' + tax_id; this.form.action = url + '/wizard/taxes/' + tax_id;
taxes.forEach(tax => { taxes.forEach(tax => {
if (tax.id == tax_id) { if (tax.id == tax_id) {
this.form.name = tax.name; this.form.name = tax.name;
this.form.rate = tax.rate; this.form.rate = tax.rate;
this.form.type = tax.type; this.form.type = tax.type;
this.form.enabled = tax.enabled; this.form.enabled = tax.enabled;
} }
}); });
this.show = true; this.show = true;
}, },
onSubmit() { onSubmit() {
this.form.oldSubmit(); this.form.oldSubmit();
}, },
} }
}); });

View File

@ -0,0 +1,152 @@
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('../../bootstrap');
import Vue from 'vue';
import DashboardPlugin from './../../plugins/dashboard-plugin';
import Global from './../../mixins/global';
import {Progress} from 'element-ui';
Vue.use(Progress);
// plugin setup
Vue.use(DashboardPlugin);
const app = new Vue({
el: '#app',
mixins: [
Global
],
components: {
[Progress.name]: Progress,
},
data: function () {
return {
changelog: {
show:false,
html: null
},
update: {
steps: [],
steps_total: 0,
total: 0,
path: '',
status: 'success',
html: ''
},
page: 'check',
name: null,
version: null
}
},
mounted() {
if (document.getElementById('page') != null && document.getElementById('page').value == 'update') {
this.steps();
}
},
methods: {
async onChangelog() {
let changelog_promise = Promise.resolve(axios.get(url + '/install/updates/changelog'));
changelog_promise.then(response => {
this.changelog.show = true;
this.changelog.html = response.data;
})
.catch(e => {
this.errors.push(e)
})
.finally(function () {
// always executed
});
},
async steps() {
let name = document.getElementById('name').value;
let steps_promise = Promise.resolve(axios.post(url + '/install/updates/steps', {
name: name,
version: version
}));
steps_promise.then(response => {
if (response.data.error) {
this.update.status = 'exception';
this.update.html = '<div class="text-danger">' + response.data.message + '</div>';
}
// Set steps
if (response.data.data) {
this.update.steps = response.data.data;
this.update.steps_total = this.update.steps.length;
this.next();
}
})
.catch(error => {
});
},
async next() {
let data = this.update.steps.shift();
let name = document.getElementById('name').value;
let alias = document.getElementById('alias').value;
let version = document.getElementById('version').value;
let installed = document.getElementById('installed').value;
if (data) {
this.update.total = parseInt((100 - ((this.update.steps.length / this.update.steps_total) * 100)).toFixed(0));
this.update.html = '<span class="text-default"><i class="fa fa-spinner fa-spin update-spin"></i> ' + data['text'] + '</span> </br>';
let step_promise = Promise.resolve(axios.post(data.url, {
name: name,
alias: alias,
version: version,
installed: installed,
path: this.update.path,
}));
step_promise.then(response => {
if (response.data.error) {
this.update.status = 'exception';
this.update.html = '<div class="text-danger"><i class="fa fa-times update-error"></i> ' + response.data.message + '</div>';
}
if (response.data.success) {
this.update.status = 'success';
}
if (response.data.data.path) {
this.update.path = response.data.data.path;
}
if (!response.data.error && !response.data.redirect) {
setTimeout(function() {
this.next();
}.bind(this), 800);
}
if (response.data.redirect) {
window.location = response.data.redirect;
}
})
.catch(error => {
});
}
}
}
});

View File

@ -1,21 +1,32 @@
<html lang="{{ app()->getLocale() }}"> <html>
@include('partials.wizard.head') @include('partials.wizard.head')
<body class="wizard-page"> <body class="wizard-page">
<div class="container mt--5"> <div class="container mt--5">
@stack('body_start') @stack('body_start')
<div id="app"> <div id="app">
{!! Form::open([
'url' => url()->current(),
'role' => 'form',
'id' => 'form-wizard',
'@submit.prevent' => 'onSubmit',
'@keydown' => 'form.errors.clear($event.target.name)',
]) !!}
<div class="card-body">
<div class="document-loading" v-if="!page_loaded">
<div><i class="fas fa-spinner fa-pulse fa-7x"></i></div>
</div>
@include('flash::message')
@include('partials.wizard.content') @yield('content')
</div>
</div>
</div> </div>
@stack('body_end') @include('partials.wizard.scripts')
</div> </body>
@include('partials.wizard.scripts') </html>
</body>
</html>

View File

@ -4,6 +4,8 @@
<script src="{{ asset('public/vendor/bootstrap/dist/js/bootstrap.bundle.min.js') }}"></script> <script src="{{ asset('public/vendor/bootstrap/dist/js/bootstrap.bundle.min.js') }}"></script>
<script src="{{ asset('public/vendor/js-cookie/js.cookie.js') }}"></script> <script src="{{ asset('public/vendor/js-cookie/js.cookie.js') }}"></script>
<script src="{{ asset('public/js/wizard/wizard.js?v=' . version('short')) }}"></script>
@stack('body_css') @stack('body_css')
@stack('body_stylesheet') @stack('body_stylesheet')

View File

@ -3,84 +3,5 @@
@section('title', trans('general.wizard')) @section('title', trans('general.wizard'))
@section('content') @section('content')
<div class="card">
{!! Form::model($company, [
'method' => 'PATCH',
'route' => ['wizard.companies.update'],
'id' => 'company',
'@submit.prevent' => 'onSubmit',
'@keydown' => 'form.errors.clear($event.target.name)',
'files' => true,
'role' => 'form',
'class' => 'form-loading-button mb-0',
'novalidate' => true
]) !!}
<div id="wizard-loading"></div>
@include('partials.wizard.steps')
<div class="card-body">
<div id="wizard-loading"></div>
<div class="row mb--4">
<div class="col-md-12 {!! (!setting('apps.api_key', null)) ?: 'hidden' !!}">
<div class="form-group {{ $errors->has('api_key') ? 'has-error' : ''}}"
:class="[{'has-error': form.errors.get('api_key') }]">
{!! Form::label('api-key', trans('modules.api_key'), ['class' => 'form-control-label']) !!}
<div class="input-group input-group-merge">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="fa fa-key"></i>
</span>
</div>
{!! Form::text('api_key', setting('apps.api_key', null), array_merge([
'class' => 'form-control',
'data-name' => 'api_key',
'data-value' => setting('apps.api_key', null),
'placeholder' => trans('general.form.enter', ['field' => trans('modules.api_key')]),
'v-model' => 'form.api_key'
], [])) !!}
</div>
<div class="invalid-feedback d-block" v-if="form.errors.has('api_key')" v-html="form.errors.get('api_key')"></div>
</div>
<p class="mb-0 mt--3">
<small>{!! trans('modules.get_api_key', ['url' => 'https://akaunting.com/dashboard']) !!}</small>
</p>
<br>
</div>
{{ Form::textGroup('tax_number', trans('general.tax_number'), 'percent', []) }}
{{ Form::dateGroup('financial_start', trans('settings.localisation.financial_start'), 'calendar', ['id' => 'financial_start', 'class' => 'form-control datepicker', 'show-date-format' => 'j F', 'date-format' => 'd-m', 'autocomplete' => 'off'], Date::now()->startOfYear()->format('d-m')) }}
{{ Form::textareaGroup('address', trans('settings.company.address')) }}
{{ Form::fileGroup('logo', trans('settings.company.logo'), '', ['dropzone-class' => 'form-file']) }}
</div>
</div>
<div class="card-footer">
<div class="row">
<div class="col-md-12 text-right">
{!! Form::button(
'<span v-if="form.loading" class="btn-inner--icon"><i class="aka-loader"></i></span> <span :class="[{\'ml-0\': form.loading}]" class="btn-inner--text">' . trans('general.save') . '</span>',
[':disabled' => 'form.loading', 'type' => 'submit', 'class' => 'btn btn-icon btn-success']) !!}
<a href="{{ route('wizard.currencies.index') }}" id="wizard-skip" class="btn btn-white">
{{ trans('general.skip') }}
</a>
</div>
</div>
</div>
{!! Form::close() !!}
</div>
@endsection @endsection
@push('scripts_start')
<script src="{{ asset('public/js/wizard/company.js?v=' . version('short')) }}"></script>
@endpush

View File

@ -3,143 +3,5 @@
@section('title', trans('general.wizard')) @section('title', trans('general.wizard'))
@section('content') @section('content')
<div class="card">
@include('partials.wizard.steps')
<div class="card-body border-bottom-0">
<div class="row">
<div class="col-md-12 text-right">
<button type="button" @click="onAddCurrency" class="btn btn-success btn-sm">
{{ trans('general.add_new') }}
</button>
</div>
</div>
</div>
<div class="table-responsive">
{!! Form::open([
'route' => 'wizard.currencies.store',
'id' => 'currency',
'@submit.prevent' => 'onSubmit',
'@keydown' => 'form.errors.clear($event.target.name)',
'files' => true,
'role' => 'form',
'class' => 'form-loading-button mb-0',
'novalidate' => true
]) !!}
<table class="table table-flush table-hover" id='tbl-currencies'>
<thead class="thead-light">
<tr class="row table-head-line">
<th class="col-xs-4 col-sm-4 col-md-3">@sortablelink('name', trans('general.name'))</th>
<th class="col-md-3 d-none d-md-block">@sortablelink('code', trans('currencies.code'))</th>
<th class="col-md-2 d-none d-md-block">@sortablelink('rate', trans('currencies.rate'))</th>
<th class="col-xs-4 col-sm-4 col-md-2 ">@sortablelink('enabled', trans('general.enabled'))</th>
<th class="col-xs-4 col-sm-4 col-md-2 text-center">{{ trans('general.actions') }}</th>
</tr>
</thead>
<tbody>
@foreach($currencies as $item)
<tr class="row align-items-center border-top-1" id="currency-{{ $item->id }}">
<td class="col-xs-4 col-sm-4 col-md-3">
<a href="javascript:void(0);" @click="onEditCurrency('{{ $item->id }}')">
{{ $item->name }}
</a>
</td>
<td class="col-md-3 d-none d-md-block">{{ $item->code }}</td>
<td class="col-md-2 d-none d-md-block">{{ $item->rate }}</td>
<td class="col-xs-4 col-sm-4 col-md-2">
@if (user()->can('update-settings-currencies'))
{{ Form::enabledGroup($item->id, $item->name, $item->enabled) }}
@else
@if ($item->enabled)
<badge rounded type="success" class="mw-60">{{ trans('general.yes') }}</badge>
@else
<badge rounded type="danger" class="mw-60">{{ trans('general.no') }}</badge>
@endif
@endif
</td>
<td class="col-xs-4 col-sm-4 col-md-2 text-center">
<div class="dropdown">
<a class="btn btn-neutral btn-sm text-light items-align-center py-2" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-ellipsis-h text-muted"></i>
</a>
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
<button type="button" class="dropdown-item" @click="onEditCurrency('{{ $item->id }}')">
{{ trans('general.edit') }}
</button>
@can('delete-settings-currencies')
<div class="dropdown-divider"></div>
{!! Form::deleteLink($item, 'wizard.currencies.destroy') !!}
@endcan
</div>
</div>
</td>
</tr>
@endforeach
<tr class="row align-items-center border-top-1" v-show="show">
<td class="col-xs-4 col-sm-4 col-md-3">
{{ Form::textGroup('name', trans('general.name'), 'font', [], null, '') }}
</td>
<td class="col-md-3 d-none d-md-block">
{{ Form::selectGroup('code', trans('currencies.code'), 'code', $codes, null, ['required' => 'required', 'change' => 'onChangeCode', 'model' => 'form.code'], '') }}
</td>
<td class="col-md-2 d-none d-md-block">
{{ Form::textGroup('rate', trans('currencies.rate'), 'percentage', ['required' => 'required'], null, '') }}
</td>
<td class="col-xs-4 col-sm-4 col-md-2">
{{ Form::radioGroup('enabled', trans('general.enabled')) }}
</td>
<td class="col-xs-4 col-sm-4 col-md-2 text-center">
{!! Form::button(
trans('general.save'), [
':disabled' => 'form.loading',
'type' => 'submit',
'class' => 'btn btn-success',
]) !!}
<div class="d-none">
{{ Form::numberGroup('precision', trans('currencies.precision'), 'bullseye') }}
{{ Form::textGroup('symbol', trans('currencies.symbol.symbol'), 'font') }}
{{ Form::selectGroup('symbol_first', trans('currencies.symbol.position'), 'text-width', ['1' => trans('currencies.symbol.before'), '0' => trans('currencies.symbol.after')]) }}
{{ Form::textGroup('decimal_mark', trans('currencies.decimal_mark'), 'columns') }}
{{ Form::textGroup('thousands_separator', trans('currencies.thousands_separator'), 'columns', []) }}
</div>
</td>
</tr>
</tbody>
</table>
<input type="hidden" name="bulk_action_path" value="settings/currencies"/>
{!! Form::close() !!}
</div>
<div class="card-footer">
<div class="row">
<div class="col-sm-6">
<a href="{{ route('wizard.companies.edit') }}" class="btn btn-icon btn-white">
<span class="btn-inner--text">{{ trans('pagination.previous') }}</span>
</a>
</div>
<div class="col-sm-6 text-right">
<a href="{{ route('wizard.taxes.index') }}" id="wizard-skip" class="btn btn-icon btn-white">
<span class="btn-inner--text">{{ trans('pagination.next') }}</span>
</a>
</div>
</div>
</div>
</div>
@endsection @endsection
@push('scripts_start')
<script type="text/javascript">
var currencies = {!! json_encode($currencies->items()) !!}
</script>
<script src="{{ asset('public/js/wizard/currencies.js?v=' . version('short')) }}"></script>
@endpush

View File

@ -3,68 +3,5 @@
@section('title', trans('general.wizard')) @section('title', trans('general.wizard'))
@section('content') @section('content')
<div class="card">
@include('partials.wizard.steps')
<div class="card-body bg-default">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-12">
<div class="content-header">
<h3 class="text-white">{{ trans('modules.recommended_apps') }}</h3>
</div>
@if ($modules)
<div class="row">
@foreach ($modules->data as $module)
@include('partials.modules.item')
@endforeach
</div>
<div class="col-md-12">
<ul>
@if ($modules->current_page < $modules->last_page)
<li class="next"><a href="{{ url(request()->path()) }}?page={{ $modules->current_page + 1 }}" class="btn btn-default btn-sm">{!! trans('pagination.next') !!}</a></li>
@endif
@if ($modules->current_page > 1)
<li class="previous"><a href="{{ url(request()->path()) }}?page={{ $modules->current_page - 1 }}" class="btn btn-default btn-sm">{{ trans('pagination.previous') }}</a></li>
@endif
</ul>
</div>
@else
<div class="card">
<div class="card-body">
<p class="col-md-12">
{{ trans('modules.no_apps') }}
</p>
<p class="col-md-12">
<small>{!! trans('modules.developer') !!}</small>
</p>
</div>
</div>
@endif
</div>
</div>
</div>
<div class="card-footer">
<div class="row">
<div class="col-sm-6">
<a href="{{ route('wizard.taxes.index') }}" class="btn btn-icon btn-white">
<span class="btn-inner--text">{{ trans('pagination.previous') }}</span>
</a>
</div>
<div class="col-sm-6 text-right">
<a href="{{ route('dashboard') }}" id="wizard-skip" class="btn btn-icon btn-success">
<span class="btn-inner--text">{{ trans('general.go_to_dashboard') }}</span>
</a>
</div>
</div>
</div>
</div>
@endsection @endsection
@push('scripts_start')
<script src="{{ asset('public/js/wizard/finish.js?v=' . version('short')) }}"></script>
@endpush

View File

@ -3,125 +3,5 @@
@section('title', trans('general.wizard')) @section('title', trans('general.wizard'))
@section('content') @section('content')
<div class="card">
@include('partials.wizard.steps')
<div class="card-body border-bottom-0">
<div class="row">
<div class="col-md-12 text-right">
<button type="button" @click="onAddTax" class="btn btn-success btn-sm">
{{ trans('general.add_new') }}
</button>
</div>
</div>
</div>
<div class="table-responsive">
{!! Form::open([
'route' => 'wizard.taxes.store',
'id' => 'tax',
'@submit.prevent' => 'onSubmit',
'@keydown' => 'form.errors.clear($event.target.name)',
'files' => true,
'role' => 'form',
'class' => 'form-loading-button mb-0',
'novalidate' => true
]) !!}
<table class="table table-flush table-hover" id='tbl-taxes'>
<thead class="thead-light">
<tr class="row table-head-line">
<th class="col-xs-4 col-sm-4 col-md-3">@sortablelink('name', trans('general.name'))</th>
<th class="col-md-3 d-none d-md-block">@sortablelink('rate', trans('taxes.rate_percent'))</th>
<th class="col-xs-4 col-sm-4 col-md-3">@sortablelink('enabled', trans('general.enabled'))</th>
<th class="col-xs-4 col-sm-4 col-md-3 text-center">{{ trans('general.actions') }}</th>
</tr>
</thead>
<tbody>
@foreach($taxes as $item)
<tr class="row align-items-center border-top-1" id="tax-{{ $item->id }}">
<td class="col-xs-4 col-sm-4 col-md-3 tax-name">
<a href="javascript:void(0);" @click="onEditTax('{{ $item->id }}')">
{{ $item->name }}
</a>
</td>
<td class="col-md-3 d-none d-md-block">{{ $item->rate }}</td>
<td class="col-xs-4 col-sm-4 col-md-3">
@if (user()->can('update-settings-taxes'))
{{ Form::enabledGroup($item->id, $item->name, $item->enabled) }}
@else
@if ($item->enabled)
<badge rounded type="success" class="mw-60">{{ trans('general.yes') }}</badge>
@else
<badge rounded type="danger" class="mw-60">{{ trans('general.no') }}</badge>
@endif
@endif
</td>
<td class="col-xs-4 col-sm-4 col-md-3 text-center">
<div class="dropdown">
<a class="btn btn-neutral btn-sm text-light items-align-center py-2" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-ellipsis-h text-muted"></i>
</a>
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
<button type="button" class="dropdown-item" @click="onEditTax('{{ $item->id }}')">
{{ trans('general.edit') }}
</button>
@can('delete-settings-taxes')
<div class="dropdown-divider"></div>
{!! Form::deleteLink($item, 'wizard.taxes.destroy') !!}
@endcan
</div>
</div>
</td>
</tr>
@endforeach
<tr class="row align-items-center border-top-1" v-show="show">
<td class="col-xs-4 col-sm-4 col-md-3">
{{ Form::textGroup('name', trans('general.name'), 'font', [], null, '') }}
</td>
<td class="col-md-3 d-none d-md-block">
{{ Form::textGroup('rate', trans('currencies.rate'), 'percentage', ['required' => 'required'], null, '') }}
</td>
<td class="col-xs-4 col-sm-4 col-md-3">
{{ Form::radioGroup('enabled', trans('general.enabled')) }}
</td>
<td class="col-xs-4 col-sm-4 col-md-3 text-center">
{!! Form::button(
trans('general.save'), [
':disabled' => 'form.loading',
'type' => 'submit',
'class' => 'btn btn-success',
]) !!}
</td>
</tr>
</tbody>
</table>
<input type="hidden" name="bulk_action_path" value="settings/taxes" />
{!! Form::close() !!}
</div>
<div class="card-footer">
<div class="row">
<div class="col-sm-6">
<a href="{{ route('wizard.currencies.index') }}" class="btn btn-icon btn-white">
<span class="btn-inner--text">{{ trans('pagination.previous') }}</span>
</a>
</div>
<div class="col-sm-6 text-right">
<a href="{{ route('wizard.finish.index') }}" id="wizard-skip" class="btn btn-icon btn-white">
<span class="btn-inner--text">{{ trans('pagination.next') }}</span>
</a>
</div>
</div>
</div>
</div>
@endsection @endsection
@push('scripts_start')
<script type="text/javascript">
var taxes = {!! json_encode($taxes->items()) !!}
</script>
<script src="{{ asset('public/js/wizard/taxes.js?v=' . version('short')) }}"></script>
@endpush

View File

@ -9,6 +9,9 @@ use Illuminate\Support\Facades\Route;
*/ */
Route::group(['as' => 'wizard.'], function () { Route::group(['as' => 'wizard.'], function () {
Route::get('data', 'Wizard\Data@index')->name('data.index');
Route::get('translations', 'Wizard\Translations@index')->name('translations.index');
Route::get('companies', 'Wizard\Companies@edit')->name('companies.edit'); Route::get('companies', 'Wizard\Companies@edit')->name('companies.edit');
Route::patch('companies', 'Wizard\Companies@update')->name('companies.update'); Route::patch('companies', 'Wizard\Companies@update')->name('companies.update');
@ -21,4 +24,5 @@ Route::group(['as' => 'wizard.'], function () {
Route::resource('taxes', 'Wizard\Taxes'); Route::resource('taxes', 'Wizard\Taxes');
Route::get('finish', 'Wizard\Finish@index')->name('finish.index'); Route::get('finish', 'Wizard\Finish@index')->name('finish.index');
Route::patch('finish', 'Wizard\Finish@update')->name('finish.update');
}); });

4
webpack.mix.js vendored
View File

@ -58,6 +58,10 @@ mix
.js('resources/assets/js/install.js', 'public/js') .js('resources/assets/js/install.js', 'public/js')
.js('resources/assets/js/views/install/update.js', 'public/js/install') .js('resources/assets/js/views/install/update.js', 'public/js/install')
//Wizard
.js('resources/assets/js/wizard.js', 'public/js/wizard')
.js('resources/assets/js/views/wizard/update.js', 'public/js/wizard')
// Modules // Modules
.js('resources/assets/js/views/modules/item.js', 'public/js/modules') .js('resources/assets/js/views/modules/item.js', 'public/js/modules')
.js('resources/assets/js/views/modules/apps.js', 'public/js/modules') .js('resources/assets/js/views/modules/apps.js', 'public/js/modules')