From c8325e6e1a31598a4d4dc6a29834fdaefcb31181 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sun, 19 Sep 2021 18:24:52 +0200 Subject: Frontend color changes --- language-web/src/main/css/index.scss | 5 +++++ language-web/src/main/css/themes.scss | 16 +++++++++------- language-web/src/main/js/theme/EditorTheme.ts | 4 ++-- language-web/src/main/js/theme/ThemeStore.ts | 6 +++++- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/language-web/src/main/css/index.scss b/language-web/src/main/css/index.scss index 21a9c05b..9d6e0f6a 100644 --- a/language-web/src/main/css/index.scss +++ b/language-web/src/main/css/index.scss @@ -94,6 +94,11 @@ body { color: map.get($theme, 'delimiter'); } + .cm-comment { + color: map.get($theme, 'comment'); + font-style: italic; + } + .problem-predicate, .problem-class, .problem-reference, .problem-enum { color: map.get($theme, 'predicate'); } diff --git a/language-web/src/main/css/themes.scss b/language-web/src/main/css/themes.scss index 0118290d..a30f1de3 100644 --- a/language-web/src/main/css/themes.scss +++ b/language-web/src/main/css/themes.scss @@ -1,8 +1,8 @@ $themes: ( 'dark': ( 'foreground': #abb2bf, - 'background': #282c34, - 'paper': #21252b, + 'foregroundHighlight': #eeffff, + 'background': #212121, 'primary': #56b6c2, 'secondary': #ff5370, 'keyword': #56b6c2, @@ -10,11 +10,12 @@ $themes: ( 'variable': #c8ae9d, 'uniqueNode': #d6e9ff, 'number': #6e88a6, - 'delimiter': #6f7682, + 'delimiter': #707787, + 'comment': #5c6370, 'cursor': #56b6c2, 'selection': #3e4452, - 'currentLine': #2c323c, - 'lineNumber': #5c6340, + 'currentLine': rgba(0, 0, 0, 0.2), + 'lineNumber': #5c6370, ), 'light': ( 'foreground': #abb2bf, @@ -27,10 +28,11 @@ $themes: ( 'variable': #c8ae9d, 'uniqueNode': #d6e9ff, 'number': #6e88a6, - 'delimiter': #6f7682, + 'delimiter': #56606d, + 'comment': #55606d, 'cursor': #f3efe7, 'selection': #3e4452, 'currentLine': #2c323c, - 'lineNumber': #5c6340, + 'lineNumber': #5c6370, ), ); diff --git a/language-web/src/main/js/theme/EditorTheme.ts b/language-web/src/main/js/theme/EditorTheme.ts index 9420dafa..957f2426 100644 --- a/language-web/src/main/js/theme/EditorTheme.ts +++ b/language-web/src/main/js/theme/EditorTheme.ts @@ -16,9 +16,9 @@ export class EditorThemeData { foreground!: string; - background!: string; + foregroundHighlight!: string; - paper!: string; + background!: string; primary!: string; diff --git a/language-web/src/main/js/theme/ThemeStore.ts b/language-web/src/main/js/theme/ThemeStore.ts index 0f283c98..0e4aeb23 100644 --- a/language-web/src/main/js/theme/ThemeStore.ts +++ b/language-web/src/main/js/theme/ThemeStore.ts @@ -34,7 +34,7 @@ export class ThemeStore { mode: themeData.paletteMode, background: { default: themeData.background, - paper: themeData.paper, + paper: themeData.background, }, primary: { main: themeData.primary, @@ -42,6 +42,10 @@ export class ThemeStore { secondary: { main: themeData.secondary, }, + text: { + primary: themeData.foregroundHighlight, + secondary: themeData.foreground, + }, }, }); return responsiveFontSizes(materialUiTheme); -- cgit v1.2.3-54-g00ecf From 8821ee733365bf3c7db90c4a4f70c8d5761e450c Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sun, 19 Sep 2021 18:36:37 +0200 Subject: Make language-model gets the Xtext nature If the project does not have the Xtext nature, the Problem.xtext file will not be able to load problem.ecore --- language-model/build.gradle | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/language-model/build.gradle b/language-model/build.gradle index 2d9b54b9..3950140c 100644 --- a/language-model/build.gradle +++ b/language-model/build.gradle @@ -31,4 +31,8 @@ task generateEPackage(type: JavaExec) { compileJava.dependsOn(generateEPackage) clean.dependsOn(cleanGenerateEPackage) -eclipse.project.natures += ['org.eclipse.sirius.nature.modelingproject', 'org.eclipse.pde.PluginNature'] +eclipse.project.natures += [ + 'org.eclipse.sirius.nature.modelingproject', + 'org.eclipse.pde.PluginNature', + 'org.eclipse.xtext.ui.shared.xtextNature' +] -- cgit v1.2.3-54-g00ecf From 32b45c00d383a59b200d843bc9772c1501f29ded Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sun, 19 Sep 2021 19:10:53 +0200 Subject: Allow running ServerLauncher from Eclipse --- .../java/org/eclipse/viatra/solver/language/web/ServerLauncher.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java index 2c0413df..a9017264 100644 --- a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java +++ b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java @@ -3,6 +3,7 @@ */ package org.eclipse.viatra.solver.language.web; +import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import java.net.URI; @@ -62,7 +63,8 @@ public class ServerLauncher { } var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html"); if (indexUrlInJar == null) { - throw new IOException("Cannot find pacakged web assets"); + var workingPath = new String[] { System.getProperty("user.dir"), "build", "webpack", "development", }; + return Resource.newResource(new File(String.join(File.separator, workingPath))); } var webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/")); return Resource.newResource(webRootUri); -- cgit v1.2.3-54-g00ecf From 0a118b7f4a16b2e3849fd77eeeaecac0f22128ba Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sun, 19 Sep 2021 19:29:43 +0200 Subject: Allow launching server from Eclipse --- .../org/eclipse/viatra/solver/language/web/ProblemServlet.java | 2 -- .../org/eclipse/viatra/solver/language/web/ServerLauncher.java | 9 +-------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ProblemServlet.java b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ProblemServlet.java index 337df54b..18b86ade 100644 --- a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ProblemServlet.java +++ b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ProblemServlet.java @@ -4,7 +4,6 @@ package org.eclipse.viatra.solver.language.web; import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; import org.eclipse.xtext.util.DisposableRegistry; import org.eclipse.xtext.web.servlet.XtextServlet; @@ -12,7 +11,6 @@ import org.eclipse.xtext.web.servlet.XtextServlet; /** * Deploy this class into a servlet container to enable DSL-specific services. */ -@WebServlet(name = "XtextServices", urlPatterns = "/xtext-service/*") public class ProblemServlet extends XtextServlet { private static final long serialVersionUID = 1L; diff --git a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java index a9017264..63088511 100644 --- a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java +++ b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java @@ -9,15 +9,10 @@ import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; -import org.eclipse.jetty.annotations.AnnotationConfiguration; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.log.Slf4jLog; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.webapp.Configuration; -import org.eclipse.jetty.webapp.MetaInfConfiguration; import org.eclipse.jetty.webapp.WebAppContext; -import org.eclipse.jetty.webapp.WebInfConfiguration; -import org.eclipse.jetty.webapp.WebXmlConfiguration; public class ServerLauncher { private static final Slf4jLog LOG = new Slf4jLog(ServerLauncher.class.getName()); @@ -30,9 +25,7 @@ public class ServerLauncher { ctx.setBaseResource(baseResource); ctx.setWelcomeFiles(new String[] { "index.html" }); ctx.setContextPath("/"); - ctx.setConfigurations(new Configuration[] { new AnnotationConfiguration(), new WebXmlConfiguration(), - new WebInfConfiguration(), new MetaInfConfiguration() }); - ctx.setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, ".*/build/classes/.*,.*\\.jar"); + ctx.addServlet(ProblemServlet.class, "/xtext-service/*"); ctx.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false"); server.setHandler(ctx); } -- cgit v1.2.3-54-g00ecf From 29fec79e948c18493887a627255bd830bd84ec5a Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Mon, 20 Sep 2021 02:11:46 +0200 Subject: Refactor ServerLauncher --- language-web/build.gradle | 24 ++-- .../viatra/solver/language/web/ServerLauncher.java | 134 ++++++++++++++------- .../viatra/solver/language/GenerateProblem.mwe2 | 3 + 3 files changed, 107 insertions(+), 54 deletions(-) diff --git a/language-web/build.gradle b/language-web/build.gradle index a2acb3b0..6910fea0 100644 --- a/language-web/build.gradle +++ b/language-web/build.gradle @@ -7,15 +7,13 @@ dependencies { compile "org.eclipse.xtext:org.eclipse.xtext.web.servlet:${xtextVersion}" compile "org.eclipse.xtend:org.eclipse.xtend.lib:${xtextVersion}" compile "org.eclipse.jetty:jetty-server:${jettyVersion}" - compile "org.eclipse.jetty:jetty-annotations:${jettyVersion}" + compile "org.eclipse.jetty:jetty-servlet:${jettyVersion}" compile "org.slf4j:slf4j-simple:${slf4JVersion}" } def webpackOutputDir = "${buildDir}/webpack" def productionResources = "${webpackOutputDir}/production" def mainClass = 'org.eclipse.viatra.solver.language.web.ServerLauncher' -def devMode = System.getenv('NODE_ENV') != 'production' -def currentNodeEnv = devMode ? 'development' : 'production' apply plugin: 'com.moowork.node' @@ -71,18 +69,21 @@ shadowJar { } task jettyRun(type: JavaExec) { - if (devMode) { - dependsOn webpackDevelopment - } else { - dependsOn webpackProduction - } + shouldRunAfter webpackProduction dependsOn sourceSets.main.runtimeClasspath classpath = sourceSets.main.runtimeClasspath.filter{it.exists()} main = mainClass standardInput = System.in - environment BASE_RESOURCE: "${webpackOutputDir}/${currentNodeEnv}" + environment BASE_RESOURCE: productionResources + group = 'run' + description = 'Start a Jetty web server serving the Xtex API and assets (without rebuilding assets).' +} + +task jettyRunAssets { + dependsOn webpackProduction + dependsOn jettyRun group = 'run' - description = 'Start a Jetty web server serving the Xtex API and assets.' + description = 'Rebuild assets and start a Jetty web server serving the Xtex API and assets.' } task webpackServe(type: NpmTask) { @@ -98,6 +99,9 @@ task webpackServe(type: NpmTask) { task eslint(type: NpmTask) { dependsOn npmInstall args = ['run', 'eslint'] + inputs.dir 'src/main/js' + inputs.file 'tsconfig.json' + inputs.file '.eslintrc.js' group = 'verification' description = 'Checks for TypeScript errors.' } diff --git a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java index 63088511..d92c7735 100644 --- a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java +++ b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java @@ -8,26 +8,62 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; +import java.util.Set; + +import javax.servlet.SessionTrackingMode; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.session.SessionHandler; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.log.Slf4jLog; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.webapp.WebAppContext; public class ServerLauncher { + public static final String DEFAULT_LISTEN_ADDRESS = "localhost"; + + public static final int DEFAULT_LISTEN_PORT = 1312; + + // Use this cookie name for load balancing. + public static final String SESSION_COOKIE_NAME = "JSESSIONID"; + private static final Slf4jLog LOG = new Slf4jLog(ServerLauncher.class.getName()); private final Server server; public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource) { server = new Server(bindAddress); - var ctx = new WebAppContext(); - ctx.setBaseResource(baseResource); - ctx.setWelcomeFiles(new String[] { "index.html" }); - ctx.setContextPath("/"); - ctx.addServlet(ProblemServlet.class, "/xtext-service/*"); - ctx.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false"); - server.setHandler(ctx); + var handler = new ServletContextHandler(); + addSessionHandler(handler); + addProblemServlet(handler); + if (baseResource != null) { + handler.setBaseResource(baseResource); + handler.setWelcomeFiles(new String[] { "index.html" }); + addDefaultServlet(handler); + } + server.setHandler(handler); + } + + private void addSessionHandler(ServletContextHandler handler) { + var sessionHandler = new SessionHandler(); + sessionHandler.setSessionTrackingModes(Set.of(SessionTrackingMode.COOKIE)); + sessionHandler.setSessionCookie(SESSION_COOKIE_NAME); + handler.setSessionHandler(sessionHandler); + } + + private void addProblemServlet(ServletContextHandler handler) { + handler.addServlet(ProblemServlet.class, "/xtext-service/*"); + } + + private void addDefaultServlet(ServletContextHandler handler) { + var defaultServletHolder = new ServletHolder(DefaultServlet.class); + var isWindows = System.getProperty("os.name").toLowerCase().contains("win"); + // Avoid file locking on Windows: https://stackoverflow.com/a/4985717 + // See also the related Jetty ticket: + // https://github.com/eclipse/jetty.project/issues/2925 + defaultServletHolder.setInitParameter("useFileMappedBuffer", isWindows ? "false" : "true"); + handler.addServlet(defaultServletHolder, "/"); } public void start() throws Exception { @@ -38,55 +74,65 @@ public class ServerLauncher { if (key != -1) { server.stop(); } else { - LOG.warn( - "Console input is not available. In order to stop the server, you need to cancel process manually."); + LOG.warn("Console input is not available. " + + "In order to stop the server, you need to cancel process manually."); } } - private static InetSocketAddress getBindAddress(String listenAddress, int port) { - if (listenAddress == null) { - return new InetSocketAddress(port); - } - return new InetSocketAddress(listenAddress, port); - } - - private static Resource getBaseResource(String baseResourceOverride) throws IOException, URISyntaxException { - if (baseResourceOverride != null) { - return Resource.newResource(baseResourceOverride); - } - var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html"); - if (indexUrlInJar == null) { - var workingPath = new String[] { System.getProperty("user.dir"), "build", "webpack", "development", }; - return Resource.newResource(new File(String.join(File.separator, workingPath))); + public static void main(String[] args) { + try { + var bindAddress = getBindAddress(); + var baseResource = getBaseResource(); + var serverLauncher = new ServerLauncher(bindAddress, baseResource); + serverLauncher.start(); + } catch (Exception exception) { + LOG.warn(exception); + System.exit(1); } - var webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/")); - return Resource.newResource(webRootUri); } - public static void main(String[] args) { + private static String getListenAddress() { var listenAddress = System.getenv("LISTEN_ADDRESS"); if (listenAddress == null) { - listenAddress = "localhost"; + return DEFAULT_LISTEN_ADDRESS; } - var port = 1312; + return listenAddress; + } + + private static int getListenPort() { var portStr = System.getenv("LISTEN_PORT"); if (portStr != null) { - try { - port = Integer.parseInt(portStr); - } catch (NumberFormatException e) { - LOG.warn(e); - System.exit(1); - } + return Integer.parseInt(portStr); } + return DEFAULT_LISTEN_PORT; + } + + private static InetSocketAddress getBindAddress() { + var listenAddress = getListenAddress(); + var listenPort = getListenPort(); + return new InetSocketAddress(listenAddress, listenPort); + } + + private static Resource getBaseResource() throws IOException, URISyntaxException { var baseResourceOverride = System.getenv("BASE_RESOURCE"); - try { - var bindAddress = getBindAddress(listenAddress, port); - var baseResource = getBaseResource(baseResourceOverride); - var serverLauncher = new ServerLauncher(bindAddress, baseResource); - serverLauncher.start(); - } catch (Exception exception) { - LOG.warn(exception); - System.exit(1); + if (baseResourceOverride != null) { + // If a user override is provided, use it. + return Resource.newResource(baseResourceOverride); + } + var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html"); + if (indexUrlInJar != null) { + // If the app is packaged in the jar, serve it. + var webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/")); + return Resource.newResource(webRootUri); + } + // Look for unpacked production artifacts (convenience for running from IDE). + var unpackedResourcePathComponents = new String[] { System.getProperty("user.dir"), "build", "webpack", + "production" }; + var unpackedResourceDir = new File(String.join(File.separator, unpackedResourcePathComponents)); + if (unpackedResourceDir.isDirectory()) { + return Resource.newResource(unpackedResourceDir); } + // Fall back to just serving a 404. + return null; } } diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2 b/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2 index ca3e2665..9b0bcd41 100644 --- a/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2 +++ b/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2 @@ -53,6 +53,9 @@ Workflow { webSupport = ProblemWebIntegrationFragment { highlightingPath = "js/mode-problem.js" generateHtmlExample = false + generateJettyLauncher = false + generateServlet = false + generateWebXml = false } } } -- cgit v1.2.3-54-g00ecf From cdb64c525b7e289a562cabeb72f26a298d2b4e22 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Mon, 20 Sep 2021 02:21:33 +0200 Subject: Force LF line endings in frontend files eslint will signal an error if Git adds CRLF line endings to TypeScript files on Windows. --- .gitattributes | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..63f6b190 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +*.css eol=lf +*.js eol=lf +*.json eol=lf +*.jsx eol=lf +*.scss eol=lf +*.ts eol=lf +*.tsx eol=lf -- cgit v1.2.3-54-g00ecf