WIP
This commit is contained in:
parent
2386a56036
commit
7265184fc5
12 changed files with 410 additions and 584 deletions
682
assets/app.css
682
assets/app.css
|
|
@ -1,580 +1,222 @@
|
|||
/*
|
||||
Main CSS file for madr.se
|
||||
If you have any questions regarding the CSS, feel free
|
||||
to contact me: yttan at madr dot se
|
||||
|
||||
Table of contents, 7-1 inspired
|
||||
|
||||
1. Base
|
||||
2. Components
|
||||
3. Layout
|
||||
4. Pages
|
||||
5. Themes
|
||||
6. Vendors
|
||||
7. Shame
|
||||
*/
|
||||
|
||||
/* === 1. Base === */
|
||||
|
||||
/*
|
||||
Normalize and resets.
|
||||
Only properties, element and attribute selectors are allowed in this
|
||||
section.
|
||||
|
||||
All dynamic values that should change according to user preferences
|
||||
(dark or light color mode, reduced motion etc) and agent abilities
|
||||
(small handheld screen, big desktop screen) are handled by properties
|
||||
when appliable.
|
||||
|
||||
This is to avoid redeclarating CSS rules.
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* colors, dark mode default */
|
||||
--color: hsl(0 0 90%);
|
||||
--bgcolor: hsl(180 75% 6%);
|
||||
--tree-item-accent-color: dimgrey;
|
||||
--panel-bg-color: hsla(0 0 50% / 0.16);
|
||||
--monospace-color: springgreen;
|
||||
--monospace-color-inline: seagreen;
|
||||
--a-color: gold;
|
||||
|
||||
/* typography, mobile first */
|
||||
--base-font-size: 1.33em;
|
||||
--page-title-font-size: 2em;
|
||||
--tree-font-size: 0.85em;
|
||||
--section-heading-lv2-font-size: 1.5em;
|
||||
--section-heading-lv3-font-size: 1.2em;
|
||||
--section-heading-lv4-font-size: 1em;
|
||||
--system-serif-fonts: Cambria, Cochin, Georgia, Times, "Times New Roman",
|
||||
serif;
|
||||
--system-sansserif-fonts: apple-system, system-ui, BlinkMacSystemFont,
|
||||
Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;
|
||||
--monospace-fonts: "JetBrains mono", monaco, menlo, meslo, "Courier New",
|
||||
Courier, monospace;
|
||||
|
||||
/* whitespace */
|
||||
--gap-sm: 0.5em;
|
||||
--gap-md: 1em;
|
||||
--gap-lg: 3em;
|
||||
|
||||
/* transitions */
|
||||
--animation-duration: 0.5s;
|
||||
|
||||
/* dimensions and aspect ratios */
|
||||
--map-ratio: 1;
|
||||
|
||||
@media (min-width: 666px) {
|
||||
--base-font-size: 1.66em;
|
||||
--tree-font-size: 0.67em;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
color: var(--color);
|
||||
background-color: var(--bgcolor);
|
||||
font: normal var(--base-font-size) / 1.5 var(--system-sansserif-fonts);
|
||||
}
|
||||
|
||||
body {
|
||||
background: #222;
|
||||
margin: 0;
|
||||
|
||||
> footer > p {
|
||||
margin-top: var(--gap-lg);
|
||||
color: #666;
|
||||
font-size: 0.66em;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--a-color);
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
font-size: 1.2em;
|
||||
padding: 0.25em;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-family: var(--system-serif-fonts);
|
||||
background-image: linear-gradient(
|
||||
175deg,
|
||||
#212223,
|
||||
#222 350px,
|
||||
#302928 345px,
|
||||
#282828
|
||||
);
|
||||
font-family:
|
||||
system-ui,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
"Segoe UI",
|
||||
Roboto,
|
||||
Oxygen,
|
||||
Ubuntu,
|
||||
Cantarell,
|
||||
"Open Sans",
|
||||
"Helvetica Neue",
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0.5em 0;
|
||||
line-height: 0.95;
|
||||
font-size: var(--page-title-font-size);
|
||||
|
||||
@media (min-width: 666px) {
|
||||
text-transform: lowercase;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
text-align: right;
|
||||
line-height: 0.9;
|
||||
color: var(--tree-item-accent-color);
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
h2,
|
||||
h3 {
|
||||
margin-top: 2em;
|
||||
line-height: 1.1;
|
||||
font-size: 1.75em;
|
||||
letter-spacing: -0.066em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: var(--section-heading-lv2-font-size);
|
||||
border-bottom: 3px solid var(--panel-bg-color);
|
||||
font-size: 1.33em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: var(--section-heading-lv3-font-size);
|
||||
p,
|
||||
li {
|
||||
line-height: 1.66em;
|
||||
}
|
||||
|
||||
h3,
|
||||
h4 {
|
||||
font-size: var(--section-heading-lv4-font-size);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
main {
|
||||
margin: 0 0 0 13em;
|
||||
max-width: 37em;
|
||||
}
|
||||
|
||||
.cards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.33em;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border: 2px solid #444;
|
||||
padding: 3em;
|
||||
border-radius: 9px;
|
||||
box-shadow: 0 0 5px #000;
|
||||
|
||||
:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.collapsed {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 2em 0;
|
||||
background-color: #022;
|
||||
color: var(--monospace-color);
|
||||
padding: 0.5em;
|
||||
background-color: #1e2025;
|
||||
color: #96df71;
|
||||
position: relative;
|
||||
margin: 1em 2em;
|
||||
overflow-y: auto;
|
||||
padding: 0.66em;
|
||||
box-shadow: 4px 4px 0 var(--panel-bg-color);
|
||||
position: relative;
|
||||
line-height: 1.2;
|
||||
font-size: 0.8em;
|
||||
|
||||
> button {
|
||||
font-size: 0.75em;
|
||||
button {
|
||||
position: absolute;
|
||||
top: 0.25em;
|
||||
right: 0.25em;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: var(--monospace-fonts);
|
||||
|
||||
&.inline {
|
||||
color: var(--monospace-color-inline);
|
||||
background: #f3f3f3;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
section {
|
||||
position: relative;
|
||||
|
||||
& > h2 {
|
||||
background: var(--bgcolor);
|
||||
color: var(--color);
|
||||
padding: 0.5em 0.25em;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
article {
|
||||
line-height: 1.33;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
text-align: center;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
background-color: var(--background-color-l);
|
||||
padding: 0.25em;
|
||||
font-size: 0.8em;
|
||||
border: 1px solid rgb(128, 128, 128, 0.5);
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: var(--background-color-ll);
|
||||
text-transform: uppercase;
|
||||
color: var(--em-color);
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
li {
|
||||
color: var(--em-color);
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
li:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
li::marker {
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
color: var(--em-color);
|
||||
font-size: 1.2em;
|
||||
line-height: 1.2;
|
||||
font-style: italic;
|
||||
border-left: 5px solid var(--background-color-l);
|
||||
margin: 1em 1em 1em 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
blockquote p::after,
|
||||
blockquote p::before {
|
||||
content: '"';
|
||||
}
|
||||
|
||||
/* === /Base === */
|
||||
/* === 2. Components === */
|
||||
|
||||
/*
|
||||
Use kebab case named classes to identify components, and nesting
|
||||
to group subcomponents.
|
||||
|
||||
Element selectors are preferred as subcomponents, due to the simple
|
||||
nature of this site. As a general rule though, classes are the most
|
||||
versatile.
|
||||
*/
|
||||
|
||||
.home-search,
|
||||
.profiles {
|
||||
font-size: var(--tree-font-size);
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
left: -999em;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.flx {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.breadcrumbs {
|
||||
border-radius: 8px 8px 0 0;
|
||||
padding: 1em;
|
||||
> .trail > span::after {
|
||||
content: "/";
|
||||
}
|
||||
background: #080808;
|
||||
background-image: linear-gradient(
|
||||
#080808 0,
|
||||
#080808 50%,
|
||||
#161616 50%,
|
||||
#080808 100%
|
||||
);
|
||||
color: #fff;
|
||||
|
||||
.sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.interactive-map {
|
||||
aspect-ratio: var(--map-ratio);
|
||||
}
|
||||
|
||||
.home-h1 {
|
||||
font-size: 1.33em;
|
||||
}
|
||||
|
||||
.list-link {
|
||||
&::after {
|
||||
content: " →";
|
||||
a {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.feed-link {
|
||||
&::after {
|
||||
content: " ↗";
|
||||
.head {
|
||||
color: #fff;
|
||||
background-color: #345;
|
||||
|
||||
padding: 1em 2em;
|
||||
border-radius: 0 0 8px 8px;
|
||||
margin-bottom: 1.5em;
|
||||
|
||||
:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.skiplink {
|
||||
position: absolute;
|
||||
top: -5em;
|
||||
transition: top var(--animation-duration) ease-out;
|
||||
padding: 0.25em 0.5em;
|
||||
top: -1.75em;
|
||||
left: 1em;
|
||||
background-color: #ff0;
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
padding: 0.25em;
|
||||
transition: top 0.25s ease-out;
|
||||
|
||||
&:focus {
|
||||
top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.tree {
|
||||
nav {
|
||||
display: flex;
|
||||
margin: 2em 0 1em;
|
||||
|
||||
> ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.66em;
|
||||
font-size: var(--tree-font-size);
|
||||
|
||||
> li {
|
||||
text-align: center;
|
||||
display: grid;
|
||||
grid-template-columns: 50px 1fr auto;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
gap: 0.5em;
|
||||
padding: 0.75em;
|
||||
min-height: 50px;
|
||||
background-color: rgba(128, 128, 128, 0.1);
|
||||
border: 1px solid rgba(192, 192, 192, 0.1);
|
||||
|
||||
&:focus-within {
|
||||
background-color: rgba(128, 128, 128, 0.25);
|
||||
}
|
||||
|
||||
> small {
|
||||
opacity: 0.66;
|
||||
font-family: var(--monospace-fonts);
|
||||
font-size: 0.66em;
|
||||
}
|
||||
}
|
||||
|
||||
> .article {
|
||||
--tree-item-accent-color: rebeccapurple;
|
||||
}
|
||||
|
||||
> .album {
|
||||
--tree-item-accent-color: goldenrod;
|
||||
}
|
||||
|
||||
> .link {
|
||||
--tree-item-accent-color: honeydew;
|
||||
}
|
||||
|
||||
> .events {
|
||||
--tree-item-accent-color: firebrick;
|
||||
gap: 1.5em;
|
||||
background: #111;
|
||||
padding: 0.33em 1.5em 0.25em;
|
||||
border-radius: 0 1.33em 1.33em 0;
|
||||
border: 2px solid #333;
|
||||
border-left-width: 0;
|
||||
padding-left: 13em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--color);
|
||||
text-decoration: none;
|
||||
flex: 1;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.landing {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 2em 0;
|
||||
box-sizing: border-box;
|
||||
gap: 1.66em;
|
||||
}
|
||||
|
||||
.breadcrumbs {
|
||||
display: block;
|
||||
margin: var(--gap-sm) 0;
|
||||
padding: var(--gap-sm);
|
||||
border: 1px solid rgb(128, 128, 128, 0.25);
|
||||
background-color: var(--panel-bg-color);
|
||||
border-radius: 0;
|
||||
|
||||
> span {
|
||||
display: inline;
|
||||
|
||||
&:after {
|
||||
content: " /";
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--color);
|
||||
}
|
||||
}
|
||||
|
||||
.months {
|
||||
grid-auto-flow: rows;
|
||||
display: grid;
|
||||
list-style: none;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 0.5em;
|
||||
padding-left: 0;
|
||||
margin: 2.75em 0;
|
||||
|
||||
> li {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.article {
|
||||
> div > p:first-child::first-letter {
|
||||
@media (min-width: 500px) {
|
||||
float: left;
|
||||
font-size: 7em;
|
||||
border: 8px double hsl(0 0 50%);
|
||||
padding: 0.1em;
|
||||
margin-right: 0.066em;
|
||||
font-style: normal;
|
||||
font-family: var(--system-serif-fonts);
|
||||
}
|
||||
}
|
||||
|
||||
> footer {
|
||||
font-style: italic;
|
||||
font-size: 0.8em;
|
||||
text-align: right;
|
||||
|
||||
> p {
|
||||
margin-top: 2.75em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.articles {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 3em;
|
||||
grid-auto-rows: 1fr;
|
||||
|
||||
> * {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
border-top: 6px solid red;
|
||||
|
||||
&:focus-within {
|
||||
background-color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
time {
|
||||
border-top: 1px solid crimson;
|
||||
padding: 0.25em 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.links {
|
||||
> :is(h2, h3) {
|
||||
margin-top: 3em;
|
||||
}
|
||||
}
|
||||
|
||||
.brutal-legend {
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
flex-direction: row-reverse;
|
||||
|
||||
> p {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
> img {
|
||||
.anders {
|
||||
img {
|
||||
position: fixed;
|
||||
top: 1em;
|
||||
left: 1em;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 50%;
|
||||
width: 175px;
|
||||
|
||||
&:hover {
|
||||
animation: 1s ease-out 0s infinite alternate burst;
|
||||
}
|
||||
}
|
||||
|
||||
img + img {
|
||||
top: 12.5em;
|
||||
left: 5em;
|
||||
width: 125px;
|
||||
}
|
||||
|
||||
img + img + img {
|
||||
top: 18.5em;
|
||||
left: 0.5em;
|
||||
width: 90px;
|
||||
}
|
||||
}
|
||||
|
||||
.profiles {
|
||||
.bookmarks {
|
||||
display: flex;
|
||||
gap: 1.66em;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
flex-direction: column;
|
||||
gap: 2em;
|
||||
}
|
||||
|
||||
> li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@keyframes burst {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
|
||||
/* === /Components === */
|
||||
/* === 3. Layout === */
|
||||
/*
|
||||
Containers and wrappers for components.
|
||||
Only class selectors allowed, with the following element selectors as
|
||||
exceptions: aside, body, footer, header, main and nav.
|
||||
*/
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 33em;
|
||||
box-sizing: border-box;
|
||||
min-height: 100vh;
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
/* === /Layout === */
|
||||
/* === 4. Pages === */
|
||||
/*
|
||||
Styles that should only apply to certain pages.
|
||||
*/
|
||||
/* === /Pages === */
|
||||
/* === 5. Themes === */
|
||||
/*
|
||||
Styles to create user-customized themes.
|
||||
|
||||
This section adapts the design to the following user preferences:
|
||||
Color theme, reduced motion
|
||||
*/
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--color: #000;
|
||||
--bgcolor: #fff;
|
||||
--a-color: blue;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion) {
|
||||
:root {
|
||||
--animation-duration: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 800px) {
|
||||
:root {
|
||||
--map-ratio: 3 / 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1000px) {
|
||||
:root {
|
||||
--page-title-font-size: 4em;
|
||||
}
|
||||
}
|
||||
/* === /Themes === */
|
||||
/* === 6. Vendors === */
|
||||
/*
|
||||
Styles belonging to third-party components.
|
||||
*/
|
||||
|
||||
.footnotes-list {
|
||||
color: var(--aside-color);
|
||||
font-size: 80%;
|
||||
}
|
||||
/* === /Vendors === */
|
||||
|
||||
/* === 7. Shame === */
|
||||
/*
|
||||
Styles necessary for specifity issues and for cutting corners
|
||||
(breaking the rules in short terms in waiting for an opportunity
|
||||
to rewrite or fix a problem for good).
|
||||
|
||||
madr.se has no reason to feel ashamed. Yet.
|
||||
*/
|
||||
/* === /Shame === */
|
||||
|
|
|
|||
|
|
@ -42,6 +42,31 @@ defmodule Mse25.Directus do
|
|||
get("/articles?" <> params)
|
||||
end
|
||||
|
||||
def get_note(slug) do
|
||||
get_item(:notes, slug)
|
||||
end
|
||||
|
||||
def get_notes!(options \\ []) do
|
||||
params =
|
||||
[
|
||||
"fields=" <>
|
||||
Enum.join(
|
||||
[
|
||||
"id",
|
||||
"contents",
|
||||
"images",
|
||||
"date_created",
|
||||
"location"
|
||||
],
|
||||
","
|
||||
)
|
||||
]
|
||||
|> annual?(:notes, options)
|
||||
|> query_params_string(options, :notes)
|
||||
|
||||
get("/notes?" <> params)
|
||||
end
|
||||
|
||||
def get_album(externalId) do
|
||||
case get_item(
|
||||
:albums,
|
||||
|
|
@ -198,6 +223,13 @@ defmodule Mse25.Directus do
|
|||
end
|
||||
end
|
||||
|
||||
defp get_item(:notes, externalId, fields) do
|
||||
case get("/notes?fields=" <> fields <> "&filter[id][_eq]=" <> externalId) do
|
||||
[] -> {:not_found, externalId}
|
||||
[item | _] -> {:ok, item}
|
||||
end
|
||||
end
|
||||
|
||||
defp get_item(collection, slug, fields) do
|
||||
case get(
|
||||
"/" <> to_string(collection) <> "?fields=" <> fields <> "&filter[slug][_eq]=" <> slug
|
||||
|
|
|
|||
|
|
@ -1,8 +1,19 @@
|
|||
<a href="#content" class="skiplink">Hoppa till innehållet</a>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/webblogg">Webblogg</a></li>
|
||||
<li><a href="/delningar">Länkar</a></li>
|
||||
<li><a href="/anteckningar">Anteckningar</a></li>
|
||||
<li><a href="/evenemang">Evenemang</a></li>
|
||||
<li><a href="/om">Om</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main id="content">
|
||||
<div class="breadcrumbs">
|
||||
<span class="sr-only">Du är här:</span>
|
||||
<span class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList">
|
||||
<span class="trail" itemscope itemtype="https://schema.org/BreadcrumbList">
|
||||
<span itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
|
||||
<a href="/" rel="home">
|
||||
<span itemprop="name">madr.se</span>
|
||||
|
|
@ -19,8 +30,7 @@
|
|||
</span>
|
||||
<% end %>
|
||||
</span>
|
||||
</nav>
|
||||
<main id="content">
|
||||
</div>
|
||||
<%= @inner_content %>
|
||||
</main>
|
||||
<%= if show_footer?(assigns) do %>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,13 @@ defmodule Mse25Web.ItemController do
|
|||
end
|
||||
end
|
||||
|
||||
defp fetch([_year, album_id], :note) do
|
||||
case Directus.get_note(album_id) do
|
||||
{:ok, response} -> {:ok, :note, response}
|
||||
not_found -> not_found
|
||||
end
|
||||
end
|
||||
|
||||
defp fetch([year, "brutal-legend-" <> external_id]) do
|
||||
fetch([year, external_id], :album)
|
||||
end
|
||||
|
|
@ -174,6 +181,21 @@ defmodule Mse25Web.ItemController do
|
|||
]
|
||||
end
|
||||
|
||||
defp assigns(:note, %{
|
||||
"contents" => text,
|
||||
"images" => images,
|
||||
"date_created" => published_at
|
||||
}) do
|
||||
year = String.slice(published_at, 0..3)
|
||||
|
||||
[
|
||||
text: Earmark.as_html!(text),
|
||||
breadcrumbs: [{"anteckningar", "Anteckningar"}, {year, year, ""}],
|
||||
date_created: String.slice(published_at, 0..9),
|
||||
images: images
|
||||
]
|
||||
end
|
||||
|
||||
defp assigns(:album, %{
|
||||
"year" => year,
|
||||
"album" => album,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<article class="article" vocab="https://schema.org/" typeof="Article">
|
||||
<article class="collapsed article card" vocab="https://schema.org/" typeof="Article">
|
||||
<h1 property="name"><%= @heading %></h1>
|
||||
|
||||
<div property="articleBody">
|
||||
|
|
|
|||
10
lib/mse25_web/controllers/item_html/note.html.heex
Normal file
10
lib/mse25_web/controllers/item_html/note.html.heex
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<article class="collapsed article card" vocab="https://schema.org/" typeof="Article">
|
||||
<h1 property="name articleBody"><%= raw(@contents) %></h1>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
Publicerad <time property="datePublished"><%= @published_at %></time>
|
||||
av <span property="publisher">Anders Englöf Ytterström</span>
|
||||
</p>
|
||||
</footer>
|
||||
</article>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<article class="article" vocab="https://schema.org/" typeof="Article">
|
||||
<article class="card article" vocab="https://schema.org/" typeof="Article">
|
||||
<h1 property="name"><%= @heading %></h1>
|
||||
|
||||
<div property="articleBody">
|
||||
|
|
|
|||
|
|
@ -68,6 +68,26 @@ defmodule Mse25Web.PageController do
|
|||
)
|
||||
end
|
||||
|
||||
def notes(conn, params) do
|
||||
{notes, page_title} =
|
||||
case params do
|
||||
%{"q" => query_string} ->
|
||||
{Directus.get_notes!(limit: @almost_infinity, query: query_string),
|
||||
"Anteckningar: \"#{query_string}\""}
|
||||
|
||||
_ ->
|
||||
{Directus.get_notes!(limit: @almost_infinity), "Anteckningar"}
|
||||
end
|
||||
|
||||
render(conn, :notes,
|
||||
page_title: page_title,
|
||||
breadcrumbs: [],
|
||||
notes: group_by_creation_date(notes),
|
||||
q: params["q"],
|
||||
nosearch?: params["q"] == nil or params["q"] == ""
|
||||
)
|
||||
end
|
||||
|
||||
def events(conn, params) do
|
||||
{_, %{"title" => title, "contents" => contents}} = Directus.get_page("evenemang")
|
||||
|
||||
|
|
@ -93,7 +113,7 @@ defmodule Mse25Web.PageController do
|
|||
end
|
||||
|
||||
def links(conn, _params) do
|
||||
links = Directus.get_links!(limit: @almost_infinity) |> group_by_date
|
||||
links = Directus.get_links!(limit: @almost_infinity) |> group_by_pub_date
|
||||
|
||||
render(conn, :links,
|
||||
page_title: "Delningar",
|
||||
|
|
@ -109,10 +129,17 @@ defmodule Mse25Web.PageController do
|
|||
|> Enum.sort(fn {a, _a}, {b, _b} -> b < a end)
|
||||
end
|
||||
|
||||
defp group_by_date(items) do
|
||||
defp group_by_pub_date(items) do
|
||||
items
|
||||
|> Enum.group_by(fn %{"pubDate" => pub_date} -> pub_date end)
|
||||
|> Map.to_list()
|
||||
|> Enum.sort(fn {a, _a}, {b, _b} -> b < a end)
|
||||
end
|
||||
|
||||
defp group_by_creation_date(items) do
|
||||
items
|
||||
|> Enum.group_by(fn %{"date_created" => pub_date} -> String.slice(pub_date, 0..9) end)
|
||||
|> Map.to_list()
|
||||
|> Enum.sort(fn {a, _a}, {b, _b} -> b < a end)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,4 +3,8 @@ defmodule Mse25Web.PageHTML do
|
|||
import Mse25.EventHelpers
|
||||
|
||||
embed_templates "page_html/*"
|
||||
|
||||
defp fancy_timestamp(datestr) do
|
||||
datestr |> IO.inspect()
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
<h1>
|
||||
<div class="head">
|
||||
<h1>
|
||||
<%= @page_title %>
|
||||
</h1>
|
||||
<p>
|
||||
</h1>
|
||||
<p>
|
||||
Inlägg skrivna sedan 2006.
|
||||
<%= if @nosearch? do %>
|
||||
Gå direkt till:
|
||||
<% end %>
|
||||
</p>
|
||||
<ul class="months">
|
||||
</p>
|
||||
<ul class="months">
|
||||
<%= for {year, articles} <- @articles do %>
|
||||
<li>
|
||||
<a href={"#y" <> year}><%= year %></a> (<%= Enum.count(articles) %>)
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<form method="get" action="/webblogg">
|
||||
</ul>
|
||||
<form method="get" action="/webblogg">
|
||||
<p>
|
||||
<%= if @nosearch? do %>
|
||||
Eller
|
||||
|
|
@ -23,9 +24,11 @@
|
|||
<input type="search" value={@q} name="q" id="q" size="7" />
|
||||
<button>Sök</button>
|
||||
</p>
|
||||
</form>
|
||||
<%= for {year, articles} <- @articles do %>
|
||||
<section id={"y" <> year}>
|
||||
</form>
|
||||
</div>
|
||||
<div class="cards">
|
||||
<%= for {year, articles} <- @articles do %>
|
||||
<section class="card" id={"y" <> year}>
|
||||
<h2 class="sticky"><%= year %></h2>
|
||||
<div class="articles">
|
||||
<%= for article <- articles do %>
|
||||
|
|
@ -38,4 +41,5 @@
|
|||
<% end %>
|
||||
</div>
|
||||
</section>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
74
lib/mse25_web/controllers/page_html/notes.html.heex
Normal file
74
lib/mse25_web/controllers/page_html/notes.html.heex
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<div class="head">
|
||||
<h1>Anteckningar</h1>
|
||||
<p>Blandade tankar, oftast på engelska. Replikerat på Mastodon.</p>
|
||||
</div>
|
||||
<div class="cards">
|
||||
<%= for {date, links} <- @notes do %>
|
||||
<section class="card" id={"d" <> date}>
|
||||
<h2>
|
||||
<%= date
|
||||
|> Date.from_iso8601!()
|
||||
|> Calendar.strftime(
|
||||
"%A, %d %B %Y",
|
||||
month_names: fn m ->
|
||||
Enum.at(
|
||||
[
|
||||
"januari",
|
||||
"februari",
|
||||
"mars",
|
||||
"april",
|
||||
"maj",
|
||||
"juni",
|
||||
"juli",
|
||||
"augusti",
|
||||
"september",
|
||||
"oktober",
|
||||
"november",
|
||||
"december"
|
||||
],
|
||||
m - 1
|
||||
)
|
||||
end,
|
||||
day_of_week_names: fn d ->
|
||||
Enum.at(
|
||||
[
|
||||
"måndag",
|
||||
"tisdag",
|
||||
"onsdag",
|
||||
"torsdag",
|
||||
"fredag",
|
||||
"lördag",
|
||||
"söndag"
|
||||
],
|
||||
d - 1
|
||||
)
|
||||
end
|
||||
)
|
||||
|> String.replace(~r/ 0/, " ") %>
|
||||
</h2>
|
||||
<div class="bookmarks">
|
||||
<%= for link <- links do %>
|
||||
<article vocab="https://schema.org/" typeof="WebContent Review" class="bookmark">
|
||||
<h3>
|
||||
<div property="reviewBody">
|
||||
<%= link["contents"] |> Earmark.as_html!() |> raw %>
|
||||
</div>
|
||||
</h3>
|
||||
<footer>
|
||||
<p>
|
||||
Posted on
|
||||
<a class="permalink" href={"/notes/" <> to_string(link["id"])} title="Permalänk">
|
||||
<%= fancy_timestamp(link["date_created"]) %>
|
||||
</a>
|
||||
at
|
||||
<a href="https://www.openstreetmap.org/#map=15/50.82806/-0.12861">
|
||||
pos
|
||||
</a>
|
||||
</p>
|
||||
</footer>
|
||||
</article>
|
||||
<% end %>
|
||||
</div>
|
||||
</section>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
@ -31,6 +31,7 @@ defmodule Mse25Web.Router do
|
|||
get "/evenemang", PageController, :events
|
||||
get "/webblogg", PageController, :articles
|
||||
get "/delningar", PageController, :links
|
||||
get "/anteckningar", PageController, :notes
|
||||
get "/sok", PageController, :search
|
||||
|
||||
get "/prenumerera.xml", FeedController, :feed
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue