Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
JannisDommer committed Jan 10, 2024
2 parents b395704 + 1932dd7 commit b3f7faa
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 112 deletions.
6 changes: 3 additions & 3 deletions WebSocketClient/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ COPY . .
RUN npm run build

# Install Nginx
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get clean
RUN apt-get update \
&& apt-get install -y nginx \
&& apt-get clean

# Copy your static files into the Nginx document root directory
RUN cp -r dist/* /var/www/html/
Expand Down
16 changes: 8 additions & 8 deletions WebSocketClient/assets/uvlTutorialContent.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export const tutorialContent = [{
title: "Welcome",
text: "<p>Welcome to the UVL Tutorial! </br>All code listings will automatically be placed in the editor on the left. Click <b>'Next'</b> to start the tutorial.</p>"
text: "<p>Welcome to the UVL Tutorial! </br>In the following, code listings will be inserted into the editor for further explanation. <span class='warning'>Please be aware that your progress may be lost.</span></br> Click <b>'Next'</b> to start the tutorial.</p>"
}, {
title: "Basic Feature Model",
text: "<p>Start with the <b><tt>features</tt></b> key word to start enumerating your features. Indentations matter in UVL and represent the tree structure.</br>We will start with a basic feature model that represents a computer. Every computer needs a CPU and can optionally have some devices connected via SATA.</p>",
text: "<p>Start with the <b><code class='keyword'>features</code></b> key word to start enumerating your features. Indentations matter in UVL and represent the tree structure.</br>We will start with a basic feature model that represents a computer. Every computer needs a CPU and can optionally have some devices connected via SATA.</p>",
codeListing: `features
Computer
mandatory
Expand All @@ -12,7 +12,7 @@ export const tutorialContent = [{
SATADevices`
}, {
title: "Special Feature Names",
text: "<p>To use special characters or spaces in feature names use <b><tt>\"</tt></b> to enclose the names.</br>In this example we write <b><tt>SATA-Devices</tt></b> with a dash instead of <b><tt>SATADevices</tt></b>.</p>",
text: "<p>To use special characters or spaces in feature names use quotes (<b><code class='literal'>\"</code></b>) to enclose the names.</br>In this example we write <b><code class='literal'>SATA-Devices</code></b> with a dash instead of <b><code class='literal'>SATADevices</code></b>.</p>",
codeListing: `features
Computer
mandatory
Expand All @@ -21,7 +21,7 @@ export const tutorialContent = [{
"SATA-Devices"`
}, {
title: "Basic Constraints",
text: "<p>Use the <b><tt>constraints</tt></b> keyword to start the section of constraints. In its basic form, a constraint uses propositional logic.</br>In this example, we enforce that if a computer contains a dedicated graphics card, it must also use liquid cooling. We do that with the <b><tt>=></tt></b> symbol to represent an implication.</br>Other logic connectors are <b><tt>&</tt></b>, <b><tt>|</tt></b>, <b><tt>not</tt></b></p>",
text: "<p>Use the <b><code class='keyword'>constraints</code></b> keyword to start the section of constraints. In its basic form, a constraint uses propositional logic.</br>In this example, we enforce that if a computer contains a dedicated graphics card, it must also use liquid cooling. We do that with the <b><code>=></code></b> symbol to represent an implication.</br>Other logic connectors are <b><code>&</code></b>, <b><code>|</code></b>, <b><code>not</code></b></p>",
codeListing: `features
Computer
mandatory
Expand All @@ -41,7 +41,7 @@ constraints
Dedicated => Liquid`
}, {
title: "Feature Attributes",
text: "<p>Features can have attributes in curly brackets as key value pairs. The value can be omitted if it is a boolean attribute and the value is true. This is the case for the <b><tt>abstract</tt></b> attribute in the feature <b><tt>Computer</tt></b>. We also use attributes to indicate the power consumption of different parts of the computer.</p>",
text: "<p>Features can have attributes in curly brackets as key value pairs. The value can be omitted if it is a boolean attribute and the value is true. This is the case for the <b><code class='qualifier'>abstract</code></b> attribute in the feature <b><code class='literal'>Computer</code></b>. We also use attributes to indicate the power consumption of different parts of the computer.</p>",
codeListing: `features
Computer {abstract}
mandatory
Expand All @@ -61,7 +61,7 @@ constraints
Dedicated => Liquid`
}, {
title: "Complex Constraints",
text: "<p>We can now create more complex constraints and for example access attributes of features. In this case we use the aggregate function <b><tt>sum</tt></b> to sum over all powerConsumption attributes and check if the overall <b><tt>powerConsumption</tt></b> is larger than a threshold and if so enforce a stronger power supply unit. You could also access feature attributes and perform basic calculations with them.</p>",
text: "<p>We can now create more complex constraints and for example access attributes of features. In this case we use the aggregate function <b><code>sum</code></b> to sum over all powerConsumption attributes and check if the overall <b><code class='qualifier'>powerConsumption</code></b> is larger than a threshold and if so enforce a stronger power supply unit. You could also access feature attributes and perform basic calculations with them.</p>",
codeListing: `features
Computer {abstract}
mandatory
Expand All @@ -86,7 +86,7 @@ constraints
sum(powerConsumption) > 300 => StrongPSU`
}, {
title: "Group Cardinality",
text: "<p>Group cardinalities are more generic than <b><tt>or</tt></b> and <b><tt>alternative</tt></b>.</br>In our example, the motherboard only has space for up to 2 SATA-Devices. So we enforce that there are 0, 1, or 2 SATA-Devices.</p>",
text: "<p>Group cardinalities are more generic than <b><code class='keyword'>or</code></b> and <b><code class='keyword'>alternative</code></b>.</br>In our example, the motherboard only has space for up to 2 SATA-Devices. So we enforce that there are 0, 1, or 2 SATA-Devices.</p>",
codeListing: `features
Computer {abstract}
mandatory
Expand Down Expand Up @@ -145,7 +145,7 @@ constraints
sum(powerConsumption) > 300 => StrongPSU`
}, {
title: "Types",
text: "<p>In UVL, you can use types to create special features. In this case, we change the power supply unit. It has a <b><tt>Manufacturer</tt></b> feature of the type <b><tt>String</tt></b> and a <b><tt>Watt</tt></b> feature of the type <b><tt>Integer</tt></b>.</br>This means, when configuring the feature model, the features are not just selected or deselected, but get a value of their corresponding type. We can utilize this for even more complex constraints and check if the manufacturer of the CPU and the PSU match.</p>",
text: "<p>In UVL, you can use types to create special features. In this case, we change the power supply unit. It has a <b><code class='qualifier'>Manufacturer</code></b> feature of the type <b><code>String</code></b> and a <b><code class='qualifier'>Watt</code></b> feature of the type <b><code>Integer</code></b>.</br>This means, when configuring the feature model, the features are not just selected or deselected, but get a value of their corresponding type. We can utilize this for even more complex constraints and check if the manufacturer of the CPU and the PSU match.</p>",
codeListing: `features
Computer {abstract}
mandatory
Expand Down
17 changes: 6 additions & 11 deletions WebSocketClient/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ <h1>UVL Playground</h1>
</div>
</div>
</div>

<div class="dropdown">
<div class="dropdown-wrapper">
<span>Select an Example</span>
Expand All @@ -36,6 +37,7 @@ <h1>UVL Playground</h1>
</div>
</div>
</div>

<div>
<dialog id="dialog">
<div>
Expand All @@ -55,12 +57,11 @@ <h1>Get the UVLS VSCode Extension</h1>
<div>
<button id="uploadClose">X</button>
</div>



</dialog>
</div>

<input type="file" id="uploadInput" accept=".uvl">

<div id="main-div" style="display: flex;">
<div id="splitter" class="splitter">
<div id="first">
Expand All @@ -82,11 +83,12 @@ <h1>Get the UVLS VSCode Extension</h1>
href="https://github.com/Universal-Variability-Language/uvl-lsp">UVL Language Server</a>. To fully
use all features use the UVLS - Universal Variability Language Server extension for visual studio code. </p>
</div>

<script type="module">
import {startUvlClient} from "./src/main.ts";

startUvlClient();
</script>

<script>
// A function is used for dragging and moving
function dragElement(element, direction) {
Expand All @@ -97,7 +99,6 @@ <h1>Get the UVLS VSCode Extension</h1>
element.onmousedown = onMouseDown;

function onMouseDown(e) {
//console.log("mouse down: " + e.clientX);
md = {
e,
offsetLeft: element.offsetLeft,
Expand All @@ -108,13 +109,11 @@ <h1>Get the UVLS VSCode Extension</h1>

document.onmousemove = onMouseMove;
document.onmouseup = () => {
//console.log("mouse up");
document.onmousemove = document.onmouseup = null;
}
}

function onMouseMove(e) {
//console.log("mouse move: " + e.clientX);
var delta = {
x: e.clientX - md.e.clientX,
y: e.clientY - md.e.clientY
Expand All @@ -133,11 +132,7 @@ <h1>Get the UVLS VSCode Extension</h1>
}
}


dragElement(document.getElementById("separator"), "H");
</script>
<script>

</script>
</body>
</html>
9 changes: 6 additions & 3 deletions WebSocketClient/src/ImportExportFiles.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import config from './config';
import {displayEditorErrorAtContent} from "./util.ts";

export function downloadFile(content: string, filename: string): void {
// Create a Blob from the file content
Expand Down Expand Up @@ -30,15 +31,17 @@ export function uploadFile(): Promise<string> {
return new Promise<string>((resolve, reject) => {
uploadInput.onchange = () => {
if(!uploadInput.files){
reject();
reject("Cannot reach HTML-Input field");
return;
}
const file = uploadInput.files[0];
let stringPromise = file.text();
uploadInput.files = null;
uploadInput.value = "";
stringPromise.then((res) => {
if(res.length > config.MAX_NUMBER_LINES){
const lineCount = res.split('\n').length;
if(lineCount > config.MAX_NUMBER_LINES){
displayEditorErrorAtContent(`The Editor only allows content up to ${config.MAX_NUMBER_LINES} Lines!`);
resolve(res.split('\n').slice(0, config.MAX_NUMBER_LINES - 1).reduce((acc, curr) => acc + curr + "\n", ""));
}else{
resolve(res);
Expand All @@ -48,5 +51,5 @@ export function uploadFile(): Promise<string> {
};
})
}
return new Promise((_resolve, reject) => reject());
return Promise.reject("Cannot reach HTML-Input field");
}
11 changes: 3 additions & 8 deletions WebSocketClient/src/intro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ import { sendGenerateGraphCommand } from "./main";


export const initIntroJS = () => {


var intro = introJs();
const intro = introJs();

intro.setOptions({
steps: [{
element: '#container', intro: 'This is the text editor where you write and edit your UVL feature model. It will assist you with syntax highlighting, autocompletion and more features.',
element: '#container', intro: 'This is the text editor where you write and edit your UVL feature model. It will assist you with syntax highlighting, autocompletion and more features.\n Please note: The editor limits the content length as it is not intended for larger projects.',
}, {
element: '.codelens-decoration', intro: 'You can click on the buttons to use a variety of features.'
}, {
Expand Down Expand Up @@ -41,14 +39,11 @@ export const initIntroJS = () => {
intro.setOption("highlightClass", "tmpClass");
intro.start();

var helperLayer = document.getElementsByClassName("tmpClass");
const helperLayer = document.getElementsByClassName("tmpClass");
setTimeout(() => {
if(helperLayer[0] instanceof HTMLElement){
helperLayer[0].style["box-shadow"] = "rgb(255, 255, 255) 0px 0px 1px 2px, rgba(230, 230, 230, 0.44) 0px 0px 0px 5000px";
}
}, 100);


});

}
54 changes: 32 additions & 22 deletions WebSocketClient/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@ import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-
import getThemeServiceOverride from '@codingame/monaco-vscode-theme-service-override';
import getTextmateServiceOverride from '@codingame/monaco-vscode-textmate-service-override';
import {initServices, MonacoLanguageClient} from 'monaco-languageclient';
import {CloseAction, ErrorAction, MessageTransports} from 'vscode-languageclient';
import {CloseAction, ErrorAction, ExecuteCommandSignature, MessageTransports} from 'vscode-languageclient';
import {toSocket, WebSocketMessageReader, WebSocketMessageWriter} from 'vscode-ws-jsonrpc';
import {
RegisteredFileSystemProvider,
RegisteredMemoryFile,
registerFileSystemOverlay
RegisteredFileSystemProvider, RegisteredMemoryFile, registerFileSystemOverlay
} from 'vscode/service-override/files';
import config from './config.js';
import {instance} from "@viz-js/viz";
Expand All @@ -30,11 +28,10 @@ import initUvlTutorial from './uvlTutorial.ts';

import {buildWorkerDefinition} from 'monaco-editor-workers';
import {initIntroJS} from "./intro.ts";
import {ExecuteCommandSignature} from "vscode-languageclient";
import {downloadFile, uploadFile} from "./ImportExportFiles.ts";
import IIdentifiedSingleEditOperation = editor.IIdentifiedSingleEditOperation;
import {initExamples} from "./examples.ts";
import {aggregateCharacters, displayEditorError, displayEditorErrorAtContent} from "./util.ts";
import IIdentifiedSingleEditOperation = editor.IIdentifiedSingleEditOperation;

buildWorkerDefinition('./node_modules/monaco-editor-workers/dist/workers', new URL('', window.location.href).href, false);

Expand All @@ -52,7 +49,7 @@ const createUrl = (hostname: string, port: number, path: string, secure: boolean

const createWebSocket = (url: string): WebSocket => {
const webSocket = new WebSocket(url);

webSocket.onerror = () => {
displayEditorError("Could not connect to language server. Reconnecting ...");
setTimeout(() => {
Expand All @@ -75,14 +72,17 @@ const createWebSocket = (url: string): WebSocket => {
}, 500);
});
};

return webSocket;
};

function onExecuteCommand(command: string, args: any[], client: MonacoLanguageClient, next: ExecuteCommandSignature) {
const information = {command: command, arguments: args};
debounceGenGraph = lodash.debounce(() => {
client?.sendRequest(ExecuteCommandRequest.type, {command: "uvls/generate_diagram", arguments: [`file:///workspace/${fileID}.uvl`]}).then((res) => {
client?.sendRequest(ExecuteCommandRequest.type, {
command: "uvls/generate_diagram",
arguments: [`file:///workspace/${fileID}.uvl`]
}).then((res) => {
createDiagramFromDot(res as string);
});
}, 500);
Expand Down Expand Up @@ -124,7 +124,6 @@ function onExecuteCommand(command: string, args: any[], client: MonacoLanguageCl
secondPane.style.width = "0%";
}
}

} else {
next(command, args);
}
Expand All @@ -144,8 +143,10 @@ const createLanguageClient = (transports: MessageTransports): MonacoLanguageClie
});
vscode.commands.registerCommand("uvlPlayground/downloadFile", () => {
const model1 = globalEditor?.getModel();
if(model1){
downloadFile(model1.getLinesContent().reduce((prev, curr) => {return prev+curr+'\n'}, ""), fileID);
if (model1) {
downloadFile(model1.getLinesContent().reduce((prev, curr) => {
return prev + curr + '\n'
}, ""), fileID);
}
});
const client = new MonacoLanguageClient({
Expand Down Expand Up @@ -178,20 +179,27 @@ const createLanguageClient = (transports: MessageTransports): MonacoLanguageClie
middleware: {
executeCommand(command, args, next) {
onExecuteCommand(command, args, client, next);
},
provideCodeLenses(document, token, next): ProviderResult<CodeLens[]> {
}, provideCodeLenses(document, token, next): ProviderResult<CodeLens[]> {
const results = next(document, token);
if(results instanceof Promise){
if (results instanceof Promise) {
results.then((codeLenses: CodeLens[]) => {
codeLenses.forEach((codeLens) => {
if (codeLens.command?.title === "generate graph"){
if (codeLens.command?.title === "generate graph") {
codeLens.command.title = updateGraph ? "Hide Feature Model" : "Show Feature Model";
}
});
const command1: vscode.Command = {title: "Download File", command: "uvlPlayground/downloadFile", tooltip: "Download a File"}
const command1: vscode.Command = {
title: "Download File",
command: "uvlPlayground/downloadFile",
tooltip: "Download a File"
}
const codeLens1: CodeLens = new CodeLens(codeLenses[0].range, command1);
codeLenses.push(codeLens1);
const command: vscode.Command = {title: "Upload File", command: "uvlPlayground/uploadFile", tooltip: "Upload a File"}
const command: vscode.Command = {
title: "Upload File",
command: "uvlPlayground/uploadFile",
tooltip: "Upload a File"
}
const codeLens: CodeLens = new CodeLens(codeLenses[0].range, command);
codeLenses.push(codeLens);
})
Expand All @@ -213,7 +221,7 @@ const createLanguageClient = (transports: MessageTransports): MonacoLanguageClie
function createDiagramFromDot(res: string): void {
instance().then(viz => {
const div = document.getElementsByClassName("graph");
let svg = viz.renderSVGElement(res!);
let svg = viz.renderSVGElement(res);
svg.id = "SVGGraph";
div[0].replaceChildren(svg);
});
Expand Down Expand Up @@ -287,8 +295,7 @@ export const startUvlClient = async () => {
} else if (numberCharacters > config.MAX_NUMBER_CHARACTERS) {
if (numberCharacters > config.MAX_NUMBER_CHARACTERS + 1) {
vscode.commands.executeCommand("undo");
}
else {
} else {
vscode.commands.executeCommand("deleteLeft");
}
displayEditorErrorAtContent(`The Editor only allows content up to ${config.MAX_NUMBER_CHARACTERS} Characters!`);
Expand All @@ -308,7 +315,10 @@ export const startUvlClient = async () => {
};

let debounceGenGraph = lodash.debounce(() => {
languageClient?.sendRequest(ExecuteCommandRequest.type, {command: "uvls/generate_diagram", arguments: [`file:///workspace/${fileID}.uvl`]}).then((res) => {
languageClient?.sendRequest(ExecuteCommandRequest.type, {
command: "uvls/generate_diagram",
arguments: [`file:///workspace/${fileID}.uvl`]
}).then((res) => {
createDiagramFromDot(res as string);
});
}, 500);
Expand Down
2 changes: 1 addition & 1 deletion WebSocketClient/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function displayEditorErrorAtContent(msg: string) {
debounceRemoveWidget();
}

const debounceRemoveWidget = lodash.debounce(removeWidget, 2000);
const debounceRemoveWidget = lodash.debounce(removeWidget, 5000);

function removeWidget() {
if (currentContentWidget) {
Expand Down
Loading

0 comments on commit b3f7faa

Please sign in to comment.