Added Frontend
This commit is contained in:
245
frontend/css/index.css
Normal file
245
frontend/css/index.css
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: #03071E;
|
||||||
|
color: #EAE2B7;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
font-size: 125%;
|
||||||
|
text-decoration: none;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 150%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 200%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: 20px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
ul li {
|
||||||
|
padding-right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
list-style: georgian;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background-color: #03071E;
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
margin: 100px 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-family: "Staatliches", sans-serif;
|
||||||
|
}
|
||||||
|
.header-title h1 {
|
||||||
|
font-size: 90px;
|
||||||
|
letter-spacing: 30px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.header-title h2 {
|
||||||
|
font-size: 30px;
|
||||||
|
letter-spacing: 10px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 3px;
|
||||||
|
background-color: #ad080f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation {
|
||||||
|
background-color: black;
|
||||||
|
color: inherit;
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
width: 100%;
|
||||||
|
padding-top: 1%;
|
||||||
|
padding-bottom: 1%;
|
||||||
|
height: 5%;
|
||||||
|
min-height: 50px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.navigation img {
|
||||||
|
margin-right: auto;
|
||||||
|
width: 3%;
|
||||||
|
min-width: 30px;
|
||||||
|
padding-left: 2.5%;
|
||||||
|
}
|
||||||
|
.navigation a {
|
||||||
|
padding: 0 2%;
|
||||||
|
font-size: 200%;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article {
|
||||||
|
padding: 2%;
|
||||||
|
}
|
||||||
|
.article:hover {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-body {
|
||||||
|
width: 60;
|
||||||
|
font-size: 80%;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-top: 1%;
|
||||||
|
font-family: "Roboto Mono", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-body, .article-body-fulltext {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-description {
|
||||||
|
font-weight: 500;
|
||||||
|
font-family: "Roboto Mono", monospace;
|
||||||
|
color: #D00000;
|
||||||
|
font-size: 75%;
|
||||||
|
margin-top: 0.5%;
|
||||||
|
}
|
||||||
|
.article-description:p {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.articles {
|
||||||
|
margin: auto;
|
||||||
|
width: 80%;
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.foot {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
margin: 2.5% 0;
|
||||||
|
}
|
||||||
|
.foot a {
|
||||||
|
font-family: "Roboto Mono", monospace;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 0 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-section {
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
width: 60%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.legal-section {
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
.legal-section p {
|
||||||
|
margin-bottom: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-section {
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
.contact-section p {
|
||||||
|
margin-bottom: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
border: 2px solid #D62828;
|
||||||
|
padding: 5px 3px;
|
||||||
|
background: #03071E;
|
||||||
|
color: #EAE2B7;
|
||||||
|
margin: 0 10px;
|
||||||
|
font-size: 1rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
max-width: 200px;
|
||||||
|
width: 10%;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1000px) {
|
||||||
|
.navigation {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.navigation img {
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.navigation * {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.header-title h1 {
|
||||||
|
font-size: 50px;
|
||||||
|
letter-spacing: 20px;
|
||||||
|
}
|
||||||
|
.header-title h2 {
|
||||||
|
font-size: 20px;
|
||||||
|
letter-spacing: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.articles {
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
.articles div {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 130%;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.foot {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
.header-title h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
letter-spacing: 5px;
|
||||||
|
}
|
||||||
|
.header-title h2 {
|
||||||
|
letter-spacing: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-description p {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}/*# sourceMappingURL=index.css.map */
|
||||||
1
frontend/css/index.css.map
Normal file
1
frontend/css/index.css.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["index.sass","index.css"],"names":[],"mappings":"AAMA;EACE,SAAA;EACA,UAAA;EACA,aAAA;EACA,sBAAA;EACA,yBAXiB;EAYjB,cAXW;ACMb;;ADOA;EACE,cAAA;EACA,eAAA;EACA,qBAAA;EACA,mBAAA;ACJF;;ADMA;EACE,eAAA;EACA,SAAA;ACHF;;ADKA;EACE,eAAA;EACA,SAAA;ACFF;;ADIA;EACE,aAAA;EACA,mBAAA;EACA,eAAA;EACA,gBAAA;ACDF;ADGE;EACE,mBAAA;ACDJ;;ADGA;EACE,aAAA;EACA,sBAAA;EACA,oBAAA;ACAF;;ADEA;EACE,yBA3CiB;EA4CjB,WAAA;EACA,aAAA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,iCAAA;ACCF;;ADCA;EACE,eAAA;EACA,aAAA;EACA,sBAAA;EACA,mBAAA;EACA,uBAAA;EACA,sCAAA;ACEF;ADAE;EACE,eAAA;EACA,oBAAA;EACA,SAAA;ACEJ;ADAE;EACE,eAAA;EACA,oBAAA;EACA,SAAA;ACEJ;;ADAA;EACE,WAAA;EACA,yBAAA;ACGF;;ADDA;EACE,uBAAA;EACA,cAAA;EACA,iCAAA;EACA,WAAA;EACA,eAAA;EACA,kBAAA;EACA,UAAA;EACA,gBAAA;EACA,aAAA;EACA,mBAAA;ACIF;ADFE;EACE,kBAAA;EACA,SAAA;EACA,eAAA;EACA,kBAAA;ACIJ;ADFE;EACE,aAAA;EACA,eAAA;EACA,mBAAA;ACIJ;;ADFA;EACE,WAAA;ACKF;ADHE;EACE,YAAA;ACKJ;;ADHA;EACE,SAAA;EACA,cAAA;EACA,mBAAA;EACA,cAAA;EACA,qCAAA;ACMF;;ADJA;EACE,WAAA;ACOF;;ADLA;EACE,gBAAA;EACA,qCAAA;EACA,cAAA;EACA,cAAA;EACA,gBAAA;ACQF;ADNE;EACE,gBAAA;ACQJ;;ADNA;EACE,YAAA;EACA,UAAA;EACA,iCAAA;ACSF;;ADPA;EACE,aAAA;EACA,mBAAA;EACA,8BAAA;EACA,WAAA;EACA,cAAA;ACUF;ADRE;EACE,qCAAA;EACA,mBAAA;EACA,cAAA;ACUJ;;ADRA;EACE,kBAAA;ACWF;;ADTA;EACE,iCAAA;EACA,UAAA;EACA,kBAAA;ACYF;ADPA;EACE,iCAAA;EACA,UAAA;ACSF;ADLA;EACE,iBAAA;ACOF;;ADJA;EACE,iCAAA;EACA,UAAA;ACOF;ADHA;EACE,iBAAA;ACKF;;ADFA;EACI,yBAAA;EACA,gBAAA;EACA,mBA7Ke;EA8Kf,cA7KS;EA8KT,cAAA;EACA,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,UAAA;EACA,gBAAA;ACKJ;;ADFA;EACE;IACE,sBAAA;ECKF;EDHE;IACE,cAAA;IACA,UAAA;ECKJ;EDHE;IACE,aAAA;ECKJ;;EDHA;IACE,kBAAA;ECMF;EDJE;IACE,eAAA;IACA,oBAAA;ECMJ;EDJE;IACE,eAAA;IACA,oBAAA;ECMJ;;EDJA;IACE,UAAA;ECOF;EDLE;IACE,cAAA;ECOJ;;EDLA;IACE,eAAA;ECQF;;EDPA;IACE,eAAA;ECUF;;EDRA;IACE,sBAAA;ECWF;AACF;ADRA;EAEI;IACE,eAAA;IACA,mBAAA;ECSJ;EDPE;IACE,mBAAA;ECSJ;;EDNE;IACE,aAAA;IACA,mBAAA;IACA,8BAAA;ECSJ;AACF","file":"index.css"}
|
||||||
235
frontend/css/index.sass
Normal file
235
frontend/css/index.sass
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
$background-color: #03071E
|
||||||
|
$text-color: #EAE2B7
|
||||||
|
$secondary-text-color: #F77F00
|
||||||
|
$primary-color: #D62828
|
||||||
|
$secondary-color: #F77F00
|
||||||
|
|
||||||
|
body
|
||||||
|
margin: 0
|
||||||
|
padding: 0
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
background-color: $background-color
|
||||||
|
color: $text-color
|
||||||
|
|
||||||
|
a
|
||||||
|
color: inherit
|
||||||
|
font-size: 125%
|
||||||
|
text-decoration: none
|
||||||
|
letter-spacing: 2px
|
||||||
|
|
||||||
|
p
|
||||||
|
font-size: 150%
|
||||||
|
margin: 0
|
||||||
|
|
||||||
|
h3
|
||||||
|
font-size: 200%
|
||||||
|
margin: 0
|
||||||
|
|
||||||
|
ul
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
font-size: 20px
|
||||||
|
list-style: none
|
||||||
|
|
||||||
|
li
|
||||||
|
padding-right: 30px
|
||||||
|
|
||||||
|
ol
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
list-style: georgian
|
||||||
|
|
||||||
|
.header
|
||||||
|
background-color: $background-color
|
||||||
|
width: 100%
|
||||||
|
height: 100px
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: flex-end
|
||||||
|
font-family: 'Roboto', sans-serif
|
||||||
|
|
||||||
|
.header-title
|
||||||
|
margin: 100px 0
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
align-items: center
|
||||||
|
justify-content: center
|
||||||
|
font-family: 'Staatliches', sans-serif
|
||||||
|
|
||||||
|
h1
|
||||||
|
font-size: 90px
|
||||||
|
letter-spacing: 30px
|
||||||
|
margin: 0
|
||||||
|
|
||||||
|
h2
|
||||||
|
font-size: 30px
|
||||||
|
letter-spacing: 10px
|
||||||
|
margin: 0
|
||||||
|
|
||||||
|
.divider
|
||||||
|
height: 3px
|
||||||
|
background-color: #ad080f
|
||||||
|
|
||||||
|
.navigation
|
||||||
|
background-color: black
|
||||||
|
color: inherit
|
||||||
|
font-family: 'Roboto', sans-serif
|
||||||
|
width: 100%
|
||||||
|
padding-top: 1%
|
||||||
|
padding-bottom: 1%
|
||||||
|
height: 5%
|
||||||
|
min-height: 50px
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
img
|
||||||
|
margin-right: auto
|
||||||
|
width: 3%
|
||||||
|
min-width: 30px
|
||||||
|
padding-left: 2.5%
|
||||||
|
|
||||||
|
a
|
||||||
|
padding: 0 2%
|
||||||
|
font-size: 200%
|
||||||
|
font-weight: bolder
|
||||||
|
|
||||||
|
.article
|
||||||
|
padding: 2%
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
color: white
|
||||||
|
|
||||||
|
.article-body
|
||||||
|
width: 60
|
||||||
|
font-size: 80%
|
||||||
|
font-weight: normal
|
||||||
|
margin-top: 1%
|
||||||
|
font-family: 'Roboto Mono', monospace
|
||||||
|
|
||||||
|
.article-body, .article-body-fulltext
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.article-description
|
||||||
|
font-weight: 500
|
||||||
|
font-family: 'Roboto Mono', monospace
|
||||||
|
color: #D00000
|
||||||
|
font-size: 75%
|
||||||
|
margin-top: 0.5%
|
||||||
|
|
||||||
|
&:p
|
||||||
|
white-space: pre
|
||||||
|
|
||||||
|
.articles
|
||||||
|
margin: auto
|
||||||
|
width: 80%
|
||||||
|
font-family: 'Roboto', sans-serif
|
||||||
|
|
||||||
|
.foot
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: space-between
|
||||||
|
width: 100%
|
||||||
|
margin: 2.5% 0
|
||||||
|
|
||||||
|
a
|
||||||
|
font-family: 'Roboto Mono', monospace
|
||||||
|
font-weight: normal
|
||||||
|
padding: 0 10%
|
||||||
|
|
||||||
|
i
|
||||||
|
margin-right: 20px
|
||||||
|
|
||||||
|
.about-section
|
||||||
|
font-family: "Roboto", sans-serif
|
||||||
|
width: 60%
|
||||||
|
text-align: center
|
||||||
|
margin:auto
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.legal-section
|
||||||
|
font-family: "Roboto", sans-serif
|
||||||
|
width: 60%
|
||||||
|
margin:auto
|
||||||
|
|
||||||
|
|
||||||
|
.legal-section p
|
||||||
|
margin-bottom: 5%
|
||||||
|
|
||||||
|
|
||||||
|
.contact-section
|
||||||
|
font-family: "Roboto", sans-serif
|
||||||
|
width: 60%
|
||||||
|
margin:auto
|
||||||
|
|
||||||
|
|
||||||
|
.contact-section p
|
||||||
|
margin-bottom: 5%
|
||||||
|
|
||||||
|
|
||||||
|
input
|
||||||
|
border: 2px solid $primary-color
|
||||||
|
padding: 5px 3px
|
||||||
|
background: $background-color
|
||||||
|
color: $text-color
|
||||||
|
margin: 0 10px
|
||||||
|
font-size: 1rem
|
||||||
|
border-radius: 3px
|
||||||
|
max-width: 200px
|
||||||
|
width: 10%
|
||||||
|
min-width: 100px
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width: 1000px)
|
||||||
|
.navigation
|
||||||
|
flex-direction: column
|
||||||
|
|
||||||
|
img
|
||||||
|
margin: 10px 0
|
||||||
|
padding: 0
|
||||||
|
|
||||||
|
*
|
||||||
|
margin: 5px 0
|
||||||
|
|
||||||
|
.header-title
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
h1
|
||||||
|
font-size: 50px
|
||||||
|
letter-spacing: 20px
|
||||||
|
|
||||||
|
h2
|
||||||
|
font-size: 20px
|
||||||
|
letter-spacing: 10px
|
||||||
|
|
||||||
|
.articles
|
||||||
|
width: 95%
|
||||||
|
|
||||||
|
div
|
||||||
|
margin: 10px 0
|
||||||
|
|
||||||
|
h3
|
||||||
|
font-size: 130%
|
||||||
|
p
|
||||||
|
font-size: 100%
|
||||||
|
|
||||||
|
.foot
|
||||||
|
flex-direction: column
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px)
|
||||||
|
.header-title
|
||||||
|
h1
|
||||||
|
font-size: 40px
|
||||||
|
letter-spacing: 5px
|
||||||
|
|
||||||
|
h2
|
||||||
|
letter-spacing: 3px
|
||||||
|
|
||||||
|
.article-description
|
||||||
|
p
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
justify-content: space-between
|
||||||
46
frontend/error/404.html
Normal file
46
frontend/error/404.html
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Error 404</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto&family=Roboto+Mono&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="ErrorDiv">
|
||||||
|
<h1>Error 404</h1>
|
||||||
|
<h2>Page Not Found</h2>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.ErrorDiv {
|
||||||
|
position: absolute;
|
||||||
|
margin: auto;
|
||||||
|
width: 50%;
|
||||||
|
text-align: center;
|
||||||
|
top: 50%;
|
||||||
|
left: 25%;
|
||||||
|
-ms-transform: translateY(-50%);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #03071e;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 800%;
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 400%;
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</html>
|
||||||
46
frontend/error/500.html
Normal file
46
frontend/error/500.html
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Error 500</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto&family=Roboto+Mono&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="ErrorDiv">
|
||||||
|
<h1>Error 500</h1>
|
||||||
|
<h2>Internal Server Error</h2>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.ErrorDiv {
|
||||||
|
position: absolute;
|
||||||
|
margin: auto;
|
||||||
|
width: 50%;
|
||||||
|
text-align: center;
|
||||||
|
top: 50%;
|
||||||
|
left: 25%;
|
||||||
|
-ms-transform: translateY(-50%);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #03071e;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 800%;
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 400%;
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</html>
|
||||||
32
frontend/html/about.html
Normal file
32
frontend/html/about.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="../css/index.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&family=Roboto:wght@400;700&family=Staatliches:wght@400;500&display=swap" rel="stylesheet">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="navigation">
|
||||||
|
<img id="logo" src="../img/logodark.svg">
|
||||||
|
<a href="../">Home</a>
|
||||||
|
<a href="about.html">About</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="about-section">
|
||||||
|
<h1>About</h1>
|
||||||
|
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="foot">
|
||||||
|
<a href="about.html">ABOUT</a>
|
||||||
|
<a href="contact.html">CONTACT</a>
|
||||||
|
<a href="legal-notice.html">LEGAL NOTICE</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</html>
|
||||||
94
frontend/html/article.gohtml
Normal file
94
frontend/html/article.gohtml
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de" dir="ltr">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{.Title}}</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="img/logodark.svg">
|
||||||
|
<base href="{{.BasePath}}">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/index.css">
|
||||||
|
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<meta name="title" content="{{.Title}}">
|
||||||
|
<meta name="og:title" content="{{.Title}}">
|
||||||
|
<meta name="description" content="{{.Summary}}">
|
||||||
|
<meta name="og:description" content="{{.Summary}}">
|
||||||
|
<link rel="img" src="{{.Image}}">
|
||||||
|
<meta name="og:image" content="{{.Image}}">
|
||||||
|
{{if .Authors}}
|
||||||
|
<meta name="author" content="{{index .Authors 0}}">
|
||||||
|
{{end}}
|
||||||
|
<meta name="keywords" content="{{.Tags}}">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navigation">
|
||||||
|
<img id="logo" src="img/logodark.svg">
|
||||||
|
<a href="#">Home</a>
|
||||||
|
<a href="html/about.html">About</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<div class="articles">
|
||||||
|
<div class="article">
|
||||||
|
|
||||||
|
<div class="article-header">
|
||||||
|
<h3>{{.Title}}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{if .Image}}
|
||||||
|
<div class="article-image">
|
||||||
|
<img src="{{.Image}}" alt="">
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
<div class="article-date">
|
||||||
|
<p>{{.Date}}</p>
|
||||||
|
{{if .Modified}}
|
||||||
|
<i>(modified)</i>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="article-authors">
|
||||||
|
{{range .Authors}}
|
||||||
|
<p>{{.}}</p>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="article-tags">
|
||||||
|
{{range .Tags}}
|
||||||
|
<p>{{.}}</p>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{if .Summary}}
|
||||||
|
<div class="article-summary">
|
||||||
|
<p>{{.Summary}}</p>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
<div class="article-body fulltext">
|
||||||
|
{{.Content}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="foot">
|
||||||
|
<a href="html/about.html">ABOUT</a>
|
||||||
|
<a href="html/contact.html">CONTACT</a>
|
||||||
|
<a href="html/legal-notice.html">LEGAL NOTICE</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</html>
|
||||||
37
frontend/html/contact.html
Normal file
37
frontend/html/contact.html
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<title>Contact</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../css/index.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&family=Roboto:wght@400;700&family=Staatliches:wght@400;500&display=swap" rel="stylesheet">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="navigation">
|
||||||
|
<img id="logo" src="../img/logodark.svg" alt="Logo">
|
||||||
|
<a href="../">Home</a>
|
||||||
|
<a href="about.html">About</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contact-section">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
|
||||||
|
<p>Twitter: theadversary</p>
|
||||||
|
<p>Instagram: theadversary</p>
|
||||||
|
<p>E-Mail: contact@theadversary.org</p>
|
||||||
|
<p>Post: Jahnstraße 5, Hühnfeld, Hessen, Deutschland</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="foot">
|
||||||
|
<a href="about.html">ABOUT</a>
|
||||||
|
<a href="contact.html">CONTACT</a>
|
||||||
|
<a href="legal-notice.html">LEGAL NOTICE</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</html>
|
||||||
65
frontend/html/landingpage.gohtml
Normal file
65
frontend/html/landingpage.gohtml
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de" dir="ltr">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>THE ADVERSARY</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="img/logodark.svg">
|
||||||
|
<base href="{{.BasePath}}">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/index.css">
|
||||||
|
<script src="js/api.js" type="text/javascript"></script>
|
||||||
|
<script src="js/main.js" type="text/javascript" defer></script>
|
||||||
|
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&family=Roboto:wght@400;700&family=Staatliches:wght@400;500&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navigation">
|
||||||
|
<img id="logo" src="img/logodark.svg">
|
||||||
|
<a href="#">Home</a>
|
||||||
|
<a href="html/about.html">About</a>
|
||||||
|
<input oninput="updateSeach(this.value)" type="text" placeholder="Search" name="" value="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header-title">
|
||||||
|
<h1>The Adversary</h1>
|
||||||
|
<h2>Assault penguins to the Power</h2>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div id="articles" class="articles">
|
||||||
|
<!--
|
||||||
|
<a href="#">
|
||||||
|
<div class="article">
|
||||||
|
<div class="article-header">
|
||||||
|
<h3>Java is trash, and here is the proof.</h3>
|
||||||
|
</div>
|
||||||
|
<div class="article-description">
|
||||||
|
<p><i>OPINION</i><i>DAVID</i><i>15.12.2021</i></p>
|
||||||
|
</div>
|
||||||
|
<div class="article-body">
|
||||||
|
<p>After a recent vulnerability voices get louder that demand to retire the language.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="foot">
|
||||||
|
<a href="html/about.html">ABOUT</a>
|
||||||
|
<a href="html/contact.html">CONTACT</a>
|
||||||
|
<a href="html/legal-notice.html">LEGAL NOTICE</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</html>
|
||||||
34
frontend/html/legal-notice.html
Normal file
34
frontend/html/legal-notice.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="../css/index.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&family=Roboto:wght@400;700&family=Staatliches:wght@400;500&display=swap" rel="stylesheet">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="navigation">
|
||||||
|
<img id="logo" src="../img/logodark.svg">
|
||||||
|
<a href="../">Home</a>
|
||||||
|
<a href="about.html">About</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="legal-section">
|
||||||
|
<h1>Legal Notice</h1>
|
||||||
|
<p>The information contained in this website is for general information purposes only. The information is provided by The Adversary and while we endeavour to keep the information up to date and correct, we make no representations or warranties of any kind, express or implied, about the completeness, accuracy, reliability, suitability or availability with respect to the website or the information, products, services, or related graphics contained on the website for any purpose. Any reliance you place on such information is therefore strictly at your own risk.</p>
|
||||||
|
<p>Through this website you are able to link to other websites which are not under the control of The Adversary. We have no control over the nature, content and availability of those sites. The inclusion of any links does not necessarily imply a recommendation or endorse the views expressed within them.</p>
|
||||||
|
<p>Every effort is made to keep the website up and running smoothly. However, The Adversary takes no responsibility for, and will not be liable for, the website being temporarily unavailable due to technical issues beyond our control.</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="foot">
|
||||||
|
<a href="about.html">ABOUT</a>
|
||||||
|
<a href="contact.html">CONTACT</a>
|
||||||
|
<a href="legal-notice.html">LEGAL NOTICE</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</html>
|
||||||
98
frontend/img/logodark.svg
Normal file
98
frontend/img/logodark.svg
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
sodipodi:docname="LOGO-FINAL-DARK.svg"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 17.197914 15.875005"
|
||||||
|
height="15.875005mm"
|
||||||
|
width="17.197914mm">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective1549"
|
||||||
|
inkscape:persp3d-origin="105 : -182.125 : 1"
|
||||||
|
inkscape:vp_z="210 : -132.625 : 1"
|
||||||
|
inkscape:vp_y="0 : 999.99997 : 0"
|
||||||
|
inkscape:vp_x="0 : -132.625 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-top="0"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-height="1017"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:cy="36.490448"
|
||||||
|
inkscape:cx="22.175528"
|
||||||
|
inkscape:zoom="22.627417"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base">
|
||||||
|
<inkscape:grid
|
||||||
|
originy="-120.38541"
|
||||||
|
originx="-88.635412"
|
||||||
|
id="grid833"
|
||||||
|
type="xygrid" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
transform="translate(-88.635416,-120.38542)"
|
||||||
|
inkscape:label="Background"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
id="path1541"
|
||||||
|
d="m 91.28125,136.26042 h 1.322917 l 5.291666,-10.58333 h -1.322915 z"
|
||||||
|
style="fill:#003049;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path1682"
|
||||||
|
d="m 96.572915,128.32292 h 0.529167 l 1.852083,1.05833 h -0.529166 z"
|
||||||
|
style="fill:#003049;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(-88.635416,-120.38542)"
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Ebene 1">
|
||||||
|
<path
|
||||||
|
transform="scale(0.26458333)"
|
||||||
|
d="m 365,455 -30,60 h 10 l 10,-20 10,-5 10,5 10,20 h 10 z m 0,20 7,14 -7,-4 -7,4 z"
|
||||||
|
style="fill:#d62828;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.944882;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path1468" />
|
||||||
|
<path
|
||||||
|
id="path1678"
|
||||||
|
d="m 96.572915,120.38542 h 1.322917 l 7.937498,15.87499 h -1.32291 z"
|
||||||
|
style="fill:#003049;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.4 KiB |
98
frontend/img/logolight.svg
Normal file
98
frontend/img/logolight.svg
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
sodipodi:docname="LOGO-FINAL-LIGHT.svg"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 17.197914 15.875005"
|
||||||
|
height="15.875005mm"
|
||||||
|
width="17.197914mm">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective1549"
|
||||||
|
inkscape:persp3d-origin="105 : -182.125 : 1"
|
||||||
|
inkscape:vp_z="210 : -132.625 : 1"
|
||||||
|
inkscape:vp_y="0 : 999.99997 : 0"
|
||||||
|
inkscape:vp_x="0 : -132.625 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-top="0"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-height="1017"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:current-layer="layer2"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:cy="35.054888"
|
||||||
|
inkscape:cx="18.899507"
|
||||||
|
inkscape:zoom="8"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base">
|
||||||
|
<inkscape:grid
|
||||||
|
originy="-120.38541"
|
||||||
|
originx="-88.635412"
|
||||||
|
id="grid833"
|
||||||
|
type="xygrid" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
transform="translate(-88.635416,-120.38542)"
|
||||||
|
inkscape:label="Background"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
id="path1541"
|
||||||
|
d="m 91.28125,136.26042 h 1.322917 l 5.291666,-10.58333 h -1.322915 z"
|
||||||
|
style="fill:#d62828;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path1682"
|
||||||
|
d="m 96.572915,128.32292 h 0.529167 l 1.852083,1.05833 h -0.529166 z"
|
||||||
|
style="fill:#d62828;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(-88.635416,-120.38542)"
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Ebene 1">
|
||||||
|
<path
|
||||||
|
transform="scale(0.26458333)"
|
||||||
|
d="m 365,455 -30,60 h 10 l 10,-20 10,-5 10,5 10,20 h 10 z m 0,20 7,14 -7,-4 -7,4 z"
|
||||||
|
style="fill:#003049;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.944882;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path1468" />
|
||||||
|
<path
|
||||||
|
id="path1678"
|
||||||
|
d="m 96.572915,120.38542 h 1.322917 l 7.937498,15.87499 h -1.32291 z"
|
||||||
|
style="fill:#d62828;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.4 KiB |
198
frontend/js/api.js
Normal file
198
frontend/js/api.js
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
const prefix = document.getElementsByTagName("base")[0].href.replace(/(?=.*)\/$/gm, "");
|
||||||
|
async function unknownResponse(resp) {
|
||||||
|
let text = await resp.text();
|
||||||
|
try {
|
||||||
|
let json = JSON.parse(text);
|
||||||
|
return new Error(`${json["message"]} (${resp.status})`);
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
return new Error(`Server sent unknown error: ${text} (${resp.status})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function buildQuery(options) {
|
||||||
|
let query = [];
|
||||||
|
options.forEach(element => {
|
||||||
|
if (element[1] !== undefined) {
|
||||||
|
if (element[1] instanceof Date) {
|
||||||
|
element[1] = element[1].getSeconds();
|
||||||
|
}
|
||||||
|
else if (element[1] instanceof Array) {
|
||||||
|
element[1] = JSON.stringify(element[1]);
|
||||||
|
}
|
||||||
|
query.push(`${element[0]}=${element[1]}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return query.join("&");
|
||||||
|
}
|
||||||
|
async function login(username, password) {
|
||||||
|
let result = await fetch(`${prefix}/api/login`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({ "username": username, "password": password }),
|
||||||
|
credentials: "same-origin"
|
||||||
|
});
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return;
|
||||||
|
case 401:
|
||||||
|
throw new Error("Wrong username and/or password");
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function authors(name, limit) {
|
||||||
|
let query = [["name", name], ["limit", limit]];
|
||||||
|
let result = await fetch(`${prefix}/api/authors?${buildQuery(query)}`);
|
||||||
|
if (result.status == 200) {
|
||||||
|
return await result.json();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function tags(name, limit) {
|
||||||
|
let query = [["name", name], ["limit", limit]];
|
||||||
|
let result = await fetch(`${prefix}/api/tags?${buildQuery(query)}`);
|
||||||
|
if (result.status == 200) {
|
||||||
|
return await result.json();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function recent(limit = 20) {
|
||||||
|
let query = [["limit", limit]];
|
||||||
|
let result = await fetch(`${prefix}/api/recent?${buildQuery(query)}`);
|
||||||
|
if (result.status == 200) {
|
||||||
|
return await result.json();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function search(q) {
|
||||||
|
let query = [["q", q.query], ["from", q.from], ["to", q.to], ["authors", q.authors], ["tags", q.tags], ["limit", q.limit]];
|
||||||
|
let result = await fetch(`${prefix}/api/search?${buildQuery(query)}`);
|
||||||
|
if (result.status == 200) {
|
||||||
|
return await result.json();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function getArticle(id) {
|
||||||
|
let query = [["id", id]];
|
||||||
|
let result = await fetch(`${prefix}/api/article?${buildQuery(query)}`, {
|
||||||
|
method: "GET"
|
||||||
|
});
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return await result.json();
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized");
|
||||||
|
case 404:
|
||||||
|
throw new Error("Article not found");
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function uploadArticle(payload) {
|
||||||
|
let result = await fetch(`${prefix}/api/article`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
switch (result.status) {
|
||||||
|
case 201:
|
||||||
|
return await result.json();
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized");
|
||||||
|
case 409:
|
||||||
|
throw new Error("An article with the same title already exists");
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function editArticle(payload) {
|
||||||
|
let result = await fetch(`${prefix}/api/article`, {
|
||||||
|
method: "PATCH",
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
let json = await result.json();
|
||||||
|
switch (result.status) {
|
||||||
|
case 201:
|
||||||
|
return json;
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized");
|
||||||
|
case 404:
|
||||||
|
throw new Error("Could not find article");
|
||||||
|
case 409:
|
||||||
|
throw new Error("An article with the same title already exists");
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function deleteArticle(id) {
|
||||||
|
let result = await fetch(`${prefix}/api/article`, {
|
||||||
|
method: "DELETE",
|
||||||
|
body: JSON.stringify({ "id": id })
|
||||||
|
});
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return;
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized");
|
||||||
|
case 404:
|
||||||
|
throw new Error("Could not find article");
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function getAssets(name, limit = 20) {
|
||||||
|
let query = [["q", name], ["limit", limit]];
|
||||||
|
let result = await fetch(`${prefix}/api/assets?${buildQuery(query)}`, {
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return await result.json();
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized");
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function addAsset(name, content) {
|
||||||
|
let result = await fetch(`${prefix}/api/assets`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
"name": name,
|
||||||
|
"content": content,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
switch (result.status) {
|
||||||
|
case 201:
|
||||||
|
return await result.json();
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized");
|
||||||
|
case 409:
|
||||||
|
throw new Error("An asset with the same name already exists");
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function deleteAsset(id) {
|
||||||
|
let result = await fetch(`${prefix}/api/assets`, {
|
||||||
|
method: "DELETE",
|
||||||
|
body: JSON.stringify({ "id": id })
|
||||||
|
});
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return;
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized");
|
||||||
|
case 404:
|
||||||
|
throw new Error("An asset with this id does not exist");
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=api.js.map
|
||||||
1
frontend/js/api.js.map
Normal file
1
frontend/js/api.js.map
Normal file
File diff suppressed because one or more lines are too long
277
frontend/js/api.ts
Normal file
277
frontend/js/api.ts
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
const prefix = document.getElementsByTagName("base")[0].href.replace(/(?=.*)\/$/gm, "");
|
||||||
|
|
||||||
|
|
||||||
|
async function unknownResponse(resp: Response): Promise<Error> {
|
||||||
|
let text = await resp.text()
|
||||||
|
try {
|
||||||
|
let json = JSON.parse(text)
|
||||||
|
return new Error(`${json["message"]} (${resp.status})`)
|
||||||
|
} catch (error) {
|
||||||
|
return new Error(`Server sent unknown error: ${text} (${resp.status})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildQuery(options: any[][]): string {
|
||||||
|
let query: string[] = []
|
||||||
|
options.forEach(element => {
|
||||||
|
if (element[1] !== undefined) {
|
||||||
|
if (element[1] instanceof Date) {
|
||||||
|
element[1] = element[1].getSeconds()
|
||||||
|
} else if (element[1] instanceof Array) {
|
||||||
|
element[1] = JSON.stringify(element[1])
|
||||||
|
}
|
||||||
|
query.push(`${element[0]}=${element[1]}`)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return query.join("&")
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Author {
|
||||||
|
id: number,
|
||||||
|
name: string,
|
||||||
|
information: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArticleSummary {
|
||||||
|
id: number,
|
||||||
|
title: string,
|
||||||
|
summary: string
|
||||||
|
authors: Author[],
|
||||||
|
image?: string,
|
||||||
|
tags: string[],
|
||||||
|
created: Date,
|
||||||
|
modified?: Date,
|
||||||
|
link: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Asset {
|
||||||
|
id: number,
|
||||||
|
name: string,
|
||||||
|
link: string
|
||||||
|
}
|
||||||
|
|
||||||
|
async function login(username: string, password: string): Promise<void> {
|
||||||
|
let result = await fetch(`${prefix}/api/login`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({"username": username, "password": password}),
|
||||||
|
credentials: "same-origin"
|
||||||
|
})
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return
|
||||||
|
case 401:
|
||||||
|
throw new Error("Wrong username and/or password")
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function authors(name?: string, limit?: number): Promise<Author[]> {
|
||||||
|
let query = [["name", name], ["limit", limit]]
|
||||||
|
|
||||||
|
let result = await fetch(`${prefix}/api/authors?${buildQuery(query)}`)
|
||||||
|
if (result.status == 200) {
|
||||||
|
return await result.json()
|
||||||
|
} else {
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function tags(name?: string, limit?: number): Promise<string[]> {
|
||||||
|
let query = [["name", name], ["limit", limit]]
|
||||||
|
|
||||||
|
let result = await fetch(`${prefix}/api/tags?${buildQuery(query)}`)
|
||||||
|
if (result.status == 200) {
|
||||||
|
return await result.json()
|
||||||
|
} else {
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function recent(limit: number = 20): Promise<ArticleSummary[]> {
|
||||||
|
let query = [["limit", limit]]
|
||||||
|
|
||||||
|
let result = await fetch(`${prefix}/api/recent?${buildQuery(query)}`)
|
||||||
|
if (result.status == 200) {
|
||||||
|
return await result.json()
|
||||||
|
} else {
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SearchQuery {
|
||||||
|
query?: string,
|
||||||
|
from?: Date,
|
||||||
|
to?: Date,
|
||||||
|
authors?: number[],
|
||||||
|
tags?: string[],
|
||||||
|
limit?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
async function search(q: SearchQuery): Promise<ArticleSummary[]> {
|
||||||
|
let query = [["q", q.query], ["from", q.from], ["to", q.to], ["authors", q.authors], ["tags", q.tags], ["limit", q.limit]]
|
||||||
|
|
||||||
|
let result = await fetch(`${prefix}/api/search?${buildQuery(query)}`)
|
||||||
|
if (result.status == 200) {
|
||||||
|
return await result.json()
|
||||||
|
} else {
|
||||||
|
throw unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArticleGetPayload {
|
||||||
|
title: string,
|
||||||
|
summary: string,
|
||||||
|
authors: number[],
|
||||||
|
image: string,
|
||||||
|
tags: string[],
|
||||||
|
link: string
|
||||||
|
content: string
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getArticle(id: number): Promise<ArticleGetPayload> {
|
||||||
|
let query = [["id", id]]
|
||||||
|
|
||||||
|
let result = await fetch(`${prefix}/api/article?${buildQuery(query)}`, {
|
||||||
|
method: "GET"
|
||||||
|
})
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return await result.json()
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized")
|
||||||
|
case 404:
|
||||||
|
throw new Error("Article not found")
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArticleUploadPayload {
|
||||||
|
title: string,
|
||||||
|
summary: string,
|
||||||
|
authors: number[],
|
||||||
|
image?: string,
|
||||||
|
tags: string[],
|
||||||
|
link?: string
|
||||||
|
content: string
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploadArticle(payload: ArticleUploadPayload): Promise<ArticleSummary> {
|
||||||
|
let result = await fetch(`${prefix}/api/article`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
})
|
||||||
|
switch (result.status) {
|
||||||
|
case 201:
|
||||||
|
return await result.json()
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized")
|
||||||
|
case 409:
|
||||||
|
throw new Error("An article with the same title already exists")
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArticleEditPayload {
|
||||||
|
id: number,
|
||||||
|
title?: string,
|
||||||
|
summary?: string,
|
||||||
|
authors?: number[],
|
||||||
|
image?: string,
|
||||||
|
tags?: string[],
|
||||||
|
link?: string
|
||||||
|
content?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
async function editArticle(payload: ArticleEditPayload): Promise<ArticleSummary> {
|
||||||
|
let result = await fetch(`${prefix}/api/article`, {
|
||||||
|
method: "PATCH",
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
})
|
||||||
|
let json = await result.json()
|
||||||
|
|
||||||
|
switch (result.status) {
|
||||||
|
case 201:
|
||||||
|
return json
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized")
|
||||||
|
case 404:
|
||||||
|
throw new Error("Could not find article")
|
||||||
|
case 409:
|
||||||
|
throw new Error("An article with the same title already exists")
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteArticle(id: number): Promise<void> {
|
||||||
|
let result = await fetch(`${prefix}/api/article`, {
|
||||||
|
method: "DELETE",
|
||||||
|
body: JSON.stringify({"id": id})
|
||||||
|
})
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized")
|
||||||
|
case 404:
|
||||||
|
throw new Error("Could not find article")
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAssets(name?: string, limit: number = 20): Promise<Asset[]> {
|
||||||
|
let query = [["q", name], ["limit", limit]]
|
||||||
|
|
||||||
|
let result = await fetch(`${prefix}/api/assets?${buildQuery(query)}`, {
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return await result.json()
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized")
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addAsset(name: string, content: string): Promise<Asset> {
|
||||||
|
let result = await fetch(`${prefix}/api/assets`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
"name": name,
|
||||||
|
"content": content,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
switch (result.status) {
|
||||||
|
case 201:
|
||||||
|
return await result.json()
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized")
|
||||||
|
case 409:
|
||||||
|
throw new Error("An asset with the same name already exists")
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteAsset(id: number): Promise<void> {
|
||||||
|
let result = await fetch(`${prefix}/api/assets`, {
|
||||||
|
method: "DELETE",
|
||||||
|
body: JSON.stringify({"id": id})
|
||||||
|
})
|
||||||
|
switch (result.status) {
|
||||||
|
case 200:
|
||||||
|
return
|
||||||
|
case 401:
|
||||||
|
throw new Error("Not authorized")
|
||||||
|
case 404:
|
||||||
|
throw new Error("An asset with this id does not exist")
|
||||||
|
default:
|
||||||
|
throw await unknownResponse(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
69
frontend/js/main.js
Normal file
69
frontend/js/main.js
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
let articleParent = document.getElementById("articles");
|
||||||
|
function updateSeach(value) {
|
||||||
|
if (value == "") {
|
||||||
|
addRecent();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let query = {
|
||||||
|
query: value,
|
||||||
|
limit: 5
|
||||||
|
};
|
||||||
|
clearArticles();
|
||||||
|
search(query).then(function (data) {
|
||||||
|
data.forEach(function (article) {
|
||||||
|
addArticle(article);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function clearArticles() {
|
||||||
|
articleParent.innerHTML = "";
|
||||||
|
}
|
||||||
|
window.onload = function () {
|
||||||
|
addRecent();
|
||||||
|
};
|
||||||
|
function addRecent() {
|
||||||
|
clearArticles();
|
||||||
|
recent(5).then(function (data) {
|
||||||
|
data.forEach(function (article) {
|
||||||
|
addArticle(article);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function addArticle(article) {
|
||||||
|
let articleA = document.createElement("a");
|
||||||
|
articleA.setAttribute("href", article.link);
|
||||||
|
let articleDiv = document.createElement("div");
|
||||||
|
articleDiv.setAttribute("class", "article");
|
||||||
|
let articleHeader = document.createElement("div");
|
||||||
|
articleHeader.setAttribute("class", "article-header");
|
||||||
|
let articleHeaderTitle = document.createElement("h3");
|
||||||
|
articleHeaderTitle.innerHTML = article.title;
|
||||||
|
articleHeader.appendChild(articleHeaderTitle);
|
||||||
|
articleDiv.appendChild(articleHeader);
|
||||||
|
let articleDescription = document.createElement("div");
|
||||||
|
articleDescription.setAttribute("class", "article-description");
|
||||||
|
let articleDescriptionP = document.createElement("p");
|
||||||
|
let articleDescriptionTopics = document.createElement("i");
|
||||||
|
articleDescriptionTopics.innerHTML = article.tags.join(", ");
|
||||||
|
let articleDescriptionAuthors = document.createElement("i");
|
||||||
|
articleDescriptionAuthors.innerHTML = article.authors[0].name;
|
||||||
|
let articleDescriptionDate = document.createElement("i");
|
||||||
|
articleDescriptionDate.innerHTML = article.modified.toString();
|
||||||
|
articleDescriptionP.appendChild(articleDescriptionTopics);
|
||||||
|
articleDescriptionP.appendChild(articleDescriptionAuthors);
|
||||||
|
articleDescriptionP.appendChild(articleDescriptionDate);
|
||||||
|
articleDescription.appendChild(articleDescriptionP);
|
||||||
|
articleDiv.appendChild(articleDescription);
|
||||||
|
let articleBody = document.createElement("div");
|
||||||
|
articleBody.setAttribute("class", "article-body");
|
||||||
|
let articleBodyP = document.createElement("p");
|
||||||
|
articleBodyP.innerHTML = article.summary;
|
||||||
|
articleBody.appendChild(articleBodyP);
|
||||||
|
articleDiv.appendChild(articleBody);
|
||||||
|
articleA.appendChild(articleDiv);
|
||||||
|
articleParent.appendChild(articleA);
|
||||||
|
let divider = document.createElement("div");
|
||||||
|
divider.setAttribute("class", "divider");
|
||||||
|
articleParent.appendChild(divider);
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=main.js.map
|
||||||
1
frontend/js/main.js.map
Normal file
1
frontend/js/main.js.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":"AAAA,IAAI,aAAa,GAAG,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;AAExD,SAAS,WAAW,CAAC,KAAa;IAC9B,IAAI,KAAK,GAAgB;QACrB,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,CAAC;KACX,CAAA;IAGD,aAAa,EAAE,CAAA;IACf,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAS,IAAI;QAC5B,IAAI,CAAC,OAAO,CAAC,UAAS,OAAO;YACzB,UAAU,CAAC,OAAO,CAAC,CAAA;QACvB,CAAC,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC;AAED,SAAS,aAAa;IAClB,aAAa,CAAC,SAAS,GAAG,EAAE,CAAA;AAChC,CAAC;AAED,MAAM,CAAC,MAAM,GAAG;IAEZ,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAS,IAAI;QACxB,IAAI,CAAC,OAAO,CAAC,UAAS,OAAO;YACzB,UAAU,CAAC,OAAO,CAAC,CAAA;QACvB,CAAC,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC,CAAA;AAED,SAAS,UAAU,CAAC,OAAuB;IACvC,IAAI,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IAC1C,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3C,IAAI,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAC9C,UAAU,CAAC,YAAY,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IAE3C,IAAI,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IACjD,aAAa,CAAC,YAAY,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAA;IAErD,IAAI,kBAAkB,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;IACrD,kBAAkB,CAAC,SAAS,GAAG,OAAO,CAAC,KAAK,CAAA;IAE5C,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAA;IAC7C,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAA;IAErC,IAAI,kBAAkB,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IACtD,kBAAkB,CAAC,YAAY,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAA;IAE/D,IAAI,mBAAmB,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IAErD,IAAI,wBAAwB,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IAC1D,wBAAwB,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAE5D,IAAI,yBAAyB,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IAC3D,yBAAyB,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAE7D,IAAI,sBAAsB,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IACxD,sBAAsB,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAA;IAE9D,mBAAmB,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAA;IACzD,mBAAmB,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAA;IAC1D,mBAAmB,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAA;IAEvD,kBAAkB,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAA;IACnD,UAAU,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAA;IAE1C,IAAI,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAC/C,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;IAEjD,IAAI,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IAC9C,YAAY,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAA;IAExC,WAAW,CAAC,WAAW,CAAC,YAAY,CAAC,CAAA;IACrC,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAA;IAEnC,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;IAChC,aAAa,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;IAEnC,IAAI,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAC3C,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IAExC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;AACtC,CAAC"}
|
||||||
93
frontend/js/main.ts
Normal file
93
frontend/js/main.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
let articleParent = document.getElementById("articles");
|
||||||
|
|
||||||
|
function updateSeach(value: string) {
|
||||||
|
if(value == "") {
|
||||||
|
addRecent()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let query: SearchQuery = {
|
||||||
|
query: value,
|
||||||
|
limit: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
clearArticles()
|
||||||
|
search(query).then(function(data) {
|
||||||
|
data.forEach(function(article) {
|
||||||
|
addArticle(article)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearArticles() {
|
||||||
|
articleParent.innerHTML = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
addRecent()
|
||||||
|
}
|
||||||
|
|
||||||
|
function addRecent () {
|
||||||
|
clearArticles()
|
||||||
|
recent(5).then(function(data) {
|
||||||
|
data.forEach(function(article) {
|
||||||
|
addArticle(article)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function addArticle(article: ArticleSummary) {
|
||||||
|
let articleA = document.createElement("a")
|
||||||
|
articleA.setAttribute("href", article.link)
|
||||||
|
|
||||||
|
let articleDiv = document.createElement("div")
|
||||||
|
articleDiv.setAttribute("class", "article")
|
||||||
|
|
||||||
|
let articleHeader = document.createElement("div")
|
||||||
|
articleHeader.setAttribute("class", "article-header")
|
||||||
|
|
||||||
|
let articleHeaderTitle = document.createElement("h3")
|
||||||
|
articleHeaderTitle.innerHTML = article.title
|
||||||
|
|
||||||
|
articleHeader.appendChild(articleHeaderTitle)
|
||||||
|
articleDiv.appendChild(articleHeader)
|
||||||
|
|
||||||
|
let articleDescription = document.createElement("div")
|
||||||
|
articleDescription.setAttribute("class", "article-description")
|
||||||
|
|
||||||
|
let articleDescriptionP = document.createElement("p")
|
||||||
|
|
||||||
|
let articleDescriptionTopics = document.createElement("i")
|
||||||
|
articleDescriptionTopics.innerHTML = article.tags.join(", ")
|
||||||
|
|
||||||
|
let articleDescriptionAuthors = document.createElement("i")
|
||||||
|
articleDescriptionAuthors.innerHTML = article.authors[0].name //TODO join ALL Auhtors
|
||||||
|
|
||||||
|
let articleDescriptionDate = document.createElement("i")
|
||||||
|
articleDescriptionDate.innerHTML = article.modified.toString()
|
||||||
|
|
||||||
|
articleDescriptionP.appendChild(articleDescriptionTopics)
|
||||||
|
articleDescriptionP.appendChild(articleDescriptionAuthors)
|
||||||
|
articleDescriptionP.appendChild(articleDescriptionDate)
|
||||||
|
|
||||||
|
articleDescription.appendChild(articleDescriptionP)
|
||||||
|
articleDiv.appendChild(articleDescription)
|
||||||
|
|
||||||
|
let articleBody = document.createElement("div")
|
||||||
|
articleBody.setAttribute("class", "article-body")
|
||||||
|
|
||||||
|
let articleBodyP = document.createElement("p")
|
||||||
|
articleBodyP.innerHTML = article.summary
|
||||||
|
|
||||||
|
articleBody.appendChild(articleBodyP)
|
||||||
|
articleDiv.appendChild(articleBody)
|
||||||
|
|
||||||
|
articleA.appendChild(articleDiv)
|
||||||
|
articleParent.appendChild(articleA)
|
||||||
|
|
||||||
|
let divider = document.createElement("div")
|
||||||
|
divider.setAttribute("class", "divider")
|
||||||
|
|
||||||
|
articleParent.appendChild(divider)
|
||||||
|
}
|
||||||
10
frontend/js/tsconfig.json
Normal file
10
frontend/js/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": true,
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es2018",
|
||||||
|
"removeComments": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"lib": ["es2018", "dom"]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user