Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add uuid widget #6675

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dev-test/backends/test/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ collections: # A list of collections the CMS should be able to edit
search_fields: ['title', 'body']
value_field: 'title'
- { label: 'Title', name: 'title', widget: 'string' }
- { label: 'ID', name: 'uuid', widget: 'uuid', read_only: true, prefix: '', use_b32_encode: false }
- { label: 'Boolean', name: 'boolean', widget: 'boolean', default: true }
- { label: 'Map', name: 'map', widget: 'map' }
- { label: 'Text', name: 'text', widget: 'text', hint: 'Plain text, not markdown' }
Expand Down
2 changes: 1 addition & 1 deletion dev-test/backends/test/index.html

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dev-test/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ collections: # A list of collections the CMS should be able to edit
search_fields: ['title', 'body']
value_field: 'title'
- { label: 'Title', name: 'title', widget: 'string' }
- { label: 'ID', name: 'uuid', widget: 'uuid', read_only: true, prefix: '', use_b32_encode: false }
- { label: 'Boolean', name: 'boolean', widget: 'boolean', default: true }
- { label: 'Map', name: 'map', widget: 'map' }
- { label: 'Text', name: 'text', widget: 'text', hint: 'Plain text, not markdown' }
Expand Down
2 changes: 1 addition & 1 deletion dev-test/index.html

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/netlify-cms-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
"dependencies": {
"@emotion/core": "^10.0.35",
"@emotion/styled": "^10.0.27",
"base32-encode": "^2.0.0",
"codemirror": "^5.46.0",
"hex-to-array-buffer": "^2.0.0",
"immutable": "^3.7.6",
"lodash": "^4.17.11",
"moment": "^2.24.0",
Expand Down Expand Up @@ -63,6 +65,7 @@
"netlify-cms-widget-select": "^2.8.2",
"netlify-cms-widget-string": "^2.3.0",
"netlify-cms-widget-text": "^2.4.1",
"netlify-cms-widget-uuid": "^0.1.0",
"prop-types": "^15.7.2",
"react-immutable-proptypes": "^2.1.0",
"uuid": "^3.3.2"
Expand Down
2 changes: 2 additions & 0 deletions packages/netlify-cms-app/src/extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import NetlifyCmsWidgetDate from 'netlify-cms-widget-date';
import NetlifyCmsWidgetDatetime from 'netlify-cms-widget-datetime';
import NetlifyCmsWidgetCode from 'netlify-cms-widget-code';
import NetlifyCmsWidgetColorString from 'netlify-cms-widget-colorstring';
import NetlifyCmsWidgetUuid from 'netlify-cms-widget-uuid';
// Editor Components
import image from 'netlify-cms-editor-component-image';
// Locales
Expand Down Expand Up @@ -55,6 +56,7 @@ CMS.registerWidget([
NetlifyCmsWidgetDatetime.Widget(),
NetlifyCmsWidgetCode.Widget(),
NetlifyCmsWidgetColorString.Widget(),
NetlifyCmsWidgetUuid.Widget(),
]);
CMS.registerEditorComponent(image);
CMS.registerEditorComponent({
Expand Down
7 changes: 7 additions & 0 deletions packages/netlify-cms-widget-uuid/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.


**Note:** Version bump only for package netlify-cms-widget-uuid
11 changes: 11 additions & 0 deletions packages/netlify-cms-widget-uuid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Docs coming soon!

Netlify CMS was recently converted from a single npm package to a "monorepo" of over 20 packages.
That's over 20 Readme's! We haven't created one for this package yet, but we will soon.

In the meantime, you can:

1. Check out the [main readme](https://github.com/netlify/netlify-cms/#readme) or the [documentation
site](https://www.netlifycms.org) for more info.
2. Reach out to the [community chat](https://netlifycms.org/chat/) if you need help.
3. Help out and [write the readme yourself](https://github.com/netlify/netlify-cms/edit/master/packages/netlify-cms-widget-string/README.md)!
30 changes: 30 additions & 0 deletions packages/netlify-cms-widget-uuid/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "netlify-cms-widget-uuid",
"description": "Widget for uuid values in Netlify CMS.",
"version": "0.1.0",
"homepage": "https://www.netlifycms.org/docs/widgets/#uuid",
"repository": "https://github.com/netlify/netlify-cms/tree/master/packages/netlify-cms-widget-uuid",
"bugs": "https://github.com/netlify/netlify-cms/issues",
"module": "dist/esm/index.js",
"main": "dist/netlify-cms-widget-uuid.js",
"license": "MIT",
"keywords": [
"netlify",
"netlify-cms",
"widget",
"uuid"
],
"sideEffects": false,
"scripts": {
"develop": "yarn build:esm --watch",
"build": "cross-env NODE_ENV=production webpack",
"build:esm": "cross-env NODE_ENV=esm babel src --out-dir dist/esm --ignore \"**/__tests__\" --root-mode upward"
},
"peerDependencies": {
"base32-encode": "^2.0.0",
"hex-to-array-buffer": "^2.0.0",
"netlify-cms-ui-default": "^2.12.1",
"prop-types": "^15.7.2",
"react": "^16.8.4 || ^17.0.0"
}
}
80 changes: 80 additions & 0 deletions packages/netlify-cms-widget-uuid/src/UuidControl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from 'react';
import PropTypes from 'prop-types';
import base32Encode from 'base32-encode';
import hexToArrayBuffer from 'hex-to-array-buffer';

export default class UuidControl extends React.Component {
static propTypes = {
onChange: PropTypes.func.isRequired,
forID: PropTypes.string,
value: PropTypes.node,
classNameWrapper: PropTypes.string.isRequired,
setActiveStyle: PropTypes.func.isRequired,
setInactiveStyle: PropTypes.func.isRequired,
};

// The selection to maintain for the input element
_sel = 0;

// The input element ref
_el = null;

// NOTE: This prevents the cursor from jumping to the end of the text for
// nested inputs. In other words, this is not an issue on top-level text
// fields such as the `title` of a collection post. However, it becomes an
// issue on fields nested within other components, namely widgets nested
// within a `markdown` widget. For example, the alt text on a block image
// within markdown.
// SEE: https://github.com/netlify/netlify-cms/issues/4539
// SEE: https://github.com/netlify/netlify-cms/issues/3578
componentDidUpdate() {
if (this._el && this._el.selectionStart !== this._sel) {
this._el.setSelectionRange(this._sel, this._sel);
}
}

// componentDidMount is used for generate a UUID when the page loads for the first time
componentDidMount() {
const { value, field, onChange } = this.props;
if (!value) {
const prefix = field.get('prefix', '');
const useB32Encode = field.get('use_b32_encode', false);
const uuid = crypto.randomUUID();
const uuidFormatted = useB32Encode ? this.uuidToB32(uuid) : uuid;
onChange(prefix + uuidFormatted);
}
}

uuidToB32 = uuid => {
const bytes = hexToArrayBuffer(uuid.replace(/-/g, '') || '');
const encodedUUID = base32Encode(bytes, 'RFC4648', { padding: false });
return encodedUUID.toLowerCase();
};

handleChange = e => {
this._sel = e.target.selectionStart;
this.props.onChange(e.target.value);
};

render() {
const { field, forID, value, classNameWrapper, setActiveStyle, setInactiveStyle } = this.props;
const readOnly = field.get('read_only', true);

return (
<input
ref={el => {
this._el = el;
}}
type="text"
id={forID}
readOnly={readOnly}
style={{ fontFamily: 'monospace', opacity: readOnly ? '0.5' : '1.0' }}
className={classNameWrapper}
value={value || ''}
onChange={this.handleChange}
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
/>
);
}
}
13 changes: 13 additions & 0 deletions packages/netlify-cms-widget-uuid/src/UuidPreview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import PropTypes from 'prop-types';
import { WidgetPreviewContainer } from 'netlify-cms-ui-default';

function UuidPreview({ value }) {
return <WidgetPreviewContainer>{value}</WidgetPreviewContainer>;
}

UuidPreview.propTypes = {
value: PropTypes.node,
};

export default UuidPreview;
14 changes: 14 additions & 0 deletions packages/netlify-cms-widget-uuid/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import controlComponent from './UuidControl';
import previewComponent from './UuidPreview';

function Widget(opts = {}) {
return {
name: 'uuid',
controlComponent,
previewComponent,
...opts,
};
}

export const NetlifyCmsWidgetUuid = { Widget, controlComponent, previewComponent };
export default NetlifyCmsWidgetUuid;
3 changes: 3 additions & 0 deletions packages/netlify-cms-widget-uuid/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { getConfig } = require('../../scripts/webpack.js');

module.exports = getConfig();
17 changes: 17 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5353,6 +5353,13 @@ balanced-match@^2.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9"
integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==

base32-encode@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/base32-encode/-/base32-encode-2.0.0.tgz#f029bea7d1db2ecc95df5c1d0a6038a39354029a"
integrity sha512-mlmkfc2WqdDtMl/id4qm3A7RjW6jxcbAoMjdRmsPiwQP0ufD4oXItYMnPgVHe80lnAIy+1xwzhHE1s4FoIceSw==
dependencies:
to-data-view "^2.0.0"

base64-js@^1.0.2, base64-js@^1.3.1, base64-js@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
Expand Down Expand Up @@ -9790,6 +9797,11 @@ he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==

hex-to-array-buffer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/hex-to-array-buffer/-/hex-to-array-buffer-2.0.0.tgz#82c66b3fa8b8f99d74cbae430a5c01dee678117c"
integrity sha512-svtomp6qK6DL7TgteiPmImS/FQFb5yJSt17zseS8qBcYrJLkieFJKn2a2FBjRG9BYpy9uq2VeEBh6rRc16xh8w==

highlight.js@~9.13.0:
version "9.13.1"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
Expand Down Expand Up @@ -17763,6 +17775,11 @@ to-arraybuffer@^1.0.0:
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=

to-data-view@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-data-view/-/to-data-view-2.0.0.tgz#4cc3f5c9eb59514a7436fc54c587c3c34c9b1d60"
integrity sha512-RGEM5KqlPHr+WVTPmGNAXNeFEmsBnlkxXaIfEpUYV0AST2Z5W1EGq9L/MENFrMMmL2WQr1wjkmZy/M92eKhjYA==

to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
Expand Down