diff --git a/packages/form-js-editor/src/features/properties-panel/entries/VersionTagEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/VersionTagEntry.js
new file mode 100644
index 000000000..83c51699c
--- /dev/null
+++ b/packages/form-js-editor/src/features/properties-panel/entries/VersionTagEntry.js
@@ -0,0 +1,54 @@
+import { get } from 'min-dash';
+
+import { useService } from '../hooks';
+
+import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
+
+export function VersionTagEntry(props) {
+ const { editField, field } = props;
+
+ const entries = [];
+
+ entries.push({
+ id: 'versionTag',
+ component: VersionTag,
+ editField: editField,
+ field: field,
+ isEdited: isTextFieldEntryEdited,
+ isDefaultVisible: (field) => field.type === 'default',
+ });
+
+ return entries;
+}
+
+function VersionTag(props) {
+ const { editField, field, id } = props;
+
+ const debounce = useService('debounce');
+
+ const path = ['versionTag'];
+
+ const getValue = () => {
+ return get(field, path, '');
+ };
+
+ const setValue = (value, error) => {
+ if (error) {
+ return;
+ }
+
+ return editField(field, path, value);
+ };
+
+ const tooltip =
Version tag by which this form can be referenced.
;
+
+ return TextFieldEntry({
+ debounce,
+ element: field,
+ getValue,
+ id,
+ label: 'Version tag',
+ setValue,
+ tooltip,
+ });
+}
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/index.js b/packages/form-js-editor/src/features/properties-panel/entries/index.js
index bb6c79066..452144a1c 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/index.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/index.js
@@ -39,3 +39,4 @@ export { RowCountEntry } from './RowCountEntry';
export { HeadersSourceSelectEntry } from './HeadersSourceSelectEntry';
export { ColumnsExpressionEntry } from './ColumnsExpressionEntry';
export { StaticColumnsSourceEntry } from './StaticColumnsSourceEntry';
+export { VersionTagEntry } from './VersionTagEntry';
diff --git a/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js b/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js
index 8686c074e..66c1a73fd 100644
--- a/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js
+++ b/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js
@@ -23,11 +23,13 @@ import {
TableDataSourceEntry,
PaginationEntry,
RowCountEntry,
+ VersionTagEntry,
} from '../entries';
export function GeneralGroup(field, editField, getService) {
const entries = [
...IdEntry({ field, editField }),
+ ...VersionTagEntry({ field, editField }),
...LabelEntry({ field, editField }),
...DescriptionEntry({ field, editField }),
...KeyEntry({ field, editField, getService }),
diff --git a/packages/form-js-editor/test/spec/features/properties-panel/groups/GeneralGroup.spec.js b/packages/form-js-editor/test/spec/features/properties-panel/groups/GeneralGroup.spec.js
index 0811a9851..4e843e273 100644
--- a/packages/form-js-editor/test/spec/features/properties-panel/groups/GeneralGroup.spec.js
+++ b/packages/form-js-editor/test/spec/features/properties-panel/groups/GeneralGroup.spec.js
@@ -81,6 +81,75 @@ describe('GeneralGroup', function () {
});
});
+ describe('versionTag', function () {
+ it('should render for default', function () {
+ // given
+ const field = { type: 'default' };
+
+ // when
+ const { container } = renderGeneralGroup({ field });
+
+ // then
+ const versionTagInput = findInput('versionTag', container);
+
+ expect(versionTagInput).to.exist;
+ });
+
+ it('should NOT render for textfield', function () {
+ // given
+ const field = { type: 'textfield' };
+
+ // when
+ const { container } = renderGeneralGroup({ field });
+
+ // then
+ const versionTagInput = findInput('versionTag', container);
+
+ expect(versionTagInput).to.not.exist;
+ });
+
+ it('should read', function () {
+ // given
+ const field = {
+ type: 'default',
+ id: 'foobar',
+ versionTag: 'v1',
+ };
+
+ // when
+ const { container } = renderGeneralGroup({ field });
+
+ // when
+ const versionTagInput = findInput('versionTag', container);
+
+ // then
+ expect(versionTagInput).to.exist;
+ expect(versionTagInput.value).to.equal('v1');
+ });
+
+ it('should write', function () {
+ // given
+ const field = {
+ type: 'default',
+ id: 'foobar',
+ versionTag: 'v1',
+ };
+
+ const editFieldSpy = sinon.spy((field, path, value) => set(field, path, value));
+
+ const { container } = renderGeneralGroup({ field, editField: editFieldSpy });
+
+ const versionTagInput = findInput('versionTag', container);
+
+ // when
+ fireEvent.input(versionTagInput, { target: { value: 'newVal' } });
+
+ // then
+ expect(editFieldSpy).to.have.been.calledOnce;
+ expect(field.versionTag).to.equal('newVal');
+ });
+ });
+
describe('label', function () {
it('should NOT render for default', function () {
// given