mirror of
https://github.com/Einundzwanzig-Podcast/einundzwanzig-portal.git
synced 2025-12-11 06:46:47 +00:00
front-end article submission form added
This commit is contained in:
Binary file not shown.
@@ -24,6 +24,10 @@ docker run --rm \
|
||||
|
||||
```./vendor/bin/sail artisan migrate:fresh --seed```
|
||||
|
||||
### Laravel storage link
|
||||
|
||||
```./vendor/bin/sail artisan storage:link```
|
||||
|
||||
#### Install node dependencies
|
||||
|
||||
```vendor/bin/sail yarn install```
|
||||
|
||||
84
app/Http/Controllers/Api/LecturerController.php
Normal file
84
app/Http/Controllers/Api/LecturerController.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Lecturer;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LecturerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
return Lecturer::query()
|
||||
->select('id', 'name',)
|
||||
->orderBy('name')
|
||||
->when(
|
||||
$request->search,
|
||||
fn(Builder $query) => $query
|
||||
->where('name', 'like', "%{$request->search}%")
|
||||
)
|
||||
->when(
|
||||
$request->exists('selected'),
|
||||
fn(Builder $query) => $query->whereIn('id', $request->input('selected', [])),
|
||||
fn(Builder $query) => $query->limit(10)
|
||||
)
|
||||
->get()
|
||||
->map(function (Lecturer $lecturer) {
|
||||
$lecturer->image = $lecturer->getFirstMediaUrl('avatar', 'thumb');
|
||||
|
||||
return $lecturer;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\Lecturer $lecturer
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Lecturer $lecturer)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Models\Lecturer $lecturer
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, Lecturer $lecturer)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Lecturer $lecturer
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Lecturer $lecturer)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,11 @@ class ArticleOverview extends Component
|
||||
])
|
||||
->where('type', 'markdown_article')
|
||||
->when(app()->environment('production'),
|
||||
fn($query) => $query->whereHas('createdBy.roles',
|
||||
fn($query) => $query->where('roles.name', 'news-editor')))
|
||||
fn($query) => $query
|
||||
->whereHas('createdBy.roles',
|
||||
fn($query) => $query->where('roles.name', 'news-editor'))
|
||||
)
|
||||
->where('approved', true)
|
||||
->orderByDesc('created_at')
|
||||
->get(),
|
||||
])->layout('layouts.app', [
|
||||
|
||||
79
app/Http/Livewire/News/Form/NewsArticleForm.php
Normal file
79
app/Http/Livewire/News/Form/NewsArticleForm.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\News\Form;
|
||||
|
||||
use App\Models\LibraryItem;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
|
||||
class NewsArticleForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
public ?LibraryItem $libraryItem = null;
|
||||
public $image;
|
||||
public $currentImage = 0;
|
||||
public $images;
|
||||
public $imagesCloned = [];
|
||||
public array $temporaryUrls = [];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'image' => 'required|mimes:jpeg,png,jpg,gif|max:10240',
|
||||
|
||||
'libraryItem.lecturer_id' => 'required',
|
||||
'libraryItem.name' => 'required',
|
||||
'libraryItem.type' => 'required',
|
||||
'libraryItem.language_code' => 'required',
|
||||
'libraryItem.value' => 'required',
|
||||
'libraryItem.subtitle' => 'required',
|
||||
'libraryItem.excerpt' => 'required',
|
||||
'libraryItem.main_image_caption' => 'required',
|
||||
'libraryItem.read_time' => 'required',
|
||||
'libraryItem.approved' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if ($this->libraryItem === null) {
|
||||
$this->libraryItem = new LibraryItem([
|
||||
'type' => 'markdown_article',
|
||||
'value' => '',
|
||||
'read_time' => 1,
|
||||
'language_code' => 'de',
|
||||
'approved' => auth()
|
||||
->user()
|
||||
->hasRole('news-editor'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedImages($value)
|
||||
{
|
||||
$clonedImages = collect($this->imagesCloned);
|
||||
$clonedImages = $clonedImages->push($value);
|
||||
$this->imagesCloned = $clonedImages->toArray();
|
||||
|
||||
$temporaryUrls = collect($this->temporaryUrls);
|
||||
$temporaryUrls = $temporaryUrls->push($value->temporaryUrl());
|
||||
$this->temporaryUrls = $temporaryUrls->toArray();
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate();
|
||||
$this->libraryItem->save();
|
||||
|
||||
$this->libraryItem->addMedia($this->image)
|
||||
->toMediaCollection('main');
|
||||
|
||||
return to_route('article.overview', ['country' => null]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.news.form.news-article-form');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('library_items', function (Blueprint $table) {
|
||||
$table->boolean('approved')
|
||||
->default(true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('library_items', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
};
|
||||
12
ide.json
Normal file
12
ide.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "http://laravel-ide.com/schema/laravel-ide-v1.json",
|
||||
"blade": {
|
||||
"components": {
|
||||
"viewPaths": [
|
||||
{
|
||||
"path": "resources/views/vendor/wireui/components"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
47
public/dist/filepond-plugin-image-edit.css
vendored
Normal file
47
public/dist/filepond-plugin-image-edit.css
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/*!
|
||||
* FilePondPluginImageEdit 1.6.3
|
||||
* Licensed under MIT, https://opensource.org/licenses/MIT/
|
||||
* Please visit https://pqina.nl/filepond/ for details.
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
.filepond--action-edit-item.filepond--action-edit-item {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
padding: 0.1875em;
|
||||
}
|
||||
|
||||
.filepond--action-edit-item.filepond--action-edit-item[data-align*='center'] {
|
||||
margin-left: -0.1875em;
|
||||
}
|
||||
|
||||
.filepond--action-edit-item.filepond--action-edit-item[data-align*='bottom'] {
|
||||
margin-bottom: -0.1875em;
|
||||
}
|
||||
|
||||
.filepond--action-edit-item-alt {
|
||||
border: none;
|
||||
line-height: inherit;
|
||||
background: transparent;
|
||||
font-family: inherit;
|
||||
color: inherit;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
margin: 0 0 0 0.25em;
|
||||
pointer-events: all;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.filepond--action-edit-item-alt svg {
|
||||
width: 1.3125em;
|
||||
height: 1.3125em;
|
||||
}
|
||||
|
||||
.filepond--action-edit-item-alt span {
|
||||
font-size: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
.filepond--root[data-style-panel-layout~='circle'] .filepond--action-edit-item {
|
||||
opacity: 1 !important;
|
||||
visibility: visible !important;
|
||||
}
|
||||
1047
public/dist/filepond.css
vendored
Normal file
1047
public/dist/filepond.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,8 @@
|
||||
import './bootstrap'
|
||||
|
||||
// Import the plugin styles
|
||||
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css';
|
||||
|
||||
import Alpine from 'alpinejs'
|
||||
import collapse from '@alpinejs/collapse'
|
||||
import intersect from '@alpinejs/intersect'
|
||||
|
||||
@@ -583,7 +583,7 @@
|
||||
"Changes": "",
|
||||
"Exception": "",
|
||||
"Action Happened At": "",
|
||||
"Action": "",
|
||||
"Action": "Aktion",
|
||||
"CSV (.csv)": "",
|
||||
"Excel (.xlsx)": "",
|
||||
"Filename": "",
|
||||
@@ -634,8 +634,8 @@
|
||||
"Here you can see all events of :name.": "Hier siehst du alle Kurs-Termine von :name.",
|
||||
"This is the introduction text that is shown on the landing page.": "Das ist der Einführungstext, der auf der Landing-Page angezeigt wird.",
|
||||
"This is the subtitle on the landing page.": "Das ist der Untertitel auf der Landing-Page des Dozenten.",
|
||||
"Subtitle": "Untertitel auf der Landing-Page",
|
||||
"Intro": "Intro auf der Landing-Page",
|
||||
"Subtitle": "Untertitel",
|
||||
"Intro": "Intro",
|
||||
"This lecturer has not yet written an introduction.": "Dieser Dozent hat noch keine Einführung geschrieben.",
|
||||
"If your city is not listed, please create it first.": "Wenn deine Stadt nicht aufgeführt ist, erstelle sie bitte zuerst.",
|
||||
"You get a point when you log in.": "Du bekommst einen Punkt, wenn du dich einloggst.",
|
||||
@@ -731,5 +731,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "Auf dieser Karte kannst du sehen, wo sich georangepillte Bücher befinden. Du kannst auch auf einen Marker klicken, um zum Suchergebnis zu gelangen.",
|
||||
"Community": "Community",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "Dies ist die Community, der das Meetup angehört. Wenn eine Community nicht aufgeführt ist, kontaktiere bitte den Administrator.",
|
||||
"World Map": "Weltkarte"
|
||||
"World Map": "Weltkarte",
|
||||
"Submit news articles": "Artikel einreichen",
|
||||
"News Article": "News-Artikel",
|
||||
"Author": "Autor",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "Zum Beispiel: Foto von Timothy Vollmer\/ CC BY",
|
||||
"Article as Markdown": "Artikel als Markdown",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": "Für Bilder in Markdown, benutze bitte z.B. Imgur oder einen anderen Anbieter."
|
||||
}
|
||||
|
||||
@@ -726,5 +726,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "",
|
||||
"Community": "",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "",
|
||||
"World Map": ""
|
||||
"World Map": "",
|
||||
"Submit news articles": "",
|
||||
"News Article": "",
|
||||
"Author": "",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "",
|
||||
"Article as Markdown": "",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": ""
|
||||
}
|
||||
@@ -726,5 +726,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "",
|
||||
"Community": "",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "",
|
||||
"World Map": ""
|
||||
"World Map": "",
|
||||
"Submit news articles": "",
|
||||
"News Article": "",
|
||||
"Author": "",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "",
|
||||
"Article as Markdown": "",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": ""
|
||||
}
|
||||
@@ -727,5 +727,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "",
|
||||
"Community": "",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "",
|
||||
"World Map": ""
|
||||
"World Map": "",
|
||||
"Submit news articles": "",
|
||||
"News Article": "",
|
||||
"Author": "",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "",
|
||||
"Article as Markdown": "",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": ""
|
||||
}
|
||||
@@ -727,5 +727,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "",
|
||||
"Community": "",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "",
|
||||
"World Map": ""
|
||||
"World Map": "",
|
||||
"Submit news articles": "",
|
||||
"News Article": "",
|
||||
"Author": "",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "",
|
||||
"Article as Markdown": "",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": ""
|
||||
}
|
||||
@@ -727,5 +727,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "",
|
||||
"Community": "",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "",
|
||||
"World Map": ""
|
||||
"World Map": "",
|
||||
"Submit news articles": "",
|
||||
"News Article": "",
|
||||
"Author": "",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "",
|
||||
"Article as Markdown": "",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": ""
|
||||
}
|
||||
@@ -727,5 +727,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "",
|
||||
"Community": "",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "",
|
||||
"World Map": ""
|
||||
"World Map": "",
|
||||
"Submit news articles": "",
|
||||
"News Article": "",
|
||||
"Author": "",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "",
|
||||
"Article as Markdown": "",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": ""
|
||||
}
|
||||
@@ -727,5 +727,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "",
|
||||
"Community": "",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "",
|
||||
"World Map": ""
|
||||
"World Map": "",
|
||||
"Submit news articles": "",
|
||||
"News Article": "",
|
||||
"Author": "",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "",
|
||||
"Article as Markdown": "",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": ""
|
||||
}
|
||||
@@ -727,5 +727,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "",
|
||||
"Community": "",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "",
|
||||
"World Map": ""
|
||||
"World Map": "",
|
||||
"Submit news articles": "",
|
||||
"News Article": "",
|
||||
"Author": "",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "",
|
||||
"Article as Markdown": "",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": ""
|
||||
}
|
||||
@@ -701,5 +701,11 @@
|
||||
"On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.": "",
|
||||
"Community": "",
|
||||
"This is the community that the meetup belongs to. If a community is not listed, please contact the administrator.": "",
|
||||
"World Map": ""
|
||||
"World Map": "",
|
||||
"Submit news articles": "",
|
||||
"News Article": "",
|
||||
"Author": "",
|
||||
"Ex: Photo by Timothy Vollmer\/ CC BY": "",
|
||||
"Article as Markdown": "",
|
||||
"For images in Markdown, please use eg. Imgur or another provider.": ""
|
||||
}
|
||||
30
resources/views/components/input/filepond.blade.php
Normal file
30
resources/views/components/input/filepond.blade.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<div
|
||||
wire:ignore
|
||||
x-data
|
||||
x-init="
|
||||
FilePond.registerPlugin(
|
||||
FilePondPluginImagePreview,
|
||||
FilePondPluginImageExifOrientation,
|
||||
FilePondPluginFileValidateSize,
|
||||
FilePondPluginImageEdit
|
||||
);
|
||||
FilePond.setOptions({
|
||||
labelIdle: '{{ 'Drag & Drop Deiner Dateien oder <span class="filepond--label-action"> in Ordner suchen </span>' }}',
|
||||
allowMultiple: {{ isset($attributes['multiple']) ? 'true' : 'false' }},
|
||||
server: {
|
||||
process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
|
||||
@this.upload('{{ $attributes['wire:model'] }}', file, load, error, progress)
|
||||
},
|
||||
revert: (filename, load) => {
|
||||
@this.removeUpload('{{ $attributes['wire:model'] }}', filename, load)
|
||||
},
|
||||
load: (source, load, error, progress, abort, headers) => {
|
||||
@this.load('{{ $attributes['wire:model'] }}', load, error, progress, abort, headers)
|
||||
},
|
||||
},
|
||||
});
|
||||
FilePond.create($refs.input);
|
||||
"
|
||||
>
|
||||
<input type="file" x-ref="input" name="{{ $attributes['name'] }}">
|
||||
</div>
|
||||
60
resources/views/components/input/simple-mde.blade.php
Normal file
60
resources/views/components/input/simple-mde.blade.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<div
|
||||
wire:ignore
|
||||
x-data="{
|
||||
value: @entangle($attributes->wire('model')).defer,
|
||||
init() {
|
||||
let editor = new EasyMDE({
|
||||
element: this.$refs.editor,
|
||||
lineNumbers: true,
|
||||
uploadImage: false,
|
||||
{{-- imageMaxSize: 1024 * 1024 * 10,--}}
|
||||
{{-- imageUploadFunction: (file, onSuccess, onError) => {--}}
|
||||
{{-- @this.upload('images', file, (uploadedFilename) => {--}}
|
||||
{{-- const currentImage = @this.get('currentImage');--}}
|
||||
{{-- const temporaryUrls = @this.get('temporaryUrls');--}}
|
||||
{{-- onSuccess(temporaryUrls[currentImage]);--}}
|
||||
{{-- @this.set('currentImage', currentImage + 1)--}}
|
||||
{{-- }, () => {--}}
|
||||
{{-- // Error callback.--}}
|
||||
{{-- }, (event) => {--}}
|
||||
{{-- // Progress callback.--}}
|
||||
{{-- // event.detail.progress contains a number between 1 and 100 as the upload progresses.--}}
|
||||
{{-- })--}}
|
||||
{{-- },--}}
|
||||
showIcons: [
|
||||
'heading',
|
||||
'heading-smaller',
|
||||
'heading-bigger',
|
||||
'heading-1',
|
||||
'heading-2',
|
||||
'heading-3',
|
||||
'code',
|
||||
'table',
|
||||
'quote',
|
||||
'strikethrough',
|
||||
'unordered-list',
|
||||
'ordered-list',
|
||||
'clean-block',
|
||||
'horizontal-rule',
|
||||
'undo',
|
||||
'redo',
|
||||
//'upload-image',
|
||||
],
|
||||
})
|
||||
|
||||
editor.value(this.value)
|
||||
|
||||
editor.codemirror.on('change', () => {
|
||||
this.value = editor.value()
|
||||
})
|
||||
},
|
||||
}"
|
||||
class="w-full"
|
||||
>
|
||||
<textarea x-ref="editor"></textarea>
|
||||
<style>
|
||||
.EasyMDEContainer {
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
@@ -13,8 +13,6 @@
|
||||
<!-- Fonts -->
|
||||
@googlefonts
|
||||
<!-- Scripts -->
|
||||
<link rel="stylesheet" href="{{ asset('vendor/jvector/jquery-jvectormap-2.0.5.css') }}" type="text/css"
|
||||
media="screen"/>
|
||||
<script src="{{ asset('dist/jquery.js') }}"></script>
|
||||
<script src="{{ asset('vendor/jvector/jquery-jvectormap-2.0.5.min.js') }}"></script>
|
||||
<script src="{{ asset('vendor/jvector/maps/world-mill.js') }}"></script>
|
||||
@@ -38,6 +36,9 @@
|
||||
<x-comments::scripts/>
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" href="{{ asset('vendor/jvector/jquery-jvectormap-2.0.5.css') }}" type="text/css"
|
||||
media="screen"/>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css">
|
||||
<x-comments::styles/>
|
||||
<x-embed-styles />
|
||||
@livewireStyles
|
||||
@@ -111,5 +112,6 @@
|
||||
@livewireScripts
|
||||
<!-- ProductLift SDK - Include it only once -->
|
||||
<script defer src="https://bitcoin.productlift.dev/widgets_sdk"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
<div>
|
||||
<img class="h-32 object-cover" src="{{ asset('img/einundzwanzig-news-colored.png') }}" alt="">
|
||||
</div>
|
||||
<div>
|
||||
<x-button
|
||||
:href="route('news.form')"
|
||||
primary>
|
||||
<i class="fa fa-thin fa-plus"></i>
|
||||
{{ __('Submit news articles') }}
|
||||
</x-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mx-auto mt-2 grid max-w-lg gap-5 lg:max-w-none lg:grid-cols-3">
|
||||
|
||||
|
||||
101
resources/views/livewire/news/form/news-article-form.blade.php
Normal file
101
resources/views/livewire/news/form/news-article-form.blade.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<div class="container p-4 mx-auto bg-21gray my-2">
|
||||
|
||||
<div class="pb-5 flex flex-row justify-between">
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-200">{{ __('News Article') }}</h3>
|
||||
<div class="flex flex-row space-x-2 items-center">
|
||||
<div>
|
||||
<x-button :href="route('article.overview', ['country' => null])">
|
||||
<i class="fa fa-thin fa-arrow-left"></i>
|
||||
{{ __('Back') }}
|
||||
</x-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="space-y-8 divide-y divide-gray-700 pb-24">
|
||||
<div class="space-y-8 divide-y divide-gray-700 sm:space-y-5">
|
||||
<div class="mt-6 sm:mt-5 space-y-6 sm:space-y-5">
|
||||
|
||||
<x-input.group :for="md5('libraryItem.lecturer_id')" :label="__('Author')">
|
||||
<x-select
|
||||
:clearable="false"
|
||||
wire:model="libraryItem.lecturer_id"
|
||||
:searchable="true"
|
||||
:async-data="[
|
||||
'api' => route('api.lecturers.index'),
|
||||
'method' => 'GET', // default is GET
|
||||
]"
|
||||
:template="[
|
||||
'name' => 'user-option',
|
||||
'config' => ['src' => 'image']
|
||||
]"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
/>
|
||||
</x-input.group>
|
||||
|
||||
<x-input.group :for="md5('image')" :label="__('Main picture')">
|
||||
<div class="py-4">
|
||||
@if ($image)
|
||||
<div class="text-gray-200">{{ __('Preview') }}:</div>
|
||||
<img class="h-48 object-contain" src="{{ $image->temporaryUrl() }}">
|
||||
@endif
|
||||
</div>
|
||||
<input class="text-gray-200" type="file" wire:model="image">
|
||||
@error('image') <span class="text-red-500">{{ $message }}</span> @enderror
|
||||
</x-input.group>
|
||||
|
||||
<x-input.group :for="md5('libraryItem.main_image_caption')" :label="__('Main image caption')">
|
||||
<x-input autocomplete="off" wire:model.debounce="libraryItem.main_image_caption"
|
||||
:placeholder="__('Main image caption')"
|
||||
:cornerHint="__('Ex: Photo by Timothy Vollmer/ CC BY')"/>
|
||||
</x-input.group>
|
||||
|
||||
<x-input.group :for="md5('libraryItem.name')" :label="__('Title')">
|
||||
<x-input autocomplete="off" wire:model.debounce="libraryItem.name"
|
||||
:placeholder="__('Title')"/>
|
||||
</x-input.group>
|
||||
|
||||
<x-input.group :for="md5('libraryItem.subtitle')" :label="__('Subtitle')">
|
||||
<x-input autocomplete="off" wire:model.debounce="libraryItem.subtitle"
|
||||
:placeholder="__('Subtitle')"/>
|
||||
</x-input.group>
|
||||
|
||||
<x-input.group :for="md5('libraryItem.excerpt')" :label="__('Excerpt')">
|
||||
<x-textarea autocomplete="off" wire:model.debounce="libraryItem.excerpt"
|
||||
:placeholder="__('Excerpt')"/>
|
||||
</x-input.group>
|
||||
|
||||
<x-input.group :for="md5('libraryItem.language_code')" :label="__('Language Code')">
|
||||
<x-select
|
||||
:clearable="false"
|
||||
wire:model="libraryItem.language_code"
|
||||
:options="collect(config('languages.languages'))->map(fn($value, $key) => ['id' => $key, 'name' => $value])->toArray()"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
/>
|
||||
</x-input.group>
|
||||
|
||||
<x-input.group :for="md5('libraryItem.value')" :label="__('Article as Markdown')">
|
||||
<span
|
||||
class="text-amber-500 text-xs py-2">{{ __('For images in Markdown, please use eg. Imgur or another provider.') }}</span>
|
||||
<x-input.simple-mde wire:model.defer="libraryItem.value"/>
|
||||
@error('libraryItem.value') <span class="text-red-500 py-2">{{ $message }}</span> @enderror
|
||||
</x-input.group>
|
||||
|
||||
<x-input.group :for="md5('libraryItem.read_time')" :label="__('Time to read')">
|
||||
<x-inputs.number min="1" autocomplete="off" wire:model.debounce="libraryItem.read_time"
|
||||
:placeholder="__('Time to read')" :hint="__('How many minutes to read?')"/>
|
||||
</x-input.group>
|
||||
|
||||
<x-input.group :for="md5('meetupEvent.link')" label="">
|
||||
<x-button primary wire:click="save">
|
||||
<i class="fa fa-thin fa-save"></i>
|
||||
{{ __('Save') }}
|
||||
</x-button>
|
||||
</x-input.group>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -28,6 +28,7 @@ Route::middleware([])
|
||||
->group(function () {
|
||||
Route::resource('countries', \App\Http\Controllers\Api\CountryController::class);
|
||||
Route::resource('meetup', \App\Http\Controllers\Api\MeetupController::class);
|
||||
Route::resource('lecturers', \App\Http\Controllers\Api\LecturerController::class);
|
||||
Route::resource('languages', \App\Http\Controllers\Api\LanguageController::class);
|
||||
Route::get('meetups', function () {
|
||||
return \App\Models\Meetup::query()
|
||||
|
||||
@@ -23,6 +23,17 @@ Route::middleware([])
|
||||
->get('/news', \App\Http\Livewire\News\ArticleOverview::class)
|
||||
->name('article.overview');
|
||||
|
||||
/*
|
||||
* News
|
||||
* */
|
||||
Route::middleware([])
|
||||
->as('news.')
|
||||
->prefix('/news')
|
||||
->group(function () {
|
||||
Route::get('/form/{libraryItem?}', \App\Http\Livewire\News\Form\NewsArticleForm::class)
|
||||
->name('form');
|
||||
});
|
||||
|
||||
Route::middleware([])
|
||||
->get('/news/{libraryItem:slug}', \App\Http\Livewire\News\InternArticleView::class)
|
||||
->name('article.view');
|
||||
|
||||
Reference in New Issue
Block a user