From faab1e38ba0a03368263c80e3518ec17b4e1260b Mon Sep 17 00:00:00 2001 From: Shawn Erquhart Date: Mon, 23 Jul 2018 12:14:53 -0400 Subject: [PATCH] migrate GitLab backend --- .../netlify-cms-backend-github/src/API.js | 2 +- .../src/AuthenticationPage.js | 53 +++++-------------- .../src/implementation.js | 9 +++- .../babel.config.js | 3 ++ .../netlify-cms-backend-gitlab/package.json | 41 ++++++++++++++ .../src}/API.js | 1 - .../src}/AuthenticationPage.js | 32 +++++------ .../src}/implementation.js | 5 +- .../netlify-cms-backend-gitlab/src/index.js | 4 ++ .../webpack.config.js | 1 + .../src/implementation.js | 5 +- packages/netlify-cms-core/example/config.yml | 4 +- .../netlify-cms-core/src/backends/backend.js | 12 ++--- .../src/backends/git-gateway/GitLabAPI.js | 2 +- .../backends/git-gateway/implementation.js | 2 +- .../src/AuthenticationPage.js | 43 +++++++++++++++ packages/netlify-cms-ui-default/src/index.js | 1 + webpack.config.js | 2 +- 18 files changed, 149 insertions(+), 73 deletions(-) create mode 100644 packages/netlify-cms-backend-gitlab/babel.config.js create mode 100644 packages/netlify-cms-backend-gitlab/package.json rename packages/{netlify-cms-core/src/backends/gitlab => netlify-cms-backend-gitlab/src}/API.js (99%) rename packages/{netlify-cms-core/src/backends/gitlab => netlify-cms-backend-gitlab/src}/AuthenticationPage.js (72%) rename packages/{netlify-cms-core/src/backends/gitlab => netlify-cms-backend-gitlab/src}/implementation.js (96%) create mode 100644 packages/netlify-cms-backend-gitlab/src/index.js create mode 100644 packages/netlify-cms-backend-gitlab/webpack.config.js create mode 100644 packages/netlify-cms-ui-default/src/AuthenticationPage.js diff --git a/packages/netlify-cms-backend-github/src/API.js b/packages/netlify-cms-backend-github/src/API.js index bb67186f..35c650f5 100644 --- a/packages/netlify-cms-backend-github/src/API.js +++ b/packages/netlify-cms-backend-github/src/API.js @@ -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() { diff --git a/packages/netlify-cms-backend-github/src/AuthenticationPage.js b/packages/netlify-cms-backend-github/src/AuthenticationPage.js index ac63d117..0a967d60 100644 --- a/packages/netlify-cms-backend-github/src/AuthenticationPage.js +++ b/packages/netlify-cms-backend-github/src/AuthenticationPage.js @@ -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 ( - - - {loginError ?

{loginError}

: null} - - {inProgress ? "Logging in..." : "Login with GitHub"} - -
+ ( + + {inProgress ? "Logging in..." : "Login with GitHub"} + + )} + /> ); } } diff --git a/packages/netlify-cms-backend-github/src/implementation.js b/packages/netlify-cms-backend-github/src/implementation.js index 45653c0f..5df59d36 100644 --- a/packages/netlify-cms-backend-github/src/implementation.js +++ b/packages/netlify-cms-backend-github/src/implementation.js @@ -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 diff --git a/packages/netlify-cms-backend-gitlab/babel.config.js b/packages/netlify-cms-backend-gitlab/babel.config.js new file mode 100644 index 00000000..8bb1d682 --- /dev/null +++ b/packages/netlify-cms-backend-gitlab/babel.config.js @@ -0,0 +1,3 @@ +const config = require('../../babel.config.js'); + +module.exports = config; diff --git a/packages/netlify-cms-backend-gitlab/package.json b/packages/netlify-cms-backend-gitlab/package.json new file mode 100644 index 00000000..676634e7 --- /dev/null +++ b/packages/netlify-cms-backend-gitlab/package.json @@ -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" + } +} diff --git a/packages/netlify-cms-core/src/backends/gitlab/API.js b/packages/netlify-cms-backend-gitlab/src/API.js similarity index 99% rename from packages/netlify-cms-core/src/backends/gitlab/API.js rename to packages/netlify-cms-backend-gitlab/src/API.js index 357ca120..92b9e1d1 100644 --- a/packages/netlify-cms-core/src/backends/gitlab/API.js +++ b/packages/netlify-cms-backend-gitlab/src/API.js @@ -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) { diff --git a/packages/netlify-cms-core/src/backends/gitlab/AuthenticationPage.js b/packages/netlify-cms-backend-gitlab/src/AuthenticationPage.js similarity index 72% rename from packages/netlify-cms-core/src/backends/gitlab/AuthenticationPage.js rename to packages/netlify-cms-backend-gitlab/src/AuthenticationPage.js index 2c9d753f..6218fad7 100644 --- a/packages/netlify-cms-core/src/backends/gitlab/AuthenticationPage.js +++ b/packages/netlify-cms-backend-gitlab/src/AuthenticationPage.js @@ -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 ( -
- - {loginError &&

{loginError}

} - -
+ ( + + {inProgress ? "Logging in..." : "Login with GitLab"} + + )} + /> ); } } diff --git a/packages/netlify-cms-core/src/backends/gitlab/implementation.js b/packages/netlify-cms-backend-gitlab/src/implementation.js similarity index 96% rename from packages/netlify-cms-core/src/backends/gitlab/implementation.js rename to packages/netlify-cms-backend-gitlab/src/implementation.js index c78626fa..a74abbc2 100644 --- a/packages/netlify-cms-core/src/backends/gitlab/implementation.js +++ b/packages/netlify-cms-backend-gitlab/src/implementation.js @@ -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.") } diff --git a/packages/netlify-cms-backend-gitlab/src/index.js b/packages/netlify-cms-backend-gitlab/src/index.js new file mode 100644 index 00000000..25130502 --- /dev/null +++ b/packages/netlify-cms-backend-gitlab/src/index.js @@ -0,0 +1,4 @@ +export GitLabBackend from './implementation'; +export API from './API'; +export AuthenticationPage from './AuthenticationPage'; + diff --git a/packages/netlify-cms-backend-gitlab/webpack.config.js b/packages/netlify-cms-backend-gitlab/webpack.config.js new file mode 100644 index 00000000..52d79f92 --- /dev/null +++ b/packages/netlify-cms-backend-gitlab/webpack.config.js @@ -0,0 +1 @@ +module.exports = require('../../webpack.config.js'); diff --git a/packages/netlify-cms-backend-test/src/implementation.js b/packages/netlify-cms-backend-test/src/implementation.js index 1317f300..05ee9357 100644 --- a/packages/netlify-cms-backend-test/src/implementation.js +++ b/packages/netlify-cms-backend-test/src/implementation.js @@ -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) { diff --git a/packages/netlify-cms-core/example/config.yml b/packages/netlify-cms-core/example/config.yml index 943e8ebf..c11299a4 100644 --- a/packages/netlify-cms-core/example/config.yml +++ b/packages/netlify-cms-core/example/config.yml @@ -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 diff --git a/packages/netlify-cms-core/src/backends/backend.js b/packages/netlify-cms-core/src/backends/backend.js index 90f18e4b..cb10f351 100644 --- a/packages/netlify-cms-core/src/backends/backend.js +++ b/packages/netlify-cms-core/src/backends/backend.js @@ -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 }; diff --git a/packages/netlify-cms-core/src/backends/git-gateway/GitLabAPI.js b/packages/netlify-cms-core/src/backends/git-gateway/GitLabAPI.js index 39ff7de7..64978645 100644 --- a/packages/netlify-cms-core/src/backends/git-gateway/GitLabAPI.js +++ b/packages/netlify-cms-core/src/backends/git-gateway/GitLabAPI.js @@ -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) { diff --git a/packages/netlify-cms-core/src/backends/git-gateway/implementation.js b/packages/netlify-cms-core/src/backends/git-gateway/implementation.js index fb87d648..3a10e2b3 100644 --- a/packages/netlify-cms-core/src/backends/git-gateway/implementation.js +++ b/packages/netlify-cms-core/src/backends/git-gateway/implementation.js @@ -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"; diff --git a/packages/netlify-cms-ui-default/src/AuthenticationPage.js b/packages/netlify-cms-ui-default/src/AuthenticationPage.js new file mode 100644 index 00000000..e16ad25a --- /dev/null +++ b/packages/netlify-cms-ui-default/src/AuthenticationPage.js @@ -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 }) => ( + + + {loginErrorMessage ?

{loginErrorMessage}

: null} + + {renderButtonContent()} + +
+); + +export default AuthenticationPage; diff --git a/packages/netlify-cms-ui-default/src/index.js b/packages/netlify-cms-ui-default/src/index.js index 6780bfff..45c21291 100644 --- a/packages/netlify-cms-ui-default/src/index.js +++ b/packages/netlify-cms-ui-default/src/index.js @@ -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, diff --git a/webpack.config.js b/webpack.config.js index cf6800c0..bca913b0 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -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: {