]> gitweb.hamatoma.de Git - gadeku.git/commitdiff
V 0.2.0 Module Article
authorHamatoma <author@hamatoma.de>
Tue, 23 Apr 2024 20:13:00 +0000 (22:13 +0200)
committerHamatoma <author@hamatoma.de>
Tue, 23 Apr 2024 20:13:00 +0000 (22:13 +0200)
- new: Module Article

25 files changed:
CHANGELOG.md
app/Helpers/MediaWiki.php [new symlink]
app/Helpers/TextProcessor.php
app/Helpers/dummy.html [new file with mode: 0644]
app/Http/Controllers/ArticleController.php [new file with mode: 0644]
app/Http/Controllers/ChapterController.php
app/Models/Article.php [new file with mode: 0644]
composer.lock
database/migrations/2024_04_21_092103_create_articles_table.php [new file with mode: 0644]
database/seeders/MenuitemArticleSeeder.php [new file with mode: 0644]
database/seeders/SPropertyArticleSeeder.php [new file with mode: 0644]
lang/de_DE.json
missing.seeders
resources/lang/sources/gadeku.de.json
resources/views/article/create.blade.php [new file with mode: 0644]
resources/views/article/edit.blade.php [new file with mode: 0644]
resources/views/article/index.blade.php [new file with mode: 0644]
resources/views/article/show.blade.php [new file with mode: 0644]
resources/views/article/showpretty.blade.php [new file with mode: 0644]
resources/views/chapter/edit.blade.php
resources/views/create.blade.php [new file with mode: 0644]
resources/views/edit.blade.php [new file with mode: 0644]
resources/views/index.blade.php [new file with mode: 0644]
resources/views/show.blade.php [new file with mode: 0644]
routes/web.php

index 7addaf4f87c1bcfec6165ef3787d08dab64b9b0b..77e2e0aa21806aef8818be4e2c910b2992c9b59a 100644 (file)
@@ -1,3 +1,8 @@
+# V 0.2.0 Module Article
+
+## Added
+- Module Article
+
 # V 0.1.9 Korrektur missing.seeders
 
 - missing.seeders: falsche Konfiguration (ohne "Seeder")
