Skip to content

Instantly share code, notes, and snippets.

@zachcb
Last active February 28, 2019 19:48
Show Gist options
  • Save zachcb/64cfdf9e50fa88cd7292ac340b84940d to your computer and use it in GitHub Desktop.
Save zachcb/64cfdf9e50fa88cd7292ac340b84940d to your computer and use it in GitHub Desktop.
Vuex Loading Setup
import EventBus from "@/events";
const setLoading = ({ commit }, options) => {
commit("SET_LOADING", options);
};
function statusFactory(status) {
return ({ commit }, name) => {
commit("SET_LOADING", { name, status });
EventBus.$emit(`loading/${name}`, status);
};
}
export default {
setLoading,
stop: statusFactory("stop"),
load: statusFactory("load"),
error: statusFactory("error"),
success: statusFactory("success"),
ready: statusFactory("ready")
};
/**
* Get reservation.
* @param {Object} params - The options for creating a request.
* @param {string} params.reservationId - Reservation id.
* @param {string} params.formData.reservationNumber - Reservation id.
* @param {string} params.formData.email - Reservation email.
* @return {function} getRoomsRequest
*/
async function getReservation({ reservationId, formData = {} }) {
const endpoint = isAuthenticated
? `/${endpointBase}/meetings/reservations/${reservationId}`
: `/${endpointBase}/meetings/reservations`;
return await request({
endpoint,
method: "get",
eventName: "GET_RESERVATION",
formData
})();
}
<template></template>
<script>
import { mapActions, mapGetters, mapState } from "vuex";
import formMixin from "@/mixins/form";
import { ifErrorGetMessage } from "@/forms/utils";
import { defaults, messages, validations } from "@/forms/login";
import TemplateCard from "./TemplateCard";
const formName = "login";
export default {
name: "LoginCard",
components: { TemplateCard },
mixins: [formMixin],
data: () => ({
formName,
defaults,
messages
}),
validations: validations,
computed: {
loginLoadingState() {
return this.loadingState("POST_LOGIN");
},
loginAlertState() {
return this.alertState("POST_LOGIN");
},
registerAlertState() {
return this.alertState("POST_REGISTER");
},
...mapState("forms", {
email: state => state[formName].email,
password: state => state[formName].password
}),
...mapGetters("forms", ["formByName"]),
...mapGetters("loading", ["loadingState"]),
...mapGetters("alerts", ["alertState"])
},
methods: {
submit() {
const isValid = this.validate();
isValid &&
this.postLogin().then(() => {
if (this.loginLoadingState.isSuccess) {
this.$router.push({ path: "/accounts" });
}
});
},
ifErrorGetMessage,
...mapActions("auth", ["postLogin"])
}
};
</script>
import _ from "lodash";
const getPropertyByStatus = status => ({
isReady: status === "ready",
isSuccess: status === "success",
isLoading: status === "load",
isError: status === "error",
isStopped: status === "stop"
});
const loadingState = state => name => {
const activeLoading = _.filter(
state.loading,
activeLoaders => activeLoaders.name === name
);
let matchedLoading = {};
if (_.isArray(activeLoading) && activeLoading.length === 1) {
matchedLoading = activeLoading[0];
}
if (
!_.isNil(matchedLoading) &&
!_.isEmpty(matchedLoading) &&
_.has(matchedLoading, "status")
) {
const status = matchedLoading.status;
const statusProperties = getPropertyByStatus(status);
return _.assign({}, matchedLoading, statusProperties);
}
const statusProperties = getPropertyByStatus("ready");
return _.assign({}, ...activeLoading, statusProperties);
};
const anyLoading = state =>
state.activeLoaders && state.activeLoaders.length > 0;
export default {
loading,
isLoading,
loadingState,
loadingStatus,
anyLoading
};
import actions from "./actions";
import getters from "./getters";
import mutations from "./mutations";
// Available statuses: 'stop', 'load', 'error', 'success', 'ready'
const state = {
loading: []
};
export default {
namespaced: true,
state,
actions,
getters,
mutations
};
import _ from "lodash";
const SET_LOADING = (state, options) => {
const index = _.findIndex(state.loading, activeLoaders => {
return activeLoaders.name === options.name;
});
if (index === -1) {
state.loading.push(options);
} else {
state.loading.splice(index, 1, options);
}
};
const ADD_LOADING = (state, name) => {
state.loading.push({ name: name, status: "loading" });
};
const REMOVE_LOADING = (state, name) => {
state.loading.filter(activeLoaders => activeLoaders.name === name);
};
export default {
SET_LOADING,
ADD_LOADING,
REMOVE_LOADING
};
import _ from "lodash/fp";
import store from "@/store";
import api from "@/api/dataAccessService";
function request(
{ endpoint, method, formName, formData = {}, eventName, vuex = true },
callback = false
) {
async function vuexRequest() {
const { getters, dispatch } = store;
const hasFormName = !_.isNil(formName);
const isEventNameNil = _.isNil(eventName);
const willSendForm = hasFormName;
const willDefaultEventName = _.isNil(eventName) && willSendForm;
const willFetchFormFromState =
(_.isNil(formData) || _.isEmpty(formData)) && hasFormName;
if (willSendForm) {
formName = _.camelCase(formName);
}
if (willFetchFormFromState) {
formData = getters[`forms/${formName}Form`];
}
if (willDefaultEventName) {
const toUpperSnake = _.curry(_.snakeCase, _.upperCase);
eventName = toUpperSnake(formName);
} else if (isEventNameNil) {
eventName = "UNKNOWN_EVENT";
}
dispatch("loading/load", eventName, { root: true });
try {
const response = await api[method](endpoint, formData);
await dispatch("loading/success", eventName, { root: true });
callback && (await callback());
return response;
} catch (error) {
dispatch("loading/error", eventName, { root: true });
console.log(error);
}
}
async function statelessRequest() {
try {
const response = await api[method](endpoint, formData);
callback && (await callback());
return response;
} catch (error) {
console.log(error);
}
}
return vuex ? vuexRequest : statelessRequest;
}
export default request;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment