Skip to content

Commit

Permalink
Update conflict status after request to update entity data (#908)
Browse files Browse the repository at this point in the history
Closes getodk/central#556. Also updating the alert shown in
EntityResolve when no conflicts are returned.
  • Loading branch information
matthew-white committed Dec 7, 2023
1 parent 2cf3df3 commit 4b5d237
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 16 deletions.
24 changes: 14 additions & 10 deletions src/components/entity/list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,10 @@ export default {
newOData[odataName] = updatedData[name];
this.odataEntities.value[index] = newOData;
this.$refs.table.afterUpdate(index);
if (this.resolveIndex != null) {
if (this.resolveIndex == null)
this.$refs.table.afterUpdate(index);
else
this.showResolve(this.resolveIndex);
}
},
showResolve(index) {
if (this.refreshing) return;
Expand All @@ -251,12 +250,17 @@ export default {
}
},
afterResolve(updatedEntity) {
const index = this.resolveIndex;
const newOData = Object.assign(Object.create(null), this.odataEntities.value[index]);
newOData.__system.conflict = null;
newOData.__system.updatedAt = updatedEntity.updatedAt;
this.odataEntities.value[index] = newOData;
this.$refs.table.afterUpdate(index);
// Update the OData using the REST response.
const newOData = Object.create(null);
Object.assign(newOData, this.odataEntities.value[this.resolveIndex]);
newOData.__system = {
...newOData.__system,
conflict: null,
updatedAt: updatedEntity.updatedAt
};
this.odataEntities.value[this.resolveIndex] = newOData;
this.$refs.table.afterUpdate(this.resolveIndex);
},
scrolledToBottom() {
// Using pageYOffset rather than scrollY in order to support IE.
Expand Down
2 changes: 1 addition & 1 deletion src/components/entity/resolve.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ const requestEntityVersions = () => {
extended: true
})
.then(() => {
if (entityVersions.length === 0) alert.danger(t('problem.409_15'));
if (entityVersions.length === 0) alert.danger(t('problem.400_32'));
})
.catch(noop);
};
Expand Down
9 changes: 6 additions & 3 deletions src/components/entity/show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,18 @@ setDocumentTitle(() => [entity.dataExists ? entity.currentVersion.label : null])
const update = reactive({ state: false });
const { i18n, alert } = inject('container');
const afterUpdate = (updated) => {
const afterUpdate = (updatedEntity) => {
fetchActivityData();
update.state = false;
alert.success(i18n.t('alert.updateEntity'));
entity.patch(() => {
// entity.currentVersion will no longer have extended metadata, but we don't
// need it to.
entity.currentVersion = updated.currentVersion;
entity.updatedAt = updated.updatedAt;
entity.currentVersion = updatedEntity.currentVersion;
entity.updatedAt = updatedEntity.updatedAt;
// Update entity.conflict in case a conflict has been resolved by another
// user or in another tab.
entity.conflict = updatedEntity.conflict;
});
};
Expand Down
17 changes: 15 additions & 2 deletions test/components/entity/resolve.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { mockRouter } from '../../util/router';

const relevantToConflict = () => testData.extendedEntityVersions.sorted()
.filter(version => version.relevantToConflict);
const showModal = () => {
const showModal = (respond = true) => {
const dataset = testData.extendedDatasets.last();
return mockHttp()
.mount(EntityResolve, {
Expand All @@ -25,7 +25,8 @@ const showModal = () => {
state: true,
entity: last(testData.entityOData().value)
}))
.respondWithData(relevantToConflict);
.modify(series =>
(respond ? series.respondWithData(relevantToConflict) : series));
};

describe('EntityResolve', () => {
Expand All @@ -47,6 +48,18 @@ describe('EntityResolve', () => {
extended: true
}]);
});

it('shows an alert if no conflicts are returned', () => {
testData.extendedEntities.createPast(1);
testData.extendedEntityVersions.createPast(2, { baseVersion: 1 });
return showModal(false)
.respondWithData(() => [])
.afterResponse(modal => {
modal.should.alert('danger', (message) => {
message.should.startWith('Another user has already marked the conflict as resolved.');
});
});
});
});

it('redirects to Entity details page', async () => {
Expand Down
41 changes: 41 additions & 0 deletions test/components/entity/show.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import EntityConflictSummary from '../../../src/components/entity/conflict-summary.vue';
import EntityUpdate from '../../../src/components/entity/update.vue';
import NotFound from '../../../src/components/not-found.vue';
import PageBack from '../../../src/components/page/back.vue';
Expand Down Expand Up @@ -121,6 +122,46 @@ describe('EntityShow', () => {
});

it('updates the number of entries in the feed');

it('updates the conflict status', () => {
testData.extendedEntities.createPast(1, {
uuid: 'e',
label: 'My Entity'
});
testData.extendedEntityVersions.createPast(2, { baseVersion: 1 });
return load('/projects/1/entity-lists/trees/entities/e', { root: false })
.afterResponses(component => {
component.findComponent(EntityConflictSummary).exists().should.be.true();
})
.request(async (component) => {
await component.get('#entity-data-update-button').trigger('click');
const form = component.get('#entity-update form');
await form.get('textarea').setValue('Updated Entity');
return form.trigger('submit');
})
.respondWithData(() => {
// Another user has resolved the conflict since the page was loaded.
testData.extendedEntities.resolve(-1);
testData.extendedAudits.createPast(1, {
action: 'entity.update.resolve'
});

testData.extendedEntityVersions.createNew({
label: 'Updated Entity'
});
testData.extendedAudits.createPast(1, {
action: 'entity.update.version',
details: {}
});

return testData.standardEntities.last();
})
.respondWithData(() => testData.extendedAudits.sorted())
.respondWithData(() => testData.extendedEntityVersions.sorted())
.afterResponses(component => {
component.findComponent(EntityConflictSummary).exists().should.be.false();
});
});
});

describe('after a conflict is marked as resolved', () => {
Expand Down

0 comments on commit 4b5d237

Please sign in to comment.