diff --git a/app/Helpers/MediaWiki.php b/app/Helpers/MediaWiki.php
new file mode 120000 (symlink)
index 0000000..d83989f
--- /dev/null
@@ -0,0 +1 @@
+../../vendor/hamatoma/laraknife/resources/helpers/MediaWiki.php
\ No newline at end of file
index e6ff8bbdf6733995bebff082f664733696a3ffed..f7478a53616cba005688e81e41335f66d10e0fd7 100644 (file)
@@ -3,43 +3,23 @@ namespace App\Helpers;
 
 class TextProcessor
 {
-    public static function markupToHtml(string $text): string
+    public static function expandStarItems(string $text): string
     {
-        $rc = '';
-        $pos = 0;
-        while (true) {
-            if (($end = strpos($text, "\r\n\r\n", $pos)) !== false) {
-                $text2 = substr($text, $pos, $end);
-                $rc .= self::sentenceToHtml($text2);
-                $pos = $end + 4;
-            } else {
-                $text2 = substr($text, $pos);
-                if (!empty(trim($text2))) {
-                    $rc .= self::sentenceToHtml($text2);
-                }
-                break;
-            }
-        }
-        return $rc;
-    }
-    public static function sentenceToHtml(string $text): string
-    {
-        $text2 = preg_replace_callback(
-            '/%trans\((.*?)(\|.*?)?\)%/',
-            function ($hit) {
-                $text = $hit[1];
-                $info = count($hit) == 2 ? $text : substr($hit[2], 1);
-                $rc = "<b data-toggle=\"tooltip\" data-placement=\"top\" title=\"$info\">$text</b>";
-                return $rc;
-            },
+        $rc = preg_replace(
+            [
+                '/\*(\w[^*]+\w)\*/',
+                '/\*<(\w[^*]+\w)>\*/',
+                '/\*-(\w[^*]+\w)-\*/',
+                '/\*\+(\w[^*]+\w)\+\*/'
+            ],
+            [
+                '%trans($1)%',
+                '%field($1)%',
+                '%del($1)%',
+                '%add($1)%'
+            ],
             $text
         );
-        $rc = "<p>$text2</p>\n";
-        return $rc;
-    }
-    public static function starToTrans(string $text): string
-    {
-        $rc = preg_replace('/\*(\w[^*]+\w)\*/', '%trans($1)%', $text);
         return $rc;
     }
 }
diff --git a/app/Helpers/dummy.html b/app/Helpers/dummy.html
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/app/Http/Controllers/ArticleController.php b/app/Http/Controllers/ArticleController.php
new file mode 100644 (file)
index 0000000..6f02c0b
--- /dev/null
@@ -0,0 +1,288 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\File;
+use App\Models\Module;
+use App\Helpers\Helper;
+use App\Models\Article;
+use App\Helpers\DbHelper;
+use App\Models\SProperty;
+use App\Helpers\MediaWiki;
+use App\Helpers\FileHelper;
+use App\Helpers\Pagination;
+use App\Helpers\ViewHelper;
+use Illuminate\Http\Request;
+use App\Helpers\TextProcessor;
+use App\Helpers\ContextLaraKnife;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Route;
+use Illuminate\Support\Facades\Validator;
+
+class ArticleController extends Controller
+{
+    private function asPreview(Article $article): string
+    {
+        $type = $article->markup_scope;
+        switch ($type) {
+            case 1122: // mediawiki
+                $wiki = new MediaWiki();
+                $text = $wiki->ToHtml($article->contents);
+                break;
+            case 1223: // html
+                $text = $article->contents;
+                break;
+            default:
+            case 1121: // plain text
+                $text = '<p>' . str_replace('/\r?\n/', "</p>\n<p>", $article->contents) . "</p>";
+                break;
+        }
+        return $text;
+    }
+    /**
+     * Show the form for creating a new resource.
+     */
+    public function create(Request $request)
+    {
+        if ($request->btnSubmit === 'btnCancel') {
+            $rc = redirect('/article-index');
+        } else {
+            $fields = $request->all();
+            if (count($fields) === 0) {
+                $fields = [
+                    'title' => '',
+                    'contents' => '',
+                    'info' => '',
+                    'articletype_scope' => '',
+                    'markup_scope' => '1122',
+                    'order' => '0',
+                    'audio_id' => ''
+                ];
+            }
+            $optionsArticletype = SProperty::optionsByScope('articletype', $fields['articletype_scope'], '-');
+            $optionsMarkup = SProperty::optionsByScope('markup', $fields['markup_scope'], '-');
+            $context = new ContextLaraKnife($request, $fields);
+            $rc = view('article.create', [
+                'context' => $context,
+                'optionsArticletype' => $optionsArticletype,
+                'optionsMarkup' => $optionsMarkup,
+            ]);
+        }
+        return $rc;
+    }
+    /**
+     * Show the form for editing the specified resource.
+     */
+    public function edit(Article $article, Request $request)
+    {
+        if ($request->btnSubmit === 'btnCancel') {
+            $rc = redirect('/article-index');
+        } elseif ($request->btnSubmit === 'btnStore') {
+            $rc = $this->update($article, $request);
+        } else {
+            $fields = $request->all();
+            if (count($fields) === 0) {
+                $fields = [
+                    'title' => $article->title,
+                    'contents' => $article->contents,
+                    'info' => $article->info,
+                    'articletype_scope' => $article->articletype_scope,
+                    'markup_scope' => $article->markup_scope,
+                    'order' => $article->order ?? '0',
+                    'audio_id' => $article->audio_id
+                ];
+            } else {
+                $fields['articletype_scope'] = $article->articletype_scope;
+                $fields['markup_scope'] = $article->markup_scope;
+            }
+            $optionsArticletype = SProperty::optionsByScope('articletype', $article->articletype_scope, '');
+            $optionsMarkup = SProperty::optionsByScope('markup', $article->markup_scope, '');
+            $fields = $request->btnSubmit !== 'btnPreview' ? null : ['preview' => $this->asPreview($article)];
+            $context = new ContextLaraKnife($request, $fields, $article);
+            $rc = view('article.edit', [
+                'context' => $context,
+                'optionsArticletype' => $optionsArticletype,
+                'optionsMarkup' => $optionsMarkup,
+            ]);
+        }
+        return $rc;
+    }
+    /**
+     * Remove the specified resource from storage.
+     */
+    public function destroy(Article $article, Request $request)
+    {
+        if ($request->btnSubmit === 'btnDelete') {
+            $article->delete();
+        }
+        return redirect('/article-index');
+    }
+    /**
+     * Display the database records of the resource.
+     */
+    public function index(Request $request)
+    {
+        if ($request->btnSubmit === 'btnNew') {
+            return redirect('/article-create');
+        } else {
+            $sql = "
+SELECT t0.*,
+  t1.name as articletype_scope,
+  t2.name as markup_scope,
+  t3.name as audio_id
+FROM articles t0
+LEFT JOIN sproperties t1 ON t1.id=t0.articletype_scope
+LEFT JOIN sproperties t2 ON t2.id=t0.markup_scope
+LEFT JOIN sproperties t3 ON t3.id=t0.audio_id
+";
+            $parameters = [];
+            $fields = $request->all();
+            if (count($fields) == 0) {
+                $fields = [
+                    'articletype' => '',
+                    'markup' => '',
+                    'text' => '',
+                    '_sortParams' => 'title:asc;id:asc'
+                ];
+            } else {
+                $conditions = [];
+                ViewHelper::addConditionComparism($conditions, $parameters, 'articletype_scope', 'articletype');
+                ViewHelper::addConditionComparism($conditions, $parameters, 'markup_scope', 'markup');
+                ViewHelper::addConditionPattern($conditions, $parameters, 'title,info,contents', 'text');
+                $sql = DbHelper::addConditions($sql, $conditions);
+            }
+            $sql = DbHelper::addOrderBy($sql, $fields['_sortParams']);
+            $pagination = new Pagination($sql, $parameters, $fields);
+            $records = $pagination->records;
+            $optionsArticletype = SProperty::optionsByScope('articletype', $fields['articletype'], 'all');
+            $optionsMarkup = SProperty::optionsByScope('markup', $fields['markup'], 'all');
+            $context = new ContextLaraKnife($request, $fields);
+            return view('article.index', [
+                'context' => $context,
+                'records' => $records,
+                'optionsArticletype' => $optionsArticletype,
+                'optionsMarkup' => $optionsMarkup,
+                'pagination' => $pagination
+            ]);
+        }
+    }
+    /**
+     * Returns the validation rules.
+     * @return array<string, string> The validation rules.
+     */
+    private function rules(bool $isCreate = false): array
+    {
+        $rc = [
+            'title' => 'required',
+            'contents' => 'required',
+            'info' => '',
+            'order' => 'integer|min:0|max:9999'
+        ];
+        if ($isCreate) {
+            $rc['markup_scope'] = 'required';
+            $rc['articletype_scope'] = 'required';
+        }
+        return $rc;
+    }
+    public static function routes()
+    {
+        Route::get('/article-index', [ArticleController::class, 'index'])->middleware('auth');
+        Route::post('/article-index', [ArticleController::class, 'index'])->middleware('auth');
+        Route::get('/article-create', [ArticleController::class, 'create'])->middleware('auth');
+        Route::put('/article-store', [ArticleController::class, 'store'])->middleware('auth');
+        Route::post('/article-edit/{article}', [ArticleController::class, 'edit'])->middleware('auth');
+        Route::get('/article-edit/{article}', [ArticleController::class, 'edit'])->middleware('auth');
+        Route::post('/article-update/{article}', [ArticleController::class, 'update'])->middleware('auth');
+        Route::get('/article-show/{article}/delete', [ArticleController::class, 'show'])->middleware('auth');
+        Route::delete('/article-show/{article}/delete', [ArticleController::class, 'destroy'])->middleware('auth');
+        Route::get('/article-showpretty/{article}', [ArticleController::class, 'showPretty'])->middleware('auth');
+        Route::post('/article-showpretty/{article}', [ArticleController::class, 'showPretty'])->middleware('auth');
+    }
+    /**
+     * Display the specified resource.
+     */
+    public function show(Article $article, Request $request)
+    {
+        if ($request->btnSubmit === 'btnCancel') {
+            $rc = redirect('/article-index')->middleware('auth');
+        } else {
+            $optionsArticletype = SProperty::optionsByScope('articletype', $article->articletype_scope, '');
+            $optionsMarkup = SProperty::optionsByScope('markup', $article->markup_scope, '');
+            $context = new ContextLaraKnife($request, null, $article);
+            $rc = view('article.show', [
+                'context' => $context,
+                'optionsArticletype' => $optionsArticletype,
+                'optionsMarkup' => $optionsMarkup,
+                'mode' => 'delete'
+            ]);
+        }
+        return $rc;
+    }
+    public function showPretty(Article $article, Request $request)
+    {
+        if ($request->btnSubmit === 'btnCancel') {
+            $rc = redirect('/article-index')->middleware('auth');
+        } else {
+            $text = $this->asPreview($article);
+            $link = $article->audio_id == null ? null : File::relativeFileLink($article->audio_id);
+            $context = new ContextLaraKnife($request, ['text' => $text, 'link' => $link], $article);
+            $rc = view('article.showpretty', [
+                'context' => $context,
+                'mode' => 'delete'
+            ]);
+        }
+        return $rc;
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     */
+    public function store(Request $request)
+    {
+        $rc = null;
+        if ($request->btnSubmit === 'btnStore') {
+            $fields = $request->all();
+            $validator = Validator::make($fields, $this->rules(true));
+            if ($validator->fails()) {
+                $rc = back()->withErrors($validator)->withInput();
+            } else {
+                $validated = $validator->validated();
+                $validated['info'] = strip_tags($validated['info']);
+                $validated['contents'] = TextProcessor::expandStarItems(strip_tags($validated['contents']));
+                Article::create($validated);
+            }
+        }
+        if ($rc == null) {
+            $rc = redirect('/article-index');
+        }
+        return $rc;
+    }
+    /**
+     * Update the specified resource in storage.
+     */
+    public function update(Article $article, Request $request)
+    {
+        $rc = null;
+        if ($request->btnSubmit === 'btnStore') {
+            $fields = $request->all();
+            $validator = Validator::make($fields, $this->rules(false));
+            if ($validator->fails()) {
+                $rc = back()->withErrors($validator)->withInput();
+            } else {
+                $validated = $validator->validated();
+                $validated['info'] = strip_tags($validated['info']);
+                if (empty($article->audio_id) && $request->file('file') != null) {
+                    $filename = FileHelper::textToFilename($article->title);
+                    $moduleId = Module::idOfModule('Article');
+                    $fileId = File::storeFile($request, $article->title, 1103, 1091, 'audio file of article', $filename, $moduleId, $article->id);
+                    $validated['audio_id'] = $fileId;
+                }
+                $article->update($validated);
+            }
+        }
+        if ($rc == null) {
+            $rc = redirect("/article-edit/$article->id");
+        }
+        return $rc;
+    }
+}
index 6138b74ef2d38fc9061818f26733df89a6c45112..baefe2934d3ba149beb0e6d8a0a682aa7a4bb540 100644 (file)
@@ -178,7 +178,6 @@ class ChapterController extends Controller
             ]);
         }
         return $rc;
-
     }
     /**
      * Store a newly created resource in storage.
@@ -194,7 +193,7 @@ class ChapterController extends Controller
             } else {
                 $validated = $validator->validated();
                 $validated['info'] = strip_tags($validated['info']);
-                $validated['contents'] = TextProcessor::starToTrans($validated['contents']);
+                $validated['contents'] = TextProcessor::expandStarItems(strip_tags($validated['contents']));
                 Chapter::create($validated);
             }
         }
@@ -220,7 +219,7 @@ class ChapterController extends Controller
                 $validated['contents'] = strip_tags($validated['contents']);
                 if (empty($chapter->audio_id) && $request->file('file') != null) {
                     $filename = FileHelper::textToFilename($chapter->title);
-                    $moduleId = Module::idOfModule('chapter');
+                    $moduleId = Module::idOfModule('Chapter');
                     $fileId = File::storeFile($request, $chapter->title, 1103, 1091, 'audio file of chapter', $filename, $moduleId , $chapter->id);
                     $validated['audio_id'] = $fileId;
                 }
diff --git a/app/Models/Article.php b/app/Models/Article.php
new file mode 100644 (file)
index 0000000..2cd86c8
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Support\Facades\DB;
+use Hamatoma\Laraknife\ViewHelpers;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+
+class Article extends Model
+{
+    use HasFactory;
+    protected $table = 'articles';
+    protected $fillable = [
+        'title',
+        'contents',
+        'info',
+        'articletype_scope',
+        'markup_scope',
+        'order',
+        'audio_id'
+    ];
+}
index daa434ea843f9ce038f0add06756a5719d98f445..dbd901f19d121f218448f87946f3802531b14773 100644 (file)
             "dist": {
                 "type": "path",
                 "url": "../laraknife",
-                "reference": "ffcc3fc697cf5ca157890c042061fa5f4f884aa2"
+                "reference": "d680038f94e633d0eb91a1f1d0220a0682f2dae3"
             },
             "require-dev": {
                 "phpunit/phpunit": "11.0.x-dev"
         },
         {
             "name": "nesbot/carbon",
-            "version": "3.2.4",
+            "version": "3.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/briannesbitt/Carbon.git",
-                "reference": "82c28278c1c8f7b82dcdab25692237f052ffc8d8"
+                "reference": "7219739c4e01d4680c980545821733b6ed8ee880"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/82c28278c1c8f7b82dcdab25692237f052ffc8d8",
-                "reference": "82c28278c1c8f7b82dcdab25692237f052ffc8d8",
+                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7219739c4e01d4680c980545821733b6ed8ee880",
+                "reference": "7219739c4e01d4680c980545821733b6ed8ee880",
                 "shasum": ""
             },
             "require": {
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-04-05T09:58:10+00:00"
+            "time": "2024-04-18T16:35:06+00:00"
         },
         {
             "name": "nette/schema",
diff --git a/database/migrations/2024_04_21_092103_create_articles_table.php b/database/migrations/2024_04_21_092103_create_articles_table.php
new file mode 100644 (file)
index 0000000..fb1f220
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::create('articles', function (Blueprint $table) {
+            $table->id();
+            $table->timestamps();
+            $table->string('title');
+            $table->text('contents');
+            $table->text('info')->nullable();
+            $table->integer('articletype_scope');
+            $table->integer('markup_scope');
+            $table->integer('order')->nullable();
+            $table->foreignId('audio_id')->nullable()->references('id')->on('files');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('articles');
+    }
+};
diff --git a/database/seeders/MenuitemArticleSeeder.php b/database/seeders/MenuitemArticleSeeder.php
new file mode 100644 (file)
index 0000000..4680a8d
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+
+namespace Database\Seeders;
+
+use App\Models\Module;
+use App\Models\Menuitem;
+use Illuminate\Database\Seeder;
+use Illuminate\Database\Console\Seeds\WithoutModelEvents;
+
+class MenuitemArticleSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     */
+    public function run(): void
+    {
+        Menuitem::insertIfNotExists('articles', 'bi bi-journals');
+        Module::insertIfNotExists('Article');
+    }
+}
diff --git a/database/seeders/SPropertyArticleSeeder.php b/database/seeders/SPropertyArticleSeeder.php
new file mode 100644 (file)
index 0000000..00b039e
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+
+namespace Database\Seeders;
+
+use App\Models\SProperty;
+use Illuminate\Database\Seeder;
+use Illuminate\Database\Console\Seeds\WithoutModelEvents;
+
+class SPropertyArticleSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     */
+    public function run(): void
+    {
+        SProperty::insertIfNotExists(1121, 'markup', 'plain text', 10, 'PT');
+        SProperty::insertIfNotExists(1122, 'markup', 'mediawiki', 20, 'MW');
+        SProperty::insertIfNotExists(1123, 'markup', 'HTML', 30, 'HL');
+
+        SProperty::insertIfNotExists(2031, 'articletype', 'chapter', 10, 'CH');
+        SProperty::insertIfNotExists(2032, 'articletype', 'grammar rules', 20, 'CH');
+        SProperty::insertIfNotExists(2033, 'articletype', 'cloze text', 30, 'CT');
+        SProperty::insertIfNotExists(2034, 'articletype', 'free text', 40, 'FT');
+        SProperty::insertIfNotExists(2035, 'articletype', 'snake text', 50, 'FT');
+    }
+}
index db6a9eec56d1a33e0e33d3dbd81a871502042644..8ee07db02bad4fedacbe08dd226f9687490f6ee8 100644 (file)
@@ -9,6 +9,9 @@
     "Adjective": "Adjektiv",
     "Administrator": "Administrator",
     "All": "Alle",
+    "Article": "Artikel",
+    "Articles": "Artikel",
+    "Articletype": "Artikeltyp",
     "Assign Roles": "Rollen zuordnen",
     "Body": "Info",
     "Cancel": "Abbrechen",
@@ -26,6 +29,7 @@
     "Change of a Term": "\u00c4ndern eines Termins",
     "Change of a Verb": "\u00c4nderung eines Verbs",
     "Change of a Word": "\u00c4nderung eines Wortes",
+    "Change of an Article": "\u00c4nderung eines Artikels",
     "Change of an User": "\u00c4ndern eines Benutzers",
     "Chapter": "Kapitel",
     "Chapters": "Kapitel",
@@ -40,6 +44,7 @@
     "Creation of a Scoped Property": "Erzeugen einer bereichsbasierten Eigenschaft",
     "Creation of a Term": "Erstellen eines Termins",
     "Creation of a Verb": "Neues Verb",
+    "Creation of an Article": "Neuer Artikel",
     "Creation of an User": "Erstellen eines Benutzers",
     "Date": "Datum",
     "Delete": "L\u00f6schen",
@@ -50,6 +55,7 @@
     "Deletion of a Scoped Property": "L\u00f6schen einer bereichsbasierten Eigenschaft",
     "Deletion of a Verb": "L\u00f6schen eines Verbs",
     "Deletion of a Word": "L\u00f6schen eines Wortes",
+    "Deletion of an Article": "L\u00f6schen eines Artikels",
     "Deletion of an User": "L\u00f6schen eines Benutzers",
     "Description": "Beschreibung",
     "Displaying an User": "Anzeige eines Benutzers",
@@ -82,6 +88,7 @@
     "Localization": "Lokalisierung",
     "Logout": "Abmelden",
     "Manager": "Verwalter",
+    "Markup": "Sprachtyp",
     "Name": "Name",
     "New": "Neu",
     "Not Assigned Menu Items": "Nicht zugeordnete Men\u00fceintr\u00e4ge",
     "ZZZ-last": "",
     "ZZZZZ_last": "",
     "active": "aktiv",
+    "articletype": "Artikeltyp",
+    "chapter": "Kapitel",
     "closed": "geschlossen",
+    "cloze text": "L\u00fcckentext",
     "feminine": "Femininum",
+    "free text": "Freier Text",
+    "grammar rules": "Grammatikregeln",
     "icon": "Bildsymbol",
     "inactive": "nicht aktiv",
     "label": "Beschriftung",
     "link": "Verweis",
+    "markdown simple": "einfache Markierungssprache",
     "masculine": "Maskulinum",
     "neuter": "Neutrum",
     "open": "offen",
+    "plain text": "reiner Text",
     "private": "privat",
     "public": "\u00f6ffentlich",
     "section": "Bereich",
+    "snaketext": "Schlangentext",
     "standard": "Standard",
     "work": "Arbeit"
 }
\ No newline at end of file
index 4d298f02f8fd117ec3e22ddc488e6d3011abd99e..6c99dbfa1847f7a6756d5160aeeb52007856873c 100644 (file)
@@ -1,3 +1,3 @@
 # Enter the module names separated by " ".
 # Example: MISSING="User Role Menuitem"
-MISSING="Chapter SPropertyAudio ModuleGaDeKu"
+MISSING="Chapter SPropertyAudio ModuleGaDeKu SPropertyArticle"
index 973335d80266cc510d180d84b3bc0bb71ec773c3..ddab090626c03195fd2bf3aa2c30e95ec8b017d5 100644 (file)
@@ -2,21 +2,32 @@
 "!comment": "Bitte alphabetisch sortiert eintragen!",
 "<Not verified>": "<Nicht verifiziert>",
 "Adjective": "Adjektiv",
+"Article": "Artikel",
+"Articles": "Artikel",
+"articletype": "Artikeltyp",
+"Articletype": "Artikeltyp",
+"Change of an Article": "Änderung eines Artikels",
 "Change of a Chapter": "Änderung eines Kapitels",
 "Change of a Noun": "Änderung eines Nomens",
 "Change of a Phrase": "Änderung eines Satzes",
 "Change of a Verb": "Änderung eines Verbs",
 "Change of a Word": "Änderung eines Wortes",
+"chapter": "Kapitel",
 "Chapter": "Kapitel",
 "Chapters": "Kapitel",
+"cloze text": "Lückentext",
 "Contents": "Inhalt",
+"Creation of an Article": "Neuer Artikel",
 "Creation of a Chapter": "Neues Kapitel",
 "Creation of a Verb": "Neues Verb",
+"Deletion of an Article": "Löschen eines Artikels",
 "Deletion of a Noun": "Löschen eines Nomens",
 "Deletion of a Verb": "Löschen eines Verbs",
 "Deletion of a Word": "Löschen eines Wortes",
 "feminine": "Femininum",
+"free text": "Freier Text",
 "Genus": "Geschlecht",
+"grammar rules": "Grammatikregeln",
 "Imperfect": "Imperfekt",
 "masculine": "Maskulinum",
 "neuter": "Neutrum",
@@ -27,6 +38,7 @@
 "Phrase": "Satz",
 "Phrases": "Sätze",
 "Preposition": "Präposition",
+"snaketext": "Schlangentext",
 "Translation": "Übersetzung",
 "Verb": "Verb",
 "Verbs": "Verben",
diff --git a/resources/views/article/create.blade.php b/resources/views/article/create.blade.php
new file mode 100644 (file)
index 0000000..87a8715
--- /dev/null
@@ -0,0 +1,19 @@
+@extends('layouts.backend')
+
+@section('content')
+    <form id="article-create" action="/article-store" method="POST">
+        @csrf
+        @method('PUT')
+        <x-laraknife.panels.create title="{{ __('Creation of an Article') }}">
+            <x-laraknife.forms.combobox position="first" name="articletype_scope" label="Articletype" :options="$optionsArticletype"
+                width2="4" />
+            <x-laraknife.forms.combobox position="last" name="markup_scope" label="Markup" :options="$optionsMarkup" width2="4" />
+            <x-laraknife.forms.string position="alone" name="title" label="Title"
+                value="{{ $context->valueOf('title') }}" width2="10" />
+            <x-laraknife.forms.text position="alone" name="contents" label="Contents"
+                value="{{ $context->valueOf('contents') }}" width2="10" rows="10" />
+            <x-laraknife.forms.text position="alone" name="info" label="Info" value="{{ $context->valueOf('info') }}"
+                width2="10" rows="2" />
+        </x-laraknife.panels.create>
+    </form>
+@endsection
diff --git a/resources/views/article/edit.blade.php b/resources/views/article/edit.blade.php
new file mode 100644 (file)
index 0000000..20e34a1
--- /dev/null
@@ -0,0 +1,27 @@
+@extends('layouts.backend')
+
+@section('content')
+    <form id="article-edit" action="/article-edit/{{ $context->model->id }}" method="POST">
+        @csrf
+        <x-laraknife.panels.edit title="{{ __('Change of an Article') }}">
+            <x-laraknife.forms.combobox position="first" name="articletype_scope" label="Articletype" :options="$optionsArticletype"
+                width2="4" attribute="readonly"/>
+            <x-laraknife.forms.combobox position="last" name="markup_scope" label="Markup" :options="$optionsMarkup" width2="4" attribute="readonly"/>
+            <x-laraknife.forms.string position="first" name="title" label="Title"
+                value="{{ $context->valueOf('title') }}" width2="4" />
+            <x-laraknife.forms.string type="number" position="last" name="order" label="Order"
+                value="{{ $context->valueOf('order') }}" width2="4" />
+            <x-laraknife.forms.text position="alone" name="contents" label="Contents"
+                value="{{ $context->valueOf('contents') }}" width2="10" rows="10" />
+            <x-laraknife.forms.text position="alone" name="info" label="Info" value="{{ $context->valueOf('info') }}"
+                width2="10" rows="2" />
+            <x-laraknife.forms.file-protected position="first" name="file" fieldId="{{ $context->model->audio_id }}"
+                label="Audio" width2="4" />
+            <x-laraknife.buttons.button position="last" name="btnPreview" label="Preview" />
+            @if(! empty($context->valueOf('preview')))
+            <div class="lkn-text">{!! $context->valueOf('preview') !!}
+            </div>
+            @endif
+        </x-laraknife.panels.edit>
+    </form>
+@endsection
diff --git a/resources/views/article/index.blade.php b/resources/views/article/index.blade.php
new file mode 100644 (file)
index 0000000..7395645
--- /dev/null
@@ -0,0 +1,39 @@
+@extends('layouts.backend')
+
+@section('content')
+<form id="article-index" action="/article-index" method="POST">
+    @csrf
+    <x-laraknife.panels.index title="{{ __('Articles') }}">
+      <x-laraknife.panels.filter legend="{{ $pagination->legendText() }}">
+      <x-laraknife.forms.combobox position="first" name="articletype" label="Articletype" :options="$optionsArticletype" class="lkn-autoupdate" width2="4" />
+      <x-laraknife.forms.combobox position="last" name="markup" label="Markup" :options="$optionsMarkup" class="lkn-autoupdate" width2="4" />
+      <x-laraknife.forms.string position="alone" name="text" label="Text" value="{{ $context->valueOf('title') }}" width2="10" />
+      </x-laraknife.panels.filter>
+      <x-laraknife.panels.index-button buttonType="new"/>
+      <x-laraknife.panels.sortable-table :context="$context" :pagination="$pagination">
+        <thead>
+          <tr>
+            <th></th>
+            <th sortId="title">{{__('Title')}}</th>
+            <th sortId="articletype_scope">{{__('Articletype')}}</th>
+            <th sortId="markup_scope">{{__('Markup')}}</th>
+            <th sortId="order">{{__('Order')}}</th>
+            <th></th>
+          </tr>
+        </thead>
+        <tbody>
+@foreach ($records as $article)
+        <tr>
+            <td><x-laraknife.icons.change-record module="article" no="{{ $article->id }}" /></td>
+              <td><td><a href="/article-showpretty/{{ $article->id }}">{{$article->title}}</a></td>
+              <td> {{ __($article->articletype_scope) }}</td>
+              <td> {{ __($article->markup_scope) }}</td>
+              <td>{{$article->order}}</td>
+            <td><x-laraknife.icons.delete-record module="article" no="{{ $article->id }}" /></td>
+        </tr>
+@endforeach
+      </tbody>
+    </x-laraknife.panels.sortable-table>
+  </x-laraknife.panels.index>
+</form>
+@endsection
diff --git a/resources/views/article/show.blade.php b/resources/views/article/show.blade.php
new file mode 100644 (file)
index 0000000..7010ef0
--- /dev/null
@@ -0,0 +1,17 @@
+@extends('layouts.backend')
+
+@section('content')
+    <form id="article-show" action="/article-show/{{ $context->model->id }}/{{ $mode }}" method="POST">
+        @csrf
+        @if($mode === 'delete')
+        @method('DELETE')
+        @endif
+        <x-laraknife.panels.show title="{{ __($mode !== 'delete' ? 'An Article' : 'Deletion of an Article') }}" mode="{{$mode}}">
+            <x-laraknife.forms.combobox position="first" name="articletype_scope" label="Articletype" :options="$optionsArticletype" width2="4" attribute="readonly"/>
+            <x-laraknife.forms.combobox position="last" name="markup_scope" label="Markup" :options="$optionsMarkup" width2="4" attribute="readonly"/>
+            <x-laraknife.forms.string position="alone" name="title" label="Title" value="{{ $context->valueOf('title') }}" width2="10" attribute="readonly" />
+            <x-laraknife.forms.text position="alone" name="contents" label="Contents" value="{{ $context->valueOf('contents') }}" width2="10" attribute="readonly" rows="5" />
+            <x-laraknife.forms.text position="alone" name="info" label="Info" value="{{ $context->valueOf('info') }}" width2="10" attribute="readonly" rows="2" />
+        </x-laraknife.panels.show>
+    </form>
+@endsection
diff --git a/resources/views/article/showpretty.blade.php b/resources/views/article/showpretty.blade.php
new file mode 100644 (file)
index 0000000..7506e3c
--- /dev/null
@@ -0,0 +1,17 @@
+@extends('layouts.backend')
+
+@section('content')
+    <form id="article-show" action="/article-show/{{ $context->model->id }}" method="POST">
+        @csrf
+        <x-laraknife.panels.noform-text title="{{ $context->valueof('title') }}">
+            <div class="row">
+                {!! $context->valueOf('text') !!}
+            </div>
+        </x-laraknife.panels.noform-text>
+        @if ($context->valueof('link') != null)
+            <div class="row">
+                <x-laraknife.forms.audio width1="5" width2="2" fileLink="{{ $context->valueof('link') }}" />
+            </div>
+        @endif
+    </form>
+@endsection
index 4e425ba6ebc17d193dd38993b7be84495ec8ef7e..621dff3bc3230590040c69bf602871f6b5751201 100644 (file)
@@ -13,8 +13,7 @@
             <x-laraknife.forms.text position="alone" name="contents" label="Contents"
                 value="{{ $context->valueOf('contents') }}" width2="10" rows="10" />
             <x-laraknife.forms.file-protected position="alone" name="file" fieldId="{{ $context->model->audio_id }}"
-                value="{{ $context->valueOf('file') }}" label="Audio" width2="10" />
-
+                label="Audio" width2="10" />
         </x-laraknife.panels.edit>
     </form>
 @endsection
diff --git a/resources/views/create.blade.php b/resources/views/create.blade.php
new file mode 100644 (file)
index 0000000..19424ad
--- /dev/null
@@ -0,0 +1,11 @@
+@extends('layouts.backend')
+
+@section('content')
+    <form id="-create" action="/-store" method="POST">
+        @csrf
+        @method('PUT')
+        <x-laraknife.panels.create title="{{ __('Creation of a ') }}">
+            
+</x-laraknife.panels.create>
+    </form>
+@endsection
diff --git a/resources/views/edit.blade.php b/resources/views/edit.blade.php
new file mode 100644 (file)
index 0000000..e9d8bca
--- /dev/null
@@ -0,0 +1,10 @@
+@extends('layouts.backend')
+
+@section('content')
+    <form id="-edit" action="/-update/{{ $context->model->id  }}" method="POST">
+        @csrf
+        <x-laraknife.panels.edit title="{{ __('Change of a ') }}">
+        <x-laraknife.forms.text position="alone" name="id" label="Id" value="{{ $context->model->id }}" width2="4" attribute="readonly"/>
+        </x-laraknife.panels.edit>
+    </form>
+@endsection
diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php
new file mode 100644 (file)
index 0000000..a1eb450
--- /dev/null
@@ -0,0 +1,28 @@
+@extends('layouts.backend')
+
+@section('content')
+<form id="-index" action="/-index" method="POST">
+    @csrf
+    <x-laraknife.panels.index title="{{ __('') }}">
+      <x-laraknife.panels.filter legend="{{ $pagination->legendText() }}">
+      </x-laraknife.panels.filter>
+      <x-laraknife.panels.index-button buttonType="new"/>
+      <x-laraknife.panels.sortable-table :context="$context" :pagination="$pagination">
+        <thead>
+          <tr>
+            <th></th>
+            <th></th>
+          </tr>
+        </thead>
+        <tbody>
+@foreach ($records as $)
+        <tr>
+            <td><x-laraknife.icons.change-record module="" no="{{ $->id }}" /></td>
+            <td><x-laraknife.icons.delete-record module="" no="{{ $->id }}" /></td>
+        </tr>
+@endforeach
+      </tbody>
+    </x-laraknife.panels.sortable-table>
+  </x-laraknife.panels.index>
+</form>
+@endsection
diff --git a/resources/views/show.blade.php b/resources/views/show.blade.php
new file mode 100644 (file)
index 0000000..f0227f7
--- /dev/null
@@ -0,0 +1,13 @@
+@extends('layouts.backend')
+
+@section('content')
+    <form id="-show" action="/-show/{{ $context->model->id }}/{{ $mode }}" method="POST">
+        @csrf
+        @if($mode === 'delete')
+        @method('DELETE')
+        @endif
+        <x-laraknife.panels.show title="{{ __($mode !== 'delete' ? 'A ' : 'Deletion of a ') }}" mode="{{$mode}}">
+            <x-laraknife.forms.string position="first" name="id" label="Id" value="{{ $context->model->id }}" width2="4" attribute="readonly" />
+        </x-laraknife.panels.show>
+    </form>
+@endsection
index 5662c04131f9098e10ce3e6b2b8d52fbb5dc1a14..0c8298b423d250dd7c321c96e367b031a8150a9c 100644 (file)
@@ -13,6 +13,7 @@ use App\Http\Controllers\PhraseController;
 use App\Http\Controllers\ReviewController;
 use App\Http\Controllers\MenuitemController;
 use App\Http\Controllers\ChapterController;
+use App\Http\Controllers\ArticleController;
 use App\Http\Controllers\SPropertyController;
 
 Route::get('/', function () {
@@ -35,3 +36,5 @@ PhraseController::routes();
 ReviewController::routes();
 
 ChapterController::routes();
+
+ArticleController::routes();