diff --git a/advanced/package-lock.json b/advanced/package-lock.json index aa81bef4e8bf03fabf245f0380583d3c58352564..07923732df901b670bd05f4b680f0b206501025b 100644 --- a/advanced/package-lock.json +++ b/advanced/package-lock.json @@ -18,9 +18,12 @@ "react": "^18.2.0", "react-bootstrap": "^2.9.1", "react-dom": "^18.2.0", + "react-gauge-chart": "^0.4.1", "react-grid-layout": "^1.4.4", "react-router-dom": "^6.20.1", + "react-stars": "^2.2.5", "react-syntax-highlighter": "^15.5.0", + "react-tabulator": "^0.19.0", "typewriter-effect": "^2.21.0" }, "devDependencies": { @@ -6976,6 +6979,14 @@ "node": ">= 10" } }, + "node_modules/@types/babel__traverse": { + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -7162,6 +7173,14 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-tag-autocomplete": { + "version": "5.12.6", + "resolved": "https://registry.npmjs.org/@types/react-tag-autocomplete/-/react-tag-autocomplete-5.12.6.tgz", + "integrity": "sha512-7TH9bghG+O3fwiyUrpriUs9wrOs744ilay+omshoH9ZzzDOSrNDoGmE0SfFtsxxOe5si93riFc3KHCptzzNQFQ==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.10", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", @@ -8488,6 +8507,384 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/d3": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", + "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -8573,6 +8970,14 @@ "node": ">=8" } }, + "node_modules/delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "dependencies": { + "robust-predicates": "^3.0.0" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -8713,6 +9118,17 @@ "tslib": "^2.0.3" } }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -8813,6 +9229,11 @@ "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", "dev": true }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -9611,6 +10032,15 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/html-attributes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/html-attributes/-/html-attributes-1.1.0.tgz", + "integrity": "sha512-reT/KK6Ju+DZqAbAn3sIkpMH+658kEsaEjpNrej2O5XSUsH5SzVHX7NGZk5RiZcVi7l+RsV+5q3C6TqM5vxsVA==", + "engines": { + "node": ">= 0.10.26", + "npm": ">=1.4.3" + } + }, "node_modules/html-entities": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", @@ -9823,8 +10253,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -9976,6 +10404,14 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/interpret": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", @@ -10348,6 +10784,11 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -11515,6 +11956,16 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, + "node_modules/pick-react-known-prop": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/pick-react-known-prop/-/pick-react-known-prop-0.1.5.tgz", + "integrity": "sha512-SnDf64AVdvqoAFpHeZUKT9kdn40Ellj84CPALRxYWqNJ6r6f44eAAT+Jtkb0Suhiw7yg5BdOFAQ25OJnjG+afw==", + "dependencies": { + "html-attributes": "^1.1.0", + "lodash.isplainobject": "^4.0.6", + "svg-attributes": "^1.0.0" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -11920,6 +12371,18 @@ "node": ">=6" } }, + "node_modules/react-gauge-chart": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/react-gauge-chart/-/react-gauge-chart-0.4.1.tgz", + "integrity": "sha512-xc1pQ6tF3shRpjyzIGA5EeQcRNfjy5og6Ory5fUe9cWChw8ZadaONMnUIpGHdfUefF+Ffzh6HAZuOX5+AMzOzw==", + "dependencies": { + "d3": "^7.6.1" + }, + "peerDependencies": { + "react": "^16.8.2 || ^17.0 || ^18.x", + "react-dom": "^16.8.2 || ^17.0 || ^18.x" + } + }, "node_modules/react-grid-layout": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.4.4.tgz", @@ -11989,6 +12452,11 @@ "react-dom": ">=16.8" } }, + "node_modules/react-stars": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/react-stars/-/react-stars-2.2.5.tgz", + "integrity": "sha512-O//KS6Z9RZnUOU/r+3+wxCzNalVn/wEWIcbAQFRV3dw8WbV+ys/kgcpBPijqTiNpHGrcwZdtb/7wF/UVem20CQ==" + }, "node_modules/react-syntax-highlighter": { "version": "15.5.0", "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz", @@ -12004,6 +12472,34 @@ "react": ">= 0.14.0" } }, + "node_modules/react-tabulator": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/react-tabulator/-/react-tabulator-0.19.0.tgz", + "integrity": "sha512-I9cHN9Iblnda2TBG9xLgWnQ3MW5GoZJLgy+Knjab28Zt+4UHeDc5eblLr8nypP8b2t7eFK9TRz9GVvwIxIRqpQ==", + "dependencies": { + "@types/babel__traverse": "^7.17.1", + "@types/react-tag-autocomplete": "^5.6.0", + "dotenv": "^16.3.1", + "es6-promise": "^4.2.8", + "pick-react-known-prop": "^0.1.5", + "react-tag-autocomplete": "^5.7.1", + "tabulator-tables": "5.5.2" + }, + "peerDependencies": { + "react": ">=15.6.2 || ^16.0.0 || ^17.0.0", + "react-dom": ">=15.6.2 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/react-tabulator/node_modules/react-tag-autocomplete": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/react-tag-autocomplete/-/react-tag-autocomplete-5.13.1.tgz", + "integrity": "sha512-ECcQnizAxw8VnEDUfCKuA2ZDQ0Fyxds3kVtE4NVAhJvBYOMMgkRNAM3UwyEXAQ0h7nnCwmIA+czJiwso07Mrqw==", + "peerDependencies": { + "prop-types": "^15.0.0", + "react": "^15.0.0 || ^16.0.0", + "react-dom": "^15.0.0 || ^16.0.0" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -12413,6 +12909,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -12436,8 +12942,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass-graph": { "version": "4.0.1", @@ -13106,6 +13611,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-attributes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-attributes/-/svg-attributes-1.0.0.tgz", + "integrity": "sha512-opDCROGf0kXDKJFg0so8Ydg2jewgaWRuF/35Xxuqox54Rg12rR7pLnRaru06NfJ5WCxjUSRjT5AGcikxMmzG6g==", + "engines": { + "node": ">= 0.10.26", + "npm": ">=1.4.3" + } + }, + "node_modules/tabulator-tables": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-5.5.2.tgz", + "integrity": "sha512-GlzUPXeH9Rw1iPXcl3uBLJk6Sz51xdwscZ5RrsKxDQDQ+t2g31hGq/0xjaj6ea62wHgl8vzVsHuwap0jKzsUNg==" + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", diff --git a/advanced/package.json b/advanced/package.json index fc97545aa1bf2f4aff3eed29626aec0b48f40924..bc47084365879bfa3a6b2b6bf8e60db03379c472 100644 --- a/advanced/package.json +++ b/advanced/package.json @@ -36,9 +36,12 @@ "react": "^18.2.0", "react-bootstrap": "^2.9.1", "react-dom": "^18.2.0", + "react-gauge-chart": "^0.4.1", "react-grid-layout": "^1.4.4", "react-router-dom": "^6.20.1", + "react-stars": "^2.2.5", "react-syntax-highlighter": "^15.5.0", + "react-tabulator": "^0.19.0", "typewriter-effect": "^2.21.0" } } diff --git a/advanced/src/app/components/PolarisDashboard.js b/advanced/src/app/components/PolarisDashboard.js index 0915624910d973da7f447cd6aff97991b9289d14..7c42b9e1f1a8b140bc46dd9574a543ff4f3bf49b 100644 --- a/advanced/src/app/components/PolarisDashboard.js +++ b/advanced/src/app/components/PolarisDashboard.js @@ -37,6 +37,10 @@ export default function PolarisDashboard({config}) { let tempLayout = []; Object.keys(config?.widgets).forEach((key, _) => { tempLayout.push({x: 0, y: 0, w: 2, h: 2, ...config?.widgets[key]?.layout, i: key})}) + if(debug) + { + console.log("[DEBUG] layout calculation: " + tempLayout) + } setLayout(tempLayout); } diff --git a/advanced/src/app/components/ratings/PolarisStarModal.js b/advanced/src/app/components/ratings/PolarisStarModal.js new file mode 100644 index 0000000000000000000000000000000000000000..03b0e2df5e77af1f0c49b79bf676a76e29ed911b --- /dev/null +++ b/advanced/src/app/components/ratings/PolarisStarModal.js @@ -0,0 +1,34 @@ +import React, { useState } from "react"; +import { Button, Modal } from "react-bootstrap"; +import ReactStars from 'react-stars' + +export default function PolarisStarModal({show, onHide, configuration}) +{ + let [rating, setRating] = useState(3); + + + return <Modal show={show} onHide={onHide}> + <Modal.Header closeButton> + <Modal.Title> + {configuration?.title ?? "Wie finden Sie dieses Element?"}</Modal.Title> + </Modal.Header> + <Modal.Body> + {configuration?.descriptionText} + <div className="ms-auto me-auto"> + <ReactStars + count={configuration?.maxStars ?? 5} + value={rating} + onChange={(evt) => setRating(evt)} + size={50} + color2={'#ffd700'} /></div> + </Modal.Body> + <Modal.Footer> + <Button variant="secondary" onClick={onHide}> + Abbrechen + </Button> + <Button variant="primary" onClick={onHide}> + {configuration?.submitButton ?? "Feedback absenden"} + </Button> + </Modal.Footer> + </Modal> +} \ No newline at end of file diff --git a/advanced/src/app/components/ratings/PolarisTextRatingModal.js b/advanced/src/app/components/ratings/PolarisTextRatingModal.js new file mode 100644 index 0000000000000000000000000000000000000000..4a11b1c1f201f2682e7a936bccc79047faa5b9c7 --- /dev/null +++ b/advanced/src/app/components/ratings/PolarisTextRatingModal.js @@ -0,0 +1,28 @@ +import React, { useState } from "react"; +import { Button, Form, FormControl, Modal } from "react-bootstrap"; +import ReactStars from 'react-stars' + +export default function PolarisTextRatingModal({show, onHide, configuration}) +{ + let [text, setText] = useState(undefined); + + + return <Modal show={show} onHide={onHide}> + <Modal.Header closeButton> + <Modal.Title> + {configuration?.title ?? "Wie finden Sie dieses Element?"}</Modal.Title> + </Modal.Header> + <Modal.Body> + {configuration?.descriptionText} + <Form.Control onChange={(evt) => setText(evt.target.value)} as="textarea" rows={configuration?.rows ?? 3} placeholder={configuration?.placeholder ?? "Bitte bewerten Sie das Element"} /> + </Modal.Body> + <Modal.Footer> + <Button variant="secondary" onClick={onHide}> + Abbrechen + </Button> + <Button variant="primary" onClick={onHide}> + {configuration?.submitButton ?? "Feedback absenden"} + </Button> + </Modal.Footer> + </Modal> +} \ No newline at end of file diff --git a/advanced/src/app/components/widgets/PolarisBaseWidget.js b/advanced/src/app/components/widgets/PolarisBaseWidget.js index e5461a0f7e8db46a148674769562ed79d16b81c8..2ba39b01536d7ea9261723d1f91fc98521d1173d 100644 --- a/advanced/src/app/components/widgets/PolarisBaseWidget.js +++ b/advanced/src/app/components/widgets/PolarisBaseWidget.js @@ -1,12 +1,21 @@ import React from "react"; import PolarisBaseCard from "./PolarisBaseCard"; import { FontAwesomeIcon, solid } from "@fortawesome/react-fontawesome"; -import { faStar, faThumbsDown, faThumbsUp } from "@fortawesome/free-solid-svg-icons"; +import { faExclamation, faExclamationCircle, faStar, faThumbsDown, faThumbsUp } from "@fortawesome/free-solid-svg-icons"; import PolarisLineChart from "./PolarisLineChart"; import PolarisBarChart from "./PolarisBarChart"; +import PolarisStarModal from "../ratings/PolarisStarModal"; +import PolarisTextRatingModal from "../ratings/PolarisTextRatingModal"; +import PolarisGuageChart from "./PolarisGuageChart"; +import PolarisFormCard from "./PolarisFormCard"; export default class PolarisBaseWidget extends React.Component { + constructor(props) { + super(props); + this.state = {showStarRatingModal: false, showTextRatingModal: false}; + } + render() { console.log(this.props) return <div style={{height: "100%"}} className={this.props.isResizable || this.props.isDraggable ? "db-shaking": ""} > @@ -17,11 +26,20 @@ export default class PolarisBaseWidget extends React.Component { </div> : null } {!this.props.isDraggable && !this.props.isResizable && this.props.config.feedback?.mode == "star" ? <div className="d-flex" style={{position:"absolute", zIndex: 10, right: "5px", color: this.props.config.feedback?.color == "light" ? "#fff": "#000"}}> - <FontAwesomeIcon icon={faStar} className="m-1" onClick={(evt) => { evt.preventDefault() }} /> + <FontAwesomeIcon icon={faStar} className="m-1" onClick={(evt) => { evt.preventDefault(); this.setState({ showStarRatingModal: true }) }} /> + </div>: null} + + {!this.props.isDraggable && !this.props.isResizable && this.props.config.feedback?.mode == "text" ? + <div className="d-flex" style={{position:"absolute", zIndex: 10, right: "5px", color: this.props.config.feedback?.color == "light" ? "#fff": "#000"}}> + <FontAwesomeIcon icon={faExclamationCircle} className="m-1" onClick={(evt) => { evt.preventDefault(); this.setState({ showTextRatingModal: true }) }} /> </div>: null} {this.props.config?.type === "card" ? <PolarisBaseCard parameters={this.props.config?.parameters}/> : null} {this.props.config?.type === "lineChart" ? <PolarisLineChart parameters={this.props.config?.parameters} isEdit={this.props.isResizable || this.props.isDraggable}/> : null} {this.props.config?.type === "barChart" ? <PolarisBarChart parameters={this.props.config?.parameters} isEdit={this.props.isResizable || this.props.isDraggable}/> : null} + {this.props.config?.type === "guageChart" ? <PolarisGuageChart parameters={this.props.config?.parameters} isEdit={this.props.isResizable || this.props.isDraggable}/> : null} + {this.props.config?.type === "form" ? <PolarisFormCard parameters={this.props.config?.parameters} isEdit={this.props.isResizable || this.props.isDraggable}/> : null} + <PolarisStarModal onHide={() => this.setState({ showStarRatingModal: false})} show={this.state.showStarRatingModal} configuration={this.props.config.feedback}/> + <PolarisTextRatingModal onHide={() => this.setState({ showTextRatingModal: false})} show={this.state.showTextRatingModal} configuration={this.props.config.feedback} /> </div> } } \ No newline at end of file diff --git a/advanced/src/app/components/widgets/PolarisFormCard.js b/advanced/src/app/components/widgets/PolarisFormCard.js new file mode 100644 index 0000000000000000000000000000000000000000..267b92f62ba177281050441a46d08ee24946def5 --- /dev/null +++ b/advanced/src/app/components/widgets/PolarisFormCard.js @@ -0,0 +1,24 @@ +import React from "react"; +import { Card, Form } from "react-bootstrap"; + +export default function PolarisFormCard({parameters}) +{ + return <Card style={{ height: "100%"}} bg={parameters.variant} + text={parameters.variant == null || parameters.variant.toLowerCase() === 'light' ? 'dark' : 'white'}> + <Card.Body> + <Card.Title> + {parameters.headline}</Card.Title> + <Card.Text dangerouslySetInnerHTML={{ __html: parameters.body}}></Card.Text> + <Form> + <Form.Group className="mb-3" controlId="exampleForm.ControlInput1"> + <Form.Label>Einfaches Textfeld</Form.Label> + <Form.Control type="text" placeholder="" /> + </Form.Group> + <Form.Group className="mb-3" controlId="exampleForm.ControlTextarea1"> + <Form.Label>Textarea</Form.Label> + <Form.Control as="textarea" rows={3} /> + </Form.Group> + </Form> + </Card.Body> + </Card> +} \ No newline at end of file diff --git a/advanced/src/app/components/widgets/PolarisGuageChart.js b/advanced/src/app/components/widgets/PolarisGuageChart.js new file mode 100644 index 0000000000000000000000000000000000000000..59e440c210a92534cbbe986f5c2be99ba022a209 --- /dev/null +++ b/advanced/src/app/components/widgets/PolarisGuageChart.js @@ -0,0 +1,20 @@ +import React from "react"; +import { Card } from "react-bootstrap"; +import GaugeChart from 'react-gauge-chart' + +export default function PolarisGuageChart({parameters, isEdit}) +{ + + return <Card style={{height: "100%"}} bg={parameters.variant} + text={parameters.variant == null || parameters.variant.toLowerCase() === 'light' ? 'dark' : 'white'}> + <Card.Body> + <Card.Title> + {parameters.headline}</Card.Title> +<GaugeChart id="gauge-chart2" + nrOfLevels={parameters?.data?.nrOfLevels} + percent={parameters?.data?.percent} +/> + </Card.Body> + + </Card> +} \ No newline at end of file diff --git a/advanced/src/app/layout/layout.js b/advanced/src/app/layout/layout.js index ba7e252322fec3483f2801c80426904729afb2d6..a558a9a5dbfccc07482387d5248132e472d03ab5 100644 --- a/advanced/src/app/layout/layout.js +++ b/advanced/src/app/layout/layout.js @@ -7,20 +7,27 @@ export default function Layout() { <> <Navbar expand="lg" bg="primary" data-bs-theme="dark"> <Container fluid> - <Navbar.Brand href="/">Polaris Dashboard</Navbar.Brand> + <Navbar.Brand href="/">POLARIS Dashboard</Navbar.Brand> <Navbar.Toggle aria-controls="basic-navbar-nav" /> <Navbar.Collapse id="basic-navbar-nav"> <Nav className="me-auto"> <Nav.Link href="/">Home</Nav.Link> - <Nav.Link href="#link">Datenerfassung</Nav.Link> + <Nav.Link href="/manualData">Datenerfassung</Nav.Link> <NavDropdown title="Dashboards" id="basic-nav-dropdown"> <NavDropdown.Item href="/dashboard/1">Dashboard Base SDK</NavDropdown.Item> - <NavDropdown.Item href="/dashboard/2">Dashboard Advanced SDK - </NavDropdown.Item> + <NavDropdown.Item href="/dashboard/2">Dashboard Advanced SDK</NavDropdown.Item> + <NavDropdown.Item href="/dashboard/3">Dashboard Advanced SDK mit Rights Engine</NavDropdown.Item> + <NavDropdown.Item href="/dashboard/4">Dashboard Advanced SDK mit Formularen</NavDropdown.Item> </NavDropdown> <NavDropdown title="Entwickler Tools" id="basic-nav-dropdown"> - <NavDropdown.Item href="#action/3.1">xAPI Statements Viewer</NavDropdown.Item> + <NavDropdown.Item href="/xapiviewer">xAPI Statements Viewer</NavDropdown.Item> + </NavDropdown> + </Nav> + <Nav> + <NavDropdown title="Angemeldet als user@polaris.com" id="user-account"> + {/* <NavDropdown.Item href="/about">Über diese Seite</NavDropdown.Item> */} + <NavDropdown.Item href="/login">Abmelden</NavDropdown.Item> </NavDropdown> </Nav> </Navbar.Collapse> diff --git a/advanced/src/app/pages/dashboard_2.js b/advanced/src/app/pages/dashboard_2.js index c35eefc0c9cb8a0d3a26bd426a9121554f0a5fea..4565596078d22e23136c70209799519ba0b3576c 100644 --- a/advanced/src/app/pages/dashboard_2.js +++ b/advanced/src/app/pages/dashboard_2.js @@ -17,8 +17,6 @@ export default function Dashboard2() { const dashboardConfig = { "id": "new-unique-id", "name": "Simple Dashboard", - "visualisationToken": "", - "rights_engine": "https://polaris.digitallearning.gmbh", "grid": { "cols": 6 }, @@ -36,8 +34,6 @@ export default function Dashboard2() { const dashboardConfig2 = { "id": "new-unique-id", "name": "Simple Dashboard", - "visualisationToken": "", - "rights_engine": "https://polaris.digitallearning.gmbh", "widgets": { "welcome-card": { "type": "card", @@ -64,8 +60,6 @@ export default function Dashboard2() { const dashboardConfig3 = { "id": "new-unique-id", "name": "Simple Dashboard", - "visualisationToken": "", - "rights_engine": "https://polaris.digitallearning.gmbh", "interaction": { "allowEdit": true, "allowRemove": true, @@ -97,8 +91,6 @@ export default function Dashboard2() { const dashboardConfig4 = { "id": "new-unique-id", "name": "Simple Dashboard", - "visualisationToken": "", - "rights_engine": "https://polaris.digitallearning.gmbh", "widgets": { "no-rating-card": { "type": "card", @@ -133,6 +125,18 @@ export default function Dashboard2() { "mode": "star", "color": "light", } + }, + "text-card": { + "type": "card", + "parameters": { + "headline": "Diese Karte kann per Freitext bewertet werden", + "body": "Diese Karte kann man mit einem Freitext bewerten", + "variant": "secondary", + }, + "feedback": { + "mode": "text", + "color": "light", + } } } }; @@ -140,8 +144,6 @@ export default function Dashboard2() { const dashboardConfig5 = { "id": "new-unique-id", "name": "Simple Dashboard", - "visualisationToken": "", - "rights_engine": "https://polaris.digitallearning.gmbh", "interaction": { "allowEdit": true, "allowRemove": true, @@ -184,8 +186,6 @@ export default function Dashboard2() { const dashboardConfig6 = { "id": "new-unique-id", "name": "Simple Dashboard", - "visualisationToken": "", - "rights_engine": "https://polaris.digitallearning.gmbh", "interaction": { "allowEdit": true, "allowRemove": true, @@ -242,6 +242,21 @@ export default function Dashboard2() { "w": 4 } }, + "guagechart": { + "type": "guageChart", + "parameters": { + "headline": "A sample guage chart", + "description": "Beschreibung", + "data" : { + "nrOfLevels": 20, + "percent": 0.80 + } + }, + "layout": { + "w": 4, + "h": 2 + } + }, } }; diff --git a/advanced/src/app/pages/dashboard_3.js b/advanced/src/app/pages/dashboard_3.js new file mode 100644 index 0000000000000000000000000000000000000000..51b647b3aeca2fd34e132c913f4331545eb478c6 --- /dev/null +++ b/advanced/src/app/pages/dashboard_3.js @@ -0,0 +1,137 @@ +import React, { useEffect } from 'react'; +import {mockBarChart, mockChartJSBarChart} from "../../mock_charts/mock_bar_chart"; +import {mockGrid} from "../../mock_charts/mock_grid"; +import {mockScatterGrid} from "../../mock_charts/mock_scatter_grid"; +import {mockPieGrid} from "../../mock_charts/mock_pie_grid"; +import {mockDeadlines} from "../../mock_charts/mock_deadlines"; +import {mockProgressHeat} from "../../mock_charts/mock_progress_heat"; +import {mockProgressBox} from "../../mock_charts/mock_progress_box"; +import {mockFeedback} from "../../mock_charts/mock_feedback"; +import GridLayout from "react-grid-layout"; +import PolarisDashboard from '../components/PolarisDashboard'; +import PolarisDashboardSplitView from '../components/PolarisDashboardSplitView'; + + +export default function Dashboard3() { + + const dashboardConfig = { + "id": "new-unique-id", + "name": "Simple Dashboard", + "visualisationToken": "", + "rights_engine": "https://polaris.digitallearning.gmbh", + "grid": { + "cols": 6 + }, + "interaction": { + "allowEdit": true, + "allowRemove": true, + "allowAdd": true, + "autoSave": true, + }, + "widgets": { + "welcome-card": { + "type": "card", + "parameters": { + "headline": "Das ist eine einfache Karte", + "body": "Hier könnte ein erklärender Text stehen" + } + }, + "info-card": { + "type": "card", + "parameters": { + "headline": "Das ist eine zweite Karte", + "body": "Diese Karte kann man bewerten und man kann HTML verwenden <b>HTML</b>", + "variant": "primary", + }, + "feedback": { + "mode": "thumbs", + "color": "light", + } + } + } + }; + + const dashboardConfig2 = { + "id": "new-unique-id", + "name": "Simple Dashboard", + "visualisationToken": "", + "rights_engine": "https://polaris.digitallearning.gmbh", + "grid": { + "cols": 6 + }, + "interaction": { + "allowEdit": true, + "allowRemove": true, + "allowAdd": true, + "autoSave": true, + "feedback": { + "addWidget": true, + "removeWidget": true, + "reorderWidgets": true, + } + }, + "widgets": { + "welcome-card": { + "type": "card", + "parameters": { + "headline": "Das ist eine einfache Karte", + "body": "Hier könnte ein erklärender Text stehen" + } + }, + "primary-card": { + "type": "card", + "parameters": { + "headline": "Das ist eine zweite Karte", + "body": "Diese Karte kann HTML verwenden <b>HTML</b>", + "variant": "primary", + } + }, + "secondary-card": { + "type": "card", + "parameters": { + "headline": "Das ist eine zweite Karte", + "body": "Diese Karte kann HTML verwenden <b>HTML</b>", + "variant": "secondary", + } + }, + "warning-card": { + "type": "card", + "parameters": { + "headline": "Das ist eine zweite Karte", + "body": "Diese Karte kann HTML verwenden <b>HTML</b>", + "variant": "warning", + }, + "layout": { + "w": 4, + "h": 4 + } + }, + "alert-card": { + "type": "card", + "parameters": { + "headline": "Das ist eine zweite Karte", + "body": "Diese Karte kann HTML verwenden <b>HTML</b>", + "variant": "danger", + } + }, + "info-card": { + "type": "card", + "parameters": { + "headline": "Das ist eine zweite Karte", + "body": "Diese Karte kann HTML verwenden <b>HTML</b>", + "variant": "info", + }, + "layout": { + "w": 4 + } + } + } + }; + + + return <> + <PolarisDashboardSplitView config={dashboardConfig} title={"Base example with auto save"}/> + <PolarisDashboardSplitView config={dashboardConfig2} title={"Base example dashboard as data provider"}/> + </> + +} \ No newline at end of file diff --git a/advanced/src/app/pages/dashboard_4.js b/advanced/src/app/pages/dashboard_4.js new file mode 100644 index 0000000000000000000000000000000000000000..88c74fdfacab240a13a4a5f32f867de95a672076 --- /dev/null +++ b/advanced/src/app/pages/dashboard_4.js @@ -0,0 +1,61 @@ +import React, { useEffect } from 'react'; +import {mockBarChart, mockChartJSBarChart} from "../../mock_charts/mock_bar_chart"; +import {mockGrid} from "../../mock_charts/mock_grid"; +import {mockScatterGrid} from "../../mock_charts/mock_scatter_grid"; +import {mockPieGrid} from "../../mock_charts/mock_pie_grid"; +import {mockDeadlines} from "../../mock_charts/mock_deadlines"; +import {mockProgressHeat} from "../../mock_charts/mock_progress_heat"; +import {mockProgressBox} from "../../mock_charts/mock_progress_box"; +import {mockFeedback} from "../../mock_charts/mock_feedback"; +import GridLayout from "react-grid-layout"; +import PolarisDashboard from '../components/PolarisDashboard'; +import PolarisDashboardSplitView from '../components/PolarisDashboardSplitView'; + + +export default function Dashboard4() { + + const dashboardConfig = { + "id": "new-unique-id", + "name": "Simple Dashboard", + "visualisationToken": "", + "rights_engine": "https://polaris.digitallearning.gmbh", + "grid": { + "cols": 6 + }, + "interaction": { + "allowEdit": true, + "allowRemove": true, + "allowAdd": true, + "autoSave": true, + }, + "widgets": { + "welcome-card": { + "type": "form", + "parameters": { + "headline": "Das ist ein einfaches Formular", + "body": "Hier könnte ein erklärender Text stehen", + "form": [ + { + "type": "textBox", + "label": "Einfaches Textfeld", + }, + { + "type": "textArea", + "label": "TextArea" + } + ] + }, + "layout": { + "w": 6, + "h": 3 + } + }, + } + }; + + + return <> + <PolarisDashboardSplitView config={dashboardConfig} title={"Base example with forms"}/> + </> + +} \ No newline at end of file diff --git a/advanced/src/app/pages/login.js b/advanced/src/app/pages/login.js index 49eb66fcf6b3b7f85ad09bd69a664a93c2b31850..54d3d22fd493547cafce3a7e1cbbac97a192c791 100644 --- a/advanced/src/app/pages/login.js +++ b/advanced/src/app/pages/login.js @@ -3,6 +3,7 @@ import React, { useState } from "react"; import { Button, Col, Container, Row } from "react-bootstrap"; import CoverImage from "./cover.jpg" +import { faKey, faUser } from "@fortawesome/free-solid-svg-icons"; export default function Login() { @@ -31,14 +32,14 @@ export default function Login() { <Col md={8} lg={6} xl={4}> <div className="form-left px-5"> <div className="row g-4" style={{marginTop: "50px"}}> - <h3>Polaris</h3> + <h3>POLARIS</h3> </div> <div className="row g-4 mt-2" style={{borderLeft: "4px solid #3f51b5"}}> <h4 className={""}>Bitte melden Sie sich an.</h4> <div className="col-12"> <label>Nutzername<span className="text-danger">*</span></label> <div className="input-group"> - <div className="input-group-text"><FontAwesomeIcon icon="fa-solid fa-user" /></div> + <div className="input-group-text"><FontAwesomeIcon icon={faUser} /></div> <input onKeyDown={onKeyDown} onChange={(e) => setUsername(e.target.value)} value={username} type="text" className="form-control" placeholder="E-Mail Adresse"/> </div> </div> @@ -46,7 +47,7 @@ export default function Login() { <div className="col-12"> <label>Passwort<span className="text-danger">*</span></label> <div className="input-group"> - <div className="input-group-text"><FontAwesomeIcon icon="fa-solid fa-key" /></div> + <div className="input-group-text"><FontAwesomeIcon icon={faKey}/></div> <input onKeyDown={onKeyDown} onChange={(e) => setPassword(e.target.value)} value={password} type="password" className="form-control" placeholder="Bitte geben Sie Ihr Passwort ein"/> </div> </div> diff --git a/advanced/src/app/pages/manualdata.js b/advanced/src/app/pages/manualdata.js new file mode 100644 index 0000000000000000000000000000000000000000..53542954e2c03bf1d0bcda0e66f3bead7a7d9a54 --- /dev/null +++ b/advanced/src/app/pages/manualdata.js @@ -0,0 +1,23 @@ +import React from "react"; +import { Card, Col, Container, Row } from "react-bootstrap"; +import SyntaxHighlighter from "react-syntax-highlighter/dist/esm/default-highlight"; +import { docco } from 'react-syntax-highlighter/dist/esm/styles/hljs'; + +export default function ManualData() { + + return <Container className="mt-5"> + <Row> + <Col> + <Card> + <Card.Body> + <h5>Aktivität protokollieren</h5> + </Card.Body> + </Card> + </Col> + <Col> + <SyntaxHighlighter language="javascript" style={docco}> + </SyntaxHighlighter> + </Col> + </Row> + </Container> +} \ No newline at end of file diff --git a/advanced/src/app/pages/welcome.js b/advanced/src/app/pages/welcome.js index d00c10efcdf773e558093c21d644664fbed0b681..dbf22363fe21349c7e4ed12b40f15fa035e9fc66 100644 --- a/advanced/src/app/pages/welcome.js +++ b/advanced/src/app/pages/welcome.js @@ -1,8 +1,31 @@ import React from "react"; +import { Card, Col, Container, Row } from "react-bootstrap"; + + +import CoverImage from "./cover.jpg" export default function Welcome() { - return <> - Hi welcome - </> + return <Container fluid> + <Row style={{minHeight: "100vh"}}> + <Col lg={2} xl={4} className={"d-none d-lg-block video-container"} style={{backgroundImage: "url("+ CoverImage + ")", backgroundSize: "cover"}}> + </Col> + <Col md={12} lg={10} xl={8}> + <Card className="m-5"> + <Card.Body> + <h1>POLARIS – Provider Oriented Open Learning Analytics</h1> + <p className="text-muted">entwickelt im Rahmen des KI.edu.NRW Projekts mit der Ruhr-Universtität-Bochum und der RWTH Aachen</p> + + <h3>Was ist POLARIS?</h3> + + <h3>Wie nutze ich POLARIS?</h3> + + <h3>Kann ich POLARIS selber betreiben?</h3> + + <h3>Wo finde ich den Quellcode von POLARIS?</h3> + </Card.Body> + </Card> + </Col> + </Row> + </Container> } \ No newline at end of file diff --git a/advanced/src/app/pages/xapistatementviewer.js b/advanced/src/app/pages/xapistatementviewer.js new file mode 100644 index 0000000000000000000000000000000000000000..f6c04bd0aedf368c27004d160cbabb17a38e38ab --- /dev/null +++ b/advanced/src/app/pages/xapistatementviewer.js @@ -0,0 +1,53 @@ +import React from "react"; +import { Card, Col, Container, Row } from "react-bootstrap"; +import { ReactTabulator, reactFormatter } from "react-tabulator"; + +export default function XAPIStatementViewer() { + + const data = [ + { + id: 1, + name: "Oli Bob", + age: "12", + color: "red", + dob: "01/01/1980", + rating: 5, + passed: true, + pets: ["cat", "dog"] + }, + { + id: 2, + name: "Mary May", + age: "1", + color: "green", + dob: "12/05/1989", + rating: 4, + passed: true, + pets: ["cat"] + }, + ]; + + const options = { + movableColumns: true + }; + + const columns = [ + { title: "Actor", field: "name" }, + { title: "Verb", field: "age" }, + { title: "Objekt", field: "object" }, + { title: "Context", field: "context" }, + { title: "Grouping", field: "grouping" }, + { title: "Result", field: "result" }, + ]; + + return <Container className="mt-5"> + <h3>xAPI Statements</h3> + <Card> + <ReactTabulator + columns={columns} + data={data} + options={options} + /> + </Card> + </Container> +} \ No newline at end of file diff --git a/advanced/src/index.js b/advanced/src/index.js index a11dca52db0eff255b45cf5a258607c07c559480..9b728b4cf5e2aaa72fe53fa7c28830b8bc0de090 100644 --- a/advanced/src/index.js +++ b/advanced/src/index.js @@ -11,6 +11,10 @@ import Dashboard from './app/pages/dashboard'; import Login from './app/pages/login'; import Dashboard2 from './app/pages/dashboard_2'; import Welcome from './app/pages/welcome'; +import Dashboard3 from './app/pages/dashboard_3'; +import ManualData from './app/pages/manualdata'; +import XAPIStatementViewer from './app/pages/xapistatementviewer'; +import Dashboard4 from './app/pages/dashboard_4'; // Clear the existing HTML content document.body.innerHTML = '<div id="app"></div>'; @@ -26,6 +30,14 @@ const router = createBrowserRouter([ path: "/", element: <Welcome />, }, + { + path: "manualData", + element: <ManualData />, + }, + { + path: "xapiviewer", + element: <XAPIStatementViewer />, + }, { path: "dashboard/1", element: <Dashboard />, @@ -34,6 +46,14 @@ const router = createBrowserRouter([ path: "dashboard/2", element: <Dashboard2 />, }, + { + path: "dashboard/3", + element: <Dashboard3 />, + }, + { + path: "dashboard/4", + element: <Dashboard4 />, + }, ], }, { diff --git a/advanced/src/index.scss b/advanced/src/index.scss index 2d14e3a8c900a7a48d4d87005f73c6e3050e1b66..7bce7a7bae49802d9b3ccba1fa1faf75b6c29e44 100644 --- a/advanced/src/index.scss +++ b/advanced/src/index.scss @@ -2,288 +2,6 @@ margin-left: 5px; margin-top: 2px; } - - -*, -*::before, -*::after { - box-sizing: border-box; -} - -.card { - position: relative; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - min-width: 0; - word-wrap: break-word; - background-color: #fff; - background-clip: border-box; - border: 1px solid rgba(0, 0, 0, 0.125); - border-radius: 0.25rem; -} - -.card > hr { - margin-right: 0; - margin-left: 0; -} - -.card > .list-group:first-child .list-group-item:first-child { - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; -} - -.card > .list-group:last-child .list-group-item:last-child { - border-bottom-right-radius: 0.25rem; - border-bottom-left-radius: 0.25rem; -} - -.card-body { - -ms-flex: 1 1 auto; - flex: 1 1 auto; - min-height: 1px; - padding: 1.25rem; -} - -.card-title { - margin-bottom: 0.75rem; -} - -.card-subtitle { - margin-top: -0.375rem; - margin-bottom: 0; -} - -.card-text:last-child { - margin-bottom: 0; -} - -.card-link:hover { - text-decoration: none; -} - -.card-link + .card-link { - margin-left: 1.25rem; -} - -.card-header { - padding: 0.75rem 1.25rem; - margin-bottom: 0; - background-color: rgba(0, 0, 0, 0.03); - border-bottom: 1px solid rgba(0, 0, 0, 0.125); -} - -.card-header:first-child { - border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; -} - -.card-header + .list-group .list-group-item:first-child { - border-top: 0; -} - -.card-footer { - padding: 0.75rem 1.25rem; - background-color: rgba(0, 0, 0, 0.03); - border-top: 1px solid rgba(0, 0, 0, 0.125); -} - -.card-footer:last-child { - border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); -} - -.card-header-tabs { - margin-right: -0.625rem; - margin-bottom: -0.75rem; - margin-left: -0.625rem; - border-bottom: 0; -} - -.card-header-pills { - margin-right: -0.625rem; - margin-left: -0.625rem; -} - -.card-img-overlay { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - padding: 1.25rem; -} - -.card-img, -.card-img-top, -.card-img-bottom { - -ms-flex-negative: 0; - flex-shrink: 0; - width: 100%; -} - -.card-img, -.card-img-top { - border-top-left-radius: calc(0.25rem - 1px); - border-top-right-radius: calc(0.25rem - 1px); -} - -.card-img, -.card-img-bottom { - border-bottom-right-radius: calc(0.25rem - 1px); - border-bottom-left-radius: calc(0.25rem - 1px); -} - -.card-deck .card { - margin-bottom: 15px; -} - -@media (min-width: 576px) { - .card-deck { - display: -ms-flexbox; - display: flex; - -ms-flex-flow: row wrap; - flex-flow: row wrap; - margin-right: -15px; - margin-left: -15px; - } - .card-deck .card { - -ms-flex: 1 0 0%; - flex: 1 0 0%; - margin-right: 15px; - margin-bottom: 0; - margin-left: 15px; - } -} - -.card-group > .card { - margin-bottom: 15px; -} - -@media (min-width: 576px) { - .card-group { - display: -ms-flexbox; - display: flex; - -ms-flex-flow: row wrap; - flex-flow: row wrap; - } - .card-group > .card { - -ms-flex: 1 0 0%; - flex: 1 0 0%; - margin-bottom: 0; - } - .card-group > .card + .card { - margin-left: 0; - border-left: 0; - } - .card-group > .card:not(:last-child) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - } - .card-group > .card:not(:last-child) .card-img-top, - .card-group > .card:not(:last-child) .card-header { - border-top-right-radius: 0; - } - .card-group > .card:not(:last-child) .card-img-bottom, - .card-group > .card:not(:last-child) .card-footer { - border-bottom-right-radius: 0; - } - .card-group > .card:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - } - .card-group > .card:not(:first-child) .card-img-top, - .card-group > .card:not(:first-child) .card-header { - border-top-left-radius: 0; - } - .card-group > .card:not(:first-child) .card-img-bottom, - .card-group > .card:not(:first-child) .card-footer { - border-bottom-left-radius: 0; - } -} - -.form-control { - display: block; - width: 100%; - height: calc(1.5em + 0.75rem + 2px); - padding: 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #495057; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ced4da; - border-radius: 0.25rem; - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -} - -@media (prefers-reduced-motion: reduce) { - .form-control { - transition: none; - } -} - -.form-control::-ms-expand { - background-color: transparent; - border: 0; -} - -.form-control:-moz-focusring { - color: transparent; - text-shadow: 0 0 0 #495057; -} - -.form-control:focus { - color: #495057; - background-color: #fff; - border-color: #80bdff; - outline: 0; - box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); -} - -.form-control::-webkit-input-placeholder { - color: #6c757d; - opacity: 1; -} - -.form-control::-moz-placeholder { - color: #6c757d; - opacity: 1; -} - -.form-control:-ms-input-placeholder { - color: #6c757d; - opacity: 1; -} - -.form-control::-ms-input-placeholder { - color: #6c757d; - opacity: 1; -} - -.form-control::placeholder { - color: #6c757d; - opacity: 1; -} - -.form-control:disabled, .form-control[readonly] { - background-color: #e9ecef; - opacity: 1; -} - -select.form-control:focus::-ms-value { - color: #495057; - background-color: #fff; -} - -.form-control-file, -.form-control-range { - display: block; - width: 100%; -} -textarea.form-control { - height: auto; -} $primary: #3f51b5; @@ -291,6 +9,9 @@ $primary: #3f51b5; @import '~react-grid-layout/css/styles.css'; @import '~react-resizable/css/styles.css'; +@import '~react-tabulator/lib/styles.css'; // required styles +@import '~react-tabulator/lib/css/tabulator_bootstrap4.min.css'; // theme + .db-shaking { animation: shake 1s; animation-iteration-count: infinite;