This commit is contained in:
holger.trampe 2021-05-21 16:55:38 +02:00
parent 514b89365d
commit e78a8abd1e
18 changed files with 491 additions and 23 deletions

View File

@ -6,3 +6,5 @@ module.exports = {
'no-console': 'off',
},
};

View File

@ -1,5 +1,8 @@
<?php
return [
'resources' => [
'agency' => ['url' => '/agencys'],
],
'routes' => [
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
]

View File

@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
namespace OCA\Agency\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Controller;
use OCA\Agency\Service\AgencyService;
class AgencyController extends Controller {
private $service;
private $Id;
use Errors;
public function __construct(string $AppName, IRequest $request,
AgencyService $service){
parent::__construct($AppName, $request);
$this->service = $service;
}
/**
* @NoAdminRequired
*/
public function index() {
return new DataResponse($this->service->findAll($this->Id));
}
/**
* @NoAdminRequired
*
* @param int $id
*/
public function show(int $id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->find($id);
});
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*
* @param string $title
* @param string $content
*/
public function create(string $name) {
return $this->service->create($name);
}
/**
* @NoAdminRequired
*
* @param int $id
* @param string $title
*/
public function update(int $id, string $name) {
return $this->handleNotFound(function () use ($id, $name) {
return $this->service->update($id, $name);
});
}
/**
* @NoAdminRequired
*
* @param int $id
*/
public function destroy(int $id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->delete($id);
});
}
}

24
lib/Controller/Errors.php Normal file
View File

@ -0,0 +1,24 @@
<?php
namespace OCA\Agency\Controller;
use Closure;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCA\Agency\Service\NotFoundException;
trait Errors {
protected function handleNotFound (Closure $callback) {
try {
return new DataResponse($callback());
} catch(NotFoundException $e) {
$message = ['message' => $e->getMessage()];
return new DataResponse($message, Http::STATUS_NOT_FOUND);
}
}
}

View File

