diff --git a/src/js/apps/patients/sidebar/action-sidebar_app.js b/src/js/apps/patients/sidebar/action-sidebar_app.js index 449724780..e150aecb1 100644 --- a/src/js/apps/patients/sidebar/action-sidebar_app.js +++ b/src/js/apps/patients/sidebar/action-sidebar_app.js @@ -236,7 +236,10 @@ export default App.extend(extend({ }); attachment.upload(file); - Radio.request('ws', 'add', attachment); + this.listenTo(attachment, 'upload:success', uploadedAttachment => { + this.action.addFileRelationship(uploadedAttachment); + Radio.request('ws', 'add', uploadedAttachment); + }); this.listenTo(attachment, 'upload:failed', () => { Radio.request('alert', 'show:error', intl.patients.sidebar.actionSidebarApp.uploadError); @@ -245,6 +248,8 @@ export default App.extend(extend({ onRemoveAttachment(model) { model.destroy(); + this.action.removeFileRelationship(model); + Radio.request('ws', 'unsubscribe', model); }, addSubscriptions() { diff --git a/src/js/entities-service/entities/actions.js b/src/js/entities-service/entities/actions.js index a176e0d84..157122437 100644 --- a/src/js/entities-service/entities/actions.js +++ b/src/js/entities-service/entities/actions.js @@ -64,8 +64,7 @@ const _Model = BaseModel.extend({ _download: attributes.urls.download, }); - const newFilesRelationship = [...this.get('_files'), { id: file.id, type: 'files' }]; - this.set({ _files: newFilesRelationship }); + this.addFileRelationship(attachmentModel); this.trigger('ws:add:attachment', attachmentModel); }, @@ -250,7 +249,12 @@ const _Model = BaseModel.extend({ return !!size(programAction.get('allowed_uploads')); }, - removeAttachment(resource) { + addFileRelationship(resource) { + const newFilesRelationship = [...this.get('_files'), { id: resource.id, type: 'files' }]; + + this.set({ _files: newFilesRelationship }); + }, + removeFileRelationship(resource) { const files = this.get('_files'); const newFilesRelationship = files.filter(file => { return file.id !== resource.id; diff --git a/src/js/entities-service/entities/files.js b/src/js/entities-service/entities/files.js index 3c7995a4e..6555b8e4e 100644 --- a/src/js/entities-service/entities/files.js +++ b/src/js/entities-service/entities/files.js @@ -28,7 +28,7 @@ const _Model = BaseModel.extend({ }, FileRemoved({ resource }) { const action = Radio.request('entities', 'actions:model', this.get('_action')); - action.removeAttachment(resource); + action.removeFileRelationship(resource); this.destroy({ isDeleted: true }); }, @@ -66,6 +66,9 @@ const _Model = BaseModel.extend({ this.createUpload(file.name) .then(() => this.putFile(file)) .then(() => this.fetchFile()) + .then(uploadedFile => { + this.trigger('upload:success', uploadedFile); + }) .catch(() => { this.trigger('upload:failed'); this.destroy(); diff --git a/test/integration/patients/sidebar/action-sidebar.js b/test/integration/patients/sidebar/action-sidebar.js index 9ffaf7452..23fe37231 100644 --- a/test/integration/patients/sidebar/action-sidebar.js +++ b/test/integration/patients/sidebar/action-sidebar.js @@ -968,6 +968,161 @@ context('action sidebar', function() { }); }); + specify('action attachments - show/hide icon in action list items', function() { + const testPatient = getPatient(); + + const testProgramAction = getProgramAction({ + attributes: { + allowed_uploads: ['pdf'], + }, + }); + + const testAction = getAction({ + relationships: { + 'files': getRelationship([], 'files'), + 'patient': getRelationship(testPatient), + 'program-action': getRelationship(testProgramAction), + 'state': getRelationship(stateTodo), + }, + }); + + cy + .routesForPatientAction() + .routeSettings(fx => { + fx.data.push({ id: 'upload_attachments', attributes: { value: true } }); + + return fx; + }) + .routePatient(fx => { + fx.data = testPatient; + + return fx; + }) + .routePatientActions(fx => { + fx.data = [testAction]; + + return fx; + }) + .routePatientFlows(fx => { + fx.data = []; + + return fx; + }) + .routeAction(fx => { + fx.data = testAction; + + fx.included.push(testProgramAction); + + return fx; + }) + .routeActionFiles(fx => { + fx.data = []; + + return fx; + }) + .visit(`/patient/${ testPatient.id }/action/${ testAction.id }`) + .wait('@routePatientActions') + .wait('@routePatientFlows') + .wait('@routeAction') + .wait('@routeActionFiles'); + + cy + .get('.patient__list') + .find('.table-list__item .fa-paperclip') + .should('not.exist'); + + + const putFileURL = '/api/actions/**/relationships/files?urls=upload'; + + let fileId; + + cy + .intercept('PUT', putFileURL, req => { + expect(req.body.data.attributes.path).to.include('test.pdf'); + fileId = req.body.data.id; + req.reply({ + statusCode: 201, + body: { + data: { + id: fileId, + attributes: { + path: req.body.data.attributes.path, + created_at: testTs(), + }, + meta: { + upload: '/upload-test', + }, + }, + }, + }); + }).as('routePutFile'); + + cy + .intercept('PUT', '/upload-test', req => { + req.reply({ + statusCode: 200, + throttleKbps: 10, + }); + }).as('routeUploadFile'); + + cy + .intercept('GET', '/api/files/*', req => { + req.reply({ + statusCode: 200, + body: { + data: { + id: fileId, + attributes: { + path: '/dir/test.pdf', + created_at: testTs(), + }, + meta: { + download: '/download-test', + view: '/view-test', + }, + }, + }, + }); + }).as('routeGetFile'); + + cy + .intercept('DELETE', '/api/files/*', { + statusCode: 204, + body: {}, + }) + .as('routeDeleteFile'); + + cy + .get('#upload-attachment') + .selectFile({ + contents: Cypress.Buffer.from('test'), + fileName: 'test.pdf', + }, { force: true }); + + cy + .get('.patient__list') + .find('.table-list__item .fa-paperclip') + .should('exist'); + + cy + .get('.sidebar') + .find('[data-attachments-files-region]') + .first() + .contains('Remove') + .click(); + + cy + .get('.modal--small') + .find('.js-submit') + .click() + .wait('@routeDeleteFile'); + + cy + .get('.patient__list') + .find('.table-list__item .fa-paperclip') + .should('not.exist'); + }); + specify('action attachments - uploads not allowed on program action', function() { const testProgramAction = getProgramAction({ attributes: {