Files
SCM-Manager/scm-ui/src/repos/modules/repos.js

451 lines
10 KiB
JavaScript
Raw Normal View History

2018-07-31 16:32:16 +02:00
// @flow
import { apiClient } from "@scm-manager/ui-components";
2018-07-31 16:32:16 +02:00
import * as types from "../../modules/types";
import type {
Action,
Repository,
RepositoryCollection
} from "@scm-manager/ui-types";
2018-08-03 08:52:02 +02:00
import { isPending } from "../../modules/pending";
import { getFailure } from "../../modules/failure";
2018-07-31 16:32:16 +02:00
export const FETCH_REPOS = "scm/repos/FETCH_REPOS";
export const FETCH_REPOS_PENDING = `${FETCH_REPOS}_${types.PENDING_SUFFIX}`;
export const FETCH_REPOS_SUCCESS = `${FETCH_REPOS}_${types.SUCCESS_SUFFIX}`;
export const FETCH_REPOS_FAILURE = `${FETCH_REPOS}_${types.FAILURE_SUFFIX}`;
export const FETCH_REPO = "scm/repos/FETCH_REPO";
export const FETCH_REPO_PENDING = `${FETCH_REPO}_${types.PENDING_SUFFIX}`;
export const FETCH_REPO_SUCCESS = `${FETCH_REPO}_${types.SUCCESS_SUFFIX}`;
export const FETCH_REPO_FAILURE = `${FETCH_REPO}_${types.FAILURE_SUFFIX}`;
export const CREATE_REPO = "scm/repos/CREATE_REPO";
2018-08-03 08:52:02 +02:00
export const CREATE_REPO_PENDING = `${CREATE_REPO}_${types.PENDING_SUFFIX}`;
export const CREATE_REPO_SUCCESS = `${CREATE_REPO}_${types.SUCCESS_SUFFIX}`;
export const CREATE_REPO_FAILURE = `${CREATE_REPO}_${types.FAILURE_SUFFIX}`;
export const CREATE_REPO_RESET = `${CREATE_REPO}_${types.RESET_SUFFIX}`;
2018-08-06 15:41:20 +02:00
export const MODIFY_REPO = "scm/repos/MODIFY_REPO";
export const MODIFY_REPO_PENDING = `${MODIFY_REPO}_${types.PENDING_SUFFIX}`;
export const MODIFY_REPO_SUCCESS = `${MODIFY_REPO}_${types.SUCCESS_SUFFIX}`;
export const MODIFY_REPO_FAILURE = `${MODIFY_REPO}_${types.FAILURE_SUFFIX}`;
export const DELETE_REPO = "scm/repos/DELETE_REPO";
export const DELETE_REPO_PENDING = `${DELETE_REPO}_${types.PENDING_SUFFIX}`;
export const DELETE_REPO_SUCCESS = `${DELETE_REPO}_${types.SUCCESS_SUFFIX}`;
export const DELETE_REPO_FAILURE = `${DELETE_REPO}_${types.FAILURE_SUFFIX}`;
2018-07-31 16:32:16 +02:00
const REPOS_URL = "repositories";
2018-08-03 08:52:02 +02:00
const CONTENT_TYPE = "application/vnd.scmm-repository+json;v=2";
// fetch repos
const SORT_BY = "sortBy=namespaceAndName";
2018-07-31 16:32:16 +02:00
export function fetchRepos() {
return fetchReposByLink(REPOS_URL);
}
export function fetchReposByPage(page: number) {
return fetchReposByLink(`${REPOS_URL}?page=${page - 1}`);
}
function appendSortByLink(url: string) {
if (url.includes(SORT_BY)) {
return url;
}
let urlWithSortBy = url;
if (url.includes("?")) {
urlWithSortBy += "&";
} else {
urlWithSortBy += "?";
}
return urlWithSortBy + SORT_BY;
}
export function fetchReposByLink(link: string) {
const url = appendSortByLink(link);
2018-07-31 16:32:16 +02:00
return function(dispatch: any) {
dispatch(fetchReposPending());
return apiClient
.get(url)
2018-07-31 16:32:16 +02:00
.then(response => response.json())
.then(repositories => {
dispatch(fetchReposSuccess(repositories));
})
.catch(err => {
dispatch(fetchReposFailure(err));
});
};
}
export function fetchReposPending(): Action {
return {
type: FETCH_REPOS_PENDING
};
}
export function fetchReposSuccess(repositories: RepositoryCollection): Action {
return {
type: FETCH_REPOS_SUCCESS,
payload: repositories
};
}
export function fetchReposFailure(err: Error): Action {
return {
type: FETCH_REPOS_FAILURE,
payload: err
};
}
// fetch repo
export function fetchRepo(namespace: string, name: string) {
return function(dispatch: any) {
dispatch(fetchRepoPending(namespace, name));
2018-08-03 08:52:02 +02:00
return apiClient
.get(`${REPOS_URL}/${namespace}/${name}`)
.then(response => response.json())
2018-08-03 08:52:02 +02:00
.then(repository => {
dispatch(fetchRepoSuccess(repository));
})
.catch(err => {
2018-08-03 08:52:02 +02:00
dispatch(fetchRepoFailure(namespace, name, err));
});
2018-08-03 08:52:02 +02:00
};
}
export function fetchRepoPending(namespace: string, name: string): Action {
return {
type: FETCH_REPO_PENDING,
payload: {
namespace,
name
},
itemId: namespace + "/" + name
};
}
export function fetchRepoSuccess(repository: Repository): Action {
return {
type: FETCH_REPO_SUCCESS,
payload: repository,
itemId: createIdentifier(repository)
};
}
2018-08-03 08:52:02 +02:00
export function fetchRepoFailure(
namespace: string,
name: string,
error: Error
): Action {
return {
type: FETCH_REPO_FAILURE,
payload: {
namespace,
name,
error
},
itemId: namespace + "/" + name
};
}
2018-08-03 08:52:02 +02:00
// create repo
export function createRepo(repository: Repository, callback?: () => void) {
return function(dispatch: any) {
dispatch(createRepoPending());
return apiClient
.post(REPOS_URL, repository, CONTENT_TYPE)
.then(() => {
dispatch(createRepoSuccess());
if (callback) {
callback();
}
})
.catch(err => {
dispatch(createRepoFailure(err));
});
};
}
export function createRepoPending(): Action {
return {
type: CREATE_REPO_PENDING
};
}
export function createRepoSuccess(): Action {
return {
type: CREATE_REPO_SUCCESS
};
}
export function createRepoFailure(err: Error): Action {
return {
type: CREATE_REPO_FAILURE,
payload: err
};
}
export function createRepoReset(): Action {
return {
type: CREATE_REPO_RESET
};
}
2018-08-06 15:41:20 +02:00
// modify
export function modifyRepo(repository: Repository, callback?: () => void) {
return function(dispatch: any) {
dispatch(modifyRepoPending(repository));
return apiClient
.put(repository._links.update.href, repository, CONTENT_TYPE)
.then(() => {
dispatch(modifyRepoSuccess(repository));
if (callback) {
callback();
}
})
.catch(cause => {
const error = new Error(`failed to modify repo: ${cause.message}`);
dispatch(modifyRepoFailure(repository, error));
});
};
}
export function modifyRepoPending(repository: Repository): Action {
return {
type: MODIFY_REPO_PENDING,
payload: repository,
itemId: createIdentifier(repository)
};
}
export function modifyRepoSuccess(repository: Repository): Action {
return {
type: MODIFY_REPO_SUCCESS,
payload: repository,
itemId: createIdentifier(repository)
};
}
export function modifyRepoFailure(
repository: Repository,
error: Error
): Action {
return {
type: MODIFY_REPO_FAILURE,
payload: { error, repository },
itemId: createIdentifier(repository)
};
}
// delete
export function deleteRepo(repository: Repository, callback?: () => void) {
return function(dispatch: any) {
dispatch(deleteRepoPending(repository));
return apiClient
.delete(repository._links.delete.href)
.then(() => {
dispatch(deleteRepoSuccess(repository));
if (callback) {
callback();
}
})
.catch(err => {
dispatch(deleteRepoFailure(repository, err));
});
};
}
export function deleteRepoPending(repository: Repository): Action {
return {
type: DELETE_REPO_PENDING,
payload: repository,
itemId: createIdentifier(repository)
};
}
export function deleteRepoSuccess(repository: Repository): Action {
return {
type: DELETE_REPO_SUCCESS,
payload: repository,
itemId: createIdentifier(repository)
};
}
export function deleteRepoFailure(
repository: Repository,
error: Error
): Action {
return {
type: DELETE_REPO_FAILURE,
payload: {
error,
repository
},
itemId: createIdentifier(repository)
};
}
2018-07-31 16:32:16 +02:00
// reducer
function createIdentifier(repository: Repository) {
return repository.namespace + "/" + repository.name;
}
2018-07-31 16:32:16 +02:00
function normalizeByNamespaceAndName(
repositoryCollection: RepositoryCollection
) {
const names = [];
const byNames = {};
for (const repository of repositoryCollection._embedded.repositories) {
const identifier = createIdentifier(repository);
2018-07-31 16:32:16 +02:00
names.push(identifier);
byNames[identifier] = repository;
}
return {
list: {
...repositoryCollection,
_embedded: {
repositories: names
}
},
byNames: byNames
};
}
const reducerByNames = (state: Object, repository: Repository) => {
const identifier = createIdentifier(repository);
const newState = {
...state,
byNames: {
...state.byNames,
[identifier]: repository
}
};
return newState;
};
2018-07-31 16:32:16 +02:00
export default function reducer(
state: Object = {},
action: Action = { type: "UNKNOWN" }
): Object {
if (!action.payload) {
return state;
}
switch (action.type) {
case FETCH_REPOS_SUCCESS:
return normalizeByNamespaceAndName(action.payload);
2018-08-06 15:41:20 +02:00
case MODIFY_REPO_SUCCESS:
return reducerByNames(state, action.payload);
case FETCH_REPO_SUCCESS:
return reducerByNames(state, action.payload);
default:
2018-08-03 08:52:02 +02:00
return state;
2018-07-31 16:32:16 +02:00
}
}
// selectors
export function getRepositoryCollection(state: Object) {
if (state.repos && state.repos.list && state.repos.byNames) {
const repositories = [];
for (let repositoryName of state.repos.list._embedded.repositories) {
repositories.push(state.repos.byNames[repositoryName]);
}
return {
...state.repos.list,
_embedded: {
repositories
}
};
}
}
export function isFetchReposPending(state: Object) {
return isPending(state, FETCH_REPOS);
}
export function getFetchReposFailure(state: Object) {
return getFailure(state, FETCH_REPOS);
}
export function getRepository(state: Object, namespace: string, name: string) {
if (state.repos && state.repos.byNames) {
2018-08-03 08:52:02 +02:00
return state.repos.byNames[namespace + "/" + name];
}
}
2018-08-03 08:52:02 +02:00
export function isFetchRepoPending(
state: Object,
namespace: string,
name: string
) {
return isPending(state, FETCH_REPO, namespace + "/" + name);
}
2018-08-03 08:52:02 +02:00
export function getFetchRepoFailure(
state: Object,
namespace: string,
name: string
) {
return getFailure(state, FETCH_REPO, namespace + "/" + name);
}
2018-08-03 08:52:02 +02:00
export function isAbleToCreateRepos(state: Object) {
return !!(
2018-08-03 08:52:02 +02:00
state.repos &&
state.repos.list &&
state.repos.list._links &&
state.repos.list._links.create
);
2018-08-03 08:52:02 +02:00
}
export function isCreateRepoPending(state: Object) {
return isPending(state, CREATE_REPO);
}
export function getCreateRepoFailure(state: Object) {
return getFailure(state, CREATE_REPO);
}
2018-08-06 15:41:20 +02:00
export function isModifyRepoPending(
state: Object,
namespace: string,
name: string
) {
return isPending(state, MODIFY_REPO, namespace + "/" + name);
}
export function getModifyRepoFailure(
state: Object,
namespace: string,
name: string
) {
return getFailure(state, MODIFY_REPO, namespace + "/" + name);
}
export function isDeleteRepoPending(
state: Object,
namespace: string,
name: string
) {
return isPending(state, DELETE_REPO, namespace + "/" + name);
}
export function getDeleteRepoFailure(
state: Object,
namespace: string,
name: string
) {
return getFailure(state, DELETE_REPO, namespace + "/" + name);
}