From b9cf59ab27d223f59d59992cf3a32080fe6e8077 Mon Sep 17 00:00:00 2001 From: Barry Brands Date: Thu, 15 Aug 2024 15:02:31 +0200 Subject: [PATCH] WIP: copy listing metadata --- lib/Db/Listing.php | 8 +- lib/Db/ListingMapper.php | 34 +++--- lib/Migration/Version6Date20240815105059.php | 82 ++++++++++++++ lib/Service/DirectoryService.php | 2 +- .../catalogiMetadata/AddCatalogiMetadata.vue | 12 ++- src/modals/metaData/AddMetaDataModal.vue | 6 ++ src/modals/metaData/EditMetaDataModal.vue | 1 + .../publication/AddPublicationModal.vue | 1 + src/sidebars/SideBars.vue | 4 +- src/sidebars/directory/DirectorySideBar.vue | 102 +++++++++++++++++- src/store/modules/directory.js | 2 +- src/views/publications/PublicationDetail.vue | 4 + 12 files changed, 230 insertions(+), 28 deletions(-) create mode 100644 lib/Migration/Version6Date20240815105059.php diff --git a/lib/Db/Listing.php b/lib/Db/Listing.php index a26a5a48..810d918d 100644 --- a/lib/Db/Listing.php +++ b/lib/Db/Listing.php @@ -15,7 +15,7 @@ class Listing extends Entity implements JsonSerializable protected ?string $description = null; protected ?string $search = null; protected ?string $directory = null; - protected ?string $metadata = null; + protected ?array $metadata = null; protected ?string $catalogId = null; protected ?string $status = null; protected ?DateTime $lastSync = null; @@ -29,7 +29,7 @@ public function __construct() { $this->addType(fieldName: 'description', type: 'string'); $this->addType(fieldName: 'search', type: 'string'); $this->addType(fieldName: 'directory', type: 'string'); - $this->addType(fieldName: 'metadata', type: 'string'); + $this->addType(fieldName: 'metadata', type: 'json'); $this->addType(fieldName: 'catalogId', type: 'string'); $this->addType(fieldName: 'status', type: 'string'); $this->addType(fieldName: 'lastSync', type: 'datetime'); @@ -51,6 +51,10 @@ public function hydrate(array $object): self { $jsonFields = $this->getJsonFields(); + if(isset($object['metadata']) === false) { + $object['metadata'] = []; + } + foreach($object as $key => $value) { if (in_array($key, $jsonFields) === true && $value === []) { $value = null; diff --git a/lib/Db/ListingMapper.php b/lib/Db/ListingMapper.php index a97a4730..95ac50e6 100644 --- a/lib/Db/ListingMapper.php +++ b/lib/Db/ListingMapper.php @@ -56,7 +56,7 @@ protected function mapRowToEntityCustom(array $row): Entity { } } - $row['organisation'] = $organisationIsEmpty === true ? null : Organisation::fromRow($organisationData); + // $row['organisation'] = $organisationIsEmpty === true ? null : Organisation::fromRow($organisationData); return \call_user_func($this->entityClass .'::fromRow', $row); } @@ -86,25 +86,25 @@ protected function findEntitiesCustom(IQueryBuilder $query): array { public function findAll(?int $limit = null, ?int $offset = null, ?array $filters = [], ?array $searchConditions = [], ?array $searchParams = []): array { $qb = $this->db->getQueryBuilder(); - - $qb->select( - 'l.*', - 'o.id AS organisation_id', - 'o.title AS organisation_title', - 'o.summary AS organisation_summary', - 'o.description AS organisation_description', - 'o.image AS organisation_image', - 'o.oin AS organisation_oin', - 'o.tooi AS organisation_tooi', - 'o.rsin AS organisation_rsin', - 'o.pki AS organisation_pki' + + $qb->select('*' + // 'l.*', + // 'o.id AS organisation_id', + // 'o.title AS organisation_title', + // 'o.summary AS organisation_summary', + // 'o.description AS organisation_description', + // 'o.image AS organisation_image', + // 'o.oin AS organisation_oin', + // 'o.tooi AS organisation_tooi', + // 'o.rsin AS organisation_rsin', + // 'o.pki AS organisation_pki' ) ->from('listings', 'l') - ->leftJoin('l', 'organizations', 'o', 'l.organisation = o.id') + // ->leftJoin('l', 'organizations', 'o', 'l.organisation = o.id') ->setMaxResults($limit) ->setFirstResult($offset); - + // Apply filters foreach ($filters as $filter => $value) { if ($value === 'IS NOT NULL') { @@ -115,7 +115,7 @@ public function findAll(?int $limit = null, ?int $offset = null, ?array $filters $qb->andWhere($qb->expr()->eq($filter, $qb->createNamedParameter($value))); } } - + // Apply search conditions if (!empty($searchConditions)) { $qb->andWhere('(' . implode(' OR ', $searchConditions) . ')'); @@ -123,7 +123,7 @@ public function findAll(?int $limit = null, ?int $offset = null, ?array $filters $qb->setParameter($param, $value); } } - + // Use the existing findEntities method to fetch and map the results return $this->findEntitiesCustom($qb); } diff --git a/lib/Migration/Version6Date20240815105059.php b/lib/Migration/Version6Date20240815105059.php new file mode 100644 index 00000000..44c909a4 --- /dev/null +++ b/lib/Migration/Version6Date20240815105059.php @@ -0,0 +1,82 @@ + + * + * FIXME @author Your name + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\OpenCatalogi\Migration; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; +use OCP\DB\Types; + +/** + * FIXME Auto-generated migration step: Please modify to your needs! + */ +class Version6Date20240815105059 extends SimpleMigrationStep { + + /** + * @param IOutput $output + * @param Closure(): ISchemaWrapper $schemaClosure + * @param array $options + */ + public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void { + } + + /** + * @param IOutput $output + * @param Closure(): ISchemaWrapper $schemaClosure + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + $schema = $schemaClosure(); + $table = $schema->getTable('listings'); + + if ($table->hasColumn('metadata')) { + $table->dropColumn('metadata'); + } + + $table->addColumn( + name: 'metadata', + typeName: Types::JSON, + options: [ + 'notNull' => false, + 'default' => 'a:0:{}' + ]); + + $output->info("Added 'metadata' column as JSON type with a default value of an empty array."); + + return $schema; + } + + /** + * @param IOutput $output + * @param Closure(): ISchemaWrapper $schemaClosure + * @param array $options + */ + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void { + } +} diff --git a/lib/Service/DirectoryService.php b/lib/Service/DirectoryService.php index 4de3e99b..3f0b6372 100644 --- a/lib/Service/DirectoryService.php +++ b/lib/Service/DirectoryService.php @@ -224,7 +224,7 @@ public function listCatalog (array $catalog): array $listing['title'] = $catalog['title']; $listing['organisation'] = $catalog['organisation']; - $listing['metaData'] = $catalog['metaData']; + $listing['metadata'] = $catalog['metadata']; if($this->config->hasKey($this->appName, 'mongoStorage') === false || $this->config->getValueString($this->appName, 'mongoStorage') !== '1' diff --git a/src/modals/catalogiMetadata/AddCatalogiMetadata.vue b/src/modals/catalogiMetadata/AddCatalogiMetadata.vue index 4b093c66..575b2cbc 100644 --- a/src/modals/catalogiMetadata/AddCatalogiMetadata.vue +++ b/src/modals/catalogiMetadata/AddCatalogiMetadata.vue @@ -28,7 +28,7 @@ import { catalogiStore, navigationStore } from '../../store/store.js' required /> Welke meta data typen zou u uit deze catalogus willen overnemen? - - Metedata type 1 + + {{ metadataSingular.title }} @@ -80,14 +80,112 @@ export default { CogOutline, FileTreeOutline, }, + props: { + listingItem: { + type: Object, + required: true, + }, + }, data() { return { + metadata: [], + listing: '', } }, + watch: { + publicationItem: { + handler(newVal) { + console.log('test watch') + console.log(newVal) + if (newVal && newVal.id) { + this.fetchMetaData() + } + }, + immediate: true, // Ensures the watcher runs when the component is created + }, + }, + mounted() { + this.fetchMetaData() + }, methods: { openLink(url, type = '') { window.open(url, type) }, + CopyMetadata() { + this.loading = true + // metadataStore.metaDataItem.title = 'KOPIE: ' + metadataStore.metaDataItem.title + if (Object.keys(metadataStore.metaDataItem.properties).length === 0) { + delete metadataStore.metaDataItem.properties + } + delete metadataStore.metaDataItem.id + delete metadataStore.metaDataItem._id + fetch( + '/index.php/apps/opencatalogi/api/metadata', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(metadataStore.metaDataItem), + }, + ) + .then((response) => { + this.loading = false + this.succes = true + // Lets refresh the catalogiList + metadataStore.refreshMetaDataList() + response.json().then((data) => { + metadataStore.setMetaDataItem(data) + }) + navigationStore.setSelected('metaData') + // Wait for the user to read the feedback then close the model + const self = this + setTimeout(function() { + self.succes = false + navigationStore.setDialog(false) + }, 2000) + }) + .catch((err) => { + this.error = err + this.loading = false + }) + }, + fetchMetaData() { + this.loading = true + console.log('test1') + console.log(directoryStore.listingItem) + if (directoryStore.listingItem && Array.isArray(directoryStore.listingItem.metadata)) { + directoryStore.listingItem?.metadata.forEach(metadataSingular => { + console.log('test2') + fetch( + '/index.php/apps/opencatalogi/api/metadata?source=' + metadataSingular, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + .then((response) => { + this.loading = false + this.succes = true + + response.json().then( + (data) => { + if (data?.results[0] !== undefined) { + this.metaData.push(data.results[0]) + } + return data + }, + ) + }) + .catch((err) => { + this.error = err + this.loading = false + }) + }) + } + }, }, } diff --git a/src/store/modules/directory.js b/src/store/modules/directory.js index bad527f5..3405b2b1 100644 --- a/src/store/modules/directory.js +++ b/src/store/modules/directory.js @@ -10,7 +10,7 @@ export const useDirectoryStore = defineStore( }), actions: { setListingItem(listingItem) { - this.listingItem = listingItem && new Listing(listingItem) + this.listingItem = listingItem ? new Listing(listingItem) : false console.log('Active directory item set to ' + listingItem && listingItem.id) }, setListingList(listingList) { diff --git a/src/views/publications/PublicationDetail.vue b/src/views/publications/PublicationDetail.vue index 9d96e7d6..3cb73993 100644 --- a/src/views/publications/PublicationDetail.vue +++ b/src/views/publications/PublicationDetail.vue @@ -131,6 +131,10 @@ import { catalogiStore, metadataStore, navigationStore, publicationStore } from Gewijzigd: {{ publicationStore.publicationItem.modified }} +
+ Bron: + {{ publicationStore.publicationItem.source }} +
Catalogi: Loading...