mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-22 16:51:20 +00:00
feat: add breadcrumb in admin area
- add Breadcrumb library and service - update authorizations - add missing routes to avoid 404 links in breadcrumb - add svg_helper globally in base controller - update purgecss config to check .ts files closes #17
This commit is contained in:
parent
ed6e953010
commit
7fb1de2cf3
@ -49,7 +49,7 @@ class FlatAuthorization extends \Myth\Auth\Authorization\FlatAuthorization
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a member a part of multiple groups.
|
||||
* Makes user part of given groups.
|
||||
*
|
||||
* @param $userId
|
||||
* @param array|null $groups // Either collection of ID or names
|
||||
|
@ -77,11 +77,11 @@ $routes->group(
|
||||
$routes->get('podcasts', 'Podcast::list', [
|
||||
'as' => 'podcast_list',
|
||||
]);
|
||||
$routes->get('new-podcast', 'Podcast::create', [
|
||||
$routes->get('podcasts/new', 'Podcast::create', [
|
||||
'as' => 'podcast_create',
|
||||
'filter' => 'permission:podcasts-create',
|
||||
]);
|
||||
$routes->post('new-podcast', 'Podcast::attemptCreate', [
|
||||
$routes->post('podcasts/new', 'Podcast::attemptCreate', [
|
||||
'filter' => 'permission:podcasts-create',
|
||||
]);
|
||||
|
||||
@ -108,19 +108,19 @@ $routes->group(
|
||||
'as' => 'episode_list',
|
||||
'filter' => 'permission:podcasts-view,podcast-view',
|
||||
]);
|
||||
$routes->get('new-episode', 'Episode::create/$1', [
|
||||
$routes->get('episodes/new', 'Episode::create/$1', [
|
||||
'as' => 'episode_create',
|
||||
'filter' =>
|
||||
'permission:episodes-create,podcast_episodes-create',
|
||||
]);
|
||||
$routes->post('new-episode', 'Episode::attemptCreate/$1', [
|
||||
$routes->post('episodes/new', 'Episode::attemptCreate/$1', [
|
||||
'filter' =>
|
||||
'permission:episodes-create,podcast_episodes-create',
|
||||
]);
|
||||
|
||||
$routes->get('episodes/(:num)', 'Episode::view/$1/$2', [
|
||||
'as' => 'episode_view',
|
||||
'filter' => 'permission:episodes-list,podcast_episodes-list',
|
||||
'filter' => 'permission:episodes-view,podcast_episodes-view',
|
||||
]);
|
||||
$routes->get('episodes/(:num)/edit', 'Episode::edit/$1/$2', [
|
||||
'as' => 'episode_edit',
|
||||
@ -146,15 +146,18 @@ $routes->group(
|
||||
'filter' =>
|
||||
'permission:podcasts-manage_contributors,podcast-manage_contributors',
|
||||
]);
|
||||
$routes->get('add-contributor', 'Contributor::add/$1', [
|
||||
$routes->get('contributors/add', 'Contributor::add/$1', [
|
||||
'as' => 'contributor_add',
|
||||
'filter' =>
|
||||
'permission:podcasts-manage_contributors,podcast-manage_contributors',
|
||||
]);
|
||||
$routes->post('add-contributor', 'Contributor::attemptAdd/$1', [
|
||||
$routes->post('contributors/add', 'Contributor::attemptAdd/$1', [
|
||||
'filter' =>
|
||||
'permission:podcasts-manage_contributors,podcast-manage_contributors',
|
||||
]);
|
||||
$routes->get('contributors/(:num)', 'Contributor::view/$1/$2', [
|
||||
'as' => 'contributor_view',
|
||||
]);
|
||||
$routes->get(
|
||||
'contributors/(:num)/edit',
|
||||
'Contributor::edit/$1/$2',
|
||||
@ -188,11 +191,15 @@ $routes->group(
|
||||
'as' => 'user_list',
|
||||
'filter' => 'permission:users-list',
|
||||
]);
|
||||
$routes->get('new-user', 'User::create', [
|
||||
$routes->get('users/new', 'User::create', [
|
||||
'as' => 'user_create',
|
||||
'filter' => 'permission:users-create',
|
||||
]);
|
||||
$routes->post('new-user', 'User::attemptCreate', [
|
||||
$routes->get('users/(:num)', 'User::view/$1', [
|
||||
'as' => 'user_view',
|
||||
'filter' => 'permission:users-view',
|
||||
]);
|
||||
$routes->post('users/new', 'User::attemptCreate', [
|
||||
'filter' => 'permission:users-create',
|
||||
]);
|
||||
$routes->get('users/(:num)/edit', 'User::edit/$1', [
|
||||
|
@ -7,6 +7,7 @@ use CodeIgniter\Model;
|
||||
use App\Authorization\FlatAuthorization;
|
||||
use App\Authorization\PermissionModel;
|
||||
use App\Authorization\GroupModel;
|
||||
use App\Libraries\Breadcrumb;
|
||||
use App\Models\UserModel;
|
||||
use Myth\Auth\Models\LoginModel;
|
||||
|
||||
@ -91,4 +92,13 @@ class Services extends CoreServices
|
||||
|
||||
return $instance->setUserModel($userModel);
|
||||
}
|
||||
|
||||
public static function breadcrumb(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return self::getSharedInstance('breadcrumb');
|
||||
}
|
||||
|
||||
return new Breadcrumb();
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class BaseController extends Controller
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $helpers = ['auth'];
|
||||
protected $helpers = ['auth', 'breadcrumb', 'svg'];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -41,7 +41,24 @@ class Contributor extends BaseController
|
||||
'podcast' => $this->podcast,
|
||||
];
|
||||
|
||||
echo view('admin/contributor/list', $data);
|
||||
replace_breadcrumb_params([0 => $this->podcast->title]);
|
||||
return view('admin/contributor/list', $data);
|
||||
}
|
||||
|
||||
public function view()
|
||||
{
|
||||
$data = [
|
||||
'contributor' => (new UserModel())->getPodcastContributor(
|
||||
$this->user->id,
|
||||
$this->podcast->id
|
||||
),
|
||||
];
|
||||
|
||||
replace_breadcrumb_params([
|
||||
0 => $this->podcast->title,
|
||||
1 => $this->user->username,
|
||||
]);
|
||||
return view('admin/contributor/view', $data);
|
||||
}
|
||||
|
||||
public function add()
|
||||
@ -52,7 +69,8 @@ class Contributor extends BaseController
|
||||
'roles' => (new GroupModel())->getContributorRoles(),
|
||||
];
|
||||
|
||||
echo view('admin/contributor/add', $data);
|
||||
replace_breadcrumb_params([0 => $this->podcast->title]);
|
||||
return view('admin/contributor/add', $data);
|
||||
}
|
||||
|
||||
public function attemptAdd()
|
||||
@ -87,7 +105,11 @@ class Contributor extends BaseController
|
||||
'roles' => (new GroupModel())->getContributorRoles(),
|
||||
];
|
||||
|
||||
echo view('admin/contributor/edit', $data);
|
||||
replace_breadcrumb_params([
|
||||
0 => $this->podcast->title,
|
||||
1 => $this->user->username,
|
||||
]);
|
||||
return view('admin/contributor/edit', $data);
|
||||
}
|
||||
|
||||
public function attemptEdit()
|
||||
|
@ -42,6 +42,9 @@ class Episode extends BaseController
|
||||
'podcast' => $this->podcast,
|
||||
];
|
||||
|
||||
replace_breadcrumb_params([
|
||||
0 => $this->podcast->title,
|
||||
]);
|
||||
return view('admin/episode/list', $data);
|
||||
}
|
||||
|
||||
@ -49,6 +52,10 @@ class Episode extends BaseController
|
||||
{
|
||||
$data = ['episode' => $this->episode];
|
||||
|
||||
replace_breadcrumb_params([
|
||||
0 => $this->podcast->title,
|
||||
1 => $this->episode->title,
|
||||
]);
|
||||
return view('admin/episode/view', $data);
|
||||
}
|
||||
|
||||
@ -60,7 +67,10 @@ class Episode extends BaseController
|
||||
'podcast' => $this->podcast,
|
||||
];
|
||||
|
||||
echo view('admin/episode/create', $data);
|
||||
replace_breadcrumb_params([
|
||||
0 => $this->podcast->title,
|
||||
]);
|
||||
return view('admin/episode/create', $data);
|
||||
}
|
||||
|
||||
public function attemptCreate()
|
||||
@ -115,7 +125,11 @@ class Episode extends BaseController
|
||||
'episode' => $this->episode,
|
||||
];
|
||||
|
||||
echo view('admin/episode/edit', $data);
|
||||
replace_breadcrumb_params([
|
||||
0 => $this->podcast->title,
|
||||
1 => $this->episode->title,
|
||||
]);
|
||||
return view('admin/episode/edit', $data);
|
||||
}
|
||||
|
||||
public function attemptEdit()
|
||||
|
@ -52,6 +52,7 @@ class Podcast extends BaseController
|
||||
{
|
||||
$data = ['podcast' => $this->podcast];
|
||||
|
||||
replace_breadcrumb_params([0 => $this->podcast->title]);
|
||||
return view('admin/podcast/view', $data);
|
||||
}
|
||||
|
||||
@ -69,7 +70,7 @@ class Podcast extends BaseController
|
||||
),
|
||||
];
|
||||
|
||||
echo view('admin/podcast/create', $data);
|
||||
return view('admin/podcast/create', $data);
|
||||
}
|
||||
|
||||
public function attemptCreate()
|
||||
@ -145,7 +146,8 @@ class Podcast extends BaseController
|
||||
'categories' => (new CategoryModel())->findAll(),
|
||||
];
|
||||
|
||||
echo view('admin/podcast/edit', $data);
|
||||
replace_breadcrumb_params([0 => $this->podcast->title]);
|
||||
return view('admin/podcast/edit', $data);
|
||||
}
|
||||
|
||||
public function attemptEdit()
|
||||
|
@ -34,13 +34,21 @@ class User extends BaseController
|
||||
return view('admin/user/list', $data);
|
||||
}
|
||||
|
||||
public function view()
|
||||
{
|
||||
$data = ['user' => $this->user];
|
||||
|
||||
replace_breadcrumb_params([0 => $this->user->username]);
|
||||
return view('admin/user/view', $data);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$data = [
|
||||
'roles' => (new GroupModel())->getUserRoles(),
|
||||
];
|
||||
|
||||
echo view('admin/user/create', $data);
|
||||
return view('admin/user/create', $data);
|
||||
}
|
||||
|
||||
public function attemptCreate()
|
||||
@ -99,7 +107,8 @@ class User extends BaseController
|
||||
'roles' => (new GroupModel())->getUserRoles(),
|
||||
];
|
||||
|
||||
echo view('admin/user/edit', $data);
|
||||
replace_breadcrumb_params([0 => $this->user->username]);
|
||||
return view('admin/user/edit', $data);
|
||||
}
|
||||
|
||||
public function attemptEdit()
|
||||
|
@ -50,6 +50,11 @@ class AuthSeeder extends Seeder
|
||||
'description' => 'List all users',
|
||||
'has_permission' => ['superadmin'],
|
||||
],
|
||||
[
|
||||
'name' => 'view',
|
||||
'description' => 'View any user info',
|
||||
'has_permission' => ['superadmin'],
|
||||
],
|
||||
[
|
||||
'name' => 'manage_authorizations',
|
||||
'description' => 'Add or remove roles/permissions to a user',
|
||||
@ -128,6 +133,11 @@ class AuthSeeder extends Seeder
|
||||
'description' => 'List all episodes of any podcast',
|
||||
'has_permission' => ['superadmin'],
|
||||
],
|
||||
[
|
||||
'name' => 'view',
|
||||
'description' => 'View any episode of any podcast',
|
||||
'has_permission' => ['superadmin'],
|
||||
],
|
||||
[
|
||||
'name' => 'create',
|
||||
'description' => 'Add a new episode to any podcast',
|
||||
@ -195,6 +205,11 @@ class AuthSeeder extends Seeder
|
||||
'description' => 'List all episodes of a podcast',
|
||||
'has_permission' => ['podcast_admin'],
|
||||
],
|
||||
[
|
||||
'name' => 'view',
|
||||
'description' => 'View any episode of a podcast',
|
||||
'has_permission' => ['podcast_admin'],
|
||||
],
|
||||
[
|
||||
'name' => 'create',
|
||||
'description' => 'Add new episodes for a podcast',
|
||||
|
@ -12,6 +12,12 @@ class User extends \Myth\Auth\Entities\User
|
||||
*/
|
||||
protected $podcasts = [];
|
||||
|
||||
/**
|
||||
* The podcast user is contributing to
|
||||
* @var \App\Entities\Podcast
|
||||
*/
|
||||
protected $podcast;
|
||||
|
||||
/**
|
||||
* Array of field names and the type of value to cast them as
|
||||
* when they are accessed.
|
||||
@ -20,6 +26,7 @@ class User extends \Myth\Auth\Entities\User
|
||||
'active' => 'boolean',
|
||||
'force_pass_reset' => 'boolean',
|
||||
'podcast_role' => '?string',
|
||||
'podcast_id' => '?integer',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -41,4 +48,19 @@ class User extends \Myth\Auth\Entities\User
|
||||
|
||||
return $this->podcasts;
|
||||
}
|
||||
|
||||
public function getPodcast()
|
||||
{
|
||||
if (empty($this->podcast_id)) {
|
||||
throw new \RuntimeException(
|
||||
'Podcast_id must be set before getting podcast.'
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($this->podcast)) {
|
||||
$this->podcast = (new PodcastModel())->find($this->podcast_id);
|
||||
}
|
||||
|
||||
return $this->podcast;
|
||||
}
|
||||
}
|
||||
|
28
app/Helpers/breadcrumb_helper.php
Normal file
28
app/Helpers/breadcrumb_helper.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
use Config\Services;
|
||||
|
||||
/**
|
||||
* Returns the inline svg icon
|
||||
*
|
||||
* @param string $name name of the icon file without the .svg extension
|
||||
* @param string $class to be added to the svg string
|
||||
* @return string html breadcrumb
|
||||
*/
|
||||
function render_breadcrumb()
|
||||
{
|
||||
$breadcrumb = Services::breadcrumb();
|
||||
return $breadcrumb->render();
|
||||
}
|
||||
|
||||
function replace_breadcrumb_params($newParams)
|
||||
{
|
||||
$breadcrumb = Services::breadcrumb();
|
||||
$breadcrumb->replaceParams($newParams);
|
||||
}
|
22
app/Language/en/Breadcrumb.php
Normal file
22
app/Language/en/Breadcrumb.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
return [
|
||||
'label' => 'breadcrumb',
|
||||
config('App')->adminGateway => 'Home',
|
||||
'my-podcasts' => 'my podcasts',
|
||||
'podcasts' => 'podcasts',
|
||||
'episodes' => 'episodes',
|
||||
'contributors' => 'contributors',
|
||||
'add' => 'add',
|
||||
'new' => 'new',
|
||||
'edit' => 'edit',
|
||||
'users' => 'users',
|
||||
'my-account' => 'my account',
|
||||
'change-password' => 'change password',
|
||||
];
|
@ -8,6 +8,7 @@
|
||||
|
||||
return [
|
||||
'podcast_contributors' => 'Podcast contributors',
|
||||
'view' => '{username}\'s contribution to {podcastName}',
|
||||
'add' => 'Add contributor',
|
||||
'add_contributor' => 'Add a contributor for {0}',
|
||||
'edit_role' => 'Update role for {0}',
|
||||
|
@ -8,8 +8,8 @@
|
||||
|
||||
return [
|
||||
'info' => 'My account info',
|
||||
'changePassword' => 'Change my password',
|
||||
'messages' => [
|
||||
'passwordChangeSuccess' => 'Password has been successfully changed!',
|
||||
'changePassword' => 'Change my password',
|
||||
],
|
||||
];
|
||||
|
@ -13,6 +13,7 @@ return [
|
||||
'unban' => 'Unban',
|
||||
'delete' => 'Delete',
|
||||
'create' => 'Create a user',
|
||||
'view' => '{username}\'s info',
|
||||
'all_users' => 'All users',
|
||||
'form' => [
|
||||
'email' => 'Email',
|
||||
|
104
app/Libraries/Breadcrumb.php
Normal file
104
app/Libraries/Breadcrumb.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Generates and renders a breadcrumb based on the current url segments
|
||||
*
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Libraries;
|
||||
|
||||
class Breadcrumb
|
||||
{
|
||||
/**
|
||||
* List of breadcrumb links.
|
||||
*
|
||||
* @var array
|
||||
* $links = [
|
||||
* 'text' => (string) the anchor text,
|
||||
* 'href' => (string) the anchor href,
|
||||
* ]
|
||||
*/
|
||||
protected $links = [];
|
||||
|
||||
/**
|
||||
* Initializes the Breadcrumb object using the segments from
|
||||
* current_url by populating the $links property with text and href data
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$uri = '';
|
||||
foreach (current_url(true)->getSegments() as $segment) {
|
||||
$uri .= '/' . $segment;
|
||||
array_push($this->links, [
|
||||
'text' => is_numeric($segment)
|
||||
? $segment
|
||||
: lang('Breadcrumb.' . $segment),
|
||||
'href' => base_url($uri),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all numeric text in breadcrumb's $link property
|
||||
* with new params at same position
|
||||
*
|
||||
* Given a breadcrumb with numeric params, this function
|
||||
* replaces them with the values provided in $newParams
|
||||
*
|
||||
* Example with `Home / podcasts / 1 / episodes / 1`
|
||||
*
|
||||
* $newParams = [
|
||||
* 0 => 'foo',
|
||||
* 1 => 'bar'
|
||||
* ]
|
||||
* replaceParams($newParams);
|
||||
*
|
||||
* The breadcrumb is now `Home / podcasts / foo / episodes / bar`
|
||||
*
|
||||
* @param array $newParams
|
||||
*/
|
||||
public function replaceParams($newParams)
|
||||
{
|
||||
foreach ($this->links as $key => $link) {
|
||||
if (is_numeric($link['text'])) {
|
||||
$this->links[$key]['text'] = $newParams[0];
|
||||
array_shift($newParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the breadcrumb object as an accessible html breadcrumb nav
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$listItems = '';
|
||||
$keys = array_keys($this->links);
|
||||
foreach ($this->links as $key => $link) {
|
||||
if (end($keys) == $key) {
|
||||
$listItem =
|
||||
'<li class="breadcrumb-item active" aria-current="page">' .
|
||||
$link['text'] .
|
||||
'</li>';
|
||||
} else {
|
||||
$listItem =
|
||||
'<li class="breadcrumb-item">' .
|
||||
anchor($link['href'], $link['text']) .
|
||||
'</li>';
|
||||
}
|
||||
|
||||
$listItems .= $listItem;
|
||||
}
|
||||
|
||||
return '<nav aria-label="' .
|
||||
lang('Breadcrumb.label') .
|
||||
'"><ol class="breadcrumb">' .
|
||||
$listItems .
|
||||
'</ol></nav>';
|
||||
}
|
||||
}
|
@ -17,8 +17,11 @@ class UserModel extends \Myth\Auth\Models\UserModel
|
||||
|
||||
public function getPodcastContributor($user_id, $podcast_id)
|
||||
{
|
||||
return $this->select('users.*')
|
||||
return $this->select(
|
||||
'users.*, users_podcasts.podcast_id as podcast_id, auth_groups.name as podcast_role'
|
||||
)
|
||||
->join('users_podcasts', 'users_podcasts.user_id = users.id')
|
||||
->join('auth_groups', 'auth_groups.id = users_podcasts.group_id')
|
||||
->where([
|
||||
'users.id' => $user_id,
|
||||
'podcast_id' => $podcast_id,
|
||||
|
20
app/Views/_assets/styles/breadcrumb.css
Normal file
20
app/Views/_assets/styles/breadcrumb.css
Normal file
@ -0,0 +1,20 @@
|
||||
.breadcrumb {
|
||||
@apply inline-flex flex-wrap px-1 py-2 text-sm text-gray-800;
|
||||
}
|
||||
|
||||
.breadcrumb-item + .breadcrumb-item::before {
|
||||
@apply inline-block px-1 text-gray-500;
|
||||
content: "/";
|
||||
}
|
||||
|
||||
.breadcrumb-item a {
|
||||
@apply no-underline;
|
||||
|
||||
&:hover {
|
||||
@apply underline;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-item.active {
|
||||
@apply font-semibold;
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
@import "./tailwind.css";
|
||||
@import "./layout.css";
|
||||
@import "./breadcrumb.css";
|
||||
|
@ -1,10 +1,13 @@
|
||||
<header class="<?= $class ?>">
|
||||
<a href="<?= route_to(
|
||||
'admin_home'
|
||||
) ?>" class="inline-flex items-center text-xl">
|
||||
<?= svg('logo-castopod', 'text-3xl mr-2 -ml-2') ?>
|
||||
Admin
|
||||
</a>
|
||||
<div class="w-64">
|
||||
<a href="<?= route_to(
|
||||
'admin_home'
|
||||
) ?>" class="inline-flex items-center text-xl">
|
||||
<?= svg('logo-castopod', 'text-3xl mr-2') ?>
|
||||
Admin
|
||||
</a>
|
||||
</div>
|
||||
<?= render_breadcrumb() ?>
|
||||
<div class="relative ml-auto" data-toggle="dropdown">
|
||||
<button type="button" class="inline-flex items-center px-2 py-1 outline-none focus:shadow-outline" id="myAccountDropdown" data-popper="button" aria-haspopup="true" aria-expanded="false">
|
||||
Hey <?= user()->username ?>
|
||||
|
@ -1,7 +1,3 @@
|
||||
<?php
|
||||
|
||||
helper('html'); ?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
|
@ -1,7 +1,3 @@
|
||||
<?php
|
||||
|
||||
helper('html'); ?>
|
||||
|
||||
<article class="flex w-full max-w-lg mb-4 bg-white border rounded shadow">
|
||||
<img src="<?= $episode->image_url ?>" alt="<?= $episode->title ?>" class="object-cover w-32 h-32 rounded-l" />
|
||||
<div class="flex flex-col flex-1 px-4 py-2">
|
||||
|
32
app/Views/admin/_partials/_user_info.php
Normal file
32
app/Views/admin/_partials/_user_info.php
Normal file
@ -0,0 +1,32 @@
|
||||
<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium leading-5 text-gray-500">
|
||||
Email
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<?= $user->email ?>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium leading-5 text-gray-500">
|
||||
Username
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<?= $user->username ?>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium leading-5 text-gray-500">
|
||||
Roles
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
[<?= implode(', ', $user->roles) ?>]
|
||||
</dd>
|
||||
</div>
|
||||
<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium leading-5 text-gray-500">
|
||||
Permissions
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
[<?= implode(', ', $user->permissions) ?>]
|
||||
</dd>
|
||||
</div>
|
@ -11,7 +11,7 @@ $navigation = [
|
||||
<nav class="<?= $class ?>">
|
||||
<?php foreach ($navigation as $section => $data): ?>
|
||||
<div class="mb-4">
|
||||
<button class="inline-flex items-center w-full px-4 py-1 outline-none focus:shadow-outline" type="button">
|
||||
<button class="inline-flex items-center w-full px-6 py-1 outline-none focus:shadow-outline" type="button">
|
||||
<?= icon($data['icon'], 'text-gray-500') ?>
|
||||
<span class="ml-2"><?= lang('AdminNavigation.' . $section) ?></span>
|
||||
</button>
|
||||
|
@ -1,5 +1,3 @@
|
||||
<?php helper('html'); ?>
|
||||
|
||||
<?= $this->extend('admin/_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
|
28
app/Views/admin/contributor/view.php
Normal file
28
app/Views/admin/contributor/view.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?= $this->extend('admin/_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
<?= lang('Contributor.view', [
|
||||
'username' => $contributor->username,
|
||||
'podcastName' => $contributor->podcast->name,
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium leading-5 text-gray-500">
|
||||
Username
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<?= $contributor->username ?>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium leading-5 text-gray-500">
|
||||
Role
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<?= $contributor->podcast_role ?>
|
||||
</dd>
|
||||
</div>
|
||||
<?= $this->endSection() ?>
|
@ -3,17 +3,18 @@
|
||||
<?= $this->section('title') ?>
|
||||
|
||||
<?= lang('Episode.all_podcast_episodes') ?> (<?= count($podcast->episodes) ?>)
|
||||
<a class="inline-flex items-center px-2 py-1 mb-2 ml-2 text-sm text-white bg-green-500 rounded shadow-xs outline-none hover:bg-green-600 focus:shadow-outline" href="<?= route_to(
|
||||
'episode_create',
|
||||
$podcast->id
|
||||
) ?>">
|
||||
<?= icon('add', 'mr-2') ?>
|
||||
<?= lang('Episode.create') ?></a>
|
||||
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<a class="inline-block px-4 py-2 mb-2 border hover:bg-gray-100" href="<?= route_to(
|
||||
'episode_create',
|
||||
$podcast->id
|
||||
) ?>"><?= lang('Episode.create') ?></a>
|
||||
|
||||
<?= view('admin/_partials/_episode-list.php', [
|
||||
'episodes' => $podcast->episodes,
|
||||
]) ?>
|
||||
|
@ -1,12 +1,11 @@
|
||||
<?= $this->extend('admin/_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
<?= $episode->title ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<a class="underline hover:no-underline" href="<?= route_to(
|
||||
'podcast_view',
|
||||
$episode->podcast->id
|
||||
) ?>">< <?= lang('Episode.back_to_podcast') ?></a>
|
||||
<h1 class="text-2xl font-semibold"><?= $episode->title ?></h1>
|
||||
<img src="<?= $episode->image_url ?>" alt="Episode cover" class="object-cover w-40 h-40 mb-6" />
|
||||
<audio controls preload="none" class="mb-12">
|
||||
<source src="<?= $episode->enclosure_url ?>" type="<?= $episode->enclosure_type ?>">
|
||||
|
@ -7,30 +7,7 @@
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium leading-5 text-gray-500">
|
||||
Email
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<?= user()->email ?>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium leading-5 text-gray-500">
|
||||
Username
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<?= user()->username ?>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium leading-5 text-gray-500">
|
||||
Permissions
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
[<?= implode(', ', user()->permissions) ?>]
|
||||
</dd>
|
||||
</div>
|
||||
<?= view('admin/_partials/_user_info.php', ['user' => user()]) ?>
|
||||
|
||||
<?= $this->endSection()
|
||||
?>
|
||||
|
@ -1,5 +1,3 @@
|
||||
<?php helper('html'); ?>
|
||||
|
||||
<?= $this->extend('admin/_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
|
@ -1,7 +1,3 @@
|
||||
<?php
|
||||
|
||||
helper('html'); ?>
|
||||
|
||||
<?= $this->extend('admin/_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
|
@ -1,5 +1,3 @@
|
||||
<?php helper('html'); ?>
|
||||
|
||||
<?= $this->extend('admin/_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
|
12
app/Views/admin/user/view.php
Normal file
12
app/Views/admin/user/view.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?= $this->extend('admin/_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
<?= lang('User.view', ['username' => $user->username]) ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<?= view('admin/_partials/_user_info.php', ['user' => $user]) ?>
|
||||
|
||||
<?= $this->endSection() ?>
|
@ -1,7 +1,7 @@
|
||||
/* eslint-disable */
|
||||
|
||||
module.exports = {
|
||||
purge: ["./app/Views/**/*.php", "./app/Views/**/*.js"],
|
||||
purge: ["./app/Views/**/*.php", "./app/Views/**/*.ts"],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user