@ -8,19 +8,24 @@ use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Controller;
use OCP\Util;
use OCA\Agency\Service\AgencyService;
class PageController extends Controller {
protected $appName;
private $service;
public function __construct($appName, IRequest $request) {
public function __construct($appName, IRequest $request, AgencyService $service) {
parent::__construct($appName, $request);
$this->appName = $appName;
$this->service = $service;
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function index() {
Util::addScript($this->appName, 'agency-main');
Util::addStyle($this->appName, 'icons');

22
lib/Db/Agency.php Normal file
View File

@ -0,0 +1,22 @@
<?php
namespace OCA\Agency\Db;
use JsonSerializable;
use OCP\AppFramework\Db\Entity;
class Agency extends Entity implements JsonSerializable {
protected $name;
public function __construct() {
$this->addType('id','integer');
}
public function jsonSerialize() {
return [
'id' => $this->id,
'name' => $this->title,
];
}
}

25
lib/Db/AgencyMapper.php Normal file
View File

@ -0,0 +1,25 @@
<?php
namespace OCA\Agency\Db;
use OCP\IDBConnection;
use OCP\AppFramework\Db\QBMapper;
class AgencyMapper extends QBMapper {
public function __construct(IDBConnection $db) {
parent::__construct($db, 'agencys', Note::class);
}
public function find(int $id) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where(
$qb->expr()->eq('id', $qb->createNamedParameter($id))
);
return $this->findEntity($qb);
}
}

View File

@ -0,0 +1,88 @@
<?php
namespace OCA\Agency\Migration;
use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\SimpleMigrationStep;
use OCP\Migration\IOutput;
class Version000001Date20210521125400 extends SimpleMigrationStep {
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if (!$schema->hasTable('agencys')) {
$table = $schema->createTable('agencys');
$table->addColumn('id', 'integer', [
'autoincrement' => true,
'notnull' => true,
]);
$table->addColumn('name', 'string', [
'notnull' => true,
'length' => 200
]);
$table->addColumn('inhaber', 'string', [
'notnull' => false,
'length' => 200
]);
$table->addColumn('street', 'string', [
'notnull' => false,
'length' => 200
]);
$table->addColumn('city', 'string', [
'notnull' => false,
'length' => 200
]);
$table->addColumn('plz', 'string', [
'notnull' => false,
'length' => 5
]);
$table->addColumn('agency_email', 'string', [
'notnull' => false,
'length' => 200
]);
$table->addColumn('phone', 'string', [
'notnull' => false,
'length' => 200
]);
$table->setPrimaryKey(['id']);
}
if (!$schema->hasTable('agency_user')) {
$table = $schema->createTable('agency_user');
$table->addColumn('id', 'integer', [
'autoincrement' => true,
'notnull' => true,
]);
$table->rColumn('agency', 'integer', [
'notnull' => true,
'length' => 64
]);
$table->rColumn('user', 'integer', [
'notnull' => true,
'length' => 64
]);
$table->setPrimaryKey(['id']);
}
return $schema;
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace OCA\Agency\Service;
use Exception;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCA\Agency\Db\Agency;
use OCA\Agency\Db\AgencyMapper;
class AgencyService {
private $mapper;
public function __construct(AgencyMapper $mapper){
$this->mapper = $mapper;
}
private function handleException ($e) {
if ($e instanceof DoesNotExistException ||
$e instanceof MultipleObjectsReturnedException) {
throw new NotFoundException($e->getMessage());
} else {
throw $e;
}
}
public function find(int $id) {
try {
return $this->mapper->find($id);
} catch(Exception $e) {
$this->handleException($e);
}
}
public function create(string $name) {
$agency = new Agency();
$agency->setName($name);
return $this->mapper->insert($agency);
}
}

View File

@ -0,0 +1,4 @@
<?php
namespace OCA\Agency\Service;
class NotFoundException extends ServiceException {}

View File

@ -0,0 +1,6 @@
<?php
namespace OCA\Agency\Service;
use Exception;
class ServiceException extends Exception {}

132
package-lock.json generated
View File

@ -1096,6 +1096,29 @@
"to-fast-properties": "2.0.0"
}
},
"@braid/vue-formulate": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@braid/vue-formulate/-/vue-formulate-2.5.2.tgz",
"integrity": "sha512-0LWKp3Rjq2a+WwA4y49VaXqQOVClJGy6mmdivxJJyRvNB0aUcTOKOINLumeU/XHf7/c0HNhtbZih2vs6hMDyvQ==",
"requires": {
"@braid/vue-formulate-i18n": "1.16.0",
"is-plain-object": "3.0.1",
"is-url": "1.2.4",
"nanoid": "2.1.11"
},
"dependencies": {
"is-plain-object": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
"integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g=="
}
}
},
"@braid/vue-formulate-i18n": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/@braid/vue-formulate-i18n/-/vue-formulate-i18n-1.16.0.tgz",
"integrity": "sha512-CuX1kN7bWg4ukynnTS3LGsmPKrUvS2Wh75zKatIe+nHQQy0gSvfmggQsCz4QZey7Ois+pGYmOIgrE1SvX+zQTw=="
},
"@nextcloud/auth": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@nextcloud/auth/-/auth-1.3.0.tgz",
@ -1324,6 +1347,61 @@
"fastq": "1.11.0"
}
},
"@nuxt/opencollective": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.3.2.tgz",
"integrity": "sha512-XG7rUdXG9fcafu9KTDIYjJSkRO38EwjlKYIb5TQ/0WDbiTUTtUtgncMscKOYzfsY86kGs05pAuMOR+3Fi0aN3A==",
"requires": {
"chalk": "4.1.1",
"consola": "2.15.3",
"node-fetch": "2.6.1"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "2.0.1"
}
},
"chalk": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
"requires": {
"ansi-styles": "4.3.0",
"supports-color": "7.2.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"requires": {
"has-flag": "4.0.0"
}
}
}
},
"@stylelint/postcss-css-in-js": {
"version": "0.37.2",
"resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz",
@ -2181,6 +2259,30 @@
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==",
"dev": true
},
"bootstrap": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.1.tgz",
"integrity": "sha512-Fl79+wsLOZKoiU345KeEaWD0ik8WKRI5zm0YSPj2oF1Qr+BO7z0fco6GbUtqjoG1h4VI89PeKJnMsMMVQdKKTw=="
},
"bootstrap-vue": {
"version": "2.21.2",
"resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.21.2.tgz",
"integrity": "sha512-0Exe+4MZysqhZNXIKf4TzkvXaupxh9EHsoCRez0o5Dc0J7rlafayOEwql63qXv74CgZO8E4U8ugRNJko1vMvNw==",
"requires": {
"@nuxt/opencollective": "0.3.2",
"bootstrap": "4.6.0",
"popper.js": "1.16.1",
"portal-vue": "2.1.7",
"vue-functional-data-merge": "3.1.0"
},
"dependencies": {
"bootstrap": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz",
"integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw=="
}
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -2859,6 +2961,11 @@
"proto-list": "1.2.4"
}
},
"consola": {
"version": "2.15.3",
"resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz",
"integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw=="
},
"console-browserify": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
@ -5630,6 +5737,11 @@
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"dev": true
},
"is-url": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
},
"is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
@ -6436,6 +6548,11 @@
"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
"dev": true
},
"nanoid": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
},
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@ -6472,6 +6589,11 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"node-gettext": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/node-gettext/-/node-gettext-3.0.0.tgz",
@ -7184,6 +7306,11 @@
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
},
"portal-vue": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/portal-vue/-/portal-vue-2.1.7.tgz",
"integrity": "sha512-+yCno2oB3xA7irTt0EU5Ezw22L2J51uKAacE/6hMPMoO/mx3h4rXFkkBkT4GFsMDv/vEe8TNKC3ujJJ0PTwb6g=="
},
"posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@ -9910,6 +10037,11 @@
}
}
},
"vue-functional-data-merge": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz",
"integrity": "sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA=="
},
"vue-hot-reload-api": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",

