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