Skip to content

Commit

Permalink
refactor: modal implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
JammingBen committed Dec 20, 2023
1 parent 7d16901 commit b413395
Show file tree
Hide file tree
Showing 127 changed files with 1,598 additions and 1,717 deletions.
8 changes: 8 additions & 0 deletions changelog/unreleased/change-creating-modals
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Change: Creating modals

BREAKING CHANGE for developers: The way how to work with modals has been reworked. Modals can now be registered via the `registerModal` method provided by the `useModals` composable, instead of calling `createModal` or `hideModal` from the store.

For more details on how to use the modal please see the linked PR down below.

https://github.com/owncloud/web/pull/10212
https://github.com/owncloud/web/issues/10095
128 changes: 26 additions & 102 deletions packages/design-system/src/components/OcModal/OcModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@
v-model="userInputValue"
class="oc-modal-body-input"
:error-message="inputError"
:placeholder="inputPlaceholder"
:label="inputLabel"
:type="inputType"
:description-message="inputDescription"
:disabled="inputDisabled"
:fix-message-line="true"
:selection-range="inputSelectionRange"
@update:model-value="inputOnInput"
Expand All @@ -54,32 +52,32 @@
</div>

<div v-if="!hideActions" class="oc-modal-body-actions oc-flex oc-flex-right">
<oc-button
ref="cancelButton"
class="oc-modal-body-actions-cancel"
:variation="buttonCancelVariation"
:appearance="buttonCancelAppearance"
@click="cancelModalAction"
v-text="buttonCancelText"
/>
<oc-button
v-if="!withoutButtonConfirm"
ref="primaryButton"
class="oc-modal-body-actions-confirm oc-ml-s"
variation="primary"
:appearance="buttonConfirmAppearance"
:disabled="buttonConfirmDisabled || !!inputError"
@click="confirm"
v-text="buttonConfirmText"
/>
<div class="oc-modal-body-actions-grid">
<oc-button
class="oc-modal-body-actions-cancel"
variation="passive"
appearance="outline"
@click="cancelModalAction"
>{{ buttonCancelText }}</oc-button
>
<oc-button
v-if="!hideConfirmButton"
class="oc-modal-body-actions-confirm oc-ml-s"
variation="primary"
appearance="filled"
:disabled="buttonConfirmDisabled || !!inputError"
@click="confirm"
>{{ buttonConfirmText }}</oc-button
>
</div>
</div>
</div>
</focus-trap>
</div>
</template>

