Merge branch 'develop' into feat/whatsapp-embedded-signup
This commit is contained in:
@@ -4,5 +4,15 @@ FROM ghcr.io/chatwoot/chatwoot_codespace:latest
|
||||
|
||||
# Do the set up required for chatwoot app
|
||||
WORKDIR /workspace
|
||||
|
||||
# Copy dependency files first for better caching
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
COPY Gemfile Gemfile.lock ./
|
||||
|
||||
# Install dependencies (will be cached if files don't change)
|
||||
RUN pnpm install --frozen-lockfile && \
|
||||
gem install bundler && \
|
||||
bundle install --jobs=$(nproc)
|
||||
|
||||
# Copy source code after dependencies are installed
|
||||
COPY . /workspace
|
||||
RUN yarn && gem install bundler && bundle install
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
|
||||
ARG VARIANT
|
||||
ARG VARIANT="ubuntu-22.04"
|
||||
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT}
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ARG NODE_VERSION
|
||||
ARG RUBY_VERSION
|
||||
ARG USER_UID
|
||||
ARG USER_GID
|
||||
ARG PNPM_VERSION="10.2.0"
|
||||
ENV PNPM_VERSION ${PNPM_VERSION}
|
||||
ENV RUBY_CONFIGURE_OPTS=--disable-install-doc
|
||||
|
||||
# Update args in docker-compose.yaml to set the UID/GID of the "vscode" user.
|
||||
RUN if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \
|
||||
@@ -15,61 +19,80 @@ RUN if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \
|
||||
&& chmod -R $USER_UID:$USER_GID /home/vscode; \
|
||||
fi
|
||||
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& apt-get -y install --no-install-recommends \
|
||||
build-essential \
|
||||
libssl-dev \
|
||||
zlib1g-dev \
|
||||
gnupg2 \
|
||||
tar \
|
||||
tzdata \
|
||||
postgresql-client \
|
||||
libpq-dev \
|
||||
yarn \
|
||||
git \
|
||||
imagemagick \
|
||||
tmux \
|
||||
zsh \
|
||||
git-flow \
|
||||
npm \
|
||||
libyaml-dev
|
||||
RUN NODE_MAJOR=$(echo $NODE_VERSION | cut -d. -f1) \
|
||||
&& curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - \
|
||||
&& apt-get update \
|
||||
&& apt-get -y install --no-install-recommends \
|
||||
build-essential \
|
||||
libssl-dev \
|
||||
zlib1g-dev \
|
||||
gnupg \
|
||||
tar \
|
||||
tzdata \
|
||||
postgresql-client \
|
||||
libpq-dev \
|
||||
git \
|
||||
imagemagick \
|
||||
libyaml-dev \
|
||||
curl \
|
||||
ca-certificates \
|
||||
tmux \
|
||||
nodejs \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Install rbenv and ruby
|
||||
RUN git clone https://github.com/rbenv/rbenv.git ~/.rbenv \
|
||||
# Install rbenv and ruby for root user first
|
||||
RUN git clone --depth 1 https://github.com/rbenv/rbenv.git ~/.rbenv \
|
||||
&& echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc \
|
||||
&& echo 'eval "$(rbenv init -)"' >> ~/.bashrc
|
||||
ENV PATH "/root/.rbenv/bin/:/root/.rbenv/shims/:$PATH"
|
||||
RUN git clone https://github.com/rbenv/ruby-build.git && \
|
||||
RUN git clone --depth 1 https://github.com/rbenv/ruby-build.git && \
|
||||
PREFIX=/usr/local ./ruby-build/install.sh
|
||||
|
||||
RUN rbenv install $RUBY_VERSION && \
|
||||
rbenv global $RUBY_VERSION && \
|
||||
rbenv versions
|
||||
|
||||
# Install overmind
|
||||
# Set up rbenv for vscode user
|
||||
RUN su - vscode -c "git clone --depth 1 https://github.com/rbenv/rbenv.git ~/.rbenv" \
|
||||
&& su - vscode -c "echo 'export PATH=\"\$HOME/.rbenv/bin:\$PATH\"' >> ~/.bashrc" \
|
||||
&& su - vscode -c "echo 'eval \"\$(rbenv init -)\"' >> ~/.bashrc" \
|
||||
&& su - vscode -c "PATH=\"/home/vscode/.rbenv/bin:\$PATH\" rbenv install $RUBY_VERSION" \
|
||||
&& su - vscode -c "PATH=\"/home/vscode/.rbenv/bin:\$PATH\" rbenv global $RUBY_VERSION"
|
||||
|
||||
# Install overmind and gh in single layer
|
||||
RUN curl -L https://github.com/DarthSim/overmind/releases/download/v2.1.0/overmind-v2.1.0-linux-amd64.gz > overmind.gz \
|
||||
&& gunzip overmind.gz \
|
||||
&& sudo mv overmind /usr/local/bin \
|
||||
&& chmod +x /usr/local/bin/overmind
|
||||
|
||||
|
||||
# Install gh
|
||||
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
&& sudo apt update \
|
||||
&& sudo apt install gh
|
||||
&& mv overmind /usr/local/bin \
|
||||
&& chmod +x /usr/local/bin/overmind \
|
||||
&& curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends gh \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
|
||||
# Do the set up required for chatwoot app
|
||||
WORKDIR /workspace
|
||||
COPY . /workspace
|
||||
RUN chown vscode:vscode /workspace
|
||||
|
||||
# set up ruby
|
||||
COPY Gemfile Gemfile.lock ./
|
||||
RUN gem install bundler && bundle install
|
||||
# set up node js and pnpm in single layer
|
||||
RUN npm install -g pnpm@${PNPM_VERSION} \
|
||||
&& npm cache clean --force
|
||||
|
||||
# set up node js
|
||||
RUN npm install n -g && \
|
||||
n $NODE_VERSION
|
||||
RUN npm install --global yarn
|
||||
RUN yarn
|
||||
# Switch to vscode user
|
||||
USER vscode
|
||||
ENV PATH="/home/vscode/.rbenv/bin:/home/vscode/.rbenv/shims:$PATH"
|
||||
|
||||
# Copy dependency files first for better caching
|
||||
COPY --chown=vscode:vscode Gemfile Gemfile.lock package.json pnpm-lock.yaml ./
|
||||
|
||||
# Install dependencies as vscode user
|
||||
RUN eval "$(rbenv init -)" \
|
||||
&& gem install bundler -N \
|
||||
&& bundle install --jobs=$(nproc) \
|
||||
&& pnpm install --frozen-lockfile
|
||||
|
||||
# Copy source code after dependencies are installed
|
||||
COPY --chown=vscode:vscode . /workspace
|
||||
|
||||
@@ -23,15 +23,15 @@
|
||||
// 5432 postgres
|
||||
// 6379 redis
|
||||
// 1025,8025 mailhog
|
||||
"forwardPorts": [8025, 3000, 3035],
|
||||
"forwardPorts": [8025, 3000, 3036],
|
||||
|
||||
"postCreateCommand": ".devcontainer/scripts/setup.sh && POSTGRES_STATEMENT_TIMEOUT=600s bundle exec rake db:chatwoot_prepare && yarn",
|
||||
"postCreateCommand": ".devcontainer/scripts/setup.sh && POSTGRES_STATEMENT_TIMEOUT=600s bundle exec rake db:chatwoot_prepare && pnpm install",
|
||||
"portsAttributes": {
|
||||
"3000": {
|
||||
"label": "Rails Server"
|
||||
},
|
||||
"3035": {
|
||||
"label": "Webpack Dev Server"
|
||||
"3036": {
|
||||
"label": "Vite Dev Server"
|
||||
},
|
||||
"8025": {
|
||||
"label": "Mailhog UI"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Docker Compose file for building the base image in GitHub Actions
|
||||
# Usage: docker-compose -f .devcontainer/docker-compose.base.yml build base
|
||||
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
base:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: .devcontainer/Dockerfile.base
|
||||
args:
|
||||
VARIANT: 'ubuntu-22.04'
|
||||
NODE_VERSION: '23.7.0'
|
||||
RUBY_VERSION: '3.4.4'
|
||||
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
|
||||
USER_UID: '1000'
|
||||
USER_GID: '1000'
|
||||
image: ghcr.io/chatwoot/chatwoot_codespace:latest
|
||||
@@ -5,19 +5,6 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
base:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: .devcontainer/Dockerfile.base
|
||||
args:
|
||||
VARIANT: 'ubuntu-22.04'
|
||||
NODE_VERSION: '23.7.0'
|
||||
RUBY_VERSION: '3.4.4'
|
||||
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
|
||||
USER_UID: '1000'
|
||||
USER_GID: '1000'
|
||||
image: base:latest
|
||||
|
||||
app:
|
||||
build:
|
||||
context: ..
|
||||
|
||||
@@ -2,12 +2,7 @@ cp .env.example .env
|
||||
sed -i -e '/REDIS_URL/ s/=.*/=redis:\/\/localhost:6379/' .env
|
||||
sed -i -e '/POSTGRES_HOST/ s/=.*/=localhost/' .env
|
||||
sed -i -e '/SMTP_ADDRESS/ s/=.*/=localhost/' .env
|
||||
sed -i -e "/FRONTEND_URL/ s/=.*/=https:\/\/$CODESPACE_NAME-3000.githubpreview.dev/" .env
|
||||
sed -i -e "/WEBPACKER_DEV_SERVER_PUBLIC/ s/=.*/=https:\/\/$CODESPACE_NAME-3035.githubpreview.dev/" .env
|
||||
# uncomment the webpacker env variable
|
||||
sed -i -e '/WEBPACKER_DEV_SERVER_PUBLIC/s/^# //' .env
|
||||
# fix the error with webpacker
|
||||
echo 'export NODE_OPTIONS=--openssl-legacy-provider' >> ~/.zshrc
|
||||
sed -i -e "/FRONTEND_URL/ s/=.*/=https:\/\/$CODESPACE_NAME-3000.app.github.dev/" .env
|
||||
|
||||
# codespaces make the ports public
|
||||
gh codespace ports visibility 3000:public 3035:public 8025:public -c $CODESPACE_NAME
|
||||
gh codespace ports visibility 3000:public 3036:public 8025:public -c $CODESPACE_NAME
|
||||
|
||||
@@ -19,6 +19,5 @@ jobs:
|
||||
|
||||
- name: Build the Codespace Base Image
|
||||
run: |
|
||||
docker-compose -f .devcontainer/docker-compose.yml build base
|
||||
docker tag base:latest ghcr.io/chatwoot/chatwoot_codespace:latest
|
||||
docker compose -f .devcontainer/docker-compose.base.yml build base
|
||||
docker push ghcr.io/chatwoot/chatwoot_codespace:latest
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
}
|
||||
|
||||
.tabs--container--with-border {
|
||||
@apply border-b border-n-weak;
|
||||
@apply border-b border-b-n-weak;
|
||||
}
|
||||
|
||||
.tabs--container--compact.tab--chat-type {
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<script setup>
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import { computed } from 'vue';
|
||||
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
||||
import { useMapGetter } from 'dashboard/composables/store';
|
||||
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
||||
|
||||
const { updateUISettings } = useUISettings();
|
||||
|
||||
const currentAccountId = useMapGetter('getCurrentAccountId');
|
||||
const isFeatureEnabledonAccount = useMapGetter(
|
||||
'accounts/isFeatureEnabledonAccount'
|
||||
);
|
||||
|
||||
const showCopilotTab = computed(() =>
|
||||
isFeatureEnabledonAccount.value(currentAccountId.value, FEATURE_FLAGS.CAPTAIN)
|
||||
);
|
||||
|
||||
const { uiSettings } = useUISettings();
|
||||
const isContactSidebarOpen = computed(
|
||||
() => uiSettings.value.is_contact_sidebar_open
|
||||
);
|
||||
const isCopilotPanelOpen = computed(
|
||||
() => uiSettings.value.is_copilot_panel_open
|
||||
);
|
||||
|
||||
const toggleConversationSidebarToggle = () => {
|
||||
updateUISettings({
|
||||
is_contact_sidebar_open: !isContactSidebarOpen.value,
|
||||
is_copilot_panel_open: false,
|
||||
});
|
||||
};
|
||||
|
||||
const handleConversationSidebarToggle = () => {
|
||||
updateUISettings({
|
||||
is_contact_sidebar_open: true,
|
||||
is_copilot_panel_open: false,
|
||||
});
|
||||
};
|
||||
|
||||
const handleCopilotSidebarToggle = () => {
|
||||
updateUISettings({
|
||||
is_contact_sidebar_open: false,
|
||||
is_copilot_panel_open: true,
|
||||
});
|
||||
};
|
||||
|
||||
const keyboardEvents = {
|
||||
'Alt+KeyO': {
|
||||
action: toggleConversationSidebarToggle,
|
||||
},
|
||||
};
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col justify-center items-center absolute top-24 ltr:right-2 rtl:left-2 bg-n-solid-2 border border-n-weak rounded-full gap-2 p-1"
|
||||
>
|
||||
<Button
|
||||
v-tooltip.top="$t('CONVERSATION.SIDEBAR.CONTACT')"
|
||||
ghost
|
||||
slate
|
||||
sm
|
||||
class="!rounded-full"
|
||||
:class="{
|
||||
'bg-n-alpha-2': isContactSidebarOpen,
|
||||
}"
|
||||
icon="i-ph-user-bold"
|
||||
@click="handleConversationSidebarToggle"
|
||||
/>
|
||||
<Button
|
||||
v-if="showCopilotTab"
|
||||
v-tooltip.bottom="$t('CONVERSATION.SIDEBAR.COPILOT')"
|
||||
ghost
|
||||
slate
|
||||
class="!rounded-full"
|
||||
:class="{
|
||||
'bg-n-alpha-2 !text-n-iris-9': isCopilotPanelOpen,
|
||||
}"
|
||||
sm
|
||||
icon="i-woot-captain"
|
||||
@click="handleCopilotSidebarToggle"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
+12
-4
@@ -1,21 +1,29 @@
|
||||
<script setup>
|
||||
import CopilotHeader from './CopilotHeader.vue';
|
||||
import SidebarActionsHeader from './SidebarActionsHeader.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Story
|
||||
title="Captain/Copilot/CopilotHeader"
|
||||
title="Components/SidebarActionsHeader"
|
||||
:layout="{ type: 'grid', width: '800px' }"
|
||||
>
|
||||
<!-- Default State -->
|
||||
<Variant title="Default State">
|
||||
<CopilotHeader />
|
||||
<SidebarActionsHeader title="Default State" />
|
||||
</Variant>
|
||||
|
||||
<!-- With New Conversation Button -->
|
||||
<Variant title="With New Conversation Button">
|
||||
<!-- eslint-disable-next-line vue/prefer-true-attribute-shorthand -->
|
||||
<CopilotHeader :has-messages="true" />
|
||||
<SidebarActionsHeader
|
||||
title="With New Conversation Button"
|
||||
:buttons="[
|
||||
{
|
||||
key: 'new_conversation',
|
||||
icon: 'i-lucide-plus',
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
@@ -0,0 +1,47 @@
|
||||
<script setup>
|
||||
import Button from './button/Button.vue';
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
buttons: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['click', 'close']);
|
||||
|
||||
const handleButtonClick = button => {
|
||||
emit('click', button.key);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex items-center justify-between px-4 py-2 border-b border-n-weak h-12"
|
||||
>
|
||||
<div class="flex items-center justify-between gap-2 flex-1">
|
||||
<span class="font-medium text-sm text-n-slate-12">{{ title }}</span>
|
||||
<div class="flex items-center">
|
||||
<Button
|
||||
v-for="button in buttons"
|
||||
:key="button.key"
|
||||
v-tooltip="button.tooltip"
|
||||
:icon="button.icon"
|
||||
ghost
|
||||
sm
|
||||
@click="handleButtonClick(button)"
|
||||
/>
|
||||
<Button
|
||||
v-tooltip="$t('GENERAL.CLOSE')"
|
||||
icon="i-lucide-x"
|
||||
ghost
|
||||
sm
|
||||
@click="$emit('close')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -3,13 +3,15 @@ import { nextTick, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useTrack } from 'dashboard/composables';
|
||||
import { COPILOT_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
|
||||
import CopilotInput from './CopilotInput.vue';
|
||||
import CopilotLoader from './CopilotLoader.vue';
|
||||
import CopilotAgentMessage from './CopilotAgentMessage.vue';
|
||||
import CopilotAssistantMessage from './CopilotAssistantMessage.vue';
|
||||
import ToggleCopilotAssistant from './ToggleCopilotAssistant.vue';
|
||||
import Icon from '../icon/Icon.vue';
|
||||
import Icon from 'dashboard/components-next/icon/Icon.vue';
|
||||
import SidebarActionsHeader from 'dashboard/components-next/SidebarActionsHeader.vue';
|
||||
|
||||
const props = defineProps({
|
||||
supportAgent: {
|
||||
@@ -54,10 +56,6 @@ const useSuggestion = opt => {
|
||||
useTrack(COPILOT_EVENTS.SEND_SUGGESTED);
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
emit('reset');
|
||||
};
|
||||
|
||||
const chatContainer = ref(null);
|
||||
|
||||
const scrollToBottom = async () => {
|
||||
@@ -82,6 +80,21 @@ const promptOptions = [
|
||||
},
|
||||
];
|
||||
|
||||
const { updateUISettings } = useUISettings();
|
||||
|
||||
const closeCopilotPanel = () => {
|
||||
updateUISettings({
|
||||
is_copilot_panel_open: false,
|
||||
is_contact_sidebar_open: false,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSidebarAction = action => {
|
||||
if (action === 'reset') {
|
||||
emit('reset');
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
[() => props.messages, () => props.isCaptainTyping],
|
||||
() => {
|
||||
@@ -93,6 +106,18 @@ watch(
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col h-full text-sm leading-6 tracking-tight w-full">
|
||||
<SidebarActionsHeader
|
||||
:title="$t('CAPTAIN.COPILOT.TITLE')"
|
||||
:buttons="[
|
||||
{
|
||||
key: 'reset',
|
||||
icon: 'i-lucide-refresh-ccw',
|
||||
tooltip: $t('CAPTAIN.COPILOT.RESET'),
|
||||
},
|
||||
]"
|
||||
@click="handleSidebarAction"
|
||||
@close="closeCopilotPanel"
|
||||
/>
|
||||
<div ref="chatContainer" class="flex-1 px-4 py-4 space-y-6 overflow-y-auto">
|
||||
<template v-for="message in messages" :key="message.id">
|
||||
<CopilotAgentMessage
|
||||
@@ -139,14 +164,6 @@ watch(
|
||||
@set-assistant="$event => emit('setAssistant', $event)"
|
||||
/>
|
||||
<div v-else />
|
||||
<button
|
||||
v-if="messages.length"
|
||||
class="text-xs flex items-center gap-1 hover:underline"
|
||||
@click="handleReset"
|
||||
>
|
||||
<i class="i-lucide-refresh-ccw" />
|
||||
<span>{{ $t('CAPTAIN.COPILOT.RESET') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<CopilotInput class="mb-1 w-full" @send="sendMessage" />
|
||||
</div>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<script setup>
|
||||
import Button from '../button/Button.vue';
|
||||
defineProps({
|
||||
hasMessages: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
defineEmits(['reset', 'close']);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex items-center justify-between px-5 py-2 border-b border-n-weak h-12"
|
||||
>
|
||||
<div class="flex items-center justify-between gap-2 flex-1">
|
||||
<span class="font-medium text-sm text-n-slate-12">
|
||||
{{ $t('CAPTAIN.COPILOT.TITLE') }}
|
||||
</span>
|
||||
<div class="flex items-center">
|
||||
<Button
|
||||
v-if="hasMessages"
|
||||
icon="i-lucide-plus"
|
||||
ghost
|
||||
sm
|
||||
@click="$emit('reset')"
|
||||
/>
|
||||
<Button icon="i-lucide-x" ghost sm @click="$emit('close')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -519,7 +519,7 @@ const menuItems = computed(() => {
|
||||
</div>
|
||||
</section>
|
||||
<nav class="grid flex-grow gap-2 px-2 pb-5 overflow-y-scroll no-scrollbar">
|
||||
<ul class="flex flex-col gap-2 m-0 list-none">
|
||||
<ul class="flex flex-col gap-1.5 m-0 list-none">
|
||||
<SidebarGroup
|
||||
v-for="item in menuItems"
|
||||
:key="item.name"
|
||||
|
||||
@@ -814,7 +814,7 @@ watch(conversationFilters, (newVal, oldVal) => {
|
||||
class="flex flex-col flex-shrink-0 bg-n-solid-1 conversations-list-wrap"
|
||||
:class="[
|
||||
{ hidden: !showConversationList },
|
||||
isOnExpandedLayout ? 'basis-full' : 'w-[360px] 2xl:w-[420px]',
|
||||
isOnExpandedLayout ? 'basis-full' : 'w-[340px] 2xl:w-[412px]',
|
||||
]"
|
||||
>
|
||||
<slot />
|
||||
|
||||
@@ -80,16 +80,14 @@ const toggleConversationLayout = () => {
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex items-center justify-between gap-2 px-4"
|
||||
class="flex items-center justify-between gap-2 px-3 h-12"
|
||||
:class="{
|
||||
'pb-3 border-b border-n-strong': hasAppliedFiltersOrActiveFolders,
|
||||
'pt-3 pb-2': showV4View,
|
||||
'mb-2 pb-0': !showV4View,
|
||||
'border-b border-n-strong': hasAppliedFiltersOrActiveFolders,
|
||||
}"
|
||||
>
|
||||
<div class="flex items-center justify-center min-w-0">
|
||||
<h1
|
||||
class="text-lg font-medium truncate text-n-slate-12"
|
||||
class="text-base font-medium truncate text-n-slate-12"
|
||||
:title="pageTitle"
|
||||
>
|
||||
{{ pageTitle }}
|
||||
|
||||
@@ -20,7 +20,7 @@ export default {
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
class="shadow-sm bg-slate-800 dark:bg-slate-700 rounded-[4px] items-center gap-3 inline-flex mb-2 max-w-[25rem] min-h-[1.875rem] min-w-[15rem] px-6 py-3 text-left"
|
||||
class="shadow-sm bg-n-slate-12 dark:bg-n-slate-7 rounded-lg items-center gap-3 inline-flex mb-2 max-w-[25rem] min-h-[1.875rem] min-w-[15rem] px-6 py-3 text-left"
|
||||
>
|
||||
<div class="text-sm font-medium text-white dark:text-white">
|
||||
{{ message }}
|
||||
@@ -29,7 +29,7 @@ export default {
|
||||
<router-link
|
||||
v-if="action.type == 'link'"
|
||||
:to="action.to"
|
||||
class="font-medium cursor-pointer select-none text-woot-500 dark:text-woot-500 hover:text-woot-600 dark:hover:text-woot-600"
|
||||
class="font-medium cursor-pointer select-none text-n-blue-10 hover:text-n-brand"
|
||||
>
|
||||
{{ action.message }}
|
||||
</router-link>
|
||||
|
||||
@@ -1,62 +1,72 @@
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
|
||||
import WootSnackbar from './Snackbar.vue';
|
||||
import { emitter } from 'shared/helpers/mitt';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WootSnackbar,
|
||||
},
|
||||
props: {
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 2500,
|
||||
},
|
||||
const props = defineProps({
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 2500,
|
||||
},
|
||||
});
|
||||
|
||||
data() {
|
||||
return {
|
||||
snackMessages: [],
|
||||
};
|
||||
},
|
||||
const { t } = useI18n();
|
||||
|
||||
mounted() {
|
||||
emitter.on('newToastMessage', this.onNewToastMessage);
|
||||
},
|
||||
unmounted() {
|
||||
emitter.off('newToastMessage', this.onNewToastMessage);
|
||||
},
|
||||
methods: {
|
||||
onNewToastMessage({ message: originalMessage, action }) {
|
||||
// FIX ME: This is a temporary workaround to pass string from functions
|
||||
// that doesn't have the context of the VueApp.
|
||||
const usei18n = action?.usei18n;
|
||||
const duration = action?.duration || this.duration;
|
||||
const message = usei18n ? this.$t(originalMessage) : originalMessage;
|
||||
const snackMessages = ref([]);
|
||||
const snackbarContainer = ref(null);
|
||||
|
||||
this.snackMessages.push({
|
||||
key: new Date().getTime(),
|
||||
message,
|
||||
action,
|
||||
});
|
||||
window.setTimeout(() => {
|
||||
this.snackMessages.splice(0, 1);
|
||||
}, duration);
|
||||
},
|
||||
},
|
||||
const showPopover = () => {
|
||||
try {
|
||||
const el = snackbarContainer.value;
|
||||
if (el?.matches(':popover-open')) {
|
||||
el.hidePopover();
|
||||
}
|
||||
el?.showPopover();
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
const onNewToastMessage = ({ message: originalMessage, action }) => {
|
||||
const message = action?.usei18n ? t(originalMessage) : originalMessage;
|
||||
const duration = action?.duration || props.duration;
|
||||
|
||||
snackMessages.value.push({
|
||||
key: Date.now(),
|
||||
message,
|
||||
action,
|
||||
});
|
||||
|
||||
nextTick(showPopover);
|
||||
|
||||
setTimeout(() => {
|
||||
snackMessages.value.shift();
|
||||
}, duration);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
emitter.on('newToastMessage', onNewToastMessage);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
emitter.off('newToastMessage', onNewToastMessage);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<transition-group
|
||||
name="toast-fade"
|
||||
tag="div"
|
||||
class="left-0 my-0 mx-auto max-w-[25rem] overflow-hidden absolute right-0 text-center top-4 z-[9999]"
|
||||
<div
|
||||
ref="snackbarContainer"
|
||||
popover="manual"
|
||||
class="fixed top-4 left-1/2 -translate-x-1/2 max-w-[25rem] w-[calc(100%-2rem)] text-center bg-transparent border-0 p-0 m-0 outline-none overflow-visible"
|
||||
>
|
||||
<WootSnackbar
|
||||
v-for="snackMessage in snackMessages"
|
||||
:key="snackMessage.key"
|
||||
:message="snackMessage.message"
|
||||
:action="snackMessage.action"
|
||||
/>
|
||||
</transition-group>
|
||||
<transition-group name="toast-fade" tag="div">
|
||||
<WootSnackbar
|
||||
v-for="snackMessage in snackMessages"
|
||||
:key="snackMessage.key"
|
||||
:message="snackMessage.message"
|
||||
:action="snackMessage.action"
|
||||
/>
|
||||
</transition-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -48,12 +48,13 @@ useKeyboardEvents(keyboardEvents);
|
||||
<template>
|
||||
<woot-tabs
|
||||
:index="activeTabIndex"
|
||||
class="w-full px-4 py-0 tab--chat-type"
|
||||
class="w-full px-3 -mt-1 py-0 tab--chat-type"
|
||||
@change="onTabChange"
|
||||
>
|
||||
<woot-tabs-item
|
||||
v-for="(item, index) in items"
|
||||
:key="item.key"
|
||||
class="text-sm"
|
||||
:index="index"
|
||||
:name="item.name"
|
||||
:count="item.count"
|
||||
|
||||
@@ -4,17 +4,14 @@ import ConversationHeader from './ConversationHeader.vue';
|
||||
import DashboardAppFrame from '../DashboardApp/Frame.vue';
|
||||
import EmptyState from './EmptyState/EmptyState.vue';
|
||||
import MessagesView from './MessagesView.vue';
|
||||
import ConversationSidebar from './ConversationSidebar.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ConversationSidebar,
|
||||
ConversationHeader,
|
||||
DashboardAppFrame,
|
||||
EmptyState,
|
||||
MessagesView,
|
||||
},
|
||||
|
||||
props: {
|
||||
inboxId: {
|
||||
type: [Number, String],
|
||||
@@ -34,7 +31,6 @@ export default {
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ['contactPanelToggle'],
|
||||
data() {
|
||||
return { activeIndex: 0 };
|
||||
},
|
||||
@@ -86,9 +82,6 @@ export default {
|
||||
}
|
||||
this.$store.dispatch('conversationLabels/get', this.currentChat.id);
|
||||
},
|
||||
onToggleContactPanel() {
|
||||
this.$emit('contactPanelToggle');
|
||||
},
|
||||
onDashboardAppTabChange(index) {
|
||||
this.activeIndex = index;
|
||||
},
|
||||
@@ -98,7 +91,7 @@ export default {
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="conversation-details-wrap bg-n-background"
|
||||
class="conversation-details-wrap bg-n-background relative"
|
||||
:class="{
|
||||
'border-l rtl:border-l-0 rtl:border-r border-n-weak': !isOnExpandedLayout,
|
||||
}"
|
||||
@@ -107,14 +100,12 @@ export default {
|
||||
v-if="currentChat.id"
|
||||
:chat="currentChat"
|
||||
:is-inbox-view="isInboxView"
|
||||
:is-contact-panel-open="isContactPanelOpen"
|
||||
:show-back-button="isOnExpandedLayout && !isInboxView"
|
||||
@contact-panel-toggle="onToggleContactPanel"
|
||||
/>
|
||||
<woot-tabs
|
||||
v-if="dashboardApps.length && currentChat.id"
|
||||
:index="activeIndex"
|
||||
class="-mt-px bg-white dashboard-app--tabs dark:bg-slate-900"
|
||||
class="-mt-px dashboard-app--tabs border-t border-t-n-background"
|
||||
@change="onDashboardAppTabChange"
|
||||
>
|
||||
<woot-tabs-item
|
||||
@@ -130,18 +121,12 @@ export default {
|
||||
v-if="currentChat.id"
|
||||
:inbox-id="inboxId"
|
||||
:is-inbox-view="isInboxView"
|
||||
:is-contact-panel-open="isContactPanelOpen"
|
||||
@contact-panel-toggle="onToggleContactPanel"
|
||||
/>
|
||||
<EmptyState
|
||||
v-if="!currentChat.id && !isInboxView"
|
||||
:is-on-expanded-layout="isOnExpandedLayout"
|
||||
/>
|
||||
<ConversationSidebar
|
||||
v-if="showContactPanel"
|
||||
:current-chat="currentChat"
|
||||
@toggle-contact-panel="onToggleContactPanel"
|
||||
/>
|
||||
<slot />
|
||||
</div>
|
||||
<DashboardAppFrame
|
||||
v-for="(dashboardApp, index) in dashboardApps"
|
||||
|
||||
@@ -243,7 +243,7 @@ export default {
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="relative flex items-start flex-grow-0 flex-shrink-0 w-auto max-w-full px-4 py-0 border-t-0 border-b-0 border-l-2 border-r-0 border-transparent border-solid cursor-pointer conversation hover:bg-n-alpha-1 dark:hover:bg-n-alpha-3 group"
|
||||
class="relative flex items-start flex-grow-0 flex-shrink-0 w-auto max-w-full px-3 py-0 border-t-0 border-b-0 border-l-2 border-r-0 border-transparent border-solid cursor-pointer conversation hover:bg-n-alpha-1 dark:hover:bg-n-alpha-3 group"
|
||||
:class="{
|
||||
'active animate-card-select bg-n-alpha-1 dark:bg-n-alpha-3 border-n-weak':
|
||||
isActiveChat,
|
||||
@@ -278,7 +278,7 @@ export default {
|
||||
:badge="inboxBadge"
|
||||
:username="currentContact.name"
|
||||
:status="currentContact.availability_status"
|
||||
size="40px"
|
||||
size="32px"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
||||
import BackButton from '../BackButton.vue';
|
||||
import inboxMixin from 'shared/mixins/inboxMixin';
|
||||
import InboxName from '../InboxName.vue';
|
||||
@@ -29,11 +28,7 @@ export default {
|
||||
props: {
|
||||
chat: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
isContactPanelOpen: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
showBackButton: {
|
||||
type: Boolean,
|
||||
@@ -44,15 +39,6 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['contactPanelToggle'],
|
||||
setup(props, { emit }) {
|
||||
const keyboardEvents = {
|
||||
'Alt+KeyO': {
|
||||
action: () => emit('contactPanelToggle'),
|
||||
},
|
||||
};
|
||||
useKeyboardEvents(keyboardEvents);
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentChat: 'getSelectedChat',
|
||||
@@ -99,13 +85,6 @@ export default {
|
||||
}
|
||||
return this.$t('CONVERSATION.HEADER.SNOOZED_UNTIL_NEXT_REPLY');
|
||||
},
|
||||
contactPanelToggleText() {
|
||||
return `${
|
||||
this.isContactPanelOpen
|
||||
? this.$t('CONVERSATION.HEADER.CLOSE')
|
||||
: this.$t('CONVERSATION.HEADER.OPEN')
|
||||
} ${this.$t('CONVERSATION.HEADER.DETAILS')}`;
|
||||
},
|
||||
inbox() {
|
||||
const { inbox_id: inboxId } = this.chat;
|
||||
return this.$store.getters['inboxes/getInbox'](inboxId);
|
||||
@@ -133,7 +112,7 @@ export default {
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col items-center justify-between px-4 py-2 border-b bg-n-background border-n-weak md:flex-row"
|
||||
class="flex flex-col items-center justify-between px-3 py-2 border-b bg-n-background border-n-weak md:flex-row h-12"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col items-center justify-center flex-1 w-full min-w-0"
|
||||
@@ -150,6 +129,7 @@ export default {
|
||||
:badge="inboxBadge"
|
||||
:username="currentContact.name"
|
||||
:status="currentContact.availability_status"
|
||||
size="32px"
|
||||
/>
|
||||
<div
|
||||
class="flex flex-col items-start min-w-0 ml-2 overflow-hidden rtl:ml-0 rtl:mr-2 w-fit"
|
||||
@@ -157,9 +137,9 @@ export default {
|
||||
<div
|
||||
class="flex flex-row items-center max-w-full gap-1 p-0 m-0 w-fit"
|
||||
>
|
||||
<NextButton link slate @click.prevent="$emit('contactPanelToggle')">
|
||||
<NextButton link slate>
|
||||
<span
|
||||
class="text-base font-medium truncate leading-tight text-n-slate-12"
|
||||
class="text-sm font-medium truncate leading-tight text-n-slate-12"
|
||||
>
|
||||
{{ currentContact.name }}
|
||||
</span>
|
||||
@@ -180,19 +160,11 @@ export default {
|
||||
<span v-if="isSnoozed" class="font-medium text-n-amber-10">
|
||||
{{ snoozedDisplayText }}
|
||||
</span>
|
||||
<NextButton
|
||||
link
|
||||
xs
|
||||
blue
|
||||
:label="contactPanelToggleText"
|
||||
@click="$emit('contactPanelToggle')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-row items-center justify-end flex-grow gap-2 mt-3 header-actions-wrap lg:mt-0"
|
||||
:class="{ 'justify-end': isContactPanelOpen }"
|
||||
>
|
||||
<SLACardLabel v-if="hasSlaPolicyId" :chat="chat" show-extended-info />
|
||||
<Linear
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import CopilotContainer from '../../copilot/CopilotContainer.vue';
|
||||
import ContactPanel from 'dashboard/routes/dashboard/conversation/ContactPanel.vue';
|
||||
import TabBar from 'dashboard/components-next/tabbar/TabBar.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useMapGetter } from 'dashboard/composables/store';
|
||||
import { FEATURE_FLAGS } from '../../../featureFlags';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
|
||||
const props = defineProps({
|
||||
currentChat: {
|
||||
@@ -14,33 +13,8 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['toggleContactPanel']);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const channelType = computed(() => props.currentChat?.meta?.channel || '');
|
||||
|
||||
const CONTACT_TABS_OPTIONS = [
|
||||
{ key: 'CONTACT', value: 'contact' },
|
||||
{ key: 'COPILOT', value: 'copilot' },
|
||||
];
|
||||
|
||||
const tabs = computed(() => {
|
||||
return CONTACT_TABS_OPTIONS.map(tab => ({
|
||||
label: t(`CONVERSATION.SIDEBAR.${tab.key}`),
|
||||
value: tab.value,
|
||||
}));
|
||||
});
|
||||
const activeTab = ref(0);
|
||||
const toggleContactPanel = () => {
|
||||
emit('toggleContactPanel');
|
||||
};
|
||||
|
||||
const handleTabChange = selectedTab => {
|
||||
activeTab.value = tabs.value.findIndex(
|
||||
tabItem => tabItem.value === selectedTab.value
|
||||
);
|
||||
};
|
||||
const currentAccountId = useMapGetter('getCurrentAccountId');
|
||||
const isFeatureEnabledonAccount = useMapGetter(
|
||||
'accounts/isFeatureEnabledonAccount'
|
||||
@@ -49,29 +23,37 @@ const isFeatureEnabledonAccount = useMapGetter(
|
||||
const showCopilotTab = computed(() =>
|
||||
isFeatureEnabledonAccount.value(currentAccountId.value, FEATURE_FLAGS.CAPTAIN)
|
||||
);
|
||||
|
||||
const { uiSettings } = useUISettings();
|
||||
|
||||
const activeTab = computed(() => {
|
||||
const {
|
||||
is_contact_sidebar_open: isContactSidebarOpen,
|
||||
is_copilot_panel_open: isCopilotPanelOpen,
|
||||
} = uiSettings.value;
|
||||
|
||||
if (isContactSidebarOpen) {
|
||||
return 0;
|
||||
}
|
||||
if (isCopilotPanelOpen) {
|
||||
return 1;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="ltr:border-l rtl:border-r border-n-weak h-full overflow-hidden z-10 w-80 min-w-80 2xl:min-w-96 2xl:w-96 flex flex-col bg-n-background"
|
||||
>
|
||||
<div v-if="showCopilotTab" class="p-2">
|
||||
<TabBar
|
||||
:tabs="tabs"
|
||||
:initial-active-tab="activeTab"
|
||||
class="w-full [&>button]:w-full"
|
||||
@tab-changed="handleTabChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-1 overflow-auto">
|
||||
<ContactPanel
|
||||
v-if="!activeTab"
|
||||
v-show="activeTab === 0"
|
||||
:conversation-id="currentChat.id"
|
||||
:inbox-id="currentChat.inbox_id"
|
||||
:on-toggle="toggleContactPanel"
|
||||
/>
|
||||
<CopilotContainer
|
||||
v-else-if="activeTab === 1 && showCopilotTab"
|
||||
v-show="activeTab === 1 && showCopilotTab"
|
||||
:key="currentChat.id"
|
||||
:conversation-inbox-type="channelType"
|
||||
:conversation-id="currentChat.id"
|
||||
|
||||
@@ -38,8 +38,6 @@ import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
||||
import { FEATURE_FLAGS } from '../../../featureFlags';
|
||||
import { INBOX_TYPES } from 'dashboard/helper/inbox';
|
||||
|
||||
import NextButton from 'dashboard/components-next/button/Button.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Message,
|
||||
@@ -47,20 +45,8 @@ export default {
|
||||
ReplyBox,
|
||||
Banner,
|
||||
ConversationLabelSuggestion,
|
||||
NextButton,
|
||||
},
|
||||
mixins: [inboxMixin],
|
||||
props: {
|
||||
isContactPanelOpen: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isInboxView: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['contactPanelToggle'],
|
||||
setup() {
|
||||
const isPopOutReplyBox = ref(false);
|
||||
const conversationPanelRef = ref(null);
|
||||
@@ -203,12 +189,6 @@ export default {
|
||||
isATweet() {
|
||||
return this.conversationType === 'tweet';
|
||||
},
|
||||
isRightOrLeftIcon() {
|
||||
if (this.isContactPanelOpen) {
|
||||
return 'arrow-chevron-right';
|
||||
}
|
||||
return 'arrow-chevron-left';
|
||||
},
|
||||
getLastSeenAt() {
|
||||
const { contact_last_seen_at: contactLastSeenAt } = this.currentChat;
|
||||
return contactLastSeenAt;
|
||||
@@ -444,9 +424,6 @@ export default {
|
||||
relevantMessages
|
||||
);
|
||||
},
|
||||
onToggleContactPanel() {
|
||||
this.$emit('contactPanelToggle');
|
||||
},
|
||||
setScrollParams() {
|
||||
this.heightBeforeLoad = this.conversationPanel.scrollHeight;
|
||||
this.scrollTopBeforeLoad = this.conversationPanel.scrollTop;
|
||||
@@ -530,19 +507,6 @@ export default {
|
||||
class="mx-2 mt-2 overflow-hidden rounded-lg"
|
||||
:banner-message="$t('CONVERSATION.OLD_INSTAGRAM_INBOX_REPLY_BANNER')"
|
||||
/>
|
||||
<div class="flex justify-end">
|
||||
<NextButton
|
||||
faded
|
||||
xs
|
||||
slate
|
||||
class="!rounded-r-none rtl:rotate-180 !rounded-2xl !fixed z-10"
|
||||
:icon="
|
||||
isContactPanelOpen ? 'i-ph-caret-right-fill' : 'i-ph-caret-left-fill'
|
||||
"
|
||||
:class="isInboxView ? 'top-52 md:top-40' : 'top-32'"
|
||||
@click="onToggleContactPanel"
|
||||
/>
|
||||
</div>
|
||||
<NextMessageList
|
||||
v-if="showNextBubbles"
|
||||
ref="conversationPanelRef"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"PHONE_INPUT": {
|
||||
"PLACEHOLDER": "Search",
|
||||
"EMPTY_STATE": "No results found"
|
||||
}
|
||||
},
|
||||
"CLOSE": "Close"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,14 +11,14 @@ import AccordionItem from 'dashboard/components/Accordion/AccordionItem.vue';
|
||||
import ContactConversations from './ContactConversations.vue';
|
||||
import ConversationAction from './ConversationAction.vue';
|
||||
import ConversationParticipant from './ConversationParticipant.vue';
|
||||
|
||||
import ContactInfo from './contact/ContactInfo.vue';
|
||||
import ContactNotes from './contact/ContactNotes.vue';
|
||||
import ConversationInfo from './ConversationInfo.vue';
|
||||
import CustomAttributes from './customAttributes/CustomAttributes.vue';
|
||||
import Draggable from 'vuedraggable';
|
||||
import MacrosList from './Macros/List.vue';
|
||||
import ShopifyOrdersList from '../../../components/widgets/conversation/ShopifyOrdersList.vue';
|
||||
import ShopifyOrdersList from 'dashboard/components/widgets/conversation/ShopifyOrdersList.vue';
|
||||
import SidebarActionsHeader from 'dashboard/components-next/SidebarActionsHeader.vue';
|
||||
|
||||
const props = defineProps({
|
||||
conversationId: {
|
||||
@@ -29,10 +29,6 @@ const props = defineProps({
|
||||
type: Number,
|
||||
default: undefined,
|
||||
},
|
||||
onToggle: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
@@ -89,8 +85,6 @@ watch(conversationId, (newConversationId, prevConversationId) => {
|
||||
|
||||
watch(contactId, getContactDetails);
|
||||
|
||||
const onPanelToggle = props.onToggle;
|
||||
|
||||
const onDragEnd = () => {
|
||||
dragging.value = false;
|
||||
updateUISettings({
|
||||
@@ -98,6 +92,13 @@ const onDragEnd = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const closeContactPanel = () => {
|
||||
updateUISettings({
|
||||
is_contact_sidebar_open: false,
|
||||
is_copilot_panel_open: false,
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
conversationSidebarItems.value = conversationSidebarItemsOrder.value;
|
||||
getContactDetails();
|
||||
@@ -107,11 +108,11 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<ContactInfo
|
||||
:contact="contact"
|
||||
:channel-type="channelType"
|
||||
@toggle-panel="onPanelToggle"
|
||||
<SidebarActionsHeader
|
||||
:title="$t('CONVERSATION.SIDEBAR.CONTACT')"
|
||||
@close="closeContactPanel"
|
||||
/>
|
||||
<ContactInfo :contact="contact" :channel-type="channelType" />
|
||||
<div class="list-group pb-8">
|
||||
<Draggable
|
||||
:list="conversationSidebarItems"
|
||||
|
||||
@@ -10,6 +10,8 @@ import { BUS_EVENTS } from 'shared/constants/busEvents';
|
||||
import CmdBarConversationSnooze from 'dashboard/routes/dashboard/commands/CmdBarConversationSnooze.vue';
|
||||
import { emitter } from 'shared/helpers/mitt';
|
||||
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
||||
import SidepanelSwitch from 'dashboard/components-next/Conversation/SidepanelSwitch.vue';
|
||||
import ConversationSidebar from 'dashboard/components/widgets/conversation/ConversationSidebar.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -17,6 +19,8 @@ export default {
|
||||
ConversationBox,
|
||||
PopOverSearch,
|
||||
CmdBarConversationSnooze,
|
||||
SidepanelSwitch,
|
||||
ConversationSidebar,
|
||||
},
|
||||
beforeRouteLeave(to, from, next) {
|
||||
// Clear selected state if navigating away from a conversation to a route without a conversationId to prevent stale data issues
|
||||
@@ -87,13 +91,17 @@ export default {
|
||||
this.uiSettings;
|
||||
return conversationDisplayType !== CONDENSED;
|
||||
},
|
||||
isContactPanelOpen() {
|
||||
if (this.currentChat.id) {
|
||||
const { is_contact_sidebar_open: isContactSidebarOpen } =
|
||||
this.uiSettings;
|
||||
return isContactSidebarOpen;
|
||||
|
||||
shouldShowSidebar() {
|
||||
if (!this.currentChat.id) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
const {
|
||||
is_contact_sidebar_open: isContactSidebarOpen,
|
||||
is_copilot_panel_open: isCopilotPanelOpen,
|
||||
} = this.uiSettings;
|
||||
return isContactSidebarOpen || isCopilotPanelOpen;
|
||||
},
|
||||
showPopOverSearch() {
|
||||
return !this.isFeatureEnabledonAccount(
|
||||
@@ -189,11 +197,6 @@ export default {
|
||||
this.$store.dispatch('clearSelectedState');
|
||||
}
|
||||
},
|
||||
onToggleContactPanel() {
|
||||
this.updateUISettings({
|
||||
is_contact_sidebar_open: !this.isContactPanelOpen,
|
||||
});
|
||||
},
|
||||
onSearch() {
|
||||
this.showSearchModal = true;
|
||||
},
|
||||
@@ -225,10 +228,11 @@ export default {
|
||||
<ConversationBox
|
||||
v-if="showMessageView"
|
||||
:inbox-id="inboxId"
|
||||
:is-contact-panel-open="isContactPanelOpen"
|
||||
:is-on-expanded-layout="isOnExpandedLayout"
|
||||
@contact-panel-toggle="onToggleContactPanel"
|
||||
/>
|
||||
>
|
||||
<SidepanelSwitch v-if="currentChat.id" />
|
||||
</ConversationBox>
|
||||
<ConversationSidebar v-if="shouldShowSidebar" :current-chat="currentChat" />
|
||||
<CmdBarConversationSnooze />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -62,6 +62,15 @@ Rails.application.configure do
|
||||
|
||||
# Disable host check during development
|
||||
config.hosts = nil
|
||||
|
||||
# GitHub Codespaces configuration
|
||||
if ENV['CODESPACES']
|
||||
# Allow web console access from any IP
|
||||
config.web_console.whitelisted_ips = %w(0.0.0.0/0 ::/0)
|
||||
# Allow CSRF from codespace URLs
|
||||
config.force_ssl = false
|
||||
config.action_controller.forgery_protection_origin_check = false
|
||||
end
|
||||
|
||||
# customize using the environment variables
|
||||
config.log_level = ENV.fetch('LOG_LEVEL', 'debug').to_sym
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@
|
||||
premium: true
|
||||
- name: chatwoot_v4
|
||||
display_name: Chatwoot V4
|
||||
enabled: false
|
||||
enabled: true
|
||||
- name: report_v4
|
||||
display_name: Report V4
|
||||
enabled: true
|
||||
|
||||
@@ -60,6 +60,10 @@ webhook:
|
||||
$ref: ./resource/webhook.yml
|
||||
account:
|
||||
$ref: ./resource/account.yml
|
||||
account_detail:
|
||||
$ref: ./resource/account_detail.yml
|
||||
account_show_response:
|
||||
$ref: ./resource/account_show_response.yml
|
||||
account_user:
|
||||
$ref: ./resource/account_user.yml
|
||||
platform_account:
|
||||
@@ -87,6 +91,9 @@ public_inbox:
|
||||
account_create_update_payload:
|
||||
$ref: ./request/account/create_update_payload.yml
|
||||
|
||||
account_update_payload:
|
||||
$ref: ./request/account/update_payload.yml
|
||||
|
||||
account_user_create_update_payload:
|
||||
$ref: ./request/account_user/create_update_payload.yml
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: Name of the account
|
||||
example: 'My Account'
|
||||
locale:
|
||||
type: string
|
||||
description: The locale of the account
|
||||
example: 'en'
|
||||
domain:
|
||||
type: string
|
||||
description: The domain of the account
|
||||
example: 'example.com'
|
||||
support_email:
|
||||
type: string
|
||||
description: The support email of the account
|
||||
example: 'support@example.com'
|
||||
# Settings parameters (stored in settings JSONB column)
|
||||
auto_resolve_after:
|
||||
type: integer
|
||||
minimum: 10
|
||||
maximum: 1439856
|
||||
nullable: true
|
||||
description: Auto resolve conversations after specified minutes
|
||||
example: 1440
|
||||
auto_resolve_message:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Message to send when auto resolving
|
||||
example: "This conversation has been automatically resolved due to inactivity"
|
||||
auto_resolve_ignore_waiting:
|
||||
type: boolean
|
||||
nullable: true
|
||||
description: Whether to ignore waiting conversations for auto resolve
|
||||
example: false
|
||||
# Custom attributes parameters (stored in custom_attributes JSONB column)
|
||||
industry:
|
||||
type: string
|
||||
description: Industry type
|
||||
example: "Technology"
|
||||
company_size:
|
||||
type: string
|
||||
description: Company size
|
||||
example: "50-100"
|
||||
timezone:
|
||||
type: string
|
||||
description: Account timezone
|
||||
example: "UTC"
|
||||
@@ -0,0 +1,84 @@
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: number
|
||||
description: Account ID
|
||||
name:
|
||||
type: string
|
||||
description: Name of the account
|
||||
locale:
|
||||
type: string
|
||||
description: The locale of the account
|
||||
domain:
|
||||
type: string
|
||||
description: The domain of the account
|
||||
support_email:
|
||||
type: string
|
||||
description: The support email of the account
|
||||
status:
|
||||
type: string
|
||||
description: The status of the account
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The creation date of the account
|
||||
cache_keys:
|
||||
type: object
|
||||
description: Cache keys for the account
|
||||
features:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Enabled features for the account
|
||||
settings:
|
||||
type: object
|
||||
description: Account settings
|
||||
properties:
|
||||
auto_resolve_after:
|
||||
type: number
|
||||
description: Auto resolve conversations after specified minutes
|
||||
auto_resolve_message:
|
||||
type: string
|
||||
description: Message to send when auto resolving
|
||||
auto_resolve_ignore_waiting:
|
||||
type: boolean
|
||||
description: Whether to ignore waiting conversations for auto resolve
|
||||
custom_attributes:
|
||||
type: object
|
||||
description: Custom attributes of the account
|
||||
properties:
|
||||
plan_name:
|
||||
type: string
|
||||
description: Subscription plan name
|
||||
subscribed_quantity:
|
||||
type: number
|
||||
description: Subscribed quantity
|
||||
subscription_status:
|
||||
type: string
|
||||
description: Subscription status
|
||||
subscription_ends_on:
|
||||
type: string
|
||||
format: date
|
||||
description: Subscription end date
|
||||
industry:
|
||||
type: string
|
||||
description: Industry type
|
||||
company_size:
|
||||
type: string
|
||||
description: Company size
|
||||
timezone:
|
||||
type: string
|
||||
description: Account timezone
|
||||
logo:
|
||||
type: string
|
||||
description: Account logo URL
|
||||
onboarding_step:
|
||||
type: string
|
||||
description: Current onboarding step
|
||||
marked_for_deletion_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: When account was marked for deletion
|
||||
marked_for_deletion_reason:
|
||||
type: string
|
||||
description: Reason for account deletion
|
||||
@@ -0,0 +1,13 @@
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/account_detail'
|
||||
- type: object
|
||||
properties:
|
||||
latest_chatwoot_version:
|
||||
type: string
|
||||
description: Latest version of Chatwoot available
|
||||
example: "3.0.0"
|
||||
subscribed_features:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: List of subscribed enterprise features (if enterprise edition is enabled)
|
||||
@@ -0,0 +1,28 @@
|
||||
tags:
|
||||
- Account
|
||||
operationId: get-account-details
|
||||
summary: Get account details
|
||||
description: Get the details of the current account
|
||||
security:
|
||||
- userApiKey: []
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/account_id'
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/account_show_response'
|
||||
'401':
|
||||
description: Unauthorized
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/bad_request_error'
|
||||
'404':
|
||||
description: Account not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/bad_request_error'
|
||||
@@ -0,0 +1,43 @@
|
||||
tags:
|
||||
- Account
|
||||
operationId: update-account
|
||||
summary: Update account
|
||||
description: Update account details, settings, and custom attributes
|
||||
security:
|
||||
- userApiKey: []
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/account_id'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/account_update_payload'
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
$ref: '#/components/schemas/account_update_payload'
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/account_detail'
|
||||
'401':
|
||||
description: Unauthorized (requires administrator role)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/bad_request_error'
|
||||
'404':
|
||||
description: Account not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/bad_request_error'
|
||||
'422':
|
||||
description: Validation error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/bad_request_error'
|
||||
@@ -166,6 +166,15 @@
|
||||
|
||||
# ------------ Application API routes ------------#
|
||||
|
||||
# Accounts
|
||||
/api/v1/accounts/{id}:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/account_id'
|
||||
get:
|
||||
$ref: ./application/accounts/show.yml
|
||||
patch:
|
||||
$ref: ./application/accounts/update.yml
|
||||
|
||||
# AgentBots
|
||||
/api/v1/accounts/{account_id}/agent_bots:
|
||||
parameters:
|
||||
|
||||
@@ -1476,6 +1476,138 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/accounts/{id}": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/account_id"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"tags": [
|
||||
"Account"
|
||||
],
|
||||
"operationId": "get-account-details",
|
||||
"summary": "Get account details",
|
||||
"description": "Get the details of the current account",
|
||||
"security": [
|
||||
{
|
||||
"userApiKey": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/account_id"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/account_show_response"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/bad_request_error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Account not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/bad_request_error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"tags": [
|
||||
"Account"
|
||||
],
|
||||
"operationId": "update-account",
|
||||
"summary": "Update account",
|
||||
"description": "Update account details, settings, and custom attributes",
|
||||
"security": [
|
||||
{
|
||||
"userApiKey": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/account_id"
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/account_update_payload"
|
||||
}
|
||||
},
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/account_update_payload"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/account_detail"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized (requires administrator role)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/bad_request_error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Account not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/bad_request_error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/bad_request_error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/accounts/{account_id}/agent_bots": {
|
||||
"parameters": [
|
||||
{
|
||||
@@ -8774,6 +8906,145 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_detail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Account ID"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "The status of the account"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "The creation date of the account"
|
||||
},
|
||||
"cache_keys": {
|
||||
"type": "object",
|
||||
"description": "Cache keys for the account"
|
||||
},
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Enabled features for the account"
|
||||
},
|
||||
"settings": {
|
||||
"type": "object",
|
||||
"description": "Account settings",
|
||||
"properties": {
|
||||
"auto_resolve_after": {
|
||||
"type": "number",
|
||||
"description": "Auto resolve conversations after specified minutes"
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"description": "Message to send when auto resolving"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to ignore waiting conversations for auto resolve"
|
||||
}
|
||||
}
|
||||
},
|
||||
"custom_attributes": {
|
||||
"type": "object",
|
||||
"description": "Custom attributes of the account",
|
||||
"properties": {
|
||||
"plan_name": {
|
||||
"type": "string",
|
||||
"description": "Subscription plan name"
|
||||
},
|
||||
"subscribed_quantity": {
|
||||
"type": "number",
|
||||
"description": "Subscribed quantity"
|
||||
},
|
||||
"subscription_status": {
|
||||
"type": "string",
|
||||
"description": "Subscription status"
|
||||
},
|
||||
"subscription_ends_on": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Subscription end date"
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone"
|
||||
},
|
||||
"logo": {
|
||||
"type": "string",
|
||||
"description": "Account logo URL"
|
||||
},
|
||||
"onboarding_step": {
|
||||
"type": "string",
|
||||
"description": "Current onboarding step"
|
||||
},
|
||||
"marked_for_deletion_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "When account was marked for deletion"
|
||||
},
|
||||
"marked_for_deletion_reason": {
|
||||
"type": "string",
|
||||
"description": "Reason for account deletion"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_show_response": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/account_detail"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"latest_chatwoot_version": {
|
||||
"type": "string",
|
||||
"description": "Latest version of Chatwoot available",
|
||||
"example": "3.0.0"
|
||||
},
|
||||
"subscribed_features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "List of subscribed enterprise features (if enterprise edition is enabled)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"account_user": {
|
||||
"type": "array",
|
||||
"description": "Array of account users",
|
||||
@@ -9113,6 +9384,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_update_payload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account",
|
||||
"example": "My Account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account",
|
||||
"example": "en"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account",
|
||||
"example": "example.com"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account",
|
||||
"example": "support@example.com"
|
||||
},
|
||||
"auto_resolve_after": {
|
||||
"type": "integer",
|
||||
"minimum": 10,
|
||||
"maximum": 1439856,
|
||||
"nullable": true,
|
||||
"description": "Auto resolve conversations after specified minutes",
|
||||
"example": 1440
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Message to send when auto resolving",
|
||||
"example": "This conversation has been automatically resolved due to inactivity"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"description": "Whether to ignore waiting conversations for auto resolve",
|
||||
"example": false
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type",
|
||||
"example": "Technology"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size",
|
||||
"example": "50-100"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone",
|
||||
"example": "UTC"
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_user_create_update_payload": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@@ -7135,6 +7135,145 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_detail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Account ID"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "The status of the account"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "The creation date of the account"
|
||||
},
|
||||
"cache_keys": {
|
||||
"type": "object",
|
||||
"description": "Cache keys for the account"
|
||||
},
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Enabled features for the account"
|
||||
},
|
||||
"settings": {
|
||||
"type": "object",
|
||||
"description": "Account settings",
|
||||
"properties": {
|
||||
"auto_resolve_after": {
|
||||
"type": "number",
|
||||
"description": "Auto resolve conversations after specified minutes"
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"description": "Message to send when auto resolving"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to ignore waiting conversations for auto resolve"
|
||||
}
|
||||
}
|
||||
},
|
||||
"custom_attributes": {
|
||||
"type": "object",
|
||||
"description": "Custom attributes of the account",
|
||||
"properties": {
|
||||
"plan_name": {
|
||||
"type": "string",
|
||||
"description": "Subscription plan name"
|
||||
},
|
||||
"subscribed_quantity": {
|
||||
"type": "number",
|
||||
"description": "Subscribed quantity"
|
||||
},
|
||||
"subscription_status": {
|
||||
"type": "string",
|
||||
"description": "Subscription status"
|
||||
},
|
||||
"subscription_ends_on": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Subscription end date"
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone"
|
||||
},
|
||||
"logo": {
|
||||
"type": "string",
|
||||
"description": "Account logo URL"
|
||||
},
|
||||
"onboarding_step": {
|
||||
"type": "string",
|
||||
"description": "Current onboarding step"
|
||||
},
|
||||
"marked_for_deletion_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "When account was marked for deletion"
|
||||
},
|
||||
"marked_for_deletion_reason": {
|
||||
"type": "string",
|
||||
"description": "Reason for account deletion"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_show_response": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/account_detail"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"latest_chatwoot_version": {
|
||||
"type": "string",
|
||||
"description": "Latest version of Chatwoot available",
|
||||
"example": "3.0.0"
|
||||
},
|
||||
"subscribed_features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "List of subscribed enterprise features (if enterprise edition is enabled)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"account_user": {
|
||||
"type": "array",
|
||||
"description": "Array of account users",
|
||||
@@ -7474,6 +7613,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_update_payload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account",
|
||||
"example": "My Account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account",
|
||||
"example": "en"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account",
|
||||
"example": "example.com"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account",
|
||||
"example": "support@example.com"
|
||||
},
|
||||
"auto_resolve_after": {
|
||||
"type": "integer",
|
||||
"minimum": 10,
|
||||
"maximum": 1439856,
|
||||
"nullable": true,
|
||||
"description": "Auto resolve conversations after specified minutes",
|
||||
"example": 1440
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Message to send when auto resolving",
|
||||
"example": "This conversation has been automatically resolved due to inactivity"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"description": "Whether to ignore waiting conversations for auto resolve",
|
||||
"example": false
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type",
|
||||
"example": "Technology"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size",
|
||||
"example": "50-100"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone",
|
||||
"example": "UTC"
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_user_create_update_payload": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@@ -1978,6 +1978,145 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_detail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Account ID"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "The status of the account"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "The creation date of the account"
|
||||
},
|
||||
"cache_keys": {
|
||||
"type": "object",
|
||||
"description": "Cache keys for the account"
|
||||
},
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Enabled features for the account"
|
||||
},
|
||||
"settings": {
|
||||
"type": "object",
|
||||
"description": "Account settings",
|
||||
"properties": {
|
||||
"auto_resolve_after": {
|
||||
"type": "number",
|
||||
"description": "Auto resolve conversations after specified minutes"
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"description": "Message to send when auto resolving"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to ignore waiting conversations for auto resolve"
|
||||
}
|
||||
}
|
||||
},
|
||||
"custom_attributes": {
|
||||
"type": "object",
|
||||
"description": "Custom attributes of the account",
|
||||
"properties": {
|
||||
"plan_name": {
|
||||
"type": "string",
|
||||
"description": "Subscription plan name"
|
||||
},
|
||||
"subscribed_quantity": {
|
||||
"type": "number",
|
||||
"description": "Subscribed quantity"
|
||||
},
|
||||
"subscription_status": {
|
||||
"type": "string",
|
||||
"description": "Subscription status"
|
||||
},
|
||||
"subscription_ends_on": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Subscription end date"
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone"
|
||||
},
|
||||
"logo": {
|
||||
"type": "string",
|
||||
"description": "Account logo URL"
|
||||
},
|
||||
"onboarding_step": {
|
||||
"type": "string",
|
||||
"description": "Current onboarding step"
|
||||
},
|
||||
"marked_for_deletion_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "When account was marked for deletion"
|
||||
},
|
||||
"marked_for_deletion_reason": {
|
||||
"type": "string",
|
||||
"description": "Reason for account deletion"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_show_response": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/account_detail"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"latest_chatwoot_version": {
|
||||
"type": "string",
|
||||
"description": "Latest version of Chatwoot available",
|
||||
"example": "3.0.0"
|
||||
},
|
||||
"subscribed_features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "List of subscribed enterprise features (if enterprise edition is enabled)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"account_user": {
|
||||
"type": "array",
|
||||
"description": "Array of account users",
|
||||
@@ -2317,6 +2456,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_update_payload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account",
|
||||
"example": "My Account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account",
|
||||
"example": "en"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account",
|
||||
"example": "example.com"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account",
|
||||
"example": "support@example.com"
|
||||
},
|
||||
"auto_resolve_after": {
|
||||
"type": "integer",
|
||||
"minimum": 10,
|
||||
"maximum": 1439856,
|
||||
"nullable": true,
|
||||
"description": "Auto resolve conversations after specified minutes",
|
||||
"example": 1440
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Message to send when auto resolving",
|
||||
"example": "This conversation has been automatically resolved due to inactivity"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"description": "Whether to ignore waiting conversations for auto resolve",
|
||||
"example": false
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type",
|
||||
"example": "Technology"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size",
|
||||
"example": "50-100"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone",
|
||||
"example": "UTC"
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_user_create_update_payload": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@@ -1393,6 +1393,145 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_detail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Account ID"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "The status of the account"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "The creation date of the account"
|
||||
},
|
||||
"cache_keys": {
|
||||
"type": "object",
|
||||
"description": "Cache keys for the account"
|
||||
},
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Enabled features for the account"
|
||||
},
|
||||
"settings": {
|
||||
"type": "object",
|
||||
"description": "Account settings",
|
||||
"properties": {
|
||||
"auto_resolve_after": {
|
||||
"type": "number",
|
||||
"description": "Auto resolve conversations after specified minutes"
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"description": "Message to send when auto resolving"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to ignore waiting conversations for auto resolve"
|
||||
}
|
||||
}
|
||||
},
|
||||
"custom_attributes": {
|
||||
"type": "object",
|
||||
"description": "Custom attributes of the account",
|
||||
"properties": {
|
||||
"plan_name": {
|
||||
"type": "string",
|
||||
"description": "Subscription plan name"
|
||||
},
|
||||
"subscribed_quantity": {
|
||||
"type": "number",
|
||||
"description": "Subscribed quantity"
|
||||
},
|
||||
"subscription_status": {
|
||||
"type": "string",
|
||||
"description": "Subscription status"
|
||||
},
|
||||
"subscription_ends_on": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Subscription end date"
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone"
|
||||
},
|
||||
"logo": {
|
||||
"type": "string",
|
||||
"description": "Account logo URL"
|
||||
},
|
||||
"onboarding_step": {
|
||||
"type": "string",
|
||||
"description": "Current onboarding step"
|
||||
},
|
||||
"marked_for_deletion_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "When account was marked for deletion"
|
||||
},
|
||||
"marked_for_deletion_reason": {
|
||||
"type": "string",
|
||||
"description": "Reason for account deletion"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_show_response": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/account_detail"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"latest_chatwoot_version": {
|
||||
"type": "string",
|
||||
"description": "Latest version of Chatwoot available",
|
||||
"example": "3.0.0"
|
||||
},
|
||||
"subscribed_features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "List of subscribed enterprise features (if enterprise edition is enabled)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"account_user": {
|
||||
"type": "array",
|
||||
"description": "Array of account users",
|
||||
@@ -1732,6 +1871,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_update_payload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account",
|
||||
"example": "My Account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account",
|
||||
"example": "en"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account",
|
||||
"example": "example.com"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account",
|
||||
"example": "support@example.com"
|
||||
},
|
||||
"auto_resolve_after": {
|
||||
"type": "integer",
|
||||
"minimum": 10,
|
||||
"maximum": 1439856,
|
||||
"nullable": true,
|
||||
"description": "Auto resolve conversations after specified minutes",
|
||||
"example": 1440
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Message to send when auto resolving",
|
||||
"example": "This conversation has been automatically resolved due to inactivity"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"description": "Whether to ignore waiting conversations for auto resolve",
|
||||
"example": false
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type",
|
||||
"example": "Technology"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size",
|
||||
"example": "50-100"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone",
|
||||
"example": "UTC"
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_user_create_update_payload": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@@ -2154,6 +2154,145 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_detail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Account ID"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "The status of the account"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "The creation date of the account"
|
||||
},
|
||||
"cache_keys": {
|
||||
"type": "object",
|
||||
"description": "Cache keys for the account"
|
||||
},
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Enabled features for the account"
|
||||
},
|
||||
"settings": {
|
||||
"type": "object",
|
||||
"description": "Account settings",
|
||||
"properties": {
|
||||
"auto_resolve_after": {
|
||||
"type": "number",
|
||||
"description": "Auto resolve conversations after specified minutes"
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"description": "Message to send when auto resolving"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to ignore waiting conversations for auto resolve"
|
||||
}
|
||||
}
|
||||
},
|
||||
"custom_attributes": {
|
||||
"type": "object",
|
||||
"description": "Custom attributes of the account",
|
||||
"properties": {
|
||||
"plan_name": {
|
||||
"type": "string",
|
||||
"description": "Subscription plan name"
|
||||
},
|
||||
"subscribed_quantity": {
|
||||
"type": "number",
|
||||
"description": "Subscribed quantity"
|
||||
},
|
||||
"subscription_status": {
|
||||
"type": "string",
|
||||
"description": "Subscription status"
|
||||
},
|
||||
"subscription_ends_on": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Subscription end date"
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone"
|
||||
},
|
||||
"logo": {
|
||||
"type": "string",
|
||||
"description": "Account logo URL"
|
||||
},
|
||||
"onboarding_step": {
|
||||
"type": "string",
|
||||
"description": "Current onboarding step"
|
||||
},
|
||||
"marked_for_deletion_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "When account was marked for deletion"
|
||||
},
|
||||
"marked_for_deletion_reason": {
|
||||
"type": "string",
|
||||
"description": "Reason for account deletion"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_show_response": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/account_detail"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"latest_chatwoot_version": {
|
||||
"type": "string",
|
||||
"description": "Latest version of Chatwoot available",
|
||||
"example": "3.0.0"
|
||||
},
|
||||
"subscribed_features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "List of subscribed enterprise features (if enterprise edition is enabled)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"account_user": {
|
||||
"type": "array",
|
||||
"description": "Array of account users",
|
||||
@@ -2493,6 +2632,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_update_payload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the account",
|
||||
"example": "My Account"
|
||||
},
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "The locale of the account",
|
||||
"example": "en"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The domain of the account",
|
||||
"example": "example.com"
|
||||
},
|
||||
"support_email": {
|
||||
"type": "string",
|
||||
"description": "The support email of the account",
|
||||
"example": "support@example.com"
|
||||
},
|
||||
"auto_resolve_after": {
|
||||
"type": "integer",
|
||||
"minimum": 10,
|
||||
"maximum": 1439856,
|
||||
"nullable": true,
|
||||
"description": "Auto resolve conversations after specified minutes",
|
||||
"example": 1440
|
||||
},
|
||||
"auto_resolve_message": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Message to send when auto resolving",
|
||||
"example": "This conversation has been automatically resolved due to inactivity"
|
||||
},
|
||||
"auto_resolve_ignore_waiting": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"description": "Whether to ignore waiting conversations for auto resolve",
|
||||
"example": false
|
||||
},
|
||||
"industry": {
|
||||
"type": "string",
|
||||
"description": "Industry type",
|
||||
"example": "Technology"
|
||||
},
|
||||
"company_size": {
|
||||
"type": "string",
|
||||
"description": "Company size",
|
||||
"example": "50-100"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"description": "Account timezone",
|
||||
"example": "UTC"
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_user_create_update_payload": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
Reference in New Issue
Block a user