chore: change everything to vue3 syntax
This commit is contained in:
@@ -1,27 +1,21 @@
|
||||
<template>
|
||||
<div @submit.prevent="onSubmit">
|
||||
<woot-input
|
||||
v-model="title"
|
||||
:class="{ error: $v.title.$error }"
|
||||
v-model="state.title"
|
||||
:class="{ error: v$.title.$error }"
|
||||
class="w-full"
|
||||
:styles="{ ...inputStyles, padding: '6px 12px' }"
|
||||
:label="$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.TITLE.LABEL')"
|
||||
:placeholder="
|
||||
$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.TITLE.PLACEHOLDER')
|
||||
"
|
||||
:error="
|
||||
$v.title.$error
|
||||
? $t(
|
||||
'INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.TITLE.REQUIRED_ERROR'
|
||||
)
|
||||
: ''
|
||||
"
|
||||
@input="$v.title.$touch"
|
||||
:error="nameError"
|
||||
@input="v$.title.$touch"
|
||||
/>
|
||||
<label>
|
||||
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.DESCRIPTION.LABEL') }}
|
||||
<textarea
|
||||
v-model="description"
|
||||
v-model="state.description"
|
||||
:style="{ ...inputStyles, padding: '8px 12px' }"
|
||||
rows="3"
|
||||
type="text"
|
||||
@@ -33,10 +27,10 @@
|
||||
"
|
||||
/>
|
||||
</label>
|
||||
<label :class="{ error: $v.teamId.$error }">
|
||||
<label :class="{ error: v$.teamId.$error }">
|
||||
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.TEAM.LABEL') }}
|
||||
<select
|
||||
v-model="teamId"
|
||||
v-model="state.teamId"
|
||||
:style="inputStyles"
|
||||
@change="onChangeTeam($event)"
|
||||
>
|
||||
@@ -44,15 +38,13 @@
|
||||
{{ item.name }}
|
||||
</option>
|
||||
</select>
|
||||
<span v-if="$v.teamId.$error" class="message">
|
||||
{{
|
||||
$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.TEAM.REQUIRED_ERROR')
|
||||
}}
|
||||
<span v-if="v$.teamId.$error" class="message">
|
||||
{{ teamError }}
|
||||
</span>
|
||||
</label>
|
||||
<label>
|
||||
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.ASSIGNEE.LABEL') }}
|
||||
<select v-model="assigneeId" :style="inputStyles">
|
||||
<select v-model="state.assigneeId" :style="inputStyles">
|
||||
<option v-for="item in assignees" :key="item.name" :value="item.id">
|
||||
{{ item.name }}
|
||||
</option>
|
||||
@@ -61,7 +53,7 @@
|
||||
|
||||
<label>
|
||||
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.LABEL.LABEL') }}
|
||||
<select v-model="labelId" :style="inputStyles">
|
||||
<select v-model="state.labelId" :style="inputStyles">
|
||||
<option v-for="item in labels" :key="item.name" :value="item.id">
|
||||
{{ item.name }}
|
||||
</option>
|
||||
@@ -70,7 +62,7 @@
|
||||
|
||||
<label>
|
||||
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.PRIORITY.LABEL') }}
|
||||
<select v-model="priority" :style="inputStyles">
|
||||
<select v-model="state.priority" :style="inputStyles">
|
||||
<option v-for="item in priorities" :key="item.name" :value="item.id">
|
||||
{{ item.name }}
|
||||
</option>
|
||||
@@ -79,7 +71,7 @@
|
||||
|
||||
<label>
|
||||
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.PROJECT.LABEL') }}
|
||||
<select v-model="projectId" :style="inputStyles">
|
||||
<select v-model="state.projectId" :style="inputStyles">
|
||||
<option v-for="item in projects" :key="item.name" :value="item.id">
|
||||
{{ item.name }}
|
||||
</option>
|
||||
@@ -88,7 +80,7 @@
|
||||
|
||||
<label>
|
||||
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.STATUS.LABEL') }}
|
||||
<select v-model="stateId" :style="inputStyles">
|
||||
<select v-model="state.stateId" :style="inputStyles">
|
||||
<option v-for="item in statuses" :key="item.name" :value="item.id">
|
||||
{{ item.name }}
|
||||
</option>
|
||||
@@ -113,174 +105,169 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
<script setup>
|
||||
import LinearAPI from 'dashboard/api/integrations/linear';
|
||||
|
||||
import { reactive, computed, onMounted, ref } from 'vue';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
import { useI18n } from 'dashboard/composables/useI18n';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import validations from './validations';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
accountId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
conversationId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
const props = defineProps({
|
||||
accountId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: '',
|
||||
description: '',
|
||||
teamId: '',
|
||||
assigneeId: '',
|
||||
projectId: '',
|
||||
stateId: '',
|
||||
labelId: '',
|
||||
priority: 0,
|
||||
teams: [],
|
||||
assignees: [],
|
||||
projects: [],
|
||||
labels: [],
|
||||
statuses: [],
|
||||
selectedTabIndex: 0,
|
||||
priorities: [
|
||||
{
|
||||
id: 0,
|
||||
name: 'No priority',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: 'Urgent',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'High',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Normal',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Low',
|
||||
},
|
||||
],
|
||||
isCreating: false,
|
||||
searchResults: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Test',
|
||||
},
|
||||
],
|
||||
inputStyles: {
|
||||
borderRadius: '12px',
|
||||
fontSize: '14px',
|
||||
},
|
||||
};
|
||||
conversationId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
validations,
|
||||
computed: {
|
||||
isSubmitDisabled() {
|
||||
return this.$v.title.$invalid || this.isCreating;
|
||||
},
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const teams = ref([]);
|
||||
const assignees = ref([]);
|
||||
const projects = ref([]);
|
||||
const labels = ref([]);
|
||||
const statuses = ref([]);
|
||||
|
||||
const priorities = [
|
||||
{
|
||||
id: 0,
|
||||
name: 'No priority',
|
||||
},
|
||||
mounted() {
|
||||
this.getTeams();
|
||||
{
|
||||
id: 1,
|
||||
name: 'Urgent',
|
||||
},
|
||||
methods: {
|
||||
onClose() {
|
||||
this.$emit('close');
|
||||
},
|
||||
onClickTabChange(index) {
|
||||
this.selectedTabIndex = index;
|
||||
},
|
||||
onChangeTeam(event) {
|
||||
this.teamId = event.target.value;
|
||||
this.assigneeId = '';
|
||||
this.stateId = '';
|
||||
this.labelId = '';
|
||||
this.getTeamEntities();
|
||||
},
|
||||
async getTeams() {
|
||||
try {
|
||||
const response = await LinearAPI.getTeams();
|
||||
this.teams = response.data;
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
this.$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.LOADING_TEAM_ERROR')
|
||||
);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
async getTeamEntities() {
|
||||
try {
|
||||
const response = await LinearAPI.getTeamEntities(this.teamId);
|
||||
const { users, labels, projects, states } = response.data;
|
||||
this.assignees = users;
|
||||
this.labels = labels;
|
||||
this.statuses = states;
|
||||
this.projects = projects;
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
this.$t(
|
||||
'INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.LOADING_TEAM_ENTITIES_ERROR'
|
||||
)
|
||||
);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
async createIssue() {
|
||||
this.$v.$touch();
|
||||
if (this.$v.$invalid) {
|
||||
return;
|
||||
}
|
||||
const payload = {
|
||||
team_id: this.teamId,
|
||||
title: this.title,
|
||||
};
|
||||
if (this.description) {
|
||||
payload.description = this.description;
|
||||
}
|
||||
if (this.assigneeId) {
|
||||
payload.assignee_id = this.assigneeId;
|
||||
}
|
||||
if (this.projectId) {
|
||||
payload.project_id = this.projectId;
|
||||
}
|
||||
if (this.stateId) {
|
||||
payload.state_id = this.stateId;
|
||||
}
|
||||
if (this.priority) {
|
||||
payload.priority = this.priority;
|
||||
}
|
||||
if (this.labelId) {
|
||||
payload.label_ids = [this.labelId];
|
||||
}
|
||||
try {
|
||||
this.isCreating = true;
|
||||
const response = await LinearAPI.createIssue(payload);
|
||||
const { id: issueId } = response.data;
|
||||
await LinearAPI.link_issue(this.conversationId, issueId);
|
||||
this.showAlert(
|
||||
this.$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CREATE_SUCCESS')
|
||||
);
|
||||
this.onClose();
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
this.$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CREATE_ERROR')
|
||||
);
|
||||
} finally {
|
||||
this.isCreating = false;
|
||||
}
|
||||
},
|
||||
handleAgentsFilterSelection() {},
|
||||
{
|
||||
id: 2,
|
||||
name: 'High',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Normal',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Low',
|
||||
},
|
||||
];
|
||||
|
||||
const isCreating = ref(false);
|
||||
|
||||
const inputStyles = {
|
||||
borderRadius: '12px',
|
||||
fontSize: '14px',
|
||||
};
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
const state = reactive({
|
||||
title: '',
|
||||
description: '',
|
||||
teamId: '',
|
||||
assigneeId: '',
|
||||
labelId: '',
|
||||
stateId: '',
|
||||
priority: '',
|
||||
projectId: '',
|
||||
});
|
||||
|
||||
const v$ = useVuelidate(validations, state);
|
||||
|
||||
const isSubmitDisabled = computed(() => {
|
||||
return v$.value.title.$invalid || isCreating.value;
|
||||
});
|
||||
|
||||
const nameError = computed(() => {
|
||||
return v$.value.title.$error
|
||||
? t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.TITLE.REQUIRED_ERROR')
|
||||
: '';
|
||||
});
|
||||
|
||||
const teamError = computed(() => {
|
||||
return v$.value.teamId.$error
|
||||
? t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.FORM.TEAM.REQUIRED_ERROR')
|
||||
: '';
|
||||
});
|
||||
|
||||
const onClose = () => {
|
||||
emit('close');
|
||||
};
|
||||
const getTeams = async () => {
|
||||
try {
|
||||
const response = await LinearAPI.getTeams();
|
||||
teams.value = response.data;
|
||||
} catch (error) {
|
||||
useAlert(t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.LOADING_TEAM_ERROR'));
|
||||
}
|
||||
};
|
||||
|
||||
const getTeamEntities = async () => {
|
||||
try {
|
||||
const response = await LinearAPI.getTeamEntities(state.teamId);
|
||||
assignees.value = response.data.users;
|
||||
labels.value = response.data.labels;
|
||||
statuses.value = response.data.states;
|
||||
projects.value = response.data.projects;
|
||||
} catch (error) {
|
||||
useAlert(
|
||||
t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.LOADING_TEAM_ENTITIES_ERROR')
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const onChangeTeam = event => {
|
||||
state.teamId = event.target.value;
|
||||
state.assigneeId = '';
|
||||
state.stateId = '';
|
||||
state.labelId = '';
|
||||
getTeamEntities();
|
||||
};
|
||||
|
||||
const createIssue = async () => {
|
||||
v$.value.$touch();
|
||||
if (v$.value.$invalid) {
|
||||
return;
|
||||
}
|
||||
const payload = {
|
||||
team_id: state.teamId,
|
||||
title: state.title,
|
||||
};
|
||||
if (state.description) {
|
||||
payload.description = state.description;
|
||||
}
|
||||
if (state.assigneeId) {
|
||||
payload.assignee_id = state.assigneeId;
|
||||
}
|
||||
if (state.projectId) {
|
||||
payload.project_id = state.projectId;
|
||||
}
|
||||
if (state.stateId) {
|
||||
payload.state_id = state.stateId;
|
||||
}
|
||||
if (state.priority) {
|
||||
payload.priority = state.priority;
|
||||
}
|
||||
if (state.labelId) {
|
||||
payload.label_ids = [state.labelId];
|
||||
}
|
||||
try {
|
||||
isCreating.value = true;
|
||||
const response = await LinearAPI.createIssue(payload);
|
||||
const { id: issueId } = response.data;
|
||||
await LinearAPI.link_issue(props.conversationId, issueId);
|
||||
useAlert(t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CREATE_SUCCESS'));
|
||||
onClose();
|
||||
} catch (error) {
|
||||
useAlert(t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CREATE_ERROR'));
|
||||
} finally {
|
||||
isCreating.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getTeams();
|
||||
});
|
||||
</script>
|
||||
|
||||
+35
-46
@@ -36,57 +36,46 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
<script setup>
|
||||
import { useI18n } from 'dashboard/composables/useI18n';
|
||||
import { computed, ref } from 'vue';
|
||||
import LinkIssue from './LinkIssue';
|
||||
import CreateIssue from './CreateIssue';
|
||||
|
||||
import validations from './validations';
|
||||
defineProps({
|
||||
accountId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
conversationId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LinkIssue,
|
||||
CreateIssue,
|
||||
},
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
accountId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
const { t } = useI18n();
|
||||
|
||||
const selectedTabIndex = ref(0);
|
||||
|
||||
const emits = defineEmits(['close']);
|
||||
|
||||
const tabs = computed(() => {
|
||||
return [
|
||||
{
|
||||
key: 0,
|
||||
name: t('INTEGRATION_SETTINGS.LINEAR.CREATE'),
|
||||
},
|
||||
conversationId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
{
|
||||
key: 1,
|
||||
name: t('INTEGRATION_SETTINGS.LINEAR.LINK.TITLE'),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedTabIndex: 0,
|
||||
};
|
||||
},
|
||||
validations,
|
||||
computed: {
|
||||
tabs() {
|
||||
return [
|
||||
{
|
||||
key: 0,
|
||||
name: this.$t('INTEGRATION_SETTINGS.LINEAR.CREATE'),
|
||||
},
|
||||
{
|
||||
key: 1,
|
||||
name: this.$t('INTEGRATION_SETTINGS.LINEAR.LINK.TITLE'),
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onClose() {
|
||||
this.$emit('close');
|
||||
},
|
||||
onClickTabChange(index) {
|
||||
this.selectedTabIndex = index;
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
const onClose = () => {
|
||||
emits('close');
|
||||
};
|
||||
|
||||
const onClickTabChange = index => {
|
||||
selectedTabIndex.value = index;
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -29,7 +29,7 @@ const assignee = computed(() => {
|
||||
}
|
||||
return {
|
||||
name: props.issue.assignee.name,
|
||||
thumbnail: props.issue.assignee.avatarUrl,
|
||||
thumbnail: props.issue.assignee?.avatarUrl || '',
|
||||
};
|
||||
});
|
||||
|
||||
@@ -54,8 +54,8 @@ const openIssue = () => {
|
||||
<div
|
||||
class="absolute flex flex-col items-start bg-[#fdfdfd] dark:bg-slate-800 z-50 px-4 py-3 border border-solid border-slate-75 dark:border-slate-700 w-[384px] rounded-xl gap-4 max-h-96 overflow-auto"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-row justify-between w-full">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex flex-row justify-between">
|
||||
<div
|
||||
class="flex items-center justify-center gap-1 px-2 py-1 border rounded-lg border-ash-200"
|
||||
>
|
||||
@@ -138,7 +138,11 @@ const openIssue = () => {
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-ash-800">
|
||||
{{ `Created at ${formattedDate}` }}
|
||||
{{
|
||||
$t('INTEGRATION_SETTINGS.LINEAR.ISSUE.CREATED_AT', {
|
||||
createdAt: formattedDate,
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
:show-labels="false"
|
||||
:max-height="500"
|
||||
@search-change="handleSearchChange"
|
||||
@select="handleInput"
|
||||
>
|
||||
<template #noResult>
|
||||
<div class="flex items-center justify-center">
|
||||
@@ -45,82 +44,72 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
<script setup>
|
||||
import LinearAPI from 'dashboard/api/integrations/linear';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { useI18n } from 'dashboard/composables/useI18n';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
conversationId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedOptions: null,
|
||||
options: [],
|
||||
inputStyles: {
|
||||
borderRadius: '12px',
|
||||
padding: '6px 12px',
|
||||
fontSize: '14px',
|
||||
},
|
||||
isFetching: false,
|
||||
isLinking: false,
|
||||
searchQuery: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
emptyText() {
|
||||
if (this.isFetching) {
|
||||
return this.$t('INTEGRATION_SETTINGS.LINEAR.LINK.LOADING');
|
||||
}
|
||||
if (this.searchQuery) {
|
||||
return '';
|
||||
}
|
||||
return this.$t('INTEGRATION_SETTINGS.LINEAR.LINK.EMPTY_LIST');
|
||||
},
|
||||
isSubmitDisabled() {
|
||||
return !this.selectedOptions || this.isLinking;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onClose() {
|
||||
this.$emit('close');
|
||||
},
|
||||
async handleSearchChange(value) {
|
||||
if (!value) return;
|
||||
this.searchQuery = value;
|
||||
try {
|
||||
this.isFetching = true;
|
||||
const response = await LinearAPI.searchIssues(value);
|
||||
this.options = response.data;
|
||||
} catch (error) {
|
||||
this.showAlert(this.$t('INTEGRATION_SETTINGS.LINEAR.LINK.ERROR'));
|
||||
} finally {
|
||||
this.isFetching = false;
|
||||
}
|
||||
},
|
||||
handleInput() {
|
||||
this.$emit('agents-filter-selection', this.selectedOptions);
|
||||
},
|
||||
async linkIssue() {
|
||||
const { id: issueId } = this.selectedOptions;
|
||||
try {
|
||||
this.isLinking = true;
|
||||
await LinearAPI.link_issue(this.conversationId, issueId);
|
||||
this.showAlert(
|
||||
this.$t('INTEGRATION_SETTINGS.LINEAR.LINK.LINK_SUCCESS')
|
||||
);
|
||||
this.searchQuery = '';
|
||||
this.onClose();
|
||||
} catch (error) {
|
||||
this.showAlert(this.$t('INTEGRATION_SETTINGS.LINEAR.LINK.LINK_ERROR'));
|
||||
} finally {
|
||||
this.isLinking = false;
|
||||
}
|
||||
},
|
||||
const props = defineProps({
|
||||
conversationId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const { t } = useI18n();
|
||||
|
||||
const selectedOptions = ref(null);
|
||||
const options = ref([]);
|
||||
const isFetching = ref(false);
|
||||
const isLinking = ref(false);
|
||||
const searchQuery = ref('');
|
||||
|
||||
const emptyText = computed(() => {
|
||||
if (isFetching.value) {
|
||||
return t('INTEGRATION_SETTINGS.LINEAR.LINK.LOADING');
|
||||
}
|
||||
if (searchQuery.value) {
|
||||
return '';
|
||||
}
|
||||
return t('INTEGRATION_SETTINGS.LINEAR.LINK.EMPTY_LIST');
|
||||
});
|
||||
|
||||
const isSubmitDisabled = computed(() => {
|
||||
return !selectedOptions.value || isLinking.value;
|
||||
});
|
||||
|
||||
const emits = defineEmits(['close']);
|
||||
|
||||
const onClose = () => {
|
||||
emits('close');
|
||||
};
|
||||
|
||||
const handleSearchChange = async value => {
|
||||
if (!value) return;
|
||||
searchQuery.value = value;
|
||||
try {
|
||||
isFetching.value = true;
|
||||
const response = await LinearAPI.searchIssues(value);
|
||||
options.value = response.data;
|
||||
} catch (error) {
|
||||
useAlert(t('INTEGRATION_SETTINGS.LINEAR.LINK.ERROR'));
|
||||
} finally {
|
||||
isFetching.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const linkIssue = async () => {
|
||||
const { id: issueId } = selectedOptions.value;
|
||||
try {
|
||||
isLinking.value = true;
|
||||
await LinearAPI.link_issue(props.conversationId, issueId);
|
||||
useAlert(t('INTEGRATION_SETTINGS.LINEAR.LINK.LINK_SUCCESS'));
|
||||
searchQuery.value = '';
|
||||
onClose();
|
||||
} catch (error) {
|
||||
useAlert(t('INTEGRATION_SETTINGS.LINEAR.LINK.LINK_ERROR'));
|
||||
} finally {
|
||||
isLinking.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
|
||||
import { required } from '@vuelidate/validators';
|
||||
export default {
|
||||
title: {
|
||||
required,
|
||||
|
||||
@@ -264,7 +264,7 @@
|
||||
"PRIORITY": "Priority",
|
||||
"ASSIGNEE": "Assignee",
|
||||
"LABELS": "Labels",
|
||||
"CREATED_AT": "Created at"
|
||||
"CREATED_AT": "Created at %{createdAt}"
|
||||
},
|
||||
"UNLINK": {
|
||||
"TITLE": "Unlink",
|
||||
|
||||
Reference in New Issue
Block a user