feat: complete basic front end

This commit is contained in:
Muhsin Keloth
2024-05-17 14:04:48 +05:30
parent 0e11dac471
commit 3d1bafa3c0
8 changed files with 171 additions and 153 deletions
@@ -72,7 +72,7 @@
>
<SLA-card-label v-if="hasSlaPolicyId" :chat="chat" show-extended-info />
<linear
v-if="isLinearIntegrationEnabled"
v-if="isLinearIntegrationEnabled && isLinearFeatureEnabled"
:conversation-id="currentChat.id"
/>
<more-actions :conversation-id="currentChat.id" />
@@ -130,6 +130,7 @@ export default {
currentChat: 'getSelectedChat',
accountId: 'getCurrentAccountId',
isFeatureEnabledonAccount: 'accounts/isFeatureEnabledonAccount',
appIntegrations: 'integrations/getAppIntegrations',
}),
chatMetadata() {
return this.chat.meta;
@@ -188,6 +189,11 @@ export default {
return this.chat?.sla_policy_id;
},
isLinearIntegrationEnabled() {
return this.appIntegrations.find(
integration => integration.id === 'linear' && !!integration.hooks.length
);
},
isLinearFeatureEnabled() {
return this.isFeatureEnabledonAccount(
this.accountId,
FEATURE_FLAGS.LINEAR
@@ -1,144 +1,145 @@
<template>
<div class="flex flex-col gap-2">
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between group">
<a
:href="issue.url"
target="_blank"
rel="noopener noreferrer"
class="inline-block rounded-sm mb-0 break-all py-0.5 text-primary-600"
>
{{ `${issue.identifier} ${issue.title}` }}
</a>
<woot-button
size="small"
variant="clear"
color-scheme="secondary"
class="!px-2 hover:!bg-transparent hidden dark:hover:!bg-transparent underline group-hover:block"
@click="unlinkIssue"
>
{{ $t('INTEGRATION_SETTINGS.LINEAR.UNLINK.TITLE') }}
</woot-button>
</div>
<!-- <span class="text-sm font-normal text-slate-900 dark:text-slate-25">
{{ issue.description }}
</span> -->
</div>
<div class="flex justify-between w-full">
<span
class="text-sm sticky top-0 h-fit font-normal tracking-[-0.6%] min-w-[140px] truncate text-slate-600 dark:text-slate-200"
>
{{ $t('INTEGRATION_SETTINGS.LINEAR.ISSUE.STATUS') }}
</span>
<div class="flex flex-col w-full gap-2">
<span
class="text-sm font-normal text-left text-slate-900 dark:text-slate-25 tabular-nums"
>
{{ issue.state.name }}
</span>
</div>
</div>
<div class="flex justify-between w-full">
<span
class="text-sm sticky top-0 h-fit font-normal tracking-[-0.6%] min-w-[140px] truncate text-slate-600 dark:text-slate-200"
>
{{ $t('INTEGRATION_SETTINGS.LINEAR.ISSUE.PRIORITY') }}
</span>
<div class="flex flex-col w-full gap-2">
<span
class="text-sm font-normal text-left text-slate-900 dark:text-slate-25 tabular-nums"
>
{{ priorityLabel }}
</span>
</div>
</div>
<div class="flex justify-between w-full">
<span
class="text-sm sticky top-0 h-fit font-normal tracking-[-0.6%] min-w-[140px] truncate text-slate-600 dark:text-slate-200"
>
{{ $t('INTEGRATION_SETTINGS.LINEAR.ISSUE.ASSIGNEE') }}
</span>
<div class="flex flex-col w-full gap-2">
<span
class="text-sm font-normal text-left text-slate-900 dark:text-slate-25 tabular-nums"
>
{{ assigneeName }}
</span>
</div>
</div>
<div class="flex justify-between w-full">
<span
class="text-sm sticky top-0 h-fit font-normal tracking-[-0.6%] min-w-[140px] truncate text-slate-600 dark:text-slate-200"
>
{{ $t('INTEGRATION_SETTINGS.LINEAR.ISSUE.LABELS') }}
</span>
<div class="flex flex-col w-full gap-2">
<span
class="text-sm font-normal text-left text-slate-900 dark:text-slate-25 tabular-nums"
>
{{ labels }}
</span>
</div>
</div>
<div class="flex justify-between w-full">
<span
class="text-sm sticky top-0 h-fit font-normal tracking-[-0.6%] min-w-[140px] truncate text-slate-600 dark:text-slate-200"
>
{{ $t('INTEGRATION_SETTINGS.LINEAR.ISSUE.CREATED_AT') }}
</span>
<div class="flex flex-col w-full gap-2">
<span
class="text-sm font-normal text-left text-slate-900 dark:text-slate-25 tabular-nums"
>
{{ formatDate(issue.createdAt) }}
</span>
</div>
</div>
</div>
</template>
<script>
<script setup>
import { format } from 'date-fns';
import UserAvatarWithName from 'dashboard/components/widgets/UserAvatarWithName.vue';
import { computed } from 'vue';
const priorityMap = {
0: 'Low',
1: 'Medium',
2: 'High',
3: 'Urgent',
};
export default {
props: {
issue: {
type: Object,
required: true,
},
linkId: {
type: String,
required: true,
},
const props = defineProps({
issue: {
type: Object,
required: true,
},
computed: {
priorityLabel() {
return priorityMap[this.issue.priority];
},
assigneeName() {
return this.issue.assignee ? this.issue.assignee.name : '---';
},
labels() {
return this.issue.labels.nodes.length
? this.issue.labels.nodes.map(label => label.name).join(', ')
: '---';
},
},
methods: {
unlinkIssue() {
this.$emit('unlink-issue', this.linkId);
},
formatDate(timestamp) {
return format(new Date(timestamp), 'MMM dd, hh:mm a');
},
linkId: {
type: String,
required: true,
},
});
const emit = defineEmits(['unlink-issue']);
const formattedDate = computed(() => {
return format(new Date(props.issue.createdAt), 'hh:mm a, MMM dd');
});
const assignee = computed(() => {
if (!props.issue.assignee) {
return null;
}
return {
name: props.issue.assignee.name,
thumbnail: props.issue.assignee.avatarUrl,
};
});
const labels = computed(() => {
if (props.issue.labels.nodes.length) {
return props.issue.labels.nodes;
}
return [];
});
const priorityLabel = computed(() => {
return priorityMap[props.issue.priority];
});
const unlinkIssue = () => {
emit('unlink-issue', props.linkId);
};
const openIssue = () => {
window.open(props.issue.url, '_blank');
};
</script>
<template>
<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 items-center justify-center gap-1 px-2 py-1 border rounded-lg border-ash-200"
>
<fluent-icon
icon="linear"
size="19"
class="text-[#5E6AD2]"
view-box="0 0 19 19"
/>
<span class="text-xs font-medium text-ash-900">
{{ issue.identifier }}
</span>
</div>
<div class="flex">
<woot-button
variant="clear"
color-scheme="secondary"
@click="unlinkIssue"
>
<fluent-icon
icon="unlink"
size="14"
type="outline"
icon-lib="lucide"
/>
</woot-button>
<woot-button
variant="clear"
color-scheme="secondary"
@click="openIssue"
>
<fluent-icon icon="arrow-up-right" size="14" />
</woot-button>
</div>
</div>
<span class="mt-2 text-sm font-medium text-ash-900">
{{ issue.title }}
</span>
<span class="mt-1 text-sm text-ash-800">
{{
issue.description.length > 130
? issue.description.slice(0, 130) + '...'
: issue.description
}}
</span>
</div>
<div class="flex flex-row gap-2 divide-x divide-ash-200">
<user-avatar-with-name v-if="assignee" :user="assignee" />
<div class="flex items-center gap-1">
<fluent-icon
icon="status"
size="14"
:class="`text-[${issue.state.color}]`"
/>
<h6 class="text-xs text-slate-600">
{{ issue.state.name }}
</h6>
</div>
<div class="flex items-center gap-1">
<fluent-icon
:icon="`priority-${priorityLabel.toLowerCase()}`"
size="14"
view-box="0 0 14 14"
/>
<h6 class="text-xs text-slate-600">{{ priorityLabel }}</h6>
</div>
</div>
<div v-if="labels.length" class="flex flex-wrap items-center gap-1">
<woot-label
v-for="label in labels"
:key="label.id"
:title="label.name"
:description="label.description"
:color="label.color"
variant="smooth"
small
/>
</div>
<div class="flex items-center">
<span class="text-xs text-ash-800">
{{ `Created at ${formattedDate}` }}
</span>
</div>
</div>
</template>
@@ -1,10 +1,11 @@
<template>
<div class="relative" @mouseover="openSlaPopover()">
<div class="relative" @mouseover="linkedIssue ? openIssue() : null">
<woot-button
v-on-clickaway="closeSlaPopover"
v-tooltip="tooltipText"
variant="clear"
color-scheme="secondary"
@click="openSlaPopover()"
@click="openIssue()"
>
<fluent-icon
icon="linear"
@@ -12,11 +13,16 @@
class="text-[#5E6AD2]"
view-box="0 0 19 19"
/>
<span v-if="linkedIssue" class="text-xs font-medium text-ash-800">
{{ linkedIssue.issue.identifier }}
</span>
</woot-button>
<linear-issue-details
v-if="showSlaPopoverCard"
<issue-item
v-if="shouldShowIssue"
:issue="linkedIssue.issue"
:link-id="linkedIssue.id"
class="absolute right-0 top-[46px]"
@unlink-issue="unlinkIssue"
/>
<woot-modal
:show.sync="showPopup"
@@ -34,15 +40,16 @@
<script>
import { mapGetters } from 'vuex';
import LinearIssueDetails from './LinearIssueDetails.vue';
import IssueItem from './IssueItem.vue';
import LinearAPI from 'dashboard/api/integrations/linear';
import CreateOrLinkIssue from './CreateOrLinkIssue.vue';
import alertMixin from 'shared/mixins/alertMixin';
export default {
components: {
LinearIssueDetails,
IssueItem,
CreateOrLinkIssue,
},
mixins: [alertMixin],
props: {
conversationId: {
type: [Number, String],
@@ -52,7 +59,7 @@ export default {
data() {
return {
linkedIssue: null,
showSlaPopover: false,
showIssue: false,
showPopup: false,
};
},
@@ -60,8 +67,13 @@ export default {
...mapGetters({
currentAccountId: 'getCurrentAccountId',
}),
showSlaPopoverCard() {
return this.showSlaPopover && this.linkedIssue;
shouldShowIssue() {
return this.showIssue && this.linkedIssue;
},
tooltipText() {
return this.linkedIssue === null
? this.$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK_BUTTON')
: null;
},
},
watch: {
@@ -99,12 +111,12 @@ export default {
);
}
},
openSlaPopover() {
openIssue() {
if (!this.linkedIssue) this.showPopup = true;
this.showSlaPopover = true;
this.showIssue = true;
},
closeSlaPopover() {
this.showSlaPopover = false;
this.showIssue = false;
},
},
};
@@ -221,7 +221,7 @@
},
"ADD_OR_LINK": {
"TITLE": "Create/link linear issue",
"DESCRIPTION": "Create or link a linear issue to the conversation",
"DESCRIPTION": "Create Linear issues from conversations, or link existing ones for seamless tracking.",
"FORM": {
"TITLE": {
"LABEL": "Title",
@@ -277,5 +277,6 @@
"avatar-upload-outline": "M19.754 11a.75.75 0 0 1 .743.648l.007.102v7a3.25 3.25 0 0 1-3.065 3.246l-.185.005h-11a3.25 3.25 0 0 1-3.244-3.066l-.006-.184V11.75a.75.75 0 0 1 1.494-.102l.006.102v7a1.75 1.75 0 0 0 1.607 1.745l.143.006h11A1.75 1.75 0 0 0 19 18.894l.005-.143V11.75a.75.75 0 0 1 .75-.75ZM6.22 7.216l4.996-4.996a.75.75 0 0 1 .976-.073l.084.072l5.005 4.997a.75.75 0 0 1-.976 1.134l-.084-.073l-3.723-3.716l.001 11.694a.75.75 0 0 1-.648.743l-.102.007a.75.75 0 0 1-.743-.648L11 16.255V4.558L7.28 8.277a.75.75 0 0 1-.976.073l-.084-.073a.75.75 0 0 1-.073-.977l.073-.084l4.996-4.996L6.22 7.216Z",
"text-copy-outline": "M5.503 4.627L5.5 6.75v10.504a3.25 3.25 0 0 0 3.25 3.25h8.616a2.25 2.25 0 0 1-2.122 1.5H8.75A4.75 4.75 0 0 1 4 17.254V6.75c0-.98.627-1.815 1.503-2.123M17.75 2A2.25 2.25 0 0 1 20 4.25v13a2.25 2.25 0 0 1-2.25 2.25h-9a2.25 2.25 0 0 1-2.25-2.25v-13A2.25 2.25 0 0 1 8.75 2zm0 1.5h-9a.75.75 0 0 0-.75.75v13c0 .414.336.75.75.75h9a.75.75 0 0 0 .75-.75v-13a.75.75 0 0 0-.75-.75",
"linear-outline": "M1.17156 10.4618C1.14041 10.329 1.2986 10.2454 1.39505 10.3418L6.50679 15.4536C6.60323 15.55 6.5196 15.7082 6.38681 15.6771C3.80721 15.0719 1.77669 13.0414 1.17156 10.4618ZM1.00026 8.4131C0.997795 8.45277 1.01271 8.49149 1.0408 8.51959L8.32904 15.8078C8.35714 15.8359 8.39586 15.8509 8.43553 15.8484C8.76721 15.8277 9.09266 15.784 9.41026 15.7187C9.51729 15.6968 9.55447 15.5653 9.47721 15.488L1.36063 7.37142C1.28337 7.29416 1.15187 7.33134 1.12989 7.43837C1.06466 7.75597 1.02092 8.08142 1.00026 8.4131ZM1.58953 6.00739C1.56622 6.05972 1.57809 6.12087 1.6186 6.16139L10.6872 15.23C10.7278 15.2705 10.7889 15.2824 10.8412 15.2591C11.0913 15.1477 11.3336 15.0221 11.5672 14.8833C11.6445 14.8374 11.6564 14.7312 11.5929 14.6676L2.18099 5.25577C2.11742 5.1922 2.01121 5.20412 1.96529 5.28142C1.8265 5.51499 1.70091 5.75733 1.58953 6.00739ZM2.77222 4.37899C2.7204 4.32718 2.7172 4.24407 2.76602 4.18942C4.04913 2.75294 5.9156 1.84863 7.99327 1.84863C11.863 1.84863 15 4.98565 15 8.85536C15 10.933 14.0957 12.7995 12.6592 14.0826C12.6046 14.1314 12.5215 14.1282 12.4696 14.0764L2.77222 4.37899Z",
"status-outline":"m8.462 6.81l3.284 13.616c.178.737 1.211.775 1.443.054l3.257-10.122l.586 2.095a.75.75 0 0 0 .722.548h3.494a.75.75 0 0 0 0-1.5h-2.925l-1.105-3.95c-.2-.717-1.208-.736-1.436-.028l-3.203 9.957L9.224 3.574c-.182-.757-1.255-.769-1.454-.016l-2.1 7.943H2.75a.75.75 0 0 0 0 1.5h3.496a.75.75 0 0 0 .725-.558z"
"status-outline": "m8.462 6.81l3.284 13.616c.178.737 1.211.775 1.443.054l3.257-10.122l.586 2.095a.75.75 0 0 0 .722.548h3.494a.75.75 0 0 0 0-1.5h-2.925l-1.105-3.95c-.2-.717-1.208-.736-1.436-.028l-3.203 9.957L9.224 3.574c-.182-.757-1.255-.769-1.454-.016l-2.1 7.943H2.75a.75.75 0 0 0 0 1.5h3.496a.75.75 0 0 0 .725-.558z",
"unlink-outline": "m18.84 12.25l1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07a5.006 5.006 0 0 0-6.95 0l-1.72 1.71m-6.58 6.57l-1.71 1.71a5.004 5.004 0 0 0 .12 7.07a5.006 5.006 0 0 0 6.95 0l1.71-1.71M8 2v3M2 8h3m11 11v3m3-6h3"
}