diff options
Diffstat (limited to 'app/assets/javascripts/packages/list/stores')
6 files changed, 208 insertions, 0 deletions
diff --git a/app/assets/javascripts/packages/list/stores/actions.js b/app/assets/javascripts/packages/list/stores/actions.js new file mode 100644 index 00000000000..0ed24aee2c5 --- /dev/null +++ b/app/assets/javascripts/packages/list/stores/actions.js @@ -0,0 +1,73 @@ +import Api from '~/api'; +import axios from '~/lib/utils/axios_utils'; +import { deprecatedCreateFlash as createFlash } from '~/flash'; +import * as types from './mutation_types'; +import { + FETCH_PACKAGES_LIST_ERROR_MESSAGE, + DELETE_PACKAGE_ERROR_MESSAGE, + DELETE_PACKAGE_SUCCESS_MESSAGE, + DEFAULT_PAGE, + DEFAULT_PAGE_SIZE, + MISSING_DELETE_PATH_ERROR, +} from '../constants'; +import { getNewPaginationPage } from '../utils'; + +export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data); +export const setLoading = ({ commit }, data) => commit(types.SET_MAIN_LOADING, data); +export const setSorting = ({ commit }, data) => commit(types.SET_SORTING, data); +export const setSelectedType = ({ commit }, data) => commit(types.SET_SELECTED_TYPE, data); +export const setFilter = ({ commit }, data) => commit(types.SET_FILTER, data); + +export const receivePackagesListSuccess = ({ commit }, { data, headers }) => { + commit(types.SET_PACKAGE_LIST_SUCCESS, data); + commit(types.SET_PAGINATION, headers); +}; + +export const requestPackagesList = ({ dispatch, state }, params = {}) => { + dispatch('setLoading', true); + + const { page = DEFAULT_PAGE, per_page = DEFAULT_PAGE_SIZE } = params; + const { sort, orderBy } = state.sorting; + + const type = state.selectedType?.type?.toLowerCase(); + const nameFilter = state.filterQuery?.toLowerCase(); + const packageFilters = { package_type: type, package_name: nameFilter }; + + const apiMethod = state.config.isGroupPage ? 'groupPackages' : 'projectPackages'; + + return Api[apiMethod](state.config.resourceId, { + params: { page, per_page, sort, order_by: orderBy, ...packageFilters }, + }) + .then(({ data, headers }) => { + dispatch('receivePackagesListSuccess', { data, headers }); + }) + .catch(() => { + createFlash(FETCH_PACKAGES_LIST_ERROR_MESSAGE); + }) + .finally(() => { + dispatch('setLoading', false); + }); +}; + +export const requestDeletePackage = ({ dispatch, state }, { _links }) => { + if (!_links || !_links.delete_api_path) { + createFlash(DELETE_PACKAGE_ERROR_MESSAGE); + const error = new Error(MISSING_DELETE_PATH_ERROR); + return Promise.reject(error); + } + + dispatch('setLoading', true); + return axios + .delete(_links.delete_api_path) + .then(() => { + const { page: currentPage, perPage, total } = state.pagination; + const page = getNewPaginationPage(currentPage, perPage, total - 1); + + dispatch('requestPackagesList', { page }); + createFlash(DELETE_PACKAGE_SUCCESS_MESSAGE, 'success'); + }) + .catch(() => { + dispatch('setLoading', false); + createFlash(DELETE_PACKAGE_ERROR_MESSAGE); + }); +}; diff --git a/app/assets/javascripts/packages/list/stores/getters.js b/app/assets/javascripts/packages/list/stores/getters.js new file mode 100644 index 00000000000..0af7e453f19 --- /dev/null +++ b/app/assets/javascripts/packages/list/stores/getters.js @@ -0,0 +1,5 @@ +import { LIST_KEY_PROJECT } from '../constants'; +import { beautifyPath } from '../../shared/utils'; + +export default state => + state.packages.map(p => ({ ...p, projectPathName: beautifyPath(p[LIST_KEY_PROJECT]) })); diff --git a/app/assets/javascripts/packages/list/stores/index.js b/app/assets/javascripts/packages/list/stores/index.js new file mode 100644 index 00000000000..1d6a4bf831d --- /dev/null +++ b/app/assets/javascripts/packages/list/stores/index.js @@ -0,0 +1,20 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import * as actions from './actions'; +import getList from './getters'; +import mutations from './mutations'; +import state from './state'; + +Vue.use(Vuex); + +export const createStore = () => + new Vuex.Store({ + state, + getters: { + getList, + }, + actions, + mutations, + }); + +export default createStore(); diff --git a/app/assets/javascripts/packages/list/stores/mutation_types.js b/app/assets/javascripts/packages/list/stores/mutation_types.js new file mode 100644 index 00000000000..a5a584ccf1f --- /dev/null +++ b/app/assets/javascripts/packages/list/stores/mutation_types.js @@ -0,0 +1,8 @@ +export const SET_INITIAL_STATE = 'SET_INITIAL_STATE'; + +export const SET_PACKAGE_LIST_SUCCESS = 'SET_PACKAGE_LIST_SUCCESS'; +export const SET_PAGINATION = 'SET_PAGINATION'; +export const SET_MAIN_LOADING = 'SET_MAIN_LOADING'; +export const SET_SORTING = 'SET_SORTING'; +export const SET_SELECTED_TYPE = 'SET_SELECTED_TYPE'; +export const SET_FILTER = 'SET_FILTER'; diff --git a/app/assets/javascripts/packages/list/stores/mutations.js b/app/assets/javascripts/packages/list/stores/mutations.js new file mode 100644 index 00000000000..a47ba356c0a --- /dev/null +++ b/app/assets/javascripts/packages/list/stores/mutations.js @@ -0,0 +1,45 @@ +import * as types from './mutation_types'; +import { + parseIntPagination, + normalizeHeaders, + convertObjectPropsToCamelCase, +} from '~/lib/utils/common_utils'; +import { GROUP_PAGE_TYPE } from '../constants'; + +export default { + [types.SET_INITIAL_STATE](state, config) { + const { comingSoonJson, ...rest } = config; + const comingSoonObj = JSON.parse(comingSoonJson); + + state.config = { + ...rest, + comingSoon: comingSoonObj && convertObjectPropsToCamelCase(comingSoonObj), + isGroupPage: config.pageType === GROUP_PAGE_TYPE, + }; + }, + + [types.SET_PACKAGE_LIST_SUCCESS](state, packages) { + state.packages = packages; + }, + + [types.SET_MAIN_LOADING](state, isLoading) { + state.isLoading = isLoading; + }, + + [types.SET_PAGINATION](state, headers) { + const normalizedHeaders = normalizeHeaders(headers); + state.pagination = parseIntPagination(normalizedHeaders); + }, + + [types.SET_SORTING](state, sorting) { + state.sorting = { ...state.sorting, ...sorting }; + }, + + [types.SET_SELECTED_TYPE](state, type) { + state.selectedType = type; + }, + + [types.SET_FILTER](state, query) { + state.filterQuery = query; + }, +}; diff --git a/app/assets/javascripts/packages/list/stores/state.js b/app/assets/javascripts/packages/list/stores/state.js new file mode 100644 index 00000000000..18ab2390b87 --- /dev/null +++ b/app/assets/javascripts/packages/list/stores/state.js @@ -0,0 +1,57 @@ +import { PACKAGE_REGISTRY_TABS } from '../constants'; + +export default () => ({ + /** + * Determine if the component is loading data from the API + */ + isLoading: false, + /** + * configuration object, set once at store creation with the following structure + * { + * resourceId: String, + * pageType: String, + * emptyListIllustration: String, + * emptyListHelpUrl: String, + * comingSoon: { projectPath: String, suggestedContributions : String } | null; + * } + */ + config: {}, + /** + * Each object in `packages` has the following structure: + * { + * id: String + * name: String, + * version: String, + * package_type: String // endpoint to request the list + * } + */ + packages: [], + /** + * Pagination object has the following structure: + * { + * perPage: Number, + * page: Number + * total: Number + * } + */ + pagination: {}, + /** + * Sorting object has the following structure: + * { + * sort: String, + * orderBy: String + * } + */ + sorting: { + sort: 'desc', + orderBy: 'created_at', + }, + /** + * The search query that is used to filter packages by name + */ + filterQuery: '', + /** + * The selected TAB of the package types tabs + */ + selectedType: PACKAGE_REGISTRY_TABS[0], +}); |