Skip to content

Commit

Permalink
Version selection in code editor and #524
Browse files Browse the repository at this point in the history
  • Loading branch information
arnoudkooi committed Jul 7, 2024
1 parent 42bd043 commit 02e2eb0
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 66 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# CHANGELOG.md

## 8.1.7.0 (2024-07-08)
Features:
- The Monaco code editor that opens when clicking the icon next to a script, now shows a select with versions. Selecting a version shows the diff editor with the selected version left and the current version right.

Fixes / changes:
- Improve handling of sysid and search command hint clicks (Issue #524)

## 8.1.5.7 (2024-07-03)
Fixes / changes:
- Update for issue snuLoadThemeVariables (Issue #523)
Expand Down
2 changes: 1 addition & 1 deletion css/codeeditor.css
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ button:hover {

select.versions {

display: none;
/* display: none; */

min-width: 200px;
padding: 5px;
Expand Down
17 changes: 9 additions & 8 deletions inject.js
Original file line number Diff line number Diff line change
Expand Up @@ -1361,7 +1361,7 @@ function snuSlashCommandShowHints(shortcut, selectFirst, snufilter, switchText,
html += "<li class='cmdexpand' data-shortcut='" + shortcut + "' ><span class='cmdkey'>+" + (snuPropertyNames.length - snuMaxHints) + "</span> ▼ show all</span></li>";
}
else if (!html && shortcut.replace(/['" ]+/g, '').length == 32) {
html += "<li class='cmdfilter' ><span class='cmdfilter cmdkey'>/sys_id</span> " +
html += "<li class='cmdfilter' ><span class='cmdfilter cmdkey'>/sysid</span> " +
"<span class='cmdlabel'>Instance search</span></li>"
}
else if (!html && /.*_([0-9a-fA-F]{32})$/.test(shortcut)) {
Expand All @@ -1377,7 +1377,7 @@ function snuSlashCommandShowHints(shortcut, selectFirst, snufilter, switchText,
// html += "<li class='cmdfilter' ><span class='cmdkey'>/" + shortcut + "</span> " +
// "<span class='cmdlabel'>Table search &lt;encodedquery&gt; (hit ► to search tables)</span></li>"
}
if (snuPropertyNames.length == 0 && snufilter.length > 3) {
if (snuPropertyNames.length == 0 && snufilter.length > 3 && !/^\/?["']?([a-f0-9]{32})["']?$/.test(snufilter)) {
html += "<li class='cmdfilter' ><span class='cmdfilter cmdkey'>/search</span> " +
"<span class='cmdlabel'>Search for: " + snufilter + "</span></li>";
}
Expand All @@ -1402,18 +1402,19 @@ function snuSlashCommandShowHints(shortcut, selectFirst, snufilter, switchText,

function setSnuFilter(ev) {
var slshcmd = this.querySelector('.cmdkey').innerText;
if (!window.top.document.getElementById('snufilter').value.startsWith(slshcmd)) {
window.top.document.getElementById('snufilter').focus();
window.top.document.getElementById('snufilter').value = slshcmd + ' ';
snuIndex = parseInt(this.dataset.index || 0);
}
else {
if (snufilter.value.startsWith(slshcmd) || snuPropertyNames.length == 0) {
obj = { 'key': 'Enter' };
if (event.ctrlKey || event.metaKey) obj.ctrlKey = true;
window.top.document.getElementById('snufilter').dispatchEvent(new KeyboardEvent('keydown', obj));
}
else {
snufilter.focus();
snufilter.value = slshcmd + ' ';
snuIndex = parseInt(this.dataset.index || 0);
}
}


function snuDiffXml(shortcut, instance = '') {
var gsft = (document.querySelector("#gsft_main") || document.querySelector("[component-id]")?.shadowRoot.querySelector("#gsft_main"));
var doc = gsft ? gsft.contentWindow : window;
Expand Down
129 changes: 73 additions & 56 deletions js/monaco/codeeditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ let data;
let editor;
let versionid;
let theme;
let language = '';

chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
console.log(message);
if (message.event == 'fillcodeeditor') {

if (hasLoaded) return;
Expand All @@ -21,7 +23,7 @@ chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
});


let theme = (message.command.snusettings?.slashtheme == "light") ? "vs-light" : "vs-dark";
theme = (message.command.snusettings?.slashtheme == "light") ? "vs-light" : "vs-dark";
require(['vs/editor/editor.main'], () => {
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
noLib: true,
Expand Down Expand Up @@ -77,27 +79,16 @@ chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {

//monaco.languages.typescript.typescriptDefaults.setExtraLibs(libs.serverglobal); //doesnt work...

var lang = '';
if (message.command.fieldType.includes('script')) lang = 'javascript';
else if (message.command.fieldType.includes('json')) lang = 'json';
else if (message.command.fieldType.includes('css')) lang = 'scss';
else if (message.command.fieldType.includes('xml')) lang = 'xml';
else if (message.command.fieldType.includes('html')) lang = 'html';
else if (message.command.name.endsWith('psm1')) lang = 'powershell';

editor = monaco.editor.create(document.getElementById('container'), {
automaticLayout: true,
value: message.command.content,
language: lang,
theme: theme,
colorDecorators: true,
"bracketPairColorization.enabled": true
});

if (message.command.fieldType.includes('script')) language = 'javascript';
else if (message.command.fieldType.includes('json')) language = 'json';
else if (message.command.fieldType.includes('css')) language = 'scss';
else if (message.command.fieldType.includes('xml')) language = 'xml';
else if (message.command.fieldType.includes('html')) language = 'html';
else if (message.command.name.endsWith('psm1')) language = 'powershell';

addActions(editor);
changeToEditor(message.command.content);

editor.focus();
versionid = editor.getModel().getAlternativeVersionId();
});

document.querySelector('#header').classList.add(theme);
Expand All @@ -120,7 +111,7 @@ chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
document.title = data.instance.name + ' ' + data.table + ' ' + data.name;
changeFavicon(sender.tab.favIconUrl);

//loadVersionSelect();
loadVersionSelect();

}
});
Expand All @@ -145,7 +136,7 @@ function addActions(editor) {
contextMenuGroupId: "2_execution",
precondition: "editorHasSelection",
run: (editor) => {
let selection = editor.getModel().getValueInRange(editor.getSelection());
let selection = getEditor().getModel().getValueInRange(editor.getSelection());
window.open('https://www.google.com/search?q=' + selection);
}
})
Expand All @@ -156,69 +147,74 @@ function addActions(editor) {
label: "Set to Javascript",
contextMenuGroupId: "3_lang",
run: (editor) => {
monaco.editor.setModelLanguage(editor.getModel(), "javascript");
monaco.editor.setModelLanguage(getEditor().getModel(), "javascript");
}
})
editor.addAction({
id: "2_json",
label: "Set to JSON",
contextMenuGroupId: "3_lang",
run: (editor) => {
monaco.editor.setModelLanguage(editor.getModel(), "json");
monaco.editor.setModelLanguage(getEditor().getModel(), "json");
}
})
editor.addAction({
id: "3_html",
label: "Set to HTML",
contextMenuGroupId: "3_lang",
run: (editor) => {
monaco.editor.setModelLanguage(editor.getModel(), "html");
monaco.editor.setModelLanguage(getEditor().getModel(), "html");
}
})
editor.addAction({
id: "4_xml",
label: "Set to XML",
contextMenuGroupId: "3_lang",
run: (editor) => {
monaco.editor.setModelLanguage(editor.getModel(), "xml");
monaco.editor.setModelLanguage(getEditor().getModel(), "xml");
}
})
editor.addAction({
id: "5_scss",
label: "Set to CSS",
contextMenuGroupId: "3_lang",
run: (editor) => {
monaco.editor.setModelLanguage(editor.getModel(), "scss");
monaco.editor.setModelLanguage(getEditor().getModel(), "scss");
}
})
editor.addAction({
id: "6_graphql",
label: "Set to GraphQL",
contextMenuGroupId: "3_lang",
run: (editor) => {
monaco.editor.setModelLanguage(editor.getModel(), "graphql");
monaco.editor.setModelLanguage(getEditor().getModel(), "graphql");
}
})
editor.addAction({
id: "7_powershell",
label: "Set to Powershell",
contextMenuGroupId: "3_lang",
run: (editor) => {
monaco.editor.setModelLanguage(editor.getModel(), "powershell");
monaco.editor.setModelLanguage(getEditor().getModel(), "powershell");
}
})
editor.addAction({
id: "8_plain",
label: "Set to Plain text",
contextMenuGroupId: "3_lang",
run: (editor) => {
monaco.editor.setModelLanguage(editor.getModel(), "plain");
monaco.editor.setModelLanguage(getEditor().getModel(), "plain");
}
})

}


function getEditor() {
return (typeof editor.getValue !== 'undefined' )?
editor : editor.getModifiedEditor();
}

async function loadVersionSelect(){
let myurl = data.instance.url + '/api/now/table/sys_update_version?sysparm_limit=250&sysparm_display_value=true&sysparm_fields=sys_id,sys_updated_on,sys_updated_by&sysparm_query=name=' +
data.table + '_' + data.sys_id +'^ORDERBYDESCsys_updated_on';
Expand Down Expand Up @@ -246,24 +242,28 @@ async function loadVersionSelect(){

selectElement.addEventListener('change', async e => {
let selected = e.target.value;
let url = data.instance.url + '/api/now/table/sys_update_version/' + selected + '?sysparm_fields=payload';
let res = await snuFetchData(data.instance.g_ck, url);
let payload = res.result.payload;

const parser = new DOMParser();
const xmlDoc = parser.parseFromString(payload, "text/xml");

// Locate the <script> element
const fieldValue = xmlDoc.getElementsByTagName(data.field)[0];

// Extract the JavaScript content
if (fieldValue) {
const fieldContent = fieldValue.textContent;
changeToDiffEditor(fieldContent);
if (!e.target.selectedOptions[0].innerHTML.includes('*'))
e.target.selectedOptions[0].innerHTML = e.target.selectedOptions[0].innerHTML + '*';
let fieldValue;
if (selected){
let url = data.instance.url + '/api/now/table/sys_update_version/' + selected + '?sysparm_fields=payload';
let res = await snuFetchData(data.instance.g_ck, url);
let payload = res.result.payload;

const parser = new DOMParser();
const xmlDoc = parser.parseFromString(payload, "text/xml");

// Locate the <script> element
fieldValue = xmlDoc.getElementsByTagName(data.field)[0];

if (fieldValue) {
const fieldContent = fieldValue.textContent;
changeToDiffEditor(fieldContent);
if (!e.target.selectedOptions[0].innerHTML.includes('*'))
e.target.selectedOptions[0].innerHTML = e.target.selectedOptions[0].innerHTML + '*';

} else {
}
}
else {
changeToEditor(getEditor().getValue());
console.log(`No ${data.field} element found`);
}
});
Expand Down Expand Up @@ -316,7 +316,7 @@ async function updateRecord() {
try {
const url = `${data.instance.url}/api/now/table/${data.table}/${data.sys_id}?sysparm_fields=sys_id`;
const postData = {
[data.field]: editor.getModel().getValue()
[data.field]: getEditor().getModel().getValue()
};

const response = await fetch(url, {
Expand All @@ -335,7 +335,7 @@ async function updateRecord() {
const resp = await response.json();
if (resp.hasOwnProperty('result')) {
document.querySelector('#response').innerHTML = `Saved: ${new Date().toLocaleTimeString()}`;
versionid = editor.getModel().getAlternativeVersionId();
versionid = getEditor().getModel().getAlternativeVersionId();
} else {
if (resp.hasOwnProperty('error')) {
document.querySelector('#response').innerHTML = `<span style="font-size:8pt; color:red" >Error: ${new Date().toLocaleTimeString()} | ${JSON.stringify(resp.error)}</span>`;
Expand All @@ -347,22 +347,39 @@ async function updateRecord() {
}
}

function changeToEditor(editorContent) {

//let currentText = getEditor().getValue();
if (editor) editor.dispose();
editor = monaco.editor.create(document.getElementById('container'), {
automaticLayout: true,
value: editorContent,
language: language,
theme: theme,
colorDecorators: true,
"bracketPairColorization.enabled": true
});

addActions(editor);

editor.focus();
versionid = getEditor().getModel().getAlternativeVersionId();
}

function changeToDiffEditor(versionText) {

let currentText = (typeof editor.getValue !== 'undefined' )?
editor.getValue() : editor.getOriginalEditor().getValue();
let currentText = getEditor().getValue();

if (editor) editor.dispose();

const currentModel = monaco.editor.createModel(currentText, 'javascript');
const oldVersionModel = monaco.editor.createModel(versionText, 'javascript');
const currentModel = monaco.editor.createModel(currentText, language);
const oldVersionModel = monaco.editor.createModel(versionText, language);

const editorContainer = document.getElementById('container'); // Ensure this is the correct ID of your editor's container

editor = monaco.editor.createDiffEditor(editorContainer, {
enableSplitViewResizing: true,
renderSideBySide: true,
originalEditable: true
renderSideBySide: true
});

editor.setModel({
Expand Down Expand Up @@ -410,7 +427,7 @@ async function snuFetchData(token, url, post, callback) {
}

window.onbeforeunload = function (e) {
if (versionid == editor.getModel().getAlternativeVersionId()) return null
if (versionid == getEditor().getModel().getAlternativeVersionId()) return null
e = e || window.event;
return 'Closing tab will loose unsaved work, continue?';
};
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"short_name": "SN Utils",
"description": "Productivity tools for ServiceNow. (Personal work, not affiliated to ServiceNow)",
"author": "Arnoud Kooi / arnoudkooi.com",
"version": "8.1.5.7",
"version": "8.1.7.0",
"manifest_version": 3,
"permissions": [
"activeTab",
Expand Down

0 comments on commit 02e2eb0

Please sign in to comment.