diff --git a/forward_engineering/configs/templates.js b/forward_engineering/configs/templates.js index 5ea4b336..d8255af3 100644 --- a/forward_engineering/configs/templates.js +++ b/forward_engineering/configs/templates.js @@ -17,7 +17,7 @@ module.exports = { '\t\t${column_definitions}${out_of_line_constraints}\n' + '\t)${tableOptions};\n', columnDefinition: - '${name} ${type}${collation}${default}${identity}${autoincrement}${not_nul}${inline_constraint}${comment}', + '${name} ${type}${collation}${default}${identity}${autoincrement}${not_nul}${inline_constraint}${comment}${tag}', externalColumnDefinition: '${name} ${type} as ${expression}${comment}', createTableForeignKey: '${constraint}FOREIGN KEY (${columns}) REFERENCES ${primary_table} (${primary_columns})', alterTableForeignKey: @@ -25,7 +25,7 @@ module.exports = { createView: 'CREATE${secure}${materialized} VIEW IF NOT EXISTS ${name} (\n' + '\t${column_list}\n' + - ')\n${copy_grants}${comment}AS ${select_statement};\n', + ')\n${copy_grants}${comment}${tag}AS ${select_statement};\n', createUDF: 'CREATE${orReplace} FUNCTION ${name}(${arguments})\n\tRETURNS ${returnType}${notNull}\n\tLANGUAGE ${language}${parameters}${comment}\n\tAS ${body};\n', createProcedure: @@ -48,4 +48,5 @@ module.exports = { setPropertyTable: 'SET ${property};\n', alterViewScript: 'ALTER VIEW IF EXISTS ${name} ', alterMaterializedViewScript: 'ALTER MATERIALIZED VIEW ${name} ', + createTag: 'CREATE${orReplace} TAG${ifNotExist} ${name}${allowedValues}${comment};\n', }; diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index ed319b30..62abb141 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -64,6 +64,11 @@ module.exports = (baseProvider, options, app) => { tab, }); + const { getTagStatement, getTagAllowedValues, getTagKeyValues } = require('./helpers/tagHelper')({ + getName, + toString, + }); + const getOutOfLineConstraints = ( foreignKeyConstraints, primaryKeyConstraints, @@ -95,6 +100,8 @@ module.exports = (baseProvider, options, app) => { fileFormats, stages, isCaseSensitive, + tags, + schemaTags, }) { const transientStatement = transient ? ' TRANSIENT' : ''; const dataRetentionStatement = @@ -137,6 +144,7 @@ module.exports = (baseProvider, options, app) => { const getBodyStatement = body => (body ? `\n\t$$\n${body}\n\t$$` : ''); const getCommentsStatement = text => (text ? `\n\tCOMMENT = '${text}'` : ''); const getNotNullStatement = isEnabled => (isEnabled ? '\n\tNOT NULL' : ''); + const getIfNotExistStatement = ifNotExist => (ifNotExist ? ' IF NOT EXISTS' : ''); const userDefinedFunctions = udfs.map(udf => assignTemplates(templates.createUDF, { @@ -209,6 +217,26 @@ module.exports = (baseProvider, options, app) => { }), ); + const tagsStatements = tags.map(tag => + assignTemplates(templates.createTag, { + orReplace: getOrReplaceStatement(tag.orReplace), + ifNotExist: getIfNotExistStatement(tag.ifNotExist), + allowedValues: getTagAllowedValues({ allowedValues: tag.allowedValues }), + name: getFullName(currentSchemaName, getName(isCaseSensitive, tag.name)), + comment: getCommentsStatement(tag.description), + }), + ); + + if (!_.isEmpty(schemaTags)) { + const schemaTagStatement = assignTemplates(templates.alterSchema, { + name: fullName, + operation: 'SET TAG', + options: getTagKeyValues({ tags: schemaTags, isCaseSensitive }), + }); + + tagsStatements.push(schemaTagStatement); + } + const statements = []; if (databaseName) { @@ -226,6 +254,7 @@ module.exports = (baseProvider, options, app) => { ...sequencesStatements, ...fileFormatsStatements, ...stagesStatements, + ...tagsStatements, ].join('\n'); }, @@ -285,24 +314,28 @@ module.exports = (baseProvider, options, app) => { const columnDefinitions = tableData.columns .map(column => commentIfDeactivated(column.statement, column)) .join(',\n\t\t'); + const tagsStatement = getTagStatement({ + tags: tableData.tableTags, + isCaseSensitive: tableData.isCaseSensitive, + }); if (tableData.selectStatement) { return assignTemplates(templates.createAsSelect, { name: tableData.fullName, selectStatement: tableData.selectStatement, - tableOptions: addOptions([clusterKeys, copyGrants]), + tableOptions: addOptions([clusterKeys, copyGrants, tagsStatement]), }); } else if (tableData.cloneTableName) { return assignTemplates(templates.createCloneTable, { name: tableData.fullName, source_table: getFullName(schemaName, tableData.cloneTableName), - tableOptions: addOptions([atOrBefore, copyGrants]), + tableOptions: addOptions([atOrBefore, copyGrants, tagsStatement]), }); } else if (tableData.likeTableName) { return assignTemplates(templates.createLikeTable, { name: tableData.fullName, source_table: getFullName(schemaName, tableData.likeTableName), - tableOptions: addOptions([clusterKeys, copyGrants]), + tableOptions: addOptions([clusterKeys, copyGrants, tagsStatement]), }); } else if (tableData.external) { const location = tableData.externalOptions.location @@ -321,7 +354,16 @@ module.exports = (baseProvider, options, app) => { return assignTemplates(templates.createExternalTable, { name: tableData.fullName, tableOptions: addOptions( - [partitionKeys, fileFormat, location, refreshOnCreate, autoRefresh, pattern, copyGrants], + [ + partitionKeys, + fileFormat, + location, + refreshOnCreate, + autoRefresh, + pattern, + copyGrants, + tagsStatement, + ], comment, ), @@ -339,7 +381,7 @@ module.exports = (baseProvider, options, app) => { temporary: temporary, transient: transient, tableOptions: addOptions( - [clusterKeys, stageFileFormat, copyOptions, dataRetentionTime, copyGrants], + [clusterKeys, stageFileFormat, copyOptions, dataRetentionTime, copyGrants, tagsStatement], comment, ), @@ -367,6 +409,10 @@ module.exports = (baseProvider, options, app) => { not_nul: !columnDefinition.nullable ? ' NOT NULL' : '', inline_constraint: getInlineConstraint(columnDefinition), comment: columnDefinition.comment ? ` COMMENT $$${columnDefinition.comment}$$` : '', + tag: getTagStatement({ + tags: columnDefinition.columnTags, + isCaseSensitive: columnDefinition.isCaseSensitive, + }), }); return { statement: columnStatement, isActivated: columnDefinition.isActivated }; }, @@ -462,6 +508,12 @@ module.exports = (baseProvider, options, app) => { viewData.selectStatement || `SELECT \n\t${viewColumnsToString(tableColumns, isActivated)}\nFROM ${tables.join(' INNER JOIN ')}`; + const tagStatement = getTagStatement({ + tags: viewData.viewTags, + isCaseSensitive: viewData.isCaseSensitive, + indent: '', + }); + return assignTemplates(templates.createView, { secure: viewData.secure ? ' SECURE' : '', materialized: viewData.materialized ? ' MATERIALIZED' : '', @@ -470,6 +522,7 @@ module.exports = (baseProvider, options, app) => { copy_grants: viewData.copyGrants ? 'COPY GRANTS\n' : '', comment: viewData.comment ? 'COMMENT=$$' + viewData.comment + '$$\n' : '', select_statement: selectStatement, + tag: tagStatement ? tagStatement + '\n' : '', }); }, @@ -486,7 +539,8 @@ module.exports = (baseProvider, options, app) => { }, hydrateColumn({ columnDefinition, jsonSchema, dbData }) { - return Object.assign({}, columnDefinition, { + return { + ...columnDefinition, name: getName(jsonSchema.isCaseSensitive, columnDefinition.name), isCaseSensitive: jsonSchema.isCaseSensitive, timePrecision: Number(jsonSchema.tPrecision), @@ -525,10 +579,11 @@ module.exports = (baseProvider, options, app) => { uniqueKeyConstraintName: jsonSchema.uniqueKeyConstraintName, primaryKey: jsonSchema.primaryKeyConstraintName ? false : columnDefinition.primaryKey, expression: jsonSchema.expression, - }); + columnTags: jsonSchema.columnTags ?? [], + }; }, - hydrateSchema(containerData, { udfs, procedures, sequences, fileFormats, stages } = {}) { + hydrateSchema(containerData, { udfs, procedures, sequences, fileFormats, stages, tags } = {}) { return { schemaName: getName(containerData.isCaseSensitive, containerData.name), isCaseSensitive: containerData.isCaseSensitive, @@ -537,6 +592,7 @@ module.exports = (baseProvider, options, app) => { transient: containerData.transient, managedAccess: containerData.managedAccess, dataRetention: containerData.DATA_RETENTION_TIME_IN_DAYS, + schemaTags: containerData.schemaTags, udfs: Array.isArray(udfs) ? udfs .map(udf => @@ -625,6 +681,19 @@ module.exports = (baseProvider, options, app) => { ) .filter(stage => stage.name) : [], + tags: Array.isArray(tags) + ? tags + .map(tag => + clean({ + name: tag.name || undefined, + orReplace: tag.orReplace || undefined, + ifNotExist: tag.ifNotExist || undefined, + allowedValues: tag.allowedValues || undefined, + description: tag.description || undefined, + }), + ) + .filter(tag => tag.name) + : [], }; }, @@ -772,6 +841,7 @@ module.exports = (baseProvider, options, app) => { isCaseSensitive: firstTab.isCaseSensitive, }), ), + tableTags: firstTab.tableTags ?? [], }; }, @@ -791,6 +861,7 @@ module.exports = (baseProvider, options, app) => { secure: firstTab.secure, materialized: firstTab.materialized, fullName, + viewTags: firstTab.viewTags ?? [], }; }, diff --git a/forward_engineering/helpers/tagHelper.js b/forward_engineering/helpers/tagHelper.js new file mode 100644 index 00000000..613f666a --- /dev/null +++ b/forward_engineering/helpers/tagHelper.js @@ -0,0 +1,62 @@ +/** + * @typedef {{ id: string, tagName?: string, tagValue?: string }} Tag + */ + +const { isEmpty } = require('lodash'); + +module.exports = ({ getName, toString }) => { + /** + * @param {{ tags: Tag[], isCaseSensitive: boolean, indent: string }} + * @returns {string} + */ + const getTagStatement = ({ tags, isCaseSensitive, indent = ' ' }) => { + if (isEmpty(tags)) { + return ''; + } + + const keyValues = getTagKeyValues({ tags, isCaseSensitive }); + + return `${indent}WITH TAG ( ${keyValues} )`; + }; + + /** + * @param {{ allowedValues: string[] }} + * @returns {string} + */ + const getTagAllowedValues = ({ allowedValues }) => { + if (isEmpty(allowedValues)) { + return ''; + } + + const values = allowedValues.map(({ value }) => toString(value)).join(', '); + + return ` ALLOWED_VALUES ${values}`; + }; + + /** + * @param {{ tags: Tag[], isCaseSensitive: boolean }} + * @returns {string} + */ + const getTagKeyValues = ({ tags, isCaseSensitive }) => { + return tags + .filter(tag => tag.tagName) + .map(tag => `${getTagName({ tagName: tag.tagName, isCaseSensitive })} = ${toString(tag.tagValue)}`) + .join(', '); + }; + + /** + * @param {{ tagName: string, isCaseSensitive: boolean }} + * @returns {string} + */ + const getTagName = ({ tagName, isCaseSensitive }) => { + const hasSpace = /\s/.test(tagName); + + return hasSpace ? getName(isCaseSensitive, tagName) : tagName; + }; + + return { + getTagStatement, + getTagAllowedValues, + getTagKeyValues, + }; +}; diff --git a/properties_pane/container_level/containerLevelConfig.json b/properties_pane/container_level/containerLevelConfig.json index 24fb17f6..a059f3d8 100644 --- a/properties_pane/container_level/containerLevelConfig.json +++ b/properties_pane/container_level/containerLevelConfig.json @@ -156,6 +156,29 @@ making sure that you maintain a proper JSON format. "minValue": 0, "maxValue": 90 }, + { + "propertyName": "Schema Tags", + "propertyKeyword": "schemaTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -917,5 +940,61 @@ making sure that you maintain a proper JSON format. ] } ] + }, + { + "lowerTab": "Tags", + "structure": [ + { + "propertyName": "Tag", + "propertyType": "group", + "propertyKeyword": "tags", + "propertyTooltip": "Creates a new stored tag or replaces an existing tag for the current database.", + "structure": [ + { + "propertyName": "Name", + "propertyKeyword": "name", + "propertyTooltip": "The name of the tag.", + "propertyType": "text", + "validation": { + "required": true + } + }, + { + "propertyName": "Or replace", + "propertyKeyword": "orReplace", + "propertyType": "checkbox", + "propertyTooltip": "Specifies that if a tag with the same name as this one already exists, the existing tag is replaced. You can only replace a tag with a new tag." + }, + { + "propertyName": "If not exist", + "propertyKeyword": "ifNotExist", + "propertyType": "checkbox" + }, + { + "propertyName": "Allowed values", + "propertyKeyword": "allowedValues", + "propertyType": "group", + "parentType": "tags", + "structure": [ + { + "propertyName": "Value", + "propertyKeyword": "value", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, + { + "propertyName": "Comment", + "propertyKeyword": "description", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + } + ] } ] diff --git a/properties_pane/entity_level/entityLevelConfig.json b/properties_pane/entity_level/entityLevelConfig.json index b50100bd..20908aed 100644 --- a/properties_pane/entity_level/entityLevelConfig.json +++ b/properties_pane/entity_level/entityLevelConfig.json @@ -898,6 +898,29 @@ making sure that you maintain a proper JSON format. "propertyKeyword": "copyGrants", "propertyType": "checkbox" }, + { + "propertyName": "Table Tags", + "propertyKeyword": "tableTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", diff --git a/properties_pane/field_level/fieldLevelConfig.json b/properties_pane/field_level/fieldLevelConfig.json index 7ada1a4b..dc852fe1 100644 --- a/properties_pane/field_level/fieldLevelConfig.json +++ b/properties_pane/field_level/fieldLevelConfig.json @@ -499,6 +499,29 @@ making sure that you maintain a proper JSON format. } }, "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -904,6 +927,29 @@ making sure that you maintain a proper JSON format. "pattern", "enum", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -1291,6 +1337,29 @@ making sure that you maintain a proper JSON format. "pattern", "enum", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -1678,6 +1747,29 @@ making sure that you maintain a proper JSON format. "pattern", "enum", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -2065,6 +2157,29 @@ making sure that you maintain a proper JSON format. "pattern", "enum", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -2357,6 +2472,29 @@ making sure that you maintain a proper JSON format. }, "default", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -2662,6 +2800,29 @@ making sure that you maintain a proper JSON format. "value": true } }, + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -2959,6 +3120,29 @@ making sure that you maintain a proper JSON format. "default", "enum", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -3265,6 +3449,29 @@ making sure that you maintain a proper JSON format. "default", "enum", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -3579,6 +3786,29 @@ making sure that you maintain a proper JSON format. "default", "enum", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -3893,6 +4123,29 @@ making sure that you maintain a proper JSON format. "default", "enum", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -4207,6 +4460,29 @@ making sure that you maintain a proper JSON format. "default", "enum", "sample", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -4603,6 +4879,29 @@ making sure that you maintain a proper JSON format. "maxProperties", "dependencies", "additionalProperties", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -4911,6 +5210,29 @@ making sure that you maintain a proper JSON format. "maxProperties", "dependencies", "additionalProperties", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", @@ -4974,7 +5296,30 @@ making sure that you maintain a proper JSON format. "template": "textarea" }, "minProperties", - "maxProperties" + "maxProperties", + { + "propertyName": "Column Tags", + "propertyKeyword": "columnTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] + } ] } } diff --git a/properties_pane/view_level/viewLevelConfig.json b/properties_pane/view_level/viewLevelConfig.json index f3ee3b8c..d6c506ce 100644 --- a/properties_pane/view_level/viewLevelConfig.json +++ b/properties_pane/view_level/viewLevelConfig.json @@ -67,6 +67,29 @@ "propertyKeyword": "copyGrants", "shouldValidate": false, "propertyType": "checkbox" + }, + { + "propertyName": "View Tags", + "propertyKeyword": "viewTags", + "propertyTooltip": "", + "propertyType": "group", + "groupItemLimit": 50, + "structure": [ + { + "propertyName": "Tag name", + "propertyKeyword": "tagName", + "propertyTooltip": "", + "propertyType": "text" + }, + { + "propertyName": "Value", + "propertyKeyword": "tagValue", + "propertyTooltip": "", + "propertyType": "details", + "template": "textarea", + "markdown": false + } + ] } ] }