Compare commits
No commits in common. "bbdc9e9dfb832c79dc91f73c64b40ea1de171958" and "b15b806948240e8cb7e87a6e4a8ff237674c6760" have entirely different histories.
bbdc9e9dfb
...
b15b806948
34
.drone.yml
34
.drone.yml
|
@ -21,16 +21,6 @@ steps:
|
||||||
commands:
|
commands:
|
||||||
- while ! mysqladmin ping -h db -u db -pdb --silent; do sleep 1; done
|
- while ! mysqladmin ping -h db -u db -pdb --silent; do sleep 1; done
|
||||||
|
|
||||||
- name: ocdb_healthcheck
|
|
||||||
image: mysql:oracle
|
|
||||||
commands:
|
|
||||||
- while ! mysqladmin ping -h ownclouddb -u owncloud -powncloud --silent; do sleep 1; done
|
|
||||||
|
|
||||||
- name: oc_healthcheck
|
|
||||||
image: zoomyboy/adrema-base:latest
|
|
||||||
commands:
|
|
||||||
- while ! curl --silent 'http://owncloudserver:8080/ocs/v1.php/cloud/capabilities?format=json' -u admin:admin | grep '"status":"ok"'; do sleep 1; done
|
|
||||||
|
|
||||||
- name: node
|
- name: node
|
||||||
image: node:18.13.0-slim
|
image: node:18.13.0-slim
|
||||||
commands:
|
commands:
|
||||||
|
@ -68,7 +58,6 @@ steps:
|
||||||
XELATEX_BIN: /usr/bin/xelatex
|
XELATEX_BIN: /usr/bin/xelatex
|
||||||
SCOUT_DRIVER: database
|
SCOUT_DRIVER: database
|
||||||
MEILI_MASTER_KEY: abc
|
MEILI_MASTER_KEY: abc
|
||||||
TEST_OWNCLOUD_DOMAIN: http://owncloudserver:8080
|
|
||||||
|
|
||||||
- name: docker_app_push
|
- name: docker_app_push
|
||||||
image: plugins/docker
|
image: plugins/docker
|
||||||
|
@ -171,29 +160,6 @@ services:
|
||||||
image: getmeili/meilisearch:v1.6
|
image: getmeili/meilisearch:v1.6
|
||||||
commands:
|
commands:
|
||||||
- meilisearch --master-key="abc"
|
- meilisearch --master-key="abc"
|
||||||
- name: ownclouddb
|
|
||||||
image: mariadb:10.11
|
|
||||||
environment:
|
|
||||||
MYSQL_ROOT_PASSWORD: owncloud
|
|
||||||
MYSQL_USER: owncloud
|
|
||||||
MYSQL_PASSWORD: owncloud
|
|
||||||
MYSQL_DATABASE: owncloud
|
|
||||||
MARIADB_AUTO_UPGRADE: 1
|
|
||||||
- name: owncloudserver
|
|
||||||
image: owncloud/server:10.10.0
|
|
||||||
environment:
|
|
||||||
OWNCLOUD_DOMAIN: http://owncloudserver:8080
|
|
||||||
OWNCLOUD_TRUSTED_DOMAINS: owncloudserver
|
|
||||||
OWNCLOUD_DB_TYPE: mysql
|
|
||||||
OWNCLOUD_DB_NAME: owncloud
|
|
||||||
OWNCLOUD_DB_USERNAME: owncloud
|
|
||||||
OWNCLOUD_DB_PASSWORD: owncloud
|
|
||||||
OWNCLOUD_DB_HOST: ownclouddb
|
|
||||||
OWNCLOUD_ADMIN_USERNAME: admin
|
|
||||||
OWNCLOUD_ADMIN_PASSWORD: admin
|
|
||||||
OWNCLOUD_MYSQL_UTF8MB4: true
|
|
||||||
OWNCLOUD_REDIS_ENABLED: false
|
|
||||||
OWNCLOUD_REDIS_HOST: false
|
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
|
|
|
@ -16,7 +16,6 @@ Homestead.json
|
||||||
.phpunit.result.cache
|
.phpunit.result.cache
|
||||||
/storage/temp/
|
/storage/temp/
|
||||||
/storage/debugbar/
|
/storage/debugbar/
|
||||||
/tests/Fileshare/oc_tmp/*
|
|
||||||
|
|
||||||
# User data files
|
# User data files
|
||||||
/data/
|
/data/
|
||||||
|
|
|
@ -14,9 +14,3 @@
|
||||||
path = packages/medialibrary-helper
|
path = packages/medialibrary-helper
|
||||||
url = https://git.zoomyboy.de/zoomyboy/medialibrary-helper.git
|
url = https://git.zoomyboy.de/zoomyboy/medialibrary-helper.git
|
||||||
branch = version2
|
branch = version2
|
||||||
[submodule "packages/flysystem-webdav"]
|
|
||||||
path = packages/flysystem-webdav
|
|
||||||
url = https://github.com/zoomyboy/flysystem-webdav.git
|
|
||||||
[submodule "packages/table-document"]
|
|
||||||
path = packages/table-document
|
|
||||||
url = https://git.zoomyboy.de/zoomyboy/table-document.git
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ class ContributionFactory
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection<int, array{title: string, class: class-string<ContributionDocument>}>
|
* @return Collection<int, array{title: mixed, class: mixed}>
|
||||||
*/
|
*/
|
||||||
public function compilerSelect(): Collection
|
public function compilerSelect(): Collection
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,9 @@ use Sabre\CardDAV\Backend\AbstractBackend;
|
||||||
use Sabre\DAV\PropPatch;
|
use Sabre\DAV\PropPatch;
|
||||||
use Sabre\VObject\Component\VCard;
|
use Sabre\VObject\Component\VCard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template M as array{lastmodified: int, etag: string, uri: string, id: int, size: int}
|
||||||
|
*/
|
||||||
class AddressBookBackend extends AbstractBackend
|
class AddressBookBackend extends AbstractBackend
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -112,7 +115,7 @@ class AddressBookBackend extends AbstractBackend
|
||||||
*
|
*
|
||||||
* @param mixed $addressbookId
|
* @param mixed $addressbookId
|
||||||
*
|
*
|
||||||
* @return array<int, AddressBookCard>
|
* @return array<int, M>
|
||||||
*/
|
*/
|
||||||
public function getCards($addressbookId): array
|
public function getCards($addressbookId): array
|
||||||
{
|
{
|
||||||
|
@ -130,7 +133,7 @@ class AddressBookBackend extends AbstractBackend
|
||||||
* @param mixed $addressBookId
|
* @param mixed $addressBookId
|
||||||
* @param string $cardUri
|
* @param string $cardUri
|
||||||
*
|
*
|
||||||
* @return AddressBookCard|bool
|
* @return M
|
||||||
*/
|
*/
|
||||||
public function getCard($addressBookId, $cardUri)
|
public function getCard($addressBookId, $cardUri)
|
||||||
{
|
{
|
||||||
|
@ -245,7 +248,7 @@ class AddressBookBackend extends AbstractBackend
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return AddressBookCard
|
* @return M
|
||||||
*/
|
*/
|
||||||
private function cardMeta(Member $member): array
|
private function cardMeta(Member $member): array
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\Actions;
|
|
||||||
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use App\Fileshare\Resources\FileshareResource;
|
|
||||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
|
||||||
|
|
||||||
class FileshareApiIndexAction
|
|
||||||
{
|
|
||||||
use AsAction;
|
|
||||||
|
|
||||||
public function handle(): AnonymousResourceCollection
|
|
||||||
{
|
|
||||||
session()->put('menu', 'setting');
|
|
||||||
session()->put('title', 'Datei-Verbindungen');
|
|
||||||
|
|
||||||
return FileshareResource::collection(Fileshare::paginate(15));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\Actions;
|
|
||||||
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use App\Fileshare\Resources\FileshareResource;
|
|
||||||
use Inertia\Inertia;
|
|
||||||
use Inertia\Response;
|
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
|
||||||
|
|
||||||
class FileshareIndexAction
|
|
||||||
{
|
|
||||||
use AsAction;
|
|
||||||
|
|
||||||
public function handle(): Response
|
|
||||||
{
|
|
||||||
session()->put('menu', 'setting');
|
|
||||||
session()->put('title', 'Datei-Verbindungen');
|
|
||||||
|
|
||||||
return Inertia::render('fileshare/Index', [
|
|
||||||
'data' => FileshareResource::collection(Fileshare::paginate(15)),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\Actions;
|
|
||||||
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use App\Lib\Events\Succeeded;
|
|
||||||
use Illuminate\Validation\ValidationException;
|
|
||||||
use Lorisleiva\Actions\ActionRequest;
|
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
|
||||||
|
|
||||||
class FileshareStoreAction
|
|
||||||
{
|
|
||||||
use AsAction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array<string, mixed>
|
|
||||||
*/
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => 'required|string|max:255',
|
|
||||||
'type' => 'required|string|max:255|exclude',
|
|
||||||
'config' => 'array|exclude',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function asController(ActionRequest $request): void
|
|
||||||
{
|
|
||||||
$type = $request->input('type')::from($request->input('config'));
|
|
||||||
|
|
||||||
if (!$type->check()) {
|
|
||||||
throw ValidationException::withMessages(['type' => 'Verbindung fehlgeschlagen']);
|
|
||||||
}
|
|
||||||
|
|
||||||
Fileshare::create([
|
|
||||||
...$request->validated(),
|
|
||||||
'type' => $type,
|
|
||||||
]);
|
|
||||||
|
|
||||||
Succeeded::message('Verbindung erstellt.')->dispatch();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\Actions;
|
|
||||||
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use App\Lib\Events\Succeeded;
|
|
||||||
use Illuminate\Validation\ValidationException;
|
|
||||||
use Lorisleiva\Actions\ActionRequest;
|
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
|
||||||
|
|
||||||
class FileshareUpdateAction
|
|
||||||
{
|
|
||||||
use AsAction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array<string, mixed>
|
|
||||||
*/
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => 'required|string|max:255',
|
|
||||||
'type' => 'required|string|max:255|exclude',
|
|
||||||
'config' => 'array|exclude',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(ActionRequest $request, Fileshare $fileshare): void
|
|
||||||
{
|
|
||||||
$type = $request->input('type')::from($request->input('config'));
|
|
||||||
|
|
||||||
if (!$type->check()) {
|
|
||||||
throw ValidationException::withMessages(['type' => 'Verbindung fehlgeschlagen']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$fileshare->update([
|
|
||||||
...$request->validated(),
|
|
||||||
'type' => $type,
|
|
||||||
]);
|
|
||||||
|
|
||||||
Succeeded::message('Verbindung bearbeitet.')->dispatch();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\Actions;
|
|
||||||
|
|
||||||
use App\Fileshare\Data\ResourceData;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use Lorisleiva\Actions\ActionRequest;
|
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
|
||||||
use Spatie\LaravelData\DataCollection;
|
|
||||||
|
|
||||||
class ListFilesAction
|
|
||||||
{
|
|
||||||
use AsAction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return DataCollection<int, ResourceData>
|
|
||||||
*/
|
|
||||||
public function handle(ActionRequest $request, Fileshare $fileshare): DataCollection
|
|
||||||
{
|
|
||||||
return ResourceData::collection($fileshare->type->getSubDirectories($request->input('parent')))->wrap('data');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\ConnectionTypes;
|
|
||||||
|
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Spatie\LaravelData\Data;
|
|
||||||
|
|
||||||
abstract class ConnectionType extends Data
|
|
||||||
{
|
|
||||||
abstract public function check(): bool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array<string, mixed>
|
|
||||||
*/
|
|
||||||
abstract public static function defaults(): array;
|
|
||||||
|
|
||||||
abstract public static function title(): string;
|
|
||||||
|
|
||||||
abstract public function getFilesystem(): FilesystemAdapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array<int, array{label: string, key: string, type: string}>
|
|
||||||
*/
|
|
||||||
abstract public static function fields(): array;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array<int, mixed>
|
|
||||||
*/
|
|
||||||
public static function forSelect(): array
|
|
||||||
{
|
|
||||||
return self::types()
|
|
||||||
->map(fn ($file) => ['id' => $file, 'name' => $file::title(), 'defaults' => $file::defaults(), 'fields' => $file::fields()])
|
|
||||||
->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array<int, string>
|
|
||||||
*/
|
|
||||||
public function getSubDirectories(?string $parent): array
|
|
||||||
{
|
|
||||||
$filesystem = $this->getFilesystem();
|
|
||||||
|
|
||||||
return $filesystem->directories($parent ?: '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection<int, class-string<ConnectionType>>
|
|
||||||
*/
|
|
||||||
private static function types(): Collection
|
|
||||||
{
|
|
||||||
return collect(glob(base_path('app/Fileshare/ConnectionTypes/*')))
|
|
||||||
->map(fn ($file) => 'App\\Fileshare\\ConnectionTypes\\' . pathinfo($file, PATHINFO_FILENAME))
|
|
||||||
->filter(fn ($file) => $file !== static::class)
|
|
||||||
->values();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\ConnectionTypes;
|
|
||||||
|
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
|
||||||
use Illuminate\Http\Client\ConnectionException;
|
|
||||||
use Illuminate\Support\Facades\Http;
|
|
||||||
use League\Flysystem\Filesystem;
|
|
||||||
use League\Flysystem\WebDAV\WebDAVAdapter;
|
|
||||||
use Sabre\DAV\Client;
|
|
||||||
use Spatie\LaravelData\Attributes\MapInputName;
|
|
||||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
|
||||||
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
|
|
||||||
|
|
||||||
#[MapInputName(SnakeCaseMapper::class)]
|
|
||||||
#[MapOutputName(SnakeCaseMapper::class)]
|
|
||||||
class OwncloudConnection extends ConnectionType
|
|
||||||
{
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
public string $user,
|
|
||||||
public string $password,
|
|
||||||
public string $baseUrl,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function check(): bool
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$response = Http::withoutVerifying()->withBasicAuth($this->user, $this->password)->acceptJson()->get($this->baseUrl . '/ocs/v1.php/cloud/capabilities?format=json');
|
|
||||||
return $response->ok();
|
|
||||||
} catch (ConnectionException $e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public static function defaults(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'user' => '',
|
|
||||||
'password' => '',
|
|
||||||
'base_url' => '',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function title(): string
|
|
||||||
{
|
|
||||||
return 'Owncloud';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public static function fields(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
['label' => 'URL', 'key' => 'base_url', 'type' => 'text'],
|
|
||||||
['label' => 'Benutzer', 'key' => 'user', 'type' => 'text'],
|
|
||||||
['label' => 'Passwort', 'key' => 'password', 'type' => 'password'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFilesystem(): FilesystemAdapter
|
|
||||||
{
|
|
||||||
$adapter = new WebDAVAdapter(new Client([
|
|
||||||
'baseUri' => $this->baseUrl . '/remote.php/dav/files/' . $this->user,
|
|
||||||
'userName' => $this->user,
|
|
||||||
'password' => $this->password,
|
|
||||||
]), '/remote.php/dav/files/' . $this->user);
|
|
||||||
|
|
||||||
return new FilesystemAdapter(new Filesystem($adapter), $adapter);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\Data;
|
|
||||||
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
|
||||||
use Spatie\LaravelData\Attributes\MapInputName;
|
|
||||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
|
||||||
use Spatie\LaravelData\Data;
|
|
||||||
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
|
|
||||||
|
|
||||||
#[MapInputName(SnakeCaseMapper::class)]
|
|
||||||
#[MapOutputName(SnakeCaseMapper::class)]
|
|
||||||
class FileshareResourceData extends Data
|
|
||||||
{
|
|
||||||
|
|
||||||
public function __construct(public int $connectionId, public string $resource)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getConnection(): Fileshare
|
|
||||||
{
|
|
||||||
return Fileshare::find($this->connectionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStorage(): FilesystemAdapter
|
|
||||||
{
|
|
||||||
return $this->getConnection()->type->getFilesystem();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\Data;
|
|
||||||
|
|
||||||
use Spatie\LaravelData\Data;
|
|
||||||
|
|
||||||
class ResourceData extends Data
|
|
||||||
{
|
|
||||||
|
|
||||||
public function __construct(public string $name, public string $path, public string $parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fromString(string $path): self
|
|
||||||
{
|
|
||||||
$dir = '/' . trim($path, '\\/');
|
|
||||||
|
|
||||||
return self::from([
|
|
||||||
'path' => $dir,
|
|
||||||
'name' => pathinfo($dir, PATHINFO_BASENAME),
|
|
||||||
'parent' => pathinfo($dir, PATHINFO_DIRNAME),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare;
|
|
||||||
|
|
||||||
use App\Fileshare\Actions\FileshareIndexAction;
|
|
||||||
use App\Setting\Contracts\Indexable;
|
|
||||||
use App\Setting\LocalSettings;
|
|
||||||
|
|
||||||
class FileshareSettings extends LocalSettings implements Indexable
|
|
||||||
{
|
|
||||||
public static function group(): string
|
|
||||||
{
|
|
||||||
return 'fileshare';
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function slug(): string
|
|
||||||
{
|
|
||||||
return 'fileshare';
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function indexAction(): string
|
|
||||||
{
|
|
||||||
return FileshareIndexAction::class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function title(): string
|
|
||||||
{
|
|
||||||
return 'Datei-Verbindungen';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\Models;
|
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\ConnectionType;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Fileshare extends Model
|
|
||||||
{
|
|
||||||
use HasFactory;
|
|
||||||
|
|
||||||
public $guarded = [];
|
|
||||||
|
|
||||||
public $casts = [
|
|
||||||
'type' => ConnectionType::class,
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Fileshare\Resources;
|
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\ConnectionType;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use App\Lib\HasMeta;
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @mixin Fileshare
|
|
||||||
*/
|
|
||||||
class FileshareResource extends JsonResource
|
|
||||||
{
|
|
||||||
|
|
||||||
use HasMeta;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transform the resource into an array.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return array<string, mixed>
|
|
||||||
*/
|
|
||||||
public function toArray($request)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => $this->name,
|
|
||||||
'is_active' => $this->type->check(),
|
|
||||||
'type' => get_class($this->type),
|
|
||||||
'config' => $this->type->toArray(),
|
|
||||||
'id' => $this->id,
|
|
||||||
'type_human' => $this->type::title(),
|
|
||||||
'links' => [
|
|
||||||
'update' => route('fileshare.update', ['fileshare' => $this->getModel()]),
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array<string, mixed>
|
|
||||||
*/
|
|
||||||
public static function meta(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'default' => [
|
|
||||||
'name' => '',
|
|
||||||
'type' => null,
|
|
||||||
'config' => null,
|
|
||||||
],
|
|
||||||
'types' => ConnectionType::forSelect(),
|
|
||||||
'links' => [
|
|
||||||
'store' => route('fileshare.store'),
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Form\Actions;
|
|
||||||
|
|
||||||
use App\Form\Models\Form;
|
|
||||||
use App\Form\Models\Participant;
|
|
||||||
use App\Group;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
|
||||||
use Zoomyboy\TableDocument\SheetData;
|
|
||||||
use Zoomyboy\TableDocument\TableDocumentData;
|
|
||||||
|
|
||||||
class ExportSyncAction
|
|
||||||
{
|
|
||||||
use AsAction;
|
|
||||||
|
|
||||||
public Form $form;
|
|
||||||
|
|
||||||
public function handle(Form $form): void
|
|
||||||
{
|
|
||||||
$this->form = $form;
|
|
||||||
|
|
||||||
if (!$form->export->root) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage = $form->export->root->getStorage();
|
|
||||||
|
|
||||||
$storage->put($form->export->root->resource . '/Anmeldungen ' . $form->name . '.xlsx', file_get_contents($this->allSheet($this->form->participants)->compile($this->tempPath())));
|
|
||||||
|
|
||||||
if ($form->export->toGroupField) {
|
|
||||||
foreach ($form->participants->groupBy(fn ($participant) => $participant->data[$form->export->toGroupField]) as $groupId => $participants) {
|
|
||||||
$group = Group::find($groupId);
|
|
||||||
if (!$group?->fileshare) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$group->fileshare->getStorage()->put($group->fileshare->resource . '/Anmeldungen ' . $form->name . '.xlsx', file_get_contents($this->allSheet($participants)->compile($this->tempPath())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function asJob(int $formId): void
|
|
||||||
{
|
|
||||||
$this->handle(Form::find($formId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Collection<int, Participant> $participants
|
|
||||||
*/
|
|
||||||
private function allSheet(Collection $participants): TableDocumentData
|
|
||||||
{
|
|
||||||
$document = TableDocumentData::from(['title' => 'Anmeldungen für ' . $this->form->name, 'sheets' => []]);
|
|
||||||
$headers = $this->form->getFields()->map(fn ($field) => $field->name)->toArray();
|
|
||||||
|
|
||||||
$document->addSheet(SheetData::from([
|
|
||||||
'header' => $headers,
|
|
||||||
'data' => $participants
|
|
||||||
->map(fn ($participant) => $this->form->getFields()->map(fn ($field) => $participant->getFields()->find($field)->presentRaw())->toArray())
|
|
||||||
->toArray(),
|
|
||||||
'name' => 'Alle',
|
|
||||||
]));
|
|
||||||
|
|
||||||
if ($this->form->export->groupBy) {
|
|
||||||
$groups = $participants->groupBy(fn ($participant) => $participant->getFields()->findByKey($this->form->export->groupBy)->presentRaw());
|
|
||||||
|
|
||||||
foreach ($groups as $name => $participants) {
|
|
||||||
$document->addSheet(SheetData::from([
|
|
||||||
'header' => $headers,
|
|
||||||
'data' => $participants
|
|
||||||
->map(fn ($participant) => $this->form->getFields()->map(fn ($field) => $participant->getFields()->find($field)->presentRaw())->toArray())
|
|
||||||
->toArray(),
|
|
||||||
'name' => $name,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
$document->addSheet(SheetData::from([
|
|
||||||
'header' => ['Wert', 'Anzahl'],
|
|
||||||
'data' => $groups->map(fn ($participants, $name) => [$name, (string) count($participants)])->toArray(),
|
|
||||||
'name' => 'Statistik',
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $document;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function tempPath(): string
|
|
||||||
{
|
|
||||||
return sys_get_temp_dir() . '/' . str()->uuid()->toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -34,7 +34,6 @@ class FormStoreAction
|
||||||
'mailattachments' => 'present|array|exclude',
|
'mailattachments' => 'present|array|exclude',
|
||||||
'is_active' => 'boolean',
|
'is_active' => 'boolean',
|
||||||
'is_private' => 'boolean',
|
'is_private' => 'boolean',
|
||||||
'export' => 'nullable|array',
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ class FormUpdateAction
|
||||||
'mail_bottom' => 'array',
|
'mail_bottom' => 'array',
|
||||||
'is_active' => 'boolean',
|
'is_active' => 'boolean',
|
||||||
'is_private' => 'boolean',
|
'is_private' => 'boolean',
|
||||||
'export' => 'nullable|array',
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ class RegisterAction
|
||||||
$form->getFields()->each(fn ($field) => $field->afterRegistration($form, $participant, $input));
|
$form->getFields()->each(fn ($field) => $field->afterRegistration($form, $participant, $input));
|
||||||
|
|
||||||
$participant->sendConfirmationMail();
|
$participant->sendConfirmationMail();
|
||||||
ExportSyncAction::dispatch($form->id);
|
|
||||||
|
|
||||||
return $participant;
|
return $participant;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use Spatie\LaravelData\Support\DataProperty;
|
||||||
class FieldCollectionCast implements Cast
|
class FieldCollectionCast implements Cast
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param array<int, array<string, string>> $value
|
* @param array<int, array<string, mixed>> $value
|
||||||
* @param array<string, mixed> $context
|
* @param array<string, mixed> $context
|
||||||
* @return FieldCollection
|
* @return FieldCollection
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Form\Data;
|
|
||||||
|
|
||||||
use App\Fileshare\Data\FileshareResourceData;
|
|
||||||
use App\Form\Fields\Field;
|
|
||||||
use Spatie\LaravelData\Attributes\MapInputName;
|
|
||||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
|
||||||
use Spatie\LaravelData\Data;
|
|
||||||
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
|
|
||||||
|
|
||||||
#[MapInputName(SnakeCaseMapper::class)]
|
|
||||||
#[MapOutputName(SnakeCaseMapper::class)]
|
|
||||||
class ExportData extends Data
|
|
||||||
{
|
|
||||||
public function __construct(public ?FileshareResourceData $root = null, public ?string $groupBy = null, public ?string $toGroupField = null)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -79,9 +79,6 @@ abstract class Field extends Data
|
||||||
->toArray();
|
->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return class-string<Field>
|
|
||||||
*/
|
|
||||||
public static function classFromType(string $type): ?string
|
public static function classFromType(string $type): ?string
|
||||||
{
|
{
|
||||||
/** @var class-string<Field> */
|
/** @var class-string<Field> */
|
||||||
|
@ -104,7 +101,10 @@ abstract class Field extends Data
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function presentRaw(): string
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function presentRaw()
|
||||||
{
|
{
|
||||||
return $this->getPresenter()->present($this->value);
|
return $this->getPresenter()->present($this->value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace App\Form\Models;
|
namespace App\Form\Models;
|
||||||
|
|
||||||
use App\Form\Data\ExportData;
|
|
||||||
use App\Form\Data\FieldCollection;
|
use App\Form\Data\FieldCollection;
|
||||||
use App\Form\Data\FormConfigData;
|
use App\Form\Data\FormConfigData;
|
||||||
use Cviebrock\EloquentSluggable\Sluggable;
|
use Cviebrock\EloquentSluggable\Sluggable;
|
||||||
|
@ -34,7 +33,6 @@ class Form extends Model implements HasMedia
|
||||||
'mail_bottom' => 'json',
|
'mail_bottom' => 'json',
|
||||||
'is_active' => 'boolean',
|
'is_active' => 'boolean',
|
||||||
'is_private' => 'boolean',
|
'is_private' => 'boolean',
|
||||||
'export' => ExportData::class,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var array<int, string> */
|
/** @var array<int, string> */
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace App\Form\Resources;
|
namespace App\Form\Resources;
|
||||||
|
|
||||||
use App\Form\Data\ExportData;
|
|
||||||
use App\Form\Enums\NamiType;
|
use App\Form\Enums\NamiType;
|
||||||
use App\Form\Enums\SpecialType;
|
use App\Form\Enums\SpecialType;
|
||||||
use App\Form\Fields\Field;
|
use App\Form\Fields\Field;
|
||||||
|
@ -48,7 +47,6 @@ class FormResource extends JsonResource
|
||||||
'is_active' => $this->is_active,
|
'is_active' => $this->is_active,
|
||||||
'is_private' => $this->is_private,
|
'is_private' => $this->is_private,
|
||||||
'has_nami_field' => $this->getFields()->hasNamiField(),
|
'has_nami_field' => $this->getFields()->hasNamiField(),
|
||||||
'export' => $this->export,
|
|
||||||
'links' => [
|
'links' => [
|
||||||
'participant_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => null]),
|
'participant_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => null]),
|
||||||
'participant_root_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => -1]),
|
'participant_root_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => -1]),
|
||||||
|
@ -94,7 +92,6 @@ class FormResource extends JsonResource
|
||||||
'header_image' => null,
|
'header_image' => null,
|
||||||
'mailattachments' => [],
|
'mailattachments' => [],
|
||||||
'id' => null,
|
'id' => null,
|
||||||
'export' => ExportData::from([]),
|
|
||||||
],
|
],
|
||||||
'section_default' => [
|
'section_default' => [
|
||||||
'name' => '',
|
'name' => '',
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace App;
|
namespace App;
|
||||||
|
|
||||||
use App\Fileshare\Data\FileshareResourceData;
|
|
||||||
use App\Group\Enums\Level;
|
use App\Group\Enums\Level;
|
||||||
use App\Nami\HasNamiField;
|
use App\Nami\HasNamiField;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
@ -15,12 +14,11 @@ class Group extends Model
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
use HasNamiField;
|
use HasNamiField;
|
||||||
|
|
||||||
public $fillable = ['nami_id', 'name', 'inner_name', 'level', 'parent_id', 'fileshare'];
|
public $fillable = ['nami_id', 'name', 'inner_name', 'level', 'parent_id'];
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
public $casts = [
|
public $casts = [
|
||||||
'level' => Level::class,
|
'level' => Level::class
|
||||||
'fileshare' => FileshareResourceData::class,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,9 +22,6 @@ class GroupBulkstoreAction
|
||||||
'*.id' => 'required|integer|exists:groups,id',
|
'*.id' => 'required|integer|exists:groups,id',
|
||||||
'*.inner_name' => 'required|string|max:255',
|
'*.inner_name' => 'required|string|max:255',
|
||||||
'*.level' => ['required', 'string', Rule::in(Level::values())],
|
'*.level' => ['required', 'string', Rule::in(Level::values())],
|
||||||
'*.fileshare' => 'present|nullable',
|
|
||||||
'*.fileshare.connection_id' => 'nullable|numeric|exists:fileshares,id',
|
|
||||||
'*.fileshare.resource' => 'nullable|string',
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +31,7 @@ class GroupBulkstoreAction
|
||||||
public function handle(array $groups): void
|
public function handle(array $groups): void
|
||||||
{
|
{
|
||||||
foreach ($groups as $payload) {
|
foreach ($groups as $payload) {
|
||||||
Group::find($payload['id'])->update(['level' => $payload['level'], 'inner_name' => $payload['inner_name'], 'fileshare' => $payload['fileshare']]);
|
Group::find($payload['id'])->update(['level' => $payload['level'], 'inner_name' => $payload['inner_name']]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ class GroupResource extends JsonResource
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'level' => $this->level?->value,
|
'level' => $this->level?->value,
|
||||||
'children_count' => $this->children_count,
|
'children_count' => $this->children_count,
|
||||||
'fileshare' => $this->fileshare,
|
|
||||||
'links' => [
|
'links' => [
|
||||||
'children' => route('api.group', ['group' => $this->id]),
|
'children' => route('api.group', ['group' => $this->id]),
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace App\Setting;
|
namespace App\Setting;
|
||||||
|
|
||||||
use App\Fileshare\FileshareSettings;
|
|
||||||
use App\Form\FormSettings;
|
use App\Form\FormSettings;
|
||||||
use App\Invoice\InvoiceSettings;
|
use App\Invoice\InvoiceSettings;
|
||||||
use App\Mailgateway\MailgatewaySettings;
|
use App\Mailgateway\MailgatewaySettings;
|
||||||
|
@ -33,6 +32,5 @@ class SettingServiceProvider extends ServiceProvider
|
||||||
app(SettingFactory::class)->register(MailgatewaySettings::class);
|
app(SettingFactory::class)->register(MailgatewaySettings::class);
|
||||||
app(SettingFactory::class)->register(NamiSettings::class);
|
app(SettingFactory::class)->register(NamiSettings::class);
|
||||||
app(SettingFactory::class)->register(FormSettings::class);
|
app(SettingFactory::class)->register(FormSettings::class);
|
||||||
app(SettingFactory::class)->register(FileshareSettings::class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,20 +14,6 @@
|
||||||
"symlink": true
|
"symlink": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "path",
|
|
||||||
"url": "./packages/table-document",
|
|
||||||
"options": {
|
|
||||||
"symlink": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "path",
|
|
||||||
"url": "./packages/flysystem-webdav",
|
|
||||||
"options": {
|
|
||||||
"symlink": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "path",
|
"type": "path",
|
||||||
"url": "./packages/tex",
|
"url": "./packages/tex",
|
||||||
|
@ -72,12 +58,10 @@
|
||||||
"spatie/laravel-settings": "^2.2",
|
"spatie/laravel-settings": "^2.2",
|
||||||
"worksome/request-factories": "^2.5",
|
"worksome/request-factories": "^2.5",
|
||||||
"zoomyboy/laravel-nami": "dev-master",
|
"zoomyboy/laravel-nami": "dev-master",
|
||||||
"zoomyboy/medialibrary-helper": "dev-master as 1.0",
|
|
||||||
"league/flysystem-webdav": "dev-master as 3.28.0",
|
|
||||||
"zoomyboy/osm": "1.0.3",
|
"zoomyboy/osm": "1.0.3",
|
||||||
"zoomyboy/phone": "^1.0",
|
"zoomyboy/phone": "^1.0",
|
||||||
"zoomyboy/table-document": "dev-master as 1.0",
|
"zoomyboy/tex": "dev-main as 1.0",
|
||||||
"zoomyboy/tex": "dev-main as 1.0"
|
"zoomyboy/medialibrary-helper": "dev-master as 1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,43 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Database\Factories\Fileshare\Models;
|
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\ConnectionType;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @extends Factory<Fileshare>
|
|
||||||
*/
|
|
||||||
class FileshareFactory extends Factory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The name of the factory's corresponding model.
|
|
||||||
*
|
|
||||||
* @var class-string<Fileshare>
|
|
||||||
*/
|
|
||||||
protected $model = Fileshare::class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the model's default state.
|
|
||||||
*
|
|
||||||
* @return array<string, mixed>
|
|
||||||
*/
|
|
||||||
public function definition()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'type' => '{}',
|
|
||||||
'name' => '',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function type(ConnectionType $type): self
|
|
||||||
{
|
|
||||||
return $this->state(['type' => $type]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function name(string $name): self
|
|
||||||
{
|
|
||||||
return $this->state(['name' => $name]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace Database\Factories\Form\Models;
|
namespace Database\Factories\Form\Models;
|
||||||
|
|
||||||
use App\Form\Data\ExportData;
|
|
||||||
use App\Form\Models\Form;
|
use App\Form\Models\Form;
|
||||||
use Database\Factories\Traits\FakesMedia;
|
use Database\Factories\Traits\FakesMedia;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
@ -20,7 +19,6 @@ use Tests\RequestFactories\EditorRequestFactory;
|
||||||
* @method self registrationUntil(string|null $date)
|
* @method self registrationUntil(string|null $date)
|
||||||
* @method self isActive(bool $isActive)
|
* @method self isActive(bool $isActive)
|
||||||
* @method self isPrivate(bool $isPrivate)
|
* @method self isPrivate(bool $isPrivate)
|
||||||
* @method self export(ExportData $data)
|
|
||||||
*/
|
*/
|
||||||
class FormFactory extends Factory
|
class FormFactory extends Factory
|
||||||
{
|
{
|
||||||
|
@ -53,7 +51,6 @@ class FormFactory extends Factory
|
||||||
'mail_bottom' => EditorRequestFactory::new()->create(),
|
'mail_bottom' => EditorRequestFactory::new()->create(),
|
||||||
'is_active' => true,
|
'is_active' => true,
|
||||||
'is_private' => false,
|
'is_private' => false,
|
||||||
'export' => ExportData::from([]),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('fileshares', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->string('name');
|
|
||||||
$table->json('type');
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('fileshares');
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('groups', function (Blueprint $table) {
|
|
||||||
$table->json('fileshare')->after('inner_name')->nullable();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('groups', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('fileshare');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('forms', function (Blueprint $table) {
|
|
||||||
$table->json('export')->after('config')->nullable();
|
|
||||||
});
|
|
||||||
DB::table('forms')->update([
|
|
||||||
'export' => json_encode(['root' => null, 'group_by' => null, 'to_group_field' => null])
|
|
||||||
]);
|
|
||||||
Schema::table('forms', function (Blueprint $table) {
|
|
||||||
$table->json('export')->nullable(false)->change();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('forms', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('export');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit c892034c6b6ebe9c70164a352ae78d1634463c4c
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 84103d40521d77f936635a7f992cf1ae4b01dafe
|
Subproject commit b8164cd3d204412cd3be95cbf29b9fcc3d23a77d
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit c1d0221dcd2b4200b3ff17747e31f451fcc749f0
|
|
77
phpstan.neon
77
phpstan.neon
|
@ -25,7 +25,6 @@ parameters:
|
||||||
MailgatewayCustomField: 'array{name: string, label: string, type: string, storeValidator: string, updateValidator: string, default: string}'
|
MailgatewayCustomField: 'array{name: string, label: string, type: string, storeValidator: string, updateValidator: string, default: string}'
|
||||||
MailgatewayParsedCustomField: 'array{name: string, label: string, type: string, storeValidator: string, updateValidator: string, default: string, is_required: bool}'
|
MailgatewayParsedCustomField: 'array{name: string, label: string, type: string, storeValidator: string, updateValidator: string, default: string, is_required: bool}'
|
||||||
SluggableConfig: 'array<string, array{source: array<int, string>}>'
|
SluggableConfig: 'array<string, array{source: array<int, string>}>'
|
||||||
AddressBookCard: 'array{lastmodified: int, etag: string, uri: string, id: int, size: int}'
|
|
||||||
|
|
||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
-
|
-
|
||||||
|
@ -33,6 +32,11 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: app/Activity.php
|
path: app/Activity.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Method App\\\\Dav\\\\AddressBookBackend\\:\\:getCard\\(\\) should return M of array\\{lastmodified\\: int, etag\\: string, uri\\: string, id\\: int, size\\: int\\} but returns false\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: app/Dav/AddressBookBackend.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Method App\\\\Dav\\\\AddressBookBackend\\:\\:getMultipleCards\\(\\) has parameter \\$uris with no value type specified in iterable type array\\.$#"
|
message: "#^Method App\\\\Dav\\\\AddressBookBackend\\:\\:getMultipleCards\\(\\) has parameter \\$uris with no value type specified in iterable type array\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -158,6 +162,17 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: database/factories/NationalityFactory.php
|
path: database/factories/NationalityFactory.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Call to an undefined method Phake\\\\Proxies\\\\StubberProxy.*#"
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Call to an undefined method Phake\\\\Proxies\\\\VerifierProxy.*#"
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^PHPDoc tag @param has invalid value \\(\\<class\\-string\\> \\$class\\)\\: Unexpected token \"\\<\", expected type at offset 18$#"
|
||||||
|
count: 1
|
||||||
|
path: tests/TestCase.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#1 \\$api of class App\\\\Initialize\\\\InitializeGroups constructor expects Zoomyboy\\\\LaravelNami\\\\Api, PHPUnit\\\\Framework\\\\MockObject\\\\Stub given\\.$#"
|
message: "#^Parameter \\#1 \\$api of class App\\\\Initialize\\\\InitializeGroups constructor expects Zoomyboy\\\\LaravelNami\\\\Api, PHPUnit\\\\Framework\\\\MockObject\\\\Stub given\\.$#"
|
||||||
count: 6
|
count: 6
|
||||||
|
@ -448,6 +463,16 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: tests/Feature/Member/DavTest.php
|
path: tests/Feature/Member/DavTest.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Return type of call to method Illuminate\\\\Support\\\\Collection\\<int,class\\-string\\<App\\\\Contribution\\\\Documents\\\\ContributionDocument\\>\\>\\:\\:map\\(\\) contains unresolvable type\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: app/Contribution/ContributionFactory.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Return type of call to method Illuminate\\\\Support\\\\Collection\\<int,class\\-string\\<App\\\\Setting\\\\LocalSettings\\>\\>\\:\\:map\\(\\) contains unresolvable type\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: app/Setting/SettingFactory.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$email\\.$#"
|
message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$email\\.$#"
|
||||||
count: 2
|
count: 2
|
||||||
|
@ -517,53 +542,3 @@ parameters:
|
||||||
message: "#^Unable to resolve the template type TValue in call to function collect$#"
|
message: "#^Unable to resolve the template type TValue in call to function collect$#"
|
||||||
count: 1
|
count: 1
|
||||||
path: app/Form/Fields/NamiField.php
|
path: app/Form/Fields/NamiField.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Fileshare\\\\ConnectionTypes\\\\ConnectionType\\:\\:types\\(\\) should return Illuminate\\\\Support\\\\Collection\\<int, class\\-string\\<App\\\\Fileshare\\\\ConnectionTypes\\\\ConnectionType\\>\\> but returns Illuminate\\\\Support\\\\Collection\\<int, string\\>\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Fileshare/ConnectionTypes/ConnectionType.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Phake\\\\Proxies\\\\StubberProxy\\:\\:check\\(\\)\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: tests/Feature/Mailgateway/IndexTest.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Phake\\\\Proxies\\\\StubberProxy\\:\\:setCredentials\\(\\)\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: tests/Feature/Mailgateway/IndexTest.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Phake\\\\Proxies\\\\StubberProxy\\:\\:check\\(\\)\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: tests/Feature/Mailgateway/MailmanTypeTest.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Phake\\\\Proxies\\\\StubberProxy\\:\\:setCredentials\\(\\)\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: tests/Feature/Mailgateway/MailmanTypeTest.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Phake\\\\Proxies\\\\StubberProxy\\:\\:setOwner\\(\\)\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: tests/Feature/Mailgateway/MailmanTypeTest.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Phake\\\\Proxies\\\\StubberProxy\\:\\:setOwner\\(\\)\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: tests/Feature/Mailgateway/StoreTest.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Phake\\\\Proxies\\\\StubberProxy\\:\\:setParams\\(\\)\\.$#"
|
|
||||||
count: 3
|
|
||||||
path: tests/Feature/Mailgateway/StoreTest.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Phake\\\\Proxies\\\\StubberProxy\\:\\:works\\(\\)\\.$#"
|
|
||||||
count: 3
|
|
||||||
path: tests/Feature/Mailgateway/StoreTest.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Phake\\\\Proxies\\\\VerifierProxy\\:\\:handle\\(\\)\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: tests/Feature/Member/NamiPutMemberActionTest.php
|
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
<testsuite name="Feature">
|
<testsuite name="Feature">
|
||||||
<directory suffix="Test.php">./tests/Feature</directory>
|
<directory suffix="Test.php">./tests/Feature</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="Fileshare">
|
|
||||||
<directory suffix="Test.php">./tests/Fileshare</directory>
|
|
||||||
</testsuite>
|
|
||||||
<testsuite name="NamiUnit">
|
<testsuite name="NamiUnit">
|
||||||
<directory suffix="Test.php">./packages/laravel-nami/tests/Unit</directory>
|
<directory suffix="Test.php">./packages/laravel-nami/tests/Unit</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
<svg height="512" viewBox="0 0 48 48" width="512" xmlns="http://www.w3.org/2000/svg"><g data-name="Open Folder"><path d="M45 18h-4v-4a2.996 2.996 0 0 0-3-3H22.75a3 3 0 0 1-2.33-1.11l-1.96-2.41A3.985 3.985 0 0 0 15.36 6H4a2.996 2.996 0 0 0-3 3v29.57a3.367 3.367 0 0 0 1.01 2.42A3.367 3.367 0 0 0 4.43 42h33.66a3.441 3.441 0 0 0 3.3-2.47l5.53-18.97A2.003 2.003 0 0 0 45 18z" fill="rgba(currentColor, 0.5)"/><path d="M44.999 18H16.572a3.43 3.43 0 0 0-3.292 2.47L7.72 39.531A3.429 3.429 0 0 1 4.429 42h33.663a3.43 3.43 0 0 0 3.294-2.47l5.533-18.97a2 2 0 0 0-1.92-2.56z" fill="currentColor" style="filter: brightness(150%)"/></g></svg>
|
|
Before Width: | Height: | Size: 631 B |
|
@ -1,8 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="flex flex-col items-center justify-center h-full">
|
|
||||||
<ui-spinner class="border-primary-400 w-32 h-32"></ui-spinner>
|
|
||||||
<div class="text-3xl mt-10">Lade …</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup></script>
|
|
|
@ -1,7 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="fixed z-40 top-0 left-0 w-full h-full flex items-center justify-center p-6">
|
<div class="fixed z-40 top-0 left-0 w-full h-full flex items-center justify-center p-6">
|
||||||
<div class="relative rounded-lg p-8 bg-zinc-800 shadow-2xl shadow-black border border-zinc-700 border-solid w-full max-h-full flex flex-col overflow-auto"
|
<div
|
||||||
:class="full ? 'h-full' : innerWidth">
|
class="relative rounded-lg p-8 bg-zinc-800 shadow-2xl shadow-black border border-zinc-700 border-solid w-full max-h-full flex flex-col overflow-auto"
|
||||||
|
:class="full ? 'h-full' : innerWidth"
|
||||||
|
>
|
||||||
<div class="absolute top-0 right-0 mt-6 mr-6 flex space-x-6">
|
<div class="absolute top-0 right-0 mt-6 mr-6 flex space-x-6">
|
||||||
<slot name="actions"></slot>
|
<slot name="actions"></slot>
|
||||||
<a href="#" @click.prevent="$emit('close')">
|
<a href="#" @click.prevent="$emit('close')">
|
||||||
|
@ -15,7 +17,10 @@
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
<template #fallback>
|
<template #fallback>
|
||||||
<ui-loading></ui-loading>
|
<div class="flex flex-col items-center justify-center h-full">
|
||||||
|
<ui-spinner class="border-primary-400 w-32 h-32"></ui-spinner>
|
||||||
|
<div class="text-3xl mt-10">Lade …</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</suspense>
|
</suspense>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
<template>
|
|
||||||
<ui-popup v-if="selecting !== false" heading="Resource auswählen" @close="selecting = false">
|
|
||||||
<ui-remote-selector :value="selecting" @input="set"></ui-remote-selector>
|
|
||||||
</ui-popup>
|
|
||||||
<label class="flex flex-col group" :for="id" :class="sizeClass(size)">
|
|
||||||
<f-label v-if="label" :required="false" :value="label"></f-label>
|
|
||||||
<div class="relative flex-none flex">
|
|
||||||
<div class="w-full flex flex-col justify-center" :class="[fieldHeight, fieldAppearance, paddingX]" @click.prevent="selecting = modelValue === null ? null : {...modelValue}">
|
|
||||||
<div v-if="modelValue !== null" v-text="modelValue.resource"></div>
|
|
||||||
<div v-else>Datei auswählen</div>
|
|
||||||
</div>
|
|
||||||
<f-hint v-if="hint" :value="hint"></f-hint>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import useFieldSize from '../../composables/useFieldSize';
|
|
||||||
import {ref} from 'vue';
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue']);
|
|
||||||
const {fieldHeight, fieldAppearance, paddingX, sizeClass} = useFieldSize();
|
|
||||||
|
|
||||||
const selecting = ref(false);
|
|
||||||
|
|
||||||
function set(resource) {
|
|
||||||
emit('update:modelValue', resource);
|
|
||||||
selecting.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
size: {
|
|
||||||
type: String,
|
|
||||||
default: () => 'base',
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
hint: {
|
|
||||||
type: String,
|
|
||||||
default: () => '',
|
|
||||||
},
|
|
||||||
modelValue: {
|
|
||||||
validator: (v) => typeof v === 'object' || v === null,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
type: String,
|
|
||||||
default: () => '',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,90 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<f-select id="connection" v-model="innerConnection" label="Verbindung" name="connection" class="mt-2" :options="data"></f-select>
|
|
||||||
|
|
||||||
<div v-if="innerConnection" class="mt-4">
|
|
||||||
<div class="flex space-x-3 items-center bg-zinc-700 rounded-lg mt-3 py-1 px-2">
|
|
||||||
<ui-sprite class="w-4 h-4 text-primary-700" src="open-folder"></ui-sprite>
|
|
||||||
<div class="text-sm grow" v-text="structure.parent"></div>
|
|
||||||
<ui-icon-button icon="undo" @click="emit('input', null)">löschen</ui-icon-button>
|
|
||||||
<ui-icon-button icon="undo" @click="updateFiles(getParentDir(structure.parent))">Zurück</ui-icon-button>
|
|
||||||
</div>
|
|
||||||
<a
|
|
||||||
v-for="(file, index) in structure.files"
|
|
||||||
:key="index"
|
|
||||||
href="#"
|
|
||||||
class="flex space-x-3 items-center mt-1 transition duration-200 hover:bg-zinc-600 py-1 px-2 rounded"
|
|
||||||
@click.prevent="updateFiles(file.path)"
|
|
||||||
>
|
|
||||||
<ui-sprite class="w-8 h-8 text-primary-700" src="open-folder"></ui-sprite>
|
|
||||||
<span class="grow" :value="file.name">
|
|
||||||
{{ file.name }}
|
|
||||||
</span>
|
|
||||||
<button class="btn btn-primary btn-sm" @click.self.prevent.stop="select(file)">Auswählen</button>
|
|
||||||
<ui-sprite class="w-3 h-3 -rotate-90 text-primary-400" src="chevron"></ui-sprite>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import {ref, watch} from 'vue';
|
|
||||||
import {useApiIndex} from '../../composables/useApiIndex';
|
|
||||||
|
|
||||||
const {reload, data, axios} = useApiIndex('/api/fileshare');
|
|
||||||
|
|
||||||
const emit = defineEmits(['input']);
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
value: {
|
|
||||||
validator: (v) => typeof v === 'object' || v === null,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const innerConnection = ref(props.value === null ? null : props.value.connection_id);
|
|
||||||
|
|
||||||
const structure = ref({
|
|
||||||
parent: props.value === null ? '/' : getParentDir(props.value.resource),
|
|
||||||
files: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
function select(file) {
|
|
||||||
emit('input', {
|
|
||||||
connection_id: innerConnection.value,
|
|
||||||
resource: file.path,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getParentDir(dir) {
|
|
||||||
if (!dir) {
|
|
||||||
return '/';
|
|
||||||
}
|
|
||||||
return '/' + dir.split('/').slice(1, -1).join('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(innerConnection, () => updateFiles('/'));
|
|
||||||
|
|
||||||
async function updateFiles(parentDir) {
|
|
||||||
console.log(innerConnection);
|
|
||||||
if (innerConnection.value === null) {
|
|
||||||
structure.value = {
|
|
||||||
parent: '/',
|
|
||||||
files: [],
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await axios.post(`/api/fileshare/${innerConnection.value}/files`, {
|
|
||||||
parent: parentDir,
|
|
||||||
});
|
|
||||||
|
|
||||||
structure.value = {
|
|
||||||
parent: parentDir,
|
|
||||||
files: response.data.data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
await reload();
|
|
||||||
updateFiles(structure.value.parent);
|
|
||||||
</script>
|
|
|
@ -1,94 +0,0 @@
|
||||||
<template>
|
|
||||||
<page-layout>
|
|
||||||
<template #toolbar>
|
|
||||||
<page-toolbar-button color="primary" icon="plus" @click.prevent="create">Neue Verbindung</page-toolbar-button>
|
|
||||||
</template>
|
|
||||||
<ui-popup v-if="single !== null" :heading="single.id ? 'Verbindung bearbeiten' : 'Neue Verbindung'" @close="cancel">
|
|
||||||
<form @submit.prevent="submit">
|
|
||||||
<section class="grid grid-cols-2 gap-3 mt-6">
|
|
||||||
<f-text id="name" v-model="single.name" name="name" label="Bezeichnung" required></f-text>
|
|
||||||
<f-select
|
|
||||||
id="type"
|
|
||||||
:model-value="single.type"
|
|
||||||
label="Typ"
|
|
||||||
name="type"
|
|
||||||
:options="meta.types"
|
|
||||||
required
|
|
||||||
@update:model-value="
|
|
||||||
single = {
|
|
||||||
...single,
|
|
||||||
type: $event,
|
|
||||||
config: {...getType($event).defaults},
|
|
||||||
}
|
|
||||||
"
|
|
||||||
></f-select>
|
|
||||||
<template v-for="(field, index) in getType(single.type).fields">
|
|
||||||
<f-text
|
|
||||||
v-if="field.type === 'text' || field.type === 'password' || field.type === 'email'"
|
|
||||||
:id="field.key"
|
|
||||||
:key="index"
|
|
||||||
v-model="single.config[field.key]"
|
|
||||||
:label="field.label"
|
|
||||||
:type="field.type"
|
|
||||||
:name="field.key"
|
|
||||||
required
|
|
||||||
></f-text>
|
|
||||||
</template>
|
|
||||||
</section>
|
|
||||||
<section class="flex mt-4 space-x-2">
|
|
||||||
<ui-button type="submit" class="btn-danger">Speichern</ui-button>
|
|
||||||
<ui-button class="btn-primary" @click.prevent="single = null">Abbrechen</ui-button>
|
|
||||||
</section>
|
|
||||||
</form>
|
|
||||||
</ui-popup>
|
|
||||||
<setting-layout>
|
|
||||||
<div class="w-full h-full pb-6">
|
|
||||||
<table cellspacing="0" cellpadding="0" border="0" class="custom-table custom-table-sm hidden md:table">
|
|
||||||
<thead>
|
|
||||||
<th>Bezeichnung</th>
|
|
||||||
<th>Typ</th>
|
|
||||||
<th>Prüfung</th>
|
|
||||||
<th>Aktion</th>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tr v-for="(connection, index) in data" :key="index">
|
|
||||||
<td v-text="connection.name"></td>
|
|
||||||
<td v-text="connection.type_human"></td>
|
|
||||||
<td>
|
|
||||||
<ui-boolean-display
|
|
||||||
:value="connection.is_active"
|
|
||||||
long-label="Verbindungsstatus"
|
|
||||||
:label="connection.is_active ? 'Verbindung erfolgreich' : 'Verbindung fehlgeschlagen'"
|
|
||||||
></ui-boolean-display>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a v-tooltip="`Bearbeiten`" href="#" class="inline-flex btn btn-warning btn-sm" @click.prevent="edit(connection)"><ui-sprite src="pencil"></ui-sprite></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div class="px-6">
|
|
||||||
<ui-pagination class="mt-4" :value="meta" :only="['data']"></ui-pagination>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</setting-layout>
|
|
||||||
</page-layout>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import {useApiIndex} from '../../composables/useApiIndex.js';
|
|
||||||
import SettingLayout from '../setting/Layout.vue';
|
|
||||||
|
|
||||||
const {meta, data, reload, create, edit, cancel, single, submit} = useApiIndex('/api/fileshare', 'fileshare');
|
|
||||||
|
|
||||||
function getType(type) {
|
|
||||||
if (!type) {
|
|
||||||
return {
|
|
||||||
fields: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return meta.value.types.find((t) => t.id === type);
|
|
||||||
}
|
|
||||||
|
|
||||||
reload();
|
|
||||||
</script>
|
|
|
@ -61,10 +61,10 @@
|
||||||
v-model="single.excerpt"
|
v-model="single.excerpt"
|
||||||
hint="Gebe hier eine kurze Beschreibung für die Veranstaltungs-Übersicht ein (Maximal 130 Zeichen)."
|
hint="Gebe hier eine kurze Beschreibung für die Veranstaltungs-Übersicht ein (Maximal 130 Zeichen)."
|
||||||
label="Auszug"
|
label="Auszug"
|
||||||
:rows="5"
|
rows="5"
|
||||||
required
|
required
|
||||||
></f-textarea>
|
></f-textarea>
|
||||||
<f-editor id="description" v-model="single.description" name="description" label="Beschreibung" :rows="10" required></f-editor>
|
<f-editor id="description" v-model="single.description" name="description" label="Beschreibung" rows="10" required></f-editor>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="active === 1">
|
<div v-if="active === 1">
|
||||||
<ui-note class="mt-2"> Sobald sich der erste Teilnehmer für die Veranstaltung angemeldet hat, kann dieses Formular nicht mehr geändert werden. </ui-note>
|
<ui-note class="mt-2"> Sobald sich der erste Teilnehmer für die Veranstaltung angemeldet hat, kann dieses Formular nicht mehr geändert werden. </ui-note>
|
||||||
|
@ -79,12 +79,12 @@
|
||||||
</ui-note>
|
</ui-note>
|
||||||
<div>
|
<div>
|
||||||
<ui-tabs v-model="activeMailTab" :entries="mailTabs"></ui-tabs>
|
<ui-tabs v-model="activeMailTab" :entries="mailTabs"></ui-tabs>
|
||||||
<f-editor v-if="activeMailTab === 0" id="mail_top" v-model="single.mail_top" name="mail_top" label="E-Mail-Teil 1" :rows="8" conditions required>
|
<f-editor v-if="activeMailTab === 0" id="mail_top" v-model="single.mail_top" name="mail_top" label="E-Mail-Teil 1" rows="8" conditions required>
|
||||||
<template #conditions="{data, resolve}">
|
<template #conditions="{data, resolve}">
|
||||||
<conditions :single="single" :value="data" @save="resolve"> </conditions>
|
<conditions :single="single" :value="data" @save="resolve"> </conditions>
|
||||||
</template>
|
</template>
|
||||||
</f-editor>
|
</f-editor>
|
||||||
<f-editor v-if="activeMailTab === 1" id="mail_bottom" v-model="single.mail_bottom" name="mail_bottom" label="E-Mail-Teil 2" :rows="8" conditions required>
|
<f-editor v-if="activeMailTab === 1" id="mail_bottom" v-model="single.mail_bottom" name="mail_bottom" label="E-Mail-Teil 2" rows="8" conditions required>
|
||||||
<template #conditions="{data, resolve}">
|
<template #conditions="{data, resolve}">
|
||||||
<conditions :single="single" :value="data" @save="resolve"> </conditions>
|
<conditions :single="single" :value="data" @save="resolve"> </conditions>
|
||||||
</template>
|
</template>
|
||||||
|
@ -108,13 +108,6 @@
|
||||||
</template>
|
</template>
|
||||||
</f-multiplefiles>
|
</f-multiplefiles>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="active === 3">
|
|
||||||
<div class="grid gap-3">
|
|
||||||
<ui-remote-resource id="export" v-model="single.export.root" label="Haupt-Ordner"></ui-remote-resource>
|
|
||||||
<f-select id="group_by" v-model="single.export.group_by" :options="allFields" label="Gruppieren nach" name="group_by"></f-select>
|
|
||||||
<f-select id="to_group_field" v-model="single.export.to_group_field" :options="allFields" label="Nach Gruppe schreiben" name="to_group_field"></f-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<a href="#" @click.prevent="submit">
|
<a href="#" @click.prevent="submit">
|
||||||
|
@ -129,8 +122,8 @@
|
||||||
|
|
||||||
<page-filter breakpoint="xl">
|
<page-filter breakpoint="xl">
|
||||||
<f-text id="search" :model-value="getFilter('search')" label="Suchen …" size="sm" @update:model-value="setFilter('search', $event)"></f-text>
|
<f-text id="search" :model-value="getFilter('search')" label="Suchen …" size="sm" @update:model-value="setFilter('search', $event)"></f-text>
|
||||||
<f-switch id="past" :model-value="getFilter('past')" label="vergangene zeigen" name="past" size="sm" @update:model-value="setFilter('past', $event)"></f-switch>
|
<f-switch id="past" :model-value="getFilter('past')" label="vergangene zeigen" size="sm" @update:model-value="setFilter('past', $event)"></f-switch>
|
||||||
<f-switch id="inactive" :model-value="getFilter('inactive')" label="inaktive zeigen" name="inactive" size="sm" @update:model-value="setFilter('inactive', $event)"></f-switch>
|
<f-switch id="inactive" :model-value="getFilter('inactive')" label="inaktive zeigen" size="sm" @update:model-value="setFilter('inactive', $event)"></f-switch>
|
||||||
</page-filter>
|
</page-filter>
|
||||||
|
|
||||||
<table cellspacing="0" cellpadding="0" border="0" class="custom-table custom-table-sm">
|
<table cellspacing="0" cellpadding="0" border="0" class="custom-table custom-table-sm">
|
||||||
|
@ -173,7 +166,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref, inject, computed} from 'vue';
|
import {ref, inject} from 'vue';
|
||||||
import {indexProps, useIndex} from '../../composables/useInertiaApiIndex.js';
|
import {indexProps, useIndex} from '../../composables/useInertiaApiIndex.js';
|
||||||
import FormBuilder from '../formtemplate/FormBuilder.vue';
|
import FormBuilder from '../formtemplate/FormBuilder.vue';
|
||||||
import Participants from './Participants.vue';
|
import Participants from './Participants.vue';
|
||||||
|
@ -194,21 +187,6 @@ const fileSettingPopup = ref(null);
|
||||||
const tabs = [{title: 'Allgemeines'}, {title: 'Formular'}, {title: 'Bestätigungs-E-Mail'}, {title: 'Export'}];
|
const tabs = [{title: 'Allgemeines'}, {title: 'Formular'}, {title: 'Bestätigungs-E-Mail'}, {title: 'Export'}];
|
||||||
const mailTabs = [{title: 'vor Daten'}, {title: 'nach Daten'}];
|
const mailTabs = [{title: 'vor Daten'}, {title: 'nach Daten'}];
|
||||||
|
|
||||||
const allFields = computed(() => {
|
|
||||||
if (!single.value) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = [];
|
|
||||||
single.value.config.sections.forEach((section) => {
|
|
||||||
section.fields.forEach((field) => {
|
|
||||||
result.push({id: field.key, name: field.name});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
|
|
||||||
function setTemplate(template) {
|
function setTemplate(template) {
|
||||||
active.value = 0;
|
active.value = 0;
|
||||||
single.value.config = template.config;
|
single.value.config = template.config;
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
<th>NaMi-Name</th>
|
<th>NaMi-Name</th>
|
||||||
<th>Interner Name</th>
|
<th>Interner Name</th>
|
||||||
<th>Ebene</th>
|
<th>Ebene</th>
|
||||||
<th>Remote</th>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tr v-for="child in editing.children" :key="child.id">
|
<tr v-for="child in editing.children" :key="child.id">
|
||||||
<td>
|
<td>
|
||||||
|
@ -31,9 +30,6 @@
|
||||||
<td>
|
<td>
|
||||||
<f-select :id="`level-${child.id}`" v-model="child.level" label="" size="sm" :name="`level-${child.id}`" :options="meta.levels"></f-select>
|
<f-select :id="`level-${child.id}`" v-model="child.level" label="" size="sm" :name="`level-${child.id}`" :options="meta.levels"></f-select>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
|
||||||
<ui-remote-resource :id="`fileshare-${child.id}`" v-model="child.fileshare" size="sm" label=""></ui-remote-resource>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -112,8 +108,7 @@ async function edit(parent) {
|
||||||
|
|
||||||
async function store() {
|
async function store() {
|
||||||
await axios.post(meta.value.links.bulkstore, [editing.value.parent, ...editing.value.children]);
|
await axios.post(meta.value.links.bulkstore, [editing.value.parent, ...editing.value.children]);
|
||||||
await toggle(editing.value.parent);
|
children[editing.value.parent.id] = (await axios.get(editing.value.parent.links.children)).data.data;
|
||||||
await toggle(editing.value.parent);
|
|
||||||
editing.value = null;
|
editing.value = null;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -19,10 +19,6 @@ use App\Invoice\Actions\InvoiceStoreAction;
|
||||||
use App\Course\Actions\CourseUpdateAction;
|
use App\Course\Actions\CourseUpdateAction;
|
||||||
use App\Dashboard\Actions\IndexAction as DashboardIndexAction;
|
use App\Dashboard\Actions\IndexAction as DashboardIndexAction;
|
||||||
use App\Efz\ShowEfzDocumentAction;
|
use App\Efz\ShowEfzDocumentAction;
|
||||||
use App\Fileshare\Actions\FileshareApiIndexAction;
|
|
||||||
use App\Fileshare\Actions\FileshareStoreAction;
|
|
||||||
use App\Fileshare\Actions\FileshareUpdateAction;
|
|
||||||
use App\Fileshare\Actions\ListFilesAction;
|
|
||||||
use App\Form\Actions\ExportAction as ActionsExportAction;
|
use App\Form\Actions\ExportAction as ActionsExportAction;
|
||||||
use App\Form\Actions\FormDestroyAction;
|
use App\Form\Actions\FormDestroyAction;
|
||||||
use App\Form\Actions\FormIndexAction;
|
use App\Form\Actions\FormIndexAction;
|
||||||
|
@ -170,10 +166,4 @@ Route::group(['middleware' => 'auth:web'], function (): void {
|
||||||
Route::get('/form/{form}/participants/{parent?}', ParticipantIndexAction::class)->name('form.participant.index');
|
Route::get('/form/{form}/participants/{parent?}', ParticipantIndexAction::class)->name('form.participant.index');
|
||||||
Route::post('/form/{form}/is-dirty', IsDirtyAction::class)->name('form.is-dirty');
|
Route::post('/form/{form}/is-dirty', IsDirtyAction::class)->name('form.is-dirty');
|
||||||
Route::delete('/participant/{participant}', ParticipantDestroyAction::class)->name('participant.destroy');
|
Route::delete('/participant/{participant}', ParticipantDestroyAction::class)->name('participant.destroy');
|
||||||
|
|
||||||
// ------------------------------------ fileshare -----------------------------------
|
|
||||||
Route::post('/fileshare', FileshareStoreAction::class)->name('fileshare.store');
|
|
||||||
Route::patch('/fileshare/{fileshare}', FileshareUpdateAction::class)->name('fileshare.update');
|
|
||||||
Route::get('/api/fileshare', FileshareApiIndexAction::class)->name('api.fileshare.index');
|
|
||||||
Route::post('/api/fileshare/{fileshare}/files', ListFilesAction::class)->name('api.fileshare.files');
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@ use App\Subactivity;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Tests\EndToEndTestCase;
|
||||||
use Tests\Feature\Form\FormtemplateSectionRequest;
|
use Tests\Feature\Form\FormtemplateSectionRequest;
|
||||||
use Tests\RequestFactories\EditorRequestFactory;
|
use Tests\RequestFactories\EditorRequestFactory;
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace Tests\EndToEnd\Form;
|
namespace Tests\EndToEnd\Form;
|
||||||
|
|
||||||
use App\Fileshare\Data\FileshareResourceData;
|
|
||||||
use App\Form\Data\ExportData;
|
|
||||||
use App\Form\FormSettings;
|
use App\Form\FormSettings;
|
||||||
use App\Form\Models\Form;
|
use App\Form\Models\Form;
|
||||||
use App\Form\Models\Formtemplate;
|
use App\Form\Models\Formtemplate;
|
||||||
|
@ -65,7 +63,6 @@ class FormIndexActionTest extends FormTestCase
|
||||||
->assertInertiaPath('data.meta.default.is_active', true)
|
->assertInertiaPath('data.meta.default.is_active', true)
|
||||||
->assertInertiaPath('data.meta.default.is_private', false)
|
->assertInertiaPath('data.meta.default.is_private', false)
|
||||||
->assertInertiaPath('data.meta.default.mailattachments', [])
|
->assertInertiaPath('data.meta.default.mailattachments', [])
|
||||||
->assertInertiaPath('data.meta.default.export', ['root' => null, 'group_by' => null, 'to_group_field' => null])
|
|
||||||
->assertInertiaPath('data.meta.default.config', null)
|
->assertInertiaPath('data.meta.default.config', null)
|
||||||
->assertInertiaPath('data.meta.base_url', url(''))
|
->assertInertiaPath('data.meta.base_url', url(''))
|
||||||
->assertInertiaPath('data.meta.namiTypes.0', ['id' => 'Vorname', 'name' => 'Vorname'])
|
->assertInertiaPath('data.meta.namiTypes.0', ['id' => 'Vorname', 'name' => 'Vorname'])
|
||||||
|
@ -73,22 +70,6 @@ class FormIndexActionTest extends FormTestCase
|
||||||
->assertInertiaPath('data.meta.section_default.name', '');
|
->assertInertiaPath('data.meta.section_default.name', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItDisplaysExport(): void
|
|
||||||
{
|
|
||||||
$this->login()->loginNami()->withoutExceptionHandling();
|
|
||||||
Form::factory()
|
|
||||||
->name('lala')
|
|
||||||
->export(ExportData::from(['root' => FileshareResourceData::from(['connection_id' => 2, 'resource' => '/dir']), 'group_by' => 'lala', 'to_group_field' => 'abc']))
|
|
||||||
->create();
|
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
$this->get(route('form.index'))
|
|
||||||
->assertInertiaPath('data.data.0.export.group_by', 'lala')
|
|
||||||
->assertInertiaPath('data.data.0.export.root.connection_id', 2)
|
|
||||||
->assertInertiaPath('data.data.0.export.root.resource', '/dir')
|
|
||||||
->assertInertiaPath('data.data.0.export.to_group_field', 'abc');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItHandlesFullTextSearch(): void
|
public function testItHandlesFullTextSearch(): void
|
||||||
{
|
{
|
||||||
$this->withoutExceptionHandling()->login()->loginNami();
|
$this->withoutExceptionHandling()->login()->loginNami();
|
||||||
|
|
|
@ -25,8 +25,9 @@ class IndexTest extends EndToEndTestCase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
$response = $this->get('/member')->assertComponent('member/VIndex');
|
$response = $this->get('/member');
|
||||||
|
|
||||||
|
$this->assertComponent('member/VIndex', $response);
|
||||||
$this->assertInertiaHas('::firstname::', $response, 'data.data.0.firstname');
|
$this->assertInertiaHas('::firstname::', $response, 'data.data.0.firstname');
|
||||||
$this->assertInertiaHas(false, $response, 'data.data.0.has_nami');
|
$this->assertInertiaHas(false, $response, 'data.data.0.has_nami');
|
||||||
$this->assertInertiaHas('Kölner Str 3, 33333 Hilden', $response, 'data.data.0.full_address');
|
$this->assertInertiaHas('Kölner Str 3, 33333 Hilden', $response, 'data.data.0.full_address');
|
||||||
|
|
|
@ -15,7 +15,9 @@ class ForgotPasswordTest extends TestCase
|
||||||
public function testItShowsResetForm(): void
|
public function testItShowsResetForm(): void
|
||||||
{
|
{
|
||||||
$this->withoutExceptionHandling();
|
$this->withoutExceptionHandling();
|
||||||
$this->get('/password/reset')->assertComponent('authentication/PasswordReset');
|
$response = $this->get('/password/reset');
|
||||||
|
|
||||||
|
$this->assertComponent('authentication/PasswordReset', $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItRequiresAnEmailAddress(): void
|
public function testItRequiresAnEmailAddress(): void
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace Tests\Feature\Form;
|
namespace Tests\Feature\Form;
|
||||||
|
|
||||||
use App\Form\Actions\ExportAction;
|
|
||||||
use App\Form\Actions\ExportSyncAction;
|
|
||||||
use App\Form\Enums\NamiType;
|
use App\Form\Enums\NamiType;
|
||||||
use App\Form\Enums\SpecialType;
|
use App\Form\Enums\SpecialType;
|
||||||
use App\Form\Mails\ConfirmRegistrationMail;
|
use App\Form\Mails\ConfirmRegistrationMail;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace Tests\Feature\Form;
|
namespace Tests\Feature\Form;
|
||||||
|
|
||||||
use App\Form\Data\ExportData;
|
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Tests\RequestFactories\EditorRequestFactory;
|
use Tests\RequestFactories\EditorRequestFactory;
|
||||||
|
@ -20,7 +19,6 @@ use Worksome\RequestFactories\RequestFactory;
|
||||||
* @method self registrationUntil(string|null $date)
|
* @method self registrationUntil(string|null $date)
|
||||||
* @method self isActive(bool $isActive)
|
* @method self isActive(bool $isActive)
|
||||||
* @method self isPrivate(bool $isPrivate)
|
* @method self isPrivate(bool $isPrivate)
|
||||||
* @method self export(ExportData $export)
|
|
||||||
*/
|
*/
|
||||||
class FormRequest extends RequestFactory
|
class FormRequest extends RequestFactory
|
||||||
{
|
{
|
||||||
|
@ -48,7 +46,6 @@ class FormRequest extends RequestFactory
|
||||||
'mail_bottom' => EditorRequestFactory::new()->create(),
|
'mail_bottom' => EditorRequestFactory::new()->create(),
|
||||||
'header_image' => $this->getHeaderImagePayload(str()->uuid() . '.jpg'),
|
'header_image' => $this->getHeaderImagePayload(str()->uuid() . '.jpg'),
|
||||||
'mailattachments' => [],
|
'mailattachments' => [],
|
||||||
'export' => ExportData::from([])->toArray(),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace Tests\Feature\Form;
|
namespace Tests\Feature\Form;
|
||||||
|
|
||||||
use App\Fileshare\Data\FileshareResourceData;
|
|
||||||
use App\Form\Data\ExportData;
|
|
||||||
use App\Form\Enums\NamiType;
|
use App\Form\Enums\NamiType;
|
||||||
use App\Form\Models\Form;
|
use App\Form\Models\Form;
|
||||||
use App\Lib\Events\Succeeded;
|
use App\Lib\Events\Succeeded;
|
||||||
|
@ -68,16 +66,6 @@ class FormStoreActionTest extends FormTestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItStoresExport(): void
|
|
||||||
{
|
|
||||||
$this->login()->loginNami()->withoutExceptionHandling();
|
|
||||||
|
|
||||||
$this->postJson(route('form.store'), FormRequest::new()->export(ExportData::from(['root' => FileshareResourceData::from(['connection_id' => 2, 'resource' => '/dir']), 'group_by' => 'lala', 'to_group_field' => 'abc']))->create())->assertOk();
|
|
||||||
|
|
||||||
$form = Form::first();
|
|
||||||
$this->assertEquals(2, $form->export->root->connectionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function validationDataProvider(): Generator
|
public function validationDataProvider(): Generator
|
||||||
{
|
{
|
||||||
yield [FormRequest::new()->name(''), ['name' => 'Name ist erforderlich.']];
|
yield [FormRequest::new()->name(''), ['name' => 'Name ist erforderlich.']];
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace Tests\Feature\Form;
|
namespace Tests\Feature\Form;
|
||||||
|
|
||||||
use App\Fileshare\Data\FileshareResourceData;
|
|
||||||
use App\Form\Data\ExportData;
|
|
||||||
use App\Form\Models\Form;
|
use App\Form\Models\Form;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
|
@ -41,16 +39,6 @@ class FormUpdateActionTest extends FormTestCase
|
||||||
$this->assertFrontendCacheCleared();
|
$this->assertFrontendCacheCleared();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItUpdatesExport(): void
|
|
||||||
{
|
|
||||||
$this->login()->loginNami()->withoutExceptionHandling();
|
|
||||||
|
|
||||||
$form = Form::factory()->create();
|
|
||||||
$this->patchJson(route('form.update', ['form' => $form]), FormRequest::new()->export(ExportData::from(['root' => FileshareResourceData::from(['connection_id' => 2, 'resource' => '/dir']), 'group_by' => 'lala', 'to_group_field' => 'abc']))->create());
|
|
||||||
|
|
||||||
$this->assertEquals(2, $form->fresh()->export->root->connectionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItUpdatesActiveColumnsWhenFieldRemoved(): void
|
public function testItUpdatesActiveColumnsWhenFieldRemoved(): void
|
||||||
{
|
{
|
||||||
$this->login()->loginNami()->withoutExceptionHandling();
|
$this->login()->loginNami()->withoutExceptionHandling();
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace Tests\Feature\Group;
|
namespace Tests\Feature\Group;
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\OwncloudConnection;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use App\Group;
|
use App\Group;
|
||||||
use App\Group\Enums\Level;
|
use App\Group\Enums\Level;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
@ -20,37 +18,13 @@ class BulkstoreTest extends TestCase
|
||||||
$group = Group::factory()->for(Group::first(), 'parent')->create(['inner_name' => 'Gruppe', 'level' => Level::REGION]);
|
$group = Group::factory()->for(Group::first(), 'parent')->create(['inner_name' => 'Gruppe', 'level' => Level::REGION]);
|
||||||
|
|
||||||
$this->postJson(route('group.bulkstore'), [
|
$this->postJson(route('group.bulkstore'), [
|
||||||
['id' => $group->id, 'inner_name' => 'Abc', 'level' => Level::FEDERATION->value, 'fileshare' => null]
|
['id' => $group->id, 'inner_name' => 'Abc', 'level' => Level::FEDERATION->value]
|
||||||
])->assertOk();
|
])->assertOk();
|
||||||
|
|
||||||
$this->assertNull($group->fresh()->fileshare);
|
|
||||||
$this->assertDatabaseHas('groups', [
|
$this->assertDatabaseHas('groups', [
|
||||||
'id' => $group->id,
|
'id' => $group->id,
|
||||||
'inner_name' => 'Abc',
|
'inner_name' => 'Abc',
|
||||||
'level' => 'Diözese',
|
'level' => 'Diözese',
|
||||||
'fileshare' => null,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItStoresFileconnection(): void
|
|
||||||
{
|
|
||||||
$this->login()->loginNami()->withoutExceptionHandling();
|
|
||||||
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->name('lokaler Server')
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$group = Group::factory()->for(Group::first(), 'parent')->create(['inner_name' => 'Gruppe', 'level' => Level::REGION]);
|
|
||||||
|
|
||||||
$this->postJson(route('group.bulkstore'), [
|
|
||||||
['id' => $group->id, 'inner_name' => 'Abc', 'level' => Level::FEDERATION->value, 'fileshare' => [
|
|
||||||
'connection_id' => $connection->id,
|
|
||||||
'resource' => '/abc',
|
|
||||||
]]
|
|
||||||
])->assertOk();
|
|
||||||
|
|
||||||
$this->assertEquals($connection->id, $group->fresh()->fileshare->connectionId);
|
|
||||||
$this->assertEquals('/abc', $group->fresh()->fileshare->resource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace Tests\Feature\Group;
|
namespace Tests\Feature\Group;
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\OwncloudConnection;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use App\Group;
|
use App\Group;
|
||||||
use App\Group\Enums\Level;
|
use App\Group\Enums\Level;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
@ -75,21 +73,4 @@ class IndexTest extends TestCase
|
||||||
|
|
||||||
$this->get('/api/group/' . Group::first()->id)->assertJsonPath('data.0.id', $group->id);
|
$this->get('/api/group/' . Group::first()->id)->assertJsonPath('data.0.id', $group->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItDisplaysFileshare(): void
|
|
||||||
{
|
|
||||||
$this->login()->loginNami()->withoutExceptionHandling();
|
|
||||||
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->name('lokaler Server')
|
|
||||||
->create();
|
|
||||||
|
|
||||||
Group::factory()->for(Group::first(), 'parent')->create(['level' => null, 'fileshare' => [
|
|
||||||
'connection_id' => $connection->id,
|
|
||||||
'resource' => '/abc',
|
|
||||||
]]);
|
|
||||||
|
|
||||||
$this->get('/api/group/' . Group::first()->id)->assertJsonPath('data.0.fileshare.resource', '/abc');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
rm -R /var/www/owncloud/core/skeleton/*
|
|
||||||
|
|
||||||
true
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Fileshare;
|
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\OwncloudConnection;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use Tests\FileshareTestCase;
|
|
||||||
|
|
||||||
class AdapterTest extends FileshareTestCase
|
|
||||||
{
|
|
||||||
public function testItGetsFilesInRoot(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
|
|
||||||
->withDirs('badenpowell', []);
|
|
||||||
|
|
||||||
$storage = OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')])->getFilesystem();
|
|
||||||
$storage->put('/test.pdf', '');
|
|
||||||
$this->assertEquals(['test.pdf'], $storage->files('/'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItGetsFilesInSubdirectory(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
|
|
||||||
->withDirs('badenpowell', ['/pictures']);
|
|
||||||
|
|
||||||
$storage = OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')])->getFilesystem();
|
|
||||||
$storage->put('/pictures/test.pdf', '');
|
|
||||||
$this->assertEquals([], $storage->files('/'));
|
|
||||||
$this->assertEquals(['pictures/test.pdf'], $storage->files('/pictures'));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Fileshare;
|
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\OwncloudConnection;
|
|
||||||
use App\Fileshare\Data\FileshareResourceData;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use App\Form\Actions\ExportSyncAction;
|
|
||||||
use App\Form\Data\ExportData;
|
|
||||||
use App\Form\Models\Form;
|
|
||||||
use App\Form\Models\Participant;
|
|
||||||
use App\Group;
|
|
||||||
use Tests\FileshareTestCase;
|
|
||||||
use Tests\Lib\CreatesFormFields;
|
|
||||||
|
|
||||||
class ExportSyncActionTest extends FileshareTestCase
|
|
||||||
{
|
|
||||||
|
|
||||||
use CreatesFormFields;
|
|
||||||
|
|
||||||
public function testItDoesntUploadFileWhenNoExportGiven(): void
|
|
||||||
{
|
|
||||||
$form = Form::factory()->fields([
|
|
||||||
$this->textField('vorname'),
|
|
||||||
$this->textField('nachname'),
|
|
||||||
])->create();
|
|
||||||
|
|
||||||
ExportSyncAction::run($form);
|
|
||||||
$this->assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItUploadsRootFile(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->withOwncloudUser('badenpowell', 'secret')->withDirs('badenpowell', ['/abc']);
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->create();
|
|
||||||
$form = Form::factory()->name('Formular')->fields([
|
|
||||||
$this->textField('vorname'),
|
|
||||||
$this->textField('nachname'),
|
|
||||||
])->export(ExportData::from(['root' => FileshareResourceData::from(['connection_id' => $connection->id, 'resource' => '/abc'])]))->create();
|
|
||||||
Participant::factory()->for($form)->data(['firstname' => 'AAA', 'lastname' => 'BBB'])->create();
|
|
||||||
|
|
||||||
ExportSyncAction::run($form);
|
|
||||||
|
|
||||||
$this->assertEquals(['abc/Anmeldungen Formular.xlsx'], $connection->type->getFilesystem()->files('/abc'));
|
|
||||||
$this->assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItUploadsGroupFile(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->withOwncloudUser('badenpowell', 'secret')->withDirs('badenpowell', ['/abc', '/stamm']);
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->create();
|
|
||||||
$group = Group::factory()->create(['fileshare' => FileshareResourceData::from(['connection_id' => $connection->id, 'resource' => '/stamm'])]);
|
|
||||||
$form = Form::factory()->name('Formular')->fields([
|
|
||||||
$this->textField('vorname')->name('Vorname'),
|
|
||||||
$this->textField('nachname')->name('Nachname'),
|
|
||||||
$this->groupField('stamm')->name('Stamm'),
|
|
||||||
])->export(ExportData::from(['to_group_field' => 'stamm', 'group_by' => 'vorname', 'root' => FileshareResourceData::from(['connection_id' => $connection->id, 'resource' => '/abc'])]))->create();
|
|
||||||
Participant::factory()->for($form)->data(['vorname' => 'AAA', 'nachname' => 'BBB', 'stamm' => $group->id])->create();
|
|
||||||
Participant::factory()->for($form)->data(['vorname' => 'CCC', 'nachname' => 'DDD', 'stamm' => null])->create();
|
|
||||||
|
|
||||||
ExportSyncAction::run($form);
|
|
||||||
|
|
||||||
$this->assertEquals(['stamm/Anmeldungen Formular.xlsx'], $connection->type->getFilesystem()->files('/stamm'));
|
|
||||||
$this->assertTrue(true);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Fileshare;
|
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\OwncloudConnection;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use Tests\FileshareTestCase;
|
|
||||||
|
|
||||||
class FileshareFilesActionTest extends FileshareTestCase
|
|
||||||
{
|
|
||||||
public function testItGetsFilesForAConnection(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
|
|
||||||
->withDirs('badenpowell', ['/pictures', '/lala']);
|
|
||||||
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), [
|
|
||||||
'parent' => null,
|
|
||||||
])
|
|
||||||
->assertJsonCount(2, 'data')
|
|
||||||
->assertJsonPath('data.0.name', 'lala')
|
|
||||||
->assertJsonPath('data.0.path', '/lala')
|
|
||||||
->assertJsonPath('data.0.parent', '/')
|
|
||||||
->assertJsonPath('data.1.name', 'pictures')
|
|
||||||
->assertJsonPath('data.1.path', '/pictures')
|
|
||||||
->assertJsonPath('data.1.parent', '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItGetsSubdirectories(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
|
|
||||||
->withDirs('badenpowell', ['/pictures', '/lala', '/lala/dd', '/lala/ff']);
|
|
||||||
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), ['parent' => '/pictures'])->assertJsonCount(0, 'data');
|
|
||||||
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), ['parent' => '/lala'])
|
|
||||||
->assertJsonCount(2, 'data')
|
|
||||||
->assertJsonPath('data.0.name', 'dd')
|
|
||||||
->assertJsonPath('data.0.path', '/lala/dd')
|
|
||||||
->assertJsonPath('data.0.parent', '/lala')
|
|
||||||
->assertJsonPath('data.1.name', 'ff')
|
|
||||||
->assertJsonPath('data.1.path', '/lala/ff')
|
|
||||||
->assertJsonPath('data.1.parent', '/lala');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItGetsSubdirectoriesOfSubdirectory(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
|
|
||||||
->withDirs('badenpowell', ['/lala', '/lala/dd', '/lala/dd/ee']);
|
|
||||||
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), ['parent' => '/lala/dd'])
|
|
||||||
->assertJsonCount(1, 'data')
|
|
||||||
->assertJsonPath('data.0.name', 'ee')
|
|
||||||
->assertJsonPath('data.0.path', '/lala/dd/ee')
|
|
||||||
->assertJsonPath('data.0.parent', '/lala/dd');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItGetsFilesWithDot(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret')
|
|
||||||
->withDirs('badenpowell', ['/1. aa']);
|
|
||||||
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$this->postJson(route('api.fileshare.files', ['fileshare' => $connection]), ['parent' => '/'])
|
|
||||||
->assertJsonPath('data.0.name', '1. aa');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Fileshare;
|
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\OwncloudConnection;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use Tests\FileshareTestCase;
|
|
||||||
|
|
||||||
class FileshareIndexActionTest extends FileshareTestCase
|
|
||||||
{
|
|
||||||
public function testItListsOwncloudConnectionsThatAreActive(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret');
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'badenpowell', 'password' => 'secret', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->name('lokaler Server')
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$this->get('/api/fileshare')
|
|
||||||
->assertJsonPath('data.0.name', 'lokaler Server')
|
|
||||||
->assertJsonPath('data.0.type', OwncloudConnection::class)
|
|
||||||
->assertJsonPath('data.0.config.user', 'badenpowell')
|
|
||||||
->assertJsonPath('data.0.config.password', 'secret')
|
|
||||||
->assertJsonPath('data.0.config.base_url', env('TEST_OWNCLOUD_DOMAIN'))
|
|
||||||
->assertJsonPath('data.0.id', $connection->id)
|
|
||||||
->assertJsonPath('data.0.is_active', true)
|
|
||||||
->assertJsonPath('data.0.type_human', 'Owncloud')
|
|
||||||
->assertJsonPath('data.0.links.update', route('fileshare.update', ['fileshare' => $connection]))
|
|
||||||
->assertJsonPath('meta.default.name', '')
|
|
||||||
->assertJsonPath('meta.links.store', route('fileshare.store'))
|
|
||||||
->assertJsonPath('meta.types.0.id', OwncloudConnection::class)
|
|
||||||
->assertJsonPath('meta.types.0.name', 'Owncloud')
|
|
||||||
->assertJsonPath('meta.types.0.defaults.base_url', '')
|
|
||||||
->assertJsonPath('meta.types.0.fields.1', ['label' => 'Benutzer', 'key' => 'user', 'type' => 'text']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItRendersComponent(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami();
|
|
||||||
|
|
||||||
$this->get('/setting/fileshare')->assertComponent('fileshare/Index');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Fileshare;
|
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\OwncloudConnection;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use Tests\FileshareTestCase;
|
|
||||||
|
|
||||||
class FileshareStoreActionTest extends FileshareTestCase
|
|
||||||
{
|
|
||||||
public function testItStoresAConnection(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret');
|
|
||||||
|
|
||||||
$this->post(route('fileshare.store'), [
|
|
||||||
'name' => 'Lala',
|
|
||||||
'type' => OwncloudConnection::class,
|
|
||||||
'config' => [
|
|
||||||
'user' => 'badenpowell',
|
|
||||||
'password' => 'secret',
|
|
||||||
'base_url' => env('TEST_OWNCLOUD_DOMAIN'),
|
|
||||||
]
|
|
||||||
])->assertOk();
|
|
||||||
|
|
||||||
$connection = Fileshare::firstOrFail();
|
|
||||||
$this->assertEquals('badenpowell', $connection->type->user);
|
|
||||||
$this->assertEquals('secret', $connection->type->password);
|
|
||||||
$this->assertEquals(env('TEST_OWNCLOUD_DOMAIN'), $connection->type->baseUrl);
|
|
||||||
$this->assertEquals('Lala', $connection->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItChecksConnection(): void
|
|
||||||
{
|
|
||||||
$this->withExceptionHandling()->login()->loginNami();
|
|
||||||
|
|
||||||
$this->postJson(route('fileshare.store'), [
|
|
||||||
'name' => 'Lala',
|
|
||||||
'type' => OwncloudConnection::class,
|
|
||||||
'config' => [
|
|
||||||
'user' => 'badenpowell',
|
|
||||||
'password' => 'secret',
|
|
||||||
'base_url' => env('TEST_OWNCLOUD_DOMAIN'),
|
|
||||||
]
|
|
||||||
])->assertJsonValidationErrors(['type' => 'Verbindung fehlgeschlagen']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItNeedsName(): void
|
|
||||||
{
|
|
||||||
$this->withExceptionHandling()->login()->loginNami();
|
|
||||||
|
|
||||||
$this->postJson(route('fileshare.store'), [
|
|
||||||
'name' => '',
|
|
||||||
'type' => OwncloudConnection::class,
|
|
||||||
'config' => [
|
|
||||||
'user' => 'badenpowell',
|
|
||||||
'password' => 'secret',
|
|
||||||
'base_url' => env('TEST_OWNCLOUD_DOMAIN'),
|
|
||||||
]
|
|
||||||
])->assertJsonValidationErrors(['name' => 'Name ist erforderlich.']);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Fileshare;
|
|
||||||
|
|
||||||
use App\Fileshare\ConnectionTypes\OwncloudConnection;
|
|
||||||
use App\Fileshare\Models\Fileshare;
|
|
||||||
use Tests\FileshareTestCase;
|
|
||||||
|
|
||||||
class FileshareUpdateActionTest extends FileshareTestCase
|
|
||||||
{
|
|
||||||
public function testItStoresAConnection(): void
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling()->login()->loginNami()->withOwncloudUser('badenpowell', 'secret');
|
|
||||||
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'test', 'password' => 'test', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->name('lokaler Server')
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$this->patch(route('fileshare.update', ['fileshare' => $connection]), [
|
|
||||||
'name' => 'Lala',
|
|
||||||
'type' => OwncloudConnection::class,
|
|
||||||
'config' => [
|
|
||||||
'user' => 'badenpowell',
|
|
||||||
'password' => 'secret',
|
|
||||||
'base_url' => env('TEST_OWNCLOUD_DOMAIN'),
|
|
||||||
]
|
|
||||||
])->assertOk();
|
|
||||||
|
|
||||||
$connection = Fileshare::firstOrFail();
|
|
||||||
$this->assertEquals('badenpowell', $connection->type->user);
|
|
||||||
$this->assertEquals('secret', $connection->type->password);
|
|
||||||
$this->assertEquals(env('TEST_OWNCLOUD_DOMAIN'), $connection->type->baseUrl);
|
|
||||||
$this->assertEquals('Lala', $connection->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItChecksConnection(): void
|
|
||||||
{
|
|
||||||
$this->login()->loginNami()->withOwncloudUser('test', 'test');
|
|
||||||
|
|
||||||
$connection = Fileshare::factory()
|
|
||||||
->type(OwncloudConnection::from(['user' => 'test', 'password' => 'test', 'base_url' => env('TEST_OWNCLOUD_DOMAIN')]))
|
|
||||||
->name('lokaler Server')
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$this->patchJson(route('fileshare.update', ['fileshare' => $connection]), [
|
|
||||||
'name' => 'Lala',
|
|
||||||
'type' => OwncloudConnection::class,
|
|
||||||
'config' => [
|
|
||||||
'user' => 'badenpowell',
|
|
||||||
'password' => 'secret',
|
|
||||||
'base_url' => env('TEST_OWNCLOUD_DOMAIN'),
|
|
||||||
]
|
|
||||||
])->assertJsonValidationErrors(['type' => 'Verbindung fehlgeschlagen']);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
version: '3'
|
|
||||||
|
|
||||||
services:
|
|
||||||
owncloud:
|
|
||||||
image: owncloud/server:10.10.0
|
|
||||||
ports:
|
|
||||||
- 5566:8080
|
|
||||||
depends_on:
|
|
||||||
- mariadb
|
|
||||||
environment:
|
|
||||||
- OWNCLOUD_DOMAIN=http://localhost:5566
|
|
||||||
- OWNCLOUD_TRUSTED_DOMAINS=
|
|
||||||
- OWNCLOUD_DB_TYPE=mysql
|
|
||||||
- OWNCLOUD_DB_NAME=owncloud
|
|
||||||
- OWNCLOUD_DB_USERNAME=owncloud
|
|
||||||
- OWNCLOUD_DB_PASSWORD=owncloud
|
|
||||||
- OWNCLOUD_DB_HOST=mariadb
|
|
||||||
- OWNCLOUD_ADMIN_USERNAME=admin
|
|
||||||
- OWNCLOUD_ADMIN_PASSWORD=admin
|
|
||||||
- OWNCLOUD_MYSQL_UTF8MB4=true
|
|
||||||
- OWNCLOUD_REDIS_ENABLED=false
|
|
||||||
- OWNCLOUD_REDIS_HOST=false
|
|
||||||
healthcheck:
|
|
||||||
test: ['CMD', '/usr/bin/healthcheck']
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 5
|
|
||||||
volumes:
|
|
||||||
- ./oc_tmp/files:/mnt/data
|
|
||||||
- ./08-skeleton.sh:/etc/entrypoint.d/08-skeleton.sh
|
|
||||||
|
|
||||||
mariadb:
|
|
||||||
image: mariadb:10.11
|
|
||||||
environment:
|
|
||||||
- MYSQL_ROOT_PASSWORD=owncloud
|
|
||||||
- MYSQL_USER=owncloud
|
|
||||||
- MYSQL_PASSWORD=owncloud
|
|
||||||
- MYSQL_DATABASE=owncloud
|
|
||||||
- MARIADB_AUTO_UPGRADE=1
|
|
||||||
command: ['--max-allowed-packet=128M', '--innodb-log-file-size=64M']
|
|
||||||
healthcheck:
|
|
||||||
test: ['CMD', 'mysqladmin', 'ping', '-u', 'root', '--password=owncloud']
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
volumes:
|
|
||||||
- ./oc_tmp/db:/var/lib/mysql
|
|
|
@ -1,85 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests;
|
|
||||||
|
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|
||||||
use Illuminate\Http\Client\PendingRequest;
|
|
||||||
use Illuminate\Support\Facades\Http;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use League\Flysystem\DirectoryAttributes;
|
|
||||||
use League\Flysystem\Filesystem;
|
|
||||||
use League\Flysystem\WebDAV\WebDAVAdapter;
|
|
||||||
use Sabre\DAV\Client;
|
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
abstract class FileshareTestCase extends TestCase
|
|
||||||
{
|
|
||||||
use DatabaseTransactions;
|
|
||||||
|
|
||||||
protected string $adminUser = 'admin';
|
|
||||||
protected string $adminPassword = 'admin';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array<string, string>
|
|
||||||
*/
|
|
||||||
protected array $passwords = [];
|
|
||||||
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
foreach ($this->http()->get('/ocs/v1.php/cloud/users?format=json')->json('ocs.data.users') as $user) {
|
|
||||||
if ($user === $this->adminUser) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$this->http()->delete('/ocs/v1.php/cloud/users/' . $user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function withOwncloudUser(string $username, string $password): self
|
|
||||||
{
|
|
||||||
$this->passwords[$username] = $password;
|
|
||||||
$this->http()->asForm()->post('/ocs/v1.php/cloud/users?format=json', ['password' => $password, 'userid' => $username]);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function http(): PendingRequest
|
|
||||||
{
|
|
||||||
return Http::withOptions(['base_uri' => env('TEST_OWNCLOUD_DOMAIN')])->withBasicAuth($this->adminUser, $this->adminPassword)->acceptJson();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<int, string> $dirs
|
|
||||||
*/
|
|
||||||
protected function withDirs(string $username, array $dirs): self
|
|
||||||
{
|
|
||||||
$adapter = $this->adapter($username);
|
|
||||||
|
|
||||||
foreach ($adapter->directories('/') as $directory) {
|
|
||||||
$adapter->deleteDirectory($directory);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($adapter->files('/') as $file) {
|
|
||||||
$adapter->delete($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($dirs as $dir) {
|
|
||||||
$adapter->makeDirectory($dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function adapter(string $username): FilesystemAdapter
|
|
||||||
{
|
|
||||||
$adapter = new WebDAVAdapter(new Client([
|
|
||||||
'baseUri' => env('TEST_OWNCLOUD_DOMAIN') . '/remote.php/dav/files/' . $username,
|
|
||||||
'userName' => $username,
|
|
||||||
'password' => $this->passwords[$username],
|
|
||||||
]), '/remote.php/dav/files/' . $username);
|
|
||||||
|
|
||||||
return new FilesystemAdapter(new Filesystem($adapter), $adapter);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,6 +22,11 @@ trait TestsInertia
|
||||||
$this->assertInertiaDeepNest($bindings, $viewData);
|
$this->assertInertiaDeepNest($bindings, $viewData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function assertComponent(string $component, TestResponse $response): void
|
||||||
|
{
|
||||||
|
PHPUnit::assertEquals($component, $response->viewData('page')['component']);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $should
|
* @param mixed $should
|
||||||
* @param mixed $is
|
* @param mixed $is
|
||||||
|
|
|
@ -34,7 +34,7 @@ abstract class TestCase extends BaseTestCase
|
||||||
$this->initInertiaTestcase();
|
$this->initInertiaTestcase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loginNami(int $mglnr = 12345, string $password = 'password', int|Group $groupId = 55): static
|
public function loginNami(int $mglnr = 12345, string $password = 'password', int|Group $groupId = 55): self
|
||||||
{
|
{
|
||||||
Auth::success($mglnr, $password);
|
Auth::success($mglnr, $password);
|
||||||
$group = is_int($groupId)
|
$group = is_int($groupId)
|
||||||
|
@ -57,7 +57,7 @@ abstract class TestCase extends BaseTestCase
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function login(): static
|
public function login(): self
|
||||||
{
|
{
|
||||||
$this->be($user = User::factory()->create());
|
$this->be($user = User::factory()->create());
|
||||||
$this->me = $user;
|
$this->me = $user;
|
||||||
|
@ -93,8 +93,7 @@ abstract class TestCase extends BaseTestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template M of object
|
* @param <class-string> $class
|
||||||
* @param class-string<M> $class
|
|
||||||
*/
|
*/
|
||||||
public function stubIo(string $class, callable $mocker): self
|
public function stubIo(string $class, callable $mocker): self
|
||||||
{
|
{
|
||||||
|
@ -134,13 +133,6 @@ abstract class TestCase extends BaseTestCase
|
||||||
return $this;
|
return $this;
|
||||||
});
|
});
|
||||||
|
|
||||||
TestResponse::macro('assertComponent', function (string $component) {
|
|
||||||
/** @var TestResponse */
|
|
||||||
$response = $this;
|
|
||||||
Assert::assertEquals($component, data_get($response->viewData('page'), 'component'));
|
|
||||||
return $this;
|
|
||||||
});
|
|
||||||
|
|
||||||
TestResponse::macro('assertPdfPageCount', function (int $count) {
|
TestResponse::macro('assertPdfPageCount', function (int $count) {
|
||||||
/** @var TestResponse */
|
/** @var TestResponse */
|
||||||
$response = $this;
|
$response = $this;
|
||||||
|
|
|
@ -10,7 +10,6 @@ use Symfony\Component\HttpFoundation\File\File;
|
||||||
* @method self assertPdfPageCount(int $count)
|
* @method self assertPdfPageCount(int $count)
|
||||||
* @method self assertPdfName(string $filename)
|
* @method self assertPdfName(string $filename)
|
||||||
* @method self assertHasJsonPath(string $path)
|
* @method self assertHasJsonPath(string $path)
|
||||||
* @method self assertComponent(string $component)
|
|
||||||
* @method File getFile()
|
* @method File getFile()
|
||||||
*/
|
*/
|
||||||
class TestResponse
|
class TestResponse
|
||||||
|
|
Loading…
Reference in New Issue