Merge branch 'master' of https://github.com/brkcvn/akaunting into new-plans
This commit is contained in:
		@@ -425,15 +425,15 @@ abstract class Form extends Component
 | 
			
		||||
 | 
			
		||||
    protected function getCurrency($document, $currency, $currency_code)
 | 
			
		||||
    {
 | 
			
		||||
        if (!empty($currency)) {
 | 
			
		||||
        if (! empty($currency)) {
 | 
			
		||||
            return $currency;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!empty($currency_code)) {
 | 
			
		||||
        if (! empty($currency_code)) {
 | 
			
		||||
            $currency = Currency::where('code', $currency_code)->first();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (empty($currency) && !empty($document)) {
 | 
			
		||||
        if (empty($currency) && ! empty($document)) {
 | 
			
		||||
            $currency = Currency::where('code', $document->currency_code)->first();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -146,14 +146,31 @@ class Categories extends Controller
 | 
			
		||||
            $categories[$type] = [];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Category::enabled()->orderBy('name')->get()->each(function ($category) use (&$categories, $edited_category_id) {
 | 
			
		||||
            if ($edited_category_id != $category->id) {
 | 
			
		||||
                $categories[$category->type][] = [
 | 
			
		||||
                    'id' => $category->id,
 | 
			
		||||
                    'title' => $category->name,
 | 
			
		||||
                    'level' => $category->level,
 | 
			
		||||
                ];
 | 
			
		||||
        $skip_categories = [];
 | 
			
		||||
        $skip_categories[] = $edited_category_id;
 | 
			
		||||
 | 
			
		||||
        foreach ($category->sub_categories as $sub_category) {
 | 
			
		||||
            $skip_categories[] = $sub_category->id;
 | 
			
		||||
 | 
			
		||||
            if ($sub_category->sub_categories) {
 | 
			
		||||
                $skips = $this->getChildrenCategoryIds($sub_category);
 | 
			
		||||
 | 
			
		||||
                foreach ($skips as $skip) {
 | 
			
		||||
                    $skip_categories[] = $skip;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Category::enabled()->orderBy('name')->get()->each(function ($category) use (&$categories, &$skip_categories) {
 | 
			
		||||
            if (in_array($category->id, $skip_categories)) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $categories[$category->type][] = [
 | 
			
		||||
                'id' => $category->id,
 | 
			
		||||
                'title' => $category->name,
 | 
			
		||||
                'level' => $category->level,
 | 
			
		||||
            ];
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return view('settings.categories.edit', compact('category', 'types', 'type_disabled', 'categories'));
 | 
			
		||||
@@ -167,10 +184,8 @@ class Categories extends Controller
 | 
			
		||||
     *
 | 
			
		||||
     * @return Response
 | 
			
		||||
     */
 | 
			
		||||
    public function update($category_id, Request $request)
 | 
			
		||||
    public function update(Category $category, Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $category = $this->getCategoryWithoutChildren($category_id);
 | 
			
		||||
 | 
			
		||||
        $response = $this->ajaxDispatch(new UpdateCategory($category, $request));
 | 
			
		||||
 | 
			
		||||
        if ($response['success']) {
 | 
			
		||||
@@ -197,10 +212,8 @@ class Categories extends Controller
 | 
			
		||||
     *
 | 
			
		||||
     * @return Response
 | 
			
		||||
     */
 | 
			
		||||
    public function enable($category_id)
 | 
			
		||||
    public function enable(Category $category)
 | 
			
		||||
    {
 | 
			
		||||
        $category = $this->getCategoryWithoutChildren($category_id);
 | 
			
		||||
 | 
			
		||||
        $response = $this->ajaxDispatch(new UpdateCategory($category, request()->merge(['enabled' => 1])));
 | 
			
		||||
 | 
			
		||||
        if ($response['success']) {
 | 
			
		||||
@@ -217,10 +230,8 @@ class Categories extends Controller
 | 
			
		||||
     *
 | 
			
		||||
     * @return Response
 | 
			
		||||
     */
 | 
			
		||||
    public function disable($category_id)
 | 
			
		||||
    public function disable(Category $category)
 | 
			
		||||
    {
 | 
			
		||||
        $category = $this->getCategoryWithoutChildren($category_id);
 | 
			
		||||
 | 
			
		||||
        $response = $this->ajaxDispatch(new UpdateCategory($category, request()->merge(['enabled' => 0])));
 | 
			
		||||
 | 
			
		||||
        if ($response['success']) {
 | 
			
		||||
 
 | 
			
		||||
@@ -87,5 +87,29 @@ class UpdateUser extends Job implements ShouldUpdate
 | 
			
		||||
 | 
			
		||||
            throw new \Exception($message);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Can't unassigned company, The company must be assigned at least one user.
 | 
			
		||||
        $companies = $this->request->get('companies');
 | 
			
		||||
        $user_companies = $this->model->companies()->pluck('id')->toArray();
 | 
			
		||||
 | 
			
		||||
        $company_diff = array_diff($user_companies, $companies);
 | 
			
		||||
 | 
			
		||||
        if ($company_diff) {
 | 
			
		||||
            $errors = [];
 | 
			
		||||
 | 
			
		||||
            foreach ($company_diff as $company_id) {
 | 
			
		||||
                $company = Company::withCount('users')->find($company_id);
 | 
			
		||||
 | 
			
		||||
                if ($company->users_count < 2) {
 | 
			
		||||
                    $errors[] = trans('auth.error.unassigned', ['company' => $company->name]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($errors) {
 | 
			
		||||
                $message = implode('\n', $errors);
 | 
			
		||||
 | 
			
		||||
                throw new \Exception($message);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								app/Listeners/Update/V30/Version307.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/Listeners/Update/V30/Version307.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Update\V30;
 | 
			
		||||
 | 
			
		||||
use App\Abstracts\Listeners\Update as Listener;
 | 
			
		||||
use App\Events\Install\UpdateFinished as Event;
 | 
			
		||||
use Illuminate\Support\Facades\Artisan;
 | 
			
		||||
use Illuminate\Support\Facades\Log;
 | 
			
		||||
 | 
			
		||||
class Version307 extends Listener
 | 
			
		||||
{
 | 
			
		||||
    const ALIAS = 'core';
 | 
			
		||||
 | 
			
		||||
    const VERSION = '3.0.7';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->skipThisUpdate($event)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Log::channel('stdout')->info('Updating to 3.0.7 version...');
 | 
			
		||||
 | 
			
		||||
        $this->updateDatabase();
 | 
			
		||||
 | 
			
		||||
        Log::channel('stdout')->info('Done!');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function updateDatabase(): void
 | 
			
		||||
    {
 | 
			
		||||
        Log::channel('stdout')->info('Updating database...');
 | 
			
		||||
 | 
			
		||||
        Artisan::call('migrate', ['--force' => true]);
 | 
			
		||||
 | 
			
		||||
        Log::channel('stdout')->info('Database updated.');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -94,6 +94,7 @@ class Category extends Model
 | 
			
		||||
    {
 | 
			
		||||
        return $this->resolveRouteBindingQuery($this, $value, $field)
 | 
			
		||||
            ->withoutGlobalScope(Scope::class)
 | 
			
		||||
            ->getWithoutChildren()
 | 
			
		||||
            ->first();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ class Event extends Provider
 | 
			
		||||
            'App\Listeners\Update\V30\Version303',
 | 
			
		||||
            'App\Listeners\Update\V30\Version304',
 | 
			
		||||
            'App\Listeners\Update\V30\Version305',
 | 
			
		||||
            'App\Listeners\Update\V30\Version307',
 | 
			
		||||
        ],
 | 
			
		||||
        'Illuminate\Auth\Events\Login' => [
 | 
			
		||||
            'App\Listeners\Auth\Login',
 | 
			
		||||
 
 | 
			
		||||
@@ -43,4 +43,19 @@ trait Categories
 | 
			
		||||
 | 
			
		||||
        return $id == $this->getTransferCategoryId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getChildrenCategoryIds($category)
 | 
			
		||||
    {
 | 
			
		||||
        $ids = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($category->sub_categories as $sub_category) {
 | 
			
		||||
            $ids[] = $sub_category->id;
 | 
			
		||||
 | 
			
		||||
            if ($sub_category->sub_categories) {
 | 
			
		||||
                $ids = array_merge($ids, $this->getChildrenCategoryIds($sub_category));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $ids;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								public/css/app.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								public/css/app.css
									
									
									
									
										vendored
									
									
								
							@@ -51707,6 +51707,10 @@ body{
 | 
			
		||||
    right: 6rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .lg\:top-2{
 | 
			
		||||
    top: 0.5rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .lg\:col-span-5{
 | 
			
		||||
    grid-column: span 5 / span 5;
 | 
			
		||||
  }
 | 
			
		||||
@@ -51800,8 +51804,21 @@ body{
 | 
			
		||||
    height: 1rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
  .lg\:w-18{
 | 
			
		||||
    width: 4.5rem;
 | 
			
		||||
=======
 | 
			
		||||
  .lg\:h-12{
 | 
			
		||||
    height: 3rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .lg\:h-auto{
 | 
			
		||||
    height: auto;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .lg\:w-9{
 | 
			
		||||
    width: 2.25rem;
 | 
			
		||||
>>>>>>> e8693a3c924c3442b8be7a2ad7bdf8525ed982d4
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .lg\:w-1\/2{
 | 
			
		||||
@@ -51884,6 +51901,10 @@ body{
 | 
			
		||||
    width: 24rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .lg\:w-auto{
 | 
			
		||||
    width: auto;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .lg\:w-2\/4{
 | 
			
		||||
    width: 50%;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
            tabindex="-1"
 | 
			
		||||
            role="dialog"
 | 
			
		||||
            :aria-hidden="!show">
 | 
			
		||||
            <div class="w-full my-10 m-auto flex flex-col" :class="modalDialogClass ? modalDialogClass : 'max-w-screen-sm'">
 | 
			
		||||
            <div class="w-full my-10 m-auto flex flex-col" :class="modalDialogClass ? modalDialogClass : 'max-w-md'">
 | 
			
		||||
                <slot name="modal-content">
 | 
			
		||||
                    <div class="modal-content">
 | 
			
		||||
                        <div class="p-5 bg-body rounded-tl-lg rounded-tr-lg">
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
            tabindex="-1"
 | 
			
		||||
            role="dialog"
 | 
			
		||||
            :aria-hidden="!show">
 | 
			
		||||
            <div class="w-full my-10 m-auto flex flex-col" :class="modalDialogClass ? modalDialogClass : 'max-w-screen-sm'">
 | 
			
		||||
            <div class="w-full my-10 m-auto flex flex-col" :class="modalDialogClass ? modalDialogClass : 'max-w-md'">
 | 
			
		||||
                <slot name="modal-content">
 | 
			
		||||
                    <div class="modal-content">
 | 
			
		||||
                        <div class="p-5 bg-body rounded-tl-lg rounded-tr-lg">
 | 
			
		||||
 
 | 
			
		||||
@@ -1,37 +1,39 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div
 | 
			
		||||
        :id="'search-field-' + _uid"
 | 
			
		||||
        class="h-12 my-5 searh-field flex border-b transition-all js-search"
 | 
			
		||||
        class="lg:h-12 my-5 searh-field flex flex-col lg:flex-row border-b transition-all js-search"
 | 
			
		||||
        :class="input_focus ? 'border-gray-500' : 'border-gray-300'"
 | 
			
		||||
    >
 | 
			
		||||
        <div class="tags-group group items-center" style="display:contents;" v-for="(filter, index) in filtered" :index="index">
 | 
			
		||||
            <span v-if="filter.option" class="flex items-center bg-purple-lighter text-black border-0 mt-3 px-3 py-4 text-sm cursor-pointer el-tag el-tag--small el-tag-option">
 | 
			
		||||
                {{ filter.option }}
 | 
			
		||||
        <div class="w-full lg:w-auto flex overflow-x-scroll large-overflow-unset" :class="filtered.length ? 'h-12 lg:h-auto' : ''">
 | 
			
		||||
            <div class="tags-group group items-center" style="display:contents;" v-for="(filter, index) in filtered" :index="index">
 | 
			
		||||
                <span v-if="filter.option" class="flex items-center bg-purple-lighter text-black border-0 mt-3 px-3 py-4 text-sm cursor-pointer el-tag el-tag--small el-tag-option">
 | 
			
		||||
                    {{ filter.option }}
 | 
			
		||||
 | 
			
		||||
                <i v-if="!filter.operator && !filter.value" class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close" style="font-size: 16px;" @click="onFilterDelete(index)"></i>
 | 
			
		||||
            </span>
 | 
			
		||||
                    <i v-if="!filter.operator && !filter.value" class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close" style="font-size: 16px;" @click="onFilterDelete(index)"></i>
 | 
			
		||||
                </span>
 | 
			
		||||
 | 
			
		||||
            <span v-if="filter.operator" class="flex items-center bg-purple-lighter text-black border-2 border-body border-l border-r border-t-0 border-b-0 mt-3 px-3 py-4 text-sm cursor-pointer el-tag el-tag--small el-tag-operator" style="margin-left:0; margin-right:0;">
 | 
			
		||||
                <span v-if="filter.operator == '='" class="material-icons text-2xl">drag_handle</span>
 | 
			
		||||
                <span v-else-if="filter.operator == '><'" class="material-icons text-2xl transform rotate-90">height</span>
 | 
			
		||||
                <span v-if="filter.operator" class="flex items-center bg-purple-lighter text-black border-2 border-body border-l border-r border-t-0 border-b-0 mt-3 px-3 py-4 text-sm cursor-pointer el-tag el-tag--small el-tag-operator" style="margin-left:0; margin-right:0;">
 | 
			
		||||
                    <span v-if="filter.operator == '='" class="material-icons text-2xl">drag_handle</span>
 | 
			
		||||
                    <span v-else-if="filter.operator == '><'" class="material-icons text-2xl transform rotate-90">height</span>
 | 
			
		||||
 | 
			
		||||
                <img v-else :src="not_equal_image" class="w-5 h-5 object-cover block" />
 | 
			
		||||
                    <img v-else :src="not_equal_image" class="w-5 h-5 object-cover block" />
 | 
			
		||||
 | 
			
		||||
                <i v-if="!filter.value" class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close " style="font-size: 16px;" @click="onFilterDelete(index)"></i>
 | 
			
		||||
            </span>
 | 
			
		||||
                    <i v-if="!filter.value" class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close " style="font-size: 16px;" @click="onFilterDelete(index)"></i>
 | 
			
		||||
                </span>
 | 
			
		||||
 | 
			
		||||
            <span v-if="filter.value" class="flex items-center bg-purple-lighter text-black border-0 mt-3 px-3 py-4 text-sm cursor-pointer el-tag el-tag--small  el-tag-value">
 | 
			
		||||
                {{ filter.value }}
 | 
			
		||||
                <span v-if="filter.value" class="flex items-center bg-purple-lighter text-black border-0 mt-3 px-3 py-4 text-sm cursor-pointer el-tag el-tag--small  el-tag-value">
 | 
			
		||||
                    {{ filter.value }}
 | 
			
		||||
 | 
			
		||||
                <i class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close " style="font-size: 16px;" @click="onFilterDelete(index)"></i>
 | 
			
		||||
            </span>
 | 
			
		||||
                    <i class="mt-1 ltr:-right-2 rtl:left-0 rtl:right-0 el-tag__close el-icon-close " style="font-size: 16px;" @click="onFilterDelete(index)"></i>
 | 
			
		||||
                </span>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="relative w-full h-full flex">
 | 
			
		||||
            <input
 | 
			
		||||
            v-if="!show_date"
 | 
			
		||||
            type="text"
 | 
			
		||||
            class="w-full bg-transparent text-black text-sm border-0 pb-0 focus:outline-none focus:ring-transparent focus:border-purple-100"
 | 
			
		||||
            class="w-full h-12 lg:h-auto bg-transparent text-black text-sm border-0 pb-0 focus:outline-none focus:ring-transparent focus:border-purple-100"
 | 
			
		||||
            :class="!show_icon ? 'px-4' : 'px-10'"
 | 
			
		||||
            :placeholder="dynamicPlaceholder"
 | 
			
		||||
            :ref="'input-search-field-' + _uid"
 | 
			
		||||
@@ -47,7 +49,7 @@
 | 
			
		||||
                @on-open="onInputFocus"
 | 
			
		||||
                @blur="onBlur"
 | 
			
		||||
                :config="dateConfig"
 | 
			
		||||
                class="w-full bg-transparent text-black text-sm border-0 pb-0 focus:outline-none focus:ring-transparent focus:border-purple-100 datepicker"
 | 
			
		||||
                class="w-full h-12 lg:h-auto bg-transparent text-black text-sm border-0 pb-0 focus:outline-none focus:ring-transparent focus:border-purple-100 datepicker"
 | 
			
		||||
                :class="!show_icon ? 'px-4' : 'px-10'"
 | 
			
		||||
                :placeholder="dynamicPlaceholder"
 | 
			
		||||
                :ref="'input-search-date-field-' + _uid"
 | 
			
		||||
@@ -65,7 +67,7 @@
 | 
			
		||||
                    search
 | 
			
		||||
                </span>
 | 
			
		||||
 | 
			
		||||
            <button type="button" class="absolute ltr:right-0 rtl:left-0 top-2 clear" v-if="show_close_icon" @click="onSearchAndFilterClear">
 | 
			
		||||
            <button type="button" class="absolute ltr:right-0 rtl:left-0 top-4 lg:top-2 clear" v-if="show_close_icon" @click="onSearchAndFilterClear">
 | 
			
		||||
                <span class="material-icons text-sm">close</span>
 | 
			
		||||
            </button>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -107,7 +107,7 @@
 | 
			
		||||
 | 
			
		||||
        <span slot="infoBlock" class="absolute right-8 top-3 bg-green text-white px-2 py-1 rounded-md text-xs" v-if="new_options[selected]">{{ addNew.new_text }}</span>
 | 
			
		||||
 | 
			
		||||
        <select :name="name"  :id="name" v-model="selected" class="d-none">
 | 
			
		||||
        <select :name="name" :id="name" class="hidden">
 | 
			
		||||
            <option v-for="option in sortedOptions" :key="option.key" :value="option.key">{{ option.value }}</option>
 | 
			
		||||
        </select>
 | 
			
		||||
    </base-input>
 | 
			
		||||
@@ -299,6 +299,11 @@ export default {
 | 
			
		||||
            default: '',
 | 
			
		||||
            description: "Selectbox input search placeholder text"
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        forceDynamicOptionValue: {
 | 
			
		||||
            type: [Boolean, String],
 | 
			
		||||
            default: false,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    data() {
 | 
			
		||||
@@ -350,7 +355,6 @@ export default {
 | 
			
		||||
            } else {
 | 
			
		||||
                this.sorted_options.sort(this.sortBy(this.option_sortable));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return this.sorted_options;
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
@@ -865,6 +869,33 @@ export default {
 | 
			
		||||
                this.setSortedOptions();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        dynamicOptionsValue(options) {
 | 
			
		||||
            if (! this.forceDynamicOptionValue) {
 | 
			
		||||
                if (this.multiple) {
 | 
			
		||||
                    this.selected = [];
 | 
			
		||||
                } else {
 | 
			
		||||
                    this.selected = null;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.multiple) {
 | 
			
		||||
                let selected = this.selected;
 | 
			
		||||
                this.selected = [];
 | 
			
		||||
 | 
			
		||||
                selected.forEach(function (select, index) {
 | 
			
		||||
                    if (this.sorted_options.find((option) => option.key == select)) {
 | 
			
		||||
                        this.selected.push(select);
 | 
			
		||||
                    }
 | 
			
		||||
                }, this);
 | 
			
		||||
            } else {
 | 
			
		||||
                if (! options.find((option) => option == this.selected)) {
 | 
			
		||||
                    this.selected = null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    watch: {
 | 
			
		||||
@@ -882,15 +913,17 @@ export default {
 | 
			
		||||
                    let is_string = false;
 | 
			
		||||
                    let pre_value = [];
 | 
			
		||||
 | 
			
		||||
                    selected.forEach(item => {
 | 
			
		||||
                        if (typeof item != 'string') {
 | 
			
		||||
                            is_string = true;
 | 
			
		||||
                    if (selected !== undefined && selected.length) {
 | 
			
		||||
                        selected.forEach(item => {
 | 
			
		||||
                            if (typeof item != 'string') {
 | 
			
		||||
                                is_string = true;
 | 
			
		||||
 | 
			
		||||
                            if (item != '') {
 | 
			
		||||
                                pre_value.push(item.toString());
 | 
			
		||||
                                if (item != '') {
 | 
			
		||||
                                    pre_value.push(item.toString());
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (is_string) {
 | 
			
		||||
                        this.selected = pre_value;
 | 
			
		||||
@@ -949,11 +982,10 @@ export default {
 | 
			
		||||
 | 
			
		||||
        dynamicOptions: function(options) {
 | 
			
		||||
            this.sorted_options = [];
 | 
			
		||||
            this.selected = '';
 | 
			
		||||
 | 
			
		||||
            if (this.group) {
 | 
			
		||||
                // Option set sort_option data
 | 
			
		||||
                if (!Array.isArray(options)) {
 | 
			
		||||
                if (! Array.isArray(options)) {
 | 
			
		||||
                    for (const [index, _options] of Object.entries(options)) {
 | 
			
		||||
                        let values = [];
 | 
			
		||||
 | 
			
		||||
@@ -991,7 +1023,7 @@ export default {
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                // Option set sort_option data
 | 
			
		||||
                if (!Array.isArray(options)) {
 | 
			
		||||
                if (! Array.isArray(options)) {
 | 
			
		||||
                    for (const [key, value] of Object.entries(options)) {
 | 
			
		||||
                        this.sorted_options.push({
 | 
			
		||||
                            key: key.toString(),
 | 
			
		||||
@@ -1018,6 +1050,8 @@ export default {
 | 
			
		||||
                        }
 | 
			
		||||
                    }, this);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.dynamicOptionsValue(options);
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -104,7 +104,7 @@
 | 
			
		||||
 | 
			
		||||
        <span slot="infoBlock" class="absolute right-8 top-3 bg-green text-white px-2 py-1 rounded-md text-xs" v-if="new_options[selected]">{{ addNew.new_text }}</span>
 | 
			
		||||
 | 
			
		||||
        <select :name="name"  :id="name" v-model="selected" class="d-none">
 | 
			
		||||
        <select :name="name"  :id="name" class="hidden">
 | 
			
		||||
            <option v-for="option in sortedOptions" :key="option.key" :value="option.key">{{ option.value }}</option>
 | 
			
		||||
        </select>
 | 
			
		||||
 | 
			
		||||
@@ -1089,6 +1089,33 @@ export default {
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    dynamicOptionsValue(options) {
 | 
			
		||||
        if (! this.forceDynamicOptionValue) {
 | 
			
		||||
            if (this.multiple) {
 | 
			
		||||
                this.selected = [];
 | 
			
		||||
            } else {
 | 
			
		||||
                this.selected = null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.multiple) {
 | 
			
		||||
            let selected = this.selected;
 | 
			
		||||
            this.selected = [];
 | 
			
		||||
 | 
			
		||||
            selected.forEach(function (select, index) {
 | 
			
		||||
                if (this.sorted_options.find((option) => option.key == select)) {
 | 
			
		||||
                    this.selected.push(select);
 | 
			
		||||
                }
 | 
			
		||||
            }, this);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (! options.find((option) => option == this.selected)) {
 | 
			
		||||
                this.selected = null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    watch: {
 | 
			
		||||
        selected: function (selected) {
 | 
			
		||||
            if (!this.multiple) {
 | 
			
		||||
@@ -1237,6 +1264,8 @@ export default {
 | 
			
		||||
                        }
 | 
			
		||||
                    }, this);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.dynamicOptionsValue(options);
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								resources/assets/js/plugins/form.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								resources/assets/js/plugins/form.js
									
									
									
									
										vendored
									
									
								
							@@ -479,6 +479,10 @@ export default class Form {
 | 
			
		||||
            this.loading = true;
 | 
			
		||||
 | 
			
		||||
            window.location.href = response.data.redirect;
 | 
			
		||||
 | 
			
		||||
            if (window.location.hash !== undefined) {
 | 
			
		||||
                location.reload();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.response = response.data;
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ const app = new Vue({
 | 
			
		||||
 | 
			
		||||
                this.component = Vue.component('add-new-component', (resolve, reject) => {
 | 
			
		||||
                    resolve({
 | 
			
		||||
                        template: '<div id="dynamic-email-component"><akaunting-modal-add-new modal-dialog-class="max-w-screen-md" :show="email.modal" @submit="onSubmit" @cancel="onCancel" :buttons="email.buttons" :title="email.title" :is_component=true :message="email.html"></akaunting-modal-add-new></div>',
 | 
			
		||||
                        template: '<div id="dynamic-email-component"><akaunting-modal-add-new modal-dialog-class="max-w-md" :show="email.modal" @submit="onSubmit" @cancel="onCancel" :buttons="email.buttons" :title="email.title" :is_component=true :message="email.html"></akaunting-modal-add-new></div>',
 | 
			
		||||
 | 
			
		||||
                        mixins: [
 | 
			
		||||
                            Global
 | 
			
		||||
 
 | 
			
		||||
@@ -856,7 +856,7 @@ const app = new Vue({
 | 
			
		||||
 | 
			
		||||
                this.component = Vue.component('add-new-component', (resolve, reject) => {
 | 
			
		||||
                    resolve({
 | 
			
		||||
                        template: '<div id="dynamic-email-component"><akaunting-modal-add-new modal-dialog-class="max-w-screen-md" :show="email.modal" @submit="onSubmit" @cancel="onCancel" :buttons="email.buttons" :title="email.title" :is_component=true :message="email.html"></akaunting-modal-add-new></div>',
 | 
			
		||||
                        template: '<div id="dynamic-email-component"><akaunting-modal-add-new modal-dialog-class="max-w-md" :show="email.modal" @submit="onSubmit" @cancel="onCancel" :buttons="email.buttons" :title="email.title" :is_component=true :message="email.html"></akaunting-modal-add-new></div>',
 | 
			
		||||
 | 
			
		||||
                        mixins: [
 | 
			
		||||
                            Global
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,6 @@ const app = new Vue({
 | 
			
		||||
            form: new Form('category'),
 | 
			
		||||
            bulk_action: new BulkAction('categories'),
 | 
			
		||||
            categoriesBasedTypes: null,
 | 
			
		||||
            isParentCategoryDisabled: true,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -42,7 +41,6 @@ const app = new Vue({
 | 
			
		||||
 | 
			
		||||
            if (typeof JSON.parse(this.form.categories)[event] === 'undefined') {
 | 
			
		||||
                this.categoriesBasedTypes = [];
 | 
			
		||||
                this.isParentCategoryDisabled = true;
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
@@ -54,7 +52,6 @@ const app = new Vue({
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.categoriesBasedTypes = JSON.parse(this.form.categories)[event];
 | 
			
		||||
            this.isParentCategoryDisabled = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@ return [
 | 
			
		||||
    'error' => [
 | 
			
		||||
        'self_delete'       => 'Error: Can not delete yourself!',
 | 
			
		||||
        'self_disable'      => 'Error: Can not disable yourself!',
 | 
			
		||||
        'unassigned'        => 'Error: Can not unassigned company! The :company company must be assigned at least one user.',
 | 
			
		||||
        'no_company'        => 'Error: No company assigned to your account. Please, contact the system administrator.',
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
        id="{{ $formId }}"
 | 
			
		||||
        :route="$formRoute"
 | 
			
		||||
        method="{{ $formMethod }}"
 | 
			
		||||
        :model="$contact"
 | 
			
		||||
        :model="$document"
 | 
			
		||||
    >
 | 
			
		||||
        @if (! $hideCompany)
 | 
			
		||||
            <x-documents.form.company :type="$type" />
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
                @endphp
 | 
			
		||||
 | 
			
		||||
                <div class="my-2">
 | 
			
		||||
                    {!! trans('recurring.child', ['url' => $url, 'date' => company_date($child->due_at)]) !!}
 | 
			
		||||
                    {!! trans('recurring.child', ['url' => $url, 'date' => company_date($child->created_at)]) !!}
 | 
			
		||||
                </div>
 | 
			
		||||
            @endforeach
 | 
			
		||||
        @else
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
        @if ($trigger->attributes->has('override') && in_array('class', explode(',', $trigger->attributes->get('override'))))
 | 
			
		||||
        class="{{ $trigger->attributes->get('class') }}"
 | 
			
		||||
        @else
 | 
			
		||||
        class="w-9 h-9 flex items-center justify-center px-2 py-2 bg-gray-100 hover:bg-gray-200 rounded-xl text-purple text-sm font-medium leading-6" 
 | 
			
		||||
        class="w-full lg:w-9 h-9 flex items-center justify-center px-2 py-2 bg-gray-100 hover:bg-gray-200 rounded-xl text-purple text-sm font-medium leading-6" 
 | 
			
		||||
        @endif
 | 
			
		||||
        data-dropdown-toggle="{{ $id }}"
 | 
			
		||||
        {{  $trigger->attributes }}
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,12 @@
 | 
			
		||||
        search-text="{{ $searchText }}"
 | 
			
		||||
        @endif
 | 
			
		||||
 | 
			
		||||
        @if (! empty($attributes['force-dynamic-option-value']))
 | 
			
		||||
        force-dynamic-option-value
 | 
			
		||||
        @elseif (! empty($forceDynamicOptionValue))
 | 
			
		||||
        force-dynamic-option-value
 | 
			
		||||
        @endif
 | 
			
		||||
 | 
			
		||||
        @if (empty($multiple))
 | 
			
		||||
            @if (isset($selected) || old($name))
 | 
			
		||||
            value="{{ old($name, $selected) }}"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,17 @@
 | 
			
		||||
<x-form id="setting" method="PATCH" route="settings.company.update">
 | 
			
		||||
    <div class="grid sm:grid-cols-6 gap-x-8 gap-y-6 my-3.5d">
 | 
			
		||||
        <x-form.group.text name="name" label="{{ trans('settings.company.name') }}" value="{{ setting('company.name') }}" />
 | 
			
		||||
        <x-form.group.text name="name" label="{{ trans('settings.company.name') }}" value="{{ setting('company.name') }}" form-group-class="col-span-6" />
 | 
			
		||||
 | 
			
		||||
        <x-form.group.text name="email" label="{{ trans('settings.company.email') }}" value="{{ setting('company.email') }}" />
 | 
			
		||||
        <x-form.group.text name="email" label="{{ trans('settings.company.email') }}" value="{{ setting('company.email') }}" form-group-class="col-span-6" />
 | 
			
		||||
 | 
			
		||||
        <x-form.group.text name="tax_number" label="{{ trans('general.tax_number') }}" value="{{ setting('company.tax_number') }}" not-required />
 | 
			
		||||
        <x-form.group.text name="tax_number" label="{{ trans('general.tax_number') }}" value="{{ setting('company.tax_number') }}" form-group-class="col-span-6" not-required />
 | 
			
		||||
 | 
			
		||||
        <x-form.group.text name="phone" label="{{ trans('settings.company.phone') }}" value="{{ setting('company.phone') }}" not-required />
 | 
			
		||||
        <x-form.group.text name="phone" label="{{ trans('settings.company.phone') }}" value="{{ setting('company.phone') }}" form-group-class="col-span-6" not-required />
 | 
			
		||||
 | 
			
		||||
        <x-form.group.textarea name="address" label="{{ trans('settings.company.address') }}" :value="setting('company.address')" />
 | 
			
		||||
        <x-form.group.textarea name="address" label="{{ trans('settings.company.address') }}" :value="setting('company.address')" form-group-class="col-span-6" />
 | 
			
		||||
 | 
			
		||||
        <x-form.group.country />
 | 
			
		||||
        <x-form.group.country form-group-class="col-span-6" />
 | 
			
		||||
 | 
			
		||||
        <x-form.input.hidden name="_prefix" value="company" />
 | 
			
		||||
        <x-form.input.hidden name="_prefix" value="company" form-group-class="col-span-6" />
 | 
			
		||||
    </div>
 | 
			
		||||
</x-form>
 | 
			
		||||
 
 | 
			
		||||
@@ -24,10 +24,10 @@
 | 
			
		||||
                            <x-form.group.select name="type" label="{{ trans_choice('general.types', 1) }}" :options="$types" change="updateParentCategories" />
 | 
			
		||||
                        @endif
 | 
			
		||||
 | 
			
		||||
                        <x-form.group.select name="parent_id" label="{{ trans('general.parent') . ' ' . trans_choice('general.categories', 1) }}" :options="$categories[$category->type]" not-required dynamicOptions="categoriesBasedTypes" sort-options="false" v-disabled="isParentCategoryDisabled" />
 | 
			
		||||
                        <x-form.group.select name="parent_id" label="{{ trans('general.parent') . ' ' . trans_choice('general.categories', 1) }}" :options="$categories[$category->type]" not-required dynamicOptions="categoriesBasedTypes" sort-options="false" />
 | 
			
		||||
 | 
			
		||||
                        <x-form.input.hidden name="parent_category_id" value="{{ $category->parent_id }}" />
 | 
			
		||||
                        <x-form.input.hidden name="categories" value="{{ json_encode($categories) }}" />
 | 
			
		||||
                        <x-form.input.hidden name="parent_category_id" :value="$category->parent_id" />
 | 
			
		||||
                    </x-slot>
 | 
			
		||||
                </x-form.section>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ lg:pl-24
 | 
			
		||||
lg:my-12
 | 
			
		||||
lg:mt-4
 | 
			
		||||
lg:pl-6
 | 
			
		||||
lg:w-9
 | 
			
		||||
ltr:-right-1.5
 | 
			
		||||
rtl:-left-1.5
 | 
			
		||||
sm:max-w-4xl
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user