diff --git a/.gitignore b/.gitignore index 549e00a..47ba3ef 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ build/ ### VS Code ### .vscode/ + +### Live Server directory ### +html/ diff --git a/pom.xml b/pom.xml index a1dd23f..68a734d 100644 --- a/pom.xml +++ b/pom.xml @@ -22,20 +22,29 @@ org.springframework.boot spring-boot-starter-data-jpa + org.springframework.boot spring-boot-starter-thymeleaf + org.springframework.boot spring-boot-starter-web + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.0.2 + + org.springframework.boot spring-boot-starter-tomcat provided + org.springframework.boot spring-boot-starter-test diff --git a/src/main/resources/static/add-button-mask.svg b/src/main/resources/static/add-button-mask.svg new file mode 100644 index 0000000..221de76 --- /dev/null +++ b/src/main/resources/static/add-button-mask.svg @@ -0,0 +1,105 @@ + + + + + diff --git a/src/main/resources/static/add.css b/src/main/resources/static/add.css new file mode 100644 index 0000000..4361843 --- /dev/null +++ b/src/main/resources/static/add.css @@ -0,0 +1,133 @@ +@import url("main.css"); + +:root { + --accent-color: oklch(65.33% 0.158 247.76); +} + +form label:after { + content: ":"; +} + +form :is(input[type=text], textarea) { + background-color: var(--fg-color); + border: none; + border-radius: .25lh; + color: var(--text-color, white); + padding: .5em; + font-family: sans-serif; +} + +/* quick info box */ +form { + display: grid; + grid-template-columns: 1fr 1fr auto; + gap: 1rem 2rem; +} + +form > * { + display: flex; + align-items: center; + gap: 1rem; +} + +form :is(input[type=text], textarea) { + flex-grow: 1; +} + +/* switch */ +label:has(#is-dataset) { + gap: 0; +} + +#is-dataset { + display: none; +} + +#is-dataset-toggle { + margin-inline: 1ch; + padding-inline: .5ch; + width: 2rem; + height: 1lh; + background-color: var(--fg-color); + border-radius: .5lh; + position: relative; +} + +#is-dataset-toggle::before { + content: ""; + position: absolute; + top: 0; + --switch-gap: 2px; + --size: calc(1lh - 2 * var(--switch-gap)); + width: var(--size); + height: var(--size); + border-radius: 50%; + margin: var(--switch-gap); + box-sizing: border-box; + background-color: var(--text-color); + transition: inset-inline ease-out 50ms; +} + +#is-dataset:not(:checked) + #is-dataset-toggle::before { + left: 0; +} + +#is-dataset:checked + #is-dataset-toggle::before { + inset-inline: calc(2rem - .5lh - var(--switch-gap)) 0; +} + +/* short description box */ +form :has(#short-description) { + grid-column: 1 / 3; +} + +/* full description box */ +#full-description-box { + grid-column: 1 / 4; + margin: 1rem 0; + align-items: start; +} + +#full-description { + height: 15rem; + box-sizing: border-box; +} + +/* button bar */ +#btn-bar { + grid-column: 1 / 4; + justify-content: end; + gap: 1rem; +} + +/* button styling */ +.btn { + padding: .5lh 1lh; + border: none; + border-radius: .5lh; + --btn-color: var(--fg-color); + background-color: var(--btn-color); + color: var(--text-color); + font-weight: bold; + font-size: 1rem; + transition: background-color 100ms, filter 200ms; + transition-timing-function: ease-out; + --drop-shadow-opacity: .5; + --drop-shadow-offset-y: 0; + --drop-shadow-blur: .25rem; + filter: drop-shadow( + rgba(0, 0, 0, var(--drop-shadow-opacity)) + 0 var(--drop-shadow-offset-y) var(--drop-shadow-blur) + ); +} + +.btn:hover { + background-color: color-mix(in oklab, var(--btn-color) 80%, var(--bg-color)); + --drop-shadow-opacity: .8; + --drop-shadow-offset-y: .25rem; + --drop-shadow-blur: .4rem; +} + +.btn.suggested { + --btn-color: var(--accent-color); +} diff --git a/src/main/resources/static/filter.svg b/src/main/resources/static/filter.svg new file mode 100644 index 0000000..d90e5c0 --- /dev/null +++ b/src/main/resources/static/filter.svg @@ -0,0 +1,49 @@ + + + + diff --git a/src/main/resources/static/looking-glass.svg b/src/main/resources/static/looking-glass.svg new file mode 100644 index 0000000..0f7790e --- /dev/null +++ b/src/main/resources/static/looking-glass.svg @@ -0,0 +1,2 @@ + + diff --git a/src/main/resources/static/main.css b/src/main/resources/static/main.css index 03cf4e5..0711eca 100644 --- a/src/main/resources/static/main.css +++ b/src/main/resources/static/main.css @@ -5,12 +5,15 @@ --pad-datasets: 1rem; --pad-main: 2rem; --min-card-size: 60ch; + --corner-radius: 1rem; font-size: 12pt; + font-family: sans-serif; } body { background-color: var(--bg-color, black); color: var(--text-color, white); + margin: 0; } main { @@ -25,6 +28,40 @@ header { margin-inline: .75rem; } +#add-btn { + width: 7rem; + height: 7rem; + content: url("add-button-mask.svg"); + background: linear-gradient(135deg, pink, darkblue); + clip-path: polygon(0% 0%, 100% 0%, 0% 100%); + + cursor: pointer; + + position: fixed; + top: 0; + left: 0; + z-index: 1; +} +#tool-bar { + display: flex; + flex-direction: row; + float: right; + gap: .5rem; + background-color: var(--fg-color, darkgrey); + padding: .5rem 1rem; + border-radius: 1.5rem; +} + +#search-entry { + background: none; + border: none; + color: var(--text-color); +} + +#search-entry:focus-visible { + outline: none; +} + .datasets { padding-inline: var(--pad-datasets); display: grid; @@ -41,7 +78,7 @@ header { .dataset { padding: 1rem 2rem; background-color: var(--fg-color, darkgrey); - border-radius: 1rem; + border-radius: var(--corner-radius); list-style: none; display: inline-flex; align-items: center; @@ -57,27 +94,52 @@ header { align-items: center; gap: .5em; } - -.upvote-btn, .downvote-btn { - background: url(triangle.svg) no-repeat; +/* Buttons */ +.upvote-btn, .downvote-btn, #search-btn, #filter-btn, #sort-btn { + background: var(--icon-url) no-repeat; background-size: contain; border: none; - width: 2em; - height: 2em; + width: var(--icon-size); + height: var(--icon-size); padding: 0; overflow: hidden; color: transparent; cursor: pointer; } +.downvote-btn, .upvote-btn{ + --icon-url: url(triangle.svg); + --icon-size: 2rem; +} + .downvote-btn { transform: rotate(180deg); } -:is(.upvote-btn, .downvote-btn):is(:hover, :focus-visible) { +#search-btn { + --icon-url: url(looking-glass.svg); + --icon-size: 1rem; +} +#filter-btn { + --icon-url: url(filter.svg); + --icon-size: 1rem; +} + +#sort-btn { + --icon-url: url(sort.svg); + --icon-size: 1rem; +} + +.divider { + width: .05rem; + height: 1rem; + background-color: var(--bg-color); +} + +:is(.upvote-btn, .downvote-btn, #search-btn, #filter-btn, #sort-btn, #add-btn):is(:hover, :focus-visible) { filter: brightness(1.5); } -:is(.upvote-btn, .downvote-btn):active { +:is(.upvote-btn, .downvote-btn, #search-btn, #filter-btn, #sort-btn, #add-btn):active { filter: brightness(1.75); } diff --git a/src/main/resources/static/sort.svg b/src/main/resources/static/sort.svg new file mode 100644 index 0000000..a259268 --- /dev/null +++ b/src/main/resources/static/sort.svg @@ -0,0 +1,61 @@ + + + + diff --git a/src/main/resources/templates/add.html b/src/main/resources/templates/add.html new file mode 100644 index 0000000..d8472c1 --- /dev/null +++ b/src/main/resources/templates/add.html @@ -0,0 +1,58 @@ + + + + + + DataDash – Add dataset/API + + + +
+
+

Add new DataDash content

+
+ +
+

+ Please add the following information about your dataset/API to + help users better find it and understand what it is about and + how to use it. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index df5a374..172c714 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -7,12 +7,32 @@ +

Welcome to DataDash

The place to launch and discover datasets and API endpoints.

+
+ +
+ + + +
+

Recently added:

    @@ -107,7 +127,14 @@
- +
+ +
- \ No newline at end of file +