fix: emit events across the app (#10227)

This PR makes the following changes

1. Update v-model bindings for components using the old `value` prop and `input` event method
2. Remove components that were not used anywhere

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
Shivam Mishra
2024-10-04 20:33:41 +05:30
committed by GitHub
parent 88a16b8e96
commit 9338bc1391
13 changed files with 44 additions and 354 deletions

View File

@@ -84,10 +84,10 @@ const shouldShowEmptyState = computed(() => {
<slot name="search">
<DropdownSearch
v-if="enableSearch"
:input-value="searchTerm"
v-model="searchTerm"
:input-placeholder="inputPlaceholder"
:show-clear-filter="showClearFilter"
@input="onSearch"
@update:model-value="onSearch"
@remove="$emit('removeFilter')"
/>
</slot>

View File

@@ -1,10 +1,6 @@
<script setup>
import { defineEmits } from 'vue';
import { defineEmits, defineModel } from 'vue';
defineProps({
inputValue: {
type: String,
default: '',
},
inputPlaceholder: {
type: String,
default: '',
@@ -15,7 +11,12 @@ defineProps({
},
});
const emit = defineEmits(['input', 'remove']);
const emit = defineEmits(['remove']);
const value = defineModel({
type: String,
default: '',
});
</script>
<template>
@@ -29,16 +30,15 @@ const emit = defineEmits(['input', 'remove']);
class="text-slate-400 dark:text-slate-400 flex-shrink-0"
/>
<input
v-model="value"
:placeholder="inputPlaceholder"
type="text"
class="w-full mb-0 text-sm bg-white dark:bg-slate-800 text-slate-800 dark:text-slate-75 reset-base"
:placeholder="inputPlaceholder"
:value="inputValue"
@input="emit('input', $event.target.value)"
/>
</div>
<!-- Clear filter button -->
<woot-button
v-if="!inputValue && showClearFilter"
v-if="!modelValue && showClearFilter"
size="small"
variant="clear"
color-scheme="primary"

View File

@@ -1,9 +1,10 @@
<script>
export default {
// The value types are dynamic, hence prop validation removed to work with our action schema
// eslint-disable-next-line vue/require-prop-types
props: ['teams', 'value'],
emits: ['input'],
props: {
teams: { type: Array, required: true },
modelValue: { type: Object, required: true },
},
emits: ['update:modelValue'],
data() {
return {
selectedTeams: [],
@@ -11,13 +12,13 @@ export default {
};
},
mounted() {
const { team_ids: teamIds } = this.value;
const { team_ids: teamIds } = this.modelValue;
this.selectedTeams = teamIds;
this.message = this.value.message;
this.message = this.modelValue.message;
},
methods: {
updateValue() {
this.$emit('input', {
this.$emit('update:modelValue', {
team_ids: this.selectedTeams.map(team => team.id),
message: this.message,
});

View File

@@ -37,7 +37,7 @@ export default {
default: () => [],
},
},
emits: ['input', 'openPopover', 'openModal'],
emits: ['openPopover', 'openModal'],
computed: {
hasCategory() {
return (
@@ -50,9 +50,6 @@ export default {
},
},
methods: {
onSearch(value) {
this.$emit('input', value);
},
openPortalPopover() {
this.$emit('openPopover');
},

View File

@@ -1,63 +0,0 @@
<script>
export default {
emits: ['input'],
data() {
return {
searchValue: '',
};
},
methods: {
onSearch(e) {
this.$emit('input', e.target.value);
},
},
};
</script>
<template>
<div class="search-input--wrap">
<div class="search-icon--wrap">
<fluent-icon icon="search" size="18" class="search-icon" />
</div>
<input
v-model="searchValue"
class="search-input"
:placeholder="$t('HELP_CENTER.SIDEBAR.SEARCH.PLACEHOLDER')"
@input="onSearch"
/>
</div>
</template>
<style lang="scss" scoped>
.search-input--wrap {
display: flex;
padding: var(--space-small) var(--space-zero);
width: 100%;
}
.search-input {
width: 100%;
height: var(--space-large);
border-radius: var(--border-radius-normal);
background: var(--s-25);
font-size: var(--font-size-small);
padding: var(--space-small) var(--space-small) var(--space-small)
var(--space-large);
border: 1px solid var(--s-50);
&:focus {
border-color: var(--w-500);
}
}
.search-icon--wrap {
position: relative;
}
.search-icon {
position: absolute;
color: var(--s-500);
top: var(--space-small);
left: var(--space-small);
}
</style>

View File

@@ -5,12 +5,12 @@ import { mapGetters } from 'vuex';
export default {
components: { LoadingState },
props: {
value: {
modelValue: {
type: String,
default: '',
},
},
emits: ['input'],
emits: ['update:modelValue'],
data() {
return {
iframeLoading: true,
@@ -30,7 +30,7 @@ export default {
return;
}
const csmlContent = e.data.replace('chatwoot-csml-editor:update', '');
this.$emit('input', csmlContent);
this.$emit('update:modelValue', csmlContent);
};
},
methods: {
@@ -38,7 +38,7 @@ export default {
const frameElement = document.getElementById(`csml-editor--frame`);
const eventData = {
event: 'editorContext',
data: this.value || '',
data: this.modelValue || '',
};
frameElement.contentWindow.postMessage(JSON.stringify(eventData), '*');
this.iframeLoading = false;

View File

@@ -2,7 +2,7 @@
import { ref, watch } from 'vue';
const props = defineProps({
value: {
modelValue: {
type: String,
required: true,
},
@@ -20,9 +20,9 @@ const props = defineProps({
},
});
const emit = defineEmits(['input']);
const emit = defineEmits(['update:modelValue', 'input']);
const localValue = ref(props.value);
const localValue = ref(props.modelValue);
const localFlags = ref(props.selectedFlags);
watch(
@@ -33,6 +33,7 @@ watch(
);
const handleInput = e => {
emit('update:modelValue', props.type, e);
emit('input', props.type, e);
};
</script>

View File

@@ -257,8 +257,8 @@ export default {
</span>
</div>
<FormSwitch
:value="hasEnabledPushPermissions"
@input="onRequestPermissions"
:model-value="hasEnabledPushPermissions"
@update:model-value="onRequestPermissions"
/>
</div>
</div>

View File

@@ -1,57 +0,0 @@
<script>
import WithLabel from './WithLabel.vue';
export default {
components: {
WithLabel,
},
props: {
options: {
type: Array,
default: () => [],
},
name: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
value: {
type: String,
default: '',
},
hasError: {
type: Boolean,
default: false,
},
errorMessage: {
type: String,
default: '',
},
},
emits: ['input'],
};
</script>
<template>
<WithLabel
:label="label"
:name="name"
:has-error="hasError"
:error-message="errorMessage"
>
<div class="flex flex-wrap gap-2">
<woot-button
v-for="option in options"
:key="option.value"
:variant="value === option.value ? '' : 'hollow'"
:color-scheme="value === option.value ? 'primary' : 'secondary'"
size="small"
@click="$emit('input', option.value)"
>
{{ option.label }}
</woot-button>
</div>
</WithLabel>
</template>

View File

@@ -1,12 +1,12 @@
<script>
export default {
props: {
value: { type: Boolean, default: false },
modelValue: { type: Boolean, default: false },
},
emits: ['input'],
emits: ['update:modelValue'],
methods: {
onClick() {
this.$emit('input', !this.value);
this.$emit('update:modelValue', !this.modelValue);
},
},
};
@@ -17,17 +17,19 @@ export default {
type="button"
class="relative flex-shrink-0 h-4 p-0 border-none shadow-inner w-7 rounded-3xl"
:class="
value ? 'bg-primary-600 shadow-primary-800' : 'shadow-ash-400 bg-ash-200'
modelValue
? 'bg-primary-600 shadow-primary-800'
: 'shadow-ash-400 bg-ash-200'
"
role="switch"
:aria-checked="value.toString()"
:aria-checked="modelValue.toString()"
@click="onClick"
>
<span
aria-hidden="true"
class="rounded-full bg-white top-0.5 absolute dark:bg-white w-3 h-3 translate-y-0 duration-200 transition-transform ease-in-out"
:class="
value
modelValue
? 'ltr:translate-x-0 rtl:translate-x-[12px]'
: 'ltr:-translate-x-[12px] rtl:translate-x-0'
"

View File

@@ -21,7 +21,7 @@ export default {
type: String,
default: '',
},
value: {
modelValue: {
type: [String, Number],
default: '',
},
@@ -46,10 +46,10 @@ export default {
default: '',
},
},
emits: ['input', 'blur'],
emits: ['update:modelValue', 'blur'],
methods: {
onInput(e) {
this.$emit('input', e.target.value);
this.$emit('update:modelValue', e.target.value);
},
},
};
@@ -69,7 +69,7 @@ export default {
:required="required"
:placeholder="placeholder"
:data-testid="dataTestid"
:value="value"
:value="modelValue"
:rows="rows"
:class="{
'focus:outline-red-600 outline-red-600': hasError,
@@ -78,7 +78,7 @@ export default {
'resize-none': !allowResize,
}"
class="block w-full p-3 bg-white border-none rounded-md shadow-sm appearance-none outline outline-1 focus:outline focus:outline-2 text-slate-900 dark:text-slate-100 placeholder:text-slate-400 dark:bg-slate-800"
@input="onInput"
@update:model-value="onInput"
@blur="$emit('blur')"
/>
</WithLabel>

View File

@@ -1,100 +0,0 @@
<script>
import { useDarkMode } from 'widget/composables/useDarkMode';
export default {
props: {
label: {
type: String,
default: '',
},
type: {
type: String,
default: 'text',
},
placeholder: {
type: String,
default: '',
},
value: {
type: [String, Number],
required: true,
},
error: {
type: String,
default: '',
},
helpText: {
type: String,
default: '',
},
},
emits: ['input'],
setup() {
const { getThemeClass } = useDarkMode();
return { getThemeClass };
},
computed: {
labelClass() {
return this.error
? `text-red-400 ${this.getThemeClass(
'text-black-800',
'dark:text-slate-50'
)}`
: `text-black-800 ${this.getThemeClass(
'text-black-800',
'dark:text-slate-50'
)}`;
},
isInputDarkOrLightMode() {
return `${this.getThemeClass(
'bg-white',
'dark:bg-slate-600'
)} ${this.getThemeClass('text-slate-700', 'dark:text-slate-50')}`;
},
inputBorderColor() {
return `${this.getThemeClass(
'border-black-200',
'dark:border-black-500'
)}`;
},
inputHasError() {
return this.error
? `border-red-200 hover:border-red-300 focus:border-red-300 ${this.isInputDarkOrLightMode}`
: `hover:border-black-300 focus:border-black-300 ${this.isInputDarkOrLightMode} ${this.inputBorderColor}`;
},
},
methods: {
onChange(event) {
this.$emit('input', event.target.value);
},
},
};
</script>
<template>
<label class="block">
<div
v-if="label"
class="mb-2 text-xs leading-3 font-medium"
:class="labelClass"
>
{{ label }}
</div>
<input
:type="type"
class="border rounded w-full py-2 px-3 leading-tight outline-none"
:class="inputHasError"
:placeholder="placeholder"
:value="value"
@change="onChange"
/>
<div v-if="error" class="text-red-400 mt-2 text-xs leading-3 font-medium">
{{ error }}
</div>
<div
v-if="!error && helpText"
class="text-red-400 mt-2 text-xs leading-3 font-medium"
>
{{ helpText }}
</div>
</label>
</template>

View File

@@ -1,91 +0,0 @@
<script>
import { useDarkMode } from 'widget/composables/useDarkMode';
export default {
props: {
label: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '',
},
value: {
type: [String, Number],
required: true,
},
error: {
type: String,
default: '',
},
},
emits: ['input'],
setup() {
const { getThemeClass } = useDarkMode();
return { getThemeClass };
},
computed: {
labelClass() {
return this.error
? `text-red-400 ${this.getThemeClass(
'text-black-800',
'dark:text-slate-50'
)}`
: `text-black-800 ${this.getThemeClass(
'text-black-800',
'dark:text-slate-50'
)}`;
},
isTextAreaDarkOrLightMode() {
return `${this.getThemeClass(
'bg-white',
'dark:bg-slate-600'
)} ${this.getThemeClass('text-slate-700', 'dark:text-slate-50')}`;
},
textAreaBorderColor() {
return `${this.getThemeClass(
'border-black-200',
'dark:border-black-500'
)}`;
},
isTextAreaHasError() {
return this.error
? `border-red-200 hover:border-red-300 focus:border-red-300 ${this.isTextAreaDarkOrLightMode}`
: `hover:border-black-300 focus:border-black-300 ${this.isTextAreaDarkOrLightMode} ${this.textAreaBorderColor}`;
},
},
methods: {
onChange(event) {
this.$emit('input', event.target.value);
},
},
};
</script>
<template>
<label class="block">
<div
v-if="label"
class="mb-2 text-xs font-medium leading-3"
:class="labelClass"
>
{{ label }}
</div>
<textarea
class="w-full px-3 py-2 leading-tight border rounded outline-none resize-none text-slate-700"
:class="isTextAreaHasError"
:placeholder="placeholder"
:value="value"
@change="onChange"
/>
<div v-if="error" class="mt-2 text-xs font-medium leading-3 text-red-400">
{{ error }}
</div>
</label>
</template>
<style lang="scss" scoped>
textarea {
min-height: 8rem;
}
</style>