From 54ed37e0f7c7dea76ca82f4b691f93be716d3890 Mon Sep 17 00:00:00 2001 From: Matthew White Date: Thu, 25 May 2023 15:19:50 -0400 Subject: [PATCH 01/11] Add useRowChanged() composable to highlight row that has changed --- src/assets/scss/app.scss | 12 ++++++++ src/components/submission/metadata-row.vue | 16 +++++------ src/composables/row-changed.js | 18 ++++++++++++ test/composables/row-changed.spec.js | 33 ++++++++++++++++++++++ test/util/components/row-changed.vue | 26 +++++++++++++++++ 5 files changed, 97 insertions(+), 8 deletions(-) create mode 100644 src/composables/row-changed.js create mode 100644 test/composables/row-changed.spec.js create mode 100644 test/util/components/row-changed.vue diff --git a/src/assets/scss/app.scss b/src/assets/scss/app.scss index 7ddafe256..51a6cf588 100644 --- a/src/assets/scss/app.scss +++ b/src/assets/scss/app.scss @@ -825,3 +825,15 @@ becomes more complicated. } } } + + + +//////////////////////////////////////////////////////////////////////////////// +// useRowChanged() + +[data-use-row-changed="false"] { transition: background-color 0.6s 6s; } + +[data-use-row-changed="true"] { + background-color: #faf1cd; + transition: none; +} diff --git a/src/components/submission/metadata-row.vue b/src/components/submission/metadata-row.vue index 585d401e4..ea9ec4590 100644 --- a/src/components/submission/metadata-row.vue +++ b/src/components/submission/metadata-row.vue @@ -10,7 +10,7 @@ including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file. --> From 8c21c1255e9c3e498fd6256fad8afeceffcd1c2f Mon Sep 17 00:00:00 2001 From: Matthew White Date: Thu, 25 May 2023 15:19:51 -0400 Subject: [PATCH 02/11] Add component for table with frozen columns --- src/assets/scss/app.scss | 20 -- src/components/entity/table.vue | 102 +++----- src/components/project/form-access/table.vue | 90 ++++--- src/components/submission/metadata-row.vue | 85 ++----- src/components/submission/table.vue | 227 +++++------------- src/components/table-freeze.vue | 204 ++++++++++++++++ .../submission/metadata-row.spec.js | 16 +- test/components/submission/table.spec.js | 49 ---- test/components/table-freeze.spec.js | 73 ++++++ 9 files changed, 436 insertions(+), 430 deletions(-) create mode 100644 src/components/table-freeze.vue create mode 100644 test/components/table-freeze.spec.js diff --git a/src/assets/scss/app.scss b/src/assets/scss/app.scss index 51a6cf588..f5257d74f 100644 --- a/src/assets/scss/app.scss +++ b/src/assets/scss/app.scss @@ -574,26 +574,6 @@ select { } } -.table-frozen { - float: left; - width: auto; -} - -.table-container { - // Placing the margin here rather than on the table so that the horizontal - // scrollbar appears immediately below the table, above the margin. - margin-bottom: $margin-bottom-table; - overflow-x: auto; - - .table { - margin-bottom: 0; - } -} - -.table-actions { - margin-bottom: 20px; -} - .empty-table-message { color: #555; font-size: 15px; diff --git a/src/components/entity/table.vue b/src/components/entity/table.vue index 4e3623193..9c697a0a9 100644 --- a/src/components/entity/table.vue +++ b/src/components/entity/table.vue @@ -10,85 +10,59 @@ including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file. --> + diff --git a/src/components/submission/table.vue b/src/components/submission/table.vue index 539bf90f4..667b31108 100644 --- a/src/components/submission/table.vue +++ b/src/components/submission/table.vue @@ -10,196 +10,87 @@ including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file. --> + diff --git a/test/components/submission/metadata-row.spec.js b/test/components/submission/metadata-row.spec.js index d88c4e5f5..658e38bbc 100644 --- a/test/components/submission/metadata-row.spec.js +++ b/test/components/submission/metadata-row.spec.js @@ -1,9 +1,7 @@ -import sinon from 'sinon'; import { RouterLinkStub } from '@vue/test-utils'; import DateTime from '../../../src/components/date-time.vue'; import SubmissionMetadataRow from '../../../src/components/submission/metadata-row.vue'; -import SubmissionTable from '../../../src/components/submission/table.vue'; import SubmissionUpdateReviewState from '../../../src/components/submission/update-review-state.vue'; import testData from '../../data'; @@ -133,7 +131,7 @@ describe('SubmissionMetadataRow', () => { it('does not show the count if there has not been an edit', () => { testData.extendedSubmissions.createPast(1, { edits: 0 }); - mountComponent().find('.edits').exists().should.be.false(); + mountComponent().get('.edits').text().should.equal(''); }); }); @@ -190,18 +188,6 @@ describe('SubmissionMetadataRow', () => { submission.__id.should.equal('foo'); submission.__system.submitterId.should.equal('1'); }); - - it('calls SubmissionTable.methods.afterReview()', () => { - const afterReview = sinon.fake(); - return submit() - .beforeAnyResponse(component => { - const table = component.getComponent(SubmissionTable); - sinon.replace(table.vm, 'afterReview', afterReview); - }) - .afterResponse(() => { - afterReview.called.should.be.true(); - }); - }); }); }); diff --git a/test/components/submission/table.spec.js b/test/components/submission/table.spec.js index 487d8a418..ff9d23687 100644 --- a/test/components/submission/table.spec.js +++ b/test/components/submission/table.spec.js @@ -132,53 +132,4 @@ describe('SubmissionTable', () => { row.props().canUpdate.should.be.false(); }); }); - - describe('visibility of actions', () => { - it('shows actions if user hovers over a SubmissionDataRow', async () => { - testData.extendedForms.createPast(1, { submissions: 2 }); - testData.extendedSubmissions.createPast(2); - const component = mountComponent(); - await component.getComponent(SubmissionDataRow).trigger('mouseover'); - const metadataRows = component.findAllComponents(SubmissionMetadataRow); - metadataRows[0].classes('data-hover').should.be.true(); - metadataRows[1].classes('data-hover').should.be.false(); - }); - - it('toggles actions if user hovers over a new SubmissionDataRow', async () => { - testData.extendedForms.createPast(1, { submissions: 2 }); - testData.extendedSubmissions.createPast(2); - const component = mountComponent(); - const dataRows = component.findAllComponents(SubmissionDataRow); - await dataRows[0].trigger('mouseover'); - await dataRows[1].trigger('mouseover'); - const metadataRows = component.findAllComponents(SubmissionMetadataRow); - metadataRows[0].classes('data-hover').should.be.false(); - metadataRows[1].classes('data-hover').should.be.true(); - }); - - it('hides the actions if the cursor leaves the table', async () => { - testData.extendedForms.createPast(1, { submissions: 2 }); - testData.extendedSubmissions.createPast(2); - const component = mountComponent(); - await component.getComponent(SubmissionDataRow).trigger('mouseover'); - await component.get('#submission-table-data tbody').trigger('mouseleave'); - const metadataRow = component.getComponent(SubmissionMetadataRow); - metadataRow.classes('data-hover').should.be.false(); - }); - - it('adds a class for the actions trigger', async () => { - testData.extendedSubmissions.createPast(1); - const component = mountComponent({ attachTo: document.body }); - const tbody = component.get('#submission-table-metadata tbody'); - tbody.classes('submission-table-actions-trigger-hover').should.be.true(); - const btn = tbody.findAll('.btn'); - await btn[0].trigger('focusin'); - tbody.classes('submission-table-actions-trigger-focus').should.be.true(); - await component.getComponent(SubmissionMetadataRow).trigger('mousemove'); - tbody.classes('submission-table-actions-trigger-hover').should.be.true(); - await btn[1].trigger('focusin'); - await component.getComponent(SubmissionDataRow).trigger('mousemove'); - tbody.classes('submission-table-actions-trigger-hover').should.be.true(); - }); - }); }); diff --git a/test/components/table-freeze.spec.js b/test/components/table-freeze.spec.js new file mode 100644 index 000000000..4405ce042 --- /dev/null +++ b/test/components/table-freeze.spec.js @@ -0,0 +1,73 @@ +import TableFreeze from '../../src/components/table-freeze.vue'; + +import { mergeMountOptions, mount } from '../util/lifecycle'; + +const mountComponent = (options) => + mount(TableFreeze, mergeMountOptions(options, { + props: { + data: [{ id: 1, name: 'foo' }, { id: 1, name: 'bar' }], + keyProp: 'id' + }, + slots: { + headFrozen: 'id', + headScrolling: 'name', + dataFrozen: '{{ params.id }}', + dataScrolling: '{{ params.name }}' + } + })); + +describe('TableFreeze', () => { + describe('visibility of actions', () => { + const slots = { + headFrozen: 'Actions', + dataFrozen: ` + + Hover or focus to see actions +
+ +
+ + ` + }; + + it('shows actions if user hovers over a scrolling row', async () => { + const component = mountComponent({ slots }); + await component.get('.table-freeze-scrolling td').trigger('mouseover'); + const frozenRows = component.findAll('.table-freeze-frozen tr'); + frozenRows[0].classes('scrolling-hover').should.be.true(); + frozenRows[1].classes('scrolling-hover').should.be.false(); + }); + + it('toggles actions if user hovers over a new scrolling row', async () => { + const component = mountComponent({ slots }); + const scrollingRows = component.findAll('.table-freeze-scrolling tr'); + await scrollingRows[0].trigger('mouseover'); + await scrollingRows[1].trigger('mouseover'); + const frozenRows = component.findAll('.table-freeze-frozen tr'); + frozenRows[0].classes('scrolling-hover').should.be.false(); + frozenRows[1].classes('scrolling-hover').should.be.true(); + }); + + it('hides the actions if the cursor leaves the table', async () => { + const component = mountComponent({ slots }); + await component.get('.table-freeze-scrolling td').trigger('mouseover'); + await component.get('.table-freeze-scrolling tbody').trigger('mouseleave'); + const frozenRow = component.get('.table-freeze-frozen tr'); + frozenRow.classes('scrolling-hover').should.be.false(); + }); + + it('adds a class for the actions trigger', async () => { + const component = mountComponent({ slots, attachTo: document.body }); + const tbody = component.get('.table-freeze-frozen tbody'); + tbody.classes('actions-trigger-hover').should.be.true(); + const btn = tbody.findAll('.btn'); + await btn[0].trigger('focusin'); + tbody.classes('actions-trigger-focus').should.be.true(); + await tbody.get('td').trigger('mousemove'); + tbody.classes('actions-trigger-hover').should.be.true(); + await btn[1].trigger('focusin'); + await component.get('.table-freeze-scrolling td').trigger('mousemove'); + tbody.classes('actions-trigger-hover').should.be.true(); + }); + }); +}); From 774f3736830206aa65294f637efec089e6832273 Mon Sep 17 00:00:00 2001 From: Matthew White Date: Thu, 25 May 2023 15:19:53 -0400 Subject: [PATCH 03/11] Add "Last Updated / Actions" column to EntityTable The edit button will come in the next commit. --- src/components/entity/metadata-row.vue | 46 +++++++++++++++++--- src/components/entity/table.vue | 14 ++++++ test/components/entity/metadata-row.spec.js | 47 ++++++++++++++++++++- test/components/entity/table.spec.js | 4 +- test/data/entities.js | 6 ++- transifex/strings_en.json | 8 ++++ 6 files changed, 115 insertions(+), 10 deletions(-) diff --git a/src/components/entity/metadata-row.vue b/src/components/entity/metadata-row.vue index f429a03fa..0679ecee4 100644 --- a/src/components/entity/metadata-row.vue +++ b/src/components/entity/metadata-row.vue @@ -11,16 +11,32 @@ except according to the terms contained in the LICENSE file. --> @@ -69,5 +85,23 @@ const { entityPath } = useRoutes(); @include text-overflow-ellipsis; max-width: 250px; } + + .col-content { display: flex; } + .updated-at { + margin-right: 21px; + + &:empty { width: 75px; } + } + .updates { + color: #777; + margin-left: auto; + width: 41px; + + .icon-pencil { margin-right: 5px; } + } + .col-content .icon-angle-right { + color: $color-accent-primary; + font-size: 20px; + } } diff --git a/src/components/entity/table.vue b/src/components/entity/table.vue index 9c697a0a9..272cc8fed 100644 --- a/src/components/entity/table.vue +++ b/src/components/entity/table.vue @@ -17,6 +17,7 @@ except according to the terms contained in the LICENSE file. {{ $t('header.createdBy') }} {{ $t('header.createdAt') }} + {{ $t('header.updatedAtAndActions') }}