diff --git a/.editorconfig b/.editorconfig index 1a340b5bd..17f3d0d95 100755 --- a/.editorconfig +++ b/.editorconfig @@ -16,6 +16,7 @@ ij_visual_guides = none ij_wrap_on_typing = false [*.blade.php] +max_line_length = 160 ij_blade_keep_indents_on_empty_lines = false [*.css] @@ -179,7 +180,7 @@ ij_xml_space_around_equals_in_attribute = false ij_xml_space_inside_empty_tag = false ij_xml_text_wrap = normal -[{*.ats,*.cts,*.mts,*.ts}] +[{*.ats,*.cts,*.mts,*.ts,*.tsx}] indent_size = 2 max_line_length = 200 tab_width = 2 diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index a34b3841f..88efbe9fe 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,7 +1,7 @@ diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 7fb977c12..f2440eb46 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -8,8 +8,6 @@ - - @@ -37,6 +35,9 @@ + + + @@ -56,7 +57,7 @@ - + @@ -141,9 +142,10 @@ - + + + - @@ -174,7 +176,7 @@ @@ -216,6 +228,13 @@ + + + + + @@ -228,8 +247,8 @@ - + @@ -271,14 +290,20 @@ - - + + - + + + + @@ -286,27 +311,36 @@ - + + - - + + - + + + + + @@ -383,15 +417,27 @@ + + + + - + + + @@ -411,7 +457,6 @@ - diff --git a/.idea/scopes/App.xml b/.idea/scopes/App.xml new file mode 100644 index 000000000..e45bfeb27 --- /dev/null +++ b/.idea/scopes/App.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/scopes/Frontend.xml b/.idea/scopes/Frontend.xml deleted file mode 100644 index 8c08687db..000000000 --- a/.idea/scopes/Frontend.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/app/Actions/Fortify/CreateNewUser.php b/app/Actions/Fortify/CreateNewUser.php index 0443a2132..39336fd21 100644 --- a/app/Actions/Fortify/CreateNewUser.php +++ b/app/Actions/Fortify/CreateNewUser.php @@ -15,7 +15,7 @@ class CreateNewUser implements CreatesNewUsers /** * Validate and create a newly registered user. * - * @param array $input + * @param array $input */ public function create(array $input): User { diff --git a/app/Actions/Fortify/PasswordValidationRules.php b/app/Actions/Fortify/PasswordValidationRules.php index 7f99bb896..1aac09821 100644 --- a/app/Actions/Fortify/PasswordValidationRules.php +++ b/app/Actions/Fortify/PasswordValidationRules.php @@ -9,7 +9,9 @@ trait PasswordValidationRules /** * Get the validation rules used to validate passwords. * - * @return array + * @return list{'required', 'string', Password, 'confirmed'}' + * + * @noinspection PhpDocSignatureInspection */ protected function passwordRules(): array { diff --git a/app/Actions/Fortify/UpdateUserProfileInformation.php b/app/Actions/Fortify/UpdateUserProfileInformation.php index c8f2cce59..1be566f39 100644 --- a/app/Actions/Fortify/UpdateUserProfileInformation.php +++ b/app/Actions/Fortify/UpdateUserProfileInformation.php @@ -29,8 +29,8 @@ class UpdateUserProfileInformation implements UpdatesUserProfileInformation ], ])->validateWithBag('updateProfileInformation'); - if ($input['email'] !== $user->email && - $user instanceof MustVerifyEmail) { + if ($input['email'] !== $user->email && $user instanceof MustVerifyEmail) { + /** @noinspection PhpParamsInspection */ $this->updateVerifiedUser($user, $input); } else { $user->forceFill([ diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index cc8707fc9..528d84d9e 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -1,5 +1,7 @@ > */ - protected $dontReport = [ - // - ]; + protected $dontReport = []; /** * A list of the inputs that are never flashed for validation exceptions. * - * @var array + * @var array */ protected $dontFlash = [ 'current_password', @@ -33,7 +33,6 @@ class Handler extends ExceptionHandler public function register(): void { $this->reportable(static function (Throwable $e): void { - // }); } } diff --git a/app/Http/Controllers/Api/SetupController.php b/app/Http/Controllers/Api/SetupController.php index 5c567f5d7..3c4e450d8 100644 --- a/app/Http/Controllers/Api/SetupController.php +++ b/app/Http/Controllers/Api/SetupController.php @@ -14,15 +14,14 @@ use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; - -use function in_array; - +use Jackiedo\DotenvEditor\DotenvEditor; use PDOException; use RuntimeException; +use function in_array; class SetupController extends Controller { - public function __construct(private \Jackiedo\DotenvEditor\DotenvEditor $dotenvEditor) + public function __construct(private readonly DotenvEditor $dotenvEditor) { } @@ -74,6 +73,13 @@ class SetupController extends Controller // Identifying permissions granted to the user $database_name = Str::replace('_', '\_', $database_name); + /** + * @psalm-suppress InvalidArgument + * + * @noinspection PhpParamsInspection + * + * @phpstan-ignore-next-line + */ $grants = $connection->select($connection->raw('SHOW GRANTS FOR CURRENT_USER')); $requirements = [ diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php deleted file mode 100644 index 610e5efa7..000000000 --- a/app/Http/Controllers/AuthController.php +++ /dev/null @@ -1,80 +0,0 @@ -validate($this->rules($request)); -// } catch (ValidationException $e) { -// return response()->json(['message' => $e->getMessage(), 'errors' => $e->errors()], Response::HTTP_UNPROCESSABLE_ENTITY); -// } -// -// $credentials = $request->only(['username', 'password']); -// -// // TODO: Rivedere con Laravel 10 -// if (filter_var($request->get('username'), FILTER_VALIDATE_EMAIL)) { -// $credentials['email'] = $credentials['username']; -// unset($credentials['username']); -// } -// -// if (auth()->attempt($credentials, $request->get('remember') === 'on')) { -// $request->session()->regenerate(); -// if ($request->hasSession()) { -// $request->session()->put('auth.password_confirmed_at', time()); -// } -// -// return response()->noContent(); -// } -// -// return response()->json([ -// 'message' => __('Le credenziali non sono valide.') -// ], Response::HTTP_BAD_REQUEST); -// } - - /** - * Log the user out of the application. - * - * @noinspection RepetitiveMethodCallsInspection - */ - public function logout(Request $request): Response - { - auth()->logout(); - - $request->session()->invalidate(); - $request->session()->regenerateToken(); - - return response()->noContent(); - } - -// /** -// * @return array{username: string, password: string, remember: string} -// */ -// #[ArrayShape(['username' => 'string', 'password' => 'string', 'remember' => 'string'])] -// private function rules(Request $request): array -// { -// $additional_validation = ''; -// $db_field = 'username'; -// if (filter_var($request->input('username'), FILTER_VALIDATE_EMAIL)) { -// $additional_validation = '|email'; -// $db_field = 'email'; -// } -// -// return [ -// 'username' => "required|string|exists:users,$db_field|$additional_validation", -// 'password' => 'required|string', -// 'remember' => 'string|in:on', -// ]; -// } -} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 69576e579..b11425f6f 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -13,7 +13,9 @@ use Illuminate\Http\Request; use Illuminate\Routing\Controller as BaseController; use Illuminate\Support\Collection; use Illuminate\Support\Facades\File; +use Illuminate\Support\ServiceProvider; use ReflectionClass; +use ReflectionException; class Controller extends BaseController { @@ -38,7 +40,7 @@ class Controller extends BaseController } /** - * @return Collection + * @return Collection */ public static function getLanguages(): Collection { @@ -48,7 +50,7 @@ class Controller extends BaseController } /** - * @return CollectiongetLoadedProviders()) ->keys() - ->filter(static fn (string $provider) => (new ReflectionClass($provider))->isSubclassOf(ModuleServiceProvider::class)) + ->filter( + /** + * @param class-string $provider + * + * @throws ReflectionException + */ + static fn (string $provider) => (new ReflectionClass($provider))->isSubclassOf(ModuleServiceProvider::class)) ->map(static fn (string $provider) => app()->getProvider($provider)) - ->mapWithKeys(static fn (ModuleServiceProvider $provider) => [$provider::slug() => [ + ->mapWithKeys(static fn (?ServiceProvider $provider) => $provider instanceof ModuleServiceProvider ? [$provider::slug() => [ 'name' => $provider::name(), 'description' => $provider::description(), 'slug' => $provider::slug(), @@ -74,6 +82,6 @@ class Controller extends BaseController 'url' => $provider::url(), 'modulePath' => $provider::modulePath(), 'namespace' => $provider::namespace(), - ]]); + ]] : []); } } diff --git a/app/Http/Controllers/PasswordController.php b/app/Http/Controllers/PasswordController.php deleted file mode 100644 index 164c7a4cb..000000000 --- a/app/Http/Controllers/PasswordController.php +++ /dev/null @@ -1,66 +0,0 @@ -validate([ -// 'email' => 'required|email|exists:users,email', -// ]); -// } catch (ValidationException $e) { -// return response()->json([ -// 'message' => $e->getMessage(), -// 'errors' => $e->errors(), -// ], Response::HTTP_UNPROCESSABLE_ENTITY); -// } -// -// $response = Password::broker()->sendResetLink($request->input('email')); -// -// return $response === Password::RESET_LINK_SENT -// ? response()->noContent() -// : \response()->json(['message' => __($response)], Response::HTTP_UNPROCESSABLE_ENTITY); -// } -// -// public function resetPassword(Request $request): JsonResponse|Response -// { -// try { -// $request->validate([ -// 'token' => 'required|string', -// 'email' => 'required|email|exists:users,email', -// 'password' => ['required|string|confirmed', \Illuminate\Validation\Rules\Password::defaults()], -// ]); -// } catch (ValidationException $e) { -// return response()->json([ -// 'message' => $e->getMessage(), -// 'errors' => $e->errors(), -// ], Response::HTTP_UNPROCESSABLE_ENTITY); -// } -// -// $response = Password::broker()->reset( -// $request->only(['email', 'password', 'password_confirmation', 'token']), -// static function (User $user, string $password): void { -// $user->password = Hash::make($password); -// $user->setRememberToken(Str::random(60)); -// $user->save(); -// event(new PasswordReset($user)); -// } -// ); -// -// return $response === Password::PASSWORD_RESET -// ? response()->noContent() -// : response()->json(['message' => __($response)], Response::HTTP_UNPROCESSABLE_ENTITY); -// } -} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 821c41b65..491bcdded 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -1,5 +1,9 @@ */ protected $middleware = [ // \App\Http\Middleware\TrustHosts::class, @@ -51,7 +55,7 @@ class Kernel extends HttpKernel /** * The application's route middleware groups. * - * @var array + * @var array> */ protected $middlewareGroups = [ 'web' => [ @@ -79,9 +83,9 @@ class Kernel extends HttpKernel * * These middlewares may be assigned to a group or used individually. * - * @var array + * @var array */ - protected $routeMiddleware = [ + protected $middlewareAliases = [ 'auth' => Authenticate::class, 'auth.basic' => AuthenticateWithBasicAuth::class, 'cache.headers' => SetCacheHeaders::class, diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index d4ef6447a..a3c37da27 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -12,6 +12,10 @@ class Authenticate extends Middleware */ protected function redirectTo(Request $request): ?string { - return $request->expectsJson() ? null : route('login'); + if ($request->expectsJson()) { + return null; + } + + return route('login'); } } diff --git a/app/Http/Middleware/CheckConfigurationMiddleware.php b/app/Http/Middleware/CheckConfigurationMiddleware.php index 7af72dc09..ca45b8c49 100644 --- a/app/Http/Middleware/CheckConfigurationMiddleware.php +++ b/app/Http/Middleware/CheckConfigurationMiddleware.php @@ -11,6 +11,7 @@ use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\DB; use InvalidArgumentException; +use PDO; use PDOException; class CheckConfigurationMiddleware @@ -18,8 +19,8 @@ class CheckConfigurationMiddleware public function handle(Request $request, Closure $next): Response|RedirectResponse|JsonResponse { $checks = [ - 'database' => fn () => !empty(DB::connection()->getDatabaseName()) && DB::connection()->getPdo(), - 'admin_user' => fn () => !empty(User::exists()), + 'database' => static fn (): bool => !empty(DB::connection()->getDatabaseName()) && DB::connection()->getPdo() instanceof PDO, + 'admin_user' => static fn (): bool => !empty(User::exists()), ]; foreach ($checks as $check) { @@ -34,13 +35,16 @@ class CheckConfigurationMiddleware } if (!$check) { - if (str_starts_with($request->route()?->getName(), 'setup.')) { + $route = $request->route(); + if ($route && str_starts_with($route->getName(), 'setup.')) { return $next($request); } - return $request->wantsJson() - ? \response()->json(['message' => __('Configurazione del database richiesta')], Response::HTTP_SERVICE_UNAVAILABLE) - : redirect()->route('setup.index'); + if ($request->wantsJson()) { + return \response()->json(['message' => __('Configurazione del database richiesta')], Response::HTTP_SERVICE_UNAVAILABLE); + } + + return redirect()->route('setup.index'); } } diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php index 033136ad1..459dea568 100644 --- a/app/Http/Middleware/EncryptCookies.php +++ b/app/Http/Middleware/EncryptCookies.php @@ -1,5 +1,7 @@ */ - protected $except = [ - // - ]; + protected $except = []; } diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 90e611a7f..4a54f16d6 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -1,10 +1,13 @@ 'array|\Closure[]', 'locale' => Closure::class])] final public function share(Request $request): array { - return array_merge(parent::share($request), [ - 'locale' => static fn() => app()->getLocale(), - ]); + return [...parent::share($request), 'locale' => static fn () => app()->getLocale()]; } } diff --git a/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/app/Http/Middleware/PreventRequestsDuringMaintenance.php index e4956d0bb..375b1b8a5 100644 --- a/app/Http/Middleware/PreventRequestsDuringMaintenance.php +++ b/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -1,5 +1,7 @@ */ - protected $except = [ - // - ]; + protected $except = []; } diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index afc78c4e5..5ee299633 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -12,11 +12,10 @@ class RedirectIfAuthenticated { /** * Handle an incoming request. - * - * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next, string ...$guards): Response { + /** @noinspection CallableParameterUseCaseInTypeContextInspection */ $guards = empty($guards) ? [null] : $guards; foreach ($guards as $guard) { diff --git a/app/Http/Middleware/TrustProxies.php b/app/Http/Middleware/TrustProxies.php index 0c7d3b6bb..3391630ec 100644 --- a/app/Http/Middleware/TrustProxies.php +++ b/app/Http/Middleware/TrustProxies.php @@ -10,7 +10,7 @@ class TrustProxies extends Middleware /** * The trusted proxies for this application. * - * @var array|string|null + * @var array|string|null */ protected $proxies; diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 0c13b8548..fcdb9b940 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -1,5 +1,7 @@ */ - protected $except = [ - // - ]; + protected $except = []; } diff --git a/app/Models/User.php b/app/Models/User.php index 90e5f924e..8af48714d 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,7 +2,6 @@ namespace App\Models; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; @@ -11,14 +10,13 @@ use Rawilk\Settings\Models\HasSettings; class User extends Authenticatable { use HasSettings; - use HasFactory; use Notifiable; use HasApiTokens; /** * The attributes that are mass assignable. * - * @var array + * @var array */ protected $fillable = [ 'username', @@ -29,7 +27,7 @@ class User extends Authenticatable /** * The attributes that should be hidden for arrays. * - * @var array + * @var array */ protected $hidden = [ 'password', diff --git a/app/ModuleServiceProvider.php b/app/ModuleServiceProvider.php index f29544a66..62d9d63cb 100644 --- a/app/ModuleServiceProvider.php +++ b/app/ModuleServiceProvider.php @@ -5,6 +5,8 @@ namespace App; use Illuminate\Support\Arr; use Illuminate\Support\ServiceProvider; use ReflectionClass; +use function dirname; +use function in_array; abstract class ModuleServiceProvider extends ServiceProvider { @@ -30,15 +32,29 @@ abstract class ModuleServiceProvider extends ServiceProvider return static::$description; } + /** + * @psalm-suppress InvalidNullableReturnType + */ public static function slug(): string { $slug = static::$slug; if (empty($slug)) { - $cachedPackages = require app()->getCachedPackagesPath(); - $slug = array_key_first(Arr::where($cachedPackages, static fn (array $package) => in_array(static::class, $package['providers'], true))); + /** + * @psalm-suppress UnresolvableInclude + */ + $cached_packages = require app()->getCachedPackagesPath(); + $slug = array_key_first( + Arr::where( + $cached_packages, + static fn (array $package) => in_array(static::class, $package['providers'], true) + ) + ); static::$slug = $slug; } + /** + * @psalm-suppress NullableReturnStatement + */ return $slug; } diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index f7bb42c8b..eb03e9812 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -1,5 +1,7 @@ share('modules', $controller->getModules()); - Vite::macro('image', fn ($asset) => Vite::asset("resources/images/$asset")); + Vite::macro('image', fn (string $asset) => Vite::asset("resources/images/$asset")); } } diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 6153e4f1b..f5144db7e 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -1,16 +1,17 @@ */ protected $policies = [ // 'App\Models\Model' => 'App\Policies\ModelPolicy', @@ -23,6 +24,5 @@ class AuthServiceProvider extends ServiceProvider { $this->registerPolicies(); - // } } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index b0ca97c67..560482496 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -11,7 +11,7 @@ class EventServiceProvider extends ServiceProvider /** * The event listener mappings for the application. * - * @var array + * @var array> */ protected $listen = [ Registered::class => [ @@ -24,6 +24,5 @@ class EventServiceProvider extends ServiceProvider */ public function boot(): void { - // } } diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index b2825bf29..875ec73fb 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -2,10 +2,7 @@ namespace App\Providers; -use App\Actions\Fortify\CreateNewUser; use App\Actions\Fortify\ResetUserPassword; -use App\Actions\Fortify\UpdateUserPassword; -use App\Actions\Fortify\UpdateUserProfileInformation; use App\Models\User; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Http\Request; @@ -21,7 +18,6 @@ class FortifyServiceProvider extends ServiceProvider */ public function register(): void { - } /** @@ -30,11 +26,11 @@ class FortifyServiceProvider extends ServiceProvider public function boot(): void { Fortify::authenticateUsing(static function (Request $request) { - $user = User::where('email', $request->username) - ->orWhere('username', $request->username) + $user = User::where('email', $request->input('username') + ->orWhere('username', $request->input('username'))) ->first(); - if ($user && Hash::check($request->password, $user->password)) { + if ($user && Hash::check($request->input('password'), $user->password)) { return $user; } @@ -45,13 +41,13 @@ class FortifyServiceProvider extends ServiceProvider // Fortify::updateUserPasswordsUsing(UpdateUserPassword::class); Fortify::resetUserPasswordsUsing(ResetUserPassword::class); - RateLimiter::for('login', function (Request $request) { - $email = (string) $request->email; + RateLimiter::for('login', static function (Request $request) { + $email = (string) $request->input('email'); - return Limit::perMinute(5)->by($email.$request->ip()); + return Limit::perMinute(5)->by($email.((string) $request->ip())); }); - RateLimiter::for('two-factor', function (Request $request) { + RateLimiter::for('two-factor', static function (Request $request) { return Limit::perMinute(5)->by($request->session()->get('login.id')); }); } diff --git a/app/Providers/RestifyServiceProvider.php b/app/Providers/RestifyServiceProvider.php index e94a81570..a93b12e42 100644 --- a/app/Providers/RestifyServiceProvider.php +++ b/app/Providers/RestifyServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use App\Http\Controllers\Controller; +use App\Models\User; use Binaryk\LaravelRestify\Restify; use Binaryk\LaravelRestify\RestifyApplicationServiceProvider; use Illuminate\Support\Facades\Gate; @@ -13,10 +14,13 @@ class RestifyServiceProvider extends RestifyApplicationServiceProvider * Register the Restify gate. * * This gate determines who can access Restify in non-local environments. + * + * @noinspection MissingParentCallInspection + * @noinspection PhpUnusedParameterInspection */ protected function gate(): void { - Gate::define('viewRestify', function ($user) { + Gate::define('viewRestify', static function (User $user) { return true; }); } @@ -28,7 +32,9 @@ class RestifyServiceProvider extends RestifyApplicationServiceProvider // Register repositories from modules $modules = app(Controller::class)->getModules(); foreach ($modules as $module) { - Restify::repositoriesFrom($module['modulePath'].DIRECTORY_SEPARATOR.'src'.DIRECTORY_SEPARATOR.'Api', $module['namespace'].'\Api\\'); + Restify::repositoriesFrom( + $module['modulePath'].DIRECTORY_SEPARATOR.'src'.DIRECTORY_SEPARATOR.'Api', $module['namespace'].'\Api\\' + ); } } } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 21cb355ce..021fe31ff 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -19,15 +19,6 @@ class RouteServiceProvider extends ServiceProvider */ public const HOME = '/dashboard'; - /** - * The controller namespace for the application. - * - * When present, controller route declarations will automatically be prefixed with this namespace. - * - * @var string|null - */ - // protected $namespace = 'App\\Http\\Controllers'; - /** * Define your route model bindings, pattern filters, etc. */ @@ -52,6 +43,6 @@ class RouteServiceProvider extends ServiceProvider */ protected function configureRateLimiting(): void { - RateLimiter::for('api', static fn(Request $request) => Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip())); + RateLimiter::for('api', static fn (Request $request) => Limit::perMinute(60)->by($request->user()?->id ?: $request->ip())); } } diff --git a/app/Restify/Repository.php b/app/Restify/Repository.php index 283f276fd..9e0bd7420 100644 --- a/app/Restify/Repository.php +++ b/app/Restify/Repository.php @@ -2,11 +2,9 @@ namespace App\Restify; +use Binaryk\LaravelRestify\Filters\Filter; use Binaryk\LaravelRestify\Filters\MatchFilter; -use Binaryk\LaravelRestify\Http\Requests\RestifyRequest; use Binaryk\LaravelRestify\Repositories\Repository as RestifyRepository; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Eloquent\Relations\Relation; abstract class Repository extends RestifyRepository { @@ -14,41 +12,8 @@ abstract class Repository extends RestifyRepository public static array $match = ['id']; - /** - * Build a "show" and "index" query for the given repository. - * - * @param \Illuminate\Database\Eloquent\Builder $query - * @return \Illuminate\Database\Eloquent\Builder - */ - public static function mainQuery(RestifyRequest $request, Builder|Relation $query) - { - return $query; - } - - /** - * Build an "index" query for the given repository. - * - * @param \Illuminate\Database\Eloquent\Builder $query - * @return \Illuminate\Database\Eloquent\Builder - */ - public static function indexQuery(RestifyRequest $request, Builder|Relation $query) - { - return $query; - } - - /** - * Build a "show" query for the given repository. - * - * @param \Illuminate\Database\Eloquent\Builder $query - * @return \Illuminate\Database\Eloquent\Builder - */ - public static function showQuery(RestifyRequest $request, Builder|Relation $query) - { - return $query; - } - public static function matches(): array { - return array_map(static fn (string $type) => MatchFilter::make()->setType($type)->partial(), static::$match); + return array_map(static fn (string $type): Filter => MatchFilter::make()->setType($type)->partial(), static::$match); } } diff --git a/app/Restify/UserRepository.php b/app/Restify/UserRepository.php index b3f9486dc..20074acfb 100644 --- a/app/Restify/UserRepository.php +++ b/app/Restify/UserRepository.php @@ -20,9 +20,9 @@ class UserRepository extends Repository { return [ field('username')->rules('required'), - field('email')->storingRules('required', 'unique:users')->updatingRules('unique:users'), - field('created_at')->label('createdAt')->readOnly(), - field('updated_at')->label('updatedAt')->readOnly(), + field('email')->storingRules(['required', 'unique:users'])->updatingRules('unique:users'), + field('created_at')->label('createdAt')->readonly(), + field('updated_at')->label('updatedAt')->readonly(), ]; } } diff --git a/composer.json b/composer.json index ad08a0264..3ae9fe3e8 100644 --- a/composer.json +++ b/composer.json @@ -53,6 +53,7 @@ "friendsofphp/php-cs-fixer": "^3", "fumeapp/modeltyper": "^2.1", "glhd/laravel-dumper": "^1", + "jetbrains/phpstorm-attributes": "@dev", "laravel-lang/attributes": "^2", "laravel-lang/lang": "^12", "laravel-lang/publisher": "^14", diff --git a/config/app.php b/config/app.php index 29a7bcfd4..9d3e48f3e 100644 --- a/config/app.php +++ b/config/app.php @@ -10,7 +10,6 @@ return [ | This value is the name of your application. This value is used when the | framework needs to place the application's name in a notification or | any other location as required by the application or its packages. - | */ 'name' => env('APP_NAME', 'Laravel'), @@ -36,7 +35,6 @@ return [ | When your application is in debug mode, detailed error messages with | stack traces will be shown on every error that occurs within your | application. If disabled, a simple generic error page is shown. - | */ 'debug' => (bool) env('APP_DEBUG', false), @@ -64,7 +62,6 @@ return [ | Here you may specify the default timezone for your application, which | will be used by the PHP date and date-time functions. We have gone | ahead and set this to a sensible default for you out of the box. - | */ 'timezone' => 'Europe/Rome', @@ -76,7 +73,7 @@ return [ | | The application locale determines the default locale that will be used | by the translation service provider. You are free to set this value - | to any of the locales which will be supported by the application. + | to any of the locales, which will be supported by the application. | */ @@ -175,7 +172,7 @@ return [ App\Providers\EventServiceProvider::class, App\Providers\RestifyServiceProvider::class, App\Providers\RouteServiceProvider::class, - \App\Providers\FortifyServiceProvider::class, + App\Providers\FortifyServiceProvider::class, ], @@ -186,12 +183,11 @@ return [ | | This array of class aliases will be registered when this application | is started. However, feel free to register as many as you wish as - | the aliases are "lazy" loaded so they don't hinder performance. + | the aliases are "lazy" loaded, so they don't hinder performance. | */ 'aliases' => [ - 'App' => Illuminate\Support\Facades\App::class, 'Arr' => Illuminate\Support\Arr::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, @@ -232,7 +228,5 @@ return [ 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class, 'Vite' => Illuminate\Support\Facades\Vite::class, - ], - ]; diff --git a/config/auth.php b/config/auth.php index ba1a4d8cb..da5999954 100644 --- a/config/auth.php +++ b/config/auth.php @@ -25,7 +25,7 @@ return [ | | Next, you may define every authentication guard for your application. | Of course, a great default configuration has been defined for you - | here which uses session storage and the Eloquent user provider. + | here, which uses session storage and the Eloquent user provider. | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage @@ -57,8 +57,8 @@ return [ | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | - | If you have multiple user tables or models you may configure multiple - | sources which represent each model / table. These sources may then + | If you have multiple user tables or models, you may configure multiple + | sources, which represent each model / table. These sources may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" @@ -83,13 +83,13 @@ return [ |-------------------------------------------------------------------------- | | You may specify multiple password reset configurations if you have more - | than one user table or model in the application and you want to have + | than one user table or model in the application, and you want to have | separate password reset settings based on the specific user types. | - | The expire time is the number of minutes that the reset token should be - | considered valid. This security feature keeps tokens short-lived so - | they have less time to be guessed. You may change this as needed. - | + | The expiry time is the number of minutes that the reset token should be + | considered valid. + | This security feature keeps tokens short-lived, so they have less time to be guessed. + | You may change this as needed. */ 'passwords' => [ @@ -109,7 +109,6 @@ return [ | Here you may define the amount of seconds before a password confirmation | times out and the user is prompted to re-enter their password via the | confirmation screen. By default, the timeout lasts for three hours. - | */ 'password_timeout' => 10800, diff --git a/config/cache.php b/config/cache.php index 8736c7a7a..6eb5fe942 100644 --- a/config/cache.php +++ b/config/cache.php @@ -101,7 +101,7 @@ return [ | | When utilizing a RAM based store such as APC or Memcached, there might | be other applications utilizing the same cache. So, we'll specify a - | value to get prefixed to all our keys so we can avoid collisions. + | value to get prefixed to all our keys, so we can avoid collisions. | */ diff --git a/config/database.php b/config/database.php index a343e30df..d94adb529 100644 --- a/config/database.php +++ b/config/database.php @@ -24,7 +24,7 @@ return [ | | Here are each of the database connections setup for your application. | Of course, examples of configuring each database platform that is - | supported by Laravel is shown below to make development simple. + | supported by Laravel are shown below to make development simple. | | | All database work in Laravel is done through the PHP PDO facilities @@ -101,7 +101,6 @@ return [ | This table keeps track of all the migrations that have already run for | your application. Using this information, we can determine which of | the migrations on disk haven't actually been run in the database. - | */ 'migrations' => 'migrations', @@ -114,7 +113,6 @@ return [ | Redis is an open source, fast, and advanced key-value store that also | provides a richer body of commands than a typical key-value system | such as APC or Memcached. Laravel makes it easy to dig right in. - | */ 'redis' => [ diff --git a/config/filesystems.php b/config/filesystems.php index 760ef9728..b3482560d 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -10,7 +10,6 @@ return [ | Here you may specify the default filesystem disk that should be used | by the framework. The "local" disk, as well as a variety of cloud | based disks are available to your application. Just store away! - | */ 'default' => env('FILESYSTEM_DRIVER', 'local'), @@ -22,7 +21,7 @@ return [ | | Here you may configure as many filesystem "disks" as you wish, and you | may even configure multiple disks of the same driver. Defaults have - | been setup for each driver as an example of the required options. + | been set up for each driver as an example of the required options. | | Supported Drivers: "local", "ftp", "sftp", "s3" | @@ -63,7 +62,6 @@ return [ | Here you may configure the symbolic links that will be created when the | `storage:link` Artisan command is executed. The array keys should be | the locations of the links and the values should be their targets. - | */ 'links' => [ diff --git a/config/restify.php b/config/restify.php index 59ed84b08..6b0b08c47 100644 --- a/config/restify.php +++ b/config/restify.php @@ -47,7 +47,7 @@ return [ 'user_verify_url' => env('FRONTEND_APP_URL').'/verify/{id}/{emailHash}', - 'user_model' => "\App\Models\User", + 'user_model' => App\Models\User::class, ], /* diff --git a/database/migrations/2014_10_12_200000_add_two_factor_columns_to_users_table.php b/database/migrations/2014_10_12_200000_add_two_factor_columns_to_users_table.php index 1a6512d1b..8e24c8246 100644 --- a/database/migrations/2014_10_12_200000_add_two_factor_columns_to_users_table.php +++ b/database/migrations/2014_10_12_200000_add_two_factor_columns_to_users_table.php @@ -12,7 +12,7 @@ return new class() extends Migration */ public function up(): void { - Schema::table('users', function (Blueprint $table) { + Schema::table('users', static function (Blueprint $table) { $table->text('two_factor_secret') ->after('password') ->nullable(); @@ -34,13 +34,10 @@ return new class() extends Migration */ public function down(): void { - Schema::table('users', function (Blueprint $table) { - $table->dropColumn(array_merge([ - 'two_factor_secret', - 'two_factor_recovery_codes', - ], Fortify::confirmsTwoFactorAuthentication() ? [ + Schema::table('users', static function (Blueprint $table) { + $table->dropColumn(['two_factor_secret', 'two_factor_recovery_codes', ...Fortify::confirmsTwoFactorAuthentication() ? [ 'two_factor_confirmed_at', - ] : [])); + ] : []]); }); } }; diff --git a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php index 0fc7a6367..81eb0ccc6 100644 --- a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php +++ b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php @@ -11,7 +11,7 @@ return new class() extends Migration */ public function up(): void { - Schema::create('personal_access_tokens', function (Blueprint $table) { + Schema::create('personal_access_tokens', static function (Blueprint $table) { $table->id(); $table->morphs('tokenable'); $table->string('name'); diff --git a/database/migrations/2023_02_23_174814_create_action_logs_table.php b/database/migrations/2023_02_23_174814_create_action_logs_table.php index 31c338c7c..4da0e2a65 100644 --- a/database/migrations/2023_02_23_174814_create_action_logs_table.php +++ b/database/migrations/2023_02_23_174814_create_action_logs_table.php @@ -8,12 +8,10 @@ return new class() extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { - Schema::create('action_logs', function (Blueprint $table) { + Schema::create('action_logs', static function (Blueprint $table) { $table->id(); $table->char('batch_id', 36); $table->unsignedBigInteger('user_id')->index()->nullable(); @@ -39,10 +37,8 @@ return new class() extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('action_logs'); } diff --git a/psalm.xml b/psalm.xml index 2567783b8..de13099f4 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,14 +1,18 @@ + + + + diff --git a/resources/images/favicon/safari-pinned-tab.svg b/resources/images/favicon/safari-pinned-tab.svg index 8f9fcfc01..f1c78ae50 100644 --- a/resources/images/favicon/safari-pinned-tab.svg +++ b/resources/images/favicon/safari-pinned-tab.svg @@ -1,15 +1,15 @@ + "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> - -Created by potrace 1.14, written by Peter Selinger 2001-2017 - - - + + Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + - + diff --git a/resources/scss/_material.scss b/resources/scss/_material.scss index 391d716dd..20c608ecc 100644 --- a/resources/scss/_material.scss +++ b/resources/scss/_material.scss @@ -9,15 +9,14 @@ md-icon svg { } :is(md-list-item, md-list-item-link) md-icon { - padding-left: 16px; --md-icon-color: var(--_list-item-leading-icon-color); - // TODO: MD Tokens sets the icon size to 18px, but the list item icon is 24px per the specs. - //svg { - //width: var(--_list-item-leading-icon-size, var(--_with-icon-icon-size, var(--_icon-size, var(--_size)))); - //height: var(--_list-item-leading-icon-size, var(--_with-icon-icon-size, var(--_icon-size, var(--_size)))); - // line-height: 0; - //} + padding-left: 16px; + + svg { + width: var(--_list-item-leading-icon-size, var(--_with-icon-icon-size, var(--_icon-size, var(--_size)))); + height: var(--_list-item-leading-icon-size, var(--_with-icon-icon-size, var(--_icon-size, var(--_size)))); + } } label:has(> md-checkbox) { @@ -30,32 +29,35 @@ md-filled-text-field, md-outlined-text-field { } md-navigation-drawer, md-navigation-drawer-modal { - //--mdc-theme-surface: var(--md-sys-color-background, #fff); - //--mdc-theme-primary: var(--mdc-theme-primary2, variables.$primary); - - //noinspection Stylelint > md-list { display: flex; justify-content: center; md-list-item-link { - display: block; - width: 85%; --md-list-item-list-item-container-shape: 100px; --md-ripple-shape: 100px; - //--md-focus-ring-shape-start-start: 100px; - //--md-focus-ring-shape-start-end: 100px; - //--md-focus-ring-shape-end-start: 100px; - //--md-focus-ring-shape-end-end: 100px; + + display: block; + width: 85%; &[active] { --md-list-item-list-item-container-color: var(--md-sys-color-secondary-container, #3f51b5); } + + md-icon[slot="start"] svg { + // TODO: Waiting for token implementation in Material Web + // (see https://m3.material.io/components/navigation-drawer/specs#ce8bfbcf-3dec-45d2-9d8b-5e10af1cf87d) + width: 24px; + height: 24px; + } } } } top-app-bar { + --mdc-theme-primary: var(--md-sys-color-surface, #fff); + --mdc-theme-on-primary: var(--md-sys-color-on-surface, #5f6368); + width: 100%; [slot="navigationIcon"], [slot="title"] { @@ -65,9 +67,6 @@ top-app-bar { [slot="actionItems"] { --md-icon-color: var(--md-sys-color-on-surface-variant, #5f6368); } - - --mdc-theme-primary: var(--md-sys-color-surface, #fff); - --mdc-theme-on-primary: var(--md-sys-color-on-surface, #5f6368); } md-fab, md-branded-fab { diff --git a/resources/scss/_variables.scss b/resources/scss/_variables.scss index e440eda40..117a16045 100644 --- a/resources/scss/_variables.scss +++ b/resources/scss/_variables.scss @@ -1,3 +1,3 @@ // Font -$headings_font: "Montserrat, sans-serif"; -$body_font: "Nunito, sans-serif"; +$heading-font: "Montserrat, sans-serif"; +$body-font: "Nunito, sans-serif"; diff --git a/resources/scss/app.scss b/resources/scss/app.scss index 19bc64e3b..3f824ad62 100644 --- a/resources/scss/app.scss +++ b/resources/scss/app.scss @@ -18,19 +18,13 @@ body { } #app { - min-height: 100vh; display: grid; grid-template-rows: 1fr auto; -} - -.center-block { - display: block; - margin: 0 auto; + min-height: 100vh; } .center-logo { - @extend .center-block; - + display: block; width: fit-content; max-width: 100%; margin: 0 auto; @@ -41,29 +35,27 @@ body { flex-direction: column; align-items: center; justify-content: center; + + box-sizing: border-box; height: 100%; padding: 16px; - box-sizing: border-box; } .ext-card { --md-card-padding: 16px; - margin-top: 48px; @include media.media(">desktop") { max-width: 55vw; } + + margin-top: 48px; } .setup-buttons, .login-buttons { - display: flex; - justify-content: space-around; - margin: 16px 0; @include media.media("<=tablet") { &:has(:nth-child(3)) { - flex-direction: column; - flex-wrap: wrap; + flex-flow: column wrap; gap: 16px; & > * { @@ -71,30 +63,16 @@ body { } } } + + display: flex; + justify-content: space-around; + margin: 16px 0; } .flag { width: 32px; } -.stretch { - //noinspection CssInvalidPropertyValue - width: stretch; -} - -.logo-bg-sticky { - position: fixed; - z-index: 1; - top: 60%; - right: -15%; - width: 500px; - opacity: 0.1; -} - -.record-dialog { - --mdc-layout-grid-margin-desktop: 0; -} - .user-image { width: 150px; border-radius: 50%; @@ -109,12 +87,15 @@ body { --------------------------- */ footer { display: flex; + width: 100%; padding-top: 10px; padding-bottom: 10px; - background-color: var(--md-sys-color-surface, white); + color: var(--md-sys-color-on-surface, #000); + background-color: var(--md-sys-color-surface, white); + > :first-child { flex: 1; padding-left: 16px; @@ -124,6 +105,4 @@ footer { padding-right: 16px; text-align: right; } - - //--mdc-theme-primary: #{variables.$primary}; } diff --git a/resources/scss/theme/theme.scss b/resources/scss/theme/theme.scss index 3827509d3..407933c7a 100644 --- a/resources/scss/theme/theme.scss +++ b/resources/scss/theme/theme.scss @@ -7,8 +7,8 @@ body { @extend .body-large; - background-color: var(--md-sys-color-background, #fff); color: var(--md-sys-color-on-background); + background-color: var(--md-sys-color-background, #fff); } small { @@ -26,31 +26,31 @@ $headings: ( @each $selector, $class in $headings { #{$selector} { - color: var(--md-sys-color-on-surface); - @extend .#{$class}; + + color: var(--md-sys-color-on-surface); } } a { - border-radius: 4px; color: var(--md-sys-color-primary); text-decoration: underline; + border-radius: 4px; &:hover { color: var(--md-sys-color-on-primary-container); } &:focus { - border: 1px solid var(--md-sys-color-primary); margin: -1px; - box-shadow: inset 0 0 0 1px var(--md-sys-color-surface); + border: 1px solid var(--md-sys-color-primary); outline: 0; + box-shadow: inset 0 0 0 1px var(--md-sys-color-surface); } &:hover:focus { - border: 1px solid var(--md-sys-color-on-primary-container); color: var(--md-sys-color-on-primary-container); + border: 1px solid var(--md-sys-color-on-primary-container); outline: 0; } } diff --git a/resources/scss/theme/tokens.scss b/resources/scss/theme/tokens.scss index 3449d2bdb..e00abc998 100644 --- a/resources/scss/theme/tokens.scss +++ b/resources/scss/theme/tokens.scss @@ -1,4 +1,7 @@ :root { + $headlines-font-family: 'Plus Jakarta Sans'; + $body-font-family: 'Kantumruy Pro'; + --md-source: #e8a80f; /* primary */ @@ -173,9 +176,7 @@ --md-sys-color-outline-variant-dark: #4e4639; --md-sys-color-scrim-dark: #000; - $headlines-font-family: 'Plus Jakarta Sans'; - $body-font-family: 'Kantumruy Pro'; - + /* typography */ --md-ref-typeface-brand: #{$headlines-font-family}; --md-ref-typeface-plain: #{$body-font-family}; diff --git a/resources/scss/theme/typography.scss b/resources/scss/theme/typography.scss index 6019eab15..78f3d5e24 100644 --- a/resources/scss/theme/typography.scss +++ b/resources/scss/theme/typography.scss @@ -1,164 +1,164 @@ .display-large { font-family: var(--md-sys-typescale-display-large-font-family-name); font-size: var(--md-sys-typescale-display-large-font-size); - font-style: var(--md-sys-typescale-display-large-font-family-style); font-weight: var(--md-sys-typescale-display-large-font-weight); - letter-spacing: var(--md-sys-typescale-display-large-tracking); + font-style: var(--md-sys-typescale-display-large-font-family-style); line-height: var(--md-sys-typescale-display-large-height); text-decoration: var(--md-sys-typescale-display-large-text-decoration); text-transform: var(--md-sys-typescale-display-large-text-transform); + letter-spacing: var(--md-sys-typescale-display-large-tracking); } .display-medium { font-family: var(--md-sys-typescale-display-medium-font-family-name); font-size: var(--md-sys-typescale-display-medium-font-size); - font-style: var(--md-sys-typescale-display-medium-font-family-style); font-weight: var(--md-sys-typescale-display-medium-font-weight); - letter-spacing: var(--md-sys-typescale-display-medium-tracking); + font-style: var(--md-sys-typescale-display-medium-font-family-style); line-height: var(--md-sys-typescale-display-medium-height); text-decoration: var(--md-sys-typescale-display-medium-text-decoration); text-transform: var(--md-sys-typescale-display-medium-text-transform); + letter-spacing: var(--md-sys-typescale-display-medium-tracking); } .display-small { font-family: var(--md-sys-typescale-display-small-font-family-name); font-size: var(--md-sys-typescale-display-small-font-size); - font-style: var(--md-sys-typescale-display-small-font-family-style); font-weight: var(--md-sys-typescale-display-small-font-weight); - letter-spacing: var(--md-sys-typescale-display-small-tracking); + font-style: var(--md-sys-typescale-display-small-font-family-style); line-height: var(--md-sys-typescale-display-small-height); text-decoration: var(--md-sys-typescale-display-small-text-decoration); text-transform: var(--md-sys-typescale-display-small-text-transform); + letter-spacing: var(--md-sys-typescale-display-small-tracking); } .headline-large { font-family: var(--md-sys-typescale-headline-large-font-family-name); font-size: var(--md-sys-typescale-headline-large-font-size); - font-style: var(--md-sys-typescale-headline-large-font-family-style); font-weight: var(--md-sys-typescale-headline-large-font-weight); - letter-spacing: var(--md-sys-typescale-headline-large-tracking); + font-style: var(--md-sys-typescale-headline-large-font-family-style); line-height: var(--md-sys-typescale-headline-large-height); text-decoration: var(--md-sys-typescale-headline-large-text-decoration); text-transform: var(--md-sys-typescale-headline-large-text-transform); + letter-spacing: var(--md-sys-typescale-headline-large-tracking); } .headline-medium { font-family: var(--md-sys-typescale-headline-medium-font-family-name); font-size: var(--md-sys-typescale-headline-medium-font-size); - font-style: var(--md-sys-typescale-headline-medium-font-family-style); font-weight: var(--md-sys-typescale-headline-medium-font-weight); - letter-spacing: var(--md-sys-typescale-headline-medium-tracking); + font-style: var(--md-sys-typescale-headline-medium-font-family-style); line-height: var(--md-sys-typescale-headline-medium-height); text-decoration: var(--md-sys-typescale-headline-medium-text-decoration); text-transform: var(--md-sys-typescale-headline-medium-text-transform); + letter-spacing: var(--md-sys-typescale-headline-medium-tracking); } .headline-small { font-family: var(--md-sys-typescale-headline-small-font-family-name); font-size: var(--md-sys-typescale-headline-small-font-size); - font-style: var(--md-sys-typescale-headline-small-font-family-style); font-weight: var(--md-sys-typescale-headline-small-font-weight); - letter-spacing: var(--md-sys-typescale-headline-small-tracking); + font-style: var(--md-sys-typescale-headline-small-font-family-style); line-height: var(--md-sys-typescale-headline-small-height); text-decoration: var(--md-sys-typescale-headline-small-text-decoration); text-transform: var(--md-sys-typescale-headline-small-text-transform); + letter-spacing: var(--md-sys-typescale-headline-small-tracking); } .body-large { font-family: var(--md-sys-typescale-body-large-font-family-name); font-size: var(--md-sys-typescale-body-large-font-size); - font-style: var(--md-sys-typescale-body-large-font-family-style); font-weight: var(--md-sys-typescale-body-large-font-weight); - letter-spacing: var(--md-sys-typescale-body-large-tracking); + font-style: var(--md-sys-typescale-body-large-font-family-style); line-height: var(--md-sys-typescale-body-large-height); text-decoration: var(--md-sys-typescale-body-large-text-decoration); text-transform: var(--md-sys-typescale-body-large-text-transform); + letter-spacing: var(--md-sys-typescale-body-large-tracking); } .body-medium { font-family: var(--md-sys-typescale-body-medium-font-family-name); font-size: var(--md-sys-typescale-body-medium-font-size); - font-style: var(--md-sys-typescale-body-medium-font-family-style); font-weight: var(--md-sys-typescale-body-medium-font-weight); - letter-spacing: var(--md-sys-typescale-body-medium-tracking); + font-style: var(--md-sys-typescale-body-medium-font-family-style); line-height: var(--md-sys-typescale-body-medium-height); text-decoration: var(--md-sys-typescale-body-medium-text-decoration); text-transform: var(--md-sys-typescale-body-medium-text-transform); + letter-spacing: var(--md-sys-typescale-body-medium-tracking); } .body-small { font-family: var(--md-sys-typescale-body-small-font-family-name); font-size: var(--md-sys-typescale-body-small-font-size); - font-style: var(--md-sys-typescale-body-small-font-family-style); font-weight: var(--md-sys-typescale-body-small-font-weight); - letter-spacing: var(--md-sys-typescale-body-small-tracking); + font-style: var(--md-sys-typescale-body-small-font-family-style); line-height: var(--md-sys-typescale-body-small-height); text-decoration: var(--md-sys-typescale-body-small-text-decoration); text-transform: var(--md-sys-typescale-body-small-text-transform); + letter-spacing: var(--md-sys-typescale-body-small-tracking); } .label-large { font-family: var(--md-sys-typescale-label-large-font-family-name); font-size: var(--md-sys-typescale-label-large-font-size); - font-style: var(--md-sys-typescale-label-large-font-family-style); font-weight: var(--md-sys-typescale-label-large-font-weight); - letter-spacing: var(--md-sys-typescale-label-large-tracking); + font-style: var(--md-sys-typescale-label-large-font-family-style); line-height: var(--md-sys-typescale-label-large-height); text-decoration: var(--md-sys-typescale-label-large-text-decoration); text-transform: var(--md-sys-typescale-label-large-text-transform); + letter-spacing: var(--md-sys-typescale-label-large-tracking); } .label-medium { font-family: var(--md-sys-typescale-label-medium-font-family-name); font-size: var(--md-sys-typescale-label-medium-font-size); - font-style: var(--md-sys-typescale-label-medium-font-family-style); font-weight: var(--md-sys-typescale-label-medium-font-weight); - letter-spacing: var(--md-sys-typescale-label-medium-tracking); + font-style: var(--md-sys-typescale-label-medium-font-family-style); line-height: var(--md-sys-typescale-label-medium-height); text-decoration: var(--md-sys-typescale-label-medium-text-decoration); text-transform: var(--md-sys-typescale-label-medium-text-transform); + letter-spacing: var(--md-sys-typescale-label-medium-tracking); } .label-small { font-family: var(--md-sys-typescale-label-small-font-family-name); font-size: var(--md-sys-typescale-label-small-font-size); - font-style: var(--md-sys-typescale-label-small-font-family-style); font-weight: var(--md-sys-typescale-label-small-font-weight); - letter-spacing: var(--md-sys-typescale-label-small-tracking); + font-style: var(--md-sys-typescale-label-small-font-family-style); line-height: var(--md-sys-typescale-label-small-height); text-decoration: var(--md-sys-typescale-label-small-text-decoration); text-transform: var(--md-sys-typescale-label-small-text-transform); + letter-spacing: var(--md-sys-typescale-label-small-tracking); } .title-large { font-family: var(--md-sys-typescale-title-large-font-family-name); font-size: var(--md-sys-typescale-title-large-font-size); - font-style: var(--md-sys-typescale-title-large-font-family-style); font-weight: var(--md-sys-typescale-title-large-font-weight); - letter-spacing: var(--md-sys-typescale-title-large-tracking); + font-style: var(--md-sys-typescale-title-large-font-family-style); line-height: var(--md-sys-typescale-title-large-height); text-decoration: var(--md-sys-typescale-title-large-text-decoration); text-transform: var(--md-sys-typescale-title-large-text-transform); + letter-spacing: var(--md-sys-typescale-title-large-tracking); } .title-medium { font-family: var(--md-sys-typescale-title-medium-font-family-name); font-size: var(--md-sys-typescale-title-medium-font-size); - font-style: var(--md-sys-typescale-title-medium-font-family-style); font-weight: var(--md-sys-typescale-title-medium-font-weight); - letter-spacing: var(--md-sys-typescale-title-medium-tracking); + font-style: var(--md-sys-typescale-title-medium-font-family-style); line-height: var(--md-sys-typescale-title-medium-height); text-decoration: var(--md-sys-typescale-title-medium-text-decoration); text-transform: var(--md-sys-typescale-title-medium-text-transform); + letter-spacing: var(--md-sys-typescale-title-medium-tracking); } .title-small { font-family: var(--md-sys-typescale-title-small-font-family-name); font-size: var(--md-sys-typescale-title-small-font-size); - font-style: var(--md-sys-typescale-title-small-font-family-style); font-weight: var(--md-sys-typescale-title-small-font-weight); - letter-spacing: var(--md-sys-typescale-title-small-tracking); + font-style: var(--md-sys-typescale-title-small-font-family-style); line-height: var(--md-sys-typescale-title-small-height); text-decoration: var(--md-sys-typescale-title-small-text-decoration); text-transform: var(--md-sys-typescale-title-small-text-transform); + letter-spacing: var(--md-sys-typescale-title-small-tracking); } diff --git a/resources/ts/Components/DataTable/DataTable.tsx b/resources/ts/Components/DataTable/DataTable.tsx index 8bccc1c51..889c69044 100644 --- a/resources/ts/Components/DataTable/DataTable.tsx +++ b/resources/ts/Components/DataTable/DataTable.tsx @@ -6,7 +6,6 @@ import { mdiPageFirst, mdiPageLast } from '@mdi/js'; - import MdIcon from '@osm/Components/MdIcon'; import { Children, diff --git a/resources/ts/Components/DataTable/DataTableColumn.tsx b/resources/ts/Components/DataTable/DataTableColumn.tsx index 556435a65..3f4c78084 100644 --- a/resources/ts/Components/DataTable/DataTableColumn.tsx +++ b/resources/ts/Components/DataTable/DataTableColumn.tsx @@ -5,7 +5,6 @@ import { mdiArrowDown, mdiArrowUp } from '@mdi/js'; - import MdIcon from '@osm/Components/MdIcon'; import {Vnode} from 'mithril'; import { diff --git a/resources/ts/Components/DataTable/RecordsTable.tsx b/resources/ts/Components/DataTable/RecordsTable.tsx index 75c1b6654..0d3df78b4 100644 --- a/resources/ts/Components/DataTable/RecordsTable.tsx +++ b/resources/ts/Components/DataTable/RecordsTable.tsx @@ -9,7 +9,6 @@ import { } from '@maicol07/material-web-additions/data-table/lib/data-table'; import {DataTableCell} from '@maicol07/material-web-additions/data-table/lib/data-table-cell'; import {mdiDeleteOutline} from '@mdi/js'; - import DataTable, {DataTableAttributes} from '@osm/Components/DataTable/DataTable'; import DataTableColumn, {DataTableColumnAttributes} from '@osm/Components/DataTable/DataTableColumn'; import RecordsTableColumn from '@osm/Components/DataTable/RecordsTableColumn'; @@ -86,9 +85,14 @@ export default class RecordsTable, A extends RecordsTa columns.put('checkbox', ); } + // noinspection NestedFunctionJS + function isDataTableColumn(column: Vnode>): boolean { + return (typeof column.tag !== 'string' && (column.tag as Class).prototype instanceof DataTableColumn); + } + columns = columns.merge(vnode.attrs.cols.map((column: Children | RecordsTableColumnAttributes, attribute: string) => { // If the column is a vnode, and it is a DataTableColumn or a string that matches the tag name of a DataTableColumn, then use it as is. - if (isVnode>(column) && (column.tag === 'md-data-table-column' || (typeof column.tag !== 'string' && (column.tag as Class).prototype instanceof DataTableColumn))) { + if (isVnode>(column) && (column.tag === 'md-data-table-column' || isDataTableColumn(column))) { column.key ??= attribute; column.attrs['data-model-attribute'] ??= attribute; return column; @@ -123,6 +127,7 @@ export default class RecordsTable, A extends RecordsTa noRecordsContent(vnode: Vnode): Children { const colspan = vnode.attrs.cols.count() + (vnode.attrs.selectable ? 1 : 0) + (vnode.attrs.readonly ? 0 : 1); + // noinspection JSXDomNesting return ( {__('Nessun record trovato')} diff --git a/resources/ts/Components/Dialogs/AddEditRecordDialog.tsx b/resources/ts/Components/Dialogs/AddEditRecordDialog.tsx index 4ddcaec37..e87e650dc 100644 --- a/resources/ts/Components/Dialogs/AddEditRecordDialog.tsx +++ b/resources/ts/Components/Dialogs/AddEditRecordDialog.tsx @@ -1,5 +1,4 @@ import {mdiFloppy} from '@mdi/js'; - import RecordDialog, {RecordDialogAttributes} from '@osm/Components/Dialogs/RecordDialog'; import MdIcon from '@osm/Components/MdIcon'; import Model from '@osm/Models/Model'; @@ -14,8 +13,8 @@ import { Vnode, VnodeDOM } from 'mithril'; -import {Form} from 'mithril-utilities'; import Stream from 'mithril/stream'; +import {Form} from 'mithril-utilities'; import {Class} from 'type-fest'; export default abstract class AddEditRecordDialog> extends RecordDialog { diff --git a/resources/ts/Components/Dialogs/Dialog.tsx b/resources/ts/Components/Dialogs/Dialog.tsx index df4a7823f..fda6aaeb7 100644 --- a/resources/ts/Components/Dialogs/Dialog.tsx +++ b/resources/ts/Components/Dialogs/Dialog.tsx @@ -8,16 +8,16 @@ import { Vnode, VnodeDOM } from 'mithril'; +import Stream from 'mithril/stream'; import { Attributes, Component } from 'mithril-utilities'; -import Stream from 'mithril/stream'; export interface DialogAttributes extends Attributes, Partial> { open?: Stream; onOpen?: () => void; diff --git a/resources/ts/Components/Dialogs/RecordDialog.tsx b/resources/ts/Components/Dialogs/RecordDialog.tsx index ad23a6bed..9f869297e 100644 --- a/resources/ts/Components/Dialogs/RecordDialog.tsx +++ b/resources/ts/Components/Dialogs/RecordDialog.tsx @@ -3,7 +3,6 @@ import '@material/web/button/text-button.js'; import Dialog, {DialogAttributes} from '@osm/Components/Dialogs/Dialog'; import Model from '@osm/Models/Model'; - import {Vnode} from 'mithril'; export interface RecordDialogAttributes> extends DialogAttributes { diff --git a/resources/ts/Components/Page.tsx b/resources/ts/Components/Page.tsx index 1e4a652d5..28f75e634 100644 --- a/resources/ts/Components/Page.tsx +++ b/resources/ts/Components/Page.tsx @@ -1,6 +1,5 @@ import autoAnimate from '@formkit/auto-animate'; import {ComponentAttributes} from '@maicol07/inertia-mithril'; - import Footer from '@osm/Components/layout/Footer'; import {Collection} from 'collect.js'; import { diff --git a/resources/ts/Components/Pages/RecordPage.tsx b/resources/ts/Components/Pages/RecordPage.tsx index 592a9b194..acce40c5b 100644 --- a/resources/ts/Components/Pages/RecordPage.tsx +++ b/resources/ts/Components/Pages/RecordPage.tsx @@ -1,7 +1,6 @@ import '@material/web/button/outlined-button.js'; import {mdiChevronLeft} from '@mdi/js'; - import MdIcon from '@osm/Components/MdIcon'; import Page, {PageAttributes} from '@osm/Components/Page'; import Model from '@osm/Models/Model'; diff --git a/resources/ts/Components/Pages/RecordsPage.tsx b/resources/ts/Components/Pages/RecordsPage.tsx index dcd5e4baf..7fc332b6f 100644 --- a/resources/ts/Components/Pages/RecordsPage.tsx +++ b/resources/ts/Components/Pages/RecordsPage.tsx @@ -1,15 +1,15 @@ /* eslint-disable sonarjs/no-duplicate-string */ +import '@maicol07/material-web-additions/layout-grid/layout-grid.js'; +import '@material/web/dialog/dialog.js'; +import '@material/web/fab/branded-fab.js'; +import '@material/web/iconbutton/standard-icon-button.js'; + import {router} from '@maicol07/inertia-mithril'; import { FilterTextFieldInputEventDetail, SortButtonClickedEventDetail } from '@maicol07/material-web-additions/data-table/lib/data-table-column.js'; -import '@maicol07/material-web-additions/layout-grid/layout-grid.js'; -import '@material/web/dialog/dialog.js'; -import '@material/web/fab/branded-fab.js'; -import '@material/web/iconbutton/standard-icon-button.js'; import {mdiPlus} from '@mdi/js'; - import RecordsTable, {RecordsTableColumnAttributes} from '@osm/Components/DataTable/RecordsTable'; import AddEditRecordDialog from '@osm/Components/Dialogs/AddEditRecordDialog'; import DeleteRecordDialog, {DeleteRecordDialogAttributes} from '@osm/Components/Dialogs/DeleteRecordDialog'; diff --git a/resources/ts/Components/extend/extend.ts b/resources/ts/Components/extend/extend.ts index 296d9e20e..704c5dbc0 100644 --- a/resources/ts/Components/extend/extend.ts +++ b/resources/ts/Components/extend/extend.ts @@ -4,7 +4,7 @@ /** * Type that returns an array of all keys of a provided object that are of - * of the provided type, or a subtype of the type. + * the provided type, or a subtype of the type. */ declare type KeysOfType = { [Key in keyof Type]-?: Type[Key] extends Match ? Key : never; @@ -39,7 +39,7 @@ declare type KeyOfType = KeysOfType[key * * @param object The object that owns the method * @param methods The name or names of the method(s) to extend - * @param callback A callback which mutates the method's output + * @param callback A callback, which mutates the method's output. */ export function extend, K extends KeyOfType>( object: T, @@ -89,7 +89,7 @@ export function extend, K extends KeyOfType, K extends KeyOfType>( object: T, diff --git a/resources/ts/Components/layout/Drawer.tsx b/resources/ts/Components/layout/Drawer.tsx index 1dd713847..6d681cfa4 100644 --- a/resources/ts/Components/layout/Drawer.tsx +++ b/resources/ts/Components/layout/Drawer.tsx @@ -1,11 +1,12 @@ import '@material/web/list/list.js'; +import '../m3/NavigationDrawer'; +import '../m3/NavigationDrawerModal'; import { mdiAccountGroupOutline, mdiMenuOpen, mdiViewDashboardOutline } from '@mdi/js'; - import MdIcon from '@osm/Components/MdIcon'; import {VnodeCollectionItem} from '@osm/typings/jsx'; import {isMobile} from '@osm/utils/misc'; @@ -14,13 +15,11 @@ import { Children, Vnode } from 'mithril'; +import Stream from 'mithril/stream'; import { Attributes, Component } from 'mithril-utilities'; -import Stream from 'mithril/stream'; -import '../m3/NavigationDrawer'; -import '../m3/NavigationDrawerModal'; import {DrawerEntry} from './DrawerEntry'; diff --git a/resources/ts/Components/layout/DrawerEntry.tsx b/resources/ts/Components/layout/DrawerEntry.tsx index 84d885482..874131b53 100644 --- a/resources/ts/Components/layout/DrawerEntry.tsx +++ b/resources/ts/Components/layout/DrawerEntry.tsx @@ -1,9 +1,9 @@ -import {router} from '@maicol07/inertia-mithril'; import '@material/web/icon/icon.js'; -import {ListItemLink} from '@material/web/list/lib/listitemlink/list-item-link'; import '@material/web/list/list-item-link.js'; -import type * as MaterialIcons from '@mdi/js'; +import {router} from '@maicol07/inertia-mithril'; +import {ListItemLink} from '@material/web/list/lib/listitemlink/list-item-link'; +import type * as MaterialIcons from '@mdi/js'; import MdIcon from '@osm/Components/MdIcon'; import {Vnode} from 'mithril'; import { diff --git a/resources/ts/Components/layout/TopAppBar.tsx b/resources/ts/Components/layout/TopAppBar.tsx index 3797d1cad..1672e57b0 100644 --- a/resources/ts/Components/layout/TopAppBar.tsx +++ b/resources/ts/Components/layout/TopAppBar.tsx @@ -1,10 +1,10 @@ import '@material/web/iconbutton/standard-icon-button.js'; +import '@osm/WebComponents/TopAppBar'; import { mdiMenu, mdiMenuOpen } from '@mdi/js'; - import logo from '@osm/../images/logo.png'; import Drawer from '@osm/Components/layout/Drawer'; import NotificationsAction from '@osm/Components/layout/topappbar_actions/NotificationsAction'; @@ -17,17 +17,16 @@ import { isMobile, mobileMediaQuery } from '@osm/utils/misc'; -import '@osm/WebComponents/TopAppBar'; import {collect} from 'collect.js'; import { Vnode, VnodeDOM } from 'mithril'; +import Stream from 'mithril/stream'; import { Attributes, Component } from 'mithril-utilities'; -import Stream from 'mithril/stream'; export default class TopAppBar extends Component { drawerOpenState = Stream(!isMobile()); diff --git a/resources/ts/Components/layout/topappbar_actions/NotificationsAction.ts b/resources/ts/Components/layout/topappbar_actions/NotificationsAction.ts index 0a677eaf8..42c618a94 100644 --- a/resources/ts/Components/layout/topappbar_actions/NotificationsAction.ts +++ b/resources/ts/Components/layout/topappbar_actions/NotificationsAction.ts @@ -1,5 +1,4 @@ import {mdiBellOutline} from '@mdi/js'; - import TopAppBarAction from '@osm/Components/layout/topappbar_actions/TopAppBarAction'; export default class NotificationsAction extends TopAppBarAction { diff --git a/resources/ts/Components/layout/topappbar_actions/PeriodSwitcherAction.ts b/resources/ts/Components/layout/topappbar_actions/PeriodSwitcherAction.ts index cf89e6d21..8f74ff7d4 100644 --- a/resources/ts/Components/layout/topappbar_actions/PeriodSwitcherAction.ts +++ b/resources/ts/Components/layout/topappbar_actions/PeriodSwitcherAction.ts @@ -1,5 +1,4 @@ import {mdiCalendarRangeOutline} from '@mdi/js'; - import TopAppBarAction from '@osm/Components/layout/topappbar_actions/TopAppBarAction'; export default class PeriodSwitcherAction extends TopAppBarAction { diff --git a/resources/ts/Components/layout/topappbar_actions/UserInfoAction.tsx b/resources/ts/Components/layout/topappbar_actions/UserInfoAction.tsx index fcf518d4a..ca8f4515e 100644 --- a/resources/ts/Components/layout/topappbar_actions/UserInfoAction.tsx +++ b/resources/ts/Components/layout/topappbar_actions/UserInfoAction.tsx @@ -1,17 +1,17 @@ -import {router} from '@maicol07/inertia-mithril'; import '@material/web/button/outlined-button.js'; import '@material/web/button/text-button.js'; + +import {router} from '@maicol07/inertia-mithril'; import { mdiAccountCircleOutline, mdiAccountOutline, mdiLogoutVariant } from '@mdi/js'; - import Dialog from '@osm/Components/Dialogs/Dialog'; import MdIcon from '@osm/Components/MdIcon'; import {Vnode} from 'mithril'; -import {Request} from 'mithril-utilities'; import Stream from 'mithril/stream'; +import {Request} from 'mithril-utilities'; import TopAppBarAction from './TopAppBarAction'; diff --git a/resources/ts/Components/m3/NavigationDrawer.ts b/resources/ts/Components/m3/NavigationDrawer.ts index 0f8e24d3c..1ce75ef7f 100644 --- a/resources/ts/Components/m3/NavigationDrawer.ts +++ b/resources/ts/Components/m3/NavigationDrawer.ts @@ -1,5 +1,5 @@ -import {styles} from '@material/web/navigationdrawer/lib/navigation-drawer-styles.css.js'; import {NavigationDrawer as MDNavigationDrawer} from '@material/web/navigationdrawer/lib/navigation-drawer.js'; +import {styles} from '@material/web/navigationdrawer/lib/navigation-drawer-styles.css.js'; import {styles as sharedStyles} from '@material/web/navigationdrawer/lib/shared-styles.css.js'; import {css} from 'lit'; import {customElement} from 'lit/decorators.js'; diff --git a/resources/ts/Components/m3/NavigationDrawerModal.ts b/resources/ts/Components/m3/NavigationDrawerModal.ts index 27f03027c..5f941c85e 100644 --- a/resources/ts/Components/m3/NavigationDrawerModal.ts +++ b/resources/ts/Components/m3/NavigationDrawerModal.ts @@ -1,5 +1,5 @@ -import {styles} from '@material/web/navigationdrawer/lib/navigation-drawer-modal-styles.css.js'; import {NavigationDrawerModal as MDNavigationDrawerModal} from '@material/web/navigationdrawer/lib/navigation-drawer-modal.js'; +import {styles} from '@material/web/navigationdrawer/lib/navigation-drawer-modal-styles.css.js'; import {styles as sharedStyles} from '@material/web/navigationdrawer/lib/shared-styles.css.js'; import {css} from 'lit'; import {customElement} from 'lit/decorators.js'; diff --git a/resources/ts/Views/LoginPage.tsx b/resources/ts/Views/LoginPage.tsx index 6d72c1069..f3d845acd 100644 --- a/resources/ts/Views/LoginPage.tsx +++ b/resources/ts/Views/LoginPage.tsx @@ -3,6 +3,7 @@ import '@material/web/button/filled-button.js'; import '@material/web/button/text-button.js'; import '@material/web/checkbox/checkbox.js'; import '@material/web/dialog/dialog.js'; +import '@osm/Components/m3/FilledTextField'; import {Dialog} from '@material/web/dialog/lib/dialog'; import { @@ -12,8 +13,6 @@ import { mdiLockQuestion, mdiLoginVariant } from '@mdi/js'; -import '@osm/Components/m3/FilledTextField'; - import MdIcon from '@osm/Components/MdIcon'; import Page, {PageAttributes} from '@osm/Components/Page'; import {VnodeCollectionItem} from '@osm/typings/jsx'; @@ -23,13 +22,13 @@ import type { Vnode, VnodeDOM } from 'mithril'; +import Stream from 'mithril/stream'; import { Form, FormSubmitEvent, Request, RequestError } from 'mithril-utilities'; -import Stream from 'mithril/stream'; export default class LoginPage extends Page { form = { diff --git a/resources/ts/Views/ResetPasswordPage.tsx b/resources/ts/Views/ResetPasswordPage.tsx index ca1b481dc..d07fd702e 100644 --- a/resources/ts/Views/ResetPasswordPage.tsx +++ b/resources/ts/Views/ResetPasswordPage.tsx @@ -1,26 +1,26 @@ -import {router} from '@maicol07/inertia-mithril'; import '@maicol07/material-web-additions/card/elevated-card.js'; import '@material/web/button/filled-button.js'; +import '@osm/Components/m3/FilledTextField'; + +import {router} from '@maicol07/inertia-mithril'; import { mdiAccountOutline, mdiLockCheckOutline, mdiLockOutline } from '@mdi/js'; -import '@osm/Components/m3/FilledTextField'; - import MdIcon from '@osm/Components/MdIcon'; import Page, {PageAttributes} from '@osm/Components/Page'; import {VnodeCollectionItem} from '@osm/typings/jsx'; import {showSnackbar} from '@osm/utils/misc'; import collect from 'collect.js'; import type {Vnode} from 'mithril'; +import Stream from 'mithril/stream'; import { Form, FormSubmitEvent, Request, RequestError } from 'mithril-utilities'; -import Stream from 'mithril/stream'; export default class ResetPasswordPage extends Page { form = { diff --git a/resources/ts/Views/Setup/SetupPage.tsx b/resources/ts/Views/Setup/SetupPage.tsx index c77c01445..b1ce45643 100644 --- a/resources/ts/Views/Setup/SetupPage.tsx +++ b/resources/ts/Views/Setup/SetupPage.tsx @@ -1,17 +1,17 @@ -import {router} from '@maicol07/inertia-mithril'; import '@maicol07/material-web-additions/card/elevated-card.js'; +import {router} from '@maicol07/inertia-mithril'; import Page, {PageAttributes} from '@osm/Components/Page'; import {showSnackbar} from '@osm/utils/misc'; import AdminUserStep from '@osm/Views/Setup/Steps/AdminUserStep'; import DatabaseStep from '@osm/Views/Setup/Steps/DatabaseStep'; import RegionalSettings from '@osm/Views/Setup/Steps/RegionalSettings'; import type {Vnode} from 'mithril'; +import Stream from 'mithril/stream'; import { Request, RequestError } from 'mithril-utilities'; -import Stream from 'mithril/stream'; import { SetupStep, diff --git a/resources/ts/Views/Setup/Steps/AdminUserStep.tsx b/resources/ts/Views/Setup/Steps/AdminUserStep.tsx index ae2a0336d..d33339267 100644 --- a/resources/ts/Views/Setup/Steps/AdminUserStep.tsx +++ b/resources/ts/Views/Setup/Steps/AdminUserStep.tsx @@ -1,4 +1,5 @@ import '@material/web/button/filled-button.js'; +import '@osm/Components/m3/FilledTextField'; import { mdiAccountOutline, @@ -7,8 +8,6 @@ import { mdiLockCheckOutline, mdiLockOutline } from '@mdi/js'; -import '@osm/Components/m3/FilledTextField'; - import MdIcon from '@osm/Components/MdIcon'; import {VnodeCollectionItem} from '@osm/typings/jsx'; import { @@ -18,11 +17,11 @@ import { } from '@osm/Views/Setup/Steps/SetupStep'; import collect from 'collect.js'; import {Vnode} from 'mithril'; +import Stream from 'mithril/stream'; import { Form, FormSubmitEvent } from 'mithril-utilities'; -import Stream from 'mithril/stream'; interface AdminUserStepAttributes extends SetupStepAttributes { onSaveInstall: (event: FormSubmitEvent) => void; diff --git a/resources/ts/Views/Setup/Steps/DatabaseStep.tsx b/resources/ts/Views/Setup/Steps/DatabaseStep.tsx index aef5bfefa..baf312a2f 100644 --- a/resources/ts/Views/Setup/Steps/DatabaseStep.tsx +++ b/resources/ts/Views/Setup/Steps/DatabaseStep.tsx @@ -1,4 +1,5 @@ import '@maicol07/material-web-additions/layout-grid/layout-grid.js'; +import '@osm/Components/m3/FilledTextField'; import { mdiAccountOutline, @@ -8,8 +9,6 @@ import { mdiServerNetwork, mdiTestTube } from '@mdi/js'; -import '@osm/Components/m3/FilledTextField'; - import MdIcon from '@osm/Components/MdIcon'; import {VnodeCollectionItem} from '@osm/typings/jsx'; import {showSnackbar} from '@osm/utils/misc'; @@ -18,12 +17,12 @@ import { Children, Vnode } from 'mithril'; +import Stream from 'mithril/stream'; import { Form, Request, RequestError } from 'mithril-utilities'; -import Stream from 'mithril/stream'; import { SetupStep, diff --git a/resources/ts/Views/Setup/Steps/RegionalSettings.tsx b/resources/ts/Views/Setup/Steps/RegionalSettings.tsx index bd37acc5c..d4e61ecf8 100644 --- a/resources/ts/Views/Setup/Steps/RegionalSettings.tsx +++ b/resources/ts/Views/Setup/Steps/RegionalSettings.tsx @@ -3,13 +3,12 @@ import { mdiCalendarMonthOutline, mdiClockOutline } from '@mdi/js'; - import MdIcon from '@osm/Components/MdIcon'; import {VnodeCollectionItem} from '@osm/typings/jsx'; import collect from 'collect.js'; import dayjs from 'dayjs'; -import {Form} from 'mithril-utilities'; import Stream from 'mithril/stream'; +import {Form} from 'mithril-utilities'; import { SetupStep, diff --git a/resources/ts/Views/Setup/Steps/SetupStep.tsx b/resources/ts/Views/Setup/Steps/SetupStep.tsx index 6e2a79463..86934449f 100644 --- a/resources/ts/Views/Setup/Steps/SetupStep.tsx +++ b/resources/ts/Views/Setup/Steps/SetupStep.tsx @@ -4,7 +4,6 @@ import { mdiChevronLeft, mdiChevronRight } from '@mdi/js'; - import MdIcon from '@osm/Components/MdIcon'; import { Children, diff --git a/resources/ts/Views/Setup/Steps/WelcomeStep.tsx b/resources/ts/Views/Setup/Steps/WelcomeStep.tsx index b15c004c6..ee7a084e2 100644 --- a/resources/ts/Views/Setup/Steps/WelcomeStep.tsx +++ b/resources/ts/Views/Setup/Steps/WelcomeStep.tsx @@ -1,9 +1,10 @@ -import type {MdCheckbox} from '@material/web/checkbox/checkbox'; import '@material/web/checkbox/checkbox.js'; import '@material/web/field/outlined-field.js'; import '@material/web/select/filled-select.js'; -import {Select} from '@material/web/select/lib/select'; import '@material/web/select/select-option.js'; + +import type {MdCheckbox} from '@material/web/checkbox/checkbox'; +import {Select} from '@material/web/select/lib/select'; import {mdiLicense} from '@mdi/js'; import MdIcon from '@osm/Components/MdIcon'; import { @@ -15,11 +16,11 @@ import { showSnackbar } from '@osm/utils/misc'; import {Vnode} from 'mithril'; +import Stream from 'mithril/stream'; import { Request, RequestError } from 'mithril-utilities'; -import Stream from 'mithril/stream'; import { SetupStep, diff --git a/resources/ts/Views/Users/UsersRecordDialog.tsx b/resources/ts/Views/Users/UsersRecordDialog.tsx index 3c920b08f..b9600166d 100644 --- a/resources/ts/Views/Users/UsersRecordDialog.tsx +++ b/resources/ts/Views/Users/UsersRecordDialog.tsx @@ -1,10 +1,10 @@ +import '@osm/Components/m3/FilledTextField'; + import { mdiAccountOutline, mdiEmailOutline } from '@mdi/js'; - import AddEditRecordDialog from '@osm/Components/Dialogs/AddEditRecordDialog'; -import '@osm/Components/m3/FilledTextField'; import MdIcon from '@osm/Components/MdIcon'; import User, {UserAttributes} from '@osm/Models/User'; import {JSONAPI} from '@osm/typings/request'; diff --git a/resources/ts/app.ts b/resources/ts/app.ts index 25f844928..24517416b 100644 --- a/resources/ts/app.ts +++ b/resources/ts/app.ts @@ -1,5 +1,6 @@ -import {createInertiaApp} from '@maicol07/inertia-mithril'; import '@osm/../scss/app.scss'; + +import {createInertiaApp} from '@maicol07/inertia-mithril'; import {showSnackbar} from '@osm/utils/misc'; import Mithril from 'mithril'; import {registerSW} from 'virtual:pwa-register'; @@ -25,14 +26,14 @@ window.tr = translator; window._v = vnodeTranslator; window.__ = stringTranslator; -// Load modules bootstrap +// Load modules bootstrap file import.meta.glob('../../vendor/**/**/resources/{js,ts}/bootstrap.{tsx,ts,js,jsx}', {eager: true}); await createInertiaApp({ title: ((title) => `${title} - OpenSTAManager`), // This rule is disabled to avoid a bug in Inertia plugin // eslint-disable-next-line arrow-body-style - resolve: resolvePage((page) => { + resolve: resolvePage(() => { return import.meta.glob('./Views/**/*.tsx'); }), setup({el, App, props}) { @@ -41,7 +42,7 @@ await createInertiaApp({ } m.mount(el, { - view: (vnode) => m(App, props) + view: () => m(App, props) }); } }); diff --git a/resources/ts/typings/global.d.ts b/resources/ts/typings/global.d.ts index 32af1f9c5..c2581aed9 100644 --- a/resources/ts/typings/global.d.ts +++ b/resources/ts/typings/global.d.ts @@ -1,10 +1,10 @@ /* eslint-disable @typescript-eslint/naming-convention */ // noinspection JSFileReferences,JSUnusedGlobalSymbols,LocalVariableNamingConventionJS import 'inertia-plugin/client'; - -import type Mithril from 'mithril'; import 'vite-plugin-pwa/client.d'; import 'vite/client'; + +import type Mithril from 'mithril'; import type router from 'ziggy-js'; import type { @@ -25,6 +25,7 @@ declare global { REVISION: string, }; + // noinspection LocalVariableNamingConventionJS const LARAVEL_TRANSLATIONS: Record>; interface Window { @@ -36,6 +37,8 @@ declare global { const m: typeof Mithril; const tr: typeof translator; + // noinspection LocalVariableNamingConventionJS const _v: typeof vnodeTranslator; + // noinspection LocalVariableNamingConventionJS const __: typeof stringTranslator; } diff --git a/resources/ts/typings/jsx.d.ts b/resources/ts/typings/jsx.d.ts index a0b7b7626..47c18b44f 100644 --- a/resources/ts/typings/jsx.d.ts +++ b/resources/ts/typings/jsx.d.ts @@ -1,7 +1,8 @@ +import 'mithril-utilities/typings'; + import {LayoutGridAttributes} from '@maicol07/material-web-additions/layout-grid/lib/layout-grid'; import {Collection} from 'collect.js'; import Mithril from 'mithril'; -import 'mithril-utilities/typings'; export type VnodeCollectionItem = Record; export type VnodeCollection = Collection; diff --git a/resources/views/app.blade.php b/resources/views/app.blade.php index e9bf8282d..0e36a666d 100644 --- a/resources/views/app.blade.php +++ b/resources/views/app.blade.php @@ -3,7 +3,6 @@ - {{-- --}} @lang('OpenSTAManager') @@ -41,16 +40,6 @@ 'time_format' => settings('time_format'), ] ]); - {{--{--}} - {{-- events: {},--}} - {{-- locale: '{{app()->getLocale()}}',--}} - {{-- modules: @js($modules->pluck('modules')->collapse()->all()),--}} - {{-- theme: @js(session('high-contrast') ? 'high-contrast' : 'light'),--}} - {{-- translations: @js(cache()->rememberForever('translations', static fn () => Controller::getTranslations()->toArray())),--}} - {{-- user: @js(auth()->user()),--}} - {{-- VERSION: @js(trim(file_get_contents(base_path('VERSION')))),--}} - {{-- REVISION: @js(trim(file_get_contents(base_path('REVISION'))))--}} - {{--};--}} @routes diff --git a/routes/api.php b/routes/api.php index c57a447ed..023be0f55 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,7 +1,5 @@ id === (int) $id; +Broadcast::channel('App.Models.User.{id}', static function (User $user, string|int $id) { + return $user->id === (int) $id; }); diff --git a/routes/console.php b/routes/console.php index e05f4c9a1..15fb1efa4 100644 --- a/routes/console.php +++ b/routes/console.php @@ -8,12 +8,14 @@ use Illuminate\Support\Facades\Artisan; | Console Routes |-------------------------------------------------------------------------- | -| This file is where you may define all of your Closure based console +| This file is where you may define all of your Closure-based console | commands. Each Closure is bound to a command instance allowing a | simple approach to interacting with each command's IO methods. -| */ Artisan::command('inspire', function () { + /** + * @psalm-suppress InvalidScope + */ $this->comment(Inspiring::quote()); })->purpose('Display an inspiring quote'); diff --git a/routes/web.php b/routes/web.php index 7f7c4a69d..f6ac8ac2a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,7 +1,5 @@ group(static function () { ->name('password.reset'); Route::inertia('setup', 'Setup/SetupPage', [ - 'languages' => cache()->rememberForever('app.languages', fn () => array_map( - static fn ($file) => basename($file, '.json'), - glob(lang_path('/*.json'), GLOB_NOSORT) - )), - 'license' => cache()->rememberForever('app.license', fn () => file_get_contents(base_path('LICENSE'))), + 'languages' => app(Controller::class)->getLanguages(), + 'license' => cache()->rememberForever('app.license', static fn () => file_get_contents(base_path('LICENSE'))), 'external' => true, ]) ->middleware('guest', CheckConfigurationMiddleware::class) @@ -57,7 +52,7 @@ Route::middleware('auth')->group(static function () { ->name('users.show'); }); -Route::get('refresh_csrf', static fn () => function () { +Route::get('refresh_csrf', static fn () => static function () { session()->regenerate(); return response()->json(['token' => csrf_token()]);