chore: Adjust Chatwoot Config to deploy frontend as a separate app (#2347)

This commit is contained in:
Pranav Raj S
2021-05-28 19:21:16 +05:30
committed by GitHub
parent 3b39eb3e33
commit 25ba852b68
16 changed files with 53 additions and 60 deletions

View File

@@ -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';

View File

@@ -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>

View File

@@ -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({

View File

@@ -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/';

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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>

View File

@@ -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(() => {

View File

@@ -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');

View File

@@ -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');

View File

@@ -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';

View File

@@ -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';

View File

@@ -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);
}); });

View File

@@ -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',

View File

@@ -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 => {

View File

@@ -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',