{{ $t('heading[0]') }}
-
+
- {{ $t('resource.entities') }}
-
-
-
@import '../../assets/scss/variables';
-#odata-data-access { float: right; }
-
#dataset-entities {
.toggle-deleted-entities {
margin-left: 8px;
@@ -175,12 +182,24 @@ export default {
left: 12px;
font-size: 14px;
}
+
+ .dataset-entities-heading-row {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ }
+
+ #odata-data-access {
+ margin-left: auto;
+ font-size: initial;
+ }
}
{
"en": {
+ "upload": "Upload Entities",
"alert": {
"upload": "Success! Your Entities have been uploaded."
},
diff --git a/src/components/date-range-picker.vue b/src/components/date-range-picker.vue
index 3031fbe13..ae5ef0cc4 100644
--- a/src/components/date-range-picker.vue
+++ b/src/components/date-range-picker.vue
@@ -10,14 +10,15 @@ including this file, may be copied, modified, propagated, or distributed
except according to the terms contained in the LICENSE file.
-->
-
@@ -70,7 +73,7 @@ export default {
type: Boolean,
default: false
},
- placeholder: {
+ label: {
type: String,
required: true
},
@@ -187,13 +190,34 @@ export default {
}
.form-inline .flatpickr-input {
- // Leave space for the .close button.
- width: 205px;
- &.required { width: 193px };
+ width: 87px;
- &:lang(ja) {
+ &.has-value {
+ // Leave space for the .close button.
+ width: 207px;
+ &.required { width: 193px };
+ }
+
+ &.has-value:lang(ja) {
width: 252px;
&.required { width: 240px; }
}
+
+ &.none {
+ font-style: italic;
+ }
+}
+
+#date-range-picker-container {
+ .icon-angle-down {
+ font-size: 16px;
+ color: #555555;
+ font-weight: bold;
+ vertical-align: -4px;
+ }
+
+ .form-label {
+ transform: translateY(2px);
+ }
}
diff --git a/src/components/entity/download-button.vue b/src/components/entity/download-button.vue
index 02f98d337..461390d67 100644
--- a/src/components/entity/download-button.vue
+++ b/src/components/entity/download-button.vue
@@ -11,17 +11,14 @@ except according to the terms contained in the LICENSE file.
-->
- {{ text }}
+
+ {{ $t('action.download') }}
diff --git a/src/components/entity/filters.vue b/src/components/entity/filters.vue
index 9e88d9892..23b2a5801 100644
--- a/src/components/entity/filters.vue
+++ b/src/components/entity/filters.vue
@@ -12,7 +12,7 @@ except according to the terms contained in the LICENSE file.
- {{ $t('common.filter') }}
+
diff --git a/src/components/entity/filters/conflict.vue b/src/components/entity/filters/conflict.vue
index d2c4578a8..fa01b89bf 100644
--- a/src/components/entity/filters/conflict.vue
+++ b/src/components/entity/filters/conflict.vue
@@ -37,9 +37,19 @@ defineEmits(['update:modelValue']);
const { t } = useI18n();
const options = computed(() => [true, false].map(value =>
({ value, text: t(`conflict.${value}`) })));
-const placeholder = (counts) => t('placeholder', counts);
+const placeholder = (counts) => {
+ if (counts.total === counts.selected) return t('common.none');
+
+ return t('placeholder', counts);
+};
+
+
{
"en": {
diff --git a/src/components/entity/list.vue b/src/components/entity/list.vue
index 9903a1ee0..140ee38f1 100644
--- a/src/components/entity/list.vue
+++ b/src/components/entity/list.vue
@@ -11,20 +11,17 @@ except according to the terms contained in the LICENSE file.
-->
-
+
-
+
+ {{ $t('action.refresh') }}
+
+
- {{ $t('resource.submissions') }}
-
- {{ $t('action.createSubmission') }}
-
-
-
- {{ $tcn('action.toggleDeletedSubmissions', deletedSubmissionCount.value) }}
-
-
+
- {{ $t('purgeDescription') }}
-
-
-
@@ -43,7 +47,7 @@ except according to the terms contained in the LICENSE file.
@@ -54,15 +39,7 @@ export default {
// @transifexKey component.SubmissionDownloadDropdown
"en": {
"action": {
- "download": {
- "unfiltered": "Download {count} Submission | Download {count} Submissions",
- "filtered": {
- // This is the text of a button. This text is shown when the number of
- // matching Submissions is unknown.
- "withoutCount": "Download matching Submissions",
- "withCount": "Download {count} matching Submission | Download {count} matching Submissions"
- }
- }
+ "download": "Download"
}
}
}
diff --git a/src/components/submission/field-dropdown.vue b/src/components/submission/field-dropdown.vue
index 8f3470d90..a0ab45cd1 100644
--- a/src/components/submission/field-dropdown.vue
+++ b/src/components/submission/field-dropdown.vue
@@ -13,7 +13,7 @@ except according to the terms contained in the LICENSE file.
@@ -79,7 +79,7 @@ const placeholder = (counts) => t('placeholder', counts);
// This is the text of a dropdown that allows the user to select which
// columns to display in a table. {selected} is the number of columns
// selected; {total} is the total number of columns.
- "placeholder": "{selected} of {total}",
+ "placeholder": "{selected} of {total} column shown | {selected} of {total} columns shown",
"field": {
// This is shown beneath text that indicates the number of columns that
// the user has selected to display in a table. For example, that text may
diff --git a/src/components/submission/filters.vue b/src/components/submission/filters.vue
index f2ab3ea5f..1f67f5c19 100644
--- a/src/components/submission/filters.vue
+++ b/src/components/submission/filters.vue
@@ -12,13 +12,13 @@ except according to the terms contained in the LICENSE file.
- {{ $t('common.filter') }}
+
+
{
"en": {
diff --git a/src/components/submission/filters/review-state.vue b/src/components/submission/filters/review-state.vue
index be737e38c..aeb8cbd28 100644
--- a/src/components/submission/filters/review-state.vue
+++ b/src/components/submission/filters/review-state.vue
@@ -45,9 +45,18 @@ const options = reviewStates.map(reviewState => ({
}));
const { t } = useI18n();
-const placeholder = (counts) => t('placeholder', counts);
+const placeholder = (counts) => {
+ if (counts.total === counts.selected) return t('common.none');
+ return t('placeholder', counts);
+};
+
+
{
"en": {
diff --git a/src/components/submission/filters/submitter.vue b/src/components/submission/filters/submitter.vue
index c714af63a..67cf926d8 100644
--- a/src/components/submission/filters/submitter.vue
+++ b/src/components/submission/filters/submitter.vue
@@ -89,9 +89,19 @@ const update = (value) => {
}
};
-const placeholder = (counts) => t('placeholder', counts);
+const placeholder = (counts) => {
+ if (counts.total === counts.selected) return t('common.none');
+
+ return t('placeholder', counts);
+};
+
+
{
"en": {
diff --git a/src/components/submission/list.vue b/src/components/submission/list.vue
index d950767ec..d7808a230 100644
--- a/src/components/submission/list.vue
+++ b/src/components/submission/list.vue
@@ -13,7 +13,7 @@ except according to the terms contained in the LICENSE file.
-
+
@@ -29,17 +29,19 @@ except according to the terms contained in the LICENSE file.
v-model:submissionDate="submissionDateRange"
v-model:reviewState="reviewStates"
:disabled="deleted" :disabled-message="deleted ? $t('filterDisabledMessage') : null"/>
+
+
- {{ $t('action.refresh') }}
+ {{ $t('action.refresh') }}
-
@@ -306,11 +308,15 @@ export default {
this.formVersion.submissions += this.deleted ? size : -size;
}
}
+ },
+ downloadModalState(newState) {
+ this.downloadModal.state = newState;
}
},
created() {
this.fetchData();
},
+ expose: ['showDownloadModal'],
methods: {
// `clear` indicates whether this.odata should be cleared before sending the
// request. `refresh` indicates whether the request is a background refresh.
@@ -502,6 +508,9 @@ export default {
// less than the lowest size option, hence we don't need to make a request.
if (this.odata.count < this.pageSizeOptions[0]) return;
this.fetchChunk(false);
+ },
+ showDownloadModal() {
+ this.downloadModal.show();
}
}
};
@@ -525,11 +534,10 @@ export default {
// the download button can wrap above the other actions if the viewport is not
// wide enough.
gap: 10px;
- margin-bottom: 30px;
+ // margin-bottom: 30px;
- .form-inline {
- margin-bottom: 0;
- padding-bottom: 0;
+ .field-dropdown-form {
+ margin-left: auto;
}
}
#submission-field-dropdown {
@@ -540,7 +548,6 @@ export default {
// Additional space between the dropdown and the refresh button
margin-right: 5px;
}
-#submission-download-button { margin-left: auto; }
// Adjust the spacing between actions on the draft testing page.
#submission-list-test-in-browser {
diff --git a/src/components/table-freeze.vue b/src/components/table-freeze.vue
index 2015d33f1..9a7889467 100644
--- a/src/components/table-freeze.vue
+++ b/src/components/table-freeze.vue
@@ -148,7 +148,7 @@ defineExpose({ getRowPair });
.table {
margin-bottom: 0;
- width: auto;
+ width: 100%;
}
}
diff --git a/src/locales/en.json5 b/src/locales/en.json5
index cdfc47b44..25ae2e575 100644
--- a/src/locales/en.json5
+++ b/src/locales/en.json5
@@ -188,8 +188,7 @@
"continue": "Continue",
"create": "Create",
// This is the text of a button that is used to fill out a new Submission.
- // It is shown next to a heading whose text is "Submissions".
- "createSubmission": "New",
+ "createSubmission": "New Submission",
"delete": "Delete",
"done": "Done",
"download": "Download",
@@ -447,7 +446,8 @@
// {version} is a version number.
"versionShort": "v{version}",
// This text is shown on its own before details about a warning.
- "warning": "Warning"
+ "warning": "Warning",
+ "none": "(none)"
},
"mixin": {
"request": {
diff --git a/test/components/date-range-picker.spec.js b/test/components/date-range-picker.spec.js
index 6cbaa69fa..c8aa1373c 100644
--- a/test/components/date-range-picker.spec.js
+++ b/test/components/date-range-picker.spec.js
@@ -22,7 +22,7 @@ const mountComponent = (options) => {
const merged = mergeMountOptions(options, {
props: {
modelValue: ['1970-01-01', '1970-01-01'],
- placeholder: 'Date range'
+ label: 'Date range'
}
});
merged.props.modelValue = merged.props.modelValue.map(fromISO);
@@ -248,26 +248,6 @@ describe('DateRangePicker', () => {
});
});
- describe('placeholder prop', () => {
- it('uses the placeholder prop', () => {
- const component = mountComponent({
- props: { placeholder: 'My date range', required: false }
- });
- const { placeholder } = component.get('input').attributes();
- placeholder.should.equal('My date range');
- component.get('.form-label').text().should.equal('My date range');
- });
-
- it('appends * to the placeholder if the required prop is true', () => {
- const component = mountComponent({
- props: { placeholder: 'My date range', required: true }
- });
- const { placeholder } = component.get('input').attributes();
- placeholder.should.equal('My date range *');
- component.get('.form-label').text().should.equal('My date range *');
- });
- });
-
it('adds the required class if the required prop is true', () => {
const component = mountComponent({
props: { required: true }
diff --git a/test/components/entity/download-button.spec.js b/test/components/entity/download-button.spec.js
index 161d366bf..0df8dc43d 100644
--- a/test/components/entity/download-button.spec.js
+++ b/test/components/entity/download-button.spec.js
@@ -19,7 +19,7 @@ describe('EntityDownloadButton', () => {
describe('text', () => {
it('shows the correct text', () => {
testData.extendedDatasets.createPast(1, { entities: 1000 });
- mountComponent().text().should.equal('Download 1,000 Entities');
+ mountComponent().text().should.equal('Download');
});
describe('entities are filtered', () => {
@@ -28,7 +28,7 @@ describe('EntityDownloadButton', () => {
const component = mountComponent({
props: { odataFilter: '__system/conflict ne null' }
});
- component.text().should.equal('Download matching Entities');
+ component.text().should.equal('Download');
});
it('shows correct text after first chunk of entities has loaded', () => {
@@ -41,7 +41,7 @@ describe('EntityDownloadButton', () => {
}
}
});
- component.text().should.equal('Download 1,000 matching Entities');
+ component.text().should.equal('Download');
});
});
});
diff --git a/test/components/entity/list.spec.js b/test/components/entity/list.spec.js
index 393dd17f4..dbc4f8107 100644
--- a/test/components/entity/list.spec.js
+++ b/test/components/entity/list.spec.js
@@ -64,13 +64,13 @@ describe('EntityList', () => {
app.vm.$container.requestData.dataset.entities.should.equal(1);
app.get('#page-head-tabs li.active .badge').text().should.equal('1');
const button = app.get('#entity-download-button');
- button.text().should.equal('Download 1 Entity');
+ button.text().should.equal('Download');
})
.afterResponse(app => {
app.vm.$container.requestData.dataset.entities.should.equal(2);
app.get('#page-head-tabs li.active .badge').text().should.equal('2');
const button = app.get('#entity-download-button');
- button.text().should.equal('Download 2 Entities');
+ button.text().should.equal('Download');
});
});
@@ -491,7 +491,7 @@ describe('EntityList', () => {
describe('after a successful response', () => {
const del = () => {
testData.extendedEntities.createPast(1, { label: 'My Entity' });
- return load('/projects/1/entity-lists/trees/entities', { root: false })
+ return load('/projects/1/entity-lists/trees/entities')
.complete()
.request(async (component) => {
await component.get('.entity-metadata-row .delete-button').trigger('click');
@@ -518,8 +518,8 @@ describe('EntityList', () => {
it('updates the entity count', async () => {
const component = await del();
- const text = component.get('#entity-download-button').text();
- text.should.equal('Download 0 Entities');
+ const text = component.get('#page-head-tabs li:nth-of-type(2)').text();
+ text.should.equal('Data 0');
});
});
@@ -1039,13 +1039,12 @@ describe('EntityList', () => {
});
});
- it('disables filters and download button', () => {
+ it('disables filters', () => {
testData.extendedEntities.createPast(1, { label: 'My Entity' });
testData.extendedEntities.createPast(1, { label: 'deleted 1', deletedAt: new Date().toISOString() });
testData.extendedEntities.createPast(1, { label: 'deleted 2', deletedAt: new Date().toISOString() });
return loadEntityList({ props: { deleted: true } })
.afterResponse(component => {
- component.find('#entity-download-button').attributes('aria-disabled').should.equal('true');
component.getComponent('#entity-filters').props().disabled.should.be.true;
});
});
diff --git a/test/components/form-draft/testing.spec.js b/test/components/form-draft/testing.spec.js
index af6006e10..1dcc69d4b 100644
--- a/test/components/form-draft/testing.spec.js
+++ b/test/components/form-draft/testing.spec.js
@@ -44,7 +44,7 @@ describe('FormDraftTesting', () => {
root: false
});
const text = component.getComponent(SubmissionDownloadButton).text();
- text.should.equal('Download 2 Submissions…');
+ text.should.equal('Download');
});
});
diff --git a/test/components/form/submissions.spec.js b/test/components/form/submissions.spec.js
index 649d8fbf9..49d3ecd47 100644
--- a/test/components/form/submissions.spec.js
+++ b/test/components/form/submissions.spec.js
@@ -42,7 +42,7 @@ describe('FormSubmissions', () => {
root: false
});
const text = component.getComponent(SubmissionDownloadButton).text();
- text.should.equal('Download 1 Submission…');
+ text.should.equal('Download');
});
it('updates the tab badge if the count changes', () => {
diff --git a/test/components/submission/download-button.spec.js b/test/components/submission/download-button.spec.js
index fd0764d5a..f6448da08 100644
--- a/test/components/submission/download-button.spec.js
+++ b/test/components/submission/download-button.spec.js
@@ -23,7 +23,7 @@ describe('SubmissionDownloadButton', () => {
describe('text', () => {
it('shows the correct text if the submissions are not filtered', () => {
testData.extendedForms.createPast(1, { submissions: 2 });
- mountComponent().text().should.equal('Download 2 Submissions…');
+ mountComponent().text().should.equal('Download');
});
describe('submissions are filtered', () => {
@@ -32,7 +32,7 @@ describe('SubmissionDownloadButton', () => {
const component = mountComponent({
props: { filtered: true }
});
- component.text().should.equal('Download matching Submissions…');
+ component.text().should.equal('Download');
});
it('shows correct text after first chunk of submissions has loaded', () => {
@@ -45,7 +45,7 @@ describe('SubmissionDownloadButton', () => {
}
}
});
- component.text().should.equal('Download 1 matching Submission…');
+ component.text().should.equal('Download');
});
});
});
diff --git a/test/components/submission/download.spec.js b/test/components/submission/download.spec.js
index 99ccba8c7..ad771fbb5 100644
--- a/test/components/submission/download.spec.js
+++ b/test/components/submission/download.spec.js
@@ -15,6 +15,7 @@ import { mockLogin } from '../../util/session';
import { relativeUrl } from '../../util/request';
import { testRequestData } from '../../util/request-data';
import { waitUntil } from '../../util/util';
+import { load } from '../../util/http';
const mountComponent = (options = undefined) => {
// First, merge mount options in order to get the test data associated with
@@ -55,6 +56,17 @@ describe('SubmissionDownload', () => {
it('toggles the modal', () => {
testData.extendedForms.createPast(1);
+ return load('/projects/1/forms/f/submissions')
+ .complete()
+ .testModalToggles({
+ modal: SubmissionDownload,
+ show: '#submission-download-button',
+ hide: '.modal-actions .btn'
+ });
+ });
+
+ it('toggles the modal - draft', () => {
+ testData.extendedForms.createPast(1, { draft: true });
return loadSubmissionList().testModalToggles({
modal: SubmissionDownload,
show: '#submission-download-button',
diff --git a/test/components/submission/list.spec.js b/test/components/submission/list.spec.js
index 6655c09f3..525cda7b7 100644
--- a/test/components/submission/list.spec.js
+++ b/test/components/submission/list.spec.js
@@ -324,16 +324,27 @@ describe('SubmissionList', () => {
});
});
- it('disables filters and download button', () => {
+ it('disables filters', () => {
testData.extendedSubmissions.createPast(1, { meta: { instanceName: 'live' } });
testData.extendedSubmissions.createPast(1, { meta: { instanceName: 'deleted 1' }, deletedAt: new Date().toISOString() });
testData.extendedSubmissions.createPast(1, { meta: { instanceName: 'deleted 2' }, deletedAt: new Date().toISOString() });
return loadSubmissionList({ props: { deleted: true } })
.afterResponse(component => {
- component.find('#submission-download-button').attributes('aria-disabled').should.equal('true');
component.getComponent('#submission-filters').props().disabled.should.be.true;
});
});
+
+ it('disables download button', () => {
+ testData.extendedSubmissions.createPast(1, { deletedAt: new Date().toISOString() });
+ return load('/projects/1/forms/f/submissions', { root: false, container: { router: testRouter() } })
+ .complete()
+ .request(component =>
+ component.get('.toggle-deleted-submissions').trigger('click'))
+ .respondWithData(testData.submissionDeletedOData)
+ .afterResponses((component) => {
+ component.find('#submission-download-button').attributes('aria-disabled').should.equal('true');
+ });
+ });
});
describe('delete', () => {
@@ -378,7 +389,7 @@ describe('SubmissionList', () => {
describe('after a successful response', () => {
const del = () => {
testData.extendedSubmissions.createPast(1);
- return load('/projects/1/forms/f/submissions', { root: false })
+ return load('/projects/1/forms/f/submissions')
.complete()
.request(async (component) => {
await component.get('.submission-metadata-row .delete-button').trigger('click');
@@ -405,8 +416,8 @@ describe('SubmissionList', () => {
it('updates the submission count', async () => {
const component = await del();
- const text = component.get('#submission-download-button').text();
- text.should.equal('Download 0 Submissions…');
+ const text = component.get('#form-head-form-tabs li:nth-of-type(3)').text();
+ text.should.equal('Submissions 0');
});
it('shows deleted submission button', async () => {
diff --git a/test/util/entity.js b/test/util/entity.js
index 2038b1369..8162593b2 100644
--- a/test/util/entity.js
+++ b/test/util/entity.js
@@ -22,6 +22,9 @@ export const loadEntityList = (mountOptions = {}) => {
dataset
}),
router: mockRouter('')
+ },
+ global: {
+ provide: { projectId: project.id.toString(), datasetName: dataset.name }
}
});
const { deleted } = mergedOptions.props;
diff --git a/transifex/strings_en.json b/transifex/strings_en.json
index 1b871823f..2cde1be98 100644
--- a/transifex/strings_en.json
+++ b/transifex/strings_en.json
@@ -342,8 +342,8 @@
"developer_comment": "This is the text for an action, for example, the text of a button."
},
"createSubmission": {
- "string": "New",
- "developer_comment": "This is the text of a button that is used to fill out a new Submission. It is shown next to a heading whose text is \"Submissions\"."
+ "string": "New Submission",
+ "developer_comment": "This is the text of a button that is used to fill out a new Submission."
},
"delete": {
"string": "Delete",
@@ -941,6 +941,9 @@
"string": "Warning",
"developer_comment": "This text is shown on its own before details about a warning."
},
+ "none": {
+ "string": "(none)"
+ },
"currentDraft": {
"string": "Your Current Draft",
"developer_comment": "This is a title shown above a section of the page."
@@ -1517,6 +1520,9 @@
}
},
"DatasetEntities": {
+ "upload": {
+ "string": "Upload Entities"
+ },
"alert": {
"upload": {
"string": "Success! Your Entities have been uploaded."
@@ -3539,12 +3545,8 @@
},
"OdataDataAccess": {
"action": {
- "apiAccess": {
- "string": "API access",
- "developer_comment": "This is the text for an action, for example, the text of a button."
- },
- "analyze": {
- "string": "Analyze via OData",
+ "connectData": {
+ "string": "Connect Data",
"developer_comment": "This is the text for an action, for example, the text of a button."
}
}
@@ -4482,20 +4484,8 @@
"SubmissionDownloadDropdown": {
"action": {
"download": {
- "unfiltered": {
- "string": "{count, plural, one {Download {count} Submission} other {Download {count} Submissions}}",
- "developer_comment": "This is the text for an action, for example, the text of a button."
- },
- "filtered": {
- "withoutCount": {
- "string": "Download matching Submissions",
- "developer_comment": "This is the text of a button. This text is shown when the number of matching Submissions is unknown."
- },
- "withCount": {
- "string": "{count, plural, one {Download {count} matching Submission} other {Download {count} matching Submissions}}",
- "developer_comment": "This is the text for an action, for example, the text of a button."
- }
- }
+ "string": "Download",
+ "developer_comment": "This is the text for an action, for example, the text of a button."
}
}
},
@@ -4598,7 +4588,7 @@
},
"SubmissionFieldDropdown": {
"placeholder": {
- "string": "{selected} of {total}",
+ "string": "{count, plural, one {{selected} of {total} column shown} other {{selected} of {total} columns shown}}",
"developer_comment": "This is the text of a dropdown that allows the user to select which columns to display in a table. {selected} is the number of columns selected; {total} is the total number of columns."
},
"field": {