Merge pull request #961 from openclassify/dia

#3290 [advs] Admin list make city select2
This commit is contained in:
spektra2147 2021-02-24 12:47:42 +03:00 committed by GitHub
commit 3463ba8f68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 278 additions and 287 deletions

View File

@ -146,11 +146,32 @@ $(document).ready(function () {
});
// Country filter
$("select[name=filter_country]").select2({
const locationFilter = $("select[name=filter_country]")
locationFilter.select2({
placeholder: $('select[name=filter_country] option:first-child').text()
});
locationFilter.change(function () {
if ($(this).val()) {
getCities($(this).val())
}
}).trigger('change');
// City filter
$("select[name=filter_City]").select2({
placeholder: $('select[name=filter_City] option:first-child').text()
});
});
function getCities(country) {
return crudAjax(`id=${country}`, '/ajax/getCities', 'POST', () => {}, true)
.then(function (cities) {
$('select[name="filter_City"]').html("<option value=''>" + $('select[name=filter_City] option:first-child').text() + "</option>");
$.each(cities, function (index, value) {
$('select[name="filter_City"]').append("<option value='" + value.id + "'>" + value.name + "</option>");
});
})
}
$("#listFilterForm").submit(function(e) {
// Disable unselected inputs
const inputs = $('#listFilterForm :input');

View File

@ -44,4 +44,5 @@ return [
'publish' => 'Publish',
'import' => 'Import',
'new_status' => 'New Status',
'fast_edit' => 'Fast Edit',
];

View File

@ -279,6 +279,17 @@ return [
'yes' => [
'name' => 'Yes'
],
'no' => [
'name' => 'No'
],
'is_system' => [
'name' => 'Is System',
'instructions' => 'System status are required and should not be changed',
],
'user_access' => [
'name' => 'User Access',
'instructions' => 'Can a user use this status on his ads?',
],
"no_location" => "No location is selected.",
"continue" => 'Continue',
"gallery" => 'Gallery',

View File

@ -30,4 +30,5 @@ return [
'approve_status_change' => "Your Ad's Status Has Been Set to Active!",
'passive_status_change' => "Your Ad's Status Has Been Set to Passive!",
'sold_status_change' => "Your Ad's Status Has Been Set to Sold!",
'status_change' => "Your Ad's Status Has Been Set to :status!",
];

View File

@ -411,4 +411,9 @@ class AdvModel extends AdvsAdvsEntryModel implements AdvInterface
'publish_at' => date('Y-m-d H:i:s')
]);
}
public function changeStatus($status)
{
$this->update(['status' => $status]);
}
}

View File

