From dde7669e37f9aa1ea8d9d8ea4fbf4a302f0c1da4 Mon Sep 17 00:00:00 2001 From: Remko Date: Fri, 20 Sep 2024 14:32:16 +0200 Subject: [PATCH 001/155] Updated mian.css --- css/main.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/css/main.css b/css/main.css index 19ef91a..798b07a 100755 --- a/css/main.css +++ b/css/main.css @@ -23,6 +23,8 @@ z-index: 1000; background-color: var(--color-main-background); border-bottom: 1px solid var(--color-border); + display: flex; + align-items: center; } .searchField { From 8bf78d85c212d2be84d2d007d815ea43073471c0 Mon Sep 17 00:00:00 2001 From: Remko Date: Tue, 24 Sep 2024 10:15:40 +0200 Subject: [PATCH 002/155] WIP Sources --- css/main.css | 12 +++- docker-compose.yml | 1 + src/modals/Source/EditSource.vue | 89 +++++++++++++++++++----------- src/store/modules/navigation.js | 2 +- src/store/modules/source.js | 4 +- src/views/Source/SourceDetails.vue | 2 +- src/views/Source/SourcesIndex.vue | 2 +- 7 files changed, 73 insertions(+), 39 deletions(-) diff --git a/css/main.css b/css/main.css index 798b07a..754ed28 100644 --- a/css/main.css +++ b/css/main.css @@ -5,7 +5,6 @@ } /* Pages */ - .pageHeader { margin-block-start: var(--app-navigation-padding); margin-inline-start: calc( @@ -16,7 +15,6 @@ } /* Lists */ - .listHeader { position: sticky; top: 0; @@ -39,6 +37,10 @@ } /* Detail pages */ +.detailHeader { + display: flex; + justify-content: space-between; +} .detailContainer { margin-block-start: var(--OC-margin-20); @@ -109,6 +111,11 @@ } /* Modals */ +.modalContent { + margin: var(--OC-margin-50); + text-align: center; +} + .form-group > * { margin-block-end: 10px; } @@ -129,7 +136,6 @@ } /* File drag and drop */ - .filesListDragDropNotice { width: 100%; min-height: 113px; diff --git a/docker-compose.yml b/docker-compose.yml index 74b9893..c9781ff 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,6 +31,7 @@ services: - nextcloud:/var/www/html:rw - ./custom-apps:/var/www/html/custom_apps - .:/var/www/html/custom_apps/openconnector + environment: - MYSQL_PASSWORD='!ChangeMe!' - MYSQL_DATABASE=nextcloud diff --git a/src/modals/Source/EditSource.vue b/src/modals/Source/EditSource.vue index 8730159..34d8a17 100644 --- a/src/modals/Source/EditSource.vue +++ b/src/modals/Source/EditSource.vue @@ -3,9 +3,12 @@ import { sourceStore, navigationStore } from '../../store/store.js' Ververs - + @@ -48,20 +48,20 @@ import { synchronizationStore, navigationStore, searchStore } from '../../store/ - + /* Styles remain the same */ - \ No newline at end of file + From a09d9ca04f71566ab54c3383ca3512bcaea707ae Mon Sep 17 00:00:00 2001 From: Thijn Date: Tue, 24 Sep 2024 15:49:42 +0200 Subject: [PATCH 005/155] attempted to fix the styling --- css/main.css | 7 ++- .../Synchronization/EditSynchronization.vue | 48 +++++++++++-------- .../Synchronization/SynchronizationsIndex.vue | 2 - 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/css/main.css b/css/main.css index 754ed28..f31bef5 100644 --- a/css/main.css +++ b/css/main.css @@ -1,6 +1,8 @@ :root { --OC-margin-10: 10px; --OC-margin-20: 20px; + --OC-margin-30: 30px; + --OC-margin-40: 40px; --OC-margin-50: 50px; } @@ -112,9 +114,12 @@ /* Modals */ .modalContent { - margin: var(--OC-margin-50); + margin: var(--OC-margin-10); text-align: center; } +.modalContent > *:not(:last-child) { + margin-block-end: 1rem; +} .form-group > * { margin-block-end: 10px; diff --git a/src/modals/Synchronization/EditSynchronization.vue b/src/modals/Synchronization/EditSynchronization.vue index 165e463..c5a251e 100644 --- a/src/modals/Synchronization/EditSynchronization.vue +++ b/src/modals/Synchronization/EditSynchronization.vue @@ -3,9 +3,13 @@ import { synchronizationStore, navigationStore } from '../../store/store.js' From 9ec6a69bc1024ff9162771e8a1f4510e304391eb Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Fri, 27 Sep 2024 00:16:41 +0200 Subject: [PATCH 011/155] First checks on the call service --- lib/Controller/SourcesController.php | 24 +- lib/Db/CallLog.php | 78 +++++ lib/Db/CallLogMapper.php | 72 ++++ lib/Db/Source.php | 340 ------------------- lib/Migration/Version0Date20240926235025.php | 85 +++++ lib/Service/CallService.php | 199 +++++++---- src/modals/Source/EditSource.vue | 11 +- src/modals/TestSource/TestSource.vue | 26 +- src/store/modules/source.js | 36 +- src/views/Source/SourceDetails.vue | 4 +- 10 files changed, 421 insertions(+), 454 deletions(-) create mode 100644 lib/Db/CallLog.php create mode 100644 lib/Db/CallLogMapper.php create mode 100644 lib/Migration/Version0Date20240926235025.php diff --git a/lib/Controller/SourcesController.php b/lib/Controller/SourcesController.php index 21f710d..3f675db 100644 --- a/lib/Controller/SourcesController.php +++ b/lib/Controller/SourcesController.php @@ -188,7 +188,7 @@ public function test(CallService $callService,int $id): JSONResponse { // get the source try { - $source = JSONResponse($this->sourceMapper->find(id: (int) $id)); + $source = $this->sourceMapper->find(id: (int) $id); } catch (DoesNotExistException $exception) { return new JSONResponse(data: ['error' => 'Not Found'], statusCode: 404); } @@ -210,7 +210,7 @@ public function test(CallService $callService,int $id): JSONResponse } // Set method, default to POST if not provided - $method = $requestData['method'] ?? 'POST'; + $method = $requestData['method'] ?? 'GET'; // Set endpoint $endpoint = $requestData['endpoint'] ?? ''; @@ -236,21 +236,11 @@ public function test(CallService $callService,int $id): JSONResponse } // fire the call - $response = $callService->call($source, $data); - - // Map it back to json - $responseObject = [ - 'requestUrl' => $response->getEffectiveUri()->__toString(), - 'requestMethod' => $response->getRequest()->getMethod(), - 'statusCode' => $response->getStatusCode(), - 'statusMessage' => $response->getReasonPhrase(), - 'responseTime' => $response->getTransferTime(), - 'size' => $response->getBody()->getSize(), - 'remoteIp' => $response->getHeaderLine('X-Real-IP') ?: $response->getHeaderLine('X-Forwarded-For') ?: null, - 'headers' => $response->getHeaders(), - 'body' => $response->getBody()->getContents(), - ]; + + $time_start = microtime(true); + $callLog = $callService->call($source, $endpoint, $method, $config); + $time_end = microtime(true); - return new JSONResponse($responseObject); + return new JSONResponse($callLog->jsonSerialize()); } } \ No newline at end of file diff --git a/lib/Db/CallLog.php b/lib/Db/CallLog.php new file mode 100644 index 0000000..2557c27 --- /dev/null +++ b/lib/Db/CallLog.php @@ -0,0 +1,78 @@ +addType('statusCode', 'integer'); + $this->addType('statusMessage', 'string'); + $this->addType('request', 'json'); + $this->addType('response', 'json'); + $this->addType('sourceId', 'integer'); + $this->addType('actionId', 'integer'); + $this->addType('synchronizationId', 'integer'); + $this->addType('createdAt', 'datetime'); + $this->addType('updatedAt', 'datetime'); + } + + public function getJsonFields(): array + { + return array_keys( + array_filter($this->getFieldTypes(), function ($field) { + return $field === 'json'; + }) + ); + } + + public function hydrate(array $object): self + { + $jsonFields = $this->getJsonFields(); + + foreach($object as $key => $value) { + if (in_array($key, $jsonFields) === true && $value === []) { + $value = []; + } + + $method = 'set'.ucfirst($key); + + try { + $this->$method($value); + } catch (\Exception $exception) { + // Handle or log the exception if needed + } + } + + return $this; + } + + public function jsonSerialize(): array + { + return [ + 'id' => $this->id, + 'statusCode' => $this->statusCode, + 'statusMessage' => $this->statusMessage, + 'request' => $this->request, + 'response' => $this->response, + 'sourceId' => $this->sourceId, + 'actionId' => $this->actionId, + 'synchronizationId' => $this->synchronizationId, + 'createdAt' => $this->createdAt, + 'updatedAt' => $this->updatedAt, + ]; + } +} \ No newline at end of file diff --git a/lib/Db/CallLogMapper.php b/lib/Db/CallLogMapper.php new file mode 100644 index 0000000..0e57ffd --- /dev/null +++ b/lib/Db/CallLogMapper.php @@ -0,0 +1,72 @@ +db->getQueryBuilder(); + + $qb->select('*') + ->from('openconnector_call_logs') + ->where( + $qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)) + ); + + return $this->findEntity($qb); + } + + public function findAll(?int $limit = null, ?int $offset = null, ?array $filters = [], ?array $searchConditions = [], ?array $searchParams = []): array + { + $qb = $this->db->getQueryBuilder(); + + $qb->select('*') + ->from('openconnector_call_logs') + ->setMaxResults($limit) + ->setFirstResult($offset); + + foreach($filters as $filter => $value) { + if ($value === 'IS NOT NULL') { + $qb->andWhere($qb->expr()->isNotNull($filter)); + } elseif ($value === 'IS NULL') { + $qb->andWhere($qb->expr()->isNull($filter)); + } else { + $qb->andWhere($qb->expr()->eq($filter, $qb->createNamedParameter($value))); + } + } + + if (!empty($searchConditions)) { + $qb->andWhere('(' . implode(' OR ', $searchConditions) . ')'); + foreach ($searchParams as $param => $value) { + $qb->setParameter($param, $value); + } + } + + return $this->findEntities($qb); + } + + public function createFromArray(array $object): CallLog + { + $callLog = new CallLog(); + $callLog->hydrate($object); + return $this->insert($callLog); + } + + public function updateFromArray(int $id, array $object): CallLog + { + $callLog = $this->find($id); + $callLog->hydrate($object); + + return $this->update($callLog); + } +} \ No newline at end of file diff --git a/lib/Db/Source.php b/lib/Db/Source.php index 1eeb698..22182d0 100644 --- a/lib/Db/Source.php +++ b/lib/Db/Source.php @@ -150,344 +150,4 @@ public function jsonSerialize(): array 'test' => $this->test ]; } - - public function getName(): ?string - { - return $this->name; - } - - public function setName(?string $name): void - { - $this->name = $name; - } - - public function getDescription(): ?string - { - return $this->description; - } - - public function setDescription(?string $description): void - { - $this->description = $description; - } - - public function getReference(): ?string - { - return $this->reference; - } - - public function setReference(?string $reference): void - { - $this->reference = $reference; - } - - public function getVersion(): ?string - { - return $this->version; - } - - public function setVersion(?string $version): void - { - $this->version = $version; - } - - public function getLocation(): ?string - { - return $this->location; - } - - public function setLocation(?string $location): void - { - $this->location = $location; - } - - public function getIsEnabled(): ?bool - { - return $this->isEnabled; - } - - public function setIsEnabled(?bool $isEnabled): void - { - $this->isEnabled = $isEnabled; - } - - public function getType(): ?string - { - return $this->type; - } - - public function setType(?string $type): void - { - $this->type = $type; - } - - public function getAuthorizationHeader(): ?string - { - return $this->authorizationHeader; - } - - public function setAuthorizationHeader(?string $authorizationHeader): void - { - $this->authorizationHeader = $authorizationHeader; - } - - public function getAuth(): ?string - { - return $this->auth; - } - - public function setAuth(?string $auth): void - { - $this->auth = $auth; - } - - public function getAuthenticationConfig(): ?array - { - return $this->authenticationConfig; - } - - public function setAuthenticationConfig(?array $authenticationConfig): void - { - $this->authenticationConfig = $authenticationConfig; - } - - public function getAuthorizationPassthroughMethod(): ?string - { - return $this->authorizationPassthroughMethod; - } - - public function setAuthorizationPassthroughMethod(?string $authorizationPassthroughMethod): void - { - $this->authorizationPassthroughMethod = $authorizationPassthroughMethod; - } - - public function getLocale(): ?string - { - return $this->locale; - } - - public function setLocale(?string $locale): void - { - $this->locale = $locale; - } - - public function getAccept(): ?string - { - return $this->accept; - } - - public function setAccept(?string $accept): void - { - $this->accept = $accept; - } - - public function getJwt(): ?string - { - return $this->jwt; - } - - public function setJwt(?string $jwt): void - { - $this->jwt = $jwt; - } - - public function getJwtId(): ?string - { - return $this->jwtId; - } - - public function setJwtId(?string $jwtId): void - { - $this->jwtId = $jwtId; - } - - public function getSecret(): ?string - { - return $this->secret; - } - - public function setSecret(?string $secret): void - { - $this->secret = $secret; - } - - public function getUsername(): ?string - { - return $this->username; - } - - public function setUsername(?string $username): void - { - $this->username = $username; - } - - public function getPassword(): ?string - { - return $this->password; - } - - public function setPassword(?string $password): void - { - $this->password = $password; - } - - public function getApikey(): ?string - { - return $this->apikey; - } - - public function setApikey(?string $apikey): void - { - $this->apikey = $apikey; - } - - public function getDocumentation(): ?string - { - return $this->documentation; - } - - public function setDocumentation(?string $documentation): void - { - $this->documentation = $documentation; - } - - public function getLoggingConfig(): ?array - { - return $this->loggingConfig; - } - - public function setLoggingConfig(?array $loggingConfig): void - { - $this->loggingConfig = $loggingConfig; - } - - public function getOas(): ?string - { - return $this->oas; - } - - public function setOas(?string $oas): void - { - $this->oas = $oas; - } - - public function getPaths(): ?array - { - return $this->paths; - } - - public function setPaths(?array $paths): void - { - $this->paths = $paths; - } - - public function getHeaders(): ?array - { - return $this->headers; - } - - public function setHeaders(?array $headers): void - { - $this->headers = $headers; - } - - public function getTranslationConfig(): ?array - { - return $this->translationConfig; - } - - public function setTranslationConfig(?array $translationConfig): void - { - $this->translationConfig = $translationConfig; - } - - public function getConfiguration(): ?array - { - return $this->configuration; - } - - public function setConfiguration(?array $configuration): void - { - $this->configuration = $configuration; - } - - public function getEndpointsConfig(): ?array - { - return $this->endpointsConfig; - } - - public function setEndpointsConfig(?array $endpointsConfig): void - { - $this->endpointsConfig = $endpointsConfig; - } - - public function getStatus(): ?string - { - return $this->status; - } - - public function setStatus(?string $status): void - { - $this->status = $status; - } - - public function getLastCall(): ?DateTime - { - return $this->lastCall; - } - - public function setLastCall(?DateTime $lastCall): void - { - $this->lastCall = $lastCall; - } - - public function getLastSync(): ?DateTime - { - return $this->lastSync; - } - - public function setLastSync(?DateTime $lastSync): void - { - $this->lastSync = $lastSync; - } - - public function getObjectCount(): ?int - { - return $this->objectCount; - } - - public function setObjectCount(?int $objectCount): void - { - $this->objectCount = $objectCount; - } - - public function getDateCreated(): ?DateTime - { - return $this->dateCreated; - } - - public function setDateCreated(?DateTime $dateCreated): void - { - $this->dateCreated = $dateCreated; - } - - public function getDateModified(): ?DateTime - { - return $this->dateModified; - } - - public function setDateModified(?DateTime $dateModified): void - { - $this->dateModified = $dateModified; - } - - public function getTest(): ?bool - { - return $this->test; - } - - public function setTest(?bool $test): void - { - $this->test = $test; - } } \ No newline at end of file diff --git a/lib/Migration/Version0Date20240926235025.php b/lib/Migration/Version0Date20240926235025.php new file mode 100644 index 0000000..e71cc8f --- /dev/null +++ b/lib/Migration/Version0Date20240926235025.php @@ -0,0 +1,85 @@ +hasTable('openconnector_call_logs')) { + $table = $schema->createTable('openconnector_call_logs'); + $table->addColumn('id', 'integer', [ + 'autoincrement' => true, + 'notnull' => true, + ]); + $table->addColumn('status_code', 'integer', [ + 'notnull' => false, + 'length' => 3 + ]); + $table->addColumn('status_message', 'string', [ + 'notnull' => false, + 'length' => 256 + ]); + $table->addColumn('request', 'json', [ + 'notnull' => false, + ]); + $table->addColumn('response', 'json', [ + 'notnull' => false, + ]); + $table->addColumn('source_id', 'integer', [ + 'notnull' => true, + ]); + $table->addColumn('action_id', 'integer', [ + 'notnull' => false, + ]); + $table->addColumn('synchronization_id', 'integer', [ + 'notnull' => false, + ]); + $table->addColumn('created_at', 'datetime', [ + 'notnull' => true, + 'default' => 'CURRENT_TIMESTAMP' + ]); + $table->addColumn('updated_at', 'datetime', [ + 'notnull' => true, + 'default' => 'CURRENT_TIMESTAMP' + ]); + + $table->setPrimaryKey(['id']); + $table->addIndex(['source_id'], 'openconnector_call_logs_source_id_index'); + $table->addIndex(['action_id'], 'openconnector_call_logs_action_id_index'); + $table->addIndex(['synchronization_id'], 'openconnector_call_logs_sync_id_index'); + $table->addIndex(['status_code'], 'openconnector_call_logs_status_code_index'); + } + + return $schema; + } +} \ No newline at end of file diff --git a/lib/Service/CallService.php b/lib/Service/CallService.php index 6d4357a..45386d5 100644 --- a/lib/Service/CallService.php +++ b/lib/Service/CallService.php @@ -12,113 +12,162 @@ use GuzzleHttp\Exception\ServerException; use GuzzleHttp\Promise\Promise; use GuzzleHttp\Psr7\Response; +use OCA\OpenConnector\Db\CallLog; +use OCA\OpenConnector\Db\CallLogMapper; class CallService { - /** - * The constructor sets al needed variables. - * - * @param AuthenticationService $authenticationService The authentication service - * @param MappingService $mappingService The mapping service - */ - public function __construct( - AuthenticationService $authenticationService, - MappingService $mappingService, - LoggerInterface $callLogger - ) { - $this->authenticationService = $authenticationService; - $this->mappingService = $mappingService; - $this->client = new Client([]); - - }//end __construct() /** + private $callLogMapper; /** - * Calls a source according to given configuration. - * - * @param Source $source The source to call. - * @param string $endpoint The endpoint on the source to call. - * @param string $method The method on which to call the source. - * @param array $config The additional configuration to call the source. - * @param bool $asynchronous Whether or not to call the source asynchronously. - * @param bool $createCertificates Whether or not to create certificates for this source. - * - * @throws Exception - * - * @return Response - */ - public function call( - Source $source, - string $endpoint = '', - string $method = 'GET', - array $config = [], - bool $asynchronous = false, - bool $createCertificates = true, - bool $overruleAuth = false - ): Response + * The constructor sets al needed variables. + * + * @param AuthenticationService $authenticationService The authentication service + * @param MappingService $mappingService The mapping service + */ + public function __construct(CallLogMapper $callLogMapper) { - $this->source = $source; + $this->client = new Client([]); + $this->callLogMapper = $callLogMapper; + } + + /** + * Calls a source according to given configuration. + * + * @param Source $source The source to call. + * @param string $endpoint The endpoint on the source to call. + * @param string $method The method on which to call the source. + * @param array $config The additional configuration to call the source. + * @param bool $asynchronous Whether or not to call the source asynchronously. + * @param bool $createCertificates Whether or not to create certificates for this source. + * + * @throws Exception + * + * @return Response + */ + public function call( + Source $source, + string $endpoint = '', + string $method = 'GET', + array $config = [], + bool $asynchronous = false, + bool $createCertificates = true, + bool $overruleAuth = false + ): CallLog + { + $this->source = $source; if ($this->source->getIsEnabled() === null || $this->source->getIsEnabled() === false) { - throw new HttpException('409', "This source is not enabled: {$this->source->getName()}"); - } + // Create and save the CallLog + $callLog = new CallLog(); + $callLog->setSourceId($this->source->getId()); + $callLog->setStatusCode(409); + $callLog->setStatusMessage("This source is not enabled"); + $callLog->setCreatedAt(new \DateTime()); + $callLog->setUpdatedAt(new \DateTime()); + + $this->callLogMapper->insert($callLog); + + return $callLog; + } - if (empty($this->source->getLocation()) === true) { - throw new HttpException('409', "This source has no location: {$this->source->getName()}"); - } + if (empty($this->source->getLocation()) === true) { + // Create and save the CallLog + $callLog = new CallLog(); + $callLog->setSourceId($this->source->getId()); + $callLog->setStatusCode(409); + $callLog->setStatusMessage("This source has no location"); + $callLog->setCreatedAt(new \DateTime()); + $callLog->setUpdatedAt(new \DateTime()); + + $this->callLogMapper->insert($callLog); + + return $callLog; + } // Check if the source has a configuration and merge it with the given config - if (empty($this->source->getConfiguration()) === false) { - $config = array_merge_recursive($config, $this->source->getConfiguration()); - } + if (empty($this->source->getConfiguration()) === false) { + $config = array_merge_recursive($config, $this->source->getConfiguration()); + } // Check if the config has a Content-Type header and overwrite it if it does if (isset($config['headers']['Content-Type']) === true) { - $overwriteContentType = $config['headers']['Content-Type']; - } + $overwriteContentType = $config['headers']['Content-Type']; + } // decapiitilized fall back for content-type - if (isset($config['headers']['content-type']) === true) { - $overwriteContentType = $config['headers']['content-type']; - } + if (isset($config['headers']['content-type']) === true) { + $overwriteContentType = $config['headers']['content-type']; + } // Make sure we do not have an array of accept headers but just one value - if (isset($config['headers']['accept']) === true && is_array($config['headers']['accept']) === true) { - $config['headers']['accept'] = $config['headers']['accept'][0]; - } + if (isset($config['headers']['accept']) === true && is_array($config['headers']['accept']) === true) { + $config['headers']['accept'] = $config['headers']['accept'][0]; + } // Check if the config has a headers array and create it if it doesn't - if (isset($config['headers']) === false) { - $config['headers'] = []; - } + if (isset($config['headers']) === false) { + $config['headers'] = []; + } + + // We want to suprres guzzle exceptions and return the response instead + $config['http_errors'] = false; // Set the URL to call and add an endpoint if needed $url = $this->source->getLocation().$endpoint; - // Set authentication if needed. @todo: create the authentication service - //$createCertificates && $this->getCertificate($config); - - // Set the request info array - $requestInfo = [ - 'url' => $url, - 'method' => $method, - ]; + // Set authentication if needed. @todo: create the authentication service + //$createCertificates && $this->getCertificate($config); // Let's log the call. $this->source->setLastCall(new \DateTime()); // @todo: save the source - // Let's make the call. + // Let's make the call. + $time_start = microtime(true); try { - if ($asynchronous === false) { - $response = $this->client->request($method, $url, $config); - } else { - return $this->client->requestAsync($method, $url, $config); - } - } catch (ClientException $e) { - // @todo: log the error + if ($asynchronous === false) { + $response = $this->client->request($method, $url, $config); + } else { + return $this->client->requestAsync($method, $url, $config); + } + } catch (GuzzleHttp\Exception\BadResponseException $e) { + $response = $e->getResponse(); } - return $response; + $time_end = microtime(true); + + // Let create the data array + $data = [ + 'request' => [ + 'url' => $url, + 'method' => $method, + ...$config + ], + 'response' => [ + 'statusCode' => $response->getStatusCode(), + 'statusMessage' => $response->getReasonPhrase(), + 'responseTime' => ( $time_end - $time_start ) * 1000, + 'size' => $response->getBody()->getSize(), + 'remoteIp' => $response->getHeaderLine('X-Real-IP') ?: $response->getHeaderLine('X-Forwarded-For') ?: null, + 'headers' => $response->getHeaders(), + 'body' => $response->getBody()->getContents(), + ] + ]; + + // Create and save the CallLog + $callLog = new CallLog(); + $callLog->setSourceId($this->source->getId()); + $callLog->setStatusCode($data['response']['statusCode']); + $callLog->setStatusMessage($data['response']['statusMessage']); + $callLog->setRequest($data['request']); + $callLog->setResponse($data['response']); + $callLog->setCreatedAt(new \DateTime()); + $callLog->setUpdatedAt(new \DateTime()); + + $this->callLogMapper->insert($callLog); + + return $callLog; } } diff --git a/src/modals/Source/EditSource.vue b/src/modals/Source/EditSource.vue index 34d8a17..5567c8b 100644 --- a/src/modals/Source/EditSource.vue +++ b/src/modals/Source/EditSource.vue @@ -30,19 +30,20 @@ import { sourceStore, navigationStore } from '../../store/store.js' + id="location" + label="location*" + :value.sync="sourceItem.location" /> Test connection + + +

The connection to the source was successful.

+
+ +

An error occurred while testing the connection: {{ sourceStore.sourceTest ? sourceStore.sourceTest.response.statusMessage : error }}

+
+ +
+

Status: {{ sourceStore.sourceTest.response.statusMessage }} ({{ sourceStore.sourceTest.response.statusCode }})

+

Response time: {{ sourceStore.sourceTest.response.responseTime }} (Milliseconds)

+

Size: {{ sourceStore.sourceTest.response.size }} (Bytes)

+

Remote IP: {{ sourceStore.sourceTest.response.remoteIp }}

+

Headers: {{ sourceStore.sourceTest.response.headers }}

+

Body: {{ sourceStore.sourceTest.response.body }}

+
@@ -58,6 +73,7 @@ import { NcLoadingIcon, NcTextField, NcTextArea, + NcNoteCard, } from '@nextcloud/vue' import Sync from 'vue-material-design-icons/Sync.vue' @@ -70,6 +86,7 @@ export default { NcLoadingIcon, NcTextField, NcTextArea, + NcNoteCard, }, data() { return { @@ -99,7 +116,7 @@ export default { { id: 'PUT', label: 'PUT' }, { id: 'DELETE', label: 'DELETE' }, ], - value: { id: 'POST', label: 'POST' }, + value: { id: 'GET', label: 'GET' }, }, } @@ -129,11 +146,12 @@ export default { // Close modal or show success message this.success = true this.loading = false - setTimeout(this.closeModal, 2000) + this.error = false } catch (error) { this.loading = false this.success = false this.error = error.message || 'Er is een fout opgetreden bij het opslaan van de bron' + sourceStore.setSourceTest(false) } }, }, diff --git a/src/store/modules/source.js b/src/store/modules/source.js index 3e7c4e2..ce5db64 100644 --- a/src/store/modules/source.js +++ b/src/store/modules/source.js @@ -6,6 +6,7 @@ export const useSourceStore = defineStore( 'source', { state: () => ({ sourceItem: false, + sourceTest: false, sourceList: [], }), actions: { @@ -13,6 +14,10 @@ export const useSourceStore = defineStore( this.sourceItem = sourceItem && new Source(sourceItem) console.log('Active source item set to ' + sourceItem) }, + setSourceTest(sourceTest) { + this.sourceTest = sourceTest + console.log('Source test set to ' + sourceTest) + }, setSourceList(sourceList) { this.sourceList = sourceList.map( (sourceItem) => new Source(sourceItem), @@ -81,29 +86,34 @@ export const useSourceStore = defineStore( }) }, // Test a source - testSource(sourceItem) { - if (!sourceItem) { + testSource(testSourceItem) { + if (!this.sourceItem) { throw new Error('No source item to test') } + if (!testSourceItem) { + throw new Error('No testobject to test') + } console.log('Testing source...') - const endpoint = `/index.php/apps/openconnector/api/source-test/${sourceItem.id}` + const endpoint = `/index.php/apps/openconnector/api/source-test/${this.sourceItem.id}` return fetch(endpoint, { - method: sourceItem.method, - body: sourceItem.body, + method: 'POST', headers: { - 'x-endpoint': sourceItem.endpoint, - 'x-method': sourceItem.method, + 'Content-Type': 'application/json', }, + body: JSON.stringify(testSourceItem), }) - .then((response) => { - console.log('response', response) - this.refreshSourceList() + .then((response) => response.json()) + .then((data) => { + this.setSourceTest(data) + console.log('Source tested') + // Refresh the source list + return this.refreshSourceList() }) .catch((err) => { - console.error('Error testing source:', err) + console.error('Error saving source:', err) throw err }) }, @@ -129,6 +139,10 @@ export const useSourceStore = defineStore( } }) + // remove the dateCreated and dateModified fields + delete sourceToSave.dateCreated + delete sourceToSave.dateModified + return fetch( endpoint, { diff --git a/src/views/Source/SourceDetails.vue b/src/views/Source/SourceDetails.vue index 6c2e10e..68ae1c6 100644 --- a/src/views/Source/SourceDetails.vue +++ b/src/views/Source/SourceDetails.vue @@ -39,8 +39,8 @@ import { sourceStore, navigationStore } from '../../store/store.js'
- URL: -

{{ sourceStore.sourceItem.url }}

+ location: +

{{ sourceStore.sourceItem.location }}

From 76f229da649f78def421763f033ecb19e1a463b8 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Fri, 27 Sep 2024 00:34:22 +0200 Subject: [PATCH 012/155] Add route for getting the logs for a source --- appinfo/routes.php | 1 + lib/Controller/SourcesController.php | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/appinfo/routes.php b/appinfo/routes.php index 9612115..ef695ea 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -10,5 +10,6 @@ 'routes' => [ ['name' => 'dashboard#page', 'url' => '/', 'verb' => 'GET'], ['name' => 'sources#test', 'url' => '/api/source-test/{id}', 'verb' => 'POST'], + ['name' => 'sources#logs', 'url' => '/api/sources/{id}/logs', 'verb' => 'GET'], ], ]; diff --git a/lib/Controller/SourcesController.php b/lib/Controller/SourcesController.php index 3f675db..74de6c5 100644 --- a/lib/Controller/SourcesController.php +++ b/lib/Controller/SourcesController.php @@ -164,6 +164,28 @@ public function destroy(int $id): JSONResponse return new JSONResponse([]); } + /** + * Retrieves call logs for a source + * + * This method returns all the call logs associated with a source based on its ID. + * + * @NoAdminRequired + * @NoCSRFRequired + * + * @param int $id The ID of the source to retrieve logs for + * @return JSONResponse A JSON response containing the call logs + */ + public function logs(int $id): JSONResponse + { + try { + $source = $this->sourceMapper->find($id); + $callLogs = $this->callLogMapper->findAll(null, null, ['source_id' => $source->getId()]); + return new JSONResponse($callLogs); + } catch (DoesNotExistException $e) { + return new JSONResponse(['error' => 'Source not found'], 404); + } + } + /** * Test a source * From d534a35b3d7950470aea87a03927d139c82eca2d Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Fri, 27 Sep 2024 11:43:12 +0200 Subject: [PATCH 013/155] Wip Jobs - Refactor - Service - Loging --- lib/Db/CallLog.php | 3 - lib/Db/Job.php | 78 +++++------------- lib/Db/JobLog.php | 75 +++++++++++++++++ lib/Db/JobLogMapper.php | 72 +++++++++++++++++ lib/Migration/Version0Date20240826193657.php | 69 +++++++++++----- lib/Migration/Version0Date20240926235025.php | 85 -------------------- src/modals/Job/EditJob.vue | 9 ++- 7 files changed, 218 insertions(+), 173 deletions(-) create mode 100644 lib/Db/JobLog.php create mode 100644 lib/Db/JobLogMapper.php delete mode 100644 lib/Migration/Version0Date20240926235025.php diff --git a/lib/Db/CallLog.php b/lib/Db/CallLog.php index 2557c27..25139a0 100644 --- a/lib/Db/CallLog.php +++ b/lib/Db/CallLog.php @@ -16,7 +16,6 @@ class CallLog extends Entity implements JsonSerializable protected ?int $actionId = null; protected ?int $synchronizationId = null; protected ?DateTime $createdAt = null; - protected ?DateTime $updatedAt = null; public function __construct() { $this->addType('statusCode', 'integer'); @@ -27,7 +26,6 @@ public function __construct() { $this->addType('actionId', 'integer'); $this->addType('synchronizationId', 'integer'); $this->addType('createdAt', 'datetime'); - $this->addType('updatedAt', 'datetime'); } public function getJsonFields(): array @@ -72,7 +70,6 @@ public function jsonSerialize(): array 'actionId' => $this->actionId, 'synchronizationId' => $this->synchronizationId, 'createdAt' => $this->createdAt, - 'updatedAt' => $this->updatedAt, ]; } } \ No newline at end of file diff --git a/lib/Db/Job.php b/lib/Db/Job.php index c75a7ba..3806672 100644 --- a/lib/Db/Job.php +++ b/lib/Db/Job.php @@ -10,54 +10,26 @@ class Job extends Entity implements JsonSerializable { protected ?string $name = null; protected ?string $description = null; - protected ?string $reference = null; - protected ?string $version = null; - protected ?string $crontab = null; + protected ?integer $interval = null; + protected ?bool $timeSensitive = true; + protected ?bool $allowParallelRuns = false; + protected ?bool $isEnabled = true; protected ?string $userId = null; - protected ?string $throws = null; protected ?array $data = null; - protected ?DateTime $lastRun = null; - protected ?DateTime $nextRun = null; - protected ?bool $isEnabled = null; - protected ?DateTime $dateCreated = null; - protected ?DateTime $dateModified = null; - protected ?array $listens = null; - protected ?array $conditions = null; - protected ?string $class = null; - protected ?int $priority = null; - protected ?bool $async = null; - protected ?array $configuration = null; - protected ?bool $isLockable = null; - protected ?bool $locked = null; - protected ?int $lastRunTime = null; - protected ?bool $status = null; - protected ?array $actionHandlerConfiguration = null; + protected ?DateTime $created = null; + protected ?DateTime $updated = null; public function __construct() { $this->addType('name', 'string'); $this->addType('description', 'string'); - $this->addType('reference', 'string'); - $this->addType('version', 'string'); - $this->addType('crontab', 'string'); + $this->addType('interval', 'integer'); + $this->addType('timeSensitive', 'boolean'); + $this->addType('allowParallelRuns', 'boolean'); + $this->addType('isEnabled', 'boolean'); $this->addType('userId', 'string'); - $this->addType('throws', 'string'); $this->addType('data', 'json'); - $this->addType('lastRun', 'datetime'); - $this->addType('nextRun', 'datetime'); - $this->addType('isEnabled', 'boolean'); - $this->addType('dateCreated', 'datetime'); - $this->addType('dateModified', 'datetime'); - $this->addType('listens', 'json'); - $this->addType('conditions', 'json'); - $this->addType('class', 'string'); - $this->addType('priority', 'integer'); - $this->addType('async', 'boolean'); - $this->addType('configuration', 'json'); - $this->addType('isLockable', 'boolean'); - $this->addType('locked', 'boolean'); - $this->addType('lastRunTime', 'integer'); - $this->addType('status', 'boolean'); - $this->addType('actionHandlerConfiguration', 'json'); + $this->addType('created', 'datetime'); + $this->addType('updated', 'datetime'); } public function getJsonFields(): array @@ -96,28 +68,14 @@ public function jsonSerialize(): array 'id' => $this->id, 'name' => $this->name, 'description' => $this->description, - 'reference' => $this->reference, - 'version' => $this->version, - 'crontab' => $this->crontab, + 'interval' => $this->interval, + 'timeSensitive' => $this->timeSensitive, + 'allowParallelRuns' => $this->allowParallelRuns, + 'isEnabled' => $this->isEnabled, 'userId' => $this->userId, - 'throws' => $this->throws, 'data' => $this->data, - 'lastRun' => $this->lastRun, - 'nextRun' => $this->nextRun, - 'isEnabled' => $this->isEnabled, - 'dateCreated' => $this->dateCreated, - 'dateModified' => $this->dateModified, - 'listens' => $this->listens, - 'conditions' => $this->conditions, - 'class' => $this->class, - 'priority' => $this->priority, - 'async' => $this->async, - 'configuration' => $this->configuration, - 'isLockable' => $this->isLockable, - 'locked' => $this->locked, - 'lastRunTime' => $this->lastRunTime, - 'status' => $this->status, - 'actionHandlerConfiguration' => $this->actionHandlerConfiguration + 'created' => $this->created, + 'updated' => $this->updated, ]; } } \ No newline at end of file diff --git a/lib/Db/JobLog.php b/lib/Db/JobLog.php new file mode 100644 index 0000000..25139a0 --- /dev/null +++ b/lib/Db/JobLog.php @@ -0,0 +1,75 @@ +addType('statusCode', 'integer'); + $this->addType('statusMessage', 'string'); + $this->addType('request', 'json'); + $this->addType('response', 'json'); + $this->addType('sourceId', 'integer'); + $this->addType('actionId', 'integer'); + $this->addType('synchronizationId', 'integer'); + $this->addType('createdAt', 'datetime'); + } + + public function getJsonFields(): array + { + return array_keys( + array_filter($this->getFieldTypes(), function ($field) { + return $field === 'json'; + }) + ); + } + + public function hydrate(array $object): self + { + $jsonFields = $this->getJsonFields(); + + foreach($object as $key => $value) { + if (in_array($key, $jsonFields) === true && $value === []) { + $value = []; + } + + $method = 'set'.ucfirst($key); + + try { + $this->$method($value); + } catch (\Exception $exception) { + // Handle or log the exception if needed + } + } + + return $this; + } + + public function jsonSerialize(): array + { + return [ + 'id' => $this->id, + 'statusCode' => $this->statusCode, + 'statusMessage' => $this->statusMessage, + 'request' => $this->request, + 'response' => $this->response, + 'sourceId' => $this->sourceId, + 'actionId' => $this->actionId, + 'synchronizationId' => $this->synchronizationId, + 'createdAt' => $this->createdAt, + ]; + } +} \ No newline at end of file diff --git a/lib/Db/JobLogMapper.php b/lib/Db/JobLogMapper.php new file mode 100644 index 0000000..29a99b6 --- /dev/null +++ b/lib/Db/JobLogMapper.php @@ -0,0 +1,72 @@ +db->getQueryBuilder(); + + $qb->select('*') + ->from('openconnector_job_logs') + ->where( + $qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)) + ); + + return $this->findEntity($qb); + } + + public function findAll(?int $limit = null, ?int $offset = null, ?array $filters = [], ?array $searchConditions = [], ?array $searchParams = []): array + { + $qb = $this->db->getQueryBuilder(); + + $qb->select('*') + ->from('openconnector_job_logs') + ->setMaxResults($limit) + ->setFirstResult($offset); + + foreach($filters as $filter => $value) { + if ($value === 'IS NOT NULL') { + $qb->andWhere($qb->expr()->isNotNull($filter)); + } elseif ($value === 'IS NULL') { + $qb->andWhere($qb->expr()->isNull($filter)); + } else { + $qb->andWhere($qb->expr()->eq($filter, $qb->createNamedParameter($value))); + } + } + + if (!empty($searchConditions)) { + $qb->andWhere('(' . implode(' OR ', $searchConditions) . ')'); + foreach ($searchParams as $param => $value) { + $qb->setParameter($param, $value); + } + } + + return $this->findEntities($qb); + } + + public function createFromArray(array $object): JobLog + { + $jobLog = new JobLog(); + $jobLog->hydrate($object); + return $this->insert($jobLog); + } + + public function updateFromArray(int $id, array $object): JobLog + { + $jobLog = $this->find($id); + $jobLog->hydrate($object); + + return $this->update($jobLog); + } +} \ No newline at end of file diff --git a/lib/Migration/Version0Date20240826193657.php b/lib/Migration/Version0Date20240826193657.php index cf6e160..a160537 100644 --- a/lib/Migration/Version0Date20240826193657.php +++ b/lib/Migration/Version0Date20240826193657.php @@ -46,28 +46,14 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt $table->addColumn('id', Types::BIGINT, ['autoincrement' => true, 'notnull' => true, 'length' => 20]); $table->addColumn('name', Types::STRING, ['notnull' => true, 'length' => 255]); $table->addColumn('description', Types::TEXT, ['notnull' => false]); - $table->addColumn('reference', Types::STRING, ['notnull' => false, 'length' => 255]); - $table->addColumn('version', Types::STRING, ['notnull' => false, 'length' => 50]); - $table->addColumn('crontab', Types::STRING, ['notnull' => false, 'length' => 255]); + $table->addColumn('interval', Types::INTEGER, ['notnull' => true]); + $table->addColumn('time_sensitive', Types::BOOLEAN, ['notnull' => true, 'default' => true]); + $table->addColumn('allow_parallel_runs', Types::BOOLEAN, ['notnull' => true, 'default' => false]); + $table->addColumn('is_enabled', Types::BOOLEAN, ['notnull' => true, 'default' => true]); $table->addColumn('user_id', Types::STRING, ['notnull' => false, 'length' => 255]); - $table->addColumn('throws', Types::TEXT, ['notnull' => false]); $table->addColumn('data', Types::TEXT, ['notnull' => false]); - $table->addColumn('last_run', Types::DATETIME, ['notnull' => false]); - $table->addColumn('next_run', Types::DATETIME, ['notnull' => false]); - $table->addColumn('is_enabled', Types::BOOLEAN, ['notnull' => true, 'default' => true]); - $table->addColumn('listens', Types::TEXT, ['notnull' => false]); - $table->addColumn('conditions', Types::TEXT, ['notnull' => false]); - $table->addColumn('class', Types::STRING, ['notnull' => false, 'length' => 255]); - $table->addColumn('priority', Types::INTEGER, ['notnull' => false]); - $table->addColumn('async', Types::BOOLEAN, ['notnull' => true, 'default' => false]); - $table->addColumn('configuration', Types::TEXT, ['notnull' => false]); - $table->addColumn('is_lockable', Types::BOOLEAN, ['notnull' => true, 'default' => false]); - $table->addColumn('locked', Types::BOOLEAN, ['notnull' => true, 'default' => false]); - $table->addColumn('last_run_time', Types::INTEGER, ['notnull' => false]); - $table->addColumn('status', Types::BOOLEAN, ['notnull' => true, 'default' => true]); - $table->addColumn('action_handler_configuration', Types::TEXT, ['notnull' => false]); - $table->addColumn('date_created', Types::DATETIME, ['notnull' => true, 'default' => 'CURRENT_TIMESTAMP']); - $table->addColumn('date_modified', Types::DATETIME, ['notnull' => true, 'default' => 'CURRENT_TIMESTAMP']); + $table->addColumn('created', Types::DATETIME, ['notnull' => true, 'default' => 'CURRENT_TIMESTAMP']); + $table->addColumn('updated', Types::DATETIME, ['notnull' => true, 'default' => 'CURRENT_TIMESTAMP']); $table->setPrimaryKey(['id']); } @@ -181,7 +167,48 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt $table->addColumn('date_created', Types::DATETIME, ['notnull' => true, 'default' => 'CURRENT_TIMESTAMP']); $table->addColumn('date_modified', Types::DATETIME, ['notnull' => true, 'default' => 'CURRENT_TIMESTAMP']); $table->setPrimaryKey(['id']); - } + } + + if (!$schema->hasTable('openconnector_call_logs')) { + $table = $schema->createTable('openconnector_call_logs'); + $table->addColumn('id', 'integer', [ + 'autoincrement' => true, + 'notnull' => true, + ]); + $table->addColumn('status_code', 'integer', [ + 'notnull' => false, + 'length' => 3 + ]); + $table->addColumn('status_message', 'string', [ + 'notnull' => false, + 'length' => 256 + ]); + $table->addColumn('request', 'json', [ + 'notnull' => false, + ]); + $table->addColumn('response', 'json', [ + 'notnull' => false, + ]); + $table->addColumn('source_id', 'integer', [ + 'notnull' => true, + ]); + $table->addColumn('action_id', 'integer', [ + 'notnull' => false, + ]); + $table->addColumn('synchronization_id', 'integer', [ + 'notnull' => false, + ]); + $table->addColumn('created_at', 'datetime', [ + 'notnull' => true, + 'default' => 'CURRENT_TIMESTAMP' + ]); + + $table->setPrimaryKey(['id']); + $table->addIndex(['source_id'], 'openconnector_call_logs_source_id_index'); + $table->addIndex(['action_id'], 'openconnector_call_logs_action_id_index'); + $table->addIndex(['synchronization_id'], 'openconnector_call_logs_sync_id_index'); + $table->addIndex(['status_code'], 'openconnector_call_logs_status_code_index'); + } return $schema; } diff --git a/lib/Migration/Version0Date20240926235025.php b/lib/Migration/Version0Date20240926235025.php deleted file mode 100644 index e71cc8f..0000000 --- a/lib/Migration/Version0Date20240926235025.php +++ /dev/null @@ -1,85 +0,0 @@ -hasTable('openconnector_call_logs')) { - $table = $schema->createTable('openconnector_call_logs'); - $table->addColumn('id', 'integer', [ - 'autoincrement' => true, - 'notnull' => true, - ]); - $table->addColumn('status_code', 'integer', [ - 'notnull' => false, - 'length' => 3 - ]); - $table->addColumn('status_message', 'string', [ - 'notnull' => false, - 'length' => 256 - ]); - $table->addColumn('request', 'json', [ - 'notnull' => false, - ]); - $table->addColumn('response', 'json', [ - 'notnull' => false, - ]); - $table->addColumn('source_id', 'integer', [ - 'notnull' => true, - ]); - $table->addColumn('action_id', 'integer', [ - 'notnull' => false, - ]); - $table->addColumn('synchronization_id', 'integer', [ - 'notnull' => false, - ]); - $table->addColumn('created_at', 'datetime', [ - 'notnull' => true, - 'default' => 'CURRENT_TIMESTAMP' - ]); - $table->addColumn('updated_at', 'datetime', [ - 'notnull' => true, - 'default' => 'CURRENT_TIMESTAMP' - ]); - - $table->setPrimaryKey(['id']); - $table->addIndex(['source_id'], 'openconnector_call_logs_source_id_index'); - $table->addIndex(['action_id'], 'openconnector_call_logs_action_id_index'); - $table->addIndex(['synchronization_id'], 'openconnector_call_logs_sync_id_index'); - $table->addIndex(['status_code'], 'openconnector_call_logs_status_code_index'); - } - - return $schema; - } -} \ No newline at end of file diff --git a/src/modals/Job/EditJob.vue b/src/modals/Job/EditJob.vue index f616115..97d7d0a 100644 --- a/src/modals/Job/EditJob.vue +++ b/src/modals/Job/EditJob.vue @@ -16,9 +16,9 @@ import { jobStore, navigationStore } from '../../store/store.js'
@@ -27,8 +27,9 @@ import { jobStore, navigationStore } from '../../store/store.js' :value.sync="jobStore.jobItem.description" />
- - +
From 173cb4d5f574674d42597fcc075a4fd7f3382d56 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Fri, 27 Sep 2024 13:12:14 +0200 Subject: [PATCH 014/155] Very small but essential fixes Job cretion now works --- lib/Db/Job.php | 2 +- src/modals/Job/EditJob.vue | 7 ++++++- src/views/Job/JobsList.vue | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/Db/Job.php b/lib/Db/Job.php index 3806672..6caf563 100644 --- a/lib/Db/Job.php +++ b/lib/Db/Job.php @@ -10,7 +10,7 @@ class Job extends Entity implements JsonSerializable { protected ?string $name = null; protected ?string $description = null; - protected ?integer $interval = null; + protected ?int $interval = null; protected ?bool $timeSensitive = true; protected ?bool $allowParallelRuns = false; protected ?bool $isEnabled = true; diff --git a/src/modals/Job/EditJob.vue b/src/modals/Job/EditJob.vue index 97d7d0a..59d0d1e 100644 --- a/src/modals/Job/EditJob.vue +++ b/src/modals/Job/EditJob.vue @@ -29,7 +29,7 @@ import { jobStore, navigationStore } from '../../store/store.js'
+ :value.sync="jobStore.jobItem.interval" />
@@ -75,6 +75,11 @@ export default { }, data() { return { + sourceItem: { + name: '', + description: '', + location: '', + }, success: false, loading: false, error: false, diff --git a/src/views/Job/JobsList.vue b/src/views/Job/JobsList.vue index a83803b..b15cd92 100644 --- a/src/views/Job/JobsList.vue +++ b/src/views/Job/JobsList.vue @@ -50,13 +50,13 @@ import { jobStore, navigationStore, searchStore } from '../../store/store.js' - Bewerken + Edit - Verwijderen + Delete From 00a93a85d5b303873f44706169059cca693eb6d8 Mon Sep 17 00:00:00 2001 From: Remko Date: Fri, 27 Sep 2024 17:08:41 +0200 Subject: [PATCH 015/155] Added mappings to mapping --- .gitignore | 1 + css/main.css | 13 +- lib/Db/Job.php | 4 +- lib/Db/Log.php | 4 +- lib/Db/Mapping.php | 4 +- lib/Db/Source.php | 4 +- lib/Db/Synchronization.php | 4 +- src/modals/Mapping/EditMapping.vue | 70 +++++++---- src/modals/Modals.vue | 6 + .../mappingMapping/DeleteMappingMapping.vue | 118 ++++++++++++++++++ .../mappingMapping/EditMappingMapping.vue | 117 +++++++++++++++++ src/store/modules/mapping.js | 15 ++- src/store/modules/navigation.js | 2 +- src/views/Mapping/MappingDetails.vue | 92 ++++++++++++-- src/views/Mapping/MappingsIndex.vue | 8 +- 15 files changed, 407 insertions(+), 55 deletions(-) create mode 100644 src/modals/mappingMapping/DeleteMappingMapping.vue create mode 100644 src/modals/mappingMapping/EditMappingMapping.vue diff --git a/.gitignore b/.gitignore index 4036a2b..c7220ec 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ /node_modules/ /js/ /custom_apps/ +/custom-apps/ /config/ /coverage/ diff --git a/css/main.css b/css/main.css index f31bef5..d017436 100644 --- a/css/main.css +++ b/css/main.css @@ -114,7 +114,7 @@ /* Modals */ .modalContent { - margin: var(--OC-margin-10); + margin: var(--OC-margin-50); text-align: center; } .modalContent > *:not(:last-child) { @@ -175,3 +175,14 @@ margin-left: 16px; color: inherit; } + +.h1 { + display: block !important; + font-size: 2em !important; + margin-block-start: 0.67em !important; + margin-block-end: 0.67em !important; + margin-inline-start: 0px !important; + margin-inline-end: 0px !important; + font-weight: bold !important; + unicode-bidi: isolate !important; +} diff --git a/lib/Db/Job.php b/lib/Db/Job.php index c75a7ba..681661a 100644 --- a/lib/Db/Job.php +++ b/lib/Db/Job.php @@ -105,8 +105,8 @@ public function jsonSerialize(): array 'lastRun' => $this->lastRun, 'nextRun' => $this->nextRun, 'isEnabled' => $this->isEnabled, - 'dateCreated' => $this->dateCreated, - 'dateModified' => $this->dateModified, + 'dateCreated' => isset($this->dateCreated) ? $this->dateCreated->format('c') : null, + 'dateModified' => isset($this->dateModified) ? $this->dateModified->format('c') : null, 'listens' => $this->listens, 'conditions' => $this->conditions, 'class' => $this->class, diff --git a/lib/Db/Log.php b/lib/Db/Log.php index ada5b87..b5b41ec 100644 --- a/lib/Db/Log.php +++ b/lib/Db/Log.php @@ -122,8 +122,8 @@ public function jsonSerialize(): array 'gateway' => $this->gateway, 'handler' => $this->handler, 'objectId' => $this->objectId, - 'dateCreated' => $this->dateCreated, - 'dateModified' => $this->dateModified + 'dateCreated' => isset($this->dateCreated) ? $this->dateCreated->format('c') : null, + 'dateModified' => isset($this->dateModified) ? $this->dateModified->format('c') : null, ]; } } \ No newline at end of file diff --git a/lib/Db/Mapping.php b/lib/Db/Mapping.php index 81c4969..29c1e2e 100644 --- a/lib/Db/Mapping.php +++ b/lib/Db/Mapping.php @@ -74,8 +74,8 @@ public function jsonSerialize(): array 'unset' => $this->unset, 'cast' => $this->cast, 'passTrough' => $this->passTrough, - 'dateCreated' => $this->dateCreated, - 'dateModified' => $this->dateModified + 'dateCreated' => isset($this->dateCreated) ? $this->dateCreated->format('c') : null, + 'dateModified' => isset($this->dateModified) ? $this->dateModified->format('c') : null, ]; } } \ No newline at end of file diff --git a/lib/Db/Source.php b/lib/Db/Source.php index 22182d0..12d2064 100644 --- a/lib/Db/Source.php +++ b/lib/Db/Source.php @@ -145,8 +145,8 @@ public function jsonSerialize(): array 'lastCall' => $this->lastCall, 'lastSync' => $this->lastSync, 'objectCount' => $this->objectCount, - 'dateCreated' => $this->dateCreated, - 'dateModified' => $this->dateModified, + 'dateCreated' => isset($this->dateCreated) ? $this->dateCreated->format('c') : null, + 'dateModified' => isset($this->dateModified) ? $this->dateModified->format('c') : null, 'test' => $this->test ]; } diff --git a/lib/Db/Synchronization.php b/lib/Db/Synchronization.php index 5fa46d4..e85a46b 100644 --- a/lib/Db/Synchronization.php +++ b/lib/Db/Synchronization.php @@ -95,8 +95,8 @@ public function jsonSerialize(): array 'sourceLastChanged' => $this->sourceLastChanged, 'lastChecked' => $this->lastChecked, 'lastSynced' => $this->lastSynced, - 'dateCreated' => $this->dateCreated, - 'dateModified' => $this->dateModified, + 'dateCreated' => isset($this->dateCreated) ? $this->dateCreated->format('c') : null, + 'dateModified' => isset($this->dateModified) ? $this->dateModified->format('c') : null, 'tryCounter' => $this->tryCounter, 'dontSyncBefore' => $this->dontSyncBefore, 'mapping' => $this->mapping diff --git a/src/modals/Mapping/EditMapping.vue b/src/modals/Mapping/EditMapping.vue index d657199..ae980bc 100644 --- a/src/modals/Mapping/EditMapping.vue +++ b/src/modals/Mapping/EditMapping.vue @@ -5,9 +5,9 @@ import { mappingStore, navigationStore } from '../../store/store.js'