This commit is contained in:
Sonny Bakker 2021-01-23 17:10:43 +01:00
parent 01f86399b2
commit cf078ee42a
42 changed files with 554 additions and 307 deletions

1
.gitignore vendored
View file

@ -35,6 +35,7 @@ eggs/
lib/ lib/
!src/newsreader/scss/lib !src/newsreader/scss/lib
!src/newsreader/js/lib
lib64/ lib64/
parts/ parts/

31
CHANGELOG.md Normal file
View file

@ -0,0 +1,31 @@
# Changelog
## 0.3.7
- Add a dark theme
- Update object representations
- Move sentry to optional dependency
- Add CHANGELOG.md
## 0.3.6.3
- Update deploy job
## 0.3.6.2
- Use warning logging level for BuilderSkippedException's
- Change working directory before running ansible
## 0.3.6.1
- Install ansible required roles
## 0.3.6
- Update deploy job
- Add user manageable reddit filters
## 0.3.5
- Show timezone next to post datetimes
- Take read status in consideration when sorting posts

View file

@ -20,3 +20,4 @@ deploy:
--inventory inventory.yml --inventory inventory.yml
--private-key deploy_key --private-key deploy_key
--vault-password-file vault --vault-password-file vault
--extra-vars "app_branch=$CI_COMMIT_TAG"

View file

@ -7,6 +7,6 @@ release:
- echo 'running release job' - echo 'running release job'
release: release:
name: 'Release $CI_COMMIT_TAG' name: 'Release $CI_COMMIT_TAG'
description: 'Auto created release' description: './CHANGELOG.md'
tag_name: '$CI_COMMIT_TAG' tag_name: '$CI_COMMIT_TAG'
ref: '$CI_COMMIT_TAG' ref: '$CI_COMMIT_TAG'

595
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -24,10 +24,13 @@ psycopg2-binary = "^2.8.5"
gunicorn = "^20.0.4" gunicorn = "^20.0.4"
python-dotenv = "^0.12.0" python-dotenv = "^0.12.0"
django = ">=3.0.7" django = ">=3.0.7"
sentry-sdk = "^0.15.1" sentry-sdk = {version = "^0.15.1", optional = true}
ftfy = "^5.8" ftfy = "^5.8"
requests_oauthlib = "^1.3.0" requests_oauthlib = "^1.3.0"
[tool.poetry.extras]
sentry = ["sentry_sdk"]
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
factory-boy = "^2.12.0" factory-boy = "^2.12.0"
freezegun = "^0.3.15" freezegun = "^0.3.15"

View file

@ -1,3 +1,4 @@
import './lib/index.js';
import './pages/homepage/index.js'; import './pages/homepage/index.js';
import './pages/categories/index.js'; import './pages/categories/index.js';
import './pages/rules/index.js'; import './pages/rules/index.js';

View file

@ -0,0 +1 @@
import './theme.js';

View file

@ -0,0 +1,76 @@
function isCSSVariablesSupported() {
return window.CSS && window.CSS.supports('color', 'var(--fake-color');
}
function changeTheme(e) {
const currentPref = sessionStorage.getItem('t-dark');
const isDark = currentPref && currentPref === 'true' ? true : false;
if (isDark) {
document.documentElement.classList.remove('dark-theme');
} else {
document.documentElement.classList.add('dark-theme');
}
try {
sessionStorage.setItem('t-dark', !isDark);
} catch (e) {
// do nothing.
}
}
function prefersDarkTheme() {
try {
const currentPref = sessionStorage.getItem('t-dark');
if (currentPref && currentPref === 'true') {
return true;
} else if (
!currentPref &&
window.matchMedia('(prefers-color-scheme: dark)').matches
) {
return true;
} else {
return false;
}
} catch (e) {
return false;
}
}
function toggleDarkTheme(isDark) {
if (isDark) {
document.documentElement.classList.add('dark-theme');
} else {
document.documentElement.classList.remove('dark-theme');
}
try {
sessionStorage.setItem('t-dark', isDark);
} catch (e) {
// do nothing.
}
}
function initThemeSelector() {
const themeButton = document.getElementsByClassName('theme-switcher')[0];
const mqPrefersDarkTheme = window.matchMedia('(prefers-color-scheme: dark)');
if (prefersDarkTheme()) {
toggleDarkTheme(true);
}
themeButton.addEventListener('click', changeTheme);
mqPrefersDarkTheme.addListener(mq => {
toggleDarkTheme(mq.matches);
});
}
function init() {
if (isCSSVariablesSupported()) {
initThemeSelector();
}
}
init();