@ -1,5 +1,6 @@
<?php namespace Visiosoft\AdvsModule\Adv;
use Visiosoft\AdvsModule\Adv\Command\AddSlug;
use Visiosoft\AdvsModule\Adv\Command\DeleteOptionConfiguration;
use Anomaly\Streams\Platform\Entry\Contract\EntryInterface;
use Anomaly\Streams\Platform\Entry\EntryObserver;
@ -8,6 +9,13 @@ use Visiosoft\AdvsModule\Adv\Event\DeletingAd;
class AdvObserver extends EntryObserver
{
public function updating(EntryInterface $entry)
{
$this->dispatch(new AddSlug($entry));
parent::updating($entry);
}
public function deleting(EntryInterface $entry)
{
$this->dispatch(new DeleteOptionConfiguration($entry));

View File

@ -0,0 +1,23 @@
<?php namespace Visiosoft\AdvsModule\Adv\Command;
use Illuminate\Support\Str;
use Visiosoft\AdvsModule\Adv\Contract\AdvInterface;
class AddSlug
{
protected $ad;
public function __construct(AdvInterface $ad)
{
$this->ad = $ad;
}
public function handle()
{
if (!$this->ad->slug && $this->ad->name) {
$this->ad->update([
'slug' => Str::slug($this->ad->name)
]);
}
}
}

View File

@ -87,4 +87,6 @@ interface AdvInterface extends EntryInterface
public function getStatus();
public function approve();
public function changeStatus($status);
}

View File

@ -63,7 +63,9 @@ class AdvFormBuilder extends FormBuilder
protected $rules = [];
protected $skips = [];
protected $skips = [
'slug'
];
protected $actions = [];

View File

@ -1,11 +1,14 @@
<?php namespace Visiosoft\AdvsModule\Adv\Form;
use Visiosoft\AdvsModule\Adv\Event\ReadySimpleAdvFormFields;
use Visiosoft\AdvsModule\Status\Contract\StatusRepositoryInterface;
class SimpleAdvFormFields
{
public function handle(SimpleAdvFormBuilder $builder)
public function handle(SimpleAdvFormBuilder $builder, StatusRepositoryInterface $statusRepository)
{
$statuses = $statusRepository->all()->pluck('name', 'slug')->all();
$form_fields = [
'name',
'price',
@ -23,6 +26,13 @@ class SimpleAdvFormFields
'cat10',
'is_get_adv',
'stock',
'status' => [
'type' => 'anomaly.field_type.select',
"config" => [
"options" => $statuses,
"mode" => "search",
]
],
'files',
];

View File

@ -18,7 +18,7 @@ class SimpleAdvFormHandler
$builder->saveForm();
$ad = $advRepository->find($builder->getFormEntryId());
if ($ad->status !== 'approved') {
if (!$builder->getFormValue('status') && $ad->status !== 'approved') {
$ad->approve();
}

View File

@ -25,11 +25,19 @@ class AdvTableButtons
return ($entry->getStatus() == 'approved') ? "danger" : "success";
},
],
'edit',
'settings' => [
'text' => false,
'href' => false,
'dropdown' => [
'edit' => [
'icon' => null,
'href' => function (EntryInterface $entry) {
return route('visiosoft.module.advs::edit_adv', [$entry->id]);
},
],
'fast_edit' => [
'href' => '/admin/advs/edit/{entry.id}'
],
'change_owner' => [
'data-toggle' => 'modal',
'data-target' => '#modal',

View File

@ -1,10 +1,12 @@
<?php namespace Visiosoft\AdvsModule;
use Anomaly\Streams\Platform\Database\Seeder\Seeder;
use Visiosoft\AdvsModule\Status\StatusSeeder;
class AdvsModuleSeeder extends Seeder
{
public function run()
{
$this->call(StatusSeeder::class);
}
}

View File

@ -3,6 +3,7 @@
use Anomaly\FilesModule\File\FileModel;
use Anomaly\Streams\Platform\Addon\AddonCollection;
use Anomaly\Streams\Platform\Addon\AddonServiceProvider;
use Anomaly\Streams\Platform\Model\Advs\AdvsStatusEntryModel;
use Anomaly\Streams\Platform\Model\Location\LocationVillageEntryModel;
use Anomaly\Streams\Platform\Ui\Table\Event\TableIsQuerying;
use Visiosoft\AdvsModule\Adv\Contract\AdvRepositoryInterface;
@ -21,6 +22,9 @@ use Visiosoft\AdvsModule\Productoption\Contract\ProductoptionRepositoryInterface
use Visiosoft\AdvsModule\Productoption\ProductoptionRepository;
use Visiosoft\AdvsModule\ProductoptionsValue\Contract\ProductoptionsValueRepositoryInterface;
use Visiosoft\AdvsModule\ProductoptionsValue\ProductoptionsValueRepository;
use Visiosoft\AdvsModule\Status\Contract\StatusRepositoryInterface;
use Visiosoft\AdvsModule\Status\StatusModel;
use Visiosoft\AdvsModule\Status\StatusRepository;
use Visiosoft\LocationModule\Village\Contract\VillageRepositoryInterface;
use Visiosoft\LocationModule\Village\VillageRepository;
use Visiosoft\LocationModule\Village\VillageModel;
@ -229,6 +233,12 @@ class AdvsModuleServiceProvider extends AddonServiceProvider
'admin/advs/product_options' => 'Visiosoft\AdvsModule\Http\Controller\Admin\ProductoptionsController@index',
'admin/advs/product_options/create' => 'Visiosoft\AdvsModule\Http\Controller\Admin\ProductoptionsController@create',
'admin/advs/product_options/edit/{id}' => 'Visiosoft\AdvsModule\Http\Controller\Admin\ProductoptionsController@edit',
// StatusController
'ad/{ad_id}/change-status/{status_id}' => [
'as' => 'visiosoft.module.advs::ad.change.status',
'uses' => 'Visiosoft\AdvsModule\Http\Controller\StatusController@change'
],
];
protected $middleware = [
@ -245,6 +255,7 @@ class AdvsModuleServiceProvider extends AddonServiceProvider
protected $bindings = [
LocationVillageEntryModel::class => VillageModel::class,
AdvsAdvsEntryModel::class => AdvModel::class,
AdvsStatusEntryModel::class => StatusModel::class,
'my_form' => AdvFormBuilder::class,
];
@ -257,6 +268,7 @@ class AdvsModuleServiceProvider extends AddonServiceProvider
ProductoptionRepositoryInterface::class => ProductoptionRepository::class,
OptionConfigurationRepositoryInterface::class => OptionConfigurationRepository::class,
ProductoptionsValueRepositoryInterface::class => ProductoptionsValueRepository::class,
StatusRepositoryInterface::class => StatusRepository::class,
];
public function boot(AddonCollection $addonCollection, FileModel $fileModel)

View File

@ -1,43 +1,32 @@
<?php namespace Visiosoft\AdvsModule\Http\Controller\Admin;
use Visiosoft\AdvsModule\Status\Contract\StatusRepositoryInterface;
use Visiosoft\AdvsModule\Status\Form\StatusFormBuilder;
use Visiosoft\AdvsModule\Status\Table\StatusTableBuilder;
use Anomaly\Streams\Platform\Http\Controller\AdminController;
class StatusController extends AdminController
{
/**
* Display an index of existing entries.
*
* @param StatusTableBuilder $table
* @return \Symfony\Component\HttpFoundation\Response
*/
public function index(StatusTableBuilder $table)
{
return $table->render();
}
/**
* Create a new entry.
*
* @param StatusFormBuilder $form
* @return \Symfony\Component\HttpFoundation\Response
*/
public function create(StatusFormBuilder $form)
{
return $form->render();
}
/**
* Edit an existing entry.
*
* @param StatusFormBuilder $form
* @param $id
* @return \Symfony\Component\HttpFoundation\Response
*/
public function edit(StatusFormBuilder $form, $id)
public function edit(StatusFormBuilder $form, StatusRepositoryInterface $statusRepository, $id)
{
$status = $statusRepository->find($id);
if ($status->is_system) {
$form->skipField('user_access');
}
$form->skipField('slug');
return $form->render($id);
}
}

View File

@ -0,0 +1,37 @@
<?php namespace Visiosoft\AdvsModule\Http\Controller;
use Anomaly\Streams\Platform\Http\Controller\PublicController;
use Visiosoft\AdvsModule\Adv\Contract\AdvRepositoryInterface;
use Visiosoft\AdvsModule\Status\Contract\StatusRepositoryInterface;
class StatusController extends PublicController
{
private $advRepository;
private $statusRepository;
public function __construct(AdvRepositoryInterface $advRepository, StatusRepositoryInterface $statusRepository)
{
parent::__construct();
$this->advRepository = $advRepository;
$this->statusRepository = $statusRepository;
}
public function change($adID, $statusID)
{
$ad = $this->advRepository->find($adID);
$status = $this->statusRepository->find($statusID);
if (!$ad || !$status) {
abort(404);
}
$ad->changeStatus($status->slug);
$this->messages->success(trans(
'visiosoft.module.advs::message.status_change',
['status' => $status->name]
));
return redirect()->back();
}
}

View File

@ -1,6 +1,5 @@
<?php namespace Visiosoft\AdvsModule\Http\Controller;
use Anomaly\FilesModule\File\Contract\FileRepositoryInterface;
use Anomaly\SettingsModule\Setting\Contract\SettingRepositoryInterface;
use Anomaly\Streams\Platform\Http\Controller\PublicController;
use Anomaly\Streams\Platform\Message\MessageBag;
@ -11,7 +10,6 @@ use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Str;
use Visiosoft\AdvsModule\Adv\AdvModel;
use Visiosoft\AdvsModule\Adv\Contract\AdvRepositoryInterface;
use Visiosoft\AdvsModule\Adv\Event\ChangedStatusAd;

View File

@ -4,5 +4,5 @@ use Anomaly\Streams\Platform\Entry\Contract\EntryRepositoryInterface;
interface StatusRepositoryInterface extends EntryRepositoryInterface
{
public function getUserAccessibleStatuses();
}

View File

@ -4,63 +4,11 @@ use Anomaly\Streams\Platform\Ui\Form\FormBuilder;
class StatusFormBuilder extends FormBuilder
{
protected $skips = [
'is_system',
];
/**
* The form fields.
*
* @var array|string
*/
protected $fields = [];
/**
* Additional validation rules.
*
* @var array|string
*/
protected $rules = [];
/**
* Fields to skip.
*
* @var array|string
*/
protected $skips = [];
/**
* The form actions.
*
* @var array|string
*/
protected $actions = [];
/**
* The form buttons.
*
* @var array|string
*/
protected $buttons = [
'cancel',
];
/**
* The form options.
*
* @var array
*/
protected $options = [];
/**
* The form sections.
*
* @var array
*/
protected $sections = [];
/**
* The form assets.
*
* @var array
*/
protected $assets = [];
}

View File

@ -5,21 +5,15 @@ use Anomaly\Streams\Platform\Entry\EntryRepository;
class StatusRepository extends EntryRepository implements StatusRepositoryInterface
{
/**
* The entry model.
*
* @var StatusModel
*/
protected $model;
/**
* Create a new StatusRepository instance.
*
* @param StatusModel $model
*/
public function __construct(StatusModel $model)
{
$this->model = $model;
}
public function getUserAccessibleStatuses()
{
return $this->newQuery()->where(['is_system' => 0, 'user_access' => 1])->get();
}
}

View File

@ -1,15 +1,41 @@
<?php namespace Visiosoft\AdvsModule\Status;
use Anomaly\Streams\Platform\Database\Seeder\Seeder;
use Visiosoft\AdvsModule\Status\Contract\StatusRepositoryInterface;
class StatusSeeder extends Seeder
{
/**
* Run the seeder.
*/
public function run()
public function run(StatusRepositoryInterface $statusRepository)
{
//
// System statuses
$systemStatuses = [
[
'name' => 'Approved',
'slug' => 'approved',
],
[
'name' => 'Declined',
'slug' => 'declined',
],
[
'name' => 'Passive',
'slug' => 'passive',
],
[
'name' => 'Pending User',
'slug' => 'pending_user',
],
];
foreach ($systemStatuses as $status) {
if (!$statusRepository->findBy('slug', $status['slug'])) {
$statusRepository->create([
'name' => $status['name'],
'slug' => $status['slug'],
'is_system' => true,
'user_access' => false,
]);
}
}
}
}

View File

@ -4,60 +4,11 @@ use Anomaly\Streams\Platform\Ui\Table\TableBuilder;
class StatusTableBuilder extends TableBuilder
{
/**
* The table views.
*
* @var array|string
*/
protected $views = [];
/**
* The table filters.
*
* @var array|string
*/
protected $filters = [];
/**
* The table columns.
*
* @var array|string
*/
protected $columns = [
'name',
];
/**
* The table buttons.
*
* @var array|string
*/
protected $buttons = [
'edit'
];
/**
* The table actions.
*
* @var array|string
*/
protected $actions = [
'delete'
];
/**
* The table options.
*
* @var array
*/
protected $options = [];
/**
* The table assets.
*
* @var array
*/
protected $assets = [];
}

View File

@ -0,0 +1,28 @@
<?php namespace Visiosoft\AdvsModule\Status\Table;
use Anomaly\Streams\Platform\Entry\Contract\EntryInterface;
class StatusTableColumns
{
public function handle(StatusTableBuilder $builder)
{
$yes = trans('visiosoft.module.advs::field.yes.name');
$no = trans('visiosoft.module.advs::field.no.name');
$columns = [
'name',
'is_system' => [
'value' => function (EntryInterface $entry) use ($yes, $no) {
return $entry->is_system ? $yes : $no;
}
],
'user_access' => [
'value' => function (EntryInterface $entry) use ($yes, $no) {
return $entry->user_access ? $yes : $no;
}
],
];
$builder->setColumns($columns);
}
}

View File

@ -164,6 +164,29 @@ function dropdownRow(id, type) {
extend_ad +
"</a>\n";
if (Object.keys(userStatus).length) {
let statusItems = ''
for (const status in userStatus) {
statusItems += `
<li>
<a class="dropdown-item"
href="${statusChangeLink.replace(':adID', id).replace(':statusID', status)}">
${userStatus[status]}
</a>
</li>
`
}
dropdown += `
<li class="dropdown-submenu dropleft">
<button type="button" class="btn dropdown-item dropdown-toggle">${changeStatusTrans}</button>
<ul class="dropdown-menu">
${statusItems}
</ul>
</li>
`;
}
dropdown += "</div></div>";
return dropdown;
@ -173,6 +196,21 @@ function addDropdownBlock() {
const dropdowns = $('.my-ads-dropdown')
for (let i = 0; i < dropdowns.length; i++) {
const currentDropdown = $(dropdowns[i])
$('.dropdown-menu', currentDropdown).append(dropdownBlock.replace(':id', currentDropdown.data('id')))
$('> .dropdown-menu', currentDropdown).append(dropdownBlock.replace(':id', currentDropdown.data('id')))
}
}
// Nested dropdown
$('.tab-pane').on('click', '.dropdown-menu button.dropdown-toggle', function(e) {
if (!$(this).next().hasClass('show')) {
$(this).parents('.dropdown-menu').first().find('.show').removeClass('show');
}
var $subMenu = $(this).next('.dropdown-menu');
$subMenu.toggleClass('show');
$(this).parents('.my-ads-dropdown.show').on('hidden.bs.dropdown', function(e) {
$('.dropdown-submenu .show').removeClass('show');
});
return false;
});

View File

@ -468,6 +468,7 @@ return [
'update' => 'Update',
'change_password' => 'Change Password',
'choose_an_option' => 'Choose an option...',
'change_status' => 'Change Status',
// Register page
'accept_terms_label' => 'I accept the terms.',

View File

@ -74,7 +74,10 @@
var edit_ad = "{{ trans('visiosoft.module.profile::button.edit') }}";
var ads_per_page = "{{ setting_value('streams::per_page') }}";
var no_ads_message = "{{ trans('visiosoft.module.advs::field.no_ads') }}";
let userStatus = JSON.parse(`{{ userStatus|raw }}`)
let statusChangeLink = `{{ changeStatusUrl }}`
let dropdownBlock = `{{ addBlock('profile/dropdown-ad', {'id': ':id'})|raw }}`
var changeStatusTrans = "{{ trans('visiosoft.module.profile::field.change_status') }}";
</script>
{{ asset_add('scripts.js','visiosoft.module.profile::assets/js/ads.js') }}
{% endblock %}

View File

@ -9,6 +9,7 @@ use Illuminate\Support\Facades\Auth;
use Rinvex\Subscriptions\Models\Plan;
use Visiosoft\AdvsModule\Adv\AdvModel;
use Visiosoft\AdvsModule\Adv\Event\ChangeStatusAd;
use Visiosoft\AdvsModule\Status\Contract\StatusRepositoryInterface;
use Visiosoft\LocationModule\Country\CountryModel;
use Visiosoft\AlgoliaModule\Search\SearchModel;
use Visiosoft\CloudsiteModule\CloudsiteModule;
@ -222,9 +223,14 @@ class MyProfileController extends PublicController
}
public function myAds()
public function myAds(StatusRepositoryInterface $statusRepository)
{
return $this->view->make('visiosoft.module.profile::profile/ads');
$userStatus = $statusRepository->getUserAccessibleStatuses()->pluck('name', 'id')->toJson();
$changeStatusUrl = route('visiosoft.module.advs::ad.change.status', [':adID', ':statusID']);
return $this->view->make(
'visiosoft.module.profile::profile/ads',
compact('userStatus', 'changeStatusUrl')
);
}
public function updateAjaxProfile(UserRepositoryInterface $user)

View File

@ -26,42 +26,10 @@ use Visiosoft\ProfileModule\Profile\User\UserFormBuilder;
class ProfileModuleServiceProvider extends AddonServiceProvider
{
/**
* Additional addon plugins.
*
* @type array|null
*/
protected $plugins = [
ProfileModulePlugin::class
];
/**
* The addon Artisan commands.
*
* @type array|null
*/
protected $commands = [];
/**
* The addon's scheduled commands.
*
* @type array|null
*/
protected $schedules = [];
/**
* The addon API routes.
*
* @type array|null
*/
protected $api = [];
/**
* The addon routes.
*
* @type array|null
*/
protected $routes = [
// Admin AdressController
'admin/profile' => 'Visiosoft\ProfileModule\Http\Controller\Admin\AdressController@index',
@ -147,58 +115,10 @@ class ProfileModuleServiceProvider extends AddonServiceProvider
'ajax/get-user-info' => 'Visiosoft\ProfileModule\Http\Controller\CacheController@getUserInfo',
];
/**
* The addon middleware.
*
* @type array|null
*/
protected $middleware = [
//Visiosoft\ProfileModule\Http\Middleware\ExampleMiddleware::class
];
/**
* Addon group middleware.
*
* @var array
*/
protected $groupMiddleware = [
//'web' => [
// Visiosoft\ProfileModule\Http\Middleware\ExampleMiddleware::class,
//],
];
/**
* Addon route middleware.
*
* @type array|null
*/
protected $routeMiddleware = [];
/**
* The addon event listeners.
*
* @type array|null
*/
protected $listeners = [
//Visiosoft\ProfileModule\Event\ExampleEvent::class => [
// Visiosoft\ProfileModule\Listener\ExampleListener::class,
//],
];
/**
* The addon alias bindings.
*
* @type array|null
*/
protected $aliases = [
'Excel' => Excel::class,
];
/**
* The addon class bindings.
*
* @type array|null
*/
protected $bindings = [
'updatePassword' => PasswordFormBuilder::class,
'userProfile' => UserFormBuilder::class,
@ -210,11 +130,6 @@ class ProfileModuleServiceProvider extends AddonServiceProvider
ProfileEducationEntryModel::class => EducationModel::class,
];
/**
* The addon singleton bindings.
*
* @type array|null
*/
protected $singletons = [
AdressRepositoryInterface::class => AdressRepository::class,
EducationRepositoryInterface::class => EducationRepository::class,
@ -223,47 +138,10 @@ class ProfileModuleServiceProvider extends AddonServiceProvider
'forgot_pass' => ForgotPassFormBuilder::class,
];
/**
* Additional service providers.
*
* @type array|null
*/
protected $providers = [
ExcelServiceProvider::class,
];
/**
* The addon view overrides.
*
* @type array|null
*/
protected $overrides = [
//'streams::errors/404' => 'module::errors/404',
//'streams::errors/500' => 'module::errors/500',
];
/**
* The addon mobile-only view overrides.
*
* @type array|null
*/
protected $mobile = [
//'streams::errors/404' => 'module::mobile/errors/404',
//'streams::errors/500' => 'module::mobile/errors/500',
];
/**
* Register the addon.
*/
public function register()
{
// Run extra pre-boot registration logic here.
// Use method injection or commands to bring in services.
}
/**
* Boot the addon.
*/
public function boot(AddonCollection $addonCollection)
{
$slug = 'export';
@ -273,16 +151,4 @@ class ProfileModuleServiceProvider extends AddonServiceProvider
];
$addonCollection->get('anomaly.module.users')->addSection($slug, $section);
}
/**
* Map additional addon routes.
*
* @param Router $router
*/
public function map(Router $router)
{
// Register dynamic routes here for example.
// Use method injection or commands to bring in services.
}
}