diff --git a/Handler/Shared.hs b/Handler/Shared.hs index 41f2e92..ad530ab 100644 --- a/Handler/Shared.hs +++ b/Handler/Shared.hs @@ -96,7 +96,13 @@ browsableGitRepo bareRepoName runViewProgress :: (Channel -> Handler ()) -> Handler TypedContent -runViewProgress = runViewProgress' ViewProgressR +runViewProgress action = do + app <- getYesod + let viewingProgressStyle = appViewingProgressStyle $ appSettings app + runViewProgress' (case viewingProgressStyle of + WithWebSockets -> ViewProgressWithWebSocketsR + WithPlainText -> ViewProgressR) + action runOpenViewProgress :: (Channel -> Handler ()) -> Handler TypedContent runOpenViewProgress = runViewProgress' OpenViewProgressR @@ -147,6 +153,10 @@ getViewProgressWithWebSocketsR jobId = do background-color: black; padding: 10pt; } + #outwindow pre { + color: white; + background-color: black; + } #wait { animation: blink 1s linear infinite; } @@ -172,7 +182,7 @@ getViewProgressWithWebSocketsR jobId = do conn = new WebSocket(url); conn.onmessage = function(e) { - var p = document.createElement("p"); + var p = document.createElement("pre"); p.appendChild(document.createTextNode(e.data)); output.appendChild(p); }; diff --git a/Handler/ShowChallenge.hs b/Handler/ShowChallenge.hs index ac6d001..a5612de 100644 --- a/Handler/ShowChallenge.hs +++ b/Handler/ShowChallenge.hs @@ -1334,12 +1334,12 @@ challengeLayout withHeader challenge widget = do $(widgetFile "challenge") getTestProgressR :: Int -> Handler TypedContent -getTestProgressR m = runViewProgressWithWebSockets $ doTestProgress m +getTestProgressR m = runViewProgress $ doTestProgress m doTestProgress :: Int -> Channel -> Handler () doTestProgress m chan = do forM [1..m] $ (\i -> do - msg chan $ (Data.Text.pack $ show i) + msg chan $ (Data.Text.pack $ ("GO\n" ++ show i)) liftIO $ threadDelay 1000000 return ()) return () diff --git a/Settings.hs b/Settings.hs index fcedb22..cf64414 100644 --- a/Settings.hs +++ b/Settings.hs @@ -42,6 +42,17 @@ toLeaderboardStyle :: Text -> LeaderboardStyle toLeaderboardStyle "by-tag" = ByTag toLeaderboardStyle _ = BySubmitter +-- How showing progress for asynchronous operations +-- such as creating a challenge, submitting a submission, etc. +-- is realized technically. +data ViewingProgressStyle = WithWebSockets | WithPlainText + deriving (Eq, Show) + +toViewingProgressStyle :: Text -> ViewingProgressStyle +toViewingProgressStyle "with-web-sockets" = WithWebSockets +toViewingProgressStyle _ = WithPlainText + + -- | Runtime settings to configure this application. These settings can be -- loaded from various sources: defaults, environment variables, config files, -- theoretically even a database. @@ -96,6 +107,7 @@ data AppSettings = AppSettings -- ^ Are challenges, submission, etc. visible without logging in , appIsPublic :: Bool , appJSONWebKey :: Maybe JWK.Jwk + , appViewingProgressStyle :: ViewingProgressStyle } instance FromJSON AppSettings where @@ -143,6 +155,8 @@ instance FromJSON AppSettings where appJSONWebKey <- o .:? "json-web-key" + appViewingProgressStyle <- toViewingProgressStyle <$> o .: "viewing-progress-style" + return AppSettings {..} -- | Settings for 'widgetFile', such as which template languages to support and diff --git a/config/settings.yml b/config/settings.yml index 7b4040f..d511a44 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -17,6 +17,15 @@ new-best-result-slack-hook: "_env:NEW_BEST_RESULT_SLACK_HOOK:" server-ssh-public-key: "_env:SERVER_SSH_PUBLIC_KEY:" is-public: "_env:IS_PUBLIC:true" +# How the output of asynchronous operations is presented +# - with-plain-text - just plain text shown by the browser; +# pros: it works with anything, cons: with NGINX the output +# is not shown progressively, only when it is finished +# - with-web-sockets - using web sockets and JavaScripts, pros: +# nicer visually, fully works with NGINX, cons: does not work +# with lighttpd +viewing-progress-style: "_env:VIEWING_PROGRESS_STYLE:with-plain-text" + # Optional values with the following production defaults. # In development, they default to the inverse. # diff --git a/docker-compose.yml b/docker-compose.yml index eefcddb..5301898 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,6 +26,7 @@ services: - AUTO_OPENING=${GONITO_AUTO_OPENING:-false} - IS_PUBLIC=${GONITO_IS_PUBLIC:-true} - JSON_WEB_KEY=${JSON_WEB_KEY} + - VIEWING_PROGRESS_STYLE=${GONITO_VIEWING_PROGRESS_STYLE:-with-web-sockets} expose: - "3000" volumes: diff --git a/nginx.conf b/nginx.conf index d21ba9f..b85c32a 100644 --- a/nginx.conf +++ b/nginx.conf @@ -22,10 +22,11 @@ http { proxy_pass http://gonito; proxy_redirect off; - proxy_read_timeout 600; - proxy_connect_timeout 600; + proxy_read_timeout 6000; + proxy_connect_timeout 6000; proxy_http_version 1.1; - proxy_set_header Connection ""; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; } listen 443 ssl; diff --git a/sample.env b/sample.env index 9164e3a..5df5516 100644 --- a/sample.env +++ b/sample.env @@ -10,4 +10,5 @@ GONITO_AUTO_OPENING=false NGINX_CERTIFICATE_DIR=/home/user/certs GONITO_IS_PUBLIC=true GONITO_SSH_DIRECTORY=/home/user/.ssh +GONITO_VIEWING_PROGRESS_STYLE=with-web-sockets JSON_WEB_KEY="{\"kty\":\"RSA\", \"alg\":\"RS256\", \"use\":\"sig\", \"kid\":\"h01jmt_bD-1Di8i_GYbEV2a4NxhptzySHO-R8VuNHVA\", \"e\":\"AQAB\", \"n\": \"qG1elE6KPW3BYMxNpgK73MoksvbrUSfpRY4z9hU5iMsJREyD5Ar6XpjM1xAr6G7xglnOoumPC9o6FqhDHihm6QdJ5s5MA9ZyGkbi--kvy9Qc2d_VIGU-UR4vwyk3hAwXOFLhoknpQrJBJmMQvGFdas1Yr-m9EIWwT1zN7neHZkRUYZSVyQw_XghtMIWAUsLnhr6mM7nstHLafgxe5Qamzuc4K5EC_qipFXu4ugYkMDnaknlhkT43m7tcduVDnv5GV_4dBesF7FRII8tgUQWyw3Ty_FIoq43SInUPU_9cxA-qPGQz5C50th2aJl1z1snpLWS_1Zfsa8lnFsMj8_oh6w\"}"