diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-10 15:08:54 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-10 15:08:54 +0000 |
commit | 11e5d1b9ca3efa7be34ddebb708a6aedb4e91639 (patch) | |
tree | 999fdffb9d3db2e5200994e289e50fa3a3a1684a /app/assets/javascripts/registry/explorer | |
parent | 7351a484d79236b7e9d47c86f2fcc970b7ae10b0 (diff) | |
download | gitlab-ce-11e5d1b9ca3efa7be34ddebb708a6aedb4e91639.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/registry/explorer')
11 files changed, 310 insertions, 0 deletions
diff --git a/app/assets/javascripts/registry/explorer/constants.js b/app/assets/javascripts/registry/explorer/constants.js new file mode 100644 index 00000000000..bb311157627 --- /dev/null +++ b/app/assets/javascripts/registry/explorer/constants.js @@ -0,0 +1,32 @@ +import { __ } from '~/locale'; + +export const FETCH_IMAGES_LIST_ERROR_MESSAGE = __( + 'Something went wrong while fetching the packages list.', +); +export const FETCH_TAGS_LIST_ERROR_MESSAGE = __( + 'Something went wrong while fetching the tags list.', +); + +export const DELETE_IMAGE_ERROR_MESSAGE = __('Something went wrong while deleting the image.'); +export const DELETE_IMAGE_SUCCESS_MESSAGE = __('Image deleted successfully'); +export const DELETE_TAG_ERROR_MESSAGE = __('Something went wrong while deleting the tag.'); +export const DELETE_TAG_SUCCESS_MESSAGE = __('Tag deleted successfully'); +export const DELETE_TAGS_ERROR_MESSAGE = __('Something went wrong while deleting the tags.'); +export const DELETE_TAGS_SUCCESS_MESSAGE = __('Tags deleted successfully'); + +export const DEFAULT_PAGE = 1; +export const DEFAULT_PAGE_SIZE = 10; + +export const GROUP_PAGE_TYPE = 'groups'; + +export const LIST_KEY_TAG = 'name'; +export const LIST_KEY_IMAGE_ID = 'short_revision'; +export const LIST_KEY_SIZE = 'total_size'; +export const LIST_KEY_LAST_UPDATED = 'created_at'; +export const LIST_KEY_ACTIONS = 'actions'; +export const LIST_KEY_CHECKBOX = 'checkbox'; + +export const LIST_LABEL_TAG = __('Tag'); +export const LIST_LABEL_IMAGE_ID = __('Image ID'); +export const LIST_LABEL_SIZE = __('Size'); +export const LIST_LABEL_LAST_UPDATED = __('Last Updated'); diff --git a/app/assets/javascripts/registry/explorer/index.js b/app/assets/javascripts/registry/explorer/index.js new file mode 100644 index 00000000000..daa2e4fb109 --- /dev/null +++ b/app/assets/javascripts/registry/explorer/index.js @@ -0,0 +1,33 @@ +import Vue from 'vue'; +import Translate from '~/vue_shared/translate'; +import RegistryExplorer from './pages/index.vue'; +import { createStore } from './stores'; +import createRouter from './router'; + +Vue.use(Translate); + +export default () => { + const el = document.getElementById('js-container-registry'); + + if (!el) { + return null; + } + + const { endpoint } = el.dataset; + + const store = createStore(); + const router = createRouter(endpoint, store); + store.dispatch('setInitialState', el.dataset); + + return new Vue({ + el, + store, + router, + components: { + RegistryExplorer, + }, + render(createElement) { + return createElement('registry-explorer'); + }, + }); +}; diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/registry/explorer/pages/details.vue new file mode 100644 index 00000000000..6d32ba41eae --- /dev/null +++ b/app/assets/javascripts/registry/explorer/pages/details.vue @@ -0,0 +1,7 @@ +<script> +export default {}; +</script> + +<template> + <div></div> +</template> diff --git a/app/assets/javascripts/registry/explorer/pages/index.vue b/app/assets/javascripts/registry/explorer/pages/index.vue new file mode 100644 index 00000000000..deefbfc40e0 --- /dev/null +++ b/app/assets/javascripts/registry/explorer/pages/index.vue @@ -0,0 +1,11 @@ +<script> +export default {}; +</script> + +<template> + <div class="position-relative"> + <transition name="slide"> + <router-view /> + </transition> + </div> +</template> diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue new file mode 100644 index 00000000000..6d32ba41eae --- /dev/null +++ b/app/assets/javascripts/registry/explorer/pages/list.vue @@ -0,0 +1,7 @@ +<script> +export default {}; +</script> + +<template> + <div></div> +</template> diff --git a/app/assets/javascripts/registry/explorer/router.js b/app/assets/javascripts/registry/explorer/router.js new file mode 100644 index 00000000000..8cf35b8f245 --- /dev/null +++ b/app/assets/javascripts/registry/explorer/router.js @@ -0,0 +1,42 @@ +import Vue from 'vue'; +import VueRouter from 'vue-router'; +import { __ } from '~/locale'; +import List from './pages/list.vue'; +import Details from './pages/details.vue'; + +Vue.use(VueRouter); + +export default function createRouter(base, store) { + const router = new VueRouter({ + base, + mode: 'history', + routes: [ + { + name: 'list', + path: '/', + component: List, + meta: { + name: __('Container Registry'), + }, + beforeEnter: (to, from, next) => { + store.dispatch('requestImagesList'); + next(); + }, + }, + { + name: 'details', + path: '/:id', + component: Details, + meta: { + name: __('Tags'), + }, + beforeEnter: (to, from, next) => { + store.dispatch('requestTagsList', { id: to.params.id }); + next(); + }, + }, + ], + }); + + return router; +} diff --git a/app/assets/javascripts/registry/explorer/stores/actions.js b/app/assets/javascripts/registry/explorer/stores/actions.js new file mode 100644 index 00000000000..7c06a12a5fc --- /dev/null +++ b/app/assets/javascripts/registry/explorer/stores/actions.js @@ -0,0 +1,115 @@ +import axios from '~/lib/utils/axios_utils'; +import createFlash from '~/flash'; +import * as types from './mutation_types'; +import { + FETCH_IMAGES_LIST_ERROR_MESSAGE, + DEFAULT_PAGE, + DEFAULT_PAGE_SIZE, + FETCH_TAGS_LIST_ERROR_MESSAGE, + DELETE_TAG_SUCCESS_MESSAGE, + DELETE_TAG_ERROR_MESSAGE, + DELETE_TAGS_SUCCESS_MESSAGE, + DELETE_TAGS_ERROR_MESSAGE, + DELETE_IMAGE_ERROR_MESSAGE, + DELETE_IMAGE_SUCCESS_MESSAGE, +} from '../constants'; + +export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data); + +export const receiveImagesListSuccess = ({ commit }, { data, headers }) => { + commit(types.SET_IMAGES_LIST_SUCCESS, data); + commit(types.SET_PAGINATION, headers); +}; + +export const receiveTagsListSuccess = ({ commit }, { data, headers }) => { + commit(types.SET_TAGS_LIST_SUCCESS, data); + commit(types.SET_TAGS_PAGINATION, headers); +}; + +export const requestImagesList = ({ commit, dispatch, state }, pagination = {}) => { + commit(types.SET_MAIN_LOADING, true); + const { page = DEFAULT_PAGE, perPage = DEFAULT_PAGE_SIZE } = pagination; + + return axios + .get(state.config.endpoint, { params: { page, per_page: perPage } }) + .then(({ data, headers }) => { + dispatch('receiveImagesListSuccess', { data, headers }); + }) + .catch(() => { + createFlash(FETCH_IMAGES_LIST_ERROR_MESSAGE); + }) + .finally(() => { + commit(types.SET_MAIN_LOADING, false); + }); +}; + +export const requestTagsList = ({ commit, dispatch }, { pagination = {}, id }) => { + commit(types.SET_MAIN_LOADING, true); + const url = window.atob(id); + + const { page = DEFAULT_PAGE, perPage = DEFAULT_PAGE_SIZE } = pagination; + return axios + .get(url, { params: { page, per_page: perPage } }) + .then(({ data, headers }) => { + dispatch('receiveTagsListSuccess', { data, headers }); + }) + .catch(() => { + createFlash(FETCH_TAGS_LIST_ERROR_MESSAGE); + }) + .finally(() => { + commit(types.SET_MAIN_LOADING, false); + }); +}; + +export const requestDeleteTag = ({ commit, dispatch, state }, { tag, imageId }) => { + commit(types.SET_MAIN_LOADING, true); + return axios + .delete(tag.destroy_path) + .then(() => { + createFlash(DELETE_TAG_SUCCESS_MESSAGE, 'success'); + dispatch('requestTagsList', { pagination: state.tagsPagination, id: imageId }); + }) + .catch(() => { + createFlash(DELETE_TAG_ERROR_MESSAGE); + }) + .finally(() => { + commit(types.SET_MAIN_LOADING, false); + }); +}; + +export const requestDeleteTags = ({ commit, dispatch, state }, { ids, imageId }) => { + commit(types.SET_MAIN_LOADING, true); + const url = `/${state.config.projectPath}/registry/repository/${imageId}/tags/bulk_destroy`; + + return axios + .delete(url, { params: { ids } }) + .then(() => { + createFlash(DELETE_TAGS_SUCCESS_MESSAGE, 'success'); + dispatch('requestTagsList', { pagination: state.tagsPagination, id: imageId }); + }) + .catch(() => { + createFlash(DELETE_TAGS_ERROR_MESSAGE); + }) + .finally(() => { + commit(types.SET_MAIN_LOADING, false); + }); +}; + +export const requestDeleteImage = ({ commit, dispatch, state }, destroyPath) => { + commit(types.SET_MAIN_LOADING, true); + + return axios + .delete(destroyPath) + .then(() => { + dispatch('requestImagesList', { pagination: state.pagination }); + createFlash(DELETE_IMAGE_SUCCESS_MESSAGE, 'success'); + }) + .catch(() => { + createFlash(DELETE_IMAGE_ERROR_MESSAGE); + }) + .finally(() => { + commit(types.SET_MAIN_LOADING, false); + }); +}; + +export default () => {}; diff --git a/app/assets/javascripts/registry/explorer/stores/index.js b/app/assets/javascripts/registry/explorer/stores/index.js new file mode 100644 index 00000000000..91a35aac149 --- /dev/null +++ b/app/assets/javascripts/registry/explorer/stores/index.js @@ -0,0 +1,16 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import * as actions from './actions'; +import mutations from './mutations'; +import state from './state'; + +Vue.use(Vuex); + +export const createStore = () => + new Vuex.Store({ + state, + actions, + mutations, + }); + +export default createStore(); diff --git a/app/assets/javascripts/registry/explorer/stores/mutation_types.js b/app/assets/javascripts/registry/explorer/stores/mutation_types.js new file mode 100644 index 00000000000..92b747dffc5 --- /dev/null +++ b/app/assets/javascripts/registry/explorer/stores/mutation_types.js @@ -0,0 +1,7 @@ +export const SET_INITIAL_STATE = 'SET_INITIAL_STATE'; + +export const SET_IMAGES_LIST_SUCCESS = 'SET_PACKAGE_LIST_SUCCESS'; +export const SET_PAGINATION = 'SET_PAGINATION'; +export const SET_MAIN_LOADING = 'SET_MAIN_LOADING'; +export const SET_TAGS_PAGINATION = 'SET_TAGS_PAGINATION'; +export const SET_TAGS_LIST_SUCCESS = 'SET_TAGS_LIST_SUCCESS'; diff --git a/app/assets/javascripts/registry/explorer/stores/mutations.js b/app/assets/javascripts/registry/explorer/stores/mutations.js new file mode 100644 index 00000000000..186f36a759a --- /dev/null +++ b/app/assets/javascripts/registry/explorer/stores/mutations.js @@ -0,0 +1,32 @@ +import * as types from './mutation_types'; +import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils'; + +export default { + [types.SET_INITIAL_STATE](state, config) { + state.config = { + ...config, + }; + }, + + [types.SET_IMAGES_LIST_SUCCESS](state, images) { + state.images = images; + }, + + [types.SET_TAGS_LIST_SUCCESS](state, tags) { + state.tags = tags; + }, + + [types.SET_MAIN_LOADING](state, isLoading) { + state.isLoading = isLoading; + }, + + [types.SET_PAGINATION](state, headers) { + const normalizedHeaders = normalizeHeaders(headers); + state.pagination = parseIntPagination(normalizedHeaders); + }, + + [types.SET_TAGS_PAGINATION](state, headers) { + const normalizedHeaders = normalizeHeaders(headers); + state.tagsPagination = parseIntPagination(normalizedHeaders); + }, +}; diff --git a/app/assets/javascripts/registry/explorer/stores/state.js b/app/assets/javascripts/registry/explorer/stores/state.js new file mode 100644 index 00000000000..91a378f139b --- /dev/null +++ b/app/assets/javascripts/registry/explorer/stores/state.js @@ -0,0 +1,8 @@ +export default () => ({ + isLoading: false, + config: {}, + images: [], + tags: [], + pagination: {}, + tagsPagination: {}, +}); |