Skip to content

Commit

Permalink
Merge pull request #10205 from owncloud/refactor-resource-conflict-modal
Browse files Browse the repository at this point in the history
refactor: resource conflict modal
  • Loading branch information
JammingBen authored Dec 19, 2023
2 parents 0614cef + 923e5c5 commit 13f07aa
Show file tree
Hide file tree
Showing 13 changed files with 247 additions and 177 deletions.
83 changes: 3 additions & 80 deletions packages/design-system/src/components/OcModal/OcModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,6 @@
@keydown.enter.prevent="confirm"
/>
</template>
<div v-if="checkboxLabel" class="oc-modal-body-actions oc-flex oc-flex-left">
<oc-checkbox
v-model="checkboxValue"
size="medium"
:label="checkboxLabel"
:aria-label="checkboxLabel"
/>
</div>
</div>

<div v-if="!hideActions" class="oc-modal-body-actions oc-flex oc-flex-right">
Expand All @@ -70,15 +62,6 @@
@click="cancelModalAction"
v-text="buttonCancelText"
/>
<oc-button
v-if="buttonSecondaryText"
ref="secondaryButton"
class="oc-modal-body-actions-secondary oc-ml-s"
:variation="buttonSecondaryVariation"
:appearance="buttonSecondaryAppearance"
@click="secondaryModalAction"
v-text="buttonSecondaryText"
/>
<oc-button
v-if="!withoutButtonConfirm"
ref="primaryButton"
Expand All @@ -98,7 +81,6 @@
<script lang="ts">
import { defineComponent, PropType, ComponentPublicInstance, ref, onMounted, unref } from 'vue'
import OcButton from '../OcButton/OcButton.vue'
import OcCheckbox from '../OcCheckbox/OcCheckbox.vue'
import OcIcon from '../OcIcon/OcIcon.vue'
import OcTextInput from '../OcTextInput/OcTextInput.vue'
import { FocusTrap } from 'focus-trap-vue'
Expand Down Expand Up @@ -126,7 +108,6 @@ export default defineComponent({
components: {
OcButton,
OcCheckbox,
OcIcon,
OcTextInput,
FocusTrap
Expand Down Expand Up @@ -169,14 +150,6 @@ export default defineComponent({
required: false,
default: null
},
/**
* Modal checkbox label
*/
checkboxLabel: {
type: String,
required: false,
default: ''
},
/**
* Contextual helper label
*/
Expand Down Expand Up @@ -223,36 +196,6 @@ export default defineComponent({
return ['outline', 'filled', 'raw'].includes(value)
}
},
/**
* Text of the secondary button
*/
buttonSecondaryText: {
type: String,
required: false,
default: ''
},
/**
* Variation type of the secondary button
*/
buttonSecondaryVariation: {
type: String,
required: false,
default: 'passive',
validator: (value: string) => {
return ['passive', 'primary', 'danger', 'success', 'warning'].includes(value)
}
},
/**
* Appearance of the secondary button
*/
buttonSecondaryAppearance: {
type: String,
required: false,
default: 'outline',
validator: (value: string) => {
return ['outline', 'filled', 'raw'].includes(value)
}
},
/**
* Text of the confirm button
*/
Expand Down Expand Up @@ -376,28 +319,22 @@ export default defineComponent({
default: false
}
},
emits: ['cancel', 'confirm', 'confirm-secondary', 'input', 'checkbox-changed'],
emits: ['cancel', 'confirm', 'input'],
setup() {
const primaryButton = ref(null)
const secondaryButton = ref(null)
const cancelButton = ref(null)
const setButtonsEqualWidth = () => {
const _primaryButton = unref(primaryButton)
const _secondaryButton = unref(secondaryButton)
const _cancelButton = unref(cancelButton)
const primaryWidth = _primaryButton?.$el?.offsetWidth || 0
const secondaryWidth = _secondaryButton?.$el?.offsetWidth || 0
const cancelWidth = _cancelButton?.$el?.offsetWidth || 0
const maxWidth = Math.max(primaryWidth, secondaryWidth, cancelWidth)
const maxWidth = Math.max(primaryWidth, cancelWidth)
if (_primaryButton?.$el) {
_primaryButton.$el.style.minWidth = `${maxWidth}px`
}
if (_secondaryButton?.$el) {
_secondaryButton.$el.style.minWidth = `${maxWidth}px`
}
if (_cancelButton?.$el) {
_cancelButton.$el.style.minWidth = `${maxWidth}px`
}
Expand All @@ -408,14 +345,12 @@ export default defineComponent({
return {
primaryButton,
secondaryButton,
cancelButton
}
},
data() {
return {
userInputValue: null,
checkboxValue: false
userInputValue: null
}
},
computed: {
Expand Down Expand Up @@ -456,10 +391,6 @@ export default defineComponent({
inputValue: {
handler: 'inputAssignPropAsValue',
immediate: true
},
checkboxValue: {
handler: 'checkboxValueChanged',
immediate: true
}
},
methods: {
Expand All @@ -469,9 +400,6 @@ export default defineComponent({
*/
this.$emit('cancel')
},
secondaryModalAction() {
this.$emit('confirm-secondary')
},
confirm() {
if (this.buttonConfirmDisabled || this.inputError) {
return
Expand All @@ -493,9 +421,6 @@ export default defineComponent({
},
inputAssignPropAsValue(value) {
this.userInputValue = value
},
checkboxValueChanged(value) {
this.$emit('checkbox-changed', value)
}
}
})
Expand Down Expand Up @@ -694,7 +619,6 @@ export default defineComponent({
message="Do you accept our terms of use?"
button-cancel-text="Decline"
button-confirm-text="Accept"
checkbox-label="I accept the terms of use"
class="oc-mb-l oc-position-relative"
/>
</div>
Expand All @@ -708,7 +632,6 @@ export default defineComponent({
message="Do you accept our terms of use?"
button-cancel-text="Decline"
button-confirm-text="Accept"
button-secondary-text="Accept some"
class="oc-mb-l oc-position-relative"
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ exports[`OcModal displays input 1`] = `
<!--v-if-->
<!--v-if-->
<oc-text-input-stub class="oc-modal-body-input" clearbuttonaccessiblelabel="" clearbuttonenabled="false" disabled="false" fixmessageline="true" id="oc-textinput-1" label="Folder name" modelvalue="New folder" passwordpolicy="[object Object]" readonly="false" type="text"></oc-text-input-stub>
<!--v-if-->
</div>
<div class="oc-modal-body-actions oc-flex oc-flex-right">
<oc-button-stub appearance="outline" class="oc-modal-body-actions-cancel" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" style="min-width: 0px;" submit="button" type="button" variation="passive">Cancel</oc-button-stub>
<!--v-if-->
<oc-button-stub appearance="filled" class="oc-modal-body-actions-confirm oc-ml-s" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" style="min-width: 0px;" submit="button" type="button" variation="primary">Confirm</oc-button-stub>
</div>
</div>
Expand All @@ -36,11 +34,9 @@ exports[`OcModal hides icon if not specified 1`] = `
<p class="oc-modal-body-message oc-mt-rm oc-mb-rm">Example message</p>
<!--v-if-->
<!--v-if-->
<!--v-if-->
</div>
<div class="oc-modal-body-actions oc-flex oc-flex-right">
<oc-button-stub appearance="outline" class="oc-modal-body-actions-cancel" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" style="min-width: 0px;" submit="button" type="button" variation="passive">Cancel</oc-button-stub>
<!--v-if-->
<oc-button-stub appearance="filled" class="oc-modal-body-actions-confirm oc-ml-s" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" style="min-width: 0px;" submit="button" type="button" variation="primary">Confirm</oc-button-stub>
</div>
</div>
Expand All @@ -60,11 +56,9 @@ exports[`OcModal matches snapshot 1`] = `
<p class="oc-modal-body-message oc-mt-rm oc-mb-rm">Example message</p>
<!--v-if-->
<!--v-if-->
<!--v-if-->
</div>
<div class="oc-modal-body-actions oc-flex oc-flex-right">
<oc-button-stub appearance="outline" class="oc-modal-body-actions-cancel" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" style="min-width: 0px;" submit="button" type="button" variation="passive">Cancel</oc-button-stub>
<!--v-if-->
<oc-button-stub appearance="filled" class="oc-modal-body-actions-confirm oc-ml-s" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" style="min-width: 0px;" submit="button" type="button" variation="primary">Confirm</oc-button-stub>
</div>
</div>
Expand All @@ -84,11 +78,9 @@ exports[`OcModal overrides props message with slot 1`] = `
<div class="oc-modal-body-message">
<p>Slot message</p>
</div>
<!--v-if-->
</div>
<div class="oc-modal-body-actions oc-flex oc-flex-right">
<oc-button-stub appearance="outline" class="oc-modal-body-actions-cancel" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" style="min-width: 0px;" submit="button" type="button" variation="passive">Cancel</oc-button-stub>
<!--v-if-->
<oc-button-stub appearance="filled" class="oc-modal-body-actions-confirm oc-ml-s" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" style="min-width: 0px;" submit="button" type="button" variation="primary">Confirm</oc-button-stub>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ export class ResourceConflict extends ConflictDialog {
const resolvedConflict: ResolveConflict = await this.resolveFileExists(
{ name: conflict.name, isFolder } as Resource,
conflictsLeft,
conflictsLeft === 1,
isFolder,
true
)
Expand Down
133 changes: 133 additions & 0 deletions packages/web-pkg/src/components/Modals/ResourceConflictModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<template>
<span v-text="message" />
<div class="oc-my-m">
<oc-checkbox
v-if="conflictCount > 1"
v-model="checkboxValue"
size="medium"
:label="checkboxLabel"
:aria-label="checkboxLabel"
/>
</div>
<div class="oc-flex oc-flex-right oc-flex-middle oc-mt-m">
<oc-button
class="oc-modal-body-actions-cancel oc-ml-s"
appearance="outline"
variation="passive"
@click="onCancel"
>{{ $gettext('Skip') }}
</oc-button>
<oc-button
class="oc-modal-body-actions-secondary oc-ml-s"
appearance="outline"
variation="passive"
@click="onConfirmSecondary"
>{{ $gettext('Replace') }}
</oc-button>
<oc-button
class="oc-modal-body-actions-confirm oc-ml-s"
appearance="filled"
variation="primary"
@click="onConfirm"
>{{ $gettext('Keep both') }}
</oc-button>
</div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType, ref, unref } from 'vue'
import { useGettext } from 'vue3-gettext'
import { useStore } from '../../composables'
import { Resource } from '@ownclouders/web-client/src'
import { ResolveConflict, ResolveStrategy } from '../../helpers/resource'
export default defineComponent({
name: 'ResourceConflictModal',
props: {
resource: { type: Object as PropType<Resource>, required: true },
conflictCount: { type: Number, required: true },
callbackFn: {
type: Function as PropType<(resolveConflict: ResolveConflict) => void>,
required: true
},
suggestMerge: { type: Boolean, default: true },
separateSkipHandling: { type: Boolean, default: false }
},
setup(props, { expose }) {
const store = useStore()
const { $gettext } = useGettext()
const checkboxValue = ref()
const checkboxLabel = computed(() => {
if (props.conflictCount < 2) {
return ''
}
if (!props.separateSkipHandling) {
return $gettext(
'Apply to all %{count} conflicts',
{ count: props.conflictCount.toString() },
true
)
} else if (props.resource.isFolder) {
return $gettext(
'Apply to all %{count} folders',
{ count: props.conflictCount.toString() },
true
)
} else {
return $gettext(
'Apply to all %{count} files',
{ count: props.conflictCount.toString() },
true
)
}
})
const message = computed(() =>
props.resource.isFolder
? $gettext(
'Folder with name "%{name}" already exists.',
{ name: props.resource.name },
true
)
: $gettext('File with name "%{name}" already exists.', { name: props.resource.name }, true)
)
const onConfirm = async () => {
await store.dispatch('hideModal')
props.callbackFn({
strategy: ResolveStrategy.KEEP_BOTH,
doForAllConflicts: unref(checkboxValue)
})
}
const onConfirmSecondary = async () => {
await store.dispatch('hideModal')
const strategy = props.suggestMerge ? ResolveStrategy.MERGE : ResolveStrategy.REPLACE
props.callbackFn({
strategy,
doForAllConflicts: unref(checkboxValue)
})
}
const onCancel = async () => {
await store.dispatch('hideModal')
props.callbackFn({
strategy: ResolveStrategy.SKIP,
doForAllConflicts: unref(checkboxValue)
})
}
expose({ onConfirm, onConfirmSecondary, onCancel })
return {
message,
checkboxValue,
checkboxLabel,
onConfirm,
onConfirmSecondary,
onCancel
}
}
})
</script>
1 change: 1 addition & 0 deletions packages/web-pkg/src/components/Modals/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as ResourceConflictModal } from './ResourceConflictModal.vue'
1 change: 1 addition & 0 deletions packages/web-pkg/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './AppTemplates'
export * from './ContextActions'
export * from './FilesList'
export * from './Filters'
export * from './Modals'
export * from './SideBar'
export * from './Search'
export * from './Spaces'
Expand Down
Loading

0 comments on commit 13f07aa

Please sign in to comment.