Skip to content

Commit

Permalink
feat: add uuid widget
Browse files Browse the repository at this point in the history
Add a uuid widget which supports options:
* read_only (bool)
* prefix (string)
* use_b32_encoding (bool)

close: decaporg#1975
  • Loading branch information
liufuyang committed Jan 30, 2023
1 parent 0c5efd1 commit 43fd4e3
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 2 deletions.
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

0 comments on commit 43fd4e3

Please sign in to comment.