@@ -728,6 +728,8 @@ let lastActiveKonvaElement;
728728 * @param {FieldInfo } [fieldInfo]
729729 */
730730function setActiveField ( konvaElement , fieldInfo ) {
731+ clearKeywordEditor ( ) ;
732+
731733 if ( lastActiveKonvaElement ) {
732734 const bg = lastActiveKonvaElement . findOne ( `#bg` ) ;
733735 // Remove background from last active element
@@ -984,44 +986,16 @@ function sendFieldUpdate(recordFormat, originalFieldName, newFieldInfo) {
984986/**
985987 * Used to create panels for editable key/value lists.
986988 * @param {string } id
987- * @param {Keyword[] } keywords
989+ * @param {Keyword[] } inputKeywords
988990 * @param {(keywords: Keyword[]) => void } [onUpdate]
989991 */
990- function createKeywordPanel ( id , keywords , onUpdate ) {
992+ function createKeywordPanel ( id , inputKeywords , onUpdate ) {
993+ /** @type {Keyword[] } */
994+ const keywords = JSON . parse ( JSON . stringify ( inputKeywords ) ) ;
995+
991996 const section = document . createElement ( `div` ) ;
992997 section . id = id ;
993998
994- const createInputCell = ( id , value , readonly ) => {
995- const cell = document . createElement ( `vscode-table-cell` ) ;
996-
997- if ( readonly ) {
998- cell . innerText = value ;
999-
1000- } else {
1001- const input = document . createElement ( `code` ) ;
1002- input . id = id ;
1003- input . innerText = value ;
1004-
1005- input . setAttribute ( `contenteditable` , `true` ) ;
1006-
1007- cell . appendChild ( input ) ;
1008- }
1009-
1010- return cell ;
1011- } ;
1012-
1013- const createDeleteButtonCell = ( onClick ) => {
1014- const cell = document . createElement ( `vscode-table-cell` ) ;
1015-
1016- const button = document . createElement ( `vscode-icon` ) ;
1017- button . setAttribute ( `name` , `trash` ) ;
1018- button . onclick = onClick ;
1019-
1020- cell . appendChild ( button ) ;
1021-
1022- return cell ;
1023- } ;
1024-
1025999 const tree = document . createElement ( `vscode-tree` ) ;
10261000 tree . id = id ;
10271001
@@ -1044,25 +1018,43 @@ function createKeywordPanel(id, keywords, onUpdate) {
10441018 open : 'folder-opened' ,
10451019 } ;
10461020
1047- tree . data = keywords . map ( ( keyword , index ) => {
1048- return {
1049- icons,
1050- label : keyword . name ,
1051- value : keyword ,
1052- description : keyword . value ,
1053- actions,
1054- subItems : keyword . conditions . map ( c => ( {
1055- label : String ( c . indicator ) ,
1056- description : c . negate ? `Negated` : undefined ,
1057- icons
1058- } ) ) ,
1059- } ;
1060- } ) ;
1021+ const rerenderTree = ( ) => {
1022+ tree . data = keywords . map ( ( keyword , index ) => {
1023+ return {
1024+ icons,
1025+ label : keyword . name ,
1026+ value : keyword ,
1027+ description : keyword . value ,
1028+ actions,
1029+ subItems : keyword . conditions . map ( c => ( {
1030+ label : String ( c . indicator ) ,
1031+ description : c . negate ? `Negated` : undefined ,
1032+ icons
1033+ } ) ) ,
1034+ } ;
1035+ } ) ;
1036+ } ;
1037+
1038+ rerenderTree ( ) ;
10611039
10621040 tree . addEventListener ( 'vsc-run-action' , ( event ) => {
10631041 console . log ( event . detail ) ;
10641042 // TODO: check event.action for `delete` and `edit`
10651043 // TODO: show UI here and update event.value with changes value
1044+
1045+ /** @type {Keyword } */
1046+ const currentKeyword = event . detail . value ;
1047+ editKeyword ( event . detail . value , ( newKeyword ) => {
1048+ const oldKeywordIndex = keywords . findIndex ( k => k . name === currentKeyword . name && k . value === currentKeyword . value )
1049+ if ( oldKeywordIndex >= 0 ) {
1050+ keywords [ oldKeywordIndex ] = newKeyword ;
1051+ } else {
1052+ keywords . push ( newKeyword ) ;
1053+ }
1054+
1055+ clearKeywordEditor ( ) ;
1056+ rerenderTree ( ) ;
1057+ } ) ;
10661058 } ) ;
10671059
10681060 section . appendChild ( tree ) ;
@@ -1084,15 +1076,8 @@ function createKeywordPanel(id, keywords, onUpdate) {
10841076 updateButton . style . display = `block` ;
10851077
10861078 updateButton . addEventListener ( `click` , ( e ) => {
1087- const rows = section . querySelectorAll ( `[id^='${ ROW_PREFIX } ']` ) ;
1088- console . log ( rows ) ;
1089-
1090- /** @type {Keyword[] } */
1091- let newKeywords = [ ] ;
1092-
1093- // Update newKeywors based on tree.data
1094-
1095- onUpdate ( newKeywords ) ;
1079+ // As we update keywords, the `keywords` variable is updated
1080+ onUpdate ( keywords ) ;
10961081 } ) ;
10971082
10981083 section . appendChild ( newKeyword ) ;
@@ -1181,4 +1166,148 @@ function createValuesPanel(id, properties, onUpdate) {
11811166 }
11821167
11831168 return section ;
1169+ }
1170+
1171+ function clearKeywordEditor ( ) {
1172+ const keywordEditorArea = document . getElementById ( `keywordEditorArea` ) ;
1173+ keywordEditorArea . innerHTML = `` ;
1174+ }
1175+
1176+ /**
1177+ * @param {Keyword } keyword
1178+ * @param {(keyword: Keyword) => void } onUpdate
1179+ */
1180+ function editKeyword ( keyword , onUpdate ) {
1181+ const group = document . createElement ( `vscode-form-group` ) ;
1182+ group . id = `currentKeywordEditor` ;
1183+ group . setAttribute ( `variant` , `vertical` ) ;
1184+ group . style . paddingLeft = `1em` ;
1185+ group . style . paddingRight = `1em` ;
1186+
1187+ const createLabel = ( label , forId ) => {
1188+ const labelElement = document . createElement ( `vscode-label` ) ;
1189+ labelElement . setAttribute ( `for` , forId ) ;
1190+ labelElement . innerText = label ;
1191+ labelElement . style . marginTop = `0.5em` ;
1192+ return labelElement ;
1193+ } ;
1194+
1195+ const createInputField = ( id , value ) => {
1196+ const input = document . createElement ( `vscode-textfield` ) ;
1197+ input . setAttribute ( `id` , id ) ;
1198+ input . setAttribute ( `value` , value ) ;
1199+ return input ;
1200+ } ;
1201+
1202+ const createIndicatorSelect = ( id , defaultValue ) => {
1203+ const select = document . createElement ( `vscode-single-select` ) ;
1204+ select . setAttribute ( `id` , id ) ;
1205+
1206+ const options = [ `None` ] ;
1207+
1208+ for ( let i = 1 ; i <= 99 ; i ++ ) {
1209+ options . push ( i ) ;
1210+ }
1211+
1212+ options . forEach ( option => {
1213+ const optionElement = document . createElement ( `vscode-option` ) ;
1214+ optionElement . setAttribute ( `value` , option ) ;
1215+ optionElement . innerText = option ;
1216+
1217+ if ( option === defaultValue ) {
1218+ optionElement . setAttribute ( `selected` , `true` ) ;
1219+ }
1220+
1221+ select . appendChild ( optionElement ) ;
1222+ } ) ;
1223+
1224+ return select ;
1225+ } ;
1226+
1227+ const createCheckbox = ( id , label , checked ) => {
1228+ const checkbox = document . createElement ( `vscode-checkbox` ) ;
1229+ checkbox . setAttribute ( `id` , id ) ;
1230+ checkbox . setAttribute ( `label` , label ) ;
1231+ if ( checked ) {
1232+ checkbox . setAttribute ( `checked` , checked ) ;
1233+ }
1234+ return checkbox ;
1235+ } ;
1236+
1237+ group . appendChild ( createLabel ( `Keyword` , `keyword` ) ) ;
1238+ group . appendChild ( createInputField ( `keyword` , keyword . name ) ) ;
1239+
1240+ group . appendChild ( createLabel ( `Value` , `value` ) ) ;
1241+ group . appendChild ( createInputField ( `value` , keyword . value || `` ) ) ;
1242+
1243+ group . appendChild ( createLabel ( `Indicator 1` , `ind1` ) ) ;
1244+ group . appendChild ( createIndicatorSelect ( `ind1` , keyword . conditions [ 0 ] ?. indicator ) ) ;
1245+
1246+ group . appendChild ( createCheckbox ( `neg1` , `Negate` , keyword . conditions [ 0 ] ?. negate ) ) ;
1247+
1248+ group . appendChild ( createLabel ( `Indicator 2` , `ind2` ) ) ;
1249+ group . appendChild ( createIndicatorSelect ( `ind2` , keyword . conditions [ 1 ] ?. indicator ) ) ;
1250+
1251+ group . appendChild ( createCheckbox ( `neg2` , `Negate` , keyword . conditions [ 1 ] ?. negate ) ) ;
1252+
1253+ group . appendChild ( createLabel ( `Indicator 3` , `ind3` ) ) ;
1254+ group . appendChild ( createIndicatorSelect ( `ind3` , keyword . conditions [ 2 ] ?. indicator ) ) ;
1255+
1256+ group . appendChild ( createCheckbox ( `neg3` , `Negate` , keyword . conditions [ 2 ] ?. negate ) ) ;
1257+
1258+ const button = document . createElement ( `vscode-button` ) ;
1259+ button . setAttribute ( `icon` , `check` ) ;
1260+ button . style . marginTop = `1em` ;
1261+ button . style . display = `block` ;
1262+ button . innerText = `Save` ;
1263+ button . onclick = ( ) => {
1264+ const keywordName = group . querySelector ( `#keyword` ) . value ;
1265+ const keywordValue = group . querySelector ( `#value` ) . value ;
1266+
1267+ const ind1 = group . querySelector ( `#ind1` ) . value ;
1268+ const neg1 = group . querySelector ( `#neg1` ) . checked ;
1269+
1270+ const ind2 = group . querySelector ( `#ind2` ) . value ;
1271+ const neg2 = group . querySelector ( `#neg2` ) . checked ;
1272+
1273+ const ind3 = group . querySelector ( `#ind3` ) . value ;
1274+ const neg3 = group . querySelector ( `#neg3` ) . checked ;
1275+
1276+ const newKeyword = {
1277+ name : keywordName ,
1278+ value : keywordValue ? keywordValue : undefined ,
1279+ conditions : [ ]
1280+ } ;
1281+
1282+ if ( ind1 !== `None` ) {
1283+ newKeyword . conditions . push ( {
1284+ indicator : ind1 ,
1285+ negate : neg1
1286+ } ) ;
1287+ }
1288+
1289+ if ( ind2 !== `None` ) {
1290+ newKeyword . conditions . push ( {
1291+ indicator : ind2 ,
1292+ negate : neg2
1293+ } ) ;
1294+ }
1295+
1296+ if ( ind3 !== `None` ) {
1297+ newKeyword . conditions . push ( {
1298+ indicator : ind3 ,
1299+ negate : neg3
1300+ } ) ;
1301+ }
1302+
1303+ onUpdate ( newKeyword ) ;
1304+ } ;
1305+
1306+ group . appendChild ( button ) ;
1307+
1308+ const keywordEditorArea = document . getElementById ( `keywordEditorArea` ) ;
1309+ keywordEditorArea . innerHTML = `` ;
1310+
1311+ keywordEditorArea . appendChild ( document . createElement ( `vscode-divider` ) ) ;
1312+ keywordEditorArea . appendChild ( group ) ;
11841313}
0 commit comments