Add credentials form
This commit is contained in:
parent
085fa85fcd
commit
774ef59e28
9 changed files with 365 additions and 34 deletions
85
app/Http/Controllers/PlatformAccountsController.php
Normal file
85
app/Http/Controllers/PlatformAccountsController.php
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\PlatformAccount;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
|
||||||
|
class PlatformAccountsController extends Controller
|
||||||
|
{
|
||||||
|
public function index(): View
|
||||||
|
{
|
||||||
|
$accounts = PlatformAccount::orderBy('platform')->orderBy('created_at', 'desc')->get();
|
||||||
|
|
||||||
|
return view('pages.platforms.index', compact('accounts'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(): View
|
||||||
|
{
|
||||||
|
return view('pages.platforms.create');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'platform' => 'required|in:lemmy,mastodon,reddit',
|
||||||
|
'instance_url' => 'required|url',
|
||||||
|
'username' => 'required|string|max:255',
|
||||||
|
'password' => 'required|string',
|
||||||
|
'settings' => 'nullable|array',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$account = PlatformAccount::create($validated);
|
||||||
|
|
||||||
|
// If this is the first account for this platform, make it active
|
||||||
|
if (! PlatformAccount::where('platform', $validated['platform'])->where('is_active', true)->exists()) {
|
||||||
|
$account->setAsActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('platforms.index')
|
||||||
|
->with('success', 'Platform account created successfully!');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(PlatformAccount $platformAccount): View
|
||||||
|
{
|
||||||
|
return view('pages.platforms.edit', compact('platformAccount'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, PlatformAccount $platformAccount): RedirectResponse
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'instance_url' => 'required|url',
|
||||||
|
'username' => 'required|string|max:255',
|
||||||
|
'password' => 'nullable|string',
|
||||||
|
'settings' => 'nullable|array',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Don't update password if not provided
|
||||||
|
if (empty($validated['password'])) {
|
||||||
|
unset($validated['password']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$platformAccount->update($validated);
|
||||||
|
|
||||||
|
return redirect()->route('platforms.index')
|
||||||
|
->with('success', 'Platform account updated successfully!');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(PlatformAccount $platformAccount): RedirectResponse
|
||||||
|
{
|
||||||
|
$platformAccount->delete();
|
||||||
|
|
||||||
|
return redirect()->route('platforms.index')
|
||||||
|
->with('success', 'Platform account deleted successfully!');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setActive(PlatformAccount $platformAccount): RedirectResponse
|
||||||
|
{
|
||||||
|
$platformAccount->setAsActive();
|
||||||
|
|
||||||
|
return redirect()->route('platforms.index')
|
||||||
|
->with('success', "Set $platformAccount->username@$platformAccount->instance_url as active for $platformAccount->platform!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
use App\Services\Article\ArticleFetcher;
|
use App\Services\Article\ArticleFetcher;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Queue\Queueable;
|
use Illuminate\Foundation\Queue\Queueable;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
class PublishToLemmyJob implements ShouldQueue
|
class PublishToLemmyJob implements ShouldQueue
|
||||||
{
|
{
|
||||||
|
|
@ -37,7 +38,7 @@ public function handle(): void
|
||||||
]);
|
]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
LemmyPublisher::fromConfig()->publish($this->article, $extractedData);
|
LemmyPublisher::fromActiveAccount()->publish($this->article, $extractedData);
|
||||||
|
|
||||||
logger()->info('Article published successfully', [
|
logger()->info('Article published successfully', [
|
||||||
'article_id' => $this->article->id
|
'article_id' => $this->article->id
|
||||||
|
|
@ -45,6 +46,12 @@ public function handle(): void
|
||||||
|
|
||||||
} catch (PublishException $e) {
|
} catch (PublishException $e) {
|
||||||
$this->fail($e);
|
$this->fail($e);
|
||||||
|
} catch (RuntimeException $e) {
|
||||||
|
logger()->warning('No active Lemmy accounts configured', [
|
||||||
|
'article_id' => $this->article->id,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
$this->fail($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
86
app/Models/PlatformAccount.php
Normal file
86
app/Models/PlatformAccount.php
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Crypt;
|
||||||
|
use App\Enums\PlatformEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property PlatformEnum $platform
|
||||||
|
* @property string $instance_url
|
||||||
|
* @property string $username
|
||||||
|
* @property string $password
|
||||||
|
* @property string $settings
|
||||||
|
* @property bool $is_active
|
||||||
|
* @property Carbon $last_tested_at
|
||||||
|
* @property string $status
|
||||||
|
* @property Carbon $created_at
|
||||||
|
* @property Carbon $updated_at
|
||||||
|
* @method static where(string $string, PlatformEnum $platform)
|
||||||
|
* @method static orderBy(string $string)
|
||||||
|
* @method static create(array $validated)
|
||||||
|
*/
|
||||||
|
class PlatformAccount extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'platform',
|
||||||
|
'instance_url',
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'api_token',
|
||||||
|
'settings',
|
||||||
|
'is_active',
|
||||||
|
'last_tested_at',
|
||||||
|
'status'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'platform' => PlatformEnum::class,
|
||||||
|
'settings' => 'array',
|
||||||
|
'is_active' => 'boolean',
|
||||||
|
'last_tested_at' => 'datetime'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Encrypt password when storing
|
||||||
|
protected function password(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::make(
|
||||||
|
get: fn ($value) => $value ? Crypt::decryptString($value) : null,
|
||||||
|
set: fn ($value) => $value ? Crypt::encryptString($value) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt API token when storing
|
||||||
|
protected function apiToken(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::make(
|
||||||
|
get: fn ($value) => $value ? Crypt::decryptString($value) : null,
|
||||||
|
set: fn ($value) => $value ? Crypt::encryptString($value) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the active accounts for a platform (returns collection)
|
||||||
|
public static function getActive(PlatformEnum $platform): Collection
|
||||||
|
{
|
||||||
|
return static::where('platform', $platform)
|
||||||
|
->where('is_active', true)
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set this account as active (deactivates others for same platform)
|
||||||
|
public function setAsActive(): void
|
||||||
|
{
|
||||||
|
// Deactivate other accounts for this platform
|
||||||
|
static::where('platform', $this->platform)
|
||||||
|
->where('id', '!=', $this->id)
|
||||||
|
->update(['is_active' => false]);
|
||||||
|
|
||||||
|
// Activate this account
|
||||||
|
$this->update(['is_active' => true]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,30 +6,32 @@
|
||||||
use App\Exceptions\PublishException;
|
use App\Exceptions\PublishException;
|
||||||
use App\Models\Article;
|
use App\Models\Article;
|
||||||
use App\Models\ArticlePublication;
|
use App\Models\ArticlePublication;
|
||||||
|
use App\Models\PlatformAccount;
|
||||||
use App\Services\Auth\LemmyAuthService;
|
use App\Services\Auth\LemmyAuthService;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
class LemmyPublisher
|
class LemmyPublisher
|
||||||
{
|
{
|
||||||
private LemmyApiService $api;
|
private LemmyApiService $api;
|
||||||
private string $username;
|
private PlatformAccount $account;
|
||||||
private string $community;
|
|
||||||
|
|
||||||
public function __construct(string $instance, string $username, string $community)
|
public function __construct(PlatformAccount $account)
|
||||||
{
|
{
|
||||||
$this->api = new LemmyApiService($instance);
|
$this->api = new LemmyApiService($account->instance_url);
|
||||||
$this->username = $username;
|
$this->account = $account;
|
||||||
$this->community = $community;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function fromConfig(): self
|
public static function fromActiveAccount(): self
|
||||||
{
|
{
|
||||||
return new self(
|
$accounts = PlatformAccount::getActive(PlatformEnum::LEMMY);
|
||||||
config('lemmy.instance'),
|
|
||||||
config('lemmy.username'),
|
if ($accounts->isEmpty()) {
|
||||||
config('lemmy.community')
|
throw new RuntimeException('No active Lemmy accounts configured');
|
||||||
);
|
}
|
||||||
|
|
||||||
|
return new self($accounts->first());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -38,7 +40,7 @@ public static function fromConfig(): self
|
||||||
public function publish(Article $article, array $extractedData): ArticlePublication
|
public function publish(Article $article, array $extractedData): ArticlePublication
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$token = LemmyAuthService::getToken();
|
$token = LemmyAuthService::getToken($this->account);
|
||||||
$communityId = $this->getCommunityId();
|
$communityId = $this->getCommunityId();
|
||||||
|
|
||||||
$languageId = $this->getLanguageIdForSource($article->url);
|
$languageId = $this->getLanguageIdForSource($article->url);
|
||||||
|
|
@ -59,16 +61,25 @@ public function publish(Article $article, array $extractedData): ArticlePublicat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
private function getCommunityId(): int
|
private function getCommunityId(): int
|
||||||
{
|
{
|
||||||
$cacheKey = "lemmy_community_id_{$this->community}";
|
$community = config('lemmy.community');
|
||||||
|
|
||||||
|
if (! $community) {
|
||||||
|
throw new RuntimeException('No community configured in config');
|
||||||
|
}
|
||||||
|
|
||||||
|
$cacheKey = "lemmy_community_id_$community";
|
||||||
$cachedId = Cache::get($cacheKey);
|
$cachedId = Cache::get($cacheKey);
|
||||||
|
|
||||||
if ($cachedId) {
|
if ($cachedId) {
|
||||||
return $cachedId;
|
return $cachedId;
|
||||||
}
|
}
|
||||||
|
|
||||||
$communityId = $this->api->getCommunityId($this->community);
|
$communityId = $this->api->getCommunityId($community);
|
||||||
Cache::put($cacheKey, $communityId, 3600);
|
Cache::put($cacheKey, $communityId, 3600);
|
||||||
|
|
||||||
return $communityId;
|
return $communityId;
|
||||||
|
|
@ -80,7 +91,7 @@ private function createPublicationRecord(Article $article, array $postData, int
|
||||||
'article_id' => $article->id,
|
'article_id' => $article->id,
|
||||||
'post_id' => $postData['post_view']['post']['id'],
|
'post_id' => $postData['post_view']['post']['id'],
|
||||||
'community_id' => $communityId,
|
'community_id' => $communityId,
|
||||||
'published_by' => $this->username,
|
'published_by' => $this->account->username,
|
||||||
'published_at' => now(),
|
'published_at' => now(),
|
||||||
'platform' => 'lemmy',
|
'platform' => 'lemmy',
|
||||||
'publication_data' => $postData,
|
'publication_data' => $postData,
|
||||||
|
|
@ -106,7 +117,7 @@ private function getLanguageIdForSource(string $url): ?int
|
||||||
|
|
||||||
private function getLanguageId(string $languageCode): ?int
|
private function getLanguageId(string $languageCode): ?int
|
||||||
{
|
{
|
||||||
$cacheKey = "lemmy_language_id_{$languageCode}";
|
$cacheKey = "lemmy_language_id_$languageCode";
|
||||||
$cachedId = Cache::get($cacheKey);
|
$cachedId = Cache::get($cacheKey);
|
||||||
|
|
||||||
if ($cachedId !== null) {
|
if ($cachedId !== null) {
|
||||||
|
|
|
||||||
|
|
@ -4,37 +4,38 @@
|
||||||
|
|
||||||
use App\Enums\PlatformEnum;
|
use App\Enums\PlatformEnum;
|
||||||
use App\Exceptions\PlatformAuthException;
|
use App\Exceptions\PlatformAuthException;
|
||||||
|
use App\Models\PlatformAccount;
|
||||||
use App\Modules\Lemmy\Services\LemmyApiService;
|
use App\Modules\Lemmy\Services\LemmyApiService;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
class LemmyAuthService
|
class LemmyAuthService
|
||||||
{
|
{
|
||||||
public static function getToken(): string
|
/**
|
||||||
|
* @throws PlatformAuthException
|
||||||
|
*/
|
||||||
|
public static function getToken(PlatformAccount $account): string
|
||||||
{
|
{
|
||||||
$cachedToken = Cache::get('lemmy_jwt_token');
|
$cacheKey = "lemmy_jwt_token_$account->id";
|
||||||
|
$cachedToken = Cache::get($cacheKey);
|
||||||
|
|
||||||
if ($cachedToken) {
|
if ($cachedToken) {
|
||||||
return $cachedToken;
|
return $cachedToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
$username = config('lemmy.username');
|
if (! $account->username || ! $account->password || ! $account->instance_url) {
|
||||||
$password = config('lemmy.password');
|
throw new PlatformAuthException(PlatformEnum::LEMMY, 'Missing credentials for account: ' . $account->username);
|
||||||
$instance = config('lemmy.instance');
|
|
||||||
|
|
||||||
if (!$username || !$password || !$instance) {
|
|
||||||
throw new PlatformAuthException(PlatformEnum::LEMMY, 'Missing credentials or instance');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$api = new LemmyApiService($instance);
|
$api = new LemmyApiService($account->instance_url);
|
||||||
$token = $api->login($username, $password);
|
$token = $api->login($account->username, $account->password);
|
||||||
|
|
||||||
if (!$token) {
|
if (!$token) {
|
||||||
throw new PlatformAuthException(PlatformEnum::LEMMY, 'Login failed');
|
throw new PlatformAuthException(PlatformEnum::LEMMY, 'Login failed for account: ' . $account->username);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache for 50 minutes (3000 seconds) to allow buffer before token expires
|
// Cache for 50 minutes (3000 seconds) to allow buffer before token expires
|
||||||
Cache::put('lemmy_jwt_token', $token, config('lemmy.token_ttl', 3000));
|
Cache::put($cacheKey, $token, 3000);
|
||||||
|
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('platform_accounts', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->enum('platform', ['lemmy']);
|
||||||
|
$table->string('instance_url');
|
||||||
|
$table->string('username');
|
||||||
|
$table->string('password');
|
||||||
|
$table->json('settings')->nullable();
|
||||||
|
$table->boolean('is_active')->default(false);
|
||||||
|
$table->timestamp('last_tested_at')->nullable();
|
||||||
|
$table->string('status')->default('untested');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique(['username', 'platform', 'is_active']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('platform_accounts');
|
||||||
|
}
|
||||||
|
};
|
||||||
103
resources/views/pages/platforms/index.blade.php
Normal file
103
resources/views/pages/platforms/index.blade.php
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('page-title', 'Platform Accounts')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="mb-6">
|
||||||
|
<a href="{{ route('platforms.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg inline-flex items-center">
|
||||||
|
<i class="fas fa-plus mr-2"></i>
|
||||||
|
Add Platform Account
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white rounded-lg shadow">
|
||||||
|
<div class="px-6 py-4 border-b border-gray-200">
|
||||||
|
<h2 class="text-lg font-medium text-gray-900">Platform Accounts</h2>
|
||||||
|
<p class="text-sm text-gray-600 mt-1">Manage your social media platform accounts for posting</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if($accounts->isEmpty())
|
||||||
|
<div class="p-6 text-center">
|
||||||
|
<i class="fas fa-share-alt text-gray-400 text-4xl mb-4"></i>
|
||||||
|
<h3 class="text-lg font-medium text-gray-900 mb-2">No platform accounts configured</h3>
|
||||||
|
<p class="text-gray-600 mb-4">Add your first platform account to start posting articles</p>
|
||||||
|
<a href="{{ route('platforms.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg inline-flex items-center">
|
||||||
|
<i class="fas fa-plus mr-2"></i>
|
||||||
|
Add Platform Account
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="min-w-full divide-y divide-gray-200">
|
||||||
|
<thead class="bg-gray-50">
|
||||||
|
<tr>
|
||||||
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Platform</th>
|
||||||
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Account</th>
|
||||||
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
|
||||||
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Last Tested</th>
|
||||||
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="bg-white divide-y divide-gray-200">
|
||||||
|
@foreach($accounts as $account)
|
||||||
|
<tr class="hover:bg-gray-50">
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<i class="fab fa-{{ $account->platform }} text-lg mr-3
|
||||||
|
{{ $account->platform === 'lemmy' ? 'text-orange-500' :
|
||||||
|
($account->platform === 'mastodon' ? 'text-purple-500' : 'text-red-500') }}"></i>
|
||||||
|
<span class="text-sm font-medium text-gray-900 capitalize">{{ $account->platform }}</span>
|
||||||
|
@if($account->is_active)
|
||||||
|
<span class="ml-2 inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800">
|
||||||
|
Active
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4">
|
||||||
|
<div class="text-sm text-gray-900">{{ $account->username }}</div>
|
||||||
|
<div class="text-sm text-gray-500">{{ $account->instance_url }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full
|
||||||
|
{{ $account->status === 'working' ? 'bg-green-100 text-green-800' :
|
||||||
|
($account->status === 'failed' ? 'bg-red-100 text-red-800' : 'bg-gray-100 text-gray-800') }}">
|
||||||
|
{{ ucfirst($account->status) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
|
{{ $account->last_tested_at ? $account->last_tested_at->format('Y-m-d H:i') : 'Never' }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
@if(!$account->is_active)
|
||||||
|
<form action="{{ route('platforms.set-active', $account) }}" method="POST" class="inline">
|
||||||
|
@csrf
|
||||||
|
<button type="submit" class="text-green-600 hover:text-green-900">
|
||||||
|
<i class="fas fa-check mr-1"></i>Set Active
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<a href="{{ route('platforms.edit', $account) }}" class="text-blue-600 hover:text-blue-900">
|
||||||
|
<i class="fas fa-edit mr-1"></i>Edit
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<form action="{{ route('platforms.destroy', $account) }}" method="POST" class="inline"
|
||||||
|
onsubmit="return confirm('Are you sure you want to delete this platform account?')">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button type="submit" class="text-red-600 hover:text-red-900">
|
||||||
|
<i class="fas fa-trash mr-1"></i>Delete
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -10,6 +10,10 @@
|
||||||
<i class="fas fa-newspaper mr-3"></i>
|
<i class="fas fa-newspaper mr-3"></i>
|
||||||
Articles
|
Articles
|
||||||
</a>
|
</a>
|
||||||
|
<a href="/platforms" class="flex items-center px-4 py-3 text-gray-300 hover:bg-gray-700 hover:text-white transition-colors {{ request()->is('platforms*') ? 'bg-gray-700 text-white' : '' }}">
|
||||||
|
<i class="fas fa-share-alt mr-3"></i>
|
||||||
|
Platforms
|
||||||
|
</a>
|
||||||
<a href="/logs" class="flex items-center px-4 py-3 text-gray-300 hover:bg-gray-700 hover:text-white transition-colors {{ request()->is('logs') ? 'bg-gray-700 text-white' : '' }}">
|
<a href="/logs" class="flex items-center px-4 py-3 text-gray-300 hover:bg-gray-700 hover:text-white transition-colors {{ request()->is('logs') ? 'bg-gray-700 text-white' : '' }}">
|
||||||
<i class="fas fa-list mr-3"></i>
|
<i class="fas fa-list mr-3"></i>
|
||||||
Logs
|
Logs
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,6 @@
|
||||||
|
|
||||||
Route::get('/articles', ArticlesController::class)->name('articles');
|
Route::get('/articles', ArticlesController::class)->name('articles');
|
||||||
Route::get('/logs', LogsController::class)->name('logs');
|
Route::get('/logs', LogsController::class)->name('logs');
|
||||||
|
|
||||||
|
Route::resource('platforms', App\Http\Controllers\PlatformAccountsController::class)->names('platforms');
|
||||||
|
Route::post('/platforms/{platformAccount}/set-active', [App\Http\Controllers\PlatformAccountsController::class, 'setActive'])->name('platforms.set-active');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue