Compare commits

..

1 Commits

Author SHA1 Message Date
nomadjimbob
43abc6d1c6 Dependency update 2025-12-31 20:59:17 +00:00
19 changed files with 1207 additions and 1472 deletions

View File

@@ -1,24 +0,0 @@
name: renovate
on:
workflow_dispatch:
schedule:
- cron: "@daily"
push:
branches:
- main
jobs:
renovate:
runs-on: ubuntu-latest
container: ghcr.io/renovatebot/renovate:43.2.3
steps:
- uses: actions/checkout@v4
- run: renovate
working-directory: ${{ gitea.workspace }}
env:
RENOVATE_CONFIG_FILE: "renovate-config.json"
LOG_LEVEL: "info"
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}

15
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "daily"

55
.github/workflows/dependency-update.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: Dependency Update
on:
schedule:
- cron: "0 20 * * 1" # Mondays 20:00 UTC
workflow_dispatch: {}
permissions:
contents: write
pull-requests: write
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- uses: shivammathur/setup-php@v2
with:
php-version: "8.4"
tools: composer:v2
- name: Install current deps
run: |
npm ci
composer install --no-interaction --no-progress
- name: Update deps
run: |
npm update
composer update --no-interaction --no-progress
- name: Detect changes
id: changes
run: |
if git diff --quiet; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Create PR
if: steps.changes.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v6
with:
commit-message: "Dependency update"
title: "Dependency update"
body: "Automated dependency update."
branch: "bot/dependency-update"
delete-branch: true

View File

@@ -3,59 +3,39 @@ name: Laravel
on:
push:
branches: ["main"]
pull_request:
jobs:
laravel-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: "8.4"
php-version: "8.2"
- uses: actions/checkout@v3
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
- name: Install PHP Dependencies
- name: Install Dependencies
run: composer install -q --no-interaction --no-progress --prefer-dist
- name: Generate key
run: php artisan key:generate
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Create Database
run: |
mkdir -p database
touch database/database.sqlite
- name: Install Node.js
uses: actions/setup-node@v2
with:
node-version: "20"
- name: Install Node dependencies
run: npm ci
- name: Build frontend
run: npm run build
- name: Run migrations
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
run: php artisan migrate --force
- name: Run PHPUnit
- name: Execute tests (Unit and Feature tests) via PHPUnit
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
run: vendor/bin/phpunit
- name: Install Node.js
uses: actions/setup-node@v2
with:
node-version: "16.x"
- name: Install dependencies
run: npm ci
- name: Run Vue tests
env:
LARAVEL_BYPASS_ENV_CHECK: "1"

View File

@@ -49,24 +49,6 @@ We would like to extend our thanks to the following sponsors for funding Laravel
- **[byte5](https://byte5.de)**
- **[OP.GG](https://op.gg)**
## Code Style
This project uses [Laravel Pint](https://laravel.com/docs/pint) for code styling. Pint is an opinionated PHP code style fixer for minimalists, built on top of PHP-CS-Fixer.
To automatically fix code style issues, run:
```bash
composer pint
```
To check for code style issues without fixing them:
```bash
composer pint-test
```
The code style configuration can be found in `pint.json`.
## Contributing
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).

View File

@@ -9,11 +9,11 @@ class HomeController extends Controller
{
public function index()
{
// $posts = Post::query()->orderBy('created_at', 'desc')->limit(4)->get();
$posts = Post::query()->orderBy('created_at', 'desc')->limit(4)->get();
$workshops = Workshop::query()->where('starts_at', '>', now())->where('status', '!=', 'private')->orderBy('starts_at', 'asc')->limit(4)->get();
return view('home', [
// 'posts' => $posts,
'posts' => $posts,
'workshops' => $workshops,
]);
}

View File

@@ -111,17 +111,15 @@ class MediaController extends Controller
public function admin_store(Request $request)
{
$file = null;
$cleanupPath = null;
// Check if the endpoint received a file...
if($request->hasFile('file')) {
try {
$file = $this->upload($request);
if(is_array($file) && !empty($file['chunk'])) {
if($file === true) {
return response()->json([
'message' => 'Chunk stored',
'upload_token' => $file['token'] ?? null,
]);
} else if(!$file) {
return response()->json([
@@ -152,20 +150,8 @@ class MediaController extends Controller
}
// else check if it received a file name of a previous upload...
} else if($request->has('upload_token') || $request->has('file')) {
$uploadToken = $request->input('upload_token', $request->input('file'));
$chunkUploads = session()->get('chunk_uploads', []);
if(!is_string($uploadToken) || !isset($chunkUploads[$uploadToken])) {
return response()->json([
'message' => 'Could not find the referenced file on the server.',
'errors' => [
'file' => 'Could not find the referenced file on the server.'
]
], 422);
}
$tempFileName = $chunkUploads[$uploadToken];
} else if($request->has('file')) {
$tempFileName = sys_get_temp_dir() . '/chunk-' . Auth::id() . '-' . $request->file;
if(!file_exists($tempFileName)) {
return response()->json([
'message' => 'Could not find the referenced file on the server.',
@@ -179,16 +165,7 @@ class MediaController extends Controller
if($fileMime === false) {
$fileMime = 'application/octet-stream';
}
$fileName = $request->input('filename', 'upload');
$fileName = Helpers::cleanFileName($fileName);
if ($fileName === '') {
$fileName = 'upload';
}
$file = new UploadedFile($tempFileName, $fileName, $fileMime, null, true);
$cleanupPath = $tempFileName;
unset($chunkUploads[$uploadToken]);
session()->put('chunk_uploads', $chunkUploads);
$file = new UploadedFile($tempFileName, $request->file, $fileMime, null, true);
}
// Check there is an actual file
@@ -265,13 +242,7 @@ class MediaController extends Controller
}
}
if(is_string($cleanupPath)) {
$realPath = realpath($cleanupPath);
$tempDir = realpath(sys_get_temp_dir());
if($realPath !== false && $tempDir !== false && str_starts_with($realPath, $tempDir . DIRECTORY_SEPARATOR)) {
@unlink($realPath);
}
}
unlink($file->getRealPath());
if($request->wantsJson()) {
return response()->json([
@@ -415,10 +386,6 @@ class MediaController extends Controller
$fileName = $request->input('filename', $file->getClientOriginalName());
$fileName = Helpers::cleanFileName($fileName);
if ($fileName === '') {
$extension = strtolower($file->getClientOriginalExtension());
$fileName = 'upload' . ($extension !== '' ? '.' . $extension : '');
}
if(($request->has('filestart') || $request->has('fileappend')) && $request->has('filesize')) {
$fileSize = $request->get('filesize');
@@ -427,25 +394,7 @@ class MediaController extends Controller
throw new FileTooLargeException('The file is larger than the maximum size allowed of ' . Helpers::bytesToString($max_size));
}
$chunkUploads = session()->get('chunk_uploads', []);
$uploadToken = $request->input('upload_token');
if($request->has('filestart')) {
$uploadToken = bin2hex(random_bytes(16));
$tempFilePath = tempnam(sys_get_temp_dir(), 'chunk-' . Auth::id() . '-');
if($tempFilePath === false) {
throw new FileInvalidException('Unable to create a temporary upload file.');
}
$chunkUploads[$uploadToken] = $tempFilePath;
session()->put('chunk_uploads', $chunkUploads);
} else {
if(!is_string($uploadToken) || !isset($chunkUploads[$uploadToken])) {
throw new FileInvalidException('Invalid upload token.');
}
$tempFilePath = $chunkUploads[$uploadToken];
}
$tempFilePath = sys_get_temp_dir() . '/chunk-' . Auth::id() . '-' . $fileName;
$filemode = 'a';
if($request->has('filestart')) {
@@ -466,17 +415,9 @@ class MediaController extends Controller
$fileMime = 'application/octet-stream';
}
if(is_string($uploadToken) && isset($chunkUploads[$uploadToken])) {
unset($chunkUploads[$uploadToken]);
session()->put('chunk_uploads', $chunkUploads);
}
return new UploadedFile($tempFilePath, $fileName, $fileMime, null, true);
} else {
return [
'chunk' => true,
'token' => $uploadToken,
];
return true;
}
}

View File

@@ -5,14 +5,14 @@
"keywords": ["laravel", "framework"],
"license": "MIT",
"require": {
"php": "^8.4",
"php": "^8.2",
"ext-imagick": "*",
"chillerlan/php-qrcode": "^5.0",
"gehrisandro/tailwind-merge-laravel": "^1.2",
"intervention/image": "^3.5",
"laravel/framework": "^12.0",
"laravel/tinker": "^2.9",
"livewire/livewire": "^4.1",
"livewire/livewire": "^3.4",
"php-ffmpeg/php-ffmpeg": "^1.2",
"robthree/twofactorauth": "^3.0"
},
@@ -22,7 +22,7 @@
"laravel/pint": "^1.13",
"laravel/sail": "^1.26",
"mockery/mockery": "^1.6",
"phpunit/phpunit": "^12.5",
"phpunit/phpunit": "^10.5",
"spatie/laravel-ignition": "^2.4"
},
"autoload": {
@@ -52,12 +52,6 @@
"@php artisan key:generate --ansi",
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
"@php artisan migrate --graceful --ansi"
],
"pint": [
"./vendor/bin/pint"
],
"pint-test": [
"./vendor/bin/pint --test"
]
},
"extra": {
@@ -66,9 +60,6 @@
}
},
"config": {
"platform": {
"php": "8.4.17"
},
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,

1363
composer.lock generated

File diff suppressed because it is too large Load Diff

925
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,29 +3,28 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"snyk:test": "snyk test --all-projects --exclude=vendor"
"build": "vite build"
},
"devDependencies": {
"@tailwindcss/vite": "^4.1.17",
"autoprefixer": "^10.4.24",
"axios": "^1.13.4",
"laravel-vite-plugin": "^2.0.1",
"autoprefixer": "^10.4.19",
"axios": "^1.6.4",
"laravel-vite-plugin": "^1.0",
"postcss": "^8.4.38",
"vite": "^7.3.0"
"vite": "^6.4"
},
"dependencies": {
"@tiptap/core": "^3.10.7",
"@tiptap/extension-highlight": "^3.18.0",
"@tiptap/extension-image": "^3.18.0",
"@tiptap/extension-link": "^3.18.0",
"@tiptap/extension-subscript": "^3.18.0",
"@tiptap/extension-superscript": "^3.18.0",
"@tiptap/extension-text-align": "^3.18.0",
"@tiptap/extension-typography": "^3.18.0",
"@tiptap/extension-underline": "^3.18.0",
"@tiptap/pm": "^3.10.7",
"@tiptap/starter-kit": "^3.18.0",
"@tiptap/core": "^2.3.0",
"@tiptap/extension-highlight": "^2.3.0",
"@tiptap/extension-image": "^2.3.0",
"@tiptap/extension-link": "^2.3.0",
"@tiptap/extension-subscript": "^2.3.0",
"@tiptap/extension-superscript": "^2.3.0",
"@tiptap/extension-text-align": "^2.3.0",
"@tiptap/extension-typography": "^2.3.0",
"@tiptap/extension-underline": "^2.3.0",
"@tiptap/pm": "^2.3.0",
"@tiptap/starter-kit": "^2.3.0",
"tailwindcss": "^4.1.17"
}
}

View File

@@ -1,8 +0,0 @@
{
"preset": "laravel",
"rules": {
"simplified_null_return": true,
"new_with_braces": true,
"no_unused_imports": true
}
}

View File

@@ -1,26 +1,4 @@
let SM = {
redirectIfSafe: (target) => {
if (typeof target !== 'string' || target === '') {
window.location.assign('/');
return;
}
let url;
try {
url = new URL(target, window.location.origin);
} catch (error) {
window.location.assign('/');
return;
}
if (url.origin !== window.location.origin) {
window.location.assign('/');
return;
}
window.location.assign(url.href);
},
alert: (title, text, type = 'info') =>{
const data = {
position: 'top-end',
@@ -106,7 +84,7 @@ let SM = {
axios.delete(url)
.then((response) => {
if(response.data.success){
SM.redirectIfSafe(response.data.redirect);
window.location.href = response.data.redirect;
}
})
.catch(() => {
@@ -158,7 +136,7 @@ let SM = {
}
}
const uploadFile = (file, start, title, idx, count, uploadToken = null) => {
const uploadFile = (file, start, title, idx, count) => {
const showPercentDecimals = (file.size > (1024 * 1024 * 40));
const chunkSize = 1024 * 1024 * 2;
const end = Math.min(file.size, start + chunkSize);
@@ -168,9 +146,6 @@ let SM = {
formData.append('file', chunk);
formData.append('filename', file.name);
formData.append('filesize', file.size);
if (uploadToken) {
formData.append('upload_token', uploadToken);
}
if (start === 0) {
formData.append('filestart', 'true');
@@ -208,10 +183,6 @@ let SM = {
}
}).then((response) => {
if (response.status === 200) {
if (response.data && response.data.upload_token) {
uploadToken = response.data.upload_token;
}
if (end >= file.size) {
uploadedFiles.push({ file: file, title: title, data: response.data });
@@ -234,13 +205,12 @@ let SM = {
} else {
start = 0;
idx += 1;
uploadToken = null;
}
} else {
start = end;
}
uploadFile(files[idx], start, titles[idx] || '', idx, files.length, uploadToken);
uploadFile(files[idx], start, titles[idx] || '', idx, files.length);
} else {
showError(response.data.message);
}

View File

@@ -1,8 +0,0 @@
{
"endpoint": "https://git.stemmechanics.com.au/api/v1",
"gitAuthor": "Renovate Bot <renovate-bot@stemmechanics.com.au>",
"platform": "gitea",
"onboardingConfigFileName": "renovate.json",
"autodiscover": true,
"optimizeForDisabled": true
}

View File

@@ -1,24 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
],
"automerge": true,
"platformAutomerge": true,
"requiredStatusChecks": null,
"packageRules": [
{
"matchUpdateTypes": [
"patch"
],
"automerge": true
},
{
"matchUpdateTypes": [
"minor",
"major"
],
"automerge": false
}
]
}

View File

@@ -1,7 +1,6 @@
import Link from "@tiptap/extension-link";
import {Editor} from "@tiptap/core";
import StarterKit from "@tiptap/starter-kit";
import Underline from "@tiptap/extension-underline";
import Highlight from "@tiptap/extension-highlight";
import TextAlign from "@tiptap/extension-text-align";
import Typography from "@tiptap/extension-typography";
@@ -50,16 +49,12 @@ document.addEventListener('alpine:init', () => {
editor = new Editor({
element: this.$refs.element,
extensions: [
StarterKit.configure({
link: false,
underline: false,
}),
StarterKit,
Highlight,
CustomLink.configure({
rel: 'noopener noreferrer',
openOnClick: 'whenNotEditable',
}),
Underline,
TextAlign.configure({
types: ['heading', 'paragraph', 'small', 'extraSmall'],
}),
@@ -70,11 +65,6 @@ document.addEventListener('alpine:init', () => {
ExtraSmall,
Box
],
editorProps: {
attributes: {
class: 'tiptap content',
},
},
content: content,
onCreate({/* editor */}) {
_this.updatedAt = Date.now()
@@ -151,9 +141,6 @@ document.addEventListener('alpine:init', () => {
unsetAllMarks() {
editor.chain().focus().unsetAllMarks().run()
},
clearNodes() {
editor.chain().focus().clearNodes().run()
},
clearNotes() {
editor.chain().focus().clearNodes().run()
},

View File

@@ -1,19 +0,0 @@
@props(['item' => 'results', 'search', 'message', 'title'])
@php
if(!isset($message)) {
if(!isset($search) || $search == '')
$message = "We couldn't find any $item";
else
$message = "We couldn't find any $item matching \"$search\"";
}
if(!isset($title)) {
$title = "No results found";
}
@endphp
<div class="flex flex-col items-center my-8 w-full">
<i class="text-gray-300 mb-6 text-8xl fa-solid fa-cat"></i>
<p class="text-gray-500 mt-2">No workshops coming up. Were on a short break, mostly by playing with the cat.</p>
</div>

View File

@@ -36,7 +36,7 @@
imgElement.src = details.thumbnail;
imgElement.classList.remove('hidden');
placeholderElement.classList.add('hidden!');
placeholderElement.classList.add('hidden');
document.getElementById(name).value = value;
});

View File

@@ -12,7 +12,7 @@
<x-container>
<h2 class="text-2xl font-bold mb-6">Upcoming workshops</h2>
@if($workshops->isEmpty())
<x-on-holiday />
<x-none-found item="workshops" message="No workshops have been scheduled at this time" title="" />
@else
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8 w-full">
@foreach($workshops as $index => $workshop)