Skip to content

Commit

Permalink
feat: simplify ConflictPicker by providing content only + preview resize
Browse files Browse the repository at this point in the history
Signed-off-by: John Molakvoæ <[email protected]>
  • Loading branch information
skjnldsv committed Sep 1, 2023
1 parent a47ad15 commit 2606188
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 107 deletions.
12 changes: 7 additions & 5 deletions cypress/components/ConflictPicker.cy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable no-unused-expressions */
// dist file might not be built when running eslint only
// eslint-disable-next-line import/no-unresolved,n/no-missing-import
import type { ConflictResolutionResult } from '../../lib'

import { File as NcFile } from '@nextcloud/files'
import { openConflictPicker } from '../../dist/index.mjs'

Expand Down Expand Up @@ -95,7 +97,7 @@ describe('ConflictPicker resolving', () => {
cy.get('[data-cy-conflict-picker-input-incoming="all"] input').check({ force: true })
cy.get('[data-cy-conflict-picker-submit]').click()

promise.then((results) => {
promise.then((results: ConflictResolutionResult) => {
expect(results.selected).to.deep.equal(images)
expect(results.renamed).to.have.length(0)

Expand Down Expand Up @@ -128,7 +130,7 @@ describe('ConflictPicker resolving', () => {
cy.get('[data-cy-conflict-picker-input-existing="all"] input').check({ force: true })
cy.get('[data-cy-conflict-picker-submit]').click()

promise.then((results) => {
promise.then((results: ConflictResolutionResult) => {
expect(results.selected).to.have.length(0)
expect(results.renamed).to.have.length(0)

Expand Down Expand Up @@ -163,7 +165,7 @@ describe('ConflictPicker resolving', () => {
cy.get('[data-cy-conflict-picker-submit]').click()

// We only return the files to handle
promise.then((results) => {
promise.then((results: ConflictResolutionResult) => {
expect(results.selected).to.deep.equal([images[0]])
expect(results.renamed).to.have.length(0)

Expand Down Expand Up @@ -197,7 +199,7 @@ describe('ConflictPicker resolving', () => {
cy.get('[data-cy-conflict-picker-input-existing="all"] input').check({ force: true })
cy.get('[data-cy-conflict-picker-submit]').click()

promise.then((results) => {
promise.then((results: ConflictResolutionResult) => {
expect(results.selected).to.have.length(0)
expect(results.renamed).to.have.length(2)
expect(results.renamed[0].name).to.equal('image1 (1).jpg')
Expand Down Expand Up @@ -231,7 +233,7 @@ describe('ConflictPicker resolving', () => {
cy.get('[data-cy-conflict-picker-fieldset]').should('have.length', 3)
cy.get('[data-cy-conflict-picker-skip]').click()

promise.then((results) => {
promise.then((results: ConflictResolutionResult) => {
expect(results.selected).to.have.length(0)
expect(results.renamed).to.have.length(0)

Expand Down
10 changes: 10 additions & 0 deletions cypress/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": [
"@tsconfig/cypress/tsconfig.json",
"../tsconfig.json"
],
"include": ["./**/*.ts"],
"compilerOptions": {
"types": ["cypress"]
}
}
79 changes: 44 additions & 35 deletions lib/components/ConflictPicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@
</fieldset>

<!-- Files loop -->
<NodesPicker v-for="(node, index) in conflicts"
<NodesPicker v-for="(node, index) in files"
ref="nodesPicker"
:key="node.fileid"
:incoming="files[index]"
:existing="conflicts[index]"
:incoming="conflicts[index]"
:existing="files[index]"
:new-selected.sync="newSelected"
:old-selected.sync="oldSelected" />
</form>
Expand Down Expand Up @@ -72,6 +72,7 @@

<script lang="ts">
import type { ConflictResolutionResult } from '../index.ts'
import type { PropType } from 'vue'
import { basename, extname } from 'path'
import { Node } from '@nextcloud/files'
Expand All @@ -88,6 +89,8 @@ import { n, t } from '../utils/l10n.ts'
import logger from '../utils/logger.ts'
import NodesPicker from './NodesPicker.vue'
export type NodesPickerRef = InstanceType<typeof NodesPicker>
export default Vue.extend({
name: 'ConflictPicker',
Expand All @@ -109,45 +112,42 @@ export default Vue.extend({
/** All the existing files in the current directory */
content: {
type: Array as () => Node[],
required: true,
},
/** Existing files to be replaced */
conflicts: {
type: Array as () => Node[],
type: Array as PropType<Node[]>,
required: true,
},
/** New files being moved/uploaded */
files: {
type: Array as () => (Node|File)[],
conflicts: {
type: Array as PropType<(Node|File)[]>,
required: true,
},
},
data() {
return {
// computed list of conflicting files already present in the directory
files: [] as Node[],
opened: true,
blockedTitle: t('You need to select at least one version of each file to continue.'),
newSelected: [] as Node[],
newSelected: [] as (Node|File)[],
oldSelected: [] as Node[],
}
},
computed: {
name() {
if (this?.dirname?.trim?.() !== '') {
return n('{count} file conflict in {dirname}', '{count} file conflicts in {dirname}', this.files.length, {
count: this.files.length,
return n('{count} file conflict in {dirname}', '{count} file conflicts in {dirname}', this.conflicts.length, {
count: this.conflicts.length,
dirname: this.dirname,
})
}
return n('{count} file conflict', '{count} files conflict', this.files.length, { count: this.files.length })
return n('{count} file conflict', '{count} files conflict', this.conflicts.length, { count: this.conflicts.length })
},
skipButtonLabel() {
return n('Skip this file', 'Skip {count} files', this.files.length, { count: this.files.length })
return n('Skip this file', 'Skip {count} files', this.conflicts.length, { count: this.conflicts.length })
},
// Select all incoming files
Expand All @@ -164,7 +164,7 @@ export default Vue.extend({
},
isAllNewSelected() {
return this.newSelected.length === this.files.length
return this.newSelected.length === this.conflicts.length
},
isNoneNewSelected() {
return this.newSelected.length === 0
Expand All @@ -187,7 +187,7 @@ export default Vue.extend({
},
isAllOldSelected() {
return this.oldSelected.length === this.conflicts.length
return this.oldSelected.length === this.files.length
},
isNoneOldSelected() {
return this.oldSelected.length === 0
Expand All @@ -203,26 +203,35 @@ export default Vue.extend({
}
// If we're in an intermediate state, we need to check
// if all files have at least one version selected.
return this.$refs?.nodesPicker?.every?.(picker => picker.isEnoughSelected)
return (this.$refs?.nodesPicker as NodesPickerRef[])?.every?.(picker => picker.isEnoughSelected)
},
},
beforeMount() {
if (this.files.length === 0 || this.conflicts.length === 0) {
this.onCancel()
throw new Error('ConflictPicker: files and conflicts must not be empty')
// Using map keep the same order
this.files = this.conflicts.map((conflict: File|Node) => {
const name = (conflict instanceof File) ? conflict.name : conflict.basename
return this.content.find((node: Node) => node.basename === name)
}).filter(Boolean) as Node[]
logger.debug('ConflictPicker initialised', { files: this.files, conflicts: this.conflicts, content: this.content })
if (this.conflicts.length === 0 || this.files.length === 0) {
const error = new Error('ConflictPicker: files and conflicts must not be empty')
this.onCancel(error)
throw error
}
if (this.files.length !== this.conflicts.length) {
this.onCancel()
throw new Error('ConflictPicker: files and conflicts must have the same length')
if (this.conflicts.length !== this.files.length) {
const error = new Error('ConflictPicker: files and conflicts must have the same length')
this.onCancel(error)
throw error
}
},
methods: {
onCancel() {
onCancel(error?: Error) {
this.opened = false
this.$emit('cancel')
this.$emit('cancel', error)
},
onSkip() {
Expand Down Expand Up @@ -288,9 +297,9 @@ export default Vue.extend({
/**
* Get a unique name for a file based
* on the existing directory content.
* @param name The original file name with extension
* @param names The existing directory content names
* @return A unique name
* @param {string} name The original file name with extension
* @param {string} names The existing directory content names
* @return {string} A unique name
* TODO: migrate to @nextcloud/files
*/
getUniqueName(name: string, names: string[]): string {
Expand Down Expand Up @@ -322,20 +331,20 @@ export default Vue.extend({
}
},
onSelectAllNew(selected) {
onSelectAllNew(selected: boolean) {
if (selected) {
logger.debug('Selected all new files')
this.newSelected = this.files
this.newSelected = this.conflicts
} else {
logger.debug('Cleared new selection')
this.newSelected = []
}
},
onSelectAllOld(selected) {
onSelectAllOld(selected: boolean) {
if (selected) {
logger.debug('Selected all existing files')
this.oldSelected = this.conflicts
this.oldSelected = this.files
} else {
logger.debug('Cleared old selection')
this.oldSelected = []
Expand Down
Loading

0 comments on commit 2606188

Please sign in to comment.