View file

@ -92,6 +92,9 @@ class FeedBuilder(PostBuilder):
content_details = "\n ".join([item.get("value") for item in content_items]) content_details = "\n ".join([item.get("value") for item in content_items])
return self.sanitize_fragment(content_details) return self.sanitize_fragment(content_details)
def __str__(self):
return f"{self.stream.rule.pk}: FeedBuilder"
class FeedStream(PostStream): class FeedStream(PostStream):
rule_type = RuleTypeChoices.feed rule_type = RuleTypeChoices.feed
@ -108,6 +111,9 @@ class FeedStream(PostStream):
message = "Could not parse feed" message = "Could not parse feed"
raise StreamParseException(response=response, message=message) from e raise StreamParseException(response=response, message=message) from e
def __str__(self):
return f"{self.rule.pk}: FeedStream"
class FeedClient(PostClient): class FeedClient(PostClient):
stream = FeedStream stream = FeedStream

View file

@ -290,6 +290,9 @@ class RedditBuilder(PostBuilder):
title=title, title=title,
) )
def __str__(self):
return f"{self.stream.rule.pk}: RedditBuilder"
class RedditStream(PostStream): class RedditStream(PostStream):
rule_type = RuleTypeChoices.subreddit rule_type = RuleTypeChoices.subreddit
@ -315,6 +318,9 @@ class RedditStream(PostStream):
response=response, message="Failed parsing json" response=response, message="Failed parsing json"
) from e ) from e
def __str__(self):
return f"{self.rule.pk}: RedditStream"
class RedditClient(PostClient): class RedditClient(PostClient):
stream = RedditStream stream = RedditStream

View file

@ -175,6 +175,9 @@ class TwitterBuilder(PostBuilder):
return formatted_entities return formatted_entities
def __str__(self):
return f"{self.stream.rule.pk}: TwitterBuilder"
class TwitterStream(PostStream): class TwitterStream(PostStream):
rule_type = RuleTypeChoices.twitter_timeline rule_type = RuleTypeChoices.twitter_timeline
@ -199,6 +202,9 @@ class TwitterStream(PostStream):
response=response, message="Failed parsing json" response=response, message="Failed parsing json"
) from e ) from e
def __str__(self):
return f"{self.rule.pk}: TwitterStream"
class TwitterClient(PostClient): class TwitterClient(PostClient):
stream = TwitterStream stream = TwitterStream

View file

@ -12,7 +12,14 @@ class RulesWidget(CheckboxSelectMultiple):
def create_option(self, *args, **kwargs): def create_option(self, *args, **kwargs):
option = super().create_option(*args, **kwargs) option = super().create_option(*args, **kwargs)
instance = self.choices.queryset.get(pk=option["value"])
# see https://docs.djangoproject.com/en/3.1/releases/3.1/#id1
try:
pk = int(option["value"])
except TypeError:
pk = option["value"].value
instance = self.choices.queryset.get(pk=pk)
if self.category and instance.category: if self.category and instance.category:
option["selected"] = self.category.pk == instance.category.pk option["selected"] = self.category.pk == instance.category.pk

View file

@ -3,7 +3,6 @@
padding: 0; padding: 0;
font-family: Rubik, sans-serif; font-family: Rubik, sans-serif;
color: $font-color;
} }
body { body {

View file

@ -7,7 +7,7 @@
width: 50%; width: 50%;
background-color: $white; background-color: var(--background-color);
&__header { &__header {
display: flex; display: flex;
@ -16,7 +16,7 @@
padding: 15px 0; padding: 15px 0;
border-bottom: 2px $gray solid; border-bottom: 2px var(--lightest-accent-color) solid;
} }
&__content { &__content {

View file

@ -36,6 +36,6 @@
} }
&--selected, &:hover { &--selected, &:hover {
background-color: $gray; background-color: var(--lighter-accent-color);
} }
} }

