-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
handle different locale #48
Changes from 7 commits
c292e80
723cc36
7cdfe74
f8ff7ed
d2a22ca
52d3ef0
719f8c5
c0d0df8
438245b
84786d0
4ced67d
f444864
d2c5306
88c9078
abf2f59
6baee6f
72b9512
b74a712
164b8bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,10 @@ | |
|
||
## UNRELEASED | ||
|
||
### Adds | ||
|
||
* TODO: | ||
|
||
### Changes | ||
|
||
* Hide "Duplicates Detected." notification. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,13 +6,64 @@ const { EJSON } = require('bson'); | |
module.exports = self => { | ||
return { | ||
async import(req, moduleName) { | ||
const { | ||
docs, attachmentsInfo, exportPath, filePath | ||
} = await self.readExportFile(req); | ||
if (!req.user) { | ||
throw self.apos.error('forbidden'); | ||
} | ||
|
||
const overrideLocale = self.apos.launder.boolean(req.body.overrideLocale); | ||
let exportPath = self.apos.launder.string(req.body.exportPath); | ||
|
||
let docs; | ||
let attachmentsInfo; | ||
|
||
if (exportPath) { | ||
const filesData = await self.getFilesData(exportPath); | ||
|
||
({ docs, attachmentsInfo } = filesData); | ||
} else { | ||
const exportFile = await self.readExportFile(req); | ||
|
||
({ docs, attachmentsInfo } = exportFile); | ||
exportPath = exportFile.exportPath; | ||
|
||
await self.cleanFile(exportFile.filePath); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we now clean the archive right after having extracted it so we don't have to think about removing it at several other places |
||
} | ||
|
||
const siteHasMultipleLocales = Object.keys(self.apos.i18n.locales).length > 1; | ||
const differentDocsLocale = self.getFirstDifferentLocale(req, docs); | ||
|
||
if (siteHasMultipleLocales && differentDocsLocale) { | ||
if (!overrideLocale) { | ||
// Display confirmation modal to ask the user if he wants to | ||
// continue the import with the current locale overriding the docs one: | ||
await self.apos.notify(req, ' ', { | ||
type: 'warning', | ||
event: { | ||
name: 'import-locale-differs', | ||
data: { | ||
moduleName, | ||
exportPath, | ||
content: { | ||
heading: req.t('aposImportExport:importWithCurrentLocaleHeading'), | ||
description: req.t('aposImportExport:importWithCurrentLocaleDescription', { | ||
docsLocale: differentDocsLocale, | ||
currentLocale: req.locale | ||
}), | ||
negativeLabel: 'apostrophe:no', | ||
affirmativeLabel: 'apostrophe:yes' | ||
} | ||
} | ||
}, | ||
classes: [ 'apos-notification--hidden' ] | ||
}); | ||
|
||
return; | ||
} | ||
|
||
// The user decided to continue the import (`overrideLocale` param sent) | ||
self.rewriteDocsWithCurrentLocale(req, docs); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suppose this method is called twice, another time with the confirmation to change locale? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method is called only during the 2nd call (when the user chooses Yes), see the early return above |
||
} | ||
|
||
const total = docs.length + attachmentsInfo.length; | ||
const { | ||
reporting, jobId, notificationId | ||
|
@@ -21,6 +72,7 @@ module.exports = self => { | |
const { | ||
duplicatedDocs, duplicatedIds, failedIds | ||
} = await self.insertDocs(req, docs, reporting); | ||
|
||
const importedAttachments = await self.insertAttachments(req, { | ||
attachmentsInfo, | ||
reporting, | ||
|
@@ -52,7 +104,6 @@ module.exports = self => { | |
}); | ||
|
||
await self.cleanFile(exportPath); | ||
await self.cleanFile(filePath); | ||
return; | ||
} | ||
|
||
|
@@ -87,8 +138,6 @@ module.exports = self => { | |
classes: [ 'apos-notification--hidden' ] | ||
}); | ||
|
||
self.cleanFile(filePath); | ||
|
||
return results; | ||
}, | ||
|
||
|
@@ -180,6 +229,36 @@ module.exports = self => { | |
}; | ||
}, | ||
|
||
getFirstDifferentLocale(req, docs) { | ||
const doc = docs | ||
.find(doc => self.isLocaleDifferent(req, doc)); | ||
|
||
return doc && self.stripOutMode(doc.aposLocale); | ||
}, | ||
|
||
rewriteDocsWithCurrentLocale(req, docs) { | ||
for (const doc of docs) { | ||
if (self.isLocaleDifferent(req, doc)) { | ||
self.replaceLocale(req, doc); | ||
} | ||
} | ||
}, | ||
|
||
isLocaleDifferent(req, doc) { | ||
return doc.aposLocale && self.stripOutMode(doc.aposLocale) !== req.locale; | ||
}, | ||
|
||
replaceLocale(req, doc) { | ||
const [ id, , mode ] = doc._id.split(':'); | ||
|
||
doc._id = [ id, req.locale, mode ].join(':'); | ||
doc.aposLocale = [ req.locale, mode ].join(':'); | ||
}, | ||
|
||
stripOutMode(aposLocale) { | ||
return aposLocale.split(':').at(0); | ||
}, | ||
|
||
async insertDocs(req, docs, reporting) { | ||
const duplicatedDocs = []; | ||
const duplicatedIds = []; | ||
|
@@ -342,20 +421,20 @@ module.exports = self => { | |
} | ||
}, | ||
|
||
async cleanFile(exportPath) { | ||
async cleanFile(path) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor change: |
||
try { | ||
const stat = await fsp.lstat(exportPath); | ||
const stat = await fsp.lstat(path); | ||
if (stat.isDirectory()) { | ||
await fsp.rm(exportPath, { | ||
await fsp.rm(path, { | ||
recursive: true, | ||
force: true | ||
}); | ||
} else { | ||
await fsp.unlink(exportPath); | ||
await fsp.unlink(path); | ||
} | ||
} catch (err) { | ||
self.apos.util.error( | ||
`Error while trying to remove the file or folder: ${exportPath}. You might want to remove it yourself.` | ||
`Error while trying to remove the file or folder: ${path}. You might want to remove it yourself.` | ||
); | ||
} | ||
}, | ||
|
@@ -428,15 +507,15 @@ module.exports = self => { | |
const jobId = self.apos.launder.string(req.body.jobId); | ||
const notificationId = self.apos.launder.string(req.body.notificationId); | ||
|
||
const jobManager = self.apos.modules['@apostrophecms/job']; | ||
const job = await jobManager.db.findOne({ _id: jobId }); | ||
|
||
jobManager.end(job, true); | ||
if (jobId) { | ||
const jobManager = self.apos.modules['@apostrophecms/job']; | ||
const job = await jobManager.db.findOne({ _id: jobId }); | ||
jobManager.end(job, true); | ||
} | ||
if (notificationId) { | ||
self.apos.notification.dismiss(req, notificationId, 2000).catch(self.apos.util.error); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. clean job and notification only if existing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see |
||
|
||
self.apos.notification.dismiss(req, notificationId, 2000) | ||
.catch((error) => { | ||
self.apos.util.error(error); | ||
}); | ||
await self.cleanFile(exportPath); | ||
} | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ export default () => { | |
apos.bus.$on('export-download', openUrl); | ||
apos.bus.$on('import-started', addBeforeUnloadListener); | ||
apos.bus.$on('import-ended', removeBeforeUnloadListener); | ||
apos.bus.$on('import-locale-differs', handleDifferentLocale); | ||
apos.bus.$on('import-duplicates', handleDuplicates); | ||
} | ||
}); | ||
|
@@ -25,6 +26,46 @@ export default () => { | |
window.removeEventListener('beforeunload', warningImport); | ||
} | ||
|
||
async function handleDifferentLocale(event) { | ||
const continueImport = await apos.modal.execute('AposModalConfirm', event); | ||
|
||
if (continueImport) { | ||
try { | ||
const moduleAction = apos.modules[event.moduleName].action; | ||
|
||
await apos.http.post(`${moduleAction}/import`, { | ||
body: { | ||
overrideLocale: true, | ||
exportPath: event.exportPath | ||
} | ||
}); | ||
} catch (error) { | ||
apos.notify('aposImportExport:importFailed', { | ||
type: 'danger', | ||
dismiss: true | ||
}); | ||
} | ||
|
||
return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we agree that in this case the export file is cleaned from the import route directly? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, it should be done at line 107, as in a "normal" case where no locale overriding is involved |
||
} | ||
|
||
// If not, we still need to clean the uploaded archive | ||
try { | ||
await apos.http.post('/api/v1/@apostrophecms/import-export/clean-export', { | ||
body: { | ||
exportPath: event.exportPath | ||
} | ||
}); | ||
} catch (error) { | ||
apos.notify('aposImportExport:importCleanFailed', { | ||
type: 'warning', | ||
interpolate: { | ||
exportPath: event.exportPath | ||
} | ||
}); | ||
} | ||
} | ||
|
||
async function handleDuplicates(event) { | ||
if (event.duplicatedDocs.length) { | ||
await apos.modal.execute('AposDuplicateImportModal', event); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -194,7 +194,7 @@ export default { | |
} | ||
}); | ||
} catch (error) { | ||
apos.notify(this.$t('aposImportExport:importCleanFailed'), { | ||
apos.notify('aposImportExport:importCleanFailed', { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
type: 'warning', | ||
interpolate: { | ||
exportPath: this.exportPath | ||
|
@@ -217,7 +217,7 @@ export default { | |
jobId: this.jobId | ||
} | ||
}).catch(() => { | ||
apos.notify(this.$t('aposImportExport:exportFailed'), { | ||
apos.notify('aposImportExport:exportFailed', { | ||
type: 'danger', | ||
dismiss: true | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what means the fact that this method receives an exportPath? Does it mean that the gzip file has already been cleaned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The gzip file is now cleaned as soon as it's extracted (cf. comment below)
This method is provided
exportPath
when the user choosesYes
(continue the import with the current locale), because is archive has already been extracted during theimport
method first call.It just early returned to display the confirmation modal.
So at the 2nd call, we simply give the method back the
exportPath
so it knows where the files were extracted during the 1st call