diff --git a/services/web/app/src/infrastructure/ExpressLocals.js b/services/web/app/src/infrastructure/ExpressLocals.js
index c28d265c26..96225241b7 100644
--- a/services/web/app/src/infrastructure/ExpressLocals.js
+++ b/services/web/app/src/infrastructure/ExpressLocals.js
@@ -346,6 +346,10 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
hasSamlFeature: Features.hasFeature('saml'),
samlInitPath: _.get(Settings, ['saml', 'ukamf', 'initPath']),
hasLinkUrlFeature: Features.hasFeature('link-url'),
+ hasLinkedProjectFileFeature: Features.hasFeature('linked-project-file'),
+ hasLinkedProjectOutputFileFeature: Features.hasFeature(
+ 'linked-project-output-file'
+ ),
siteUrl: Settings.siteUrl,
emailConfirmationDisabled: Settings.emailConfirmationDisabled,
maxEntitiesPerProject: Settings.maxEntitiesPerProject,
diff --git a/services/web/app/src/infrastructure/Features.js b/services/web/app/src/infrastructure/Features.js
index 3d28029890..72c10472fe 100644
--- a/services/web/app/src/infrastructure/Features.js
+++ b/services/web/app/src/infrastructure/Features.js
@@ -85,8 +85,17 @@ const Features = {
return Boolean(_.get(Settings, ['apis', 'references', 'url']))
case 'saml':
return Boolean(Settings.enableSaml)
+ case 'linked-project-file':
+ return Boolean(Settings.enabledLinkedFileTypes.includes('project_file'))
+ case 'linked-project-output-file':
+ return Boolean(
+ Settings.enabledLinkedFileTypes.includes('project_output_file')
+ )
case 'link-url':
- return Boolean(_.get(Settings, ['apis', 'linkedUrlProxy', 'url']))
+ return Boolean(
+ _.get(Settings, ['apis', 'linkedUrlProxy', 'url']) &&
+ Settings.enabledLinkedFileTypes.includes('url')
+ )
case 'public-registration':
return publicRegistrationModuleAvailable
case 'support':
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-body.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-body.js
index 5b669cfa4c..8ab7a9716e 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-body.js
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-body.js
@@ -40,11 +40,14 @@ export default function FileTreeModalCreateFileBody() {
label={t('upload')}
/>
-
+ {(window.ExposedSettings.hasLinkedProjectFileFeature ||
+ window.ExposedSettings.hasLinkedProjectOutputFileFeature) && (
+
+ )}
{window.ExposedSettings.hasLinkUrlFeature && (
)}
-
- or
-
-
+ {canSwitchOutputFilesMode && (
+
+ or
+
+
+ )}
', function () {
// click on the button to toggle between source and output files
const sourceTypeButton = screen.getByRole('button', {
+ // NOTE: When changing the label, update the other tests with this label as well.
name: 'select from output files',
})
await fireEvent.click(sourceTypeButton)
@@ -295,6 +296,48 @@ describe('', function () {
).to.be.true
})
+ describe('when the output files feature is not available', function () {
+ const flagBefore = window.ExposedSettings.hasLinkedProjectOutputFileFeature
+ before(function () {
+ window.ExposedSettings.hasLinkedProjectOutputFileFeature = false
+ })
+ after(function () {
+ window.ExposedSettings.hasLinkedProjectOutputFileFeature = flagBefore
+ })
+
+ it('should not show the import from output file mode', async function () {
+ fetchMock.get('path:/user/projects', {
+ projects: [
+ {
+ _id: 'test-project',
+ name: 'This Project',
+ },
+ {
+ _id: 'project-1',
+ name: 'Project One',
+ },
+ {
+ _id: 'project-2',
+ name: 'Project Two',
+ },
+ ],
+ })
+
+ render(
+
+
+
+ )
+
+ // should not show the toggle
+ expect(
+ screen.queryByRole('button', {
+ name: 'select from output files',
+ })
+ ).to.be.null
+ })
+ })
+
it('import from a URL when the form is submitted', async function () {
fetchMock.post('express:/project/:projectId/linked_file', () => 204)
diff --git a/services/web/test/unit/src/infrastructure/FeaturesTests.js b/services/web/test/unit/src/infrastructure/FeaturesTests.js
index 494bc66777..acfa3cafd1 100644
--- a/services/web/test/unit/src/infrastructure/FeaturesTests.js
+++ b/services/web/test/unit/src/infrastructure/FeaturesTests.js
@@ -8,6 +8,7 @@ describe('Features', function () {
requires: {
'@overleaf/settings': (this.settings = {
moduleImportSequence: [],
+ enabledLinkedFileTypes: [],
}),
},
})
@@ -106,12 +107,12 @@ describe('Features', function () {
expect(this.Features.hasFeature('affiliations')).to.be.true
expect(this.Features.hasFeature('analytics')).to.be.true
expect(this.Features.hasFeature('custom-togglers')).to.be.true
- expect(this.Features.hasFeature('link-url')).to.be.true
expect(this.Features.hasFeature('overleaf-integration')).to.be.true
expect(this.Features.hasFeature('references')).to.be.true
expect(this.Features.hasFeature('registration')).to.be.true
})
it('should return false', function () {
+ expect(this.Features.hasFeature('link-url')).to.be.false
expect(this.Features.hasFeature('git-bridge')).to.be.false
expect(this.Features.hasFeature('github-sync')).to.be.false
expect(this.Features.hasFeature('homepage')).to.be.false
@@ -126,8 +127,10 @@ describe('Features', function () {
this.settings.enableGithubSync = true
this.settings.enableSaml = true
this.settings.oauth = true
+ this.settings.enabledLinkedFileTypes = ['url', 'project_file']
})
it('should return true or return value', function () {
+ expect(this.Features.hasFeature('link-url')).to.be.true
expect(this.Features.hasFeature('affiliations')).to.be.true
expect(this.Features.hasFeature('analytics')).to.be.true
expect(this.Features.hasFeature('custom-togglers')).to.be.true