View File

@ -15,9 +15,14 @@
"stylelint:fix": "stylelint src --fix"
},
"dependencies": {
"@braid/vue-formulate": "^2.5.2",
"@braid/vue-formulate-i18n": "^1.16.0",
"@nextcloud/l10n": "^1.4.1",
"@nextcloud/router": "^2.0.0",
"@nextcloud/vue": "^3.7.0",
"axios": "^0.21.1",
"bootstrap": "^5.0.1",
"bootstrap-vue": "^2.21.2",
"vue": "^2.6.12",
"vue-router": "^3.5.1"
},

View File

@ -2,8 +2,8 @@
<AppNavigation>
<template #list>
<AppNavigationItem to="/"
title="Übersicht"
icon="icon-category-dashboard" />
title="Agenturdaten"
icon="icon-category-customization" />
</template>
</AppNavigation>
</template>

View File

@ -2,8 +2,20 @@ import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
import Routes from './router/routes'
import VueFormulate from '@braid/vue-formulate'
import { de } from '@braid/vue-formulate-i18n'
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
Vue.use(VueRouter)
Vue.use(VueFormulate, {
plugins: [de],
locale: 'de',
})
Vue.use(BootstrapVue)
Vue.use(IconsPlugin)
Vue.prototype.$hostname = 'http://localhost:8080'
const router = new VueRouter({
routes: Routes,

View File

@ -1,9 +1,9 @@
import Dashboard from '../views/Dashboard'
import AgencyData from '../views/AgencyData'
export default [
{
path: '/',
name: 'dashboard',
component: Dashboard,
name: 'agencydata',
component: AgencyData,
},
]

34
src/views/AgencyData.vue Normal file
View File

@ -0,0 +1,34 @@
<template>
<Content app-name="AgencyData">
<FormulateForm
@submit="submitHandler">
<FormulateInput name="name"
type="text" />
<FormulateInput
type="submit"
label="Aktualisieren" />
</FormulateForm>
</Content>
</template>
<script>
import Content from '@nextcloud/vue/dist/Components/Content'
import { generateUrl } from '@nextcloud/router'
const axios = require('axios').default
export default ({
name: 'AgencyData',
components: {
Content,
},
data() {
return {
}
},
methods: {
async submitHandler(data) {
const response = await axios.post(generateUrl('/apps/agency/agencys'), data)
console.log(response)
},
},
})
</script>

View File

@ -1,15 +0,0 @@
<template>
<Content app-name="Dashboard">
<h1>Agenturverwaltung</h1>
</Content>
</template>
<script>
import Content from '@nextcloud/vue/dist/Components/Content'
export default ({
name: 'Dashboard',
components: {
Content,
},
})
</script>