Commit d86142eb authored by Yassine Doghri's avatar Yassine Doghri
Browse files

feat(admin): update admin layout for better ux + update brand pine colors

parent 7a276764
......@@ -41,7 +41,7 @@ if (! function_exists('button')) {
$variantClass = [
'default' => 'text-black bg-gray-300 hover:bg-gray-400',
'primary' => 'text-white bg-pine-700 hover:bg-pine-800',
'primary' => 'text-white bg-pine-500 hover:bg-pine-800',
'secondary' => 'text-white bg-gray-700 hover:bg-gray-800',
'accent' => 'text-white bg-rose-600 hover:bg-rose-800',
'success' => 'text-white bg-green-600 hover:bg-green-700',
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M4 22a8 8 0 1 1 16 0H4zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6z"/>
<path d="M12 2c5.52 0 10 4.48 10 10s-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2zM6.023 15.416C7.491 17.606 9.695 19 12.16 19c2.464 0 4.669-1.393 6.136-3.584A8.968 8.968 0 0 0 12.16 13a8.968 8.968 0 0 0-6.137 2.416zM12 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
</g>
</svg>
/* Admin layout */
.holy-grail-grid {
@apply grid min-h-screen overflow-y-auto;
grid-template: 1fr auto / auto 1fr;
grid-template: auto 1fr auto / auto 1fr;
& .holy-grail-sidebar {
@apply col-start-1 col-end-2 row-start-1 row-end-3 w-80;
& .holy-grail__header {
@apply h-10 col-start-1 col-end-4 row-start-1 row-end-2;
}
& .holy-grail-main {
@apply w-full col-start-1 col-end-3 row-start-1 row-end-2;
& .holy-grail__sidebar {
@apply col-start-1 col-end-2 row-start-2 row-end-4;
width: 300px;
max-height: calc(100vh - 2.5rem);
}
& .holy-grail__main {
@apply col-start-1 col-end-3 row-start-2 row-end-3;
}
& .holy-grail-footer {
@apply w-full col-start-1 col-end-3 row-start-2 row-end-3;
& .holy-grail__footer {
@apply col-start-1 col-end-3 row-start-3 row-end-4;
}
@screen md {
& .holy-grail-main {
& .holy-grail__main {
@apply col-start-2;
}
& .holy-grail-footer {
& .holy-grail__footer {
@apply col-start-2;
}
}
......
......@@ -29,7 +29,7 @@ class Button extends Component
$variantClass = [
'default' => 'text-black bg-gray-300 hover:bg-gray-400',
'primary' => 'text-white bg-pine-700 hover:bg-pine-800',
'primary' => 'text-white bg-pine-500 hover:bg-pine-800',
'secondary' => 'text-white bg-gray-700 hover:bg-gray-800',
'accent' => 'text-white bg-rose-600 hover:bg-rose-800',
'success' => 'text-white bg-green-600 hover:bg-green-700',
......
......@@ -18,14 +18,14 @@ class MyAccountController extends BaseController
{
public function index(): string
{
return view('my_account\view');
return view('my_account/view');
}
public function changePassword(): string
{
helper('form');
return view('my_account\change_password');
return view('my_account/change_password');
}
public function attemptChange(): RedirectResponse
......
......@@ -9,7 +9,7 @@ declare(strict_types=1);
*/
return [
'go_to_website' => 'Go to website',
'go_to_website' => 'View site',
'dashboard' => 'Dashboard',
'admin' => 'Home',
'podcasts' => 'Podcasts',
......
......@@ -9,7 +9,7 @@ declare(strict_types=1);
*/
return [
'go_to_website' => 'Go to website',
'go_to_website' => 'View site',
'dashboard' => 'Dashboard',
'admin' => 'Home',
'podcasts' => 'Podcasts',
......
......@@ -55,6 +55,7 @@
"lit": "^2.0.0-rc.2",
"postcss-import": "^14.0.2",
"postcss-preset-env": "^6.7.0",
"postcss-reporter": "^7.0.2",
"prettier": "2.3.2",
"prettier-plugin-organize-imports": "^2.3.3",
"semantic-release": "^17.4.4",
......@@ -62,6 +63,7 @@
"stylelint-config-standard": "^22.0.0",
"svgo": "^2.3.1",
"tailwindcss": "^2.2.7",
"tailwindcss-scroll-snap": "^1.1.0",
"typescript": "^4.3.5",
"vite": "^2.4.4"
}
......@@ -13724,6 +13726,26 @@
"node": ">=0.10.0"
}
},
"node_modules/postcss-reporter": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.5.tgz",
"integrity": "sha512-glWg7VZBilooZGOFPhN9msJ3FQs19Hie7l5a/eE6WglzYqVeH3ong3ShFcp9kDWJT1g2Y/wd59cocf9XxBtkWA==",
"dev": true,
"dependencies": {
"picocolors": "^1.0.0",
"thenby": "^1.3.4"
},
"engines": {
"node": ">=10"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-resolve-nested-selector": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
......@@ -16172,6 +16194,16 @@
"postcss": "^8.0.9"
}
},
"node_modules/tailwindcss-scroll-snap": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tailwindcss-scroll-snap/-/tailwindcss-scroll-snap-1.1.0.tgz",
"integrity": "sha512-qmV7PJMqQrdzf2uKjaIrgIW9fpz8SNdD6hhVtbUbRGjz95CsZvsVozHRCz3NrPphro+tbRMbUhDYmTNKP6qPSw==",
"dev": true,
"dependencies": {
"lodash": "^4.17.15",
"reduce-css-calc": "^2.1.7"
}
},
"node_modules/tailwindcss/node_modules/fs-extra": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
......@@ -16308,6 +16340,12 @@
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"node_modules/thenby": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz",
"integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==",
"dev": true
},
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
......@@ -27630,6 +27668,16 @@
}
}
},
"postcss-reporter": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.5.tgz",
"integrity": "sha512-glWg7VZBilooZGOFPhN9msJ3FQs19Hie7l5a/eE6WglzYqVeH3ong3ShFcp9kDWJT1g2Y/wd59cocf9XxBtkWA==",
"dev": true,
"requires": {
"picocolors": "^1.0.0",
"thenby": "^1.3.4"
}
},
"postcss-resolve-nested-selector": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
......@@ -29621,6 +29669,16 @@
}
}
},
"tailwindcss-scroll-snap": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tailwindcss-scroll-snap/-/tailwindcss-scroll-snap-1.1.0.tgz",
"integrity": "sha512-qmV7PJMqQrdzf2uKjaIrgIW9fpz8SNdD6hhVtbUbRGjz95CsZvsVozHRCz3NrPphro+tbRMbUhDYmTNKP6qPSw==",
"dev": true,
"requires": {
"lodash": "^4.17.15",
"reduce-css-calc": "^2.1.7"
}
},
"temp-dir": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
......@@ -29660,6 +29718,12 @@
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"thenby": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz",
"integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==",
"dev": true
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
......@@ -3,6 +3,7 @@
module.exports = {
plugins: [
require("postcss-import"),
require("postcss-reporter"),
require("tailwindcss"),
require("postcss-preset-env")({ stage: 1 }),
...(process.env.NODE_ENV === "production"
......
......@@ -19,16 +19,16 @@ module.exports = {
},
colors: {
pine: {
50: "#ebf8f8",
100: "#cff7f3",
200: "#9df2e4",
300: "#5ee8d4",
400: "#1cd7ba",
500: "#08c09a",
600: "#07a57d",
700: "#009486",
800: "#006D60",
900: "#00564A",
50: "#F2FAF9",
100: "#E7F9E4",
200: "#bfe4e1",
300: "#99d4cf",
400: "#4db4aa",
500: "#009486",
600: "#008579",
700: "#006D60",
800: "#00564A",
900: "#003D0B",
},
rose: {
50: "#fcf9f8",
......@@ -56,5 +56,6 @@ module.exports = {
require("@tailwindcss/forms"),
require("@tailwindcss/typography"),
require("@tailwindcss/line-clamp"),
require("tailwindcss-scroll-snap"),
],
};
......@@ -13,20 +13,70 @@
<?= service('vite')->asset('js/audio-player.ts', 'js') ?>
</head>
<body class="relative bg-gray-100 holy-grail-grid">
<body class="relative bg-pine-50 holy-grail-grid">
<div id="sidebar-backdrop" role="button" tabIndex="0" aria-label="Close" class="fixed z-50 hidden w-full h-full bg-gray-900 bg-opacity-50 md:hidden"></div>
<aside id="admin-sidebar" class="sticky top-0 z-50 flex flex-col max-h-screen transition duration-200 ease-in-out transform -translate-x-full bg-white border-r w-80 holy-grail-sidebar md:translate-x-0">
<header class="sticky top-0 z-50 flex items-center justify-between h-10 text-white border-b holy-grail__header bg-pine-800 border-pine-900">
<div class="inline-flex items-center h-full">
<a href="<?= route_to(
'admin',
) ?>" class="inline-flex items-center h-full px-2 border-r border-pine-900">
<?= (isset($podcast) ? icon('arrow-left', 'mr-2') : '') . svg('castopod-logo', 'h-6') ?>
</a>
<a href="<?= route_to(
'home',
) ?>" class="inline-flex items-center h-full px-6 text-sm font-semibold outline-none hover:underline focus:ring">
<?= lang('AdminNavigation.go_to_website') ?>
<?= icon('external-link', 'ml-1 opacity-60') ?>
</a>
</div>
<button
type="button"
class="inline-flex items-center h-full px-6 mt-auto font-semibold outline-none focus:ring"
id="my-account-dropdown"
data-dropdown="button"
data-dropdown-target="my-account-dropdown-menu"
aria-haspopup="true"
aria-expanded="false">
<?= icon('account-circle', 'text-2xl opacity-60 mr-2') ?>
<?= user()->username ?>
<?= icon('caret-down', 'ml-auto text-2xl') ?>
</button>
<nav
id="my-account-dropdown-menu"
class="absolute z-50 flex flex-col py-2 text-black whitespace-no-wrap bg-white border-black rounded border-[3px]"
aria-labelledby="my-accountDropdown"
data-dropdown="menu"
data-dropdown-placement="bottom-end">
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
'my-account',
) ?>"><?= lang('AdminNavigation.account.my-account') ?></a>
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
'change-password',
) ?>"><?= lang('AdminNavigation.account.change-password') ?></a>
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
'logout',
) ?>"><?= lang('AdminNavigation.account.logout') ?></a>
</nav>
</header>
<aside id="admin-sidebar" class="sticky z-50 flex flex-col text-white transition duration-200 ease-in-out transform -translate-x-full border-r top-10 border-pine-900 bg-pine-800 holy-grail__sidebar md:translate-x-0">
<?php if (isset($podcast)): ?>
<?= $this->include('podcast/_sidebar') ?>
<?php else: ?>
<?= $this->include('_sidebar') ?>
<?php endif; ?>
<footer class="px-2 py-2 mx-auto text-xs text-right">
<?= lang('Common.powered_by', [
'castopod' =>
'<a class="underline hover:no-underline" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod</a> ' .
CP_VERSION,
]) ?>
</footer>
</aside>
<main class="holy-grail-main">
<header class="text-white bg-pine-900">
<main class="holy-grail__main">
<header class="bg-white">
<div class="container flex flex-wrap items-end justify-between px-2 py-10 mx-auto md:px-12 gap-y-6 gap-x-6">
<div class="flex flex-col">
<?= render_breadcrumb('text-gray-300') ?>
<?= render_breadcrumb('text-gray-800 text-xs') ?>
<div class="flex flex-wrap items-center">
<h1 class="text-3xl font-bold font-display"><?= $this->renderSection(
'pageTitle',
......@@ -44,13 +94,6 @@
<?= $this->renderSection('content') ?>
</div>
</main>
<footer class="px-2 py-2 mx-auto text-xs text-right holy-grail-footer">
<?= lang('Common.powered_by', [
'castopod' =>
'<a class="underline hover:no-underline" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod</a> ' .
CP_VERSION,
]) ?>
</footer>
<button
type="button"
id="sidebar-toggler"
......
......@@ -16,64 +16,25 @@ $navigation = [
'pages' => ['icon' => 'pages', 'items' => ['page-list', 'page-create']],
]; ?>
<a href="<?= route_to(
'admin',
) ?>" class="inline-flex items-baseline px-6 py-2 mb-2 text-2xl font-semibold font-display text-pine-700">
<?= 'castopod' . svg('castopod-logo', 'h-5 ml-1') ?>
</a>
<a href="<?= route_to(
'home',
) ?>" class="inline-flex items-center px-6 py-2 mb-2 text-sm underline outline-none hover:no-underline focus:ring">
<?= lang('AdminNavigation.go_to_website') ?>
<?= icon('external-link', 'ml-2 text-gray-500') ?>
</a>
<nav class="flex flex-col flex-1 overflow-y-auto">
<nav class="flex flex-col flex-1 py-4 overflow-y-auto gap-y-4">
<?php foreach ($navigation as $section => $data): ?>
<div class="mb-4">
<button class="inline-flex items-center w-full px-6 py-1 font-semibold text-gray-600 outline-none focus:ring" type="button">
<?= icon($data['icon'], 'text-gray-400 text-xl mr-3') ?>
<div>
<button class="inline-flex items-center w-full px-4 py-1 font-semibold outline-none focus:ring" type="button">
<?= icon($data['icon'], 'opacity-60 text-2xl mr-4') ?>
<?= lang('AdminNavigation.' . $section) ?>
</button>
<ul class="flex flex-col">
<?php foreach ($data['items'] as $item): ?>
<?php $isActive = url_is(route_to($item)); ?>
<li class="inline-flex">
<a class="w-full py-1 pl-14 pr-2 text-sm text-gray-600 outline-none hover:text-gray-900 focus:ring <?= $isActive
? 'font-semibold text-gray-900'
: '' ?>" href="<?= route_to($item) ?>"><?= lang(
'AdminNavigation.' . $item,
) ?></a>
<a class="w-full py-1 pl-14 pr-2 text-sm outline-none hover:opacity-100 focus:ring<?= $isActive
? ' font-semibold opacity-100 inline-flex items-center'
: ' opacity-75' ?>" href="<?= route_to($item) ?>"><?= ($isActive ? icon('chevron-right', 'mr-2') : '') .lang(
'AdminNavigation.' . $item,
) ?></a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endforeach; ?>
</nav>
<button
type="button"
class="inline-flex items-center w-full px-6 py-2 mt-auto border-t outline-none focus:ring"
id="my-account-dropdown"
data-dropdown="button"
data-dropdown-target="my-account-dropdown-menu"
aria-haspopup="true"
aria-expanded="false">
<?= icon('user', 'text-gray-500 mr-2') ?>
<?= user()->username ?>
<?= icon('caret-right', 'ml-auto') ?>
</button>
<nav
id="my-account-dropdown-menu"
class="absolute z-50 flex flex-col py-2 text-black whitespace-no-wrap bg-white border rounded shadow"
aria-labelledby="my-accountDropdown"
data-dropdown="menu"
data-dropdown-placement="right-end">
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
'my-account',
) ?>"><?= lang('AdminNavigation.account.my-account') ?></a>
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
'change-password',
) ?>"><?= lang('AdminNavigation.account.change-password') ?></a>
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
'logout',
) ?>"><?= lang('AdminNavigation.account.logout') ?></a>
</nav>
......@@ -2,16 +2,12 @@
$podcastNavigation = [
'dashboard' => [
'icon' => 'dashboard',
'items' => ['podcast-view', 'podcast-edit'],
'items' => ['podcast-view', 'podcast-edit', 'podcast-person-manage'],
],
'episodes' => [
'icon' => 'mic',
'items' => ['episode-list', 'episode-create'],
],
'persons' => [
'icon' => 'folder-user',
'items' => ['podcast-person-manage'],
],
'analytics' => [
'icon' => 'line-chart',
'items' => [
......@@ -38,82 +34,45 @@ $podcastNavigation = [
],
]; ?>
<a href="<?= route_to(
'admin',
) ?>" class="inline-flex items-center px-4 py-2 border-b">
<?= icon('arrow-left', 'mr-4 text-xl') ?>
<span class="inline-flex items-baseline text-2xl font-semibold font-display text-pine-700"> <?= 'castopod' .
svg('castopod-logo', 'h-5 ml-1') ?></span>
</a>
<div class="flex items-center border-b">
<div class="flex items-center px-4 py-2 border-b border-pine-900">
<img
src="<?= $podcast->image->thumbnail_url ?>"
alt="<?= $podcast->title ?>"
class="object-cover w-16 h-16"
class="object-cover w-16 h-16 rounded"
/>
<div class="flex flex-col items-start flex-1 w-48 px-2">
<span class="w-40 text-sm font-semibold truncate" title="<?= $podcast->title ?>"><?= $podcast->title ?></span>
<span class="w-full font-semibold truncate" title="<?= $podcast->title ?>"><?= $podcast->title ?></span>
<a href="<?= route_to(
'podcast-activity',
$podcast->handle,
) ?>" class="inline-flex items-center text-xs underline outline-none hover:no-underline focus:ring"
) ?>" class="inline-flex items-center text-sm outline-none hover:underline focus:ring"
data-toggle="tooltip" data-placement="bottom" title="<?= lang(
'PodcastNavigation.go_to_page',
) ?>">@<?= $podcast->handle ?>
<?= icon('external-link', 'ml-1 text-gray-500') ?>
<?= icon('external-link', 'ml-1 opacity-60') ?>
</a>
</div>
</div>
<nav class="flex flex-col flex-1 py-6 overflow-y-auto">
<nav class="flex flex-col flex-1 py-4 overflow-y-auto gap-y-4">
<?php foreach ($podcastNavigation as $section => $data): ?>
<div class="mb-4">
<button class="inline-flex items-center w-full px-6 py-1 outline-none focus:ring" type="button">
<?= icon($data['icon'], 'text-gray-400 text-xl mr-3') .
<div>
<button class="inline-flex items-center w-full px-4 py-1 font-semibold outline-none focus:ring" type="button">
<?= icon($data['icon'], 'opacity-60 text-2xl mr-4') .
lang('PodcastNavigation.' . $section) ?>
</button>
<ul class="flex flex-col">
<?php foreach ($data['items'] as $item): ?>
<?php $isActive = url_is(route_to($item, $podcast->id)); ?>
<li class="inline-flex">
<a class="w-full py-1 pl-14 pr-2 text-sm text-gray-600 outline-none hover:text-gray-900 focus:ring <?= $isActive
? 'font-semibold text-gray-900'
: '' ?>" href="<?= route_to(
$item,
$podcast->id,
) ?>"><?= lang('PodcastNavigation.' . $item) ?></a>
<a class="w-full py-1 pl-14 pr-2 text-sm outline-none hover:opacity-100 focus:ring <?= $isActive
? 'font-semibold opacity-100 inline-flex items-center'
: 'opacity-75' ?>" href="<?= route_to(
$item,
$podcast->id,
) ?>"><?= ($isActive ? icon('chevron-right', 'mr-2') : '') .lang('PodcastNavigation.' . $item) ?></a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endforeach; ?>
</nav>
<button
type="button"
class="inline-flex items-center w-full px-6 py-2 mt-auto border-t outline-none focus:ring"
id="my-account-dropdown"
data-dropdown="button"
data-dropdown-target="my-account-dropdown-menu"
aria-haspopup="true"
aria-expanded="false">
<?= icon('user', 'text-gray-500 mr-2') ?>
<?= user()->username ?>
<?= icon('caret-right', 'ml-auto') ?>
</button>
<nav
id="my-account-dropdown-menu"
class="flex flex-col py-2 text-black whitespace-no-wrap bg-white border rounded shadow"
aria-labelledby="my-account-dropdown"
data-dropdown="menu"
data-dropdown-placement="right-end">
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
'my-account',
) ?>"><?= lang('AdminNavigation.account.my-account') ?></a>
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
'change-password',
) ?>"><?= lang('AdminNavigation.account.change-password') ?></a>
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
'logout',
) ?>"><?= lang('AdminNavigation.account.logout') ?></a>
</nav>
</div>
......@@ -10,9 +10,9 @@
</a>
</header>
<?php if ($episodes): ?>
<div class="flex p-2 overflow-x-auto gap-x-6">
<div class="flex p-2 overflow-x-auto gap-x-6 snap snap-x snap-proximity">
<?php foreach ($episodes as $episode): ?>
<article class="flex flex-col flex-shrink-0 flex-1 w-full min-w-[12rem] overflow-hidden bg-white border shadow rounded-xl">
<article class="snap-center flex flex-col flex-shrink-0 flex-1 w-full min-w-[12rem] max-w-[17rem] overflow-hidden bg-white border-2 border-pine-100 rounded-xl">
<div class="relative">
<div class=""></div>
<?= publication_pill(
......
......@@ -27,7 +27,7 @@
<div class="grid gap-4 grid-cols-podcasts">
<?php if ($podcasts !== null): ?>
<?php foreach ($podcasts as $podcast): ?>
<article class="h-full overflow-hidden bg-white border shadow rounded-xl">
<article class="h-full overflow-hidden bg-white border-2 border-pine-100 rounded-xl">
<img
alt="<?= $podcast->title ?>"
src="<?= $podcast->image
......
......@@ -8,10 +8,6 @@
<?= $podcast->title ?>
<?= $this->endSection() ?>
<?= $this->section('headerLeft') ?>
<?= location_link($podcast->location, 'ml-4 text-sm') ?>
<?= $this->endSection() ?>
<?= $this->section('headerRight') ?>
<?= button(
lang('Podcast.edit'),
......
Supports Markdown
0% or .
You are about to add