Skip to content

Commit

Permalink
Dependency View Extension (#672)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasondaming authored Sep 27, 2024
1 parent 72977bd commit 25558ec
Show file tree
Hide file tree
Showing 13 changed files with 900 additions and 47 deletions.
5 changes: 5 additions & 0 deletions vscode-wpilib/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// eslint.config.js
module.exports =
{
ignores: ["media/", "out/", "resources/"]
};
40 changes: 40 additions & 0 deletions vscode-wpilib/media/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
body {
background-color: transparent;
}

.color-list {
list-style: none;
padding: 0;
}

.color-entry {
width: 100%;
display: flex;
margin-bottom: 0.4em;
border: 1px solid var(--vscode-input-border);
}

.color-preview {
width: 2em;
height: 2em;
}

.color-preview:hover {
outline: inset white;
}

.color-input {
display: block;
flex: 1;
width: 100%;
color: var(--vscode-input-foreground);
background-color: var(--vscode-input-background);
border: none;
padding: 0 0.6em;
}

.add-color-button {
display: block;
border: none;
margin: 0 auto;
}
178 changes: 178 additions & 0 deletions vscode-wpilib/media/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
//@ts-check

// This script will be run within the webview itself
// It cannot access the main VS Code APIs directly.
(function () {
const vscode = acquireVsCodeApi();
let dropdowns;
let buttons;
let message;
let uninstalls;
let installs;

function populateDropDowns(data) {
dropdowns.forEach((dropdown, index) => {
const versions = data[index].versionInfo;
versions.forEach((versionTuple, i) => {
const option = document.createElement('option');
option.value = versionTuple.version;
option.textContent = versionTuple.version;
if (data[index].currentVersion === versionTuple.version) {
option.selected = true;
buttons[index].textContent = versionTuple.buttonText;
if (i === 0) {
//This is the first element of the version array thus the most current
buttons[index].setAttribute('disabled', 'true');
}
}
dropdown.appendChild(option);
});
});
}

// Function to generate HTML for installed dependencies
function generateInstalledHTML(installed) {
const trash = document.getElementById('trashicon')?.innerHTML
// Create HTML for installed dependencies
let installedHtml = '<h2>Installed VendorDeps</h2>';
installed.forEach((dep, index) => {
installedHtml += `
<div class="installed-dependency">
<div class="top-line">
<span>${dep.name}</span><span>${dep.currentVersion}</span>
</div>
<div class="update">
<select id="version-select-${index}"></select>
<button id="version-action-${index}"></button>
<button id="uninstall-action-${index}" class="uninstall-button" data-dependency="${dep.name}">
<img src=${trash} alt="Uninstall">
</button>
</div>
</div>
`;
});
return installedHtml;
}

// Function to generate HTML for available dependencies
function generateAvailableHTML(available) {
// Create HTML for available dependencies
let availableHtml = '<h2>Available Dependencies</h2>';
available.forEach((dep, index) => {
availableHtml += `
<div class="available-dependency">
<div class="top-line">
<span class="name">${dep.name}</span><button id="install-action-${index}">Install</button>
</div>
<div class="details">${dep.version} - ${dep.description}</div>
</div>
`;
});
return availableHtml;
}

// Add event listeners to the buttons
function addEventListeners() {
// Handle messages sent from the extension to the webview
window.addEventListener('message', event => {
message = event.data; // The json data that the extension sent
switch (message.type) {
case 'updateDependencies':
{
const installedHTML = generateInstalledHTML(message.installed);
const availableHTML = generateAvailableHTML(message.available);

const installedContainer = document.getElementById('installed-dependencies');
const availableContainer = document.getElementById('available-dependencies');

if (installedContainer) {
installedContainer.innerHTML = installedHTML;
} else {
console.error('Element with ID "installed-dependencies" not found.');
}

if (availableContainer) {
availableContainer.innerHTML = availableHTML;
} else {
console.error('Element with ID "available-dependencies" not found.');
}

dropdowns = document.querySelectorAll('select[id^="version-select-"]');
buttons = document.querySelectorAll('button[id^="version-action-"]');
uninstalls = document.querySelectorAll('button[id^="uninstall-action-"]');
installs = document.querySelectorAll('button[id^="install-action-"]');
addDropdownListeners();
populateDropDowns(message.installed);
break;
}
}
});

document.getElementById('updateall-action')?.addEventListener('click', () => {
vscode.postMessage({ type: 'updateall' })
});

document.getElementById('refresh-action')?.addEventListener('click', () => {
vscode.postMessage({ type: 'refresh' })
});
}

function addDropdownListeners() {
// Add event listener for the dropdown
dropdowns.forEach((dropdown, index) =>
dropdown.addEventListener('change', () => {
const versions = message.installed[index].versionInfo;
var selectedText = dropdown.options[dropdown.selectedIndex].text;
const version = versions.find(versionTuple => versionTuple.version === selectedText);
// Change button text based on selected dropdown value
buttons[index].textContent = version.buttonText;

if (dropdown.selectedIndex === 0 && version.version === message.installed[index].currentVersion) {
//This is the first element of the version array thus the most current
buttons[index].disabled = true;
} else {
buttons[index].disabled = false;
}
})
);

buttons.forEach(button => {
button.addEventListener('click', () => {
const action = button.getAttribute('id');
const index = getStringUntilFirstDashFromRight(action);
const drop = document.getElementById("version-select-" + index);
if (drop && drop instanceof HTMLSelectElement) {
var selectedText = drop.options[drop.selectedIndex].text;
// Handle update logic here
vscode.postMessage({ type: 'update', version: selectedText, index: index });
}
});
});

uninstalls.forEach(uninstall => {
uninstall.addEventListener('click', () => {
const action = uninstall.getAttribute('id');
const index = getStringUntilFirstDashFromRight(action);
vscode.postMessage({ type: 'uninstall', index: index });
});
});

installs.forEach(install => {
install.addEventListener('click', () => {
const action = install.getAttribute('id');
const index = getStringUntilFirstDashFromRight(action);
vscode.postMessage({ type: 'install', index: index });
});
});
}

function getStringUntilFirstDashFromRight(str) {
const index = str.lastIndexOf("-");
if (index === -1) {
return str; // No dash found, return the whole string
}
return str.substring(index + 1);
}

addEventListeners();
}());
30 changes: 30 additions & 0 deletions vscode-wpilib/media/reset.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
html {
box-sizing: border-box;
font-size: 13px;
}

*,
*:before,
*:after {
box-sizing: inherit;
}

body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
ol,
ul {
margin: 0;
padding: 0;
font-weight: normal;
}

img {
max-width: 100%;
height: auto;
}
Binary file added vscode-wpilib/media/trash-can-solid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 91 additions & 0 deletions vscode-wpilib/media/vscode.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
:root {
--container-paddding: 20px;
--input-padding-vertical: 6px;
--input-padding-horizontal: 4px;
--input-margin-vertical: 4px;
--input-margin-horizontal: 0;
}

body {
padding: 0 var(--container-paddding);
color: var(--vscode-foreground);
font-size: var(--vscode-font-size);
font-weight: var(--vscode-font-weight);
font-family: var(--vscode-font-family);
background-color: var(--vscode-editor-background);
}

ol,
ul {
padding-left: var(--container-paddding);
}

body > *,
form > * {
margin-block-start: var(--input-margin-vertical);
margin-block-end: var(--input-margin-vertical);
}

*:focus {
outline-color: var(--vscode-focusBorder) !important;
}

a {
color: var(--vscode-textLink-foreground);
}

a:hover,
a:active {
color: var(--vscode-textLink-activeForeground);
}

code {
font-size: var(--vscode-editor-font-size);
font-family: var(--vscode-editor-font-family);
}

button {
border: none;
padding: var(--input-padding-vertical) var(--input-padding-horizontal);
width: 100%;
text-align: center;
outline: 1px solid transparent;
outline-offset: 2px !important;
color: var(--vscode-button-foreground);
background: var(--vscode-button-background);
}

button:hover {
cursor: pointer;
background: var(--vscode-button-hoverBackground);
}

button:focus {
outline-color: var(--vscode-focusBorder);
}

button.secondary {
color: var(--vscode-button-secondaryForeground);
background: var(--vscode-button-secondaryBackground);
}

button.secondary:hover {
background: var(--vscode-button-secondaryHoverBackground);
}

input:not([type='checkbox']),
textarea {
display: block;
width: 100%;
border: none;
font-family: var(--vscode-font-family);
padding: var(--input-padding-vertical) var(--input-padding-horizontal);
color: var(--vscode-input-foreground);
outline-color: var(--vscode-input-border);
background-color: var(--vscode-input-background);
}

input::placeholder,
textarea::placeholder {
color: var(--vscode-input-placeholderForeground);
}
Binary file added vscode-wpilib/media/wpilib.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 25558ec

Please sign in to comment.