<script lang="ts">
import { defineComponent, PropType, ComponentPublicInstance, ref, onMounted, unref } from 'vue'
import { defineComponent, PropType, ComponentPublicInstance } from 'vue'
import OcButton from '../OcButton/OcButton.vue'
import OcIcon from '../OcIcon/OcIcon.vue'
import OcTextInput from '../OcTextInput/OcTextInput.vue'
Expand Down Expand Up @@ -174,28 +172,6 @@ export default defineComponent({
required: false,
default: 'Cancel'
},
/**
* Variation type of the cancel button
*/
buttonCancelVariation: {
type: String,
required: false,
default: 'passive',
validator: (value: string) => {
return ['passive', 'primary', 'danger', 'success', 'warning'].includes(value)
}
},
/**
* Appearance of the cancel button
*/
buttonCancelAppearance: {
type: String,
required: false,
default: 'outline',
validator: (value: string) => {
return ['outline', 'filled', 'raw'].includes(value)
}
},
/**
* Text of the confirm button
*/
Expand All @@ -204,17 +180,6 @@ export default defineComponent({
required: false,
default: 'Confirm'
},
/**
* Appearance of the confirm button
*/
buttonConfirmAppearance: {
type: String,
required: false,
default: 'filled',
validator: (value: string) => {
return ['outline', 'filled', 'raw'].includes(value)
}
},
/**
* Asserts whether the confirm action is disabled
*/
Expand All @@ -226,7 +191,7 @@ export default defineComponent({
/**
* Asserts whether the modal should render a confirm button
*/
withoutButtonConfirm: {
hideConfirmButton: {
type: Boolean,
required: false,
default: false
Expand Down Expand Up @@ -270,14 +235,6 @@ export default defineComponent({
required: false,
default: null
},
/**
* Placeholder of the text input field
*/
inputPlaceholder: {
type: String,
required: false,
default: null
},
/**
* Additional description message for the input field
*/
Expand All @@ -294,14 +251,6 @@ export default defineComponent({
required: false,
default: null
},
/**
* Asserts whether the input is disabled
*/
inputDisabled: {
type: Boolean,
required: false,
default: false
},
/**
* Overwrite default focused element
* Can be `#id, .class`.
Expand All @@ -320,34 +269,6 @@ export default defineComponent({
}
},
emits: ['cancel', 'confirm', 'input'],
setup() {
const primaryButton = ref(null)
const cancelButton = ref(null)
const setButtonsEqualWidth = () => {
const _primaryButton = unref(primaryButton)
const _cancelButton = unref(cancelButton)
const primaryWidth = _primaryButton?.$el?.offsetWidth || 0
const cancelWidth = _cancelButton?.$el?.offsetWidth || 0
const maxWidth = Math.max(primaryWidth, cancelWidth)
if (_primaryButton?.$el) {
_primaryButton.$el.style.minWidth = `${maxWidth}px`
}
if (_cancelButton?.$el) {
_cancelButton.$el.style.minWidth = `${maxWidth}px`
}
}
onMounted(() => {
setButtonsEqualWidth()
})
return {
primaryButton,
cancelButton
}
},
data() {
return {
userInputValue: null
Expand Down Expand Up @@ -537,6 +458,12 @@ export default defineComponent({
.oc-button {
border-radius: 4px;
}
&-grid {
display: inline-grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
}
}
}
Expand Down Expand Up @@ -570,8 +497,6 @@ export default defineComponent({
message="Are you sure you want to delete this file? All its content will be permanently removed. This action cannot be undone."
button-cancel-text="Cancel"
button-confirm-text="Delete"
button-confirm-appearance="filled"
button-confirm-variation="danger"
class="oc-mb-l oc-position-relative"
/>
</div>
Expand All @@ -597,7 +522,6 @@ export default defineComponent({
<oc-modal
title="Rename file lorem.txt"
button-cancel-text="Cancel"
button-cancel-variation="warning"
button-confirm-text="Rename"
class="oc-position-relative"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ exports[`OcModal displays input 1`] = `
<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>
</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>
<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 class="oc-modal-body-actions-grid">
<oc-button-stub appearance="outline" class="oc-modal-body-actions-cancel" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" submit="button" type="button" variation="passive">Cancel</oc-button-stub>
<oc-button-stub appearance="filled" class="oc-modal-body-actions-confirm oc-ml-s" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" submit="button" type="button" variation="primary">Confirm</oc-button-stub>
</div>
</div>
</div>
</focus-trap-stub>
Expand All @@ -36,8 +38,10 @@ exports[`OcModal hides icon if not specified 1`] = `
<!--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>
<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 class="oc-modal-body-actions-grid">
<oc-button-stub appearance="outline" class="oc-modal-body-actions-cancel" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" submit="button" type="button" variation="passive">Cancel</oc-button-stub>
<oc-button-stub appearance="filled" class="oc-modal-body-actions-confirm oc-ml-s" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" submit="button" type="button" variation="primary">Confirm</oc-button-stub>
</div>
</div>
</div>
</focus-trap-stub>
Expand All @@ -58,8 +62,10 @@ exports[`OcModal matches snapshot 1`] = `
<!--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>
<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 class="oc-modal-body-actions-grid">
<oc-button-stub appearance="outline" class="oc-modal-body-actions-cancel" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" submit="button" type="button" variation="passive">Cancel</oc-button-stub>
<oc-button-stub appearance="filled" class="oc-modal-body-actions-confirm oc-ml-s" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" submit="button" type="button" variation="primary">Confirm</oc-button-stub>
</div>
</div>
</div>
</focus-trap-stub>
Expand All @@ -80,8 +86,10 @@ exports[`OcModal overrides props message with slot 1`] = `
</div>
</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>
<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 class="oc-modal-body-actions-grid">
<oc-button-stub appearance="outline" class="oc-modal-body-actions-cancel" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" submit="button" type="button" variation="passive">Cancel</oc-button-stub>
<oc-button-stub appearance="filled" class="oc-modal-body-actions-confirm oc-ml-s" disabled="false" gapsize="medium" justifycontent="center" showspinner="false" size="medium" submit="button" type="button" variation="primary">Confirm</oc-button-stub>
</div>
</div>
</div>
</focus-trap-stub>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<form autocomplete="off" @submit.prevent="onConfirm">
<form autocomplete="off" @submit.prevent="$emit('confirm')">
<oc-text-input
id="create-group-input-display-name"
v-model="group.displayName"
Expand All @@ -10,35 +10,22 @@
@update:model-value="validateDisplayName"
/>
<input type="submit" class="oc-hidden" />
<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('Cancel') }}
</oc-button>
<oc-button
class="oc-modal-body-actions-confirm oc-ml-s"
appearance="filled"
variation="primary"
:disabled="isFormInvalid"
@click="onConfirm"
>{{ $gettext('Confirm') }}
</oc-button>
</div>
</form>
</template>

<script lang="ts">
import { useGettext } from 'vue3-gettext'
import { computed, defineComponent, ref, unref } from 'vue'
import { computed, defineComponent, ref, PropType, unref, watch } from 'vue'
import { Group } from '@ownclouders/web-client/src/generated'
import { MaybeRef, useClientService, useEventBus, useStore } from '@ownclouders/web-pkg'
import { MaybeRef, Modal, useClientService, useEventBus, useStore } from '@ownclouders/web-pkg'
export default defineComponent({
name: 'CreateGroupModal',
setup(props, { expose }) {
props: {
modal: { type: Object as PropType<Modal>, required: true }
},
emits: ['confirm', 'update:confirmDisabled'],
setup(props, { emit, expose }) {
const { $gettext } = useGettext()
const store = useStore()
const eventBus = useEventBus()
Expand All @@ -58,9 +45,17 @@ export default defineComponent({
.includes(false)
})
watch(
isFormInvalid,
() => {
emit('update:confirmDisabled', unref(isFormInvalid))
},
{ immediate: true }
)
const onConfirm = async () => {
if (unref(isFormInvalid)) {
return
return Promise.reject(new Promise((reject) => reject('')))
}
try {
Expand All @@ -76,39 +71,34 @@ export default defineComponent({
title: $gettext('Failed to create group'),
error
})
} finally {
store.dispatch('hideModal')
}
}
const onCancel = () => {
store.dispatch('hideModal')
}
expose({ onConfirm, onCancel })
expose({ onConfirm })
return {
clientService,
group,
formData,
isFormInvalid,
onConfirm,
onCancel
// unit tests
onConfirm
}
},
methods: {
async validateDisplayName() {
this.formData.displayName.valid = false
if (this.group.displayName.trim() === '') {
this.formData.displayName.errorMessage = this.$gettext('Group name cannot be empty')
this.formData.displayName.valid = false
return false
}
if (this.group.displayName.length > 255) {
this.formData.displayName.errorMessage = this.$gettext(
'Group name cannot exceed 255 characters'
)
this.formData.displayName.valid = false
return false
}
Expand All @@ -121,6 +111,7 @@ export default defineComponent({
groupName: this.group.displayName
}
)
this.formData.displayName.valid = false
return false
} catch (e) {}
Expand Down
Loading

0 comments on commit b413395

Please sign in to comment.