chore: Adjust Chatwoot Config to deploy frontend as a separate app (#2347)
This commit is contained in:
@@ -46,5 +46,4 @@
|
|||||||
|
|
||||||
@import 'plugins/multiselect';
|
@import 'plugins/multiselect';
|
||||||
@import 'plugins/dropdown';
|
@import 'plugins/dropdown';
|
||||||
@import '@chatwoot/prosemirror-schema/src/woot-editor.css';
|
|
||||||
@import '~shared/assets/stylesheets/ionicons';
|
@import '~shared/assets/stylesheets/ionicons';
|
||||||
|
|||||||
@@ -2,20 +2,22 @@
|
|||||||
<div class="inbox-item">
|
<div class="inbox-item">
|
||||||
<img src="~dashboard/assets/images/no_page_image.png" alt="No Page Image" />
|
<img src="~dashboard/assets/images/no_page_image.png" alt="No Page Image" />
|
||||||
<div class="item--details columns">
|
<div class="item--details columns">
|
||||||
<h4 class="item--name">{{ inbox.label }}</h4>
|
<h4 class="item--name">
|
||||||
<p class="item--sub">Facebook</p>
|
{{ inbox.label }}
|
||||||
|
</h4>
|
||||||
|
<p class="item--sub">
|
||||||
|
Facebook
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- <span class="ion-chevron-right arrow"></span> -->
|
<!-- <span class="ion-chevron-right arrow"></span> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
/* eslint no-console: 0 */
|
/* eslint no-console: 0 */
|
||||||
/* global bus */
|
|
||||||
// import WootSwitch from '../ui/Switch';
|
// import WootSwitch from '../ui/Switch';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['inbox'],
|
props: ['inbox'],
|
||||||
created() {
|
created() {},
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import TagAgents from '../conversation/TagAgents.vue';
|
|||||||
import { EditorState } from 'prosemirror-state';
|
import { EditorState } from 'prosemirror-state';
|
||||||
import { defaultMarkdownParser } from 'prosemirror-markdown';
|
import { defaultMarkdownParser } from 'prosemirror-markdown';
|
||||||
import { wootWriterSetup } from '@chatwoot/prosemirror-schema';
|
import { wootWriterSetup } from '@chatwoot/prosemirror-schema';
|
||||||
|
import '@chatwoot/prosemirror-schema/src/woot-editor.css';
|
||||||
|
|
||||||
const createState = (content, placeholder, plugins = []) => {
|
const createState = (content, placeholder, plugins = []) => {
|
||||||
return EditorState.create({
|
return EditorState.create({
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
export default {
|
export default {
|
||||||
APP_BASE_URL: '/',
|
|
||||||
get apiURL() {
|
|
||||||
return `${this.APP_BASE_URL}/`;
|
|
||||||
},
|
|
||||||
GRAVATAR_URL: 'https://www.gravatar.com/avatar/',
|
GRAVATAR_URL: 'https://www.gravatar.com/avatar/',
|
||||||
ASSIGNEE_TYPE: {
|
ASSIGNEE_TYPE: {
|
||||||
ME: 'me',
|
ME: 'me',
|
||||||
@@ -15,3 +11,4 @@ export default {
|
|||||||
BOT: 'bot',
|
BOT: 'bot',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
export const DEFAULT_REDIRECT_URL = '/app/';
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
/* eslint no-console: 0 */
|
/* eslint no-console: 0 */
|
||||||
import constants from '../constants';
|
|
||||||
import Auth from '../api/auth';
|
import Auth from '../api/auth';
|
||||||
|
|
||||||
const parseErrorCode = error => {
|
const parseErrorCode = error => Promise.reject(error);
|
||||||
return Promise.reject(error);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default axios => {
|
export default axios => {
|
||||||
const wootApi = axios.create();
|
const { apiHost = '' } = window.chatwootConfig || {};
|
||||||
wootApi.defaults.baseURL = constants.apiURL;
|
const wootApi = axios.create({ baseURL: `${apiHost}/` });
|
||||||
// Add Auth Headers to requests if logged in
|
// Add Auth Headers to requests if logged in
|
||||||
if (Auth.isLoggedIn()) {
|
if (Auth.isLoggedIn()) {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { newMessageNotification } from 'shared/helpers/AudioNotificationHelper';
|
|||||||
|
|
||||||
class ActionCableConnector extends BaseActionCableConnector {
|
class ActionCableConnector extends BaseActionCableConnector {
|
||||||
constructor(app, pubsubToken) {
|
constructor(app, pubsubToken) {
|
||||||
super(app, pubsubToken);
|
const { websocketURL = '' } = window.chatwootConfig || {};
|
||||||
|
super(app, pubsubToken, websocketURL);
|
||||||
this.CancelTyping = [];
|
this.CancelTyping = [];
|
||||||
this.events = {
|
this.events = {
|
||||||
'message.created': this.onMessageCreated,
|
'message.created': this.onMessageCreated,
|
||||||
|
|||||||
@@ -2,31 +2,35 @@
|
|||||||
<loading-state :message="$t('CONFIRM_EMAIL')"></loading-state>
|
<loading-state :message="$t('CONFIRM_EMAIL')"></loading-state>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
/* eslint-disable */
|
|
||||||
import LoadingState from '../../components/widgets/LoadingState';
|
import LoadingState from '../../components/widgets/LoadingState';
|
||||||
import Auth from '../../api/auth';
|
import Auth from '../../api/auth';
|
||||||
|
import { DEFAULT_REDIRECT_URL } from '../../constants';
|
||||||
export default {
|
export default {
|
||||||
props: {
|
|
||||||
confirmationToken: String,
|
|
||||||
redirectUrl: String,
|
|
||||||
config: String,
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
LoadingState,
|
LoadingState,
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
confirmationToken: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.confirmToken();
|
this.confirmToken();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
confirmToken() {
|
async confirmToken() {
|
||||||
Auth.verifyPasswordToken({
|
try {
|
||||||
confirmationToken: this.confirmationToken
|
const {
|
||||||
}).then(res => {
|
data: { redirect_url: redirectURL },
|
||||||
window.location = res.data.redirect_url;
|
} = await Auth.verifyPasswordToken({
|
||||||
}).catch(res => {
|
confirmationToken: this.confirmationToken,
|
||||||
window.location = '/';
|
|
||||||
});
|
});
|
||||||
|
window.location = redirectURL;
|
||||||
|
} catch (error) {
|
||||||
|
window.location = DEFAULT_REDIRECT_URL;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -46,12 +46,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* global bus */
|
|
||||||
|
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from 'vuelidate/lib/validators';
|
||||||
import Auth from '../../api/auth';
|
import Auth from '../../api/auth';
|
||||||
|
|
||||||
import WootSubmitButton from '../../components/buttons/FormSubmitButton';
|
import WootSubmitButton from '../../components/buttons/FormSubmitButton';
|
||||||
|
import { DEFAULT_REDIRECT_URL } from '../../constants';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -81,7 +80,7 @@ export default {
|
|||||||
// If url opened without token
|
// If url opened without token
|
||||||
// redirect to login
|
// redirect to login
|
||||||
if (!this.resetPasswordToken) {
|
if (!this.resetPasswordToken) {
|
||||||
window.location = '/';
|
window.location = DEFAULT_REDIRECT_URL;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validations: {
|
validations: {
|
||||||
@@ -118,7 +117,7 @@ export default {
|
|||||||
Auth.setNewPassword(credentials)
|
Auth.setNewPassword(credentials)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
window.location = '/';
|
window.location = DEFAULT_REDIRECT_URL;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
import { required, minLength, email } from 'vuelidate/lib/validators';
|
||||||
import Auth from '../../api/auth';
|
import Auth from '../../api/auth';
|
||||||
import { frontendURL } from '../../helper/URLHelper';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -71,7 +70,6 @@ export default {
|
|||||||
successMessage = res.data.message;
|
successMessage = res.data.message;
|
||||||
}
|
}
|
||||||
this.showAlert(successMessage);
|
this.showAlert(successMessage);
|
||||||
window.location = frontendURL('login');
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
let errorMessage = this.$t('RESET_PASSWORD.API.ERROR_MESSAGE');
|
let errorMessage = this.$t('RESET_PASSWORD.API.ERROR_MESSAGE');
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ import Auth from '../../api/auth';
|
|||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
import { DEFAULT_REDIRECT_URL } from '../../constants';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [globalConfigMixin, alertMixin],
|
mixins: [globalConfigMixin, alertMixin],
|
||||||
@@ -132,7 +133,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const response = await Auth.register(this.credentials);
|
const response = await Auth.register(this.credentials);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
window.location = '/';
|
window.location = DEFAULT_REDIRECT_URL;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
let errorMessage = this.$t('REGISTER.API.ERROR_MESSAGE');
|
let errorMessage = this.$t('REGISTER.API.ERROR_MESSAGE');
|
||||||
|
|||||||
@@ -49,7 +49,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* global bus */
|
|
||||||
/* eslint no-console: 0 */
|
/* eslint no-console: 0 */
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from 'vuelidate/lib/validators';
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* global bus */
|
|
||||||
import { required, url, minLength } from 'vuelidate/lib/validators';
|
import { required, url, minLength } from 'vuelidate/lib/validators';
|
||||||
|
|
||||||
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton';
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint no-console: 0 */
|
|
||||||
import VueRouter from 'vue-router';
|
import VueRouter from 'vue-router';
|
||||||
|
|
||||||
import auth from '../api/auth';
|
import auth from '../api/auth';
|
||||||
@@ -7,14 +6,13 @@ import dashboard from './dashboard/dashboard.routes';
|
|||||||
import authRoute from './auth/auth.routes';
|
import authRoute from './auth/auth.routes';
|
||||||
import { frontendURL } from '../helper/URLHelper';
|
import { frontendURL } from '../helper/URLHelper';
|
||||||
|
|
||||||
const loggedInUser = auth.getCurrentUser() || {};
|
|
||||||
const routes = [
|
const routes = [
|
||||||
...login.routes,
|
...login.routes,
|
||||||
...dashboard.routes,
|
...dashboard.routes,
|
||||||
...authRoute.routes,
|
...authRoute.routes,
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: frontendURL(`accounts/${loggedInUser.account_id}/dashboard`),
|
redirect: '/app',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -41,10 +39,7 @@ const generateRoleWiseRoute = route => {
|
|||||||
// returns an object with roles as keys and routeArr as values
|
// returns an object with roles as keys and routeArr as values
|
||||||
generateRoleWiseRoute(routes);
|
generateRoleWiseRoute(routes);
|
||||||
|
|
||||||
export const router = new VueRouter({
|
export const router = new VueRouter({ mode: 'history', routes });
|
||||||
mode: 'history',
|
|
||||||
routes, // short for routes: routes
|
|
||||||
});
|
|
||||||
|
|
||||||
const unProtectedRoutes = ['login', 'auth_signup', 'auth_reset_password'];
|
const unProtectedRoutes = ['login', 'auth_signup', 'auth_reset_password'];
|
||||||
|
|
||||||
@@ -117,8 +112,11 @@ const validateRouteAccess = (to, from, next) => {
|
|||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
if (!to.name) {
|
if (!to.name) {
|
||||||
const user = auth.getCurrentUser();
|
const user = auth.getCurrentUser();
|
||||||
|
if (user) {
|
||||||
return next(frontendURL(`accounts/${user.account_id}/dashboard`));
|
return next(frontendURL(`accounts/${user.account_id}/dashboard`));
|
||||||
}
|
}
|
||||||
|
return next('/app/login');
|
||||||
|
}
|
||||||
|
|
||||||
return validateRouteAccess(to, from, next);
|
return validateRouteAccess(to, from, next);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,10 +13,6 @@ jest.mock('./login/login.routes', () => ({
|
|||||||
}));
|
}));
|
||||||
jest.mock('../constants', () => {
|
jest.mock('../constants', () => {
|
||||||
return {
|
return {
|
||||||
APP_BASE_URL: '/',
|
|
||||||
get apiUrl() {
|
|
||||||
return `${this.APP_BASE_URL}/`;
|
|
||||||
},
|
|
||||||
GRAVATAR_URL: 'https://www.gravatar.com/avatar',
|
GRAVATAR_URL: 'https://www.gravatar.com/avatar',
|
||||||
CHANNELS: {
|
CHANNELS: {
|
||||||
FACEBOOK: 'facebook',
|
FACEBOOK: 'facebook',
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import authAPI from '../../api/auth';
|
|||||||
import createAxios from '../../helper/APIHelper';
|
import createAxios from '../../helper/APIHelper';
|
||||||
import actionCable from '../../helper/actionCable';
|
import actionCable from '../../helper/actionCable';
|
||||||
import { setUser, getHeaderExpiry, clearCookiesOnLogout } from '../utils/api';
|
import { setUser, getHeaderExpiry, clearCookiesOnLogout } from '../utils/api';
|
||||||
|
import { DEFAULT_REDIRECT_URL } from '../../constants';
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
currentUser: {
|
currentUser: {
|
||||||
@@ -69,7 +70,7 @@ export const actions = {
|
|||||||
commit(types.default.SET_CURRENT_USER);
|
commit(types.default.SET_CURRENT_USER);
|
||||||
window.axios = createAxios(axios);
|
window.axios = createAxios(axios);
|
||||||
actionCable.init(Vue);
|
actionCable.init(Vue);
|
||||||
window.location = '/';
|
window.location = DEFAULT_REDIRECT_URL;
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ import { createConsumer } from '@rails/actioncable';
|
|||||||
const PRESENCE_INTERVAL = 60000;
|
const PRESENCE_INTERVAL = 60000;
|
||||||
|
|
||||||
class BaseActionCableConnector {
|
class BaseActionCableConnector {
|
||||||
constructor(app, pubsubToken) {
|
constructor(app, pubsubToken, websocketHost = '') {
|
||||||
this.consumer = createConsumer();
|
const websocketURL = websocketHost ? `${websocketHost}/cable` : undefined;
|
||||||
|
this.consumer = createConsumer(websocketURL);
|
||||||
this.subscription = this.consumer.subscriptions.create(
|
this.subscription = this.consumer.subscriptions.create(
|
||||||
{
|
{
|
||||||
channel: 'RoomChannel',
|
channel: 'RoomChannel',
|
||||||
|
|||||||
Reference in New Issue
Block a user