Commit 93ef4562 by Vladislav

#19461 Страница настройки целевых аккаунтов

1 parent c78151bc
......@@ -11,21 +11,20 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Request;
use Inertia\Inertia;
use phpDocumentor\Reflection\Types\Boolean;
use phpDocumentor\Reflection\Types\Integer;
class TokensController extends Controller
{
function index(){
function index()
{
return Inertia::render('Tokens/Index', [
'filters' => Request::all('api', 'type', 'login'),
'types' => [Tokens::MAIN => 'Основной аккаунт', Tokens::GOAL=> 'Целевой аккаунт'],
'types' => [Tokens::MAIN => 'Основной аккаунт', Tokens::GOAL => 'Целевой аккаунт'],
'tokens' => Tokens::filter(Request::only('api', 'type', 'login'))
->paginate()
->withQueryString()
->through(function ($token) {
return [
'id' => $token->id,
'id' => $token->getKey(),
'login' => $token->login,
'type' => $token->type,
'api' => $token->api,
......@@ -34,29 +33,42 @@ class TokensController extends Controller
]);
}
function edit(Tokens $token){
function edit(Tokens $token)
{
$mainToken = Tokens::where('type', Tokens::MAIN)->get()->first();
return Inertia::render('Tokens/Edit', [
'token' => [
'id' => $token->id,
'id' => $token->getKey(),
'login' => $token->login,
'api' => $token->api,
'token' => $token->token,
'type' => $token->type,
'main' => $token->type==Tokens::MAIN,
'main' => $token->isMain(),
'campaigns' => (
$token->type === Tokens::MAIN
$token->isMain()
? $token->campaignsForManaged
: []
),
'cities' => ($token->type==Tokens::GOAL?$token->cities:[]),
'cities' => (
!$token->isMain()
? $token->cities
: []
),
],
'cities' => Dictionary::where('type', Dictionary::CITY)->get(),
'cities' => (
!$token->isMain()
? Dictionary::where('type', Dictionary::CITY)->defaultOrderBy()->get()
: []
),
'campaigns' => $token->campaigns,
'main_token_campaigns' => $mainToken->campaignsForManaged,
'types' => $mainToken && $token->type!=Tokens::MAIN
? [Tokens::GOAL=> 'Целевой аккаунт'] :
[Tokens::MAIN => 'Основной аккаунт', Tokens::GOAL=> 'Целевой аккаунт'],
'main_token_campaigns' => (
$mainToken
? $mainToken->campaignsForManaged
: []
),
'types' => $mainToken && !$token->type === Tokens::GOAL
? [Tokens::GOAL => 'Целевой аккаунт'] :
[Tokens::MAIN => 'Основной аккаунт', Tokens::GOAL => 'Целевой аккаунт'],
]);
}
......@@ -73,6 +85,10 @@ class TokensController extends Controller
public function managedCampaign(Tokens $token, $campaign_id, $managed)
{
if (!$token->isMain()) {
return Redirect::back();
}
$campaign = $token->campaigns()->find($campaign_id);
if (!$campaign) {
......@@ -80,14 +96,18 @@ class TokensController extends Controller
}
$campaign->update([
'manage' => !!$managed,
'manage' => !!request('manage'),
]);
return Redirect::back()->with('success', 'Campaign ' . ($managed ? 'added':'deleted') . '.');
return Redirect::back()->with('success', 'Campaign ' . ($managed ? 'added' : 'deleted') . '.');
}
public function enabledCampaign(Tokens $token, $campaign_id, $enabled)
{
if (!$token->isMain()) {
return Redirect::back();
}
$campaign = $token->campaigns()->find($campaign_id);
if (!$campaign) {
......@@ -95,10 +115,10 @@ class TokensController extends Controller
}
$campaign->update([
'enabled' => !!$enabled,
'enabled' => !!request('enabled'),
]);
return Redirect::back()->with('success', 'Campaign ' . ($enabled ? 'enabled':'disabled') . '.');
return Redirect::back()->with('success', 'Campaign ' . ($enabled ? 'enabled' : 'disabled') . '.');
}
public function destroy(Tokens $token)
......@@ -108,28 +128,70 @@ class TokensController extends Controller
return Redirect::route('tokens')->with('success', 'Token deleted.');
}
function get($api){
return Inertia::location(API::getInstance( APIRequest::getInstance($api) )->getAuthLink());
public function get($api)
{
return Inertia::location(API::getInstance(APIRequest::getInstance($api))->getAuthLink());
}
function token($api){
$token = API::getInstance( APIRequest::getInstance($api) )->getToken(Request::get('code'));
public function token($api)
{
$token = API::getInstance(APIRequest::getInstance($api))->getToken(Request::get('code'));
$tokens = Tokens::firstOrNew(['token'=>$token['token']]);
$tokens = Tokens::firstOrNew(['token' => $token['token']]);
$tokens->token = $token['token'];
$tokens->login = $token['login'];
$tokens->api = $api;
$tokens->created_by = Auth::user()->id;
$tokens->created_by = Auth::user()->getKey();
$tokens->save();
return Redirect::route('tokens')->with('success', 'Token added.');
}
public function addCity(Tokens $token)
public function storeCity(Tokens $token, Dictionary $city)
{
if ($token->isMain()) {
return Redirect::back();
}
$token->cities()->syncWithoutDetaching($city);
return Redirect::route('token.edit', $token->getKey())->with('success', 'City added.');
}
public function updatedCity(Tokens $token, Dictionary $city)
{
$city = Dictionary::findOrFail(Request::input('city'));
$token->cities()->save($city);
if ($token->isMain()) {
return Redirect::back();
}
$token->cities()->updateExistingPivot($city, [
'updated' => !!request('updated'),
]);
return Redirect::route('token.edit', $token->getKey())->with('success', 'City updated.');
}
public function updatedCampaign(Tokens $token, Dictionary $city)
{
if ($token->isMain()) {
return Redirect::back();
}
$updated = !!request('updated');
//
return Redirect::route('token.edit', $token->getKey())->with('success', 'Campaign updated.');
}
public function destroyCity(Tokens $token, Dictionary $city)
{
if ($token->isMain()) {
return Redirect::back();
}
$token->cities()->detach($city);
return Redirect::route('token.edit', $token->id)->with('success', 'City added.');
return Redirect::route('token.edit', $token->getKey())->with('success', 'City deleted.');
}
}
......@@ -2,8 +2,15 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
class Dictionary extends Model
{
CONST CITY = 'city';
CONST CITY = 'City';
public function scopeDefaultOrderBy(Builder $query)
{
return $query->orderBy('name');
}
}
<?php
namespace App\Models\Pivots;
use Illuminate\Database\Eloquent\Relations\Pivot;
class TokenDictionaryPivot extends Pivot
{
protected $casts = [
'token_id' => 'int',
'dictionary_id' => 'int',
'updated' => 'boolean',
];
}
......@@ -2,7 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use App\Models\Pivots\TokenDictionaryPivot;
use Illuminate\Database\Eloquent\Model;
class Tokens extends Model
......@@ -23,6 +23,11 @@ class Tokens extends Model
});
}
public function isMain()
{
return $this->type === $this::MAIN;
}
public function limits()
{
return $this->hasMany(Limits::class, 'token', 'id')->orderBy('updated_at', 'DESC');
......@@ -33,8 +38,13 @@ class Tokens extends Model
return $this->hasMany(Campaigns::class, 'token', 'id')->orderBy('updated_at', 'DESC');
}
public function cities(){
return $this->hasMany(Dictionary::class, 'token', 'id');
public function cities()
{
return $this->belongsToMany(Dictionary::class, 'token_dictionaries', 'token_id', 'dictionary_id')
->using(TokenDictionaryPivot::class)
->withPivot('updated')
->withTimestamps()
->orderBy('token_dictionaries.created_at', 'desc');
}
public function campaignsForManaged()
......
......@@ -19,8 +19,6 @@ class CreateDictionariesTable extends Migration
$table->bigInteger('parent_id')->nullable();
$table->string('name', 255);
$table->string('type', 255);
$table->bigInteger('token')->nullable();
$table->boolean('update')->default(1);
$table->timestamps();
});
}
......
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateTokenDictionaries extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('token_dictionaries', function (Blueprint $table) {
$table->id();
$table->bigInteger('token_id');
$table->bigInteger('dictionary_id');
$table->boolean('updated')->default(1);
$table->timestamps();
$table->foreign('token_id')->references('id')->on('tokens');
$table->foreign('dictionary_id')->references('id')->on('dictionaries');
$table->unique(['token_id', 'dictionary_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('token_dictionaries');
}
}
<template>
<div>
<h2 class="mt-12 font-bold text-2xl">Campaigns</h2>
<div class="mt-4 flex flex-wrap">
<form v-if="campaigns.length" @submit.prevent="add(campaign_id)" class="flex flex-wrap">
<select-input v-model="campaign_id"
:readonly="campaign_id"
class="pr-6"
>
<option v-for="campaign in campaigns" :value="campaign.id">
{{ campaign.name }}
</option>
</select-input>
<loading-button class="btn-indigo hover:underline pl-6"
tabindex="-1"
type="submit"
>
Add
</loading-button>
</form>
</div>
<div class="mt-4 flex flex-wrap">
</div>
<div class="mt-6 bg-white rounded shadow overflow-x-auto">
<table class="w-full whitespace-nowrap">
<tr class="text-left font-bold">
<th class="px-6 pt-6 pb-4">Name</th>
<th class="px-6 pt-6 pb-4">Action</th>
</tr>
<tr v-for="campaign in token.campaigns" :key="campaign.id"
class="hover:bg-gray-100 focus-within:bg-gray-100">
<td class="border-t py-3">
{{ campaign.name }}
</td>
<td class="border-t py-3">
<input :id="'campaign-enabled-' + campaign.id" :checked="campaign.enabled"
@change="enabled(campaign.id, !campaign.enabled)"
type="checkbox"
>
<label :for="'campaign-enabled-' + campaign.id">Enabled</label>
<button class="text-red-600 hover:underline"
tabindex="-1"
type="button"
@click="destroy(campaign.id)"
>
Delete Campaign
</button>
</td>
</tr>
<tr v-if="token.campaigns.length === 0">
<td class="border-t px-6 py-4" colspan="4">No campaigns found.</td>
</tr>
</table>
</div>
</div>
</template>
<script>
import Icon from "../../Shared/Icon";
import SelectInput from "../../Shared/SelectInput";
import LoadingButton from "../../Shared/LoadingButton";
export default {
components: {
Icon,
SelectInput,
LoadingButton,
},
props: {
campaigns: Array,
token: Object,
},
data() {
return {
campaign_id: null,
}
},
watch: {},
mounted() {
},
methods: {
add(campaign_id) {
if (!campaign_id) {
return;
}
this.$emit('add', campaign_id)
},
enabled(campaign_id) {
this.$emit('enabled', campaign_id)
},
delete(campaign_id) {
this.$emit('delete', campaign_id)
},
}
}
</script>
<template>
<div>
<h2 class="mt-12 font-bold text-2xl">Cities</h2>
<div class="mt-4 flex flex-wrap">
<div v-if="all_cities" class="flex flex-wrap">
<select-input v-model="city" class="px-6">
<option v-for="city in all_cities" :value="city.id">
<div v-if="cities.length" class="mt-4 flex flex-wrap">
<select-input v-model="city" class="pr-6">
<option v-for="city in cities" :value="city.id">
{{ city.name }}
</option>
</select-input>
......@@ -19,8 +19,6 @@
</div>
</div>
<div class="mt-6 bg-white rounded shadow">
<table class="w-full whitespace-nowrap">
<tr class="text-left font-bold">
......@@ -28,42 +26,49 @@
<th class="px-6 pt-6 pb-4">Обновлять?</th>
<th class="px-6 pt-6 pb-4"></th>
</tr>
<template v-for="city in cities" >
<template v-for="city in token_cities" >
<tr :key="city.id" class="hover:bg-gray-100 focus-within:bg-gray-100">
<td colspan="2" class="border-t">
<span class="px-6 py-4 flex items-center focus:text-indigo-500"> {{ city.name }} </span>
</td>
<td class="border-t">
<input :checked="city.update"
@change=""
<input :checked="city.pivot.updated"
@change="cityUpdated(city.id, !city.pivot.updated)"
type="checkbox"
>
</td>
<td>
<inertia-link class="px-4 flex items-center" :href="route('token.city.delete', city.id)" tabindex="-1">
<button class="px-4 flex items-center"
tabindex="-1"
@click="cityDelete(city.id)"
>
<icon name="trash" class="block w-6 h-6 fill-gray-400" />
</inertia-link>
</button>
</td>
</tr>
<tr>
<th class="px-6 pt-6 pb-4" ></th>
<th class="px-6 pt-6 pb-4"></th>
<th class="px-6 pt-6 pb-4">Кампания</th>
<th class="px-6 pt-6 pb-4">Синхронизировать?</th>
<th></th>
</tr>
<tr v-for="camp in main_token_campaigns">
<tr v-for="campaign in main_token_campaigns">
<td class="border-t"></td>
<td class="border-t"><span class="px-6 py-4 flex items-center focus:text-indigo-500"> {{ camp.name }} </span></td>
<td class="border-t">
<input :checked="camp.update"
@change=""
<span class="px-6 py-4 flex items-center focus:text-indigo-500">
{{ campaign.name }}
</span>
</td>
<td class="border-t">
<input :checked="false"
@change="campaignUpdated(campaign.id, false)"
type="checkbox"
>
</td>
<td></td>
</tr>
</template>
<tr v-if="cities.length === 0">
<tr v-if="token_cities.length === 0">
<td class="border-t px-6 py-4" colspan="4">No City found.</td>
</tr>
</table>
......@@ -79,7 +84,7 @@ export default {
components: {Icon, SelectInput},
props: {
cities: Array,
all_cities: Array,
token_cities: Array,
main_token_campaigns: Array,
},
data() {
......@@ -94,9 +99,19 @@ export default {
},
methods: {
cityAdd(){
cityAdd() {
this.$emit('add', this.city)
}
},
cityDelete(id) {
this.$emit('delete', id)
},
cityUpdated(id, updated) {
console.log(this.token_cities);
this.$emit('updated', id, updated)
},
campaignUpdated(id, updated) {
this.$emit('campaignUpdated', id, updated)
},
}
}
</script>
......@@ -36,68 +36,23 @@
</div>
</form>
</div>
<div v-if="campaigns.length && token.main">
<h2 class="mt-12 font-bold text-2xl">Campaigns</h2>
<div class="mt-4 flex flex-wrap">
<form v-if="campaigns.length" @submit.prevent="campaignAdd" class="flex flex-wrap">
<loading-button :loading="campaign_add_form.processing"
class="btn-indigo hover:underline"
tabindex="-1"
type="submit"
>
Add
</loading-button>
<select-input v-model="campaign_add_form.campaign_id"
:error="campaign_add_form.errors.campaign_id"
:readonly="campaign_add_form.campaign_id"
class="px-6"
>
<option v-for="campaign in campaigns" :value="campaign.id">
{{ campaign.name }}
</option>
</select-input>
</form>
</div>
<div class="mt-4 flex flex-wrap">
</div>
<div class="mt-6 bg-white rounded shadow overflow-x-auto">
<table class="w-full whitespace-nowrap">
<tr class="text-left font-bold">
<th class="px-6 pt-6 pb-4">Name</th>
<th class="px-6 pt-6 pb-4">Action</th>
</tr>
<tr v-for="campaign in token.campaigns" :key="campaign.id"
class="hover:bg-gray-100 focus-within:bg-gray-100">
<td class="border-t py-3">
{{ campaign.name }}
</td>
<td class="border-t py-3">
<input :id="'campaign-enabled-' + campaign.id" :checked="campaign.enabled"
@change="campaignEnabled(campaign.id, !campaign.enabled)"
type="checkbox"
>
<label :for="'campaign-enabled-' + campaign.id">Enabled</label>
<button class="text-red-600 hover:underline"
tabindex="-1"
type="button"
@click="campaignDestroy(campaign.id)"
>
Delete Campaign
</button>
</td>
</tr>
<tr v-if="token.campaigns.length === 0">
<td class="border-t px-6 py-4" colspan="4">No campaigns found.</td>
</tr>
</table>
</div>
</div>
<city-settings v-if="!token.main"
:cities="state.cities"
:all_cities="cities"
<campaigns-settings v-if="campaigns.length && token.main"
:campaigns="campaigns"
:token="token"
v-on:add="campaignAdd"
v-on:enabled="campaignEnabled"
v-on:delete="campaignDelete"
></campaigns-settings>
<city-settings v-if="token.type !== 'main'"
:cities="cities"
:token_cities="token.cities"
:main_token_campaigns="main_token_campaigns"
v-on:add="addCity"
v-on:add="cityAdd"
v-on:updated="cityUpdated"
v-on:delete="cityDelete"
v-on:campaignUpdated="campaignUpdated"
></city-settings>
</div>
</template>
......@@ -110,12 +65,14 @@ import SelectInput from '@/Shared/SelectInput'
import LoadingButton from '@/Shared/LoadingButton'
import TrashedMessage from '@/Shared/TrashedMessage'
import CitySettings from "./CitySettings";
import CampaignsSettings from "./CampaignsSettings";
export default {
metaInfo() {
return {title: this.form.login}
},
components: {
CampaignsSettings,
CitySettings,
Icon,
LoadingButton,
......@@ -141,29 +98,24 @@ export default {
api: this.token.api,
type: this.token.type,
}),
campaign_add_form: this.$inertia.form({
campaign_id: null,
}),
campaigns_form: this.$inertia.form(),
state: {
all_cities: this.cities,
cities: this.token.cities,
},
}
},
methods: {
addCity(id) {
let found;
this.state.all_cities = this.state.all_cities.filter((city)=>{
if (city.id==id){
found = city
}
return city.id!=id
cityAdd(id) {
this.$inertia.post(this.route('token.city.store', [this.token.id, id]))
},
cityUpdated(id, updated) {
this.$inertia.post(this.route('token.city.updated', [this.token.id, id]), {
updated: updated ? 1 : 0,
})
},
campaignUpdated(id, updated) {
this.$inertia.post(this.route('token.city.campaign.updated', [this.token.id, id]), {
updated: updated ? 1 : 0,
})
this.state.cities.push(found)
this.$inertia.form({
city: id
}).post(this.route('token.city.add', this.token.id))
},
cityDelete(id) {
this.$inertia.delete(this.route('token.city.destroy', [this.token.id, id]))
},
tokenUpdate() {
this.form.post(this.route('token.update', this.token.id))
......@@ -174,34 +126,22 @@ export default {
}
},
campaignEnabled(campaign_id, enabled) {
this.$inertia.post(this.route('token.campaign.enabled', [
this.token.id,
campaign_id,
enabled ? 1 : 0,
]));
this.$inertia.post(this.route('token.campaign.enabled', [this.token.id, campaign_id]), {
updated: enabled ? 1 : 0,
});
},
campaignDestroy(campaign_id) {
campaignManaged(campaign_id, managed) {
this.$inertia.post(this.route('token.campaign.managed', [this.token.id, campaign_id]), {
updated: managed ? 1 : 0,
});
},
campaignDelete(campaign_id) {
if (confirm('Are you sure you want to delete this campaign?')) {
this.$inertia.post(this.route('token.campaign.managed', [
this.token.id,
campaign_id,
0,
]));
this.campaignManaged(campaign_id, 0);
}
},
campaignAdd() {
let campaign_id = this.campaign_add_form.campaign_id;
if (!campaign_id) {
return;
}
this.campaign_add_form.post(this.route('token.campaign.managed', [
this.token.id,
campaign_id,
1,
]));
campaignAdd(campaign_id) {
this.campaignManaged(campaign_id, 1);
},
filterCampaigns(token_campaigns) {
return this.campaigns.filter(
......
......@@ -169,18 +169,26 @@ Route::get('token/edit/{token}', [TokensController::class, 'edit'])
Route::post('token/edit/{token}', [TokensController::class, 'update'])
->name('token.update')
->middleware('auth');
Route::delete('token/delete/{token}', [TokensController::class, 'destroy'])
->name('token.destroy')
->middleware('auth');
Route::post('token/campaigns/managed/{token}/{campaign_id}/{managed}', [TokensController::class, 'managedCampaign'])
->name('token.campaign.managed')
->middleware('auth');
Route::post('token/campaigns/enabled/{token}/{campaign_id}/{enabled}', [TokensController::class, 'enabledCampaign'])
Route::post('token/campaigns/enabled/{token}/{campaign_id}', [TokensController::class, 'enabledCampaign'])
->name('token.campaign.enabled')
->middleware('auth');
Route::post('token/city/add/{token}', [TokensController::class, 'addCity'])
->name('token.city.add')
Route::post('token/city/store/{token}/{city}', [TokensController::class, 'storeCity'])
->name('token.city.store')
->middleware('auth');
Route::post('token/city/delete/{city}', [TokensController::class, 'removeCity'])
->name('token.city.delete')
Route::post('token/city/updated/{token}/{city}', [TokensController::class, 'updatedCity'])
->name('token.city.updated')
->middleware('auth');
Route::delete('token/delete/{token}', [TokensController::class, 'destroy'])
->name('token.destroy')
Route::post('token/city/campaign/updated/{token}/{city}', [TokensController::class, 'updatedCampaign'])
->name('token.city.campaign.updated')
->middleware('auth');
Route::delete('token/city/{token}/{city}', [TokensController::class, 'destroyCity'])
->name('token.city.destroy')
->middleware('auth');
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!