migrate GitLab backend

This commit is contained in:
Shawn Erquhart 2018-07-23 12:14:53 -04:00
parent 33f490055d
commit faab1e38ba
18 changed files with 149 additions and 73 deletions

View File

@ -15,7 +15,7 @@ export default class API {
this.repoURL = `/repos/${ this.repo }`;
this.merge_method = config.squash_merges ? "squash" : "merge";
this.initialStatus = config.initialStatus;
this.useWorkflow = config.useWorkflow;
}
user() {

View File

@ -2,39 +2,13 @@ import React from 'react';
import PropTypes from 'prop-types';
import styled from 'react-emotion';
import { NetlifyAuthenticator } from 'netlify-cms-lib-auth';
import { Icon, buttons, shadows } from 'netlify-cms-ui-default';
import { AuthenticationPage, Icon, buttons, shadows } from 'netlify-cms-ui-default';
const StyledAuthenticationPage = styled.section`
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
height: 100vh;
const LoginButtonIcon = styled(Icon)`
margin-right: 18px;
`
const PageLogoIcon = styled(Icon)`
color: #c4c6d2;
margin-top: -300px;
`
const LoginButton = styled.button`
${buttons.button};
${shadows.dropDeep};
${buttons.default};
${buttons.gray};
padding: 0 12px;
margin-top: -40px;
display: flex;
align-items: center;
position: relative;
${Icon} {
margin-right: 18px;
}
`
export default class AuthenticationPage extends React.Component {
export default class GitHubAuthenticationPage extends React.Component {
static propTypes = {
onLogin: PropTypes.func.isRequired,
inProgress: PropTypes.bool,
@ -64,17 +38,18 @@ export default class AuthenticationPage extends React.Component {
};
render() {
const { loginError } = this.state;
const { inProgress } = this.props;
return (
<StyledAuthenticationPage>
<PageLogoIcon size="300px" type="netlify-cms"/>
{loginError ? <p>{loginError}</p> : null}
<LoginButton disabled={inProgress} onClick={this.handleLogin}>
<Icon type="github" /> {inProgress ? "Logging in..." : "Login with GitHub"}
</LoginButton>
</StyledAuthenticationPage>
<AuthenticationPage
onLogin={this.handleLogin}
loginDisabled={inProgress}
loginErrorMessage={this.state.loginError}
renderButtonContent={() => (
<React.Fragment>
<LoginButtonIcon type="github"/> {inProgress ? "Logging in..." : "Login with GitHub"}
</React.Fragment>
)}
/>
);
}
}

View File

@ -37,7 +37,14 @@ export default class GitHub {
authenticate(state) {
this.token = state.token;
this.api = new API({ token: this.token, branch: this.branch, repo: this.repo, api_root: this.api_root, squash_merges: this.squash_merges });
this.api = new API({
token: this.token,
branch: this.branch,
repo: this.repo,
api_root: this.api_root,
squash_merges: this.squash_merges,
useWorkflow: this.options.useWorkflow,
});
return this.api.user().then(user =>
this.api.hasWriteAccess().then((isCollab) => {
// Unauthorized user

View File

@ -0,0 +1,3 @@
const config = require('../../babel.config.js');
module.exports = config;

View File

@ -0,0 +1,41 @@
{
"name": "netlify-cms-backend-gitlab",
"description": "GitLab backend for Netlify CMS",
"version": "2.0.0-alpha.0",
"license": "MIT",
"main": "dist/netlify-cms-backend-gitlab.js",
"keywords": [
"netlify",
"netlify-cms",
"backend",
"gitlab"
],
"sideEffects": false,
"scripts": {
"watch": "webpack -w",
"build": "cross-env NODE_ENV=production webpack"
},
"dependencies": {
"js-base64": "^2.4.8",
"semaphore": "^1.1.0"
},
"devDependencies": {
"@babel/cli": "^7.0.0-beta.54",
"@babel/core": "^7.0.0-beta.54",
"cross-env": "^5.2.0",
"rollup": "^0.63.2",
"rollup-plugin-babel": "^4.0.0-beta.7",
"webpack": "^4.16.1",
"webpack-cli": "^3.1.0"
},
"peerDependencies": {
"immutable": "^3.7.6",
"lodash": "^4.17.10",
"netlify-cms-lib-auth": "2.0.0-alpha.0",
"netlify-cms-lib-util": "2.0.0-alpha.0",
"netlify-cms-ui-default": "2.0.0-alpha.0",
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-emotion": "^9.2.6"
}
}

View File

@ -2,7 +2,6 @@ import { localForage, unsentRequest, then, APIError, Cursor } from "netlify-cms-
import { Base64 } from "js-base64";
import { fromJS, List, Map } from "immutable";
import { cond, flow, isString, partial, partialRight, pick, omit, set, update, get } from "lodash";
import AssetProxy from "ValueObjects/AssetProxy";
export default class API {
constructor(config) {

View File

@ -1,9 +1,14 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'react-emotion';
import { NetlifyAuthenticator, ImplicitAuthenticator } from 'netlify-cms-lib-auth';
import { Icon } from 'netlify-cms-ui-default';
import { AuthenticationPage, Icon, buttons, shadows } from 'netlify-cms-ui-default';
export default class AuthenticationPage extends React.Component {
const LoginButtonIcon = styled(Icon)`
margin-right: 18px;
`
export default class GitLabAuthenticationPage extends React.Component {
static propTypes = {
onLogin: PropTypes.func.isRequired,
inProgress: PropTypes.bool,
@ -49,21 +54,18 @@ export default class AuthenticationPage extends React.Component {
};
render() {
const { loginError } = this.state;
const { inProgress } = this.props;
return (
<section className="nc-githubAuthenticationPage-root">
<Icon className="nc-githubAuthenticationPage-logo" size="500px" type="netlify-cms"/>
{loginError && <p>{loginError}</p>}
<button
className="nc-githubAuthenticationPage-button"
disabled={inProgress}
onClick={this.handleLogin}
>
<Icon type="gitlab" /> {inProgress ? "Logging in..." : "Login with GitLab"}
</button>
</section>
<AuthenticationPage
onLogin={this.handleLogin}
loginDisabled={inProgress}
loginErrorMessage={this.state.loginError}
renderButtonContent={() => (
<React.Fragment>
<LoginButtonIcon type="gitlab"/> {inProgress ? "Logging in..." : "Login with GitLab"}
</React.Fragment>
)}
/>
);
}
}

View File

@ -3,12 +3,11 @@ import semaphore from "semaphore";
import { fileExtension, Cursor, CURSOR_COMPATIBILITY_SYMBOL } from 'netlify-cms-lib-util';
import AuthenticationPage from "./AuthenticationPage";
import API from "./API";
import { EDITORIAL_WORKFLOW } from "Constants/publishModes";
const MAX_CONCURRENT_DOWNLOADS = 10;
export default class GitLab {
constructor(config, options={}) {
constructor(config, options = {}) {
this.config = config;
this.options = {
proxied: false,
@ -16,7 +15,7 @@ export default class GitLab {
...options,
};
if (config.getIn(["publish_mode"]) === EDITORIAL_WORKFLOW) {
if (this.options.useWorkflow) {
throw new Error("The GitLab backend does not support the Editorial Workflow.")
}

View File

@ -0,0 +1,4 @@
export GitLabBackend from './implementation';
export API from './API';
export AuthenticationPage from './AuthenticationPage';

View File

@ -0,0 +1 @@
module.exports = require('../../webpack.config.js');

View File

@ -43,10 +43,11 @@ const getFolderEntries = (folder, extension) => {
};
export default class TestRepo {
constructor(config) {
constructor(config, options = {}) {
this.config = config;
this.assets = [];
this.initialStatus = config.initialStatus;
this.options = options;
}
authComponent() {
@ -135,7 +136,7 @@ export default class TestRepo {
}
persistEntry({ path, raw, slug }, mediaFiles = [], options = {}) {
if (options.useWorkflow) {
if (this.options.useWorkflow) {
const unpubStore = window.repoFilesUnpublished;
const existingEntryIndex = unpubStore.findIndex(e => e.file.path === path);
if (existingEntryIndex >= 0) {

View File

@ -1,10 +1,10 @@
backend:
name: test-repo
name: gitlab
repo: erquhart/blank
display_url: https://example.com
media_folder: "assets/uploads"
publish_mode: editorial_workflow # optional, enables publishing workflow
collections: # A list of collections the CMS should be able to edit
- name: "posts" # Used in routes, ie.: /admin/collections/:slug/edit

View File

@ -2,6 +2,7 @@ import { attempt, flatten, isError } from 'lodash';
import { fromJS, Map } from 'immutable';
import fuzzy from 'fuzzy';
import { GitHubBackend } from "netlify-cms-backend-github";
import { GitLabBackend } from "netlify-cms-backend-gitlab";
import { TestBackend } from "netlify-cms-backend-test";
import { resolveFormat } from "Formats/formats";
import { selectIntegration } from 'Reducers/integrations';
@ -17,7 +18,6 @@ import {
} from "Reducers/collections";
import { createEntry } from "ValueObjects/Entry";
import { sanitizeSlug } from "Lib/urlHelper";
import GitLabBackend from "./gitlab/implementation";
import BitBucketBackend from "./bitbucket/implementation";
import GitGatewayBackend from "./git-gateway/implementation";
import { registerBackend, getBackend } from 'Lib/registry';
@ -127,8 +127,11 @@ const sortByScore = (a, b) => {
};
class Backend {
constructor(implementation, { authStore = null, backendName, config } = {}) {
this.implementation = implementation.init(config, { updateUserCredentials: this.updateUserCredentials });
constructor(implementation, { backendName, authStore = null, config } = {}) {
this.implementation = implementation.init(config, {
useWorkflow: config.getIn(["publish_mode"]) === EDITORIAL_WORKFLOW,
updateUserCredentials: this.updateUserCredentials,
});
this.backendName = backendName;
this.authStore = authStore;
if (this.implementation === null) {
@ -396,8 +399,6 @@ class Backend {
const commitMessage = commitMessageFormatter(newEntry ? 'create' : 'update', config, { collection, slug: entryObj.slug, path: entryObj.path });
const useWorkflow = config.get("publish_mode") === EDITORIAL_WORKFLOW;
const collectionName = collection.get("name");
/**
@ -410,7 +411,6 @@ class Backend {
parsedData,
commitMessage,
collectionName,
useWorkflow,
initialStatus: status.first(),
...updatedOptions
};

View File

@ -1,6 +1,6 @@
import { flow } from "lodash";
import { API as GitlabAPI } from "netlify-cms-backend-gitlab";
import { unsentRequest, then } from "netlify-cms-lib-util";
import GitlabAPI from "Backends/gitlab/API";
export default class API extends GitlabAPI {
constructor(config) {

View File

@ -4,7 +4,7 @@ import {List} from 'immutable';
import { get, pick, intersection } from "lodash";
import { unsentRequest } from "netlify-cms-lib-util";
import { GitHubBackend } from "netlify-cms-backend-github";
import GitLabBackend from "Backends/gitlab/implementation";
import { GitLabBackend } from "netlify-cms-backend-gitlab";
import BitBucketBackend from "Backends/bitbucket/implementation";
import GitHubAPI from "./GitHubAPI";
import GitLabAPI from "./GitLabAPI";

View File

@ -0,0 +1,43 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'react-emotion';
import Icon from './Icon';
import { buttons, shadows } from './styles';
const StyledAuthenticationPage = styled.section`
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
height: 100vh;
`
const PageLogoIcon = styled(Icon)`
color: #c4c6d2;
margin-top: -300px;
`
const LoginButton = styled.button`
${buttons.button};
${shadows.dropDeep};
${buttons.default};
${buttons.gray};
padding: 0 12px;
margin-top: -40px;
display: flex;
align-items: center;
position: relative;
`
const AuthenticationPage = ({ onLogin, loginDisabled, loginErrorMessage, renderButtonContent }) => (
<StyledAuthenticationPage>
<PageLogoIcon size="300px" type="netlify-cms"/>
{loginErrorMessage ? <p>{loginErrorMessage}</p> : null}
<LoginButton disabled={loginDisabled} onClick={onLogin}>
{renderButtonContent()}
</LoginButton>
</StyledAuthenticationPage>
);
export default AuthenticationPage;

View File

@ -3,6 +3,7 @@ export Icon from './Icon';
export ListItemTopBar from './ListItemTopBar';
export Loader from './Loader';
export Toggle from './Toggle';
export AuthenticationPage from './AuthenticationPage';
export {
fonts,
colorsRaw,

View File

@ -29,7 +29,7 @@ module.exports = {
target: 'web',
externals: (context, request, cb) => {
const peerDeps = Object.keys(pkg.peerDependencies || {});
const isPeerDep = dep => new RegExp(`^${dep}/?`).test(request);
const isPeerDep = dep => new RegExp(`^${dep}($|/)`).test(request);
return peerDeps.some(isPeerDep) ? cb(null, request) : cb();
},
stats: {