retrieve & show information from index.yaml
This commit is contained in:
parent
51f97f8702
commit
033f5e1b8d
66
app/Index.hs
Normal file
66
app/Index.hs
Normal file
@ -0,0 +1,66 @@
|
||||
{-# Language DuplicateRecordFields,
|
||||
NoFieldSelectors,
|
||||
OverloadedRecordDot,
|
||||
OverloadedStrings,
|
||||
DeriveGeneric #-}
|
||||
|
||||
module Index where
|
||||
|
||||
import Data.Yaml
|
||||
import Control.Applicative hiding (empty)
|
||||
import GHC.Generics (Generic)
|
||||
import Data.Map
|
||||
import Data.Maybe (fromMaybe, fromJust)
|
||||
|
||||
type Index = Map String Entry
|
||||
|
||||
data Entry = Entry {
|
||||
graphFile :: String,
|
||||
category :: Maybe String,
|
||||
defScope :: Maybe String,
|
||||
defDescription :: Maybe Description,
|
||||
instDescription :: Maybe Description,
|
||||
instances :: Value
|
||||
} deriving (Show, Generic)
|
||||
|
||||
instance FromJSON Entry where
|
||||
parseJSON (Object o) = Entry <$>
|
||||
o .: "graph-file" <*>
|
||||
o .:? "category" <*>
|
||||
o .:? "definition-scope" <*>
|
||||
o .:? "definition-description" <*>
|
||||
o .:? "instance-description" <*>
|
||||
o .: "instances"
|
||||
parseJSON _ = error "Unexpected yaml"
|
||||
|
||||
type Title = String
|
||||
type Content = String
|
||||
|
||||
data Description = Description {
|
||||
fallbackLang :: Maybe String,
|
||||
fallback :: (Maybe Title, Maybe Content),
|
||||
translations :: Map String (Maybe Title, Maybe Content)
|
||||
} deriving (Show, Generic)
|
||||
|
||||
instance FromJSON Description where
|
||||
parseJSON (Object o) = Description <$>
|
||||
o .:? "fallback-lang" <*>
|
||||
o .: "fallback" <*>
|
||||
o .: "translations"
|
||||
|
||||
english = "en-eu";
|
||||
|
||||
getDefDescription :: Entry -> (Maybe Title, Maybe Content)
|
||||
getDefDescription entry = let description = fromJust entry.defDescription
|
||||
def = description.fallback
|
||||
in findWithDefault def english description.translations
|
||||
getInstDescription :: Entry -> (Maybe Title, Maybe Content)
|
||||
getInstDescription entry = let description = fromJust entry.instDescription
|
||||
def = description.fallback
|
||||
in findWithDefault def english description.translations
|
||||
|
||||
getEntryByFile :: String -> Index -> Entry
|
||||
getEntryByFile file index = query (elems index) file where
|
||||
query :: [Entry] -> String -> Entry
|
||||
query [] _ = error $ "No entries left for " ++ file
|
||||
query (x:xs) file = if x.graphFile == file then x else query xs file
|
||||
54
app/Main.hs
54
app/Main.hs
@ -10,11 +10,14 @@ module Main where
|
||||
import qualified Data.ByteString.Char8 as BS
|
||||
import Workflow (Workflow, buildData)
|
||||
import Export
|
||||
import Data.Maybe (fromJust, isNothing)
|
||||
import Data.Maybe (fromJust, isNothing, isJust, fromMaybe)
|
||||
import Data.Either (isLeft, fromLeft, fromRight)
|
||||
import Data.List (dropWhileEnd)
|
||||
import Control.Exception (throw)
|
||||
import Text.Regex.TDFA ((=~))
|
||||
|
||||
import Index (Index, Entry (Entry), getDefDescription, getInstDescription, getEntryByFile)
|
||||
import Data.Char (isSpace)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
|
||||
@ -38,8 +41,8 @@ module Main where
|
||||
-- exports the graph data to the JSON file specified in the second argument.
|
||||
generateJSON :: [String] -> IO ()
|
||||
generateJSON args = do
|
||||
print $ head args
|
||||
print $ last args
|
||||
-- print $ head args
|
||||
-- print $ last args
|
||||
content <- BS.readFile (head args)
|
||||
let decoded = decodeEither' content :: Either ParseException Workflow
|
||||
if isLeft decoded then throw (fromLeft undefined decoded) else do
|
||||
@ -60,33 +63,44 @@ module Main where
|
||||
processDirectory src to = listDirectory src >>= filterWorkflows >>= (\ x -> generateForAll x [] Nothing) where
|
||||
filterWorkflows :: [FilePath] -> IO [FilePath]
|
||||
filterWorkflows entries = return $ filter (=~ ".+\\.yaml") entries
|
||||
generateForAll :: [FilePath] -> [FilePath] -> Maybe FilePath -> IO () -- sources -> targets -> _index.yaml
|
||||
generateForAll :: [FilePath] -> [(String, FilePath)] -> Maybe FilePath -> IO () -- sources -> targets -> _index.yaml
|
||||
generateForAll [] _ Nothing = fail "_index.yaml not found"
|
||||
generateForAll [] targets (Just index) = writeIndex (decodeIndex index) targets "]"
|
||||
generateForAll (x:xs) targets index = let (rel, abs) = defineTarget x
|
||||
generateForAll [] targets (Just index) = decodeIndex index >>= \x -> writeIndex x targets "]"
|
||||
generateForAll (x:xs) targets index = let (yaml, rel, abs) = defineTarget x
|
||||
(newIndex, skip) = case index of
|
||||
Just _ -> (index, False)
|
||||
Nothing -> if x =~ ".+index\\.yaml" then (Just x, True) else (Nothing, False)
|
||||
Nothing -> if x =~ ".+index\\.yaml" then (Just $ src ++ "/" ++ x, True) else (Nothing, False)
|
||||
in if skip || x `elem` blackList
|
||||
then generateForAll xs targets newIndex
|
||||
else generateJSON [src ++ "/" ++ x, abs] >> generateForAll xs (rel:targets) newIndex
|
||||
defineTarget :: FilePath -> (FilePath, FilePath) -- (rel, abs)
|
||||
else generateJSON [src ++ "/" ++ x, abs] >> generateForAll xs ((yaml, rel):targets) newIndex
|
||||
defineTarget :: FilePath -> (String, FilePath, FilePath) -- (src, rel, abs)
|
||||
defineTarget x = let (path, match, _) = x =~ "[a-zA-Z0-9+._-]+\\.yaml" :: (String, String, String)
|
||||
(newFile, _, _) = match =~ "\\." :: (String, String, String)
|
||||
relative = "/definitions/" ++ newFile ++ ".json"
|
||||
absolute = to ++ relative
|
||||
in (relative, absolute)
|
||||
writeIndex :: Value -> [FilePath] -> String -> IO () -- content of _index.yaml -> targets -> content for index.json
|
||||
writeIndex _ [] content = writeFile (to ++ "/index.json") ('[':content)
|
||||
writeIndex index (x:xs) content = let name = x
|
||||
url = x
|
||||
description = ""
|
||||
newContent = (if null xs then "" else ",\n") ++ "{\n\"name\": \"" ++ name
|
||||
in (match, relative, absolute)
|
||||
writeIndex :: Index -> [(String, FilePath)] -> String -> IO () -- content of _index.yaml -> targets -> content for index.json
|
||||
writeIndex index [] content = print index >> writeFile (to ++ "/index.json") ('[':content)
|
||||
writeIndex index (x:xs) content = let entry = findEntry (fst x) index
|
||||
(name1, description1) = getDefDescription entry
|
||||
(name2, description2) = getInstDescription entry
|
||||
name = if isJust name1 then name1 else name2
|
||||
description = if isJust description1 then description1 else description2
|
||||
url = snd x
|
||||
format = dropWhileEnd isSpace . map (\y -> if y == '\n' then ' ' else y)
|
||||
newContent = (if null xs then "" else ",\n") ++ "{\n\"name\": \"" ++ format (fromMaybe (snd x) name)
|
||||
++ "\",\n\"description\": \""
|
||||
++ description ++ "\",\n\"url\": \"" ++ url ++ "\"}"
|
||||
++ format (fromMaybe "" description) ++ "\",\n\"url\": \"" ++ url ++ "\"}"
|
||||
in writeIndex index xs (newContent ++ content)
|
||||
decodeIndex :: FilePath -> Value
|
||||
decodeIndex _ = Null
|
||||
decodeIndex :: FilePath -> IO Index
|
||||
decodeIndex path = do
|
||||
content <- BS.readFile path
|
||||
let decoded = decodeEither' content :: Either ParseException Index
|
||||
if isLeft decoded
|
||||
then throw (fromLeft undefined decoded)
|
||||
else return $ fromRight undefined decoded
|
||||
findEntry :: String -> Index -> Entry
|
||||
findEntry file index = getEntryByFile file index
|
||||
|
||||
|
||||
---------------------------------------
|
||||
|
||||
18
editor.css
18
editor.css
@ -307,11 +307,27 @@ label {
|
||||
color: white;
|
||||
transition: all 100ms ease-in-out 0ms;
|
||||
cursor: pointer;
|
||||
text-align: justify;
|
||||
hyphens: auto;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
text-overflow: clip;
|
||||
overflow-wrap: break-word;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#filecontent div h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* #filecontent div p {
|
||||
text-align: left;
|
||||
margin-bottom: 10px;
|
||||
hyphens: auto;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
} */
|
||||
|
||||
#curtain {
|
||||
z-index: 50;
|
||||
position: fixed;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Editor</title>
|
||||
<!-- <script src="//unpkg.com/force-graph"></script> -->
|
||||
<script src="https://unpkg.com/force-graph@1.43.0/dist/force-graph.min.js"></script>
|
||||
<!-- <script src="./force-graph-master/src/force-graph.js"></script> -->
|
||||
|
||||
10
editor.js
10
editor.js
@ -128,7 +128,7 @@ var workflowFiles = [];
|
||||
var workflow = {};
|
||||
const wfGraph = ForceGraph();
|
||||
|
||||
function defineOnClick(item, url) {
|
||||
function defineOnClick(item, url, title) {
|
||||
item.onclick = (_ => {
|
||||
fetch(url)
|
||||
.then(response => response.json())
|
||||
@ -138,6 +138,7 @@ function defineOnClick(item, url) {
|
||||
workflow[key] = data[key];
|
||||
prepareWorkflow();
|
||||
updateGraph();
|
||||
document.title = title;
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -148,16 +149,17 @@ fetch('http://localhost:8080/index.json')
|
||||
workflowFiles = data;
|
||||
for (var i = 0; i < workflowFiles.length; i++) {
|
||||
var item = document.createElement('div');
|
||||
item.innerHTML = workflowFiles[i].name;
|
||||
item.innerHTML = '<h3>' + workflowFiles[i].name + '</h3>' + workflowFiles[i].description;
|
||||
var url = 'http://localhost:8080' + workflowFiles[i].url;
|
||||
defineOnClick(item, url);
|
||||
defineOnClick(item, url, workflowFiles[i].name + ' | Editor');
|
||||
fileContent.appendChild(item);
|
||||
}
|
||||
var url = 'http://localhost:8080' + data[0].url;
|
||||
var url = 'http://localhost:8080' + workflowFiles[0].url;
|
||||
return fetch(url);
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
document.title = workflowFiles[0].name + ' | Editor';
|
||||
for (var key in data)
|
||||
workflow[key] = data[key];
|
||||
wfGraph(document.getElementById('graph')).graphData({nodes: workflow.states, links: workflow.actions});
|
||||
|
||||
@ -26,7 +26,8 @@ executable workflow-visualiser
|
||||
|
||||
-- Modules included in this executable, other than Main.
|
||||
other-modules: Workflow,
|
||||
Export
|
||||
Export,
|
||||
Index
|
||||
|
||||
-- LANGUAGE extensions used by modules in this package.
|
||||
-- other-extensions:
|
||||
|
||||
@ -1,40 +1,40 @@
|
||||
[{
|
||||
"name": "/definitions/theses.json",
|
||||
"description": "",
|
||||
"name": "Theses Informatics (IfI)",
|
||||
"description": "Registration, management, and digital submission of (bachelor's and master's) theses",
|
||||
"url": "/definitions/theses.json"},
|
||||
{
|
||||
"name": "/definitions/theses-media.json",
|
||||
"description": "",
|
||||
"name": "Theses Media Informatics (IfI)",
|
||||
"description": "Registration, management, and digital submission of (bachelor's and master's) theses",
|
||||
"url": "/definitions/theses-media.json"},
|
||||
{
|
||||
"name": "/definitions/rooms-mi.json",
|
||||
"description": "",
|
||||
"name": "Reporting of Room Allocation (MI)",
|
||||
"description": "<p> Here, members of staff charged to do so, can report the alloction of offices within their area of competence. </p>",
|
||||
"url": "/definitions/rooms-mi.json"},
|
||||
{
|
||||
"name": "/definitions/recognitions-ifi.json",
|
||||
"description": "",
|
||||
"name": "Recognitions (IfI)",
|
||||
"description": "Apply here for standard recognitions. Please follow the instructions and help texts provided. For complex recognitions that cannot be handled here, please send an email or apply in the programme-coordination-consultation hours.",
|
||||
"url": "/definitions/recognitions-ifi.json"},
|
||||
{
|
||||
"name": "/definitions/master-practical-training.json",
|
||||
"description": "",
|
||||
"name": "Master individual practical training (IfI)",
|
||||
"description": "Here you can report grades for an individual practical training as part of the master informatics.",
|
||||
"url": "/definitions/master-practical-training.json"},
|
||||
{
|
||||
"name": "/definitions/general-eo-tickets.json",
|
||||
"description": "",
|
||||
"name": "General Exam-Office-Tickets",
|
||||
"description": "Here you can view all the general exam-office-tickets that concern you.",
|
||||
"url": "/definitions/general-eo-tickets.json"},
|
||||
{
|
||||
"name": "/definitions/diploma.json",
|
||||
"description": "",
|
||||
"name": "Diplomas (IfI)",
|
||||
"description": "Here you can view the status of your diploma",
|
||||
"url": "/definitions/diploma.json"},
|
||||
{
|
||||
"name": "/definitions/cs-minor-degrees.json",
|
||||
"description": "",
|
||||
"name": "Computer Science minor degrees (IfI)",
|
||||
"description": "Here you can request your degree for the following minor degree programmes: - Minor Bachelor Computer Science, 30 ECTS - Minor Bachelor Computer Science, 60 ECTS - Minor Bachelor Mediainformatics, 60 ECTS - Minor Master Computer Science, 30 ECTS",
|
||||
"url": "/definitions/cs-minor-degrees.json"},
|
||||
{
|
||||
"name": "/definitions/cip-courses-mi.json",
|
||||
"description": "",
|
||||
"name": "Registration for CIP introductory course (MI, S22)",
|
||||
"description": "<p> Hier können Sie sich für die ca. einstündige Einführungsveranstaltung anmelden, die Voraussetzung ist um die CIP-Rechner am Mathematischen Institut verwenden zu können. </p> <p> Eine entsprechende Kennung wird Ihnen im Rahmen der Einführungsveranstaltung zugeteilt. </p> <p> Berechtigt für Kennungen sind Studierende, die an der Fakultät 16 in einem (Wirtschafts-)Mathematikstudiengang eingeschrieben sind und Lehramtsstudierende mit Unterrichtsfach Mathematik. </p> <p> Falls Sie bereits eine Kennung zugeteilt bekommen haben und Sie diese nur vergessen haben, brauchen Sie nicht erneut an einer Einführungsveranstaltung teilzunehmen.<br /> Kommen Sie in diesem Fall bitte einfach in die CIP-Betreuung. </p>",
|
||||
"url": "/definitions/cip-courses-mi.json"},
|
||||
{
|
||||
"name": "/definitions/certificates.json",
|
||||
"description": "",
|
||||
"name": "Certificates (IfI)",
|
||||
"description": "Submission and application of certain certificates.",
|
||||
"url": "/definitions/certificates.json"}]
|
||||
Loading…
Reference in New Issue
Block a user