View file

@ -4,7 +4,7 @@
width: 70%; width: 70%;
background-color: $white; background-color: var(--background-color);
&__section { &__section {
&--last { &--last {

View file

@ -3,6 +3,7 @@
@import './main/index'; @import './main/index';
@import './navbar/index'; @import './navbar/index';
@import './loading-indicator/index'; @import './loading-indicator/index';
@import './theme-switcher/index';
@import './modal/index'; @import './modal/index';

View file

@ -20,7 +20,7 @@
width: 60%; width: 60%;
background-color: $white; background-color: var(--accent-color);
} }
&__header { &__header {

View file

@ -1,6 +1,7 @@
.nav { .nav {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center;
margin: 0 0 5px 0; margin: 0 0 5px 0;
padding: 10px 0; padding: 10px 0;

View file

@ -7,8 +7,6 @@
width: 60%; width: 60%;
height: 80vh; height: 80vh;
background-color: $white;
&__message { &__message {
font-size: 16px; font-size: 16px;
} }

View file

@ -11,7 +11,7 @@
overflow-y: auto; overflow-y: auto;
background-color: $white; background-color: var(--background-color);
cursor: initial; cursor: initial;
@ -33,7 +33,7 @@
&__title { &__title {
&--read { &--read {
color: $gainsboro; color: var(--read-color);
} }
} }
@ -55,7 +55,7 @@
} }
&__rule, &__category { &__rule, &__category {
background-color: $orange !important; background-color: var(--lightest-accent-color) !important;
& a { & a {
color: $black; color: $black;

View file

@ -33,7 +33,7 @@
} }
& .badge { & .badge {
background-color: $orange; background-color: var(--lightest-accent-color);
} }
&:last-child { &:last-child {
@ -48,7 +48,7 @@
font-size: 16px; font-size: 16px;
&--read { &--read {
color: darken($gainsboro, +10%); color: var(--read-color);
} }
&:hover { &:hover {

View file

@ -14,11 +14,11 @@
&:hover { &:hover {
cursor: pointer; cursor: pointer;
background-color: $gray; background-color: var(--lighter-accent-color);
} }
&--selected { &--selected {
background-color: $gray; background-color: var(--lighter-accent-color);
} }
} }

View file

@ -1,7 +1,7 @@
.table { .table {
table-layout: fixed; table-layout: fixed;
background-color: $white; background-color: var(--background-color);
width: 90%; width: 90%;
padding: 20px; padding: 20px;

View file

@ -0,0 +1,5 @@
.theme-switcher {
&:hover {
cursor: pointer;
}
}

View file

@ -0,0 +1 @@
@import './theme-switcher';

View file

@ -6,7 +6,7 @@
text-align: center; text-align: center;
background-color: $gainsboro; background-color: var(--lighter-accent-color);
font-size: small; font-size: small;
} }

View file

@ -14,7 +14,7 @@
&:checked + .checkbox__label { &:checked + .checkbox__label {
.checkbox__box { .checkbox__box {
background-color: $checkbox-blue; background-color: var(--lightest-accent-color);
} }
} }
} }
@ -29,7 +29,7 @@
height: 100%; height: 100%;
width: 100%; width: 100%;
border: 2px solid darken($gainsboro, 10%); border: 2px solid var(--lighter-accent-color);
cursor: pointer; cursor: pointer;
} }
} }

View file

@ -1,5 +1,5 @@
.h1 { .h1 {
color: $header-color; color: var(--font-color);
font-size: 20px; font-size: 20px;
} }

View file

@ -1,5 +1,5 @@
.h2 { .h2 {
color: $header-color; color: var(--font-color);
} }
h2 { h2 {

View file

@ -1,5 +1,5 @@
.h3 { .h3 {
color: $header-color; color: var(--font-color);
} }
h3 { h3 {

View file

@ -1,5 +1,5 @@
.h4 { .h4 {
color: $header-color; color: var(--font-color);
} }
h4 { h4 {

View file

@ -1,5 +1,5 @@
.h5 { .h5 {
color: $header-color; color: var(--font-color);
} }
h5 { h5 {

View file

@ -1,10 +1,12 @@
.input { .input {
@include text-padding; @include text-padding;
border: 1px $gray solid; color: var(--font-color);
background-color: var(--accent-color);
border: 1px var(--lighter-accent-color) solid;
&:focus { &:focus {
border: 1px $focus-blue solid; border: 1px var(--lightest-accent-color) solid;
} }
&[type="file"] { &[type="file"] {

View file

@ -1,5 +1,5 @@
.link { .link {
color: darken($azureish-white, 30%); color: var(--link-color);
text-decoration: none; text-decoration: none;
&:hover { &:hover {

View file

@ -1,5 +1,5 @@
.small { .small {
color: $nickel; color: var(--font-color);
font-size: small; font-size: small;
} }

View file

@ -1,10 +1,10 @@
@import '~css.gg/icons-scss/icons'; @import '~css.gg/icons-scss/icons';
.gg-link { .gg-link {
color: initial; color: var(--font-color);
} }
.gg-pen { .gg-pen {
color: var(--font-color);
transform: rotate(-45deg) scale(var(--ggs, 0.8)); transform: rotate(-45deg) scale(var(--ggs, 0.8));
color: initial;
} }

View file

@ -8,9 +8,6 @@ $white: rgba(255, 255, 255, 1);
$black: rgba(0, 0, 0, 1); $black: rgba(0, 0, 0, 1);
$dark: rgba(0, 0, 0, 0.4); $dark: rgba(0, 0, 0, 0.4);
$font-color: rgba(48, 51, 53, 1);
$header-color: rgba(100, 101, 102, 1);
$reddit-orange: rgba(255, 69, 0, 1); $reddit-orange: rgba(255, 69, 0, 1);
$twitter-blue: rgba(29, 155, 240, 1); $twitter-blue: rgba(29, 155, 240, 1);
@ -26,3 +23,25 @@ $lavendal-pink: rgba(162, 155, 254, 1);
$focus-blue: darken($azureish-white, +10%); $focus-blue: darken($azureish-white, +10%);
$checkbox-blue: rgba(34, 170, 253, 1); $checkbox-blue: rgba(34, 170, 253, 1);
// White theme
$background-color: $white;
$font-color: rgba(48, 51, 53, 1);
$link-color: darken($azureish-white, 30%);
$read-color: darken($gainsboro, 10%);
$accent-color: $gainsboro;
$lighter-accent-color: $gainsboro;
$lightest-accent-color: $orange;
// Dark theme
$dark-background-color: rgba(29, 45, 80, 1);
$dark-font-color: darken($gray, 10%);
$dark-link-color: $link-color;
$dark-read-color: darken($dark-font-color, 20%);
$dark-accent-color: rgba(19, 59, 92, 1);
$dark-lighter-accent-color: rgba(30, 95, 116, 1);
$dark-lightest-accent-color: rgba(252, 218, 183, 1);

View file

@ -0,0 +1,26 @@
:root {
--background-color: #{$background-color};
--font-color: #{$font-color};
--link-color: #{$link-color};
--read-color: #{$read-color};
--accent-color: #{$accent-color};
--lighter-accent-color: #{$lighter-accent-color};
--lightest-accent-color: #{$lightest-accent-color};
&.dark-theme {
--background-color: #{$dark-background-color};
--font-color: #{$dark-font-color};
--link-color: #{$dark-link-color};
--read-color: #{$dark-read-color};
--accent-color: #{$dark-accent-color};
--lighter-accent-color: #{$dark-lighter-accent-color};
--lightest-accent-color: #{$dark-lightest-accent-color};
}
color: var(--font-color);
background-color: var(--background-color);
}

View file

@ -1,2 +1,3 @@
@import './colors'; @import './colors';
@import './fonts'; @import './fonts';
@import './root';

View file

@ -27,6 +27,8 @@
<li class="nav__item"><a href="{% url 'accounts:register' %}">Register</a></li> <li class="nav__item"><a href="{% url 'accounts:register' %}">Register</a></li>
{% endif %} {% endif %}
</ol> </ol>
<i class="theme-switcher gg-dark-mode"></i>
</nav> </nav>
{% if messages %} {% if messages %}