From 1bb38b420c596e8c449e24a370c06742640c11f5 Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Wed, 14 Apr 2021 19:27:04 +0300 Subject: [PATCH 01/61] Removed unwanted FABs --- app/react/App/scss/layout/_sidepanel.scss | 29 ++++++++++++ .../Library/components/LibraryFilters.js | 45 +++++++++---------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/app/react/App/scss/layout/_sidepanel.scss b/app/react/App/scss/layout/_sidepanel.scss index 1f7ac0dd1b..93e0cfd626 100644 --- a/app/react/App/scss/layout/_sidepanel.scss +++ b/app/react/App/scss/layout/_sidepanel.scss @@ -300,6 +300,35 @@ $c-sidebar: $c-white; line-height: 50px; height: 50px; border-bottom: 1px solid #d7d7dc; + display: flex; + flex-flow: row nowrap; + + div:nth-child(1) { + width: 65%; + } + div:nth-child(2) { + width: 35% + } + .filter-buttons { + + .clear-button { + text-decoration: none; + letter-spacing: normal; + font-weight: normal; + display: inline; + text-transform: capitalize; + border: 1px solid rgb(204, 204, 204); + padding: 3px; + cursor: pointer; + border-radius: 2px; + } + + @media(min-width: 1020px) { + .push-right { + margin-left: 30px; + } + } + } } .item.readOnly { diff --git a/app/react/Library/components/LibraryFilters.js b/app/react/Library/components/LibraryFilters.js index 866b7340f3..f68dbce3b7 100644 --- a/app/react/Library/components/LibraryFilters.js +++ b/app/react/Library/components/LibraryFilters.js @@ -34,33 +34,32 @@ export class LibraryFilters extends Component { return (
- -

- {t('System', 'Filters configuration')} - +

{t('System', 'Filters configuration')}
+
+
+ +  Clear Filters +
+ +

{!this.props.unpublished && ( From 441ed6737fdb965f9b59f86d1daa7bb36a6f4654 Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Wed, 14 Apr 2021 19:27:50 +0300 Subject: [PATCH 02/61] Allows close button to show in unpinned mode --- app/react/Library/components/LibraryFilters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/react/Library/components/LibraryFilters.js b/app/react/Library/components/LibraryFilters.js index f68dbce3b7..ec8fa965a1 100644 --- a/app/react/Library/components/LibraryFilters.js +++ b/app/react/Library/components/LibraryFilters.js @@ -42,7 +42,7 @@ export class LibraryFilters extends Component {
From 5ecfae85f3708e939c68c66c47e30da9cd3be9d3 Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Wed, 14 Apr 2021 19:39:44 +0300 Subject: [PATCH 03/61] Removed class conditions --- app/react/Library/components/LibraryFilters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/react/Library/components/LibraryFilters.js b/app/react/Library/components/LibraryFilters.js index ec8fa965a1..f68dbce3b7 100644 --- a/app/react/Library/components/LibraryFilters.js +++ b/app/react/Library/components/LibraryFilters.js @@ -42,7 +42,7 @@ export class LibraryFilters extends Component {
From 04f2de6667cacdc6239cd9dd8199014b98b91a3d Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Wed, 14 Apr 2021 20:59:25 +0300 Subject: [PATCH 04/61] Updated selectors --- nightmare/helpers/selectors.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nightmare/helpers/selectors.js b/nightmare/helpers/selectors.js index e87967177e..d67574313b 100644 --- a/nightmare/helpers/selectors.js +++ b/nightmare/helpers/selectors.js @@ -161,9 +161,9 @@ export default { documentAfterLoadMore: '#app > div.content > div > div > div > main > div > div > div.item-group > div:nth-child(31)', superVillianType: - '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div.documentTypes-selector.nested-selector > ul > li:nth-child(2) > label', + '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div > ul > li:nth-child(2) > label', //.documentTypes-selector.nested-selector minorVillianType: - '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div.documentTypes-selector.nested-selector > ul > li:nth-child(5) > label', + '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div > ul > li:nth-child(5) > label', resetFilters: '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-footer > .resetFilters', sidePanelCloseButton: From 8076172750a15adb12b2390bcf598d5c367be325 Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Wed, 14 Apr 2021 21:17:37 +0300 Subject: [PATCH 05/61] Updated reset button selectors --- nightmare/helpers/selectors.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nightmare/helpers/selectors.js b/nightmare/helpers/selectors.js index d67574313b..261ed4d887 100644 --- a/nightmare/helpers/selectors.js +++ b/nightmare/helpers/selectors.js @@ -165,7 +165,8 @@ export default { minorVillianType: '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div > ul > li:nth-child(5) > label', resetFilters: - '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-footer > .resetFilters', + '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > p.sidepanel-title > div.filter-buttons > div.clear-button', + // '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-footer > .resetFilters', sidePanelCloseButton: '#app > div.content > div > div > div > aside.side-panel.metadata-sidepanel.is-active > div.sidepanel-header > button', sidePanelDocumentType: From 49db386964bb139e7d94382a66cfea6900728c1e Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Thu, 15 Apr 2021 13:19:56 +0300 Subject: [PATCH 06/61] Updated libraryNavButton selector --- nightmare/helpers/selectors.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nightmare/helpers/selectors.js b/nightmare/helpers/selectors.js index 261ed4d887..e99d8319cf 100644 --- a/nightmare/helpers/selectors.js +++ b/nightmare/helpers/selectors.js @@ -286,7 +286,8 @@ export default { uploadsNavButton: '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(2) > a', libraryNavButton: - '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(1) > a', + '#app > div.content > header > ul > li.menuActions > ul:nth-child(2) > li:nth-child(1) > a', + // '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(1) > a', settingsNavButton: '#app > div.content > header > ul > li.menuActions > ul.menuNav-list > li:nth-child(3) > a', spanish: From 26857a15873fba80c9bb93cd3023843195e92d27 Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Thu, 15 Apr 2021 13:20:41 +0300 Subject: [PATCH 07/61] Removed error --- nightmare/helpers/selectors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nightmare/helpers/selectors.js b/nightmare/helpers/selectors.js index e99d8319cf..60ffe5c668 100644 --- a/nightmare/helpers/selectors.js +++ b/nightmare/helpers/selectors.js @@ -287,7 +287,7 @@ export default { '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(2) > a', libraryNavButton: '#app > div.content > header > ul > li.menuActions > ul:nth-child(2) > li:nth-child(1) > a', - // '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(1) > a', + // '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(1) > a', settingsNavButton: '#app > div.content > header > ul > li.menuActions > ul.menuNav-list > li:nth-child(3) > a', spanish: From 6b62c14fa10dba0ddd75783d491353886fbea4c6 Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Thu, 15 Apr 2021 13:39:31 +0300 Subject: [PATCH 08/61] Updated selectors --- nightmare/helpers/selectors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nightmare/helpers/selectors.js b/nightmare/helpers/selectors.js index 60ffe5c668..264a6495b6 100644 --- a/nightmare/helpers/selectors.js +++ b/nightmare/helpers/selectors.js @@ -286,7 +286,7 @@ export default { uploadsNavButton: '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(2) > a', libraryNavButton: - '#app > div.content > header > ul > li.menuActions > ul:nth-child(2) > li:nth-child(1) > a', + '#app > div.content > header > ul > li.menuActions > ul.menuNav-list > li:nth-child(1) > a', // '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(1) > a', settingsNavButton: '#app > div.content > header > ul > li.menuActions > ul.menuNav-list > li:nth-child(3) > a', From 4aa75fa79c4ab494d5a5c9f43e8da8e98735dabe Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Thu, 15 Apr 2021 13:55:14 +0300 Subject: [PATCH 09/61] Updated language selectors --- nightmare/helpers/selectors.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nightmare/helpers/selectors.js b/nightmare/helpers/selectors.js index 264a6495b6..c5fa52affc 100644 --- a/nightmare/helpers/selectors.js +++ b/nightmare/helpers/selectors.js @@ -291,9 +291,9 @@ export default { settingsNavButton: '#app > div.content > header > ul > li.menuActions > ul.menuNav-list > li:nth-child(3) > a', spanish: - '#app > div.content > header > ul > li.menuActions > ul.menuNav-I18NMenu > li:nth-child(2) > a', + '#app > div.content > header > ul > li.menuActions > ul.menuNav-I18NMenu > li:nth-child(1) > a', english: - '#app > div.content > header > ul > li.menuActions > ul.menuNav-I18NMenu > li:nth-child(3) > a', + '#app > div.content > header > ul > li.menuActions > ul.menuNav-I18NMenu > li:nth-child(2) > a', }, connections: { editButton: '#app > div.content > div > div > div.sidepanel-footer > span > button', From c8205a90416dd1c5d8d519bd6ddcefbffee93480 Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Thu, 15 Apr 2021 20:17:24 +0300 Subject: [PATCH 10/61] Reverted selector changes --- nightmare/helpers/selectors.js | 4 +- nightmare/suite2/translations.spec.js | 90 ++++++++++++++------------- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/nightmare/helpers/selectors.js b/nightmare/helpers/selectors.js index c5fa52affc..264a6495b6 100644 --- a/nightmare/helpers/selectors.js +++ b/nightmare/helpers/selectors.js @@ -291,9 +291,9 @@ export default { settingsNavButton: '#app > div.content > header > ul > li.menuActions > ul.menuNav-list > li:nth-child(3) > a', spanish: - '#app > div.content > header > ul > li.menuActions > ul.menuNav-I18NMenu > li:nth-child(1) > a', - english: '#app > div.content > header > ul > li.menuActions > ul.menuNav-I18NMenu > li:nth-child(2) > a', + english: + '#app > div.content > header > ul > li.menuActions > ul.menuNav-I18NMenu > li:nth-child(3) > a', }, connections: { editButton: '#app > div.content > div > div > div.sidepanel-footer > span > button', diff --git a/nightmare/suite2/translations.spec.js b/nightmare/suite2/translations.spec.js index db7ccf7e1f..ee3f5b8754 100644 --- a/nightmare/suite2/translations.spec.js +++ b/nightmare/suite2/translations.spec.js @@ -12,63 +12,69 @@ describe('translations path', () => { afterAll(async () => nightmare.end()); describe('login', () => { - it('should log in as admin then click the settings nav button', (done) => { + it('should log in as admin then click the settings nav button', done => { loginAsAdminAndGoToSettings(nightmare, catchErrors, done); }); }); describe('Translations tests', () => { - it('should click Translations button and then click on Test Document', (done) => { + it('should click Translations button and then click on Test Document', done => { nightmare - .waitToClick(selectors.settingsView.translationsButton) - .wait(selectors.settingsView.liElementsOfSection) - .manageItemFromList(selectors.settingsView.liElementsOfSection, 'Test Document', '.btn-default') - .wait(selectors.settingsView.translationsSaveButton) - .isVisible(selectors.settingsView.translationsSaveButton) - .then((result) => { - expect(result).toBe(true); - done(); - }) - .catch(catchErrors(done)); + .waitToClick(selectors.settingsView.translationsButton) + .wait(selectors.settingsView.liElementsOfSection) + .manageItemFromList( + selectors.settingsView.liElementsOfSection, + 'Test Document', + '.btn-default' + ) + .wait(selectors.settingsView.translationsSaveButton) + .isVisible(selectors.settingsView.translationsSaveButton) + .then(result => { + expect(result).toBe(true); + done(); + }) + .catch(catchErrors(done)); }); - it('should change Test Document text to Document and Documento', (done) => { + it('should change Test Document text to Document and Documento', done => { nightmare - .clearInput(selectors.settingsView.translationInputEn) - .write(selectors.settingsView.translationInputEn, 'Document') - .clearInput(selectors.settingsView.translationInputEs) - .write(selectors.settingsView.translationInputEs, 'Documento') - .waitToClick(selectors.settingsView.translationsSaveButton) - .waitToClick('.alert.alert-success') - .then(() => { done(); }) - .catch(catchErrors(done)); + .clearInput(selectors.settingsView.translationInputEn) + .write(selectors.settingsView.translationInputEn, 'Document') + .clearInput(selectors.settingsView.translationInputEs) + .write(selectors.settingsView.translationInputEs, 'Documento') + .waitToClick(selectors.settingsView.translationsSaveButton) + .waitToClick('.alert.alert-success') + .then(() => { + done(); + }) + .catch(catchErrors(done)); }); - it('should go to library and check the translation in spanish', (done) => { + it('should go to library and check the translation in spanish', done => { nightmare - .waitToClick(selectors.navigation.libraryNavButton) - .waitToClick(selectors.navigation.spanish) - .wait(selectors.libraryView.documentTypeFilter) - .getInnerText(selectors.libraryView.documentTypeFilter) - .then((result) => { - expect(result).toBe('Documento'); - done(); - }) - .catch(catchErrors(done)); + .waitToClick(selectors.navigation.libraryNavButton) + .waitToClick(selectors.navigation.spanish) + .wait(selectors.libraryView.documentTypeFilter) + .getInnerText(selectors.libraryView.documentTypeFilter) + .then(result => { + expect(result).toBe('Documento'); + done(); + }) + .catch(catchErrors(done)); }); - it('should go to library and check the translation in english', (done) => { + it('should go to library and check the translation in english', done => { nightmare - .waitToClick(selectors.navigation.libraryNavButton) - .waitToClick(selectors.navigation.english) - .wait(selectors.libraryView.documentTypeFilter) - .wait(selectors.libraryView.documentTypeFilter) - .getInnerText(selectors.libraryView.documentTypeFilter) - .then((result) => { - expect(result).toBe('Document'); - done(); - }) - .catch(catchErrors(done)); + .waitToClick(selectors.navigation.libraryNavButton) + .waitToClick(selectors.navigation.english) + .wait(selectors.libraryView.documentTypeFilter) + .wait(selectors.libraryView.documentTypeFilter) + .getInnerText(selectors.libraryView.documentTypeFilter) + .then(result => { + expect(result).toBe('Document'); + done(); + }) + .catch(catchErrors(done)); }); }); }); From 2489f2b587e179d14cebf0497f8fcb9dfaab6280 Mon Sep 17 00:00:00 2001 From: Federico Nocetti Date: Thu, 15 Apr 2021 14:28:48 -0300 Subject: [PATCH 11/61] Fix HTML nesting --- app/react/Library/components/LibraryFilters.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/react/Library/components/LibraryFilters.js b/app/react/Library/components/LibraryFilters.js index f68dbce3b7..d16632cc35 100644 --- a/app/react/Library/components/LibraryFilters.js +++ b/app/react/Library/components/LibraryFilters.js @@ -37,7 +37,7 @@ export class LibraryFilters extends Component {
-

+

{t('System', 'Filters configuration')}
-

+
{!this.props.unpublished && ( Date: Fri, 16 Apr 2021 12:43:55 +0300 Subject: [PATCH 12/61] Updated resetFilters selector --- nightmare/helpers/selectors.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nightmare/helpers/selectors.js b/nightmare/helpers/selectors.js index 264a6495b6..51f1cd8f0b 100644 --- a/nightmare/helpers/selectors.js +++ b/nightmare/helpers/selectors.js @@ -165,8 +165,7 @@ export default { minorVillianType: '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div > ul > li:nth-child(5) > label', resetFilters: - '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > p.sidepanel-title > div.filter-buttons > div.clear-button', - // '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-footer > .resetFilters', + '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div.sidepanel-title > div.filter-buttons > div.clear-button', sidePanelCloseButton: '#app > div.content > div > div > div > aside.side-panel.metadata-sidepanel.is-active > div.sidepanel-header > button', sidePanelDocumentType: From c3f1c0771fd47162f68ad4fd4d1833aa136b4324 Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Fri, 16 Apr 2021 10:57:01 +0200 Subject: [PATCH 13/61] backend denormalizing inherited properties --- app/api/entities/entities.js | 25 +++++++++++++++++++------ app/api/entities/specs/entities.spec.js | 11 +++++++++++ app/api/entities/specs/fixtures.js | 9 +++++++-- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/app/api/entities/entities.js b/app/api/entities/entities.js index 756cb2b434..dbd71ce813 100644 --- a/app/api/entities/entities.js +++ b/app/api/entities/entities.js @@ -25,7 +25,7 @@ async function denormalizeMetadata(metadata, entity, template, dictionariesByKey } const translation = (await translationsModel.get({ locale: entity.language }))[0]; - + const allTemplates = await templates.get(); const resolveProp = async (key, value) => { if (!Array.isArray(value)) { throw new Error('denormalizeMetadata received non-array prop!'); @@ -59,12 +59,25 @@ async function denormalizeMetadata(metadata, entity, template, dictionariesByKey } if (prop.type === 'relationship') { - const partner = await model.get({ sharedId: elem.value, language: entity.language }); + const [partner] = await model.get({ sharedId: elem.value, language: entity.language }); + + if (partner && partner.title) { + elem.label = partner.title; + elem.icon = partner.icon; + elem.type = partner.file ? 'document' : 'entity'; + } + + if (prop.inherit && partner) { + const partnerTemplate = allTemplates.find( + t => t._id.toString() === partner.template.toString() + ); + + const inheritedProperty = partnerTemplate.properties.find( + p => p._id && p._id.toString() === prop.inheritProperty.toString() + ); - if (partner && partner[0] && partner[0].title) { - elem.label = partner[0].title; - elem.icon = partner[0].icon; - elem.type = partner[0].file ? 'document' : 'entity'; + elem.inheritedValue = partner.metadata[inheritedProperty.name]; + elem.inheritedType = inheritedProperty.type; } } return elem; diff --git a/app/api/entities/specs/entities.spec.js b/app/api/entities/specs/entities.spec.js index b604702ff9..564be775ca 100644 --- a/app/api/entities/specs/entities.spec.js +++ b/app/api/entities/specs/entities.spec.js @@ -730,7 +730,18 @@ describe('entities', () => { const denormalized = await entities.denormalize(entity, { user: 'dummy', language: 'en' }); expect(denormalized.metadata.friends[0].label).toBe('shared2title'); }); + + fit('should denormalize inherited metadata', async () => { + const entity = (await entities.get({ sharedId: 'shared', language: 'en' }))[0]; + + const denormalized = await entities.denormalize(entity, { user: 'dummy', language: 'en' }); + expect(denormalized.metadata.enemies[0].inheritedValue).toEqual([ + { value: 'something to b e inherited' }, + ]); + expect(denormalized.metadata.enemies[0].inheritedType).toBe('text'); + }); }); + describe('countByTemplate', () => { it('should return how many entities using the template passed', async () => { const count = await entities.countByTemplate(templateId); diff --git a/app/api/entities/specs/fixtures.js b/app/api/entities/specs/fixtures.js index 6627cec20a..d291eb1266 100644 --- a/app/api/entities/specs/fixtures.js +++ b/app/api/entities/specs/fixtures.js @@ -31,6 +31,7 @@ const relationType3 = db.id(); const relationType4 = db.id(); const uploadId1 = db.id(); const uploadId2 = db.id(); +const inheritedProperty = db.id(); export default { files: [ @@ -312,7 +313,9 @@ export default { sharedId: 'shared2', language: 'en', title: 'shared2title', - metadata: {}, + metadata: { + property1: [{ value: 'something to b e inherited' }], + }, }, { sharedId: 'source2', language: 'en' }, { @@ -358,7 +361,7 @@ export default { name: 'template_test', properties: [ { type: 'text', name: 'text' }, - { type: 'text', name: 'property1' }, + { _id: inheritedProperty, type: 'text', name: 'property1' }, { type: 'text', name: 'property2' }, { type: 'text', name: 'description' }, { type: 'select', name: 'select', content: dictionary }, @@ -377,6 +380,8 @@ export default { name: 'enemies', relationType: relationType4, content: templateId.toString(), + inherit: true, + inheritProperty: inheritedProperty, }, { type: 'nested', name: 'field_nested' }, { type: 'numeric', name: 'numeric' }, From df4a6b7b5d3705460e69f087ea9ef3baeefbe0c0 Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Fri, 16 Apr 2021 14:11:19 +0200 Subject: [PATCH 14/61] formater inheriting data --- app/react/Metadata/helpers/formater.js | 37 +++++--------- app/react/Metadata/helpers/specs/fixtures.js | 24 +++++++--- .../Metadata/helpers/specs/formater.spec.js | 4 +- app/shared/types/commonSchemas.ts | 2 + app/shared/types/commonTypes.d.ts | 2 + app/shared/types/connectionType.d.ts | 48 +++++++++++++++++++ app/shared/types/entityType.d.ts | 1 + 7 files changed, 86 insertions(+), 32 deletions(-) diff --git a/app/react/Metadata/helpers/formater.js b/app/react/Metadata/helpers/formater.js index bba28d379f..5395ef94e8 100644 --- a/app/react/Metadata/helpers/formater.js +++ b/app/react/Metadata/helpers/formater.js @@ -192,26 +192,21 @@ export default { return { label: property.get('label'), name: property.get('name'), value: sortedValues }; }, - inherit(property, thesauriValues = [], thesauris, options, templates, relationships) { + inherit(property, propValue = [], thesauris, options, templates) { const template = templates.find(templ => templ.get('_id') === property.get('content')); const inheritedProperty = template .get('properties') .find(p => p.get('_id') === property.get('inheritProperty')); - const methodType = this[inheritedProperty.get('type')] - ? inheritedProperty.get('type') - : 'default'; + const type = inheritedProperty.get('type'); - let value = thesauriValues.map(referencedEntity => { - const name = inheritedProperty.get('name'); - const reference = relationships.toJS().find(r => r.entity === referencedEntity.value) || { - entityData: { metadata: {} }, - }; - const metadata = reference.entityData.metadata ? reference.entityData.metadata : {}; - if (metadata[name] || type === 'preview') { - return this[methodType](inheritedProperty, metadata[name], thesauris, options, templates); + const methodType = this[type] ? type : 'default'; + + let value = propValue.map(v => { + if (v.inheritedValue) { + return this[methodType](inheritedProperty, v.inheritedValue, thesauris, options, templates); } - return { value: metadata[name] }; + return { value: v.inheritedValue }; }); let propType = 'inherit'; @@ -220,8 +215,9 @@ export default { _thesauri => _thesauri.get('_id') === template.get('_id') ); propType = type; - value = this.flattenInheritedMultiValue(value, type, thesauriValues, templateThesauris); + value = this.flattenInheritedMultiValue(value, type, propValue, templateThesauris); } + return { translateContext: template.get('_id'), ...inheritedProperty.toJS(), @@ -342,19 +338,12 @@ export default { return { ...doc, metadata: metadata.toJS(), documentType: template.get('name') }; }, - applyTransformation(property, { doc, thesauris, options, template, templates, relationships }) { + applyTransformation(property, { doc, thesauris, options, template, templates }) { const value = doc.metadata[property.get('name')]; const showInCard = property.get('showInCard'); - if (property.get('inherit') && relationships) { - return this.inherit( - property, - value, - thesauris, - { ...options, doc }, - templates, - relationships - ); + if (property.get('inherit')) { + return this.inherit(property, value, thesauris, { ...options, doc }, templates); } const methodType = this[property.get('type')] ? property.get('type') : 'default'; diff --git a/app/react/Metadata/helpers/specs/fixtures.js b/app/react/Metadata/helpers/specs/fixtures.js index 0d1e8033e2..84a01309d5 100644 --- a/app/react/Metadata/helpers/specs/fixtures.js +++ b/app/react/Metadata/helpers/specs/fixtures.js @@ -41,14 +41,26 @@ export const doc = { { type: 'entity', value: 'value4', label: 'Value 4' }, ], relationship3: [ - { value: 'value1', label: 'Value 1' }, - { value: 'value2', label: 'Value 2' }, - { value: 'value3', label: 'Value 3' }, + { value: 'value1', label: 'Value 1', inheritedValue: [{ value: 'how' }] }, + { value: 'value2', label: 'Value 2', inheritedValue: [{ value: 'are' }] }, + { value: 'value3', label: 'Value 3', inheritedValue: [{ value: 'you?' }] }, ], relationship4: [ - { value: 'linkedEntity1', label: 'Entity 1 Title' }, - { value: 'linkedEntity2', label: 'Entity 2 Title' }, - { value: 'linkedEntityWithoutMetadata' }, + { + value: 'linkedEntity1', + label: 'Entity 1 Title', + inheritedValue: [{ value: { lat: 13, lon: 7 } }], + }, + { + value: 'linkedEntity2', + label: 'Entity 2 Title', + inheritedValue: [{ value: { lat: 5, lon: 10, label: 'exisitng label' } }], + }, + { + value: 'linkedEntityWithoutMetadata', + label: 'Entity 2 Title', + inheritedValue: [{ value: { lat: 23, lon: 8, label: 'another label' } }], + }, ], geolocation: [{ value: { lat: 2, lon: 3 } }, { value: { lat: 13, lon: 7, label: 'home' } }], nested: [{ value: { nestedKey: [1, 2] } }, { value: { nestedKey: [3, 4] } }], diff --git a/app/react/Metadata/helpers/specs/formater.spec.js b/app/react/Metadata/helpers/specs/formater.spec.js index 44381210ef..8af55a82b7 100644 --- a/app/react/Metadata/helpers/specs/formater.spec.js +++ b/app/react/Metadata/helpers/specs/formater.spec.js @@ -166,8 +166,8 @@ describe('metadata formater', () => { ]); }); - describe('Inherit relationships', () => { - it('should process inherit relationship types', () => { + describe('Inherit ', () => { + it('should process inherit types', () => { assessBasicProperties(relationship3, ['Relationship 3', 'text', 'template2']); expect(relationship3.value.length).toBe(3); assessMultiValues(relationship3, [{ value: 'how' }, { value: 'are' }, { value: 'you?' }]); diff --git a/app/shared/types/commonSchemas.ts b/app/shared/types/commonSchemas.ts index 76bcdfe4da..a989694243 100644 --- a/app/shared/types/commonSchemas.ts +++ b/app/shared/types/commonSchemas.ts @@ -102,6 +102,8 @@ export const metadataObjectSchema = { suggestion_confidence: { type: 'number' }, suggestion_model: { type: 'string' }, provenance: { type: 'string', enum: Object.values(provenanceTypes) }, + inheritedValue: propertyValueSchema, + inheritedType: { type: 'string' }, }, }; diff --git a/app/shared/types/commonTypes.d.ts b/app/shared/types/commonTypes.d.ts index d29eef9e06..348a77eb5a 100644 --- a/app/shared/types/commonTypes.d.ts +++ b/app/shared/types/commonTypes.d.ts @@ -69,6 +69,8 @@ export interface MetadataObjectSchema { suggestion_confidence?: number; suggestion_model?: string; provenance?: '' | 'BULK_ACCEPT'; + inheritedValue?: PropertyValueSchema; + inheritedType?: string; [k: string]: unknown | undefined; } diff --git a/app/shared/types/connectionType.d.ts b/app/shared/types/connectionType.d.ts index d0d8fcb928..c43a1e3171 100644 --- a/app/shared/types/connectionType.d.ts +++ b/app/shared/types/connectionType.d.ts @@ -58,6 +58,30 @@ export interface ConnectionSchema { suggestion_confidence?: number; suggestion_model?: string; provenance?: '' | 'BULK_ACCEPT'; + inheritedValue?: + | null + | string + | number + | boolean + | { + label?: string | null; + url?: string | null; + } + | { + from?: number | null; + to?: number | null; + } + | { + label?: string; + lat: number; + lon: number; + } + | { + label?: string; + lat: number; + lon: number; + }[]; + inheritedType?: string; [k: string]: unknown | undefined; }[] | undefined; @@ -92,6 +116,30 @@ export interface ConnectionSchema { suggestion_confidence?: number; suggestion_model?: string; provenance?: '' | 'BULK_ACCEPT'; + inheritedValue?: + | null + | string + | number + | boolean + | { + label?: string | null; + url?: string | null; + } + | { + from?: number | null; + to?: number | null; + } + | { + label?: string; + lat: number; + lon: number; + } + | { + label?: string; + lat: number; + lon: number; + }[]; + inheritedType?: string; [k: string]: unknown | undefined; }[] | undefined; diff --git a/app/shared/types/entityType.d.ts b/app/shared/types/entityType.d.ts index 06c94bde5c..4cee764525 100644 --- a/app/shared/types/entityType.d.ts +++ b/app/shared/types/entityType.d.ts @@ -34,6 +34,7 @@ export type EntityWithFilesSchema = { title?: string; template?: ObjectIdSchema; published?: boolean; + generatedToc?: boolean; icon?: { _id?: string | null; label?: string; From 7133a42fd2315c66303ca27fe1450b7c6e39f580 Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Fri, 16 Apr 2021 15:09:58 +0200 Subject: [PATCH 15/61] removed focus test --- app/api/entities/specs/entities.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/entities/specs/entities.spec.js b/app/api/entities/specs/entities.spec.js index 564be775ca..99a2410495 100644 --- a/app/api/entities/specs/entities.spec.js +++ b/app/api/entities/specs/entities.spec.js @@ -731,7 +731,7 @@ describe('entities', () => { expect(denormalized.metadata.friends[0].label).toBe('shared2title'); }); - fit('should denormalize inherited metadata', async () => { + it('should denormalize inherited metadata', async () => { const entity = (await entities.get({ sharedId: 'shared', language: 'en' }))[0]; const denormalized = await entities.denormalize(entity, { user: 'dummy', language: 'en' }); From 764a3cad23c27a93027f060ba8e7ddd1773f2292 Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Mon, 19 Apr 2021 10:10:54 +0200 Subject: [PATCH 16/61] fixed entity schema --- app/api/entities/specs/entities.spec.js | 2 +- app/api/entities/specs/fixtures.js | 2 +- app/shared/types/commonSchemas.ts | 2 +- app/shared/types/commonTypes.d.ts | 4 +- app/shared/types/connectionType.d.ts | 52 +++---------------------- 5 files changed, 12 insertions(+), 50 deletions(-) diff --git a/app/api/entities/specs/entities.spec.js b/app/api/entities/specs/entities.spec.js index 99a2410495..7947aa9af9 100644 --- a/app/api/entities/specs/entities.spec.js +++ b/app/api/entities/specs/entities.spec.js @@ -736,7 +736,7 @@ describe('entities', () => { const denormalized = await entities.denormalize(entity, { user: 'dummy', language: 'en' }); expect(denormalized.metadata.enemies[0].inheritedValue).toEqual([ - { value: 'something to b e inherited' }, + { value: 'something to be inherited' }, ]); expect(denormalized.metadata.enemies[0].inheritedType).toBe('text'); }); diff --git a/app/api/entities/specs/fixtures.js b/app/api/entities/specs/fixtures.js index d291eb1266..6c7aa1903e 100644 --- a/app/api/entities/specs/fixtures.js +++ b/app/api/entities/specs/fixtures.js @@ -314,7 +314,7 @@ export default { language: 'en', title: 'shared2title', metadata: { - property1: [{ value: 'something to b e inherited' }], + property1: [{ value: 'something to be inherited' }], }, }, { sharedId: 'source2', language: 'en' }, diff --git a/app/shared/types/commonSchemas.ts b/app/shared/types/commonSchemas.ts index a989694243..50ebc60640 100644 --- a/app/shared/types/commonSchemas.ts +++ b/app/shared/types/commonSchemas.ts @@ -102,7 +102,7 @@ export const metadataObjectSchema = { suggestion_confidence: { type: 'number' }, suggestion_model: { type: 'string' }, provenance: { type: 'string', enum: Object.values(provenanceTypes) }, - inheritedValue: propertyValueSchema, + inheritedValue: { value: propertyValueSchema }, inheritedType: { type: 'string' }, }, }; diff --git a/app/shared/types/commonTypes.d.ts b/app/shared/types/commonTypes.d.ts index 348a77eb5a..7efdea0208 100644 --- a/app/shared/types/commonTypes.d.ts +++ b/app/shared/types/commonTypes.d.ts @@ -69,7 +69,9 @@ export interface MetadataObjectSchema { suggestion_confidence?: number; suggestion_model?: string; provenance?: '' | 'BULK_ACCEPT'; - inheritedValue?: PropertyValueSchema; + inheritedValue?: { + [k: string]: unknown | undefined; + }; inheritedType?: string; [k: string]: unknown | undefined; } diff --git a/app/shared/types/connectionType.d.ts b/app/shared/types/connectionType.d.ts index c43a1e3171..560a165572 100644 --- a/app/shared/types/connectionType.d.ts +++ b/app/shared/types/connectionType.d.ts @@ -58,29 +58,9 @@ export interface ConnectionSchema { suggestion_confidence?: number; suggestion_model?: string; provenance?: '' | 'BULK_ACCEPT'; - inheritedValue?: - | null - | string - | number - | boolean - | { - label?: string | null; - url?: string | null; - } - | { - from?: number | null; - to?: number | null; - } - | { - label?: string; - lat: number; - lon: number; - } - | { - label?: string; - lat: number; - lon: number; - }[]; + inheritedValue?: { + [k: string]: unknown | undefined; + }; inheritedType?: string; [k: string]: unknown | undefined; }[] @@ -116,29 +96,9 @@ export interface ConnectionSchema { suggestion_confidence?: number; suggestion_model?: string; provenance?: '' | 'BULK_ACCEPT'; - inheritedValue?: - | null - | string - | number - | boolean - | { - label?: string | null; - url?: string | null; - } - | { - from?: number | null; - to?: number | null; - } - | { - label?: string; - lat: number; - lon: number; - } - | { - label?: string; - lat: number; - lon: number; - }[]; + inheritedValue?: { + [k: string]: unknown | undefined; + }; inheritedType?: string; [k: string]: unknown | undefined; }[] From 13e19ce7ec21fd22c89ffb1d7ac5101da27607ca Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Mon, 19 Apr 2021 13:29:28 +0300 Subject: [PATCH 17/61] Removed comments --- nightmare/helpers/selectors.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nightmare/helpers/selectors.js b/nightmare/helpers/selectors.js index 51f1cd8f0b..eb25fb7704 100644 --- a/nightmare/helpers/selectors.js +++ b/nightmare/helpers/selectors.js @@ -161,7 +161,7 @@ export default { documentAfterLoadMore: '#app > div.content > div > div > div > main > div > div > div.item-group > div:nth-child(31)', superVillianType: - '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div > ul > li:nth-child(2) > label', //.documentTypes-selector.nested-selector + '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div > ul > li:nth-child(2) > label', minorVillianType: '#app > div.content > div > div > div > aside.side-panel.library-filters > div.sidepanel-body > div > ul > li:nth-child(5) > label', resetFilters: @@ -286,7 +286,6 @@ export default { '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(2) > a', libraryNavButton: '#app > div.content > header > ul > li.menuActions > ul.menuNav-list > li:nth-child(1) > a', - // '#app > div.content > header > ul > li.menuActions > ul > li:nth-child(1) > a', settingsNavButton: '#app > div.content > header > ul > li.menuActions > ul.menuNav-list > li:nth-child(3) > a', spanish: From 931b9be911d80fd6b38328e805552c4bd48b177e Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Mon, 19 Apr 2021 15:42:24 +0200 Subject: [PATCH 18/61] Added migration --- .../38-denormalize-inherited/index.js | 73 +++++++++++++++++++ .../specs/38-denormalize-inherited.spec.js | 35 +++++++++ .../specs/fixtures.js | 52 +++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 app/api/migrations/migrations/38-denormalize-inherited/index.js create mode 100644 app/api/migrations/migrations/38-denormalize-inherited/specs/38-denormalize-inherited.spec.js create mode 100644 app/api/migrations/migrations/38-denormalize-inherited/specs/fixtures.js diff --git a/app/api/migrations/migrations/38-denormalize-inherited/index.js b/app/api/migrations/migrations/38-denormalize-inherited/index.js new file mode 100644 index 0000000000..b081452451 --- /dev/null +++ b/app/api/migrations/migrations/38-denormalize-inherited/index.js @@ -0,0 +1,73 @@ +/* eslint-disable no-await-in-loop */ +export default { + delta: 38, + + name: 'denormalize-inherited', + + description: 'Denormalize inherited metadata', + + async up(db) { + const cursor = db.collection('entities').find({}); + const templates = await db + .collection('templates') + .find({}) + .toArray(); + + let index = 1; + + while (await cursor.hasNext()) { + const entity = await cursor.next(); + + if (!entity.template) { + return; + } + + const template = templates.find(t => t._id.toString() === entity.template.toString()); + + await Promise.all( + template.properties.map(async prop => { + if (prop.type === 'relationship') { + const value = entity.metadata[prop.name] || []; + const denormalizedValue = await Promise.all( + value.map(async _elem => { + const elem = { ..._elem }; + const [partner] = await db + .collection('entities') + .find({ + sharedId: elem.value, + language: entity.language, + }) + .toArray(); + + if (prop.inherit && partner) { + const partnerTemplate = templates.find( + t => t._id.toString() === partner.template.toString() + ); + + const inheritedProperty = partnerTemplate.properties.find( + p => p._id && p._id.toString() === prop.inheritProperty.toString() + ); + + elem.inheritedValue = partner.metadata[inheritedProperty.name]; + elem.inheritedType = inheritedProperty.type; + return elem; + } + }) + ); + + entity.metadata[prop.name] = denormalizedValue; + } + }) + ); + + await db + .collection('entities') + .updateOne({ _id: entity._id }, { $set: { metadata: entity.metadata } }); + + process.stdout.write(`-> processed: ${index} \r`); + index += 1; + } + + process.stdout.write('\r\n'); + }, +}; diff --git a/app/api/migrations/migrations/38-denormalize-inherited/specs/38-denormalize-inherited.spec.js b/app/api/migrations/migrations/38-denormalize-inherited/specs/38-denormalize-inherited.spec.js new file mode 100644 index 0000000000..2739ddd477 --- /dev/null +++ b/app/api/migrations/migrations/38-denormalize-inherited/specs/38-denormalize-inherited.spec.js @@ -0,0 +1,35 @@ +import testingDB from 'api/utils/testing_db'; +import migration from '../index.js'; +import fixtures from './fixtures.js'; + +describe('migration denormalize-inherited', () => { + beforeEach(async () => { + spyOn(process.stdout, 'write'); + await testingDB.clearAllAndLoad(fixtures); + }); + + afterAll(async () => { + await testingDB.disconnect(); + }); + + it('should have a delta number', () => { + expect(migration.delta).toBe(38); + }); + + it('should fail', async () => { + await migration.up(testingDB.mongodb); + const [denormalizedEntity] = await testingDB.mongodb + .collection('entities') + .find({ title: 'test_doc' }) + .toArray(); + + expect(denormalizedEntity.metadata.friend).toEqual([ + { + inheritedType: 'text', + inheritedValue: [{ value: 'Bocata Tun' }], + label: 'test_doc 2', + value: '456DEF', + }, + ]); + }); +}); diff --git a/app/api/migrations/migrations/38-denormalize-inherited/specs/fixtures.js b/app/api/migrations/migrations/38-denormalize-inherited/specs/fixtures.js new file mode 100644 index 0000000000..1b80bd43c0 --- /dev/null +++ b/app/api/migrations/migrations/38-denormalize-inherited/specs/fixtures.js @@ -0,0 +1,52 @@ +import db from 'api/utils/testing_db'; +const templateId = db.id(); +const templateId2 = db.id(); +const inheritPropertyId = db.id(); +export default { + entities: [ + { + template: templateId, + title: 'test_doc', + sharedId: '123ABC', + metadata: { friend: [{ value: '456DEF', label: 'test_doc 2' }] }, + language: 'en', + }, + { + template: templateId2, + title: 'test_doc 2', + sharedId: '456DEF', + metadata: { name: [{ value: 'Bocata Tun' }] }, + language: 'en', + }, + { + title: 'Im gona break everything', + }, + { + title: 'Try to break it harder', + template: 'whats a template?', + }, + { + title: 'There is only zull', + template: templateId, + }, + ], + templates: [ + { + _id: templateId, + properties: [ + { + type: 'relationship', + relationType: 'something', + inherit: true, + content: templateId2, + inheritProperty: inheritPropertyId, + name: 'friend', + }, + ], + }, + { + _id: templateId2, + properties: [{ _id: inheritPropertyId, type: 'text', name: 'name' }], + }, + ], +}; From 97c4879075526dc3c3424ca3581638a81bde4d02 Mon Sep 17 00:00:00 2001 From: Santiago Date: Mon, 19 Apr 2021 16:35:59 -0300 Subject: [PATCH 19/61] Migrated test to puppeteer --- e2e/suites/navlinks.test.ts | 48 +++++++++++++++++++++++++++++ nightmare/suite1/navlinks.spec.js | 51 ------------------------------- 2 files changed, 48 insertions(+), 51 deletions(-) create mode 100644 e2e/suites/navlinks.test.ts delete mode 100644 nightmare/suite1/navlinks.spec.js diff --git a/e2e/suites/navlinks.test.ts b/e2e/suites/navlinks.test.ts new file mode 100644 index 0000000000..e4c0776634 --- /dev/null +++ b/e2e/suites/navlinks.test.ts @@ -0,0 +1,48 @@ +import proxyMock from '../helpers/proxyMock'; +import insertFixtures from '../helpers/insertFixtures'; +import { adminLogin, logout } from '../helpers/login'; + +const navLink1 = '.menuItems > ul:nth-child(1) > li:nth-child(1) > a:nth-child(1)'; +const navLink2 = '.menuItems > ul:nth-child(1) > li:nth-child(2) > a:nth-child(1)'; + +describe('navlinks', () => { + beforeAll(async () => { + await insertFixtures(); + await proxyMock(); + await adminLogin(); + }); + + it('should create an item menu', async () => { + await expect(page).toClick('a', { text: 'Account settings' }); + await expect(page).toClick('a', { text: 'Menu' }); + await expect(page).toClick('a', { text: 'Add link' }); + await expect(page).toFill('input[name="settings.navlinksData.links[0].title"]', 'NavLink1'); + await expect(page).toFill('input[name="settings.navlinksData.links[0].url"]', '/some_url1'); + await expect(page).toClick('a', { text: 'Add link' }); + await expect(page).toFill('input[name="settings.navlinksData.links[1].title"]', 'NavLink2'); + await expect(page).toFill('input[name="settings.navlinksData.links[1].url"]', '/some_url2'); + await expect(page).toClick('button', { text: 'Save' }); + }); + + it('should render the menus on the header', async () => { + await expect(page).toClick('a', { text: 'Public documents' }); + await expect(page).toMatchElement(navLink1, { text: 'NavLink1' }); + await expect(page).toMatchElement(navLink2, { text: 'NavLink2' }); + + const href1 = await page.$eval(navLink1, a => a.getAttribute('href')); + const href2 = await page.$eval(navLink2, a => a.getAttribute('href')); + expect(href1).toBe('/en/some_url1'); + expect(href2).toBe('/en/some_url2'); + }); + + it('should load the form with the values previously saved', async () => { + await expect(page).toClick('a', { text: 'Account settings' }); + await expect(page).toClick('a', { text: 'Menu' }); + await expect(page).toMatchElement('span', { text: 'NavLink1' }); + await expect(page).toMatchElement('span', { text: 'NavLink2' }); + }); + + afterAll(async () => { + await logout(); + }); +}); diff --git a/nightmare/suite1/navlinks.spec.js b/nightmare/suite1/navlinks.spec.js deleted file mode 100644 index b441bb6b37..0000000000 --- a/nightmare/suite1/navlinks.spec.js +++ /dev/null @@ -1,51 +0,0 @@ -import createNightmare from '../helpers/nightmare'; -import insertFixtures from '../helpers/insertFixtures'; -import selectors from '../helpers/selectors.js'; - -import '../helpers/navlinksDSL.js'; - -const nightmare = createNightmare(); - -describe('navlinks', () => { - beforeAll(async () => insertFixtures()); - afterAll(async () => nightmare.end()); - - it('should log in as admin', async () => - nightmare - .login('admin', 'admin') - .waitToClick(selectors.navigation.settingsNavButton) - .wait(selectors.settingsView.settingsHeader) - ); - - it('should create an item menu', async () => - nightmare - .clickLink('Menu') - .navlinks.add('label', 'url') - .navlinks.add('label2', 'url2') - .navlinks.save() - ); - - it('should render the menus on the header', async () => { - const menus = await nightmare.navlinks.getMenusJSON(); - - expect(menus).toEqual([ - { label: 'label', url: 'http://localhost:3000/en/url' }, - { label: 'label2', url: 'http://localhost:3000/en/url2' }, - ]); - }); - - it('should load the form with the values previously saved', async () => { - await nightmare - .goto('http://localhost:3000/en/settings') - .clickLink('Menu') - .wait('.propery-form') - .clickLink('Edit'); - - const formData = await nightmare.navlinks.getFormJSON(); - - expect(formData).toEqual([ - { label: 'label', url: 'url' }, - { label: 'label2', url: 'url2' }, - ]); - }); -}); From 48c1b2301da596fe22ee78f261e7bca3699919a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Apr 2021 21:18:55 +0000 Subject: [PATCH 20/61] Bump ssri from 6.0.1 to 6.0.2 Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/npm/ssri/releases) - [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md) - [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2) Signed-off-by: dependabot[bot] --- yarn.lock | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index e466648f41..f46c3356e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6163,8 +6163,9 @@ fetch-mock@^9.10.7: whatwg-url "^6.5.0" figgy-pudding@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== figures@^3.0.0: version "3.2.0" @@ -13549,8 +13550,9 @@ ssim.js@^3.1.1: integrity sha512-/AcvEnpIxwh1+t4HNRE9lg+Ka8MIsUPXsXeQjzd5IQjs1DcphrlPHKciWdZRnHAQoQIbLFzXJ+5KruYeH7oXjw== ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== dependencies: figgy-pudding "^3.5.1" From 8741d0a0e5d746ae4a7e6ff55594a8f6b295d0da Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Tue, 20 Apr 2021 01:18:09 +0200 Subject: [PATCH 21/61] Denormalize Inherited now updates other entities when metadata changes --- app/api/entities/entities.js | 18 ++++++++++++++---- app/api/entities/specs/entities.spec.js | 2 +- app/react/Metadata/helpers/formater.js | 3 ++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/api/entities/entities.js b/app/api/entities/entities.js index dbd71ce813..15352b7e00 100644 --- a/app/api/entities/entities.js +++ b/app/api/entities/entities.js @@ -139,6 +139,7 @@ async function updateEntity(entity, _template) { ) { await this.renameRelatedEntityInMetadata({ ...currentDoc, ...entity }); } + const toSave = { ...entity }; if (entity.metadata) { toSave.metadata = await denormalizeMetadata(entity.metadata, entity, template); @@ -336,6 +337,7 @@ export default { const [entity] = await this.getWithRelationships({ sharedId, language }); if (updateRelationships) { await relationships.saveEntityBasedReferences(entity, language); + await this.updateDenormalizedMetadataInRelatedEntities(entity); } if (index) { await search.indexEntities({ sharedId }, '+fullText'); @@ -344,6 +346,12 @@ export default { return entity; }, + async updateDenormalizedMetadataInRelatedEntities(entity) { + const related = await relationships.getByDocument(entity.sharedId, entity.language); + const sharedIds = related.map(r => r.entityData.sharedId); + await this.updateMetdataFromRelationships(sharedIds, entity.language); + }, + async denormalize(_doc, { user, language }) { await validateEntity(_doc); const doc = _doc; @@ -515,10 +523,12 @@ export default { (!property.content || r.entityData.template.toString() === property.content) ); - entity.metadata[property.name] = relationshipsGoingToThisProperty.map(r => ({ - value: r.entity, - label: r.entityData.title, - })); + entity.metadata[property.name] = relationshipsGoingToThisProperty.map(r => { + return { + value: r.entity, + label: r.entityData.title, + }; + }); }); if (relationshipProperties.length) { entitiesToReindex.push(entity.sharedId); diff --git a/app/api/entities/specs/entities.spec.js b/app/api/entities/specs/entities.spec.js index 7947aa9af9..2db33f5004 100644 --- a/app/api/entities/specs/entities.spec.js +++ b/app/api/entities/specs/entities.spec.js @@ -511,7 +511,7 @@ describe('entities', () => { }; const user = { _id: db.id() }; - await entities.save(doc, { user, language: 'es' }); + await entities.save(doc, { user, language: 'es' }, false); await new Promise(resolve => setTimeout(resolve, 3000)); expect(entities.updateMetdataFromRelationships).not.toHaveBeenCalled(); }); diff --git a/app/react/Metadata/helpers/formater.js b/app/react/Metadata/helpers/formater.js index 5395ef94e8..10f6061f5d 100644 --- a/app/react/Metadata/helpers/formater.js +++ b/app/react/Metadata/helpers/formater.js @@ -92,10 +92,11 @@ export default { getSelectOptions(option, thesauri) { let value = ''; - const { icon } = option; + let icon; if (option) { value = option.label || option.value; + icon = option.icon; } let url; From 3b1c522ad2bc1fe70237a7684c61e73330758c8e Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Tue, 20 Apr 2021 01:34:41 +0200 Subject: [PATCH 22/61] fixed issue when inheriting empty values --- app/react/Metadata/helpers/formater.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/app/react/Metadata/helpers/formater.js b/app/react/Metadata/helpers/formater.js index 10f6061f5d..a4edcc18ed 100644 --- a/app/react/Metadata/helpers/formater.js +++ b/app/react/Metadata/helpers/formater.js @@ -202,14 +202,19 @@ export default { const type = inheritedProperty.get('type'); const methodType = this[type] ? type : 'default'; - let value = propValue.map(v => { - if (v.inheritedValue) { - return this[methodType](inheritedProperty, v.inheritedValue, thesauris, options, templates); - } - - return { value: v.inheritedValue }; - }); - + let value = propValue + .map(v => { + if (v && v.inheritedValue) { + return this[methodType]( + inheritedProperty, + v.inheritedValue, + thesauris, + options, + templates + ); + } + }) + .filter(v => v); let propType = 'inherit'; if (['multidate', 'multidaterange', 'multiselect', 'geolocation'].includes(type)) { const templateThesauris = thesauris.find( From c77a664081926283108d745b1a12a9de0ae6af16 Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Tue, 20 Apr 2021 10:00:52 +0200 Subject: [PATCH 23/61] fixed migration error when inherting from empty values --- app/api/migrations/migrations/38-denormalize-inherited/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/migrations/migrations/38-denormalize-inherited/index.js b/app/api/migrations/migrations/38-denormalize-inherited/index.js index b081452451..4b62771b35 100644 --- a/app/api/migrations/migrations/38-denormalize-inherited/index.js +++ b/app/api/migrations/migrations/38-denormalize-inherited/index.js @@ -55,7 +55,7 @@ export default { }) ); - entity.metadata[prop.name] = denormalizedValue; + entity.metadata[prop.name] = denormalizedValue.filter(v => v); } }) ); From 6c86552b06e55bcd68bee4296195173c0a8f10b0 Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Tue, 20 Apr 2021 10:14:49 +0200 Subject: [PATCH 24/61] fixed issue with migration --- app/api/migrations/migrations/38-denormalize-inherited/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/migrations/migrations/38-denormalize-inherited/index.js b/app/api/migrations/migrations/38-denormalize-inherited/index.js index 4b62771b35..dc4ac65ba5 100644 --- a/app/api/migrations/migrations/38-denormalize-inherited/index.js +++ b/app/api/migrations/migrations/38-denormalize-inherited/index.js @@ -50,8 +50,8 @@ export default { elem.inheritedValue = partner.metadata[inheritedProperty.name]; elem.inheritedType = inheritedProperty.type; - return elem; } + return elem; }) ); From 3fbb282adf02ea47d76de0e46cc285943fd9067e Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Tue, 20 Apr 2021 12:19:54 +0200 Subject: [PATCH 25/61] minor refactor --- app/api/entities/entities.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/api/entities/entities.js b/app/api/entities/entities.js index 15352b7e00..d6ffdaede5 100644 --- a/app/api/entities/entities.js +++ b/app/api/entities/entities.js @@ -523,12 +523,10 @@ export default { (!property.content || r.entityData.template.toString() === property.content) ); - entity.metadata[property.name] = relationshipsGoingToThisProperty.map(r => { - return { - value: r.entity, - label: r.entityData.title, - }; - }); + entity.metadata[property.name] = relationshipsGoingToThisProperty.map(r => ({ + value: r.entity, + label: r.entityData.title, + })); }); if (relationshipProperties.length) { entitiesToReindex.push(entity.sharedId); From 985288f22024d332678bf560e0ce116bdf16e4a1 Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Tue, 20 Apr 2021 12:20:34 +0200 Subject: [PATCH 26/61] added more scenarios to the migration specs --- .../38-denormalize-inherited/index.js | 2 +- .../specs/38-denormalize-inherited.spec.js | 22 ++++++++++++- .../specs/fixtures.js | 31 ++++++++++++++++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/app/api/migrations/migrations/38-denormalize-inherited/index.js b/app/api/migrations/migrations/38-denormalize-inherited/index.js index dc4ac65ba5..1d791afadb 100644 --- a/app/api/migrations/migrations/38-denormalize-inherited/index.js +++ b/app/api/migrations/migrations/38-denormalize-inherited/index.js @@ -48,7 +48,7 @@ export default { p => p._id && p._id.toString() === prop.inheritProperty.toString() ); - elem.inheritedValue = partner.metadata[inheritedProperty.name]; + elem.inheritedValue = partner.metadata[inheritedProperty.name] || []; elem.inheritedType = inheritedProperty.type; } return elem; diff --git a/app/api/migrations/migrations/38-denormalize-inherited/specs/38-denormalize-inherited.spec.js b/app/api/migrations/migrations/38-denormalize-inherited/specs/38-denormalize-inherited.spec.js index 2739ddd477..f3346c1b46 100644 --- a/app/api/migrations/migrations/38-denormalize-inherited/specs/38-denormalize-inherited.spec.js +++ b/app/api/migrations/migrations/38-denormalize-inherited/specs/38-denormalize-inherited.spec.js @@ -16,7 +16,7 @@ describe('migration denormalize-inherited', () => { expect(migration.delta).toBe(38); }); - it('should fail', async () => { + it('should denormalize inherited data', async () => { await migration.up(testingDB.mongodb); const [denormalizedEntity] = await testingDB.mongodb .collection('entities') @@ -30,6 +30,26 @@ describe('migration denormalize-inherited', () => { label: 'test_doc 2', value: '456DEF', }, + { + inheritedType: 'text', + inheritedValue: [], + label: 'test_doc 3', + value: '789ZXY', + }, + ]); + + const [denormalizedEntityWithoutValues] = await testingDB.mongodb + .collection('entities') + .find({ title: 'test_doc 4' }) + .toArray(); + + expect(denormalizedEntityWithoutValues.metadata.friend).toEqual([ + { + inheritedType: 'text', + inheritedValue: [], + label: 'test_doc 5', + value: '789ABC', + }, ]); }); }); diff --git a/app/api/migrations/migrations/38-denormalize-inherited/specs/fixtures.js b/app/api/migrations/migrations/38-denormalize-inherited/specs/fixtures.js index 1b80bd43c0..386e5c64a7 100644 --- a/app/api/migrations/migrations/38-denormalize-inherited/specs/fixtures.js +++ b/app/api/migrations/migrations/38-denormalize-inherited/specs/fixtures.js @@ -8,9 +8,15 @@ export default { template: templateId, title: 'test_doc', sharedId: '123ABC', - metadata: { friend: [{ value: '456DEF', label: 'test_doc 2' }] }, + metadata: { + friend: [ + { value: '456DEF', label: 'test_doc 2' }, + { value: '789ZXY', label: 'test_doc 3' }, + ], + }, language: 'en', }, + { template: templateId2, title: 'test_doc 2', @@ -18,6 +24,29 @@ export default { metadata: { name: [{ value: 'Bocata Tun' }] }, language: 'en', }, + { + template: templateId2, + title: 'test_doc 3', + sharedId: '789ZXY', + metadata: { name: [] }, + language: 'en', + }, + { + template: templateId, + title: 'test_doc 4', + sharedId: '498ABC', + metadata: { + friend: [{ value: '789ABC', label: 'test_doc 5' }], + }, + language: 'en', + }, + { + template: templateId2, + title: 'test_doc 5', + sharedId: '789ABC', + metadata: {}, + language: 'en', + }, { title: 'Im gona break everything', }, From 38d815ff45e9da5ebd78c7e7444b3d8eb9615f95 Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Tue, 20 Apr 2021 12:58:32 +0200 Subject: [PATCH 27/61] fixed scenario for migration when the entity may not have metadata --- .../38-denormalize-inherited/index.js | 78 +++++++++---------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/app/api/migrations/migrations/38-denormalize-inherited/index.js b/app/api/migrations/migrations/38-denormalize-inherited/index.js index 1d791afadb..c7091e8063 100644 --- a/app/api/migrations/migrations/38-denormalize-inherited/index.js +++ b/app/api/migrations/migrations/38-denormalize-inherited/index.js @@ -17,53 +17,49 @@ export default { while (await cursor.hasNext()) { const entity = await cursor.next(); + if (entity.template && entity.metadata) { + const template = templates.find(t => t._id.toString() === entity.template.toString()); - if (!entity.template) { - return; - } - - const template = templates.find(t => t._id.toString() === entity.template.toString()); - - await Promise.all( - template.properties.map(async prop => { - if (prop.type === 'relationship') { - const value = entity.metadata[prop.name] || []; - const denormalizedValue = await Promise.all( - value.map(async _elem => { - const elem = { ..._elem }; - const [partner] = await db - .collection('entities') - .find({ - sharedId: elem.value, - language: entity.language, - }) - .toArray(); + await Promise.all( + template.properties.map(async prop => { + if (prop.type === 'relationship') { + const value = entity.metadata[prop.name] || []; + const denormalizedValue = await Promise.all( + value.map(async _elem => { + const elem = { ..._elem }; + const [partner] = await db + .collection('entities') + .find({ + sharedId: elem.value, + language: entity.language, + }) + .toArray(); - if (prop.inherit && partner) { - const partnerTemplate = templates.find( - t => t._id.toString() === partner.template.toString() - ); + if (prop.inherit && partner) { + const partnerTemplate = templates.find( + t => t._id.toString() === partner.template.toString() + ); - const inheritedProperty = partnerTemplate.properties.find( - p => p._id && p._id.toString() === prop.inheritProperty.toString() - ); + const inheritedProperty = partnerTemplate.properties.find( + p => p._id && p._id.toString() === prop.inheritProperty.toString() + ); - elem.inheritedValue = partner.metadata[inheritedProperty.name] || []; - elem.inheritedType = inheritedProperty.type; - } - return elem; - }) - ); + elem.inheritedValue = partner.metadata[inheritedProperty.name] || []; + elem.inheritedType = inheritedProperty.type; + } + return elem; + }) + ); - entity.metadata[prop.name] = denormalizedValue.filter(v => v); - } - }) - ); - - await db - .collection('entities') - .updateOne({ _id: entity._id }, { $set: { metadata: entity.metadata } }); + entity.metadata[prop.name] = denormalizedValue.filter(v => v); + } + }) + ); + await db + .collection('entities') + .updateOne({ _id: entity._id }, { $set: { metadata: entity.metadata } }); + } process.stdout.write(`-> processed: ${index} \r`); index += 1; } From a1c04836fd0d5c1ee09e2b136ee0e781efa1746d Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Tue, 20 Apr 2021 16:48:44 +0300 Subject: [PATCH 28/61] Updated indentation --- app/react/App/scss/layout/_sidepanel.scss | 34 +++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/app/react/App/scss/layout/_sidepanel.scss b/app/react/App/scss/layout/_sidepanel.scss index 93e0cfd626..d0dc428666 100644 --- a/app/react/App/scss/layout/_sidepanel.scss +++ b/app/react/App/scss/layout/_sidepanel.scss @@ -309,26 +309,26 @@ $c-sidebar: $c-white; div:nth-child(2) { width: 35% } - .filter-buttons { - - .clear-button { - text-decoration: none; - letter-spacing: normal; - font-weight: normal; - display: inline; - text-transform: capitalize; - border: 1px solid rgb(204, 204, 204); - padding: 3px; - cursor: pointer; - border-radius: 2px; - } + .filter-buttons { + + .clear-button { + text-decoration: none; + letter-spacing: normal; + font-weight: normal; + display: inline; + text-transform: capitalize; + border: 1px solid rgb(204, 204, 204); + padding: 3px; + cursor: pointer; + border-radius: 2px; + } - @media(min-width: 1020px) { - .push-right { - margin-left: 30px; - } + @media(min-width: 1020px) { + .push-right { + margin-left: 30px; } } + } } .item.readOnly { From 6aaf04172cb6deb88d1ffca3a4f746cf11a0a674 Mon Sep 17 00:00:00 2001 From: Santiago Date: Mon, 19 Apr 2021 14:42:47 -0300 Subject: [PATCH 29/61] Updated icon in sidepanel --- app/react/Metadata/components/MetadataFormButtons.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/react/Metadata/components/MetadataFormButtons.js b/app/react/Metadata/components/MetadataFormButtons.js index 3dda8bbc11..7b07b2700b 100644 --- a/app/react/Metadata/components/MetadataFormButtons.js +++ b/app/react/Metadata/components/MetadataFormButtons.js @@ -107,7 +107,7 @@ export class MetadataFormButtons extends Component { className="btn btn-success copy-from-btn" onClick={this.props.copyFrom} > - + Copy From From 2c5bf7d1b394f0f62c871dabfca0e0180717c163 Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Fri, 23 Apr 2021 16:26:12 +0300 Subject: [PATCH 30/61] Added HTML5 drag file upload --- app/react/Markdown/components/PublicForm.js | 83 ++++++++++++++----- .../Markdown/components/scss/public-form.scss | 41 +++++++++ 2 files changed, 103 insertions(+), 21 deletions(-) create mode 100644 app/react/Markdown/components/scss/public-form.scss diff --git a/app/react/Markdown/components/PublicForm.js b/app/react/Markdown/components/PublicForm.js index cec08e2d63..3a2881ff90 100644 --- a/app/react/Markdown/components/PublicForm.js +++ b/app/react/Markdown/components/PublicForm.js @@ -11,7 +11,9 @@ import { Translate } from 'app/I18N'; import { publicSubmit } from 'app/Uploads/actions/uploadsActions'; import { bindActionCreators } from 'redux'; import { FormGroup } from 'app/Forms'; +import { Icon } from 'UI'; import Loader from 'app/components/Elements/Loader'; +import './scss/public-form.scss'; class PublicForm extends Component { static renderTitle(template) { @@ -48,31 +50,33 @@ class PublicForm extends Component { ); } - static renderFileField(id, options) { - const defaults = { className: 'form-control', model: `.${id}` }; - const props = Object.assign(defaults, options); - return ( -
-
    -
  • - -
  • -
-
- ); - } - constructor(props) { super(props); + this.fileDropped = this.fileDropped.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.validators = { captcha: { required: val => val && val.text.length }, ...validator.generate(props.template.toJS()), }; - this.state = { submiting: false }; + this.state = { submiting: false, files: [] }; + } + + fileDropped(ev) { + const fileCache = []; + ev.persist(); + const _files = ev.dataTransfer.items; + ev.preventDefault(); + if (_files) { + for (let i = 0; i < ev.dataTransfer.items.length; i += 1) { + if (ev.dataTransfer.items[i].kind === 'file') { + fileCache.push(ev.dataTransfer.items[i].getAsFile()); + } + } + } else { + ev.dataTransfer.files.forEach(file => fileCache.push(file)); + } + this.state.files.forEach(file => fileCache.push(file)); + this.setState({ files: fileCache }); } attachDispatch(dispatch) { @@ -109,6 +113,45 @@ class PublicForm extends Component { }); } + renderFileField(id, options) { + const defaults = { className: 'form-control', model: `.${id}` }; + const props = Object.assign(defaults, options); + return ( +
+
    +
  • + {id === 'file' ? 'Document' : 'Attachments'} + +
    +
      + {this.state.files.map(file => ( +
    • {file.name}
    • + ))} +
    +
    +
  • +
+
+ ); + } + renderCaptcha() { const { remote } = this.props; return ( @@ -151,9 +194,7 @@ class PublicForm extends Component { {PublicForm.renderTitle(template)} {file ? PublicForm.renderFileField('file', { accept: '.pdf' }) : false} - {attachments - ? PublicForm.renderFileField('attachments', { multiple: 'multiple' }) - : false} + {attachments ? this.renderFileField('attachments', { multiple: 'multiple' }) : false} {this.renderCaptcha()}
diff --git a/app/react/Markdown/components/scss/public-form.scss b/app/react/Markdown/components/scss/public-form.scss new file mode 100644 index 0000000000..6278a6a95d --- /dev/null +++ b/app/react/Markdown/components/scss/public-form.scss @@ -0,0 +1,41 @@ +.attachments-list { + label { + width: 100%; + height: 186px; + border: 1px dashed #AEAEB8; + border-radius: 4px; + + .text-content { + width: 240px; + height: 100%; + text-align: center; + margin-left: 35%; + color: #818181; + + #icon { + font-size: 3em; + color: #ddd; + } + + #upload-button { + #button { + border: 1px solid #818181; + border-radius: 4px; + height: 30px; + width: 70%; + margin-left: 17%; + font-style: normal; + font-weight: normal; + font-size: 12px; + line-height: 14px; + padding-top: 0.5vh; + cursor: pointer; + } + } + } + + input { + display: none + } + } +} \ No newline at end of file From c2daa3b773814919ba1e5cb134e175ea91bb071a Mon Sep 17 00:00:00 2001 From: Federico Nocetti Date: Wed, 21 Apr 2021 15:22:14 -0300 Subject: [PATCH 31/61] GH check for emit-types --- .github/workflows/ci_ts_emit_check.yml | 27 ++++++++++++++++++++ emitSchemaTypes.js | 34 ++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/ci_ts_emit_check.yml diff --git a/.github/workflows/ci_ts_emit_check.yml b/.github/workflows/ci_ts_emit_check.yml new file mode 100644 index 0000000000..36b2436cc0 --- /dev/null +++ b/.github/workflows/ci_ts_emit_check.yml @@ -0,0 +1,27 @@ +name: check-emitted-types + +on: + push: + branches: + - master + - development + - release + pull_request: + +jobs: + check-types: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14.6.x + uses: actions/setup-node@v1 + with: + node-version: '14.6.x' + - name: Cache node modules + uses: actions/cache@v2 + with: + path: ./node_modules + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + - name: install dependencies + run: yarn install + - run: yarn emit-types --check diff --git a/emitSchemaTypes.js b/emitSchemaTypes.js index 46a42d686d..34ae3106b4 100644 --- a/emitSchemaTypes.js +++ b/emitSchemaTypes.js @@ -22,6 +22,8 @@ const customImports = { 'app/shared/types/connectionSchema.ts': ["import { FileType } from 'shared/types/fileType';"], }; +const dryCheck = !!process.argv[2] && process.argv[2] === '--check'; + const firstUp = name => name.charAt(0).toUpperCase() + name.slice(1); const typesFileName = file => file @@ -49,16 +51,38 @@ const typeImports = matches => { }, ''); }; +const checkTypeFile = (file, content) => { + const endProcess = () => { + console.error(`Must emit types: ${file} changed`); + process.exit(1); + }; + + if (fs.existsSync(file)) { + const oldContent = fs.readFileSync(file).toString(); + + if (oldContent !== content) endProcess(); + } else { + endProcess(); + } +}; + const writeTypeFile = (file, commonImport, snippets) => { const goodSnippets = snippets.filter(p => p); if (goodSnippets.length) { const typeFile = typesFileName(file); const customImport = customImports[file] ? `${customImports[file].join('\n')}\n` : ''; - console.log(`Emitting ${goodSnippets.length} types from ${file} to ${typeFile}.`); - fs.writeFileSync( - typeFile, - banner + customImport + commonImport + goodSnippets.reduce((res, s) => `${res}\n${s}`, '') - ); + if (!dryCheck) { + console.log(`Emitting ${goodSnippets.length} types from ${file} to ${typeFile}.`); + } + + const content = + banner + customImport + commonImport + goodSnippets.reduce((res, s) => `${res}\n${s}`, ''); + + if (dryCheck) { + checkTypeFile(typeFile, content); + } else { + fs.writeFileSync(typeFile, content); + } } }; From 8a85cc8532313f5145d62284d6b7f12d0aba3bf1 Mon Sep 17 00:00:00 2001 From: Federico Nocetti Date: Wed, 21 Apr 2021 15:24:32 -0300 Subject: [PATCH 32/61] Change flow name --- .github/workflows/ci_ts_emit_check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_ts_emit_check.yml b/.github/workflows/ci_ts_emit_check.yml index 36b2436cc0..ca6f8b6c1b 100644 --- a/.github/workflows/ci_ts_emit_check.yml +++ b/.github/workflows/ci_ts_emit_check.yml @@ -9,7 +9,7 @@ on: pull_request: jobs: - check-types: + check-emitted-types: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From 434eb2b509a140dcad3c3a7fe9232fd8c81eb76e Mon Sep 17 00:00:00 2001 From: Daneryl Date: Mon, 26 Apr 2021 09:31:40 +0200 Subject: [PATCH 33/61] version 1.29.0-rc1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1dc914987e..50ecdeed51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uwazi", - "version": "1.28.0-rc3", + "version": "1.29.0-rc1", "description": "Uwazi is a free, open-source solution for organising, analysing and publishing your documents.", "keywords": [ "react" From 0d7eb74c82a034db2f71fa363e5522fbc5660c3d Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Mon, 26 Apr 2021 11:01:40 +0200 Subject: [PATCH 34/61] added async validation to the templates to check the thesauri exists --- app/api/entities/specs/entitySchema.spec.ts | 2 +- app/api/templates/specs/fixtures.js | 3 +++ .../templates/specs/templateSchema.spec.ts | 18 ++++++++++--- app/api/templates/specs/templates.spec.js | 15 ++++++++--- app/api/templates/specs/validatorFixtures.js | 25 +++++++++++++++---- app/shared/types/templateSchema.ts | 11 ++++++-- 6 files changed, 58 insertions(+), 16 deletions(-) diff --git a/app/api/entities/specs/entitySchema.spec.ts b/app/api/entities/specs/entitySchema.spec.ts index bf93425612..d4351e03c1 100644 --- a/app/api/entities/specs/entitySchema.spec.ts +++ b/app/api/entities/specs/entitySchema.spec.ts @@ -58,7 +58,7 @@ describe('entity schema', () => { ); }; - it('should allow ObjectId for _id fields', async () => { + fit('should allow ObjectId for _id fields', async () => { const entity = createEntity({ _id: db.id(), user: db.id(), diff --git a/app/api/templates/specs/fixtures.js b/app/api/templates/specs/fixtures.js index 2e65863f44..188e855865 100644 --- a/app/api/templates/specs/fixtures.js +++ b/app/api/templates/specs/fixtures.js @@ -14,6 +14,7 @@ const swapTemplate = db.id(); const relatedTo = db.id(); const templateToBeInherited = db.id(); const propertyToBeInherited = db.id(); +const thesauriId1 = db.id(); export default { templates: [ { @@ -130,6 +131,7 @@ export default { languages: [{ key: 'en', label: 'English', default: true }], }, ], + dictionaries: [{ _id: thesauriId1, name: 'options' }], }; export { @@ -139,4 +141,5 @@ export { swapTemplate, templateToBeInherited, propertyToBeInherited, + thesauriId1, }; diff --git a/app/api/templates/specs/templateSchema.spec.ts b/app/api/templates/specs/templateSchema.spec.ts index 75506f9a55..8cc0414106 100644 --- a/app/api/templates/specs/templateSchema.spec.ts +++ b/app/api/templates/specs/templateSchema.spec.ts @@ -7,6 +7,9 @@ import fixtures, { templateId, templateToBeInherited, propertyToBeInherited, + thesauriId1, + thesauriId2, + thesauriId4, } from './validatorFixtures'; import { safeName } from '../utils'; @@ -127,6 +130,12 @@ describe('template schema', () => { await testInvalid(); }); + it('invalid if select or multiselect property content does not exists', async () => { + template.properties = []; + template.properties.push(makeProperty('foo', 'multiselect', { content: db.id() })); + await testInvalid(); + }); + it('invalid if relationship property does not have a relationtype field', async () => { template.properties = []; template.properties.push(makeProperty('foo', 'relationship', { content: 'content' })); @@ -199,13 +208,13 @@ describe('template schema', () => { name: 'sharedproperty1', label: 'sharedProperty1', type: 'select', - content: 'thesauriId2', + content: thesauriId2.toString(), }, { name: 'sharedproperty2', label: 'sharedProperty2', type: 'select', - content: 'thesauriId1', + content: thesauriId1.toString(), }, { name: 'sharedproperty3', @@ -223,7 +232,7 @@ describe('template schema', () => { name: 'validproperty4', label: 'validProperty4', type: 'select', - content: 'thesauriId4', + content: thesauriId4.toString(), }, { name: 'validpropertydate', @@ -239,7 +248,7 @@ describe('template schema', () => { name: 'validpropertymultiselect', label: 'validPropertyMultiSelect', type: 'multiselect', - content: 'thesauriId4', + content: thesauriId4.toString(), }, { name: 'validpropertymultidate', @@ -267,6 +276,7 @@ describe('template schema', () => { fail('should throw validation error'); } catch (e) { expect(e).toBeInstanceOf(Ajv.ValidationError); + expect(e.errors.length).toBe(4); expect(e).toHaveProperty( 'errors', diff --git a/app/api/templates/specs/templates.spec.js b/app/api/templates/specs/templates.spec.js index 5533f2c98f..7d398783b6 100644 --- a/app/api/templates/specs/templates.spec.js +++ b/app/api/templates/specs/templates.spec.js @@ -18,6 +18,7 @@ import fixtures, { swapTemplate, templateToBeInherited, propertyToBeInherited, + thesauriId1, } from './fixtures.js'; describe('templates', () => { @@ -117,8 +118,8 @@ describe('templates', () => { name: 'changed', commonProperties: [{ name: 'title', label: 'Title', type: 'text' }], properties: [ - { id: '1', type: 'select', content: 'new_thesauri', label: 'select3' }, - { id: '2', type: 'multiselect', content: 'new_thesauri', label: 'multiselect' }, + { id: '1', type: 'select', content: thesauriId1.toString(), label: 'select3' }, + { id: '2', type: 'multiselect', content: thesauriId1.toString(), label: 'multiselect' }, ], }; @@ -142,7 +143,13 @@ describe('templates', () => { commonProperties: [{ name: 'title', label: 'Title', type: 'text' }], properties: [ { id: '1', type: 'text', name: 'text', label: 'Select5' }, - { id: '2', type: 'select', name: 'select5', label: 'Text', content: 'a' }, + { + id: '2', + type: 'select', + name: 'select5', + label: 'Text', + content: thesauriId1.toString(), + }, ], }; @@ -187,7 +194,7 @@ describe('templates', () => { commonProperties: [{ name: 'title', label: 'Title', type: 'text' }], properties: [ { label: 'label 1', type: 'text' }, - { label: 'label 2', type: 'select', content: 's' }, + { label: 'label 2', type: 'select', content: thesauriId1.toString() }, { label: 'label 3', type: 'image' }, { label: 'label 4', name: 'name', type: 'text' }, { label: 'label 5', type: 'geolocation' }, diff --git a/app/api/templates/specs/validatorFixtures.js b/app/api/templates/specs/validatorFixtures.js index 94871a883f..55ef187e2e 100644 --- a/app/api/templates/specs/validatorFixtures.js +++ b/app/api/templates/specs/validatorFixtures.js @@ -5,6 +5,9 @@ const templateId = db.id(); const relatedTo = db.id(); const templateToBeInherited = db.id(); const propertyToBeInherited = db.id(); +const thesauriId1 = db.id(); +const thesauriId2 = db.id(); +const thesauriId4 = db.id(); export default { templates: [ @@ -44,13 +47,13 @@ export default { type: propertyTypes.select, name: 'sharedproperty1', label: 'sharedProperty1', - content: 'thesauriId1', + content: thesauriId1.toString(), }, { type: propertyTypes.select, name: 'sharedproperty2', label: 'sharedProperty2', - content: 'thesauriId2', + content: thesauriId2.toString(), }, { type: propertyTypes.numeric, @@ -68,7 +71,7 @@ export default { name: 'validproperty4', label: 'validProperty4', type: propertyTypes.multiselect, - content: 'thesauriId4', + content: thesauriId4.toString(), }, { name: 'validpropertydate', @@ -89,7 +92,7 @@ export default { name: 'validpropertymultiselect', label: 'validPropertyMultiSelect', type: propertyTypes.select, - content: 'thesauriId4', + content: thesauriId4.toString(), }, { name: 'validpropertymultidate', @@ -106,6 +109,18 @@ export default { }, ], relationtypes: [{ _id: relatedTo, name: 'related to' }], + dictionaries: [ + { _id: thesauriId1, name: 'options' }, + { _id: thesauriId2, name: 'options' }, + { _id: thesauriId4, name: 'options' }, + ], }; -export { templateId, templateToBeInherited, propertyToBeInherited }; +export { + templateId, + templateToBeInherited, + propertyToBeInherited, + thesauriId1, + thesauriId2, + thesauriId4, +}; diff --git a/app/shared/types/templateSchema.ts b/app/shared/types/templateSchema.ts index 3ac9a98c43..c75bf0dcdf 100644 --- a/app/shared/types/templateSchema.ts +++ b/app/shared/types/templateSchema.ts @@ -1,6 +1,7 @@ import Ajv from 'ajv'; import { ObjectId } from 'mongodb'; import model from 'api/templates/templatesModel'; +import { thesauri } from 'api/thesauri/thesauri'; import { ensure, wrapValidator } from 'shared/tsUtils'; import { objectIdSchema, propertySchema } from 'shared/types/commonSchemas'; import { getCompatibleTypes } from 'shared/propertyTypes'; @@ -75,14 +76,20 @@ ajv.addKeyword('uniquePropertyFields', { }); ajv.addKeyword('requireContentForSelectFields', { + async: true, errors: false, type: 'object', - validate(schema: any, data: PropertySchema) { + async validate(schema: any, data: PropertySchema) { if (!schema) { return true; } if (['multiselect', 'select'].includes(data.type)) { - return !!(data.content && data.content.length); + if (!data.content || !data.content.length) { + return false; + } + + const found = await thesauri.getById(data.content); + return !!found; } return true; From 6ee5ddd3e6c8d5cef4007ab3e6352eac3a338b83 Mon Sep 17 00:00:00 2001 From: Alberto Casado Torres Date: Mon, 26 Apr 2021 12:33:53 +0200 Subject: [PATCH 35/61] removed focus test --- app/api/entities/specs/entitySchema.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/entities/specs/entitySchema.spec.ts b/app/api/entities/specs/entitySchema.spec.ts index d4351e03c1..bf93425612 100644 --- a/app/api/entities/specs/entitySchema.spec.ts +++ b/app/api/entities/specs/entitySchema.spec.ts @@ -58,7 +58,7 @@ describe('entity schema', () => { ); }; - fit('should allow ObjectId for _id fields', async () => { + it('should allow ObjectId for _id fields', async () => { const entity = createEntity({ _id: db.id(), user: db.id(), From b46ef8f9ccc143c98becf0ff894be6ac22f71a33 Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Mon, 26 Apr 2021 14:05:57 +0300 Subject: [PATCH 36/61] Styling preview list --- app/react/Markdown/components/PublicForm.js | 72 +++++++++---------- .../Markdown/components/scss/public-form.scss | 33 ++++++++- 2 files changed, 66 insertions(+), 39 deletions(-) diff --git a/app/react/Markdown/components/PublicForm.js b/app/react/Markdown/components/PublicForm.js index 3a2881ff90..3b6ad93529 100644 --- a/app/react/Markdown/components/PublicForm.js +++ b/app/react/Markdown/components/PublicForm.js @@ -14,6 +14,7 @@ import { FormGroup } from 'app/Forms'; import { Icon } from 'UI'; import Loader from 'app/components/Elements/Loader'; import './scss/public-form.scss'; +import Dropzone from 'react-dropzone'; class PublicForm extends Component { static renderTitle(template) { @@ -61,22 +62,13 @@ class PublicForm extends Component { this.state = { submiting: false, files: [] }; } - fileDropped(ev) { - const fileCache = []; - ev.persist(); - const _files = ev.dataTransfer.items; - ev.preventDefault(); - if (_files) { - for (let i = 0; i < ev.dataTransfer.items.length; i += 1) { - if (ev.dataTransfer.items[i].kind === 'file') { - fileCache.push(ev.dataTransfer.items[i].getAsFile()); - } - } - } else { - ev.dataTransfer.files.forEach(file => fileCache.push(file)); - } - this.state.files.forEach(file => fileCache.push(file)); - this.setState({ files: fileCache }); + fileDropped(files) { + console.log(files); + const uploadedFiles = files; + this.state.files.forEach(file => uploadedFiles.push(file)); + this.setState({ + files: uploadedFiles, + }); } attachDispatch(dispatch) { @@ -113,36 +105,40 @@ class PublicForm extends Component { }); } - renderFileField(id, options) { - const defaults = { className: 'form-control', model: `.${id}` }; - const props = Object.assign(defaults, options); + renderFileField(id /*, options */) { + // const defaults = { className: 'form-control', model: `.${id}` }; + // const props = Object.assign(defaults, options); return (
  • {id === 'file' ? 'Document' : 'Attachments'} -
  • {file.name}
    - - - Remove + this.removeAttachment(file)}> + +  Remove
  • From 7d2c9f334ffdbec15ec1cb8fdf86ca70163b9ebb Mon Sep 17 00:00:00 2001 From: Daneryl Date: Mon, 26 Apr 2021 14:03:40 +0200 Subject: [PATCH 38/61] version 1.29.0-rc2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50ecdeed51..3903ab60e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uwazi", - "version": "1.29.0-rc1", + "version": "1.29.0-rc2", "description": "Uwazi is a free, open-source solution for organising, analysing and publishing your documents.", "keywords": [ "react" From ca310dda32238e99bf109a4053f17c48d9f2e3ce Mon Sep 17 00:00:00 2001 From: Kevin Nderitu Date: Mon, 26 Apr 2021 23:52:21 +0300 Subject: [PATCH 39/61] Added mobile UI for attachments --- app/react/Markdown/components/PublicForm.js | 14 ++++++++------ .../Markdown/components/scss/public-form.scss | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/app/react/Markdown/components/PublicForm.js b/app/react/Markdown/components/PublicForm.js index bb7b8c7b47..31e44e4bb9 100644 --- a/app/react/Markdown/components/PublicForm.js +++ b/app/react/Markdown/components/PublicForm.js @@ -91,6 +91,7 @@ class PublicForm extends Component { const { submit, template, remote } = this.props; values.file = _values.file ? _values.file[0] : undefined; values.template = template.get('_id'); + values.attachments = this.state.files.length ? this.state.files : undefined; submit(values, remote) .then(uploadCompletePromise => { @@ -112,16 +113,16 @@ class PublicForm extends Component { }); } - renderFileField(id /*, options */) { - // const defaults = { className: 'form-control', model: `.${id}` }; - // const props = Object.assign(defaults, options); + renderFileField(id, options) { + const defaults = { className: 'form-control on-mobile' /*, model: `.${id}`*/ }; + const props = Object.assign(defaults, options); return (
    • {id === 'file' ? 'Document' : 'Attachments'} - -