summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/api.js14
-rw-r--r--app/assets/javascripts/ref/constants.js4
-rw-r--r--app/assets/javascripts/ref/stores/actions.js65
-rw-r--r--app/assets/javascripts/ref/stores/getters.js5
-rw-r--r--app/assets/javascripts/ref/stores/index.js16
-rw-r--r--app/assets/javascripts/ref/stores/mutation_types.js16
-rw-r--r--app/assets/javascripts/ref/stores/mutations.js91
-rw-r--r--app/assets/javascripts/ref/stores/state.js24
8 files changed, 233 insertions, 2 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 460611356c0..b89b09521ee 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -37,7 +37,9 @@ const Api = {
userStatusPath: '/api/:version/users/:id/status',
userProjectsPath: '/api/:version/users/:id/projects',
userPostStatusPath: '/api/:version/user/status',
- commitPath: '/api/:version/projects/:id/repository/commits',
+ commitPath: '/api/:version/projects/:id/repository/commits/:sha',
+ commitsPath: '/api/:version/projects/:id/repository/commits',
+
applySuggestionPath: '/api/:version/suggestions/:id/apply',
applySuggestionBatchPath: '/api/:version/suggestions/batch_apply',
commitPipelinesPath: '/:project_id/commit/:sha/pipelines',
@@ -319,9 +321,17 @@ const Api = {
.catch(() => flash(__('Something went wrong while fetching projects')));
},
+ commit(id, sha, params = {}) {
+ const url = Api.buildUrl(this.commitPath)
+ .replace(':id', encodeURIComponent(id))
+ .replace(':sha', encodeURIComponent(sha));
+
+ return axios.get(url, { params });
+ },
+
commitMultiple(id, data) {
// see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
- const url = Api.buildUrl(Api.commitPath).replace(':id', encodeURIComponent(id));
+ const url = Api.buildUrl(Api.commitsPath).replace(':id', encodeURIComponent(id));
return axios.post(url, JSON.stringify(data), {
headers: {
'Content-Type': 'application/json; charset=utf-8',
diff --git a/app/assets/javascripts/ref/constants.js b/app/assets/javascripts/ref/constants.js
new file mode 100644
index 00000000000..524ff2380c0
--- /dev/null
+++ b/app/assets/javascripts/ref/constants.js
@@ -0,0 +1,4 @@
+// This eslint-disable can be removed once a second
+// value is added to this file.
+/* eslint-disable import/prefer-default-export */
+export const X_TOTAL_HEADER = 'x-total';
diff --git a/app/assets/javascripts/ref/stores/actions.js b/app/assets/javascripts/ref/stores/actions.js
new file mode 100644
index 00000000000..8fcc99cef38
--- /dev/null
+++ b/app/assets/javascripts/ref/stores/actions.js
@@ -0,0 +1,65 @@
+import Api from '~/api';
+import * as types from './mutation_types';
+
+export const setProjectId = ({ commit }, projectId) => commit(types.SET_PROJECT_ID, projectId);
+
+export const setSelectedRef = ({ commit }, selectedRef) =>
+ commit(types.SET_SELECTED_REF, selectedRef);
+
+export const search = ({ dispatch, commit }, query) => {
+ commit(types.SET_QUERY, query);
+
+ dispatch('searchBranches');
+ dispatch('searchTags');
+ dispatch('searchCommits');
+};
+
+export const searchBranches = ({ commit, state }) => {
+ commit(types.REQUEST_START);
+
+ Api.branches(state.projectId, state.query)
+ .then(response => {
+ commit(types.RECEIVE_BRANCHES_SUCCESS, response);
+ })
+ .catch(error => {
+ commit(types.RECEIVE_BRANCHES_ERROR, error);
+ })
+ .finally(() => {
+ commit(types.REQUEST_FINISH);
+ });
+};
+
+export const searchTags = ({ commit, state }) => {
+ commit(types.REQUEST_START);
+
+ Api.tags(state.projectId, state.query)
+ .then(response => {
+ commit(types.RECEIVE_TAGS_SUCCESS, response);
+ })
+ .catch(error => {
+ commit(types.RECEIVE_TAGS_ERROR, error);
+ })
+ .finally(() => {
+ commit(types.REQUEST_FINISH);
+ });
+};
+
+export const searchCommits = ({ commit, state, getters }) => {
+ // Only query the Commit API if the search query looks like a commit SHA
+ if (getters.isQueryPossiblyASha) {
+ commit(types.REQUEST_START);
+
+ Api.commit(state.projectId, state.query)
+ .then(response => {
+ commit(types.RECEIVE_COMMITS_SUCCESS, response);
+ })
+ .catch(error => {
+ commit(types.RECEIVE_COMMITS_ERROR, error);
+ })
+ .finally(() => {
+ commit(types.REQUEST_FINISH);
+ });
+ } else {
+ commit(types.RESET_COMMIT_MATCHES);
+ }
+};
diff --git a/app/assets/javascripts/ref/stores/getters.js b/app/assets/javascripts/ref/stores/getters.js
new file mode 100644
index 00000000000..02d4ae8ff91
--- /dev/null
+++ b/app/assets/javascripts/ref/stores/getters.js
@@ -0,0 +1,5 @@
+/** Returns `true` if the query string looks like it could be a commit SHA */
+export const isQueryPossiblyASha = ({ query }) => /^[0-9a-f]{4,40}$/i.test(query);
+
+/** Returns `true` if there is at least one in-progress request */
+export const isLoading = ({ requestCount }) => requestCount > 0;
diff --git a/app/assets/javascripts/ref/stores/index.js b/app/assets/javascripts/ref/stores/index.js
new file mode 100644
index 00000000000..2bebffc19ab
--- /dev/null
+++ b/app/assets/javascripts/ref/stores/index.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import * as actions from './actions';
+import * as getters from './getters';
+import mutations from './mutations';
+import createState from './state';
+
+Vue.use(Vuex);
+
+export default () =>
+ new Vuex.Store({
+ actions,
+ getters,
+ mutations,
+ state: createState(),
+ });
diff --git a/app/assets/javascripts/ref/stores/mutation_types.js b/app/assets/javascripts/ref/stores/mutation_types.js
new file mode 100644
index 00000000000..9f6195f5f3f
--- /dev/null
+++ b/app/assets/javascripts/ref/stores/mutation_types.js
@@ -0,0 +1,16 @@
+export const SET_PROJECT_ID = 'SET_PROJECT_ID';
+export const SET_SELECTED_REF = 'SET_SELECTED_REF';
+export const SET_QUERY = 'SET_QUERY';
+
+export const REQUEST_START = 'REQUEST_START';
+export const REQUEST_FINISH = 'REQUEST_FINISH';
+
+export const RECEIVE_BRANCHES_SUCCESS = 'RECEIVE_BRANCHES_SUCCESS';
+export const RECEIVE_BRANCHES_ERROR = 'RECEIVE_BRANCHES_ERROR';
+
+export const RECEIVE_TAGS_SUCCESS = 'RECEIVE_TAGS_SUCCESS';
+export const RECEIVE_TAGS_ERROR = 'RECEIVE_TAGS_ERROR';
+
+export const RECEIVE_COMMITS_SUCCESS = 'RECEIVE_COMMITS_SUCCESS';
+export const RECEIVE_COMMITS_ERROR = 'RECEIVE_COMMITS_ERROR';
+export const RESET_COMMIT_MATCHES = 'RESET_COMMIT_MATCHES';
diff --git a/app/assets/javascripts/ref/stores/mutations.js b/app/assets/javascripts/ref/stores/mutations.js
new file mode 100644
index 00000000000..73f9d7ee487
--- /dev/null
+++ b/app/assets/javascripts/ref/stores/mutations.js
@@ -0,0 +1,91 @@
+import * as types from './mutation_types';
+import { X_TOTAL_HEADER } from '../constants';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
+
+export default {
+ [types.SET_PROJECT_ID](state, projectId) {
+ state.projectId = projectId;
+ },
+ [types.SET_SELECTED_REF](state, selectedRef) {
+ state.selectedRef = selectedRef;
+ },
+ [types.SET_QUERY](state, query) {
+ state.query = query;
+ },
+
+ [types.REQUEST_START](state) {
+ state.requestCount += 1;
+ },
+ [types.REQUEST_FINISH](state) {
+ state.requestCount -= 1;
+ },
+
+ [types.RECEIVE_BRANCHES_SUCCESS](state, response) {
+ state.matches.branches = {
+ list: convertObjectPropsToCamelCase(response.data).map(b => ({
+ name: b.name,
+ default: b.default,
+ })),
+ totalCount: parseInt(response.headers[X_TOTAL_HEADER], 10),
+ error: null,
+ };
+ },
+ [types.RECEIVE_BRANCHES_ERROR](state, error) {
+ state.matches.branches = {
+ list: [],
+ totalCount: 0,
+ error,
+ };
+ },
+
+ [types.RECEIVE_TAGS_SUCCESS](state, response) {
+ state.matches.tags = {
+ list: convertObjectPropsToCamelCase(response.data).map(b => ({
+ name: b.name,
+ })),
+ totalCount: parseInt(response.headers[X_TOTAL_HEADER], 10),
+ error: null,
+ };
+ },
+ [types.RECEIVE_TAGS_ERROR](state, error) {
+ state.matches.tags = {
+ list: [],
+ totalCount: 0,
+ error,
+ };
+ },
+
+ [types.RECEIVE_COMMITS_SUCCESS](state, response) {
+ const commit = convertObjectPropsToCamelCase(response.data);
+
+ state.matches.commits = {
+ list: [
+ {
+ name: commit.shortId,
+ value: commit.id,
+ subtitle: commit.title,
+ },
+ ],
+ totalCount: 1,
+ error: null,
+ };
+ },
+ [types.RECEIVE_COMMITS_ERROR](state, error) {
+ state.matches.commits = {
+ list: [],
+ totalCount: 0,
+
+ // 404's are expected when the search query doesn't match any commits
+ // and shouldn't be treated as an actual error
+ error: error.response?.status !== httpStatusCodes.NOT_FOUND ? error : null,
+ };
+ },
+ [types.RESET_COMMIT_MATCHES](state) {
+ state.matches.commits = {
+ list: [],
+ totalCount: 0,
+ error: null,
+ };
+ },
+};
diff --git a/app/assets/javascripts/ref/stores/state.js b/app/assets/javascripts/ref/stores/state.js
new file mode 100644
index 00000000000..65b9d6449d7
--- /dev/null
+++ b/app/assets/javascripts/ref/stores/state.js
@@ -0,0 +1,24 @@
+export default () => ({
+ projectId: null,
+
+ query: '',
+ matches: {
+ branches: {
+ list: [],
+ totalCount: 0,
+ error: null,
+ },
+ tags: {
+ list: [],
+ totalCount: 0,
+ error: null,
+ },
+ commits: {
+ list: [],
+ totalCount: 0,
+ error: null,
+ },
+ },
+ selectedRef: null,
+ requestCount: 0,
+});