Skip to content

Commit

Permalink
Refactor global instances of $api and $utils to be mixins.
Browse files Browse the repository at this point in the history
... instead of Vue.prototype variables which is the idiomatic
approach. Also, the refactor enables utils to be instantiated
as a class that takes the i18n object for util functions to have
accesss to i18n translation.
  • Loading branch information
knadh committed Jan 26, 2021
1 parent afef994 commit dc0465b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 40 deletions.
50 changes: 28 additions & 22 deletions frontend/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,43 @@ import App from './App.vue';
import router from './router';
import store from './store';
import * as api from './api';
import utils from './utils';
import { models } from './constants';
import Utils from './utils';

// Internationalisation.
Vue.use(VueI18n);

// Create VueI18n instance with options
const i18n = new VueI18n();

Vue.use(Buefy, {});
Vue.config.productionTip = false;

// Custom global elements.
Vue.prototype.$api = api;
Vue.prototype.$utils = utils;

Vue.prototype.$reloadServerConfig = () => {
// Get the config.js <script> tag, remove it, and re-add it.
let s = document.querySelector('#server-config');
const url = s.getAttribute('src');
s.remove();

s = document.createElement('script');
s.setAttribute('src', url);
s.setAttribute('id', 'server-config');
s.onload = () => {
store.commit('setModelResponse',
{ model: models.serverConfig, data: humps.camelizeKeys(window.CONFIG) });
};
document.body.appendChild(s);
};
// Globals.
const ut = new Utils(i18n);
Vue.mixin({
computed: {
$utils: () => ut,
$api: () => api,
},

methods: {
$reloadServerConfig: () => {
// Get the config.js <script> tag, remove it, and re-add it.
let s = document.querySelector('#server-config');
const url = s.getAttribute('src');
s.remove();

s = document.createElement('script');
s.setAttribute('src', url);
s.setAttribute('id', 'server-config');
s.onload = () => {
store.commit('setModelResponse',
{ model: models.serverConfig, data: humps.camelizeKeys(window.CONFIG) });
};
document.body.appendChild(s);
},
},
});


// window.CONFIG is loaded from /api/config.js directly in a <script> tag.
if (window.CONFIG) {
Expand Down
38 changes: 20 additions & 18 deletions frontend/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,35 @@ dayjs.extend(relativeTime);

const reEmail = /(.+?)@(.+?)/ig;

export default class utils {
static months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
'Sep', 'Oct', 'Nov', 'Dec'];

static days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
export default class Utils {
constructor(i18n) {
this.i18n = i18n;
}

// Parses an ISO timestamp to a simpler form.
static niceDate = (stamp, showTime) => {
niceDate = (stamp, showTime) => {
if (!stamp) {
return '';
}

const d = new Date(stamp);
let out = `${utils.days[d.getDay()]}, ${d.getDate()}`;
out += ` ${utils.months[d.getMonth()]} ${d.getFullYear()}`;
const day = this.i18n.t(`globals.days.${(d.getDay() + 1)}`);
const month = this.i18n.t(`globals.months.${(d.getMonth() + 1)}`);
let out = `${day}, ${d.getDate()}`;
out += ` ${month} ${d.getFullYear()}`;
if (showTime) {
out += ` ${d.getHours()}:${d.getMinutes()}`;
}

return out;
};

static duration(start, end) {
return dayjs(end).from(dayjs(start), true);
}
duration = (start, end) => dayjs(end).from(dayjs(start), true);

// Simple, naive, e-mail address check.
static validateEmail = (e) => e.match(reEmail);
validateEmail = (e) => e.match(reEmail);

static niceNumber = (n) => {
niceNumber = (n) => {
if (n === null || n === undefined) {
return 0;
}
Expand Down Expand Up @@ -69,20 +68,23 @@ export default class utils {
}

// UI shortcuts.
static confirm = (msg, onConfirm, onCancel) => {
confirm = (msg, onConfirm, onCancel) => {
Dialog.confirm({
scroll: 'clip',
message: !msg ? 'Are you sure?' : msg,
message: !msg ? this.i18n.t('globals.messages.confirm') : msg,
confirmText: this.i18n.t('globals.buttons.ok'),
cancelText: this.i18n.t('globals.buttons.cancel'),
onConfirm,
onCancel,
});
};

static prompt = (msg, inputAttrs, onConfirm, onCancel) => {
prompt = (msg, inputAttrs, onConfirm, onCancel) => {
Dialog.prompt({
scroll: 'clip',
message: msg,
confirmText: 'OK',
confirmText: this.i18n.t('globals.buttons.ok'),
cancelText: this.i18n.t('globals.buttons.cancel'),
inputAttrs: {
type: 'string',
maxlength: 200,
Expand All @@ -94,7 +96,7 @@ export default class utils {
});
};

static toast = (msg, typ, duration) => {
toast = (msg, typ, duration) => {
Toast.open({
message: msg,
type: !typ ? 'is-success' : typ,
Expand Down

0 comments on commit dc0465b

Please sign in to comment.