Adding hero image uploading feature
This commit is contained in:
parent
5848e22bf5
commit
219b1e27bc
@ -3735,4 +3735,4 @@ customElements.define('tags-input', class extends HTMLElement {
|
|||||||
this.input.removeEventListener('keydown', this.handleKeydown)
|
this.input.removeEventListener('keydown', this.handleKeydown)
|
||||||
this.tagsWrapper.removeEventListener('click', this.handleClick)
|
this.tagsWrapper.removeEventListener('click', this.handleClick)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
78
css/main.css
78
css/main.css
@ -2,7 +2,7 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-family: "Inter", sans-serif;
|
font-family: "Archivo", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
@ -21,8 +21,8 @@ body {
|
|||||||
body,
|
body,
|
||||||
body * {
|
body * {
|
||||||
--accent-color: #256eff;
|
--accent-color: #256eff;
|
||||||
--text-color: 36, 36, 36;
|
--text-color: 20, 20, 20;
|
||||||
--background-color: 248, 248, 248;
|
--background-color: 255, 255, 255;
|
||||||
--foreground-color: rgb(255, 255, 255);
|
--foreground-color: rgb(255, 255, 255);
|
||||||
--danger-color: rgb(255, 75, 75);
|
--danger-color: rgb(255, 75, 75);
|
||||||
--green: #1cad59;
|
--green: #1cad59;
|
||||||
@ -208,8 +208,9 @@ img {
|
|||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h3 {
|
h3 {
|
||||||
font-size: 1rem;
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h4 {
|
.h4 {
|
||||||
@ -362,7 +363,7 @@ img {
|
|||||||
height: 0.4ch;
|
height: 0.4ch;
|
||||||
width: 0.4ch;
|
width: 0.4ch;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
background-color: currentColor;
|
background-color: var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
@ -596,7 +597,6 @@ sm-copy {
|
|||||||
grid-template-columns: auto 1fr auto auto;
|
grid-template-columns: auto 1fr auto auto;
|
||||||
background-color: rgba(var(--background-color), 1);
|
background-color: rgba(var(--background-color), 1);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
border-bottom: thin solid rgba(var(--text-color), 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#expanding_search {
|
#expanding_search {
|
||||||
@ -663,11 +663,11 @@ theme-toggle {
|
|||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
width: 5.2rem;
|
width: 5.2rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: rgba(var(--text-color), 0.02);
|
background-color: #e6352f08;
|
||||||
}
|
}
|
||||||
.category .icon {
|
.category .icon {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
transition: transform 0.3s;
|
transition: transform 0.3s, background-color 0.3s;
|
||||||
transform-origin: top;
|
transform-origin: top;
|
||||||
}
|
}
|
||||||
.category:hover .icon {
|
.category:hover .icon {
|
||||||
@ -687,20 +687,21 @@ theme-toggle {
|
|||||||
.article-card__title {
|
.article-card__title {
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
.article-card .flex {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.article-card__category {
|
.article-card__category {
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
background-color: #256eff08;
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
border-radius: 0.2rem;
|
border-radius: 0.2rem;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
padding: 0.2rem 0.4rem;
|
padding: 0.2rem 0.4rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: rgba(var(--text-color), 0.8);
|
color: var(--accent-color) !important;
|
||||||
justify-self: flex-start;
|
justify-self: flex-start;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
.article-card .flex {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#trending_article_container,
|
#trending_article_container,
|
||||||
#query_results_list,
|
#query_results_list,
|
||||||
@ -711,7 +712,6 @@ theme-toggle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.trending-article {
|
.trending-article {
|
||||||
counter-increment: trending;
|
|
||||||
gap: 0.5rem 1.5rem;
|
gap: 0.5rem 1.5rem;
|
||||||
}
|
}
|
||||||
.trending-article a:first-of-type {
|
.trending-article a:first-of-type {
|
||||||
@ -762,8 +762,7 @@ theme-toggle {
|
|||||||
|
|
||||||
#article {
|
#article {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 1.5rem;
|
flex-wrap: wrap;
|
||||||
max-height: 100%;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
#article main > section:last-of-type {
|
#article main > section:last-of-type {
|
||||||
@ -793,9 +792,25 @@ theme-toggle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hero-section {
|
.hero-section {
|
||||||
|
position: relative;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
grid-template-columns: minmax(0, 1fr);
|
margin-top: 1.5rem;
|
||||||
|
align-content: flex-end;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.hero-section p {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
.hero-section .overlay {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(to top, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0));
|
||||||
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#article_image {
|
#article_image {
|
||||||
@ -930,7 +945,7 @@ theme-toggle {
|
|||||||
#preview_popup h1,
|
#preview_popup h1,
|
||||||
#article h1 {
|
#article h1 {
|
||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
line-height: 1.3;
|
line-height: 1.1;
|
||||||
}
|
}
|
||||||
#preview_popup h3:not(:first-of-type),
|
#preview_popup h3:not(:first-of-type),
|
||||||
#article h3:not(:first-of-type) {
|
#article h3:not(:first-of-type) {
|
||||||
@ -946,8 +961,7 @@ theme-toggle {
|
|||||||
}
|
}
|
||||||
#preview_popup p,
|
#preview_popup p,
|
||||||
#article p {
|
#article p {
|
||||||
font-family: "noto serif", serif;
|
font-size: 1.1rem;
|
||||||
font-size: 1rem;
|
|
||||||
line-height: 1.8;
|
line-height: 1.8;
|
||||||
}
|
}
|
||||||
#preview_popup p > *,
|
#preview_popup p > *,
|
||||||
@ -1072,6 +1086,10 @@ theme-toggle {
|
|||||||
justify-self: flex-end;
|
justify-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#article main {
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.writer-card .writer-profile {
|
.writer-card .writer-profile {
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
@ -1169,22 +1187,26 @@ theme-toggle {
|
|||||||
|
|
||||||
#preview_popup h1,
|
#preview_popup h1,
|
||||||
#article h1 {
|
#article h1 {
|
||||||
font-size: 2rem;
|
font-size: 2.2rem;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
#preview_popup h3,
|
||||||
|
#article h3 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
#article {
|
#article {
|
||||||
gap: 6vw;
|
padding: 0 4vw;
|
||||||
padding: 0;
|
|
||||||
grid-template-columns: 16rem 1fr;
|
|
||||||
}
|
}
|
||||||
#article main {
|
#article main {
|
||||||
width: 60ch;
|
width: 60ch;
|
||||||
padding: 1.5rem 0;
|
margin-left: 4vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
#article_aside {
|
#article_aside {
|
||||||
width: 20rem;
|
width: 20rem;
|
||||||
padding: 1.5rem 2rem;
|
padding: 1.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: -webkit-sticky;
|
position: -webkit-sticky;
|
||||||
@ -1259,7 +1281,7 @@ button:not(.button--primary) {
|
|||||||
}
|
}
|
||||||
.interact:hover,
|
.interact:hover,
|
||||||
button:not(.button--primary):hover {
|
button:not(.button--primary):hover {
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
background-color: #4885ff10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button--primary {
|
.button--primary {
|
||||||
|
|||||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -2,7 +2,7 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-family: "Inter", sans-serif;
|
font-family: "Archivo", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
@ -18,8 +18,8 @@ body {
|
|||||||
&,
|
&,
|
||||||
* {
|
* {
|
||||||
--accent-color: #256eff;
|
--accent-color: #256eff;
|
||||||
--text-color: 36, 36, 36;
|
--text-color: 20, 20, 20;
|
||||||
--background-color: 248, 248, 248;
|
--background-color: 255, 255, 255;
|
||||||
--foreground-color: rgb(255, 255, 255);
|
--foreground-color: rgb(255, 255, 255);
|
||||||
--danger-color: rgb(255, 75, 75);
|
--danger-color: rgb(255, 75, 75);
|
||||||
--green: #1cad59;
|
--green: #1cad59;
|
||||||
@ -199,8 +199,9 @@ img {
|
|||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h3 {
|
h3 {
|
||||||
font-size: 1rem;
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h4 {
|
.h4 {
|
||||||
@ -210,7 +211,13 @@ img {
|
|||||||
.h5 {
|
.h5 {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5 {
|
||||||
|
// font-family: "Spectral", serif;
|
||||||
|
}
|
||||||
.uppercase {
|
.uppercase {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
@ -352,7 +359,7 @@ img {
|
|||||||
height: 0.4ch;
|
height: 0.4ch;
|
||||||
width: 0.4ch;
|
width: 0.4ch;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
background-color: currentColor;
|
background-color: var(--accent-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
@ -563,7 +570,6 @@ sm-copy {
|
|||||||
grid-template-columns: auto 1fr auto auto;
|
grid-template-columns: auto 1fr auto auto;
|
||||||
background-color: rgba(var(--background-color), 1);
|
background-color: rgba(var(--background-color), 1);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
border-bottom: thin solid rgba(var(--text-color), 0.1);
|
|
||||||
}
|
}
|
||||||
#expanding_search {
|
#expanding_search {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -624,10 +630,10 @@ theme-toggle {
|
|||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
width: 5.2rem;
|
width: 5.2rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: rgba(var(--text-color), 0.02);
|
background-color: #e6352f08;
|
||||||
.icon {
|
.icon {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
transition: transform 0.3s;
|
transition: transform 0.3s, background-color 0.3s;
|
||||||
transform-origin: top;
|
transform-origin: top;
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
@ -649,21 +655,21 @@ theme-toggle {
|
|||||||
&__title {
|
&__title {
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
&__category {
|
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
padding: 0.2rem 0.4rem;
|
|
||||||
font-weight: 500;
|
|
||||||
color: rgba(var(--text-color), 0.8);
|
|
||||||
justify-self: flex-start;
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
.flex {
|
.flex {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.article-card__category {
|
||||||
|
background-color: #256eff08;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 0.2rem 0.4rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--accent-color) !important;
|
||||||
|
justify-self: flex-start;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
#trending_article_container,
|
#trending_article_container,
|
||||||
#query_results_list,
|
#query_results_list,
|
||||||
@ -673,7 +679,6 @@ theme-toggle {
|
|||||||
grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
|
||||||
}
|
}
|
||||||
.trending-article {
|
.trending-article {
|
||||||
counter-increment: trending;
|
|
||||||
gap: 0.5rem 1.5rem;
|
gap: 0.5rem 1.5rem;
|
||||||
a:first-of-type {
|
a:first-of-type {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -723,8 +728,7 @@ theme-toggle {
|
|||||||
|
|
||||||
#article {
|
#article {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 1.5rem;
|
flex-wrap: wrap;
|
||||||
max-height: 100%;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
main {
|
main {
|
||||||
& > section:last-of-type {
|
& > section:last-of-type {
|
||||||
@ -753,9 +757,25 @@ theme-toggle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.hero-section {
|
.hero-section {
|
||||||
|
position: relative;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
grid-template-columns: minmax(0, 1fr);
|
margin-top: 1.5rem;
|
||||||
|
align-content: flex-end;
|
||||||
|
width: 100%;
|
||||||
|
p {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(to top, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0));
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#article_image {
|
#article_image {
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
@ -888,7 +908,7 @@ theme-toggle {
|
|||||||
#article {
|
#article {
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
line-height: 1.3;
|
line-height: 1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3:not(:first-of-type) {
|
h3:not(:first-of-type) {
|
||||||
@ -901,8 +921,8 @@ theme-toggle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
font-family: "noto serif", serif;
|
// font-family: "Roboto", sans-serif;
|
||||||
font-size: 1rem;
|
font-size: 1.1rem;
|
||||||
line-height: 1.8;
|
line-height: 1.8;
|
||||||
& > * {
|
& > * {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
@ -1017,6 +1037,11 @@ theme-toggle {
|
|||||||
#search_button {
|
#search_button {
|
||||||
justify-self: flex-end;
|
justify-self: flex-end;
|
||||||
}
|
}
|
||||||
|
#article {
|
||||||
|
main {
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
.writer-card {
|
.writer-card {
|
||||||
.writer-profile {
|
.writer-profile {
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
@ -1104,21 +1129,24 @@ theme-toggle {
|
|||||||
#preview_popup,
|
#preview_popup,
|
||||||
#article {
|
#article {
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 2rem;
|
font-size: 2.2rem;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#article {
|
#article {
|
||||||
gap: 6vw;
|
padding: 0 4vw;
|
||||||
padding: 0;
|
|
||||||
grid-template-columns: 16rem 1fr;
|
|
||||||
main {
|
main {
|
||||||
width: 60ch;
|
width: 60ch;
|
||||||
padding: 1.5rem 0;
|
margin-left: 4vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#article_aside {
|
#article_aside {
|
||||||
width: 20rem;
|
width: 20rem;
|
||||||
padding: 1.5rem 2rem;
|
padding: 1.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
@ -1186,7 +1214,7 @@ theme-toggle {
|
|||||||
button:not(.button--primary) {
|
button:not(.button--primary) {
|
||||||
transition: background-color 0.3s;
|
transition: background-color 0.3s;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
background-color: #4885ff10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.button--primary {
|
.button--primary {
|
||||||
|
|||||||
128
index.html
128
index.html
@ -13,6 +13,9 @@
|
|||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=Noto+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=Noto+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap"
|
||||||
rel="stylesheet">
|
rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@400..700&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Barlow:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Merriweather+Sans:wght@400..800&display=swap" rel="stylesheet">
|
||||||
<script src="purify.min.js" defer></script>
|
<script src="purify.min.js" defer></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@6.4.6" defer></script>
|
<script src="https://cdn.jsdelivr.net/npm/fuse.js@6.4.6" defer></script>
|
||||||
<script id="floGlobals">
|
<script id="floGlobals">
|
||||||
@ -259,6 +262,7 @@
|
|||||||
<div id="article_contributors" class="flex"></div>
|
<div id="article_contributors" class="flex"></div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<button id="go_to_top" class="floating-button hide" onclick="goToTop()">
|
<button id="go_to_top" class="floating-button hide" onclick="goToTop()">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
fill="#000000">
|
fill="#000000">
|
||||||
@ -430,6 +434,11 @@
|
|||||||
</header>
|
</header>
|
||||||
<section class="grid gap-1-5">
|
<section class="grid gap-1-5">
|
||||||
<div class="grid gap-1-5">
|
<div class="grid gap-1-5">
|
||||||
|
<label class="grid gap-0-5">
|
||||||
|
<h5>Select Hero image</h5>
|
||||||
|
<img src="" alt="" id="preview_image">
|
||||||
|
<input id="select_image" type="file" accept="image">
|
||||||
|
</label>
|
||||||
<div class="grid gap-0-5">
|
<div class="grid gap-0-5">
|
||||||
<h5>Title</h5>
|
<h5>Title</h5>
|
||||||
<sm-input id="edit_title" required></sm-input>
|
<sm-input id="edit_title" required></sm-input>
|
||||||
@ -438,16 +447,12 @@
|
|||||||
<h5>Select category</h5>
|
<h5>Select category</h5>
|
||||||
<sm-select id="edit_category"></sm-select>
|
<sm-select id="edit_category"></sm-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-0-5">
|
</div>
|
||||||
<h5>Hero image URL</h5>
|
<div class="grid gap-1-5">
|
||||||
<sm-input id="edit_image" type="url"></sm-input>
|
|
||||||
</div>
|
|
||||||
<div class="grid gap-0-5">
|
<div class="grid gap-0-5">
|
||||||
<h5>Summary</h5>
|
<h5>Summary</h5>
|
||||||
<sm-textarea id="edit_summary" rows="4"></sm-textarea>
|
<sm-textarea id="edit_summary" rows="4"></sm-textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="grid gap-1-5">
|
|
||||||
<div class="grid gap-0-5">
|
<div class="grid gap-0-5">
|
||||||
<h5>Add tags</h5>
|
<h5>Add tags</h5>
|
||||||
<tags-input id="edit_tags" limit="10"></tags-input>
|
<tags-input id="edit_tags" limit="10"></tags-input>
|
||||||
@ -544,8 +549,9 @@
|
|||||||
</a>
|
</a>
|
||||||
<div class="flex align-center" style="margin-top: 0.3rem;">
|
<div class="flex align-center" style="margin-top: 0.3rem;">
|
||||||
<a href="" class="article-card__category interact"></a>
|
<a href="" class="article-card__category interact"></a>
|
||||||
<span class="trending-article__read-time h5"></span><span class="bullet-point"></span><time
|
<time class="trending-article__published h5"></time>
|
||||||
class="trending-article__published h5"></time>
|
<span class="bullet-point"></span>
|
||||||
|
<span class="trending-article__read-time h5"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -556,8 +562,9 @@
|
|||||||
</a>
|
</a>
|
||||||
<div class="flex align-center" style="margin-top: 0.3rem;">
|
<div class="flex align-center" style="margin-top: 0.3rem;">
|
||||||
<a href="" class="article-card__category interact"></a>
|
<a href="" class="article-card__category interact"></a>
|
||||||
<span class="article-card__read-time"></span><span class="bullet-point"></span>
|
|
||||||
<time class="article-card__published"></time>
|
<time class="article-card__published"></time>
|
||||||
|
<span class="bullet-point"></span>
|
||||||
|
<span class="article-card__read-time"></span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
@ -1164,11 +1171,13 @@
|
|||||||
getRef('news_categories_list').innerHTML = ''
|
getRef('news_categories_list').innerHTML = ''
|
||||||
getRef('news_categories_list').append(frag)
|
getRef('news_categories_list').append(frag)
|
||||||
const arrOfArticles = getArrayOfObj(floGlobals.appObjects.rmTimes.articles)
|
const arrOfArticles = getArrayOfObj(floGlobals.appObjects.rmTimes.articles)
|
||||||
// Render trending article card
|
|
||||||
let sortedByVotes = arrOfArticles.sort((a, b) => b.votes - a.votes)
|
let sortedByVotes = arrOfArticles.sort((a, b) => b.votes - a.votes)
|
||||||
sortedByVotes.slice(0, 4).forEach(articleDetail => frag.append(render.trendingArticleCard(articleDetail)))
|
// Render trending article card
|
||||||
getRef('trending_article_container').innerHTML = ''
|
compactIDB.readData('appObjects', 'heroImages').then(heroImages => {
|
||||||
getRef('trending_article_container').append(frag)
|
sortedByVotes.slice(0, 4).forEach(articleDetail => frag.append(render.trendingArticleCard({ ...articleDetail, heroImage: heroImages[articleDetail.uid].thumbnail })))
|
||||||
|
getRef('trending_article_container').innerHTML = ''
|
||||||
|
getRef('trending_article_container').append(frag)
|
||||||
|
})
|
||||||
// render latest articles
|
// render latest articles
|
||||||
const sortedArticles = sortedByVotes.slice(4).sort((a, b) => b.published - a.published)
|
const sortedArticles = sortedByVotes.slice(4).sort((a, b) => b.published - a.published)
|
||||||
sortedArticles.forEach(articleDetail => frag.append(render.articleCard(articleDetail)))
|
sortedArticles.forEach(articleDetail => frag.append(render.articleCard(articleDetail)))
|
||||||
@ -1177,9 +1186,9 @@
|
|||||||
},
|
},
|
||||||
async article(articleID, firstLoad = true) {
|
async article(articleID, firstLoad = true) {
|
||||||
const frag = document.createDocumentFragment()
|
const frag = document.createDocumentFragment()
|
||||||
const allArticles = await compactIDB.readData('appObjects', 'articlesContent')
|
const [allArticles, heroImages] = await Promise.all([compactIDB.readData('appObjects', 'articlesContent'), compactIDB.readData('appObjects', 'heroImages')])
|
||||||
const { title, published, readTime, contributors, updated, summary, heroImage } = floGlobals.appObjects.rmTimes.articles[articleID]
|
const { title, published, readTime, contributors, updated, summary } = floGlobals.appObjects.rmTimes.articles[articleID]
|
||||||
getRef('article_image').src = heroImage
|
getRef('article_image').src = heroImages[articleID].full
|
||||||
getRef('article_title').textContent = title
|
getRef('article_title').textContent = title
|
||||||
getRef('article_summary').textContent = summary
|
getRef('article_summary').textContent = summary
|
||||||
getRef('published_time').textContent = `${getFormattedTime(published, 'date-only')}${updated ? `, Updated ${relativeTime.from(updated)}` : ''}`
|
getRef('published_time').textContent = `${getFormattedTime(published, 'date-only')}${updated ? `, Updated ${relativeTime.from(updated)}` : ''}`
|
||||||
@ -1276,8 +1285,10 @@
|
|||||||
Promise.all([
|
Promise.all([
|
||||||
floCloudAPI.requestObjectData('rmTimes'),
|
floCloudAPI.requestObjectData('rmTimes'),
|
||||||
floCloudAPI.requestObjectData('articlesContent'),
|
floCloudAPI.requestObjectData('articlesContent'),
|
||||||
|
floCloudAPI.requestObjectData('heroImages'),
|
||||||
]).then(() => {
|
]).then(() => {
|
||||||
delete floGlobals.appObjects.articlesContent
|
delete floGlobals.appObjects.articlesContent
|
||||||
|
delete floGlobals.appObjects.heroImages
|
||||||
showPage(window.location.hash, { firstLoad: true })
|
showPage(window.location.hash, { firstLoad: true })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1294,19 +1305,6 @@
|
|||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
// implement image resizing
|
|
||||||
function resizeImage(img, maxWidth, maxHeight) {
|
|
||||||
const canvas = document.createElement('canvas')
|
|
||||||
const ctx = canvas.getContext('2d')
|
|
||||||
const ratio = 1
|
|
||||||
canvas.width = img.width * ratio
|
|
||||||
canvas.height = img.height * ratio
|
|
||||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
|
|
||||||
const dataURL = canvas.toDataURL('image/jpeg', 0.5)
|
|
||||||
return dataURL
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const categories = [
|
const categories = [
|
||||||
{
|
{
|
||||||
title: 'Culture',
|
title: 'Culture',
|
||||||
@ -1797,7 +1795,7 @@
|
|||||||
const isPublished = floGlobals.appObjects.rmTimes.articles.hasOwnProperty(articleID)
|
const isPublished = floGlobals.appObjects.rmTimes.articles.hasOwnProperty(articleID)
|
||||||
getConfirmation(`${isPublished ? 'Update' : 'Publish'} article?`).then(res => {
|
getConfirmation(`${isPublished ? 'Update' : 'Publish'} article?`).then(res => {
|
||||||
if (res) {
|
if (res) {
|
||||||
const { title, category, summary, published, tags, contributors } = getArticleMetaData()
|
const { title, category, summary, published, tags, contributors, heroImage } = getArticleMetaData()
|
||||||
floGlobals.appObjects.adminData.publishedVc[vectorClock] = true
|
floGlobals.appObjects.adminData.publishedVc[vectorClock] = true
|
||||||
floGlobals.appObjects.articlesContent[articleID] = content
|
floGlobals.appObjects.articlesContent[articleID] = content
|
||||||
if (isPublished) {
|
if (isPublished) {
|
||||||
@ -1816,10 +1814,12 @@
|
|||||||
floGlobals.appObjects.rmTimes.articles[articleID].tags = tags
|
floGlobals.appObjects.rmTimes.articles[articleID].tags = tags
|
||||||
floGlobals.appObjects.rmTimes.articles[articleID].readTime = readTime
|
floGlobals.appObjects.rmTimes.articles[articleID].readTime = readTime
|
||||||
floGlobals.appObjects.rmTimes.articles[articleID].summary = summary
|
floGlobals.appObjects.rmTimes.articles[articleID].summary = summary
|
||||||
|
floGlobals.appObjects.heroImages[articleID] = heroImage
|
||||||
Promise.all([
|
Promise.all([
|
||||||
floCloudAPI.updateObjectData('rmTimes'),
|
floCloudAPI.updateObjectData('rmTimes'),
|
||||||
floCloudAPI.updateObjectData('adminData'),
|
floCloudAPI.updateObjectData('adminData'),
|
||||||
floCloudAPI.updateObjectData('articlesContent'),
|
floCloudAPI.updateObjectData('articlesContent'),
|
||||||
|
floCloudAPI.updateObjectData('heroImages'),
|
||||||
]).then(() => {
|
]).then(() => {
|
||||||
notify(`${isPublished ? 'Updated' : 'Published'} article`, 'success')
|
notify(`${isPublished ? 'Updated' : 'Published'} article`, 'success')
|
||||||
if (!isPublished) {
|
if (!isPublished) {
|
||||||
@ -1838,9 +1838,9 @@
|
|||||||
const { message: { articleID, title, contributors } } = floGlobals.generalData[`publishing_requests|${floGlobals.adminID}|${floGlobals.application}`][vc]
|
const { message: { articleID, title, contributors } } = floGlobals.generalData[`publishing_requests|${floGlobals.adminID}|${floGlobals.application}`][vc]
|
||||||
const isPublished = floGlobals.appObjects.rmTimes.articles.hasOwnProperty(articleID)
|
const isPublished = floGlobals.appObjects.rmTimes.articles.hasOwnProperty(articleID)
|
||||||
if (isPublished)
|
if (isPublished)
|
||||||
setArticleMetaData(floGlobals.appObjects.rmTimes.articles[articleID])
|
setArticleMetaData(floGlobals.appObjects.rmTimes.articles[articleID], articleID)
|
||||||
else
|
else
|
||||||
setArticleMetaData({ title, contributors })
|
setArticleMetaData({ title, contributors }, articleID)
|
||||||
floGlobals.subAdminData = {
|
floGlobals.subAdminData = {
|
||||||
actionType: 'request',
|
actionType: 'request',
|
||||||
articleID,
|
articleID,
|
||||||
@ -1876,10 +1876,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setArticleMetaData(details) {
|
async function setArticleMetaData(details, articleID) {
|
||||||
const { category, title, tags, summary, published, contributors, heroImage } = details
|
const { category, title, tags, summary, published, contributors } = details
|
||||||
|
const heroImage = floGlobals.appObjects.heroImages[articleID]
|
||||||
getRef('edit_title').value = title;
|
getRef('edit_title').value = title;
|
||||||
getRef('edit_image').value = heroImage || '';
|
if (heroImage) {
|
||||||
|
getRef('preview_image').src = heroImage.thumbnail
|
||||||
|
getRef('select_image').value = '';
|
||||||
|
} else {
|
||||||
|
getRef('preview_image').src = ''
|
||||||
|
}
|
||||||
getRef('edit_summary').value = summary || '';
|
getRef('edit_summary').value = summary || '';
|
||||||
getRef('edit_category').value = category || '';
|
getRef('edit_category').value = category || '';
|
||||||
getRef('edit_contributors').value = contributors || [];
|
getRef('edit_contributors').value = contributors || [];
|
||||||
@ -1891,7 +1897,7 @@
|
|||||||
return {
|
return {
|
||||||
title: getRef('edit_title').value.trim(),
|
title: getRef('edit_title').value.trim(),
|
||||||
category: getRef('edit_category').value,
|
category: getRef('edit_category').value,
|
||||||
heroImage: getRef('edit_image').value,
|
heroImage: currentSelectedImage,
|
||||||
summary: getRef('edit_summary').value.trim(),
|
summary: getRef('edit_summary').value.trim(),
|
||||||
published: new Date(getRef('edit_published').value).getTime(),
|
published: new Date(getRef('edit_published').value).getTime(),
|
||||||
contributors: getRef('edit_contributors').value,
|
contributors: getRef('edit_contributors').value,
|
||||||
@ -1902,7 +1908,7 @@
|
|||||||
if (e.target.closest('.edit-article')) {
|
if (e.target.closest('.edit-article')) {
|
||||||
const button = e.target.closest('.edit-article');
|
const button = e.target.closest('.edit-article');
|
||||||
const articleID = button.dataset.articleId;
|
const articleID = button.dataset.articleId;
|
||||||
setArticleMetaData(floGlobals.appObjects.rmTimes.articles[articleID])
|
setArticleMetaData(floGlobals.appObjects.rmTimes.articles[articleID], articleID)
|
||||||
floGlobals.subAdminData = {
|
floGlobals.subAdminData = {
|
||||||
actionType: 'analytics',
|
actionType: 'analytics',
|
||||||
articleID,
|
articleID,
|
||||||
@ -1921,11 +1927,11 @@
|
|||||||
floGlobals.appObjects.rmTimes.articles[articleID].title = title
|
floGlobals.appObjects.rmTimes.articles[articleID].title = title
|
||||||
floGlobals.appObjects.rmTimes.articles[articleID].tags = tags
|
floGlobals.appObjects.rmTimes.articles[articleID].tags = tags
|
||||||
floGlobals.appObjects.rmTimes.articles[articleID].summary = summary
|
floGlobals.appObjects.rmTimes.articles[articleID].summary = summary
|
||||||
floGlobals.appObjects.rmTimes.articles[articleID].heroImage = heroImage
|
|
||||||
floGlobals.appObjects.rmTimes.articles[articleID].contributors = contributors
|
floGlobals.appObjects.rmTimes.articles[articleID].contributors = contributors
|
||||||
|
floGlobals.appObjects.heroImages[articleID] = heroImage
|
||||||
Promise.all([
|
Promise.all([
|
||||||
floCloudAPI.updateObjectData('rmTimes'),
|
floCloudAPI.updateObjectData('rmTimes'),
|
||||||
floCloudAPI.updateObjectData('adminData'),
|
floCloudAPI.updateObjectData('heroImages'),
|
||||||
]).then(() => {
|
]).then(() => {
|
||||||
notify(`Updated article meta data`, 'success')
|
notify(`Updated article meta data`, 'success')
|
||||||
hidePopup()
|
hidePopup()
|
||||||
@ -1991,7 +1997,10 @@
|
|||||||
console.log('calculated votes')
|
console.log('calculated votes')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
floGlobals.appObjects.articlesContent = await compactIDB.readData('appObjects', 'articlesContent')
|
Promise.all([compactIDB.readData('appObjects', 'articlesContent'), compactIDB.readData('appObjects', 'heroImages')]).then(res => {
|
||||||
|
floGlobals.appObjects.articlesContent = res[0];
|
||||||
|
floGlobals.appObjects.heroImages = res[1];
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getRef('section_selector').addEventListener('change', e => {
|
getRef('section_selector').addEventListener('change', e => {
|
||||||
@ -2118,6 +2127,45 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let currentSelectedImage = {}
|
||||||
|
getRef('select_image').addEventListener('change', function (e) {
|
||||||
|
currentSelectedImage = {}
|
||||||
|
if (this.files.length === 0) return
|
||||||
|
const selectedFile = this.files[0]
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = function (e) {
|
||||||
|
// show selected image in the preview
|
||||||
|
getRef('preview_image').src = e.target.result;
|
||||||
|
getRef('preview_image').addEventListener('load', function (event) {
|
||||||
|
// Dynamically create a canvas element
|
||||||
|
const canvas = createElement("canvas");
|
||||||
|
const context = canvas.getContext("2d");
|
||||||
|
const originalWidth = getRef('preview_image').width;
|
||||||
|
const originalHeight = getRef('preview_image').height;
|
||||||
|
const resizingFactor = parseFloat((1 / (originalWidth / 600)).toFixed(2));
|
||||||
|
|
||||||
|
const canvasWidth = originalWidth * resizingFactor;
|
||||||
|
const canvasHeight = originalHeight * resizingFactor;
|
||||||
|
|
||||||
|
canvas.width = canvasWidth;
|
||||||
|
canvas.height = canvasHeight;
|
||||||
|
|
||||||
|
context.drawImage(
|
||||||
|
getRef('preview_image'),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
originalWidth * resizingFactor,
|
||||||
|
originalHeight * resizingFactor
|
||||||
|
);
|
||||||
|
currentSelectedImage['thumbnail'] = canvas.toDataURL(selectedFile.type);
|
||||||
|
}, { once: true });
|
||||||
|
currentSelectedImage.name = selectedFile.name
|
||||||
|
currentSelectedImage.type = selectedFile.type
|
||||||
|
currentSelectedImage.full = e.target.result
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(this.files[0]);
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script id="onLoadStartUp">
|
<script id="onLoadStartUp">
|
||||||
function onLoadStartUp() {
|
function onLoadStartUp() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user