first commit

This commit is contained in:
Noor E Ilahi
2026-01-09 12:54:53 +05:30
commit 7ccf44f7da
1070 changed files with 113036 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
export function getParentElement(child, search) {
if (child.parentElement.classList.contains(search)) {
return child.parentElement;
}
return getParentElement(child.parentElement, search);
}
export function loadSections(context, router, requireSection) {
const sections = requireSection
.keys()
.map(fn => requireSection(fn).default)
.map(section => {
if (typeof section === 'function') {
return section(context, router);
}
return section;
});
sections.forEach(section => {
if (Object.prototype.hasOwnProperty.call(section, 'scope') && section.scope === 'company') {
context.addCompanySection(section);
} else {
context.addSettingsSection(section);
}
});
}

View File

@@ -0,0 +1,117 @@
import Vue from 'vue';
import axios from 'axios';
import { store } from '@/store';
import has from 'lodash/has';
import isObject from 'lodash/isObject';
// Queue for pending queries
let pendingRequests = 0;
// Changes loader bar state
const setLoading = value => {
if (value) {
if (pendingRequests === 0) Vue.prototype.$Loading.start();
pendingRequests++;
} else {
setTimeout(() => {
if (pendingRequests > 0) pendingRequests--;
if (pendingRequests < 1) Vue.prototype.$Loading.finish();
}, 300);
}
};
// Returns access token
const getAuthToken = () => localStorage.getItem('access_token');
// Adds response interceptor
const responseInterceptor = response => {
setLoading(false);
return response;
};
// Adds error response interceptor
const responseErrorInterceptor = async error => {
setLoading(false);
if (!has(error, 'response.status') || (error.request.responseType === 'blob' && error.request.status === 404)) {
return Promise.reject(error);
}
switch (error.response.status) {
case 401:
store.getters['user/loggedIn'] && store.dispatch('user/forceUserExit', error.response.data.message);
break;
case 503:
store.getters['user/loggedIn'] && store.dispatch('user/forceUserExit', 'Data reset');
break;
default:
Vue.prototype.$Notify.error({
title: 'Error',
message: has(error, 'response.data.error.message')
? error.response.data.error.message
: 'Internal server error',
duration: 5000,
});
if (isObject(error.response.data.error.fields)) {
for (const [fieldName, msgArr] of Object.entries(error.response.data.error.fields)) {
for (const msg of msgArr) {
await Vue.prototype.$nextTick();
Vue.prototype.$Notify.warning({
title: 'Warning',
message: msg,
duration: 5000,
});
}
}
}
}
return Promise.reject(error);
};
// Adds request interceptor
const requestInterceptor = config => {
setLoading(true);
return config;
};
// Adds request error interceptor
const requestErrorInterceptor = error => {
axios.isCancel(error) ? setLoading(false) : Vue.prototype.$Loading.error();
return Promise.reject(error);
};
// Sets the access token on the request
const authInterceptor = config => {
config.headers['Authorization'] = `Bearer ${getAuthToken()}`;
return config;
};
// Save pending request cancel tokens to the store
const pendingRequestsInterceptor = config => {
if (config.ignoreCancel) {
return config;
}
// Generate cancel token source
let source = axios.CancelToken.source();
// Set cancel token on this request
config.cancelToken = source.token;
store.commit('httpRequest/addCancelToken', source);
return config;
};
export default {
setup() {
axios.interceptors.response.use(responseInterceptor, responseErrorInterceptor);
axios.interceptors.request.use(requestInterceptor, requestErrorInterceptor);
axios.interceptors.request.use(pendingRequestsInterceptor);
axios.interceptors.request.use(authInterceptor);
},
};

View File

@@ -0,0 +1,9 @@
const slogans = ['Cattr - a free open source time tracker', 'Manage your time with ease'];
const getRandomInt = max => {
return Math.floor(Math.random() * Math.floor(max));
};
export default () => {
return slogans[getRandomInt(slogans.length)];
};