diff --git a/src/newsreader/fixtures/default-fixture.json b/src/newsreader/fixtures/default-fixture.json
index 7b7ecdf..a6a9162 100644
--- a/src/newsreader/fixtures/default-fixture.json
+++ b/src/newsreader/fixtures/default-fixture.json
@@ -1,68 +1,143 @@
[
{
- "model": "django_celery_beat.periodictask",
- "pk": 10,
+ "model": "contenttypes.contenttype",
"fields": {
- "name": "sonny@bakker.nl-collection-task",
- "task": "newsreader.news.collection.tasks.FeedTask",
- "interval": 4,
- "crontab": null,
- "solar": null,
- "clocked": null,
- "args": "[2]",
- "kwargs": "{}",
- "queue": null,
- "exchange": null,
- "routing_key": null,
- "headers": "{}",
- "priority": null,
- "expires": null,
- "one_off": false,
- "start_time": null,
- "enabled": true,
- "last_run_at": "2019-11-29T22:29:08.345Z",
- "total_run_count": 290,
- "date_changed": "2019-11-29T22:29:18.378Z",
- "description": ""
+ "app_label": "admin",
+ "model": "logentry"
}
},
{
- "model": "django_celery_beat.periodictask",
- "pk": 26,
+ "model": "contenttypes.contenttype",
"fields": {
- "name": "sonnyba871@gmail.com-collection-task",
- "task": "newsreader.news.collection.tasks.FeedTask",
- "interval": 4,
- "crontab": null,
- "solar": null,
- "clocked": null,
- "args": "[18]",
- "kwargs": "{}",
- "queue": null,
- "exchange": null,
- "routing_key": null,
- "headers": "{}",
- "priority": null,
- "expires": null,
- "one_off": false,
- "start_time": null,
- "enabled": true,
- "last_run_at": "2019-11-29T22:35:19.134Z",
- "total_run_count": 103,
- "date_changed": "2019-11-29T22:38:19.464Z",
- "description": ""
+ "app_label": "auth",
+ "model": "permission"
}
},
{
- "model": "django_celery_beat.crontabschedule",
- "pk": 1,
+ "model": "contenttypes.contenttype",
"fields": {
- "minute": "0",
- "hour": "4",
- "day_of_week": "*",
- "day_of_month": "*",
- "month_of_year": "*",
- "timezone": "UTC"
+ "app_label": "auth",
+ "model": "group"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "contenttypes",
+ "model": "contenttype"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "sessions",
+ "model": "session"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "django_celery_beat",
+ "model": "crontabschedule"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "django_celery_beat",
+ "model": "intervalschedule"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "django_celery_beat",
+ "model": "periodictask"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "django_celery_beat",
+ "model": "periodictasks"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "django_celery_beat",
+ "model": "solarschedule"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "django_celery_beat",
+ "model": "clockedschedule"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "registration",
+ "model": "registrationprofile"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "registration",
+ "model": "supervisedregistrationprofile"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "axes",
+ "model": "accessattempt"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "axes",
+ "model": "accesslog"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "accounts",
+ "model": "user"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "core",
+ "model": "post"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "core",
+ "model": "category"
+ }
+},
+{
+ "model": "contenttypes.contenttype",
+ "fields": {
+ "app_label": "collection",
+ "model": "collectionrule"
+ }
+},
+{
+ "model": "sessions.session",
+ "pk": "3sumq22krk8tsvexcs4b8czu82yhvuer",
+ "fields": {
+ "session_data": "OWZkZTQyZDQ2NzNkYzdkOTBhM2ZlOWU3MDhhNDkyMWQ0MDdmZTc5ODp7Il9hdXRoX3VzZXJfaWQiOiIxIiwiX2F1dGhfdXNlcl9iYWNrZW5kIjoiZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmQiLCJfYXV0aF91c2VyX2hhc2giOiJhZTMwMWFlMzI5OGFlOThkNjY1MTY1NDIxM2EyMmM0NDA0Y2FkZTc3In0=",
+ "expire_date": "2020-05-16T18:29:04.049Z"
}
},
{
@@ -97,11 +172,950 @@
"period": "hours"
}
},
+{
+ "model": "django_celery_beat.crontabschedule",
+ "pk": 1,
+ "fields": {
+ "minute": "0",
+ "hour": "4",
+ "day_of_week": "*",
+ "day_of_month": "*",
+ "month_of_year": "*",
+ "timezone": "UTC"
+ }
+},
+{
+ "model": "django_celery_beat.periodictasks",
+ "pk": 1,
+ "fields": {
+ "last_update": "2020-05-02T20:40:29.029Z"
+ }
+},
+{
+ "model": "django_celery_beat.periodictask",
+ "pk": 1,
+ "fields": {
+ "name": "celery.backend_cleanup",
+ "task": "celery.backend_cleanup",
+ "interval": null,
+ "crontab": 1,
+ "solar": null,
+ "clocked": null,
+ "args": "[]",
+ "kwargs": "{}",
+ "queue": null,
+ "exchange": null,
+ "routing_key": null,
+ "headers": "{}",
+ "priority": null,
+ "expires": null,
+ "expire_seconds": 43200,
+ "one_off": false,
+ "start_time": null,
+ "enabled": true,
+ "last_run_at": null,
+ "total_run_count": 0,
+ "date_changed": "2020-05-02T20:06:23.985Z",
+ "description": ""
+ }
+},
+{
+ "model": "django_celery_beat.periodictask",
+ "pk": 10,
+ "fields": {
+ "name": "sonny@bakker.nl-collection-task",
+ "task": "newsreader.news.collection.tasks.FeedTask",
+ "interval": 4,
+ "crontab": null,
+ "solar": null,
+ "clocked": null,
+ "args": "[2]",
+ "kwargs": "{}",
+ "queue": null,
+ "exchange": null,
+ "routing_key": null,
+ "headers": "{}",
+ "priority": null,
+ "expires": null,
+ "expire_seconds": null,
+ "one_off": false,
+ "start_time": null,
+ "enabled": true,
+ "last_run_at": "2020-05-02T20:06:24.012Z",
+ "total_run_count": 292,
+ "date_changed": "2020-05-02T20:06:24.027Z",
+ "description": ""
+ }
+},
+{
+ "model": "django_celery_beat.periodictask",
+ "pk": 26,
+ "fields": {
+ "name": "sonnyba871@gmail.com-collection-task",
+ "task": "newsreader.news.collection.tasks.FeedTask",
+ "interval": 4,
+ "crontab": null,
+ "solar": null,
+ "clocked": null,
+ "args": "[18]",
+ "kwargs": "{}",
+ "queue": null,
+ "exchange": null,
+ "routing_key": null,
+ "headers": "{}",
+ "priority": null,
+ "expires": null,
+ "expire_seconds": null,
+ "one_off": false,
+ "start_time": null,
+ "enabled": true,
+ "last_run_at": "2020-05-02T20:06:24.045Z",
+ "total_run_count": 105,
+ "date_changed": "2020-05-02T20:09:24.331Z",
+ "description": ""
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add log entry",
+ "content_type": [
+ "admin",
+ "logentry"
+ ],
+ "codename": "add_logentry"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change log entry",
+ "content_type": [
+ "admin",
+ "logentry"
+ ],
+ "codename": "change_logentry"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete log entry",
+ "content_type": [
+ "admin",
+ "logentry"
+ ],
+ "codename": "delete_logentry"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view log entry",
+ "content_type": [
+ "admin",
+ "logentry"
+ ],
+ "codename": "view_logentry"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add permission",
+ "content_type": [
+ "auth",
+ "permission"
+ ],
+ "codename": "add_permission"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change permission",
+ "content_type": [
+ "auth",
+ "permission"
+ ],
+ "codename": "change_permission"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete permission",
+ "content_type": [
+ "auth",
+ "permission"
+ ],
+ "codename": "delete_permission"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view permission",
+ "content_type": [
+ "auth",
+ "permission"
+ ],
+ "codename": "view_permission"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add group",
+ "content_type": [
+ "auth",
+ "group"
+ ],
+ "codename": "add_group"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change group",
+ "content_type": [
+ "auth",
+ "group"
+ ],
+ "codename": "change_group"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete group",
+ "content_type": [
+ "auth",
+ "group"
+ ],
+ "codename": "delete_group"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view group",
+ "content_type": [
+ "auth",
+ "group"
+ ],
+ "codename": "view_group"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add content type",
+ "content_type": [
+ "contenttypes",
+ "contenttype"
+ ],
+ "codename": "add_contenttype"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change content type",
+ "content_type": [
+ "contenttypes",
+ "contenttype"
+ ],
+ "codename": "change_contenttype"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete content type",
+ "content_type": [
+ "contenttypes",
+ "contenttype"
+ ],
+ "codename": "delete_contenttype"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view content type",
+ "content_type": [
+ "contenttypes",
+ "contenttype"
+ ],
+ "codename": "view_contenttype"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add session",
+ "content_type": [
+ "sessions",
+ "session"
+ ],
+ "codename": "add_session"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change session",
+ "content_type": [
+ "sessions",
+ "session"
+ ],
+ "codename": "change_session"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete session",
+ "content_type": [
+ "sessions",
+ "session"
+ ],
+ "codename": "delete_session"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view session",
+ "content_type": [
+ "sessions",
+ "session"
+ ],
+ "codename": "view_session"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add crontab",
+ "content_type": [
+ "django_celery_beat",
+ "crontabschedule"
+ ],
+ "codename": "add_crontabschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change crontab",
+ "content_type": [
+ "django_celery_beat",
+ "crontabschedule"
+ ],
+ "codename": "change_crontabschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete crontab",
+ "content_type": [
+ "django_celery_beat",
+ "crontabschedule"
+ ],
+ "codename": "delete_crontabschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view crontab",
+ "content_type": [
+ "django_celery_beat",
+ "crontabschedule"
+ ],
+ "codename": "view_crontabschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add interval",
+ "content_type": [
+ "django_celery_beat",
+ "intervalschedule"
+ ],
+ "codename": "add_intervalschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change interval",
+ "content_type": [
+ "django_celery_beat",
+ "intervalschedule"
+ ],
+ "codename": "change_intervalschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete interval",
+ "content_type": [
+ "django_celery_beat",
+ "intervalschedule"
+ ],
+ "codename": "delete_intervalschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view interval",
+ "content_type": [
+ "django_celery_beat",
+ "intervalschedule"
+ ],
+ "codename": "view_intervalschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add periodic task",
+ "content_type": [
+ "django_celery_beat",
+ "periodictask"
+ ],
+ "codename": "add_periodictask"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change periodic task",
+ "content_type": [
+ "django_celery_beat",
+ "periodictask"
+ ],
+ "codename": "change_periodictask"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete periodic task",
+ "content_type": [
+ "django_celery_beat",
+ "periodictask"
+ ],
+ "codename": "delete_periodictask"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view periodic task",
+ "content_type": [
+ "django_celery_beat",
+ "periodictask"
+ ],
+ "codename": "view_periodictask"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add periodic tasks",
+ "content_type": [
+ "django_celery_beat",
+ "periodictasks"
+ ],
+ "codename": "add_periodictasks"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change periodic tasks",
+ "content_type": [
+ "django_celery_beat",
+ "periodictasks"
+ ],
+ "codename": "change_periodictasks"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete periodic tasks",
+ "content_type": [
+ "django_celery_beat",
+ "periodictasks"
+ ],
+ "codename": "delete_periodictasks"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view periodic tasks",
+ "content_type": [
+ "django_celery_beat",
+ "periodictasks"
+ ],
+ "codename": "view_periodictasks"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add solar event",
+ "content_type": [
+ "django_celery_beat",
+ "solarschedule"
+ ],
+ "codename": "add_solarschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change solar event",
+ "content_type": [
+ "django_celery_beat",
+ "solarschedule"
+ ],
+ "codename": "change_solarschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete solar event",
+ "content_type": [
+ "django_celery_beat",
+ "solarschedule"
+ ],
+ "codename": "delete_solarschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view solar event",
+ "content_type": [
+ "django_celery_beat",
+ "solarschedule"
+ ],
+ "codename": "view_solarschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add clocked",
+ "content_type": [
+ "django_celery_beat",
+ "clockedschedule"
+ ],
+ "codename": "add_clockedschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change clocked",
+ "content_type": [
+ "django_celery_beat",
+ "clockedschedule"
+ ],
+ "codename": "change_clockedschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete clocked",
+ "content_type": [
+ "django_celery_beat",
+ "clockedschedule"
+ ],
+ "codename": "delete_clockedschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view clocked",
+ "content_type": [
+ "django_celery_beat",
+ "clockedschedule"
+ ],
+ "codename": "view_clockedschedule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add registration profile",
+ "content_type": [
+ "registration",
+ "registrationprofile"
+ ],
+ "codename": "add_registrationprofile"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change registration profile",
+ "content_type": [
+ "registration",
+ "registrationprofile"
+ ],
+ "codename": "change_registrationprofile"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete registration profile",
+ "content_type": [
+ "registration",
+ "registrationprofile"
+ ],
+ "codename": "delete_registrationprofile"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view registration profile",
+ "content_type": [
+ "registration",
+ "registrationprofile"
+ ],
+ "codename": "view_registrationprofile"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add supervised registration profile",
+ "content_type": [
+ "registration",
+ "supervisedregistrationprofile"
+ ],
+ "codename": "add_supervisedregistrationprofile"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change supervised registration profile",
+ "content_type": [
+ "registration",
+ "supervisedregistrationprofile"
+ ],
+ "codename": "change_supervisedregistrationprofile"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete supervised registration profile",
+ "content_type": [
+ "registration",
+ "supervisedregistrationprofile"
+ ],
+ "codename": "delete_supervisedregistrationprofile"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view supervised registration profile",
+ "content_type": [
+ "registration",
+ "supervisedregistrationprofile"
+ ],
+ "codename": "view_supervisedregistrationprofile"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add access attempt",
+ "content_type": [
+ "axes",
+ "accessattempt"
+ ],
+ "codename": "add_accessattempt"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change access attempt",
+ "content_type": [
+ "axes",
+ "accessattempt"
+ ],
+ "codename": "change_accessattempt"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete access attempt",
+ "content_type": [
+ "axes",
+ "accessattempt"
+ ],
+ "codename": "delete_accessattempt"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view access attempt",
+ "content_type": [
+ "axes",
+ "accessattempt"
+ ],
+ "codename": "view_accessattempt"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add access log",
+ "content_type": [
+ "axes",
+ "accesslog"
+ ],
+ "codename": "add_accesslog"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change access log",
+ "content_type": [
+ "axes",
+ "accesslog"
+ ],
+ "codename": "change_accesslog"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete access log",
+ "content_type": [
+ "axes",
+ "accesslog"
+ ],
+ "codename": "delete_accesslog"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view access log",
+ "content_type": [
+ "axes",
+ "accesslog"
+ ],
+ "codename": "view_accesslog"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add user",
+ "content_type": [
+ "accounts",
+ "user"
+ ],
+ "codename": "add_user"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change user",
+ "content_type": [
+ "accounts",
+ "user"
+ ],
+ "codename": "change_user"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete user",
+ "content_type": [
+ "accounts",
+ "user"
+ ],
+ "codename": "delete_user"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view user",
+ "content_type": [
+ "accounts",
+ "user"
+ ],
+ "codename": "view_user"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add post",
+ "content_type": [
+ "core",
+ "post"
+ ],
+ "codename": "add_post"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change post",
+ "content_type": [
+ "core",
+ "post"
+ ],
+ "codename": "change_post"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete post",
+ "content_type": [
+ "core",
+ "post"
+ ],
+ "codename": "delete_post"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view post",
+ "content_type": [
+ "core",
+ "post"
+ ],
+ "codename": "view_post"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add Category",
+ "content_type": [
+ "core",
+ "category"
+ ],
+ "codename": "add_category"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change Category",
+ "content_type": [
+ "core",
+ "category"
+ ],
+ "codename": "change_category"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete Category",
+ "content_type": [
+ "core",
+ "category"
+ ],
+ "codename": "delete_category"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view Category",
+ "content_type": [
+ "core",
+ "category"
+ ],
+ "codename": "view_category"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can add collection rule",
+ "content_type": [
+ "collection",
+ "collectionrule"
+ ],
+ "codename": "add_collectionrule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can change collection rule",
+ "content_type": [
+ "collection",
+ "collectionrule"
+ ],
+ "codename": "change_collectionrule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can delete collection rule",
+ "content_type": [
+ "collection",
+ "collectionrule"
+ ],
+ "codename": "delete_collectionrule"
+ }
+},
+{
+ "model": "auth.permission",
+ "fields": {
+ "name": "Can view collection rule",
+ "content_type": [
+ "collection",
+ "collectionrule"
+ ],
+ "codename": "view_collectionrule"
+ }
+},
{
"model": "accounts.user",
"fields": {
- "password": "pbkdf2_sha256$150000$5lBD7JemxYfE$B+lM5wWUW2n/ZulPFaWHtzWjyQ/QZ6iwjAC2I0R/VzU=",
- "last_login": "2019-11-27T18:57:36.686Z",
+ "password": "pbkdf2_sha256$180000$KGKGsPnSwyiN$RqQAD46r4Kzqndqp5dmpj+H/drDrPRI0r6j4gLtYBjE=",
+ "last_login": "2020-05-02T18:29:04.047Z",
"is_superuser": true,
"first_name": "",
"last_name": "",
@@ -114,23 +1128,6 @@
"user_permissions": []
}
},
-{
- "model": "accounts.user",
- "fields": {
- "password": "pbkdf2_sha256$150000$vUwxT8T25R8C$S+Eq2tMRbSDE31/X5KGJ/M+Nblh7kKfzuM/z7HraR/Q=",
- "last_login": null,
- "is_superuser": false,
- "first_name": "",
- "last_name": "",
- "is_staff": false,
- "is_active": false,
- "date_joined": "2019-11-25T15:35:14.051Z",
- "email": "sonnyba871@gmail.com",
- "task": 26,
- "groups": [],
- "user_permissions": []
- }
-},
{
"model": "core.category",
"pk": 8,
@@ -160,14 +1157,14 @@
"pk": 3,
"fields": {
"created": "2019-07-14T13:08:10.374Z",
- "modified": "2019-11-29T22:35:20.346Z",
+ "modified": "2020-05-02T20:06:25.841Z",
"name": "Hackers News",
"url": "https://news.ycombinator.com/rss",
"website_url": "https://news.ycombinator.com/",
"favicon": "https://news.ycombinator.com/favicon.ico",
"timezone": "UTC",
"category": 9,
- "last_suceeded": "2019-11-29T22:35:20.235Z",
+ "last_suceeded": "2020-05-02T20:06:25.793Z",
"succeeded": true,
"error": null,
"user": [
@@ -180,14 +1177,14 @@
"pk": 4,
"fields": {
"created": "2019-07-20T11:24:32.745Z",
- "modified": "2019-11-29T22:35:19.525Z",
+ "modified": "2020-05-02T20:06:24.719Z",
"name": "BBC",
"url": "http://feeds.bbci.co.uk/news/world/rss.xml",
"website_url": "https://www.bbc.co.uk/news/",
"favicon": "https://m.files.bbci.co.uk/modules/bbc-morph-news-waf-page-meta/2.5.2/apple-touch-icon-57x57-precomposed.png",
"timezone": "UTC",
"category": 8,
- "last_suceeded": "2019-11-29T22:35:19.241Z",
+ "last_suceeded": "2020-05-02T20:06:24.128Z",
"succeeded": true,
"error": null,
"user": [
@@ -200,14 +1197,14 @@
"pk": 5,
"fields": {
"created": "2019-07-20T11:24:50.411Z",
- "modified": "2019-11-29T22:35:20.010Z",
+ "modified": "2020-05-02T20:06:25.548Z",
"name": "Ars Technica",
"url": "http://feeds.arstechnica.com/arstechnica/index?fmt=xml",
"website_url": "https://arstechnica.com",
"favicon": "https://cdn.arstechnica.net/favicon.ico",
"timezone": "UTC",
"category": 9,
- "last_suceeded": "2019-11-29T22:35:19.808Z",
+ "last_suceeded": "2020-05-02T20:06:25.364Z",
"succeeded": true,
"error": null,
"user": [
@@ -220,14 +1217,14 @@
"pk": 6,
"fields": {
"created": "2019-07-20T11:25:02.089Z",
- "modified": "2019-11-29T22:35:20.233Z",
+ "modified": "2020-05-02T20:06:25.741Z",
"name": "The Guardian",
"url": "https://www.theguardian.com/world/rss",
"website_url": "https://www.theguardian.com/world",
"favicon": "https://assets.guim.co.uk/images/favicons/873381bf11d58e20f551905d51575117/72x72.png",
"timezone": "UTC",
"category": 8,
- "last_suceeded": "2019-11-29T22:35:20.076Z",
+ "last_suceeded": "2020-05-02T20:06:25.620Z",
"succeeded": true,
"error": null,
"user": [
@@ -240,14 +1237,14 @@
"pk": 7,
"fields": {
"created": "2019-07-20T11:25:30.121Z",
- "modified": "2019-11-29T22:35:19.695Z",
+ "modified": "2020-05-02T20:06:25.352Z",
"name": "Tweakers",
"url": "http://feeds.feedburner.com/tweakers/mixed?fmt=xml",
"website_url": "https://tweakers.net/",
"favicon": null,
"timezone": "UTC",
"category": 9,
- "last_suceeded": "2019-11-29T22:35:19.528Z",
+ "last_suceeded": "2020-05-02T20:06:24.730Z",
"succeeded": true,
"error": null,
"user": [
@@ -260,14 +1257,14 @@
"pk": 8,
"fields": {
"created": "2019-07-20T11:25:46.256Z",
- "modified": "2019-11-29T22:35:20.074Z",
+ "modified": "2020-05-02T20:06:25.792Z",
"name": "The Verge",
"url": "https://www.theverge.com/rss/index.xml",
"website_url": "https://www.theverge.com/",
"favicon": "https://cdn.vox-cdn.com/uploads/chorus_asset/file/7395367/favicon-16x16.0.png",
"timezone": "UTC",
"category": 9,
- "last_suceeded": "2019-11-29T22:35:20.012Z",
+ "last_suceeded": "2020-05-02T20:06:25.742Z",
"succeeded": true,
"error": null,
"user": [
@@ -280,19 +1277,1419 @@
"pk": 9,
"fields": {
"created": "2019-11-24T15:28:41.399Z",
- "modified": "2019-11-29T22:35:19.807Z",
+ "modified": "2020-05-02T20:06:25.619Z",
"name": "NOS",
"url": "http://feeds.nos.nl/nosnieuwsalgemeen",
"website_url": null,
"favicon": null,
"timezone": "Europe/Amsterdam",
"category": 8,
- "last_suceeded": "2019-11-29T22:35:19.697Z",
+ "last_suceeded": "2020-05-02T20:06:25.549Z",
"succeeded": true,
"error": null,
"user": [
"sonny@bakker.nl"
]
}
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 10,
+ "fields": {
+ "created": "2020-05-02T20:32:34.107Z",
+ "modified": "2020-05-02T20:32:34.107Z",
+ "name": "CollectionRule-0",
+ "url": "http://rasmussen-guerra.com/",
+ "website_url": "https://ritter.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 11,
+ "fields": {
+ "created": "2020-05-02T20:32:34.164Z",
+ "modified": "2020-05-02T20:32:34.164Z",
+ "name": "CollectionRule-1",
+ "url": "https://www.evans.com/",
+ "website_url": "https://taylor.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 12,
+ "fields": {
+ "created": "2020-05-02T20:32:34.220Z",
+ "modified": "2020-05-02T20:32:34.220Z",
+ "name": "CollectionRule-2",
+ "url": "http://weaver-quinn.net/",
+ "website_url": "https://www.mcintyre.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 13,
+ "fields": {
+ "created": "2020-05-02T20:32:34.277Z",
+ "modified": "2020-05-02T20:32:34.277Z",
+ "name": "CollectionRule-3",
+ "url": "http://www.palmer.com/",
+ "website_url": "http://www.riggs.org/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 14,
+ "fields": {
+ "created": "2020-05-02T20:32:34.333Z",
+ "modified": "2020-05-02T20:32:34.333Z",
+ "name": "CollectionRule-4",
+ "url": "http://moody-stein.net/",
+ "website_url": "https://www.lewis.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 15,
+ "fields": {
+ "created": "2020-05-02T20:32:34.390Z",
+ "modified": "2020-05-02T20:32:34.391Z",
+ "name": "CollectionRule-5",
+ "url": "http://www.ochoa.com/",
+ "website_url": "https://brown.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 16,
+ "fields": {
+ "created": "2020-05-02T20:32:34.448Z",
+ "modified": "2020-05-02T20:32:34.448Z",
+ "name": "CollectionRule-6",
+ "url": "https://www.pearson.biz/",
+ "website_url": "http://acosta-johnson.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 17,
+ "fields": {
+ "created": "2020-05-02T20:32:34.506Z",
+ "modified": "2020-05-02T20:32:34.506Z",
+ "name": "CollectionRule-7",
+ "url": "https://jones.com/",
+ "website_url": "https://www.thornton.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 18,
+ "fields": {
+ "created": "2020-05-02T20:32:34.562Z",
+ "modified": "2020-05-02T20:32:34.562Z",
+ "name": "CollectionRule-8",
+ "url": "http://www.matthews-graves.com/",
+ "website_url": "http://stewart.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 19,
+ "fields": {
+ "created": "2020-05-02T20:32:34.618Z",
+ "modified": "2020-05-02T20:32:34.618Z",
+ "name": "CollectionRule-9",
+ "url": "http://www.kelly-martinez.com/",
+ "website_url": "https://www.freeman.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 20,
+ "fields": {
+ "created": "2020-05-02T20:32:34.674Z",
+ "modified": "2020-05-02T20:32:34.674Z",
+ "name": "CollectionRule-10",
+ "url": "https://www.roberts.biz/",
+ "website_url": "http://www.lopez.info/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 21,
+ "fields": {
+ "created": "2020-05-02T20:32:34.730Z",
+ "modified": "2020-05-02T20:32:34.730Z",
+ "name": "CollectionRule-11",
+ "url": "https://www.holmes-cross.com/",
+ "website_url": "https://www.ramirez.net/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 22,
+ "fields": {
+ "created": "2020-05-02T20:32:34.786Z",
+ "modified": "2020-05-02T20:32:34.786Z",
+ "name": "CollectionRule-12",
+ "url": "https://www.jenkins.com/",
+ "website_url": "https://www.faulkner.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 23,
+ "fields": {
+ "created": "2020-05-02T20:32:34.841Z",
+ "modified": "2020-05-02T20:32:34.842Z",
+ "name": "CollectionRule-13",
+ "url": "https://www.adkins.com/",
+ "website_url": "https://www.munoz-brown.info/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 24,
+ "fields": {
+ "created": "2020-05-02T20:32:34.897Z",
+ "modified": "2020-05-02T20:32:34.898Z",
+ "name": "CollectionRule-14",
+ "url": "https://www.rodriguez-ortega.biz/",
+ "website_url": "http://www.santos.info/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 25,
+ "fields": {
+ "created": "2020-05-02T20:32:34.953Z",
+ "modified": "2020-05-02T20:32:34.954Z",
+ "name": "CollectionRule-15",
+ "url": "https://www.hawkins-stewart.com/",
+ "website_url": "http://www.jones.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 26,
+ "fields": {
+ "created": "2020-05-02T20:32:35.010Z",
+ "modified": "2020-05-02T20:32:35.010Z",
+ "name": "CollectionRule-16",
+ "url": "http://mullins.net/",
+ "website_url": "https://www.curtis.org/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 27,
+ "fields": {
+ "created": "2020-05-02T20:32:35.067Z",
+ "modified": "2020-05-02T20:32:35.067Z",
+ "name": "CollectionRule-17",
+ "url": "http://frederick.com/",
+ "website_url": "https://www.fowler.info/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 28,
+ "fields": {
+ "created": "2020-05-02T20:32:35.124Z",
+ "modified": "2020-05-02T20:32:35.124Z",
+ "name": "CollectionRule-18",
+ "url": "http://schmidt.com/",
+ "website_url": "http://bryant-hoffman.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 29,
+ "fields": {
+ "created": "2020-05-02T20:32:35.180Z",
+ "modified": "2020-05-02T20:32:35.180Z",
+ "name": "CollectionRule-19",
+ "url": "https://www.jones.net/",
+ "website_url": "http://benjamin.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 30,
+ "fields": {
+ "created": "2020-05-02T20:32:35.237Z",
+ "modified": "2020-05-02T20:32:35.237Z",
+ "name": "CollectionRule-20",
+ "url": "https://www.parker-lewis.com/",
+ "website_url": "http://www.anderson.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 31,
+ "fields": {
+ "created": "2020-05-02T20:32:35.294Z",
+ "modified": "2020-05-02T20:32:35.294Z",
+ "name": "CollectionRule-21",
+ "url": "http://martinez.com/",
+ "website_url": "http://burton-scott.biz/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 32,
+ "fields": {
+ "created": "2020-05-02T20:32:35.350Z",
+ "modified": "2020-05-02T20:32:35.350Z",
+ "name": "CollectionRule-22",
+ "url": "https://gibbs.com/",
+ "website_url": "https://www.robertson.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 33,
+ "fields": {
+ "created": "2020-05-02T20:32:35.407Z",
+ "modified": "2020-05-02T20:32:35.407Z",
+ "name": "CollectionRule-23",
+ "url": "http://www.fisher.com/",
+ "website_url": "https://mcclure-miller.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 34,
+ "fields": {
+ "created": "2020-05-02T20:32:35.463Z",
+ "modified": "2020-05-02T20:32:35.463Z",
+ "name": "CollectionRule-24",
+ "url": "https://schneider-lopez.org/",
+ "website_url": "https://andrews-williams.biz/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 35,
+ "fields": {
+ "created": "2020-05-02T20:32:35.522Z",
+ "modified": "2020-05-02T20:32:35.522Z",
+ "name": "CollectionRule-25",
+ "url": "http://www.rogers.info/",
+ "website_url": "https://www.petersen-stewart.biz/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 36,
+ "fields": {
+ "created": "2020-05-02T20:32:35.581Z",
+ "modified": "2020-05-02T20:32:35.581Z",
+ "name": "CollectionRule-26",
+ "url": "http://torres.com/",
+ "website_url": "https://hart-tapia.org/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 37,
+ "fields": {
+ "created": "2020-05-02T20:32:35.637Z",
+ "modified": "2020-05-02T20:32:35.638Z",
+ "name": "CollectionRule-27",
+ "url": "http://www.pham-scott.com/",
+ "website_url": "http://smith-diaz.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 38,
+ "fields": {
+ "created": "2020-05-02T20:32:35.699Z",
+ "modified": "2020-05-02T20:32:35.699Z",
+ "name": "CollectionRule-28",
+ "url": "http://www.gonzalez-castillo.com/",
+ "website_url": "http://www.conley.biz/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 39,
+ "fields": {
+ "created": "2020-05-02T20:32:35.758Z",
+ "modified": "2020-05-02T20:32:35.758Z",
+ "name": "CollectionRule-29",
+ "url": "https://rogers-smith.net/",
+ "website_url": "http://www.sharp.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 40,
+ "fields": {
+ "created": "2020-05-02T20:32:35.814Z",
+ "modified": "2020-05-02T20:32:35.814Z",
+ "name": "CollectionRule-30",
+ "url": "https://neal-salinas.com/",
+ "website_url": "https://www.baird-warner.net/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 41,
+ "fields": {
+ "created": "2020-05-02T20:32:35.873Z",
+ "modified": "2020-05-02T20:32:35.874Z",
+ "name": "CollectionRule-31",
+ "url": "http://www.williams.com/",
+ "website_url": "http://www.wood.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 42,
+ "fields": {
+ "created": "2020-05-02T20:32:35.930Z",
+ "modified": "2020-05-02T20:32:35.930Z",
+ "name": "CollectionRule-32",
+ "url": "https://www.mueller.com/",
+ "website_url": "http://www.miller-ramirez.org/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 43,
+ "fields": {
+ "created": "2020-05-02T20:32:35.988Z",
+ "modified": "2020-05-02T20:32:35.989Z",
+ "name": "CollectionRule-33",
+ "url": "http://lee.com/",
+ "website_url": "http://www.moody.org/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 44,
+ "fields": {
+ "created": "2020-05-02T20:32:36.044Z",
+ "modified": "2020-05-02T20:32:36.045Z",
+ "name": "CollectionRule-34",
+ "url": "http://estrada.com/",
+ "website_url": "http://www.hicks.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 45,
+ "fields": {
+ "created": "2020-05-02T20:32:36.102Z",
+ "modified": "2020-05-02T20:32:36.102Z",
+ "name": "CollectionRule-35",
+ "url": "https://griffin-brewer.org/",
+ "website_url": "http://jones.info/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 46,
+ "fields": {
+ "created": "2020-05-02T20:32:36.161Z",
+ "modified": "2020-05-02T20:32:36.161Z",
+ "name": "CollectionRule-36",
+ "url": "http://www.dixon-johnson.com/",
+ "website_url": "https://mason.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 47,
+ "fields": {
+ "created": "2020-05-02T20:32:36.217Z",
+ "modified": "2020-05-02T20:32:36.217Z",
+ "name": "CollectionRule-37",
+ "url": "https://perez.com/",
+ "website_url": "http://www.miller.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 48,
+ "fields": {
+ "created": "2020-05-02T20:32:36.278Z",
+ "modified": "2020-05-02T20:32:36.279Z",
+ "name": "CollectionRule-38",
+ "url": "https://www.grant.net/",
+ "website_url": "https://www.clayton.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 49,
+ "fields": {
+ "created": "2020-05-02T20:32:36.336Z",
+ "modified": "2020-05-02T20:32:36.336Z",
+ "name": "CollectionRule-39",
+ "url": "http://www.lewis.org/",
+ "website_url": "http://cook.org/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 50,
+ "fields": {
+ "created": "2020-05-02T20:32:36.395Z",
+ "modified": "2020-05-02T20:32:36.395Z",
+ "name": "CollectionRule-40",
+ "url": "https://galloway-allen.net/",
+ "website_url": "http://www.rodriguez-callahan.info/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 51,
+ "fields": {
+ "created": "2020-05-02T20:32:36.453Z",
+ "modified": "2020-05-02T20:32:36.453Z",
+ "name": "CollectionRule-41",
+ "url": "https://www.macias.com/",
+ "website_url": "https://jarvis-green.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 52,
+ "fields": {
+ "created": "2020-05-02T20:32:36.510Z",
+ "modified": "2020-05-02T20:32:36.510Z",
+ "name": "CollectionRule-42",
+ "url": "http://mccullough-grant.com/",
+ "website_url": "https://shannon.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 53,
+ "fields": {
+ "created": "2020-05-02T20:32:36.566Z",
+ "modified": "2020-05-02T20:32:36.566Z",
+ "name": "CollectionRule-43",
+ "url": "http://www.foster-oneal.org/",
+ "website_url": "http://johns.org/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 54,
+ "fields": {
+ "created": "2020-05-02T20:32:36.623Z",
+ "modified": "2020-05-02T20:32:36.623Z",
+ "name": "CollectionRule-44",
+ "url": "http://www.wright.net/",
+ "website_url": "http://www.ali.biz/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 55,
+ "fields": {
+ "created": "2020-05-02T20:32:36.682Z",
+ "modified": "2020-05-02T20:32:36.682Z",
+ "name": "CollectionRule-45",
+ "url": "http://www.payne-gibbs.info/",
+ "website_url": "http://knight.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 56,
+ "fields": {
+ "created": "2020-05-02T20:32:36.740Z",
+ "modified": "2020-05-02T20:32:36.740Z",
+ "name": "CollectionRule-46",
+ "url": "http://hammond.biz/",
+ "website_url": "http://www.nelson.net/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 57,
+ "fields": {
+ "created": "2020-05-02T20:32:36.797Z",
+ "modified": "2020-05-02T20:32:36.797Z",
+ "name": "CollectionRule-47",
+ "url": "http://gilmore.com/",
+ "website_url": "http://coleman.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 58,
+ "fields": {
+ "created": "2020-05-02T20:32:36.855Z",
+ "modified": "2020-05-02T20:32:36.855Z",
+ "name": "CollectionRule-48",
+ "url": "https://www.hernandez.com/",
+ "website_url": "https://www.phillips.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 59,
+ "fields": {
+ "created": "2020-05-02T20:32:36.912Z",
+ "modified": "2020-05-02T20:32:36.912Z",
+ "name": "CollectionRule-49",
+ "url": "https://www.nguyen.com/",
+ "website_url": "http://www.floyd.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 60,
+ "fields": {
+ "created": "2020-05-02T20:32:36.969Z",
+ "modified": "2020-05-02T20:32:36.969Z",
+ "name": "CollectionRule-50",
+ "url": "https://meyer-brown.net/",
+ "website_url": "https://www.blankenship.biz/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 61,
+ "fields": {
+ "created": "2020-05-02T20:32:37.026Z",
+ "modified": "2020-05-02T20:32:37.027Z",
+ "name": "CollectionRule-51",
+ "url": "https://marks.net/",
+ "website_url": "http://gregory.net/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 62,
+ "fields": {
+ "created": "2020-05-02T20:32:37.087Z",
+ "modified": "2020-05-02T20:32:37.087Z",
+ "name": "CollectionRule-52",
+ "url": "http://www.baxter.com/",
+ "website_url": "http://barrera.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 63,
+ "fields": {
+ "created": "2020-05-02T20:32:37.143Z",
+ "modified": "2020-05-02T20:32:37.143Z",
+ "name": "CollectionRule-53",
+ "url": "http://johnson.com/",
+ "website_url": "https://abbott.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 64,
+ "fields": {
+ "created": "2020-05-02T20:32:37.202Z",
+ "modified": "2020-05-02T20:32:37.202Z",
+ "name": "CollectionRule-54",
+ "url": "https://hebert-marshall.biz/",
+ "website_url": "https://www.ashley-walsh.org/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 65,
+ "fields": {
+ "created": "2020-05-02T20:32:37.261Z",
+ "modified": "2020-05-02T20:32:37.261Z",
+ "name": "CollectionRule-55",
+ "url": "https://miller.com/",
+ "website_url": "https://www.hoffman.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 66,
+ "fields": {
+ "created": "2020-05-02T20:32:37.320Z",
+ "modified": "2020-05-02T20:32:37.320Z",
+ "name": "CollectionRule-56",
+ "url": "http://frey.com/",
+ "website_url": "https://long.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 67,
+ "fields": {
+ "created": "2020-05-02T20:32:37.379Z",
+ "modified": "2020-05-02T20:32:37.379Z",
+ "name": "CollectionRule-57",
+ "url": "https://edwards.com/",
+ "website_url": "http://www.nixon-doyle.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 68,
+ "fields": {
+ "created": "2020-05-02T20:32:37.435Z",
+ "modified": "2020-05-02T20:32:37.435Z",
+ "name": "CollectionRule-58",
+ "url": "https://www.bennett.com/",
+ "website_url": "http://sullivan.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 69,
+ "fields": {
+ "created": "2020-05-02T20:32:37.493Z",
+ "modified": "2020-05-02T20:32:37.493Z",
+ "name": "CollectionRule-59",
+ "url": "http://stokes-thomas.com/",
+ "website_url": "http://morgan.net/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 70,
+ "fields": {
+ "created": "2020-05-02T20:32:37.550Z",
+ "modified": "2020-05-02T20:32:37.550Z",
+ "name": "CollectionRule-60",
+ "url": "https://moore.net/",
+ "website_url": "http://www.hubbard.biz/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 71,
+ "fields": {
+ "created": "2020-05-02T20:32:37.609Z",
+ "modified": "2020-05-02T20:32:37.609Z",
+ "name": "CollectionRule-61",
+ "url": "https://baker-edwards.com/",
+ "website_url": "https://www.anderson.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 72,
+ "fields": {
+ "created": "2020-05-02T20:32:37.666Z",
+ "modified": "2020-05-02T20:32:37.666Z",
+ "name": "CollectionRule-62",
+ "url": "https://www.jackson.com/",
+ "website_url": "https://www.edwards.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 73,
+ "fields": {
+ "created": "2020-05-02T20:32:37.724Z",
+ "modified": "2020-05-02T20:32:37.724Z",
+ "name": "CollectionRule-63",
+ "url": "https://kemp-pollard.biz/",
+ "website_url": "http://www.fuentes.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 74,
+ "fields": {
+ "created": "2020-05-02T20:32:37.782Z",
+ "modified": "2020-05-02T20:32:37.782Z",
+ "name": "CollectionRule-64",
+ "url": "https://hanna-cook.com/",
+ "website_url": "http://www.bowen.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 75,
+ "fields": {
+ "created": "2020-05-02T20:32:37.839Z",
+ "modified": "2020-05-02T20:32:37.839Z",
+ "name": "CollectionRule-65",
+ "url": "http://www.williams.net/",
+ "website_url": "http://www.chandler.org/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 76,
+ "fields": {
+ "created": "2020-05-02T20:32:37.896Z",
+ "modified": "2020-05-02T20:32:37.896Z",
+ "name": "CollectionRule-66",
+ "url": "https://www.alexander.com/",
+ "website_url": "https://johnson-ellis.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 77,
+ "fields": {
+ "created": "2020-05-02T20:32:37.951Z",
+ "modified": "2020-05-02T20:32:37.951Z",
+ "name": "CollectionRule-67",
+ "url": "https://www.cisneros.com/",
+ "website_url": "http://fox.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 78,
+ "fields": {
+ "created": "2020-05-02T20:32:38.008Z",
+ "modified": "2020-05-02T20:32:38.008Z",
+ "name": "CollectionRule-68",
+ "url": "http://www.foster-burton.com/",
+ "website_url": "https://grant.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
+},
+{
+ "model": "collection.collectionrule",
+ "pk": 79,
+ "fields": {
+ "created": "2020-05-02T20:32:38.066Z",
+ "modified": "2020-05-02T20:32:38.066Z",
+ "name": "CollectionRule-69",
+ "url": "https://www.hayes.net/",
+ "website_url": "http://morgan.com/",
+ "favicon": null,
+ "timezone": "UTC",
+ "category": null,
+ "last_suceeded": null,
+ "succeeded": false,
+ "error": null,
+ "user": [
+ "sonny@bakker.nl"
+ ]
+ }
}
]
diff --git a/src/newsreader/js/components/Selector.js b/src/newsreader/js/components/Selector.js
new file mode 100644
index 0000000..8b701f5
--- /dev/null
+++ b/src/newsreader/js/components/Selector.js
@@ -0,0 +1,23 @@
+class Selector {
+ onClick = ::this.onClick;
+
+ inputs = [];
+
+ constructor() {
+ const selectAllInput = document.querySelector('#select-all');
+
+ this.inputs = document.querySelectorAll(`[name=${selectAllInput.dataset.input}`);
+
+ selectAllInput.onchange = this.onClick;
+ }
+
+ onClick(e) {
+ const targetValue = e.target.checked;
+
+ this.inputs.forEach(input => {
+ input.checked = targetValue;
+ });
+ }
+}
+
+export default Selector;
diff --git a/src/newsreader/js/index.js b/src/newsreader/js/index.js
index 48db0b2..1ed14ed 100644
--- a/src/newsreader/js/index.js
+++ b/src/newsreader/js/index.js
@@ -1,3 +1,3 @@
import './pages/homepage/index.js';
-import './pages/rules/index.js';
import './pages/categories/index.js';
+import './pages/rules/index.js';
diff --git a/src/newsreader/js/pages/rules/App.js b/src/newsreader/js/pages/rules/App.js
deleted file mode 100644
index 7ceae4a..0000000
--- a/src/newsreader/js/pages/rules/App.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import React from 'react';
-
-import Cookies from 'js-cookie';
-
-import Card from '../../components/Card.js';
-import RuleCard from './components/RuleCard.js';
-import RuleModal from './components/RuleModal.js';
-import Messages from '../../components/Messages.js';
-
-class App extends React.Component {
- selectRule = ::this.selectRule;
- deselectRule = ::this.deselectRule;
- deleteRule = ::this.deleteRule;
-
- constructor(props) {
- super(props);
-
- this.token = Cookies.get('csrftoken');
- this.state = {
- rules: props.rules,
- selectedRuleId: null,
- message: null,
- };
- }
-
- selectRule(ruleId) {
- this.setState({ selectedRuleId: ruleId });
- }
-
- deselectRule() {
- this.setState({ selectedRuleId: null });
- }
-
- deleteRule(ruleId) {
- const url = `/api/rules/${ruleId}/`;
- const options = {
- method: 'DELETE',
- headers: {
- 'X-CSRFToken': this.token,
- },
- };
-
- fetch(url, options).then(response => {
- if (response.ok) {
- const rules = this.state.rules.filter(rule => {
- return rule.pk != ruleId;
- });
-
- return this.setState({
- rules: rules,
- selectedRuleId: null,
- message: null,
- });
- }
- });
-
- const message = {
- type: 'error',
- text: 'Unable to remove rule, try again later',
- };
- return this.setState({ selectedRuleId: null, message: message });
- }
-
- render() {
- const { rules } = this.state;
- const cards = rules.map(rule => {
- return ;
- });
-
- const selectedRule = rules.find(rule => {
- return rule.pk === this.state.selectedRuleId;
- });
-
- const pageHeader = (
- <>
-
Rules
-
-
- >
- );
-
- return (
- <>
- {this.state.message && }
-
- {cards}
- {selectedRule && (
-
- )}
- >
- );
- }
-}
-
-export default App;
diff --git a/src/newsreader/js/pages/rules/components/RuleCard.js b/src/newsreader/js/pages/rules/components/RuleCard.js
deleted file mode 100644
index d74b8d1..0000000
--- a/src/newsreader/js/pages/rules/components/RuleCard.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import React from 'react';
-
-import Card from '../../../components/Card.js';
-
-const RuleCard = props => {
- const { rule } = props;
- let favicon = null;
-
- if (rule.favicon) {
- favicon =
;
- } else {
- favicon = ;
- }
-
- const stateIcon = !rule.error ? 'gg-check' : 'gg-danger';
-
- const cardHeader = (
- <>
-
- {rule.name}
- {favicon}
- >
- );
-
- const cardContent = (
- <>
-
- {rule.error && (
-
- )}
-
- {rule.category && - {rule.category}
}
- -
-
- {rule.url}
-
-
- - {rule.created}
- - {rule.timezone}
-
- >
- );
-
- const cardFooter = (
- <>
-
- Edit
-
-
- >
- );
-
- return ;
-};
-
-export default RuleCard;
diff --git a/src/newsreader/js/pages/rules/components/RuleModal.js b/src/newsreader/js/pages/rules/components/RuleModal.js
deleted file mode 100644
index d174cc3..0000000
--- a/src/newsreader/js/pages/rules/components/RuleModal.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react';
-
-import Modal from '../../../components/Modal.js';
-
-const RuleModal = props => {
- const content = (
- <>
-
-
-
Delete rule
-
-
-
-
Are you sure you want to delete {props.rule.name}?
-
-
-
-
-
-
-
- >
- );
-
- return ;
-};
-
-export default RuleModal;
diff --git a/src/newsreader/js/pages/rules/index.js b/src/newsreader/js/pages/rules/index.js
index d0b46e9..b888121 100644
--- a/src/newsreader/js/pages/rules/index.js
+++ b/src/newsreader/js/pages/rules/index.js
@@ -1,13 +1,7 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-
-import App from './App.js';
+import Selector from '../../components/Selector.js';
const page = document.getElementById('rules--page');
if (page) {
- const dataScript = document.getElementById('rules-data');
- const rules = JSON.parse(dataScript.textContent);
-
- ReactDOM.render(, page);
+ new Selector();
}
diff --git a/src/newsreader/news/collection/forms.py b/src/newsreader/news/collection/forms.py
index d0b02be..bfa0d90 100644
--- a/src/newsreader/news/collection/forms.py
+++ b/src/newsreader/news/collection/forms.py
@@ -36,6 +36,17 @@ class CollectionRuleForm(forms.ModelForm):
fields = ("name", "url", "timezone", "favicon", "category")
+class CollectionRuleBulkForm(forms.Form):
+ rules = forms.ModelMultipleChoiceField(queryset=CollectionRule.objects.none())
+
+ def __init__(self, user, *args, **kwargs):
+ self.user = user
+
+ super().__init__(*args, **kwargs)
+
+ self.fields["rules"].queryset = CollectionRule.objects.filter(user=user)
+
+
class OPMLImportForm(forms.Form):
file = forms.FileField(allow_empty_file=False)
skip_existing = forms.BooleanField(initial=False, required=False)
diff --git a/src/newsreader/news/collection/migrations/0007_collectionrule_enabled.py b/src/newsreader/news/collection/migrations/0007_collectionrule_enabled.py
new file mode 100644
index 0000000..fe6b0eb
--- /dev/null
+++ b/src/newsreader/news/collection/migrations/0007_collectionrule_enabled.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.5 on 2020-05-10 13:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [("collection", "0006_auto_20200412_1955")]
+
+ operations = [
+ migrations.AddField(
+ model_name="collectionrule",
+ name="enabled",
+ field=models.BooleanField(
+ default=True, help_text="Wether or not to collect items from this feed"
+ ),
+ )
+ ]
diff --git a/src/newsreader/news/collection/models.py b/src/newsreader/news/collection/models.py
index d1d62ce..a5bfdfb 100644
--- a/src/newsreader/news/collection/models.py
+++ b/src/newsreader/news/collection/models.py
@@ -10,9 +10,7 @@ class CollectionRule(TimeStampedModel):
name = models.CharField(max_length=100)
url = models.URLField(max_length=1024)
- website_url = models.URLField(
- max_length=1024, editable=False, blank=True, null=True
- )
+ website_url = models.URLField(max_length=1024, editable=False, blank=True, null=True)
favicon = models.URLField(blank=True, null=True)
timezone = models.CharField(
@@ -34,6 +32,9 @@ class CollectionRule(TimeStampedModel):
last_suceeded = models.DateTimeField(blank=True, null=True)
succeeded = models.BooleanField(default=False)
error = models.CharField(max_length=1024, blank=True, null=True)
+ enabled = models.BooleanField(
+ default=True, help_text=_("Wether or not to collect items from this feed")
+ )
user = models.ForeignKey(
"accounts.User",
diff --git a/src/newsreader/news/collection/templates/collection/rules.html b/src/newsreader/news/collection/templates/collection/rules.html
index 508916a..23b3fe7 100644
--- a/src/newsreader/news/collection/templates/collection/rules.html
+++ b/src/newsreader/news/collection/templates/collection/rules.html
@@ -1,30 +1,71 @@
{% extends "base.html" %}
+{% load i18n %}
{% load static %}
{% block content %}
-
-{% endblock %}
+
+
+
+
{% endblock %}
diff --git a/src/newsreader/news/collection/tests/views/test_bulk_views.py b/src/newsreader/news/collection/tests/views/test_bulk_views.py
new file mode 100644
index 0000000..7679907
--- /dev/null
+++ b/src/newsreader/news/collection/tests/views/test_bulk_views.py
@@ -0,0 +1,244 @@
+
+from django.conf import settings
+from django.test import TestCase
+from django.urls import reverse
+from django.utils.translation import gettext_lazy as _
+
+import pytz
+
+from newsreader.accounts.tests.factories import UserFactory
+from newsreader.news.collection.models import CollectionRule
+from newsreader.news.collection.tests.factories import CollectionRuleFactory
+from newsreader.news.core.tests.factories import CategoryFactory
+
+
+class CollectionRuleBulkViewTestCase:
+ def setUp(self):
+ self.redirect_url = reverse("rules")
+
+ self.user = UserFactory()
+ self.client.force_login(self.user)
+
+
+class CollectionRuleBulkEnableViewTestCase(CollectionRuleBulkViewTestCase, TestCase):
+ def setUp(self):
+ super().setUp()
+
+ self.url = reverse("rules-enable")
+
+ self.rules = CollectionRuleFactory.create_batch(
+ size=5, user=self.user, enabled=False
+ )
+
+ def test_simple(self):
+ response = self.client.post(
+ self.url, {"rules": [rule.pk for rule in self.rules]}, follow=True
+ )
+
+ self.assertRedirects(response, self.redirect_url)
+
+ rules = CollectionRule.objects.filter(user=self.user)
+
+ for rule in rules:
+ with self.subTest(rule=rule):
+ self.assertEqual(rule.enabled, True)
+
+ self.assertNotContains(response, _("The form contains errors, try again later"))
+
+ def test_empty_rules(self):
+ response = self.client.post(self.url, {"rules": []}, follow=True)
+
+ self.assertRedirects(response, self.redirect_url)
+
+ rules = CollectionRule.objects.filter(user=self.user)
+
+ for rule in rules:
+ with self.subTest(rule=rule):
+ self.assertEqual(rule.enabled, False)
+
+ self.assertContains(response, _("The form contains errors, try again later"))
+
+ def test_rule_from_other_user(self):
+ other_user = UserFactory()
+ other_rules = CollectionRuleFactory.create_batch(
+ size=5, user=other_user, enabled=False
+ )
+
+ response = self.client.post(
+ self.url,
+ {"rules": [other_rule.pk for other_rule in other_rules]},
+ follow=True,
+ )
+
+ self.assertRedirects(response, self.redirect_url)
+
+ rules = CollectionRule.objects.filter(user=other_user)
+
+ for rule in rules:
+ with self.subTest(rule=rule):
+ self.assertEqual(rule.enabled, False)
+
+ self.assertContains(response, _("The form contains errors, try again later"))
+
+ def test_unauthenticated(self):
+ self.client.logout()
+
+ response = self.client.post(
+ self.url, {"rules": [rule.pk for rule in self.rules]}, follow=True
+ )
+
+ self.assertRedirects(
+ response, f"{reverse('accounts:login')}?next={reverse('rules-enable')}"
+ )
+
+ rules = CollectionRule.objects.filter(user=self.user)
+
+ for rule in rules:
+ with self.subTest(rule=rule):
+ self.assertEqual(rule.enabled, False)
+
+
+class CollectionRuleBulkDisableViewTestCase(CollectionRuleBulkViewTestCase, TestCase):
+ def setUp(self):
+ super().setUp()
+
+ self.url = reverse("rules-disable")
+
+ self.rules = CollectionRuleFactory.create_batch(
+ size=5, user=self.user, enabled=True
+ )
+
+ def test_simple(self):
+ response = self.client.post(
+ self.url, {"rules": [rule.pk for rule in self.rules]}, follow=True
+ )
+
+ self.assertRedirects(response, self.redirect_url)
+
+ rules = CollectionRule.objects.filter(user=self.user)
+
+ for rule in rules:
+ with self.subTest(rule=rule):
+ self.assertEqual(rule.enabled, False)
+
+ self.assertNotContains(response, _("The form contains errors, try again later"))
+
+ def test_empty_rules(self):
+ response = self.client.post(self.url, {"rules": []}, follow=True)
+
+ self.assertRedirects(response, self.redirect_url)
+
+ rules = CollectionRule.objects.filter(user=self.user)
+
+ for rule in rules:
+ with self.subTest(rule=rule):
+ self.assertEqual(rule.enabled, True)
+
+ self.assertContains(response, _("The form contains errors, try again later"))
+
+ def test_rule_from_other_user(self):
+ other_user = UserFactory()
+ other_rules = CollectionRuleFactory.create_batch(
+ size=5, user=other_user, enabled=True
+ )
+
+ response = self.client.post(
+ self.url,
+ {"rules": [other_rule.pk for other_rule in other_rules]},
+ follow=True,
+ )
+
+ self.assertRedirects(response, self.redirect_url)
+
+ rules = CollectionRule.objects.filter(user=other_user)
+
+ for rule in rules:
+ with self.subTest(rule=rule):
+ self.assertEqual(rule.enabled, True)
+
+ self.assertContains(response, _("The form contains errors, try again later"))
+
+ def test_unauthenticated(self):
+ self.client.logout()
+
+ response = self.client.post(
+ self.url, {"rules": [rule.pk for rule in self.rules]}, follow=True
+ )
+
+ self.assertRedirects(
+ response, f"{reverse('accounts:login')}?next={reverse('rules-disable')}"
+ )
+
+ rules = CollectionRule.objects.filter(user=self.user)
+
+ for rule in rules:
+ with self.subTest(rule=rule):
+ self.assertEqual(rule.enabled, True)
+
+
+class CollectionRuleBulkDeleteViewTestCase(CollectionRuleBulkViewTestCase, TestCase):
+ def setUp(self):
+ super().setUp()
+
+ self.url = reverse("rules-delete")
+
+ self.rules = CollectionRuleFactory.create_batch(size=5, user=self.user)
+
+ def test_simple(self):
+ response = self.client.post(
+ self.url, {"rules": [rule.pk for rule in self.rules]}, follow=True
+ )
+
+ self.assertRedirects(response, self.redirect_url)
+
+ rules = CollectionRule.objects.filter(user=self.user)
+
+ self.assertCountEqual(rules, [])
+
+ self.assertNotContains(response, _("The form contains errors, try again later"))
+
+ def test_empty_rules(self):
+ response = self.client.post(self.url, {"rules": []}, follow=True)
+
+ self.assertRedirects(response, self.redirect_url)
+
+ rules = CollectionRule.objects.filter(user=self.user)
+
+ self.assertCountEqual(rules, self.rules)
+
+ self.assertContains(response, _("The form contains errors, try again later"))
+
+ def test_rule_from_other_user(self):
+ other_user = UserFactory()
+ other_rules = CollectionRuleFactory.create_batch(
+ size=5, user=other_user, enabled=True
+ )
+
+ response = self.client.post(
+ self.url,
+ {"rules": [other_rule.pk for other_rule in other_rules]},
+ follow=True,
+ )
+
+ self.assertRedirects(response, self.redirect_url)
+
+ rules = CollectionRule.objects.filter(user=other_user)
+
+ self.assertCountEqual(rules, other_rules)
+
+ self.assertContains(response, _("The form contains errors, try again later"))
+
+ def test_unauthenticated(self):
+ self.client.logout()
+
+ response = self.client.post(
+ self.url, {"rules": [rule.pk for rule in self.rules]}, follow=True
+ )
+
+ self.assertRedirects(
+ response, f"{reverse('accounts:login')}?next={reverse('rules-delete')}"
+ )
+
+ rules = CollectionRule.objects.filter(user=self.user)
+
+ self.assertCountEqual(rules, self.rules)
diff --git a/src/newsreader/news/collection/tests/test_views.py b/src/newsreader/news/collection/tests/views/test_crud.py
similarity index 52%
rename from src/newsreader/news/collection/tests/test_views.py
rename to src/newsreader/news/collection/tests/views/test_crud.py
index 0acd3ed..d77bcf6 100644
--- a/src/newsreader/news/collection/tests/test_views.py
+++ b/src/newsreader/news/collection/tests/views/test_crud.py
@@ -150,135 +150,3 @@ class CollectionRuleUpdateViewTestCase(CollectionRuleViewTestCase, TestCase):
self.rule.refresh_from_db()
self.assertEquals(self.rule.category, None)
-
-
-class OPMLImportTestCase(TestCase):
- def setUp(self):
- self.user = UserFactory(password="test")
- self.client.force_login(self.user)
-
- self.form_data = {"file": "", "skip_existing": False}
- self.url = reverse("import")
-
- def _get_file_path(self, name):
- file_dir = os.path.join(settings.DJANGO_PROJECT_DIR, "utils", "tests", "files")
- return os.path.join(file_dir, name)
-
- def test_simple(self):
- file_path = self._get_file_path("feeds.opml")
-
- with open(file_path) as file:
- self.form_data.update(file=file)
-
- response = self.client.post(self.url, self.form_data)
-
- self.assertRedirects(response, reverse("rules"))
-
- rules = CollectionRule.objects.all()
- self.assertEquals(len(rules), 4)
-
- def test_existing_rules(self):
- CollectionRuleFactory(
- url="http://www.engadget.com/rss-full.xml", user=self.user
- )
- CollectionRuleFactory(url="https://news.ycombinator.com/rss", user=self.user)
- CollectionRuleFactory(
- url="http://feeds.feedburner.com/Techcrunch", user=self.user
- )
- CollectionRuleFactory(
- url="http://feeds.feedburner.com/tweakers/nieuws", user=self.user
- )
-
- file_path = self._get_file_path("feeds.opml")
-
- with open(file_path) as file:
- self.form_data.update(file=file)
-
- response = self.client.post(self.url, self.form_data)
-
- self.assertRedirects(response, reverse("rules"))
-
- rules = CollectionRule.objects.all()
- self.assertEquals(len(rules), 8)
-
- def test_skip_existing_rules(self):
- CollectionRuleFactory(
- url="http://www.engadget.com/rss-full.xml", user=self.user
- )
- CollectionRuleFactory(url="https://news.ycombinator.com/rss", user=self.user)
- CollectionRuleFactory(
- url="http://feeds.feedburner.com/Techcrunch", user=self.user
- )
- CollectionRuleFactory(
- url="http://feeds.feedburner.com/tweakers/nieuws", user=self.user
- )
-
- file_path = self._get_file_path("feeds.opml")
-
- with open(file_path) as file:
- self.form_data.update(file=file, skip_existing=True)
-
- response = self.client.post(self.url, self.form_data)
-
- self.assertEquals(response.status_code, 200)
-
- rules = CollectionRule.objects.all()
- self.assertEquals(len(rules), 4)
-
- def test_empty_feed_file(self):
- file_path = self._get_file_path("empty-feeds.opml")
-
- with open(file_path) as file:
- self.form_data.update(file=file)
-
- response = self.client.post(self.url, self.form_data)
-
- self.assertEquals(response.status_code, 200)
-
- rules = CollectionRule.objects.all()
- self.assertEquals(len(rules), 0)
-
- self.assertFormError(response, "form", "file", _("No (new) rules found"))
-
- def test_invalid_feeds(self):
- file_path = self._get_file_path("invalid-url-feeds.opml")
-
- with open(file_path) as file:
- self.form_data.update(file=file)
-
- response = self.client.post(self.url, self.form_data)
-
- self.assertEquals(response.status_code, 200)
-
- rules = CollectionRule.objects.all()
-
- self.assertEquals(len(rules), 0)
- self.assertFormError(response, "form", "file", _("No (new) rules found"))
-
- def test_invalid_file(self):
- file_path = self._get_file_path("test.png")
-
- with open(file_path, "rb") as file:
- self.form_data.update(file=file)
-
- response = self.client.post(self.url, self.form_data)
-
- self.assertEquals(response.status_code, 200)
-
- rules = CollectionRule.objects.all()
- self.assertEquals(len(rules), 0)
-
- self.assertFormError(response, "form", "file", _("Invalid OPML file"))
-
- def test_feeds_with_missing_attr(self):
- file_path = self._get_file_path("missing-feeds.opml")
-
- with open(file_path) as file:
- self.form_data.update(file=file)
-
- response = self.client.post(self.url, self.form_data)
-
- self.assertRedirects(response, reverse("rules"))
-
- rules = CollectionRule.objects.all()
- self.assertEquals(len(rules), 2)
diff --git a/src/newsreader/news/collection/tests/views/test_import_view.py b/src/newsreader/news/collection/tests/views/test_import_view.py
new file mode 100644
index 0000000..57ac502
--- /dev/null
+++ b/src/newsreader/news/collection/tests/views/test_import_view.py
@@ -0,0 +1,141 @@
+import os
+
+from django.conf import settings
+from django.test import TestCase
+from django.urls import reverse
+from django.utils.translation import gettext_lazy as _
+
+import pytz
+
+from newsreader.accounts.tests.factories import UserFactory
+from newsreader.news.collection.models import CollectionRule
+from newsreader.news.collection.tests.factories import CollectionRuleFactory
+from newsreader.news.core.tests.factories import CategoryFactory
+
+
+class OPMLImportTestCase(TestCase):
+ def setUp(self):
+ self.user = UserFactory(password="test")
+ self.client.force_login(self.user)
+
+ self.form_data = {"file": "", "skip_existing": False}
+ self.url = reverse("import")
+
+ def _get_file_path(self, name):
+ file_dir = os.path.join(settings.DJANGO_PROJECT_DIR, "utils", "tests", "files")
+ return os.path.join(file_dir, name)
+
+ def test_simple(self):
+ file_path = self._get_file_path("feeds.opml")
+
+ with open(file_path) as file:
+ self.form_data.update(file=file)
+
+ response = self.client.post(self.url, self.form_data)
+
+ self.assertRedirects(response, reverse("rules"))
+
+ rules = CollectionRule.objects.all()
+ self.assertEquals(len(rules), 4)
+
+ def test_existing_rules(self):
+ CollectionRuleFactory(url="http://www.engadget.com/rss-full.xml", user=self.user)
+ CollectionRuleFactory(url="https://news.ycombinator.com/rss", user=self.user)
+ CollectionRuleFactory(
+ url="http://feeds.feedburner.com/Techcrunch", user=self.user
+ )
+ CollectionRuleFactory(
+ url="http://feeds.feedburner.com/tweakers/nieuws", user=self.user
+ )
+
+ file_path = self._get_file_path("feeds.opml")
+
+ with open(file_path) as file:
+ self.form_data.update(file=file)
+
+ response = self.client.post(self.url, self.form_data)
+
+ self.assertRedirects(response, reverse("rules"))
+
+ rules = CollectionRule.objects.all()
+ self.assertEquals(len(rules), 8)
+
+ def test_skip_existing_rules(self):
+ CollectionRuleFactory(url="http://www.engadget.com/rss-full.xml", user=self.user)
+ CollectionRuleFactory(url="https://news.ycombinator.com/rss", user=self.user)
+ CollectionRuleFactory(
+ url="http://feeds.feedburner.com/Techcrunch", user=self.user
+ )
+ CollectionRuleFactory(
+ url="http://feeds.feedburner.com/tweakers/nieuws", user=self.user
+ )
+
+ file_path = self._get_file_path("feeds.opml")
+
+ with open(file_path) as file:
+ self.form_data.update(file=file, skip_existing=True)
+
+ response = self.client.post(self.url, self.form_data)
+
+ self.assertEquals(response.status_code, 200)
+
+ rules = CollectionRule.objects.all()
+ self.assertEquals(len(rules), 4)
+
+ def test_empty_feed_file(self):
+ file_path = self._get_file_path("empty-feeds.opml")
+
+ with open(file_path) as file:
+ self.form_data.update(file=file)
+
+ response = self.client.post(self.url, self.form_data)
+
+ self.assertEquals(response.status_code, 200)
+
+ rules = CollectionRule.objects.all()
+ self.assertEquals(len(rules), 0)
+
+ self.assertFormError(response, "form", "file", _("No (new) rules found"))
+
+ def test_invalid_feeds(self):
+ file_path = self._get_file_path("invalid-url-feeds.opml")
+
+ with open(file_path) as file:
+ self.form_data.update(file=file)
+
+ response = self.client.post(self.url, self.form_data)
+
+ self.assertEquals(response.status_code, 200)
+
+ rules = CollectionRule.objects.all()
+
+ self.assertEquals(len(rules), 0)
+ self.assertFormError(response, "form", "file", _("No (new) rules found"))
+
+ def test_invalid_file(self):
+ file_path = self._get_file_path("test.png")
+
+ with open(file_path, "rb") as file:
+ self.form_data.update(file=file)
+
+ response = self.client.post(self.url, self.form_data)
+
+ self.assertEquals(response.status_code, 200)
+
+ rules = CollectionRule.objects.all()
+ self.assertEquals(len(rules), 0)
+
+ self.assertFormError(response, "form", "file", _("Invalid OPML file"))
+
+ def test_feeds_with_missing_attr(self):
+ file_path = self._get_file_path("missing-feeds.opml")
+
+ with open(file_path) as file:
+ self.form_data.update(file=file)
+
+ response = self.client.post(self.url, self.form_data)
+
+ self.assertRedirects(response, reverse("rules"))
+
+ rules = CollectionRule.objects.all()
+ self.assertEquals(len(rules), 2)
diff --git a/src/newsreader/news/collection/urls.py b/src/newsreader/news/collection/urls.py
index 28b6f38..1ea17d6 100644
--- a/src/newsreader/news/collection/urls.py
+++ b/src/newsreader/news/collection/urls.py
@@ -8,6 +8,9 @@ from newsreader.news.collection.endpoints import (
RuleReadView,
)
from newsreader.news.collection.views import (
+ CollectionRuleBulkDeleteView,
+ CollectionRuleBulkDisableView,
+ CollectionRuleBulkEnableView,
CollectionRuleCreateView,
CollectionRuleListView,
CollectionRuleUpdateView,
@@ -34,5 +37,20 @@ urlpatterns = [
login_required(CollectionRuleCreateView.as_view()),
name="rule-create",
),
+ path(
+ "rules/delete/",
+ login_required(CollectionRuleBulkDeleteView.as_view()),
+ name="rules-delete",
+ ),
+ path(
+ "rules/enable/",
+ login_required(CollectionRuleBulkEnableView.as_view()),
+ name="rules-enable",
+ ),
+ path(
+ "rules/disable/",
+ login_required(CollectionRuleBulkDisableView.as_view()),
+ name="rules-disable",
+ ),
path("rules/import/", login_required(OPMLImportView.as_view()), name="import"),
]
diff --git a/src/newsreader/news/collection/views.py b/src/newsreader/news/collection/views.py
index 8d254e2..ca531fb 100644
--- a/src/newsreader/news/collection/views.py
+++ b/src/newsreader/news/collection/views.py
@@ -1,12 +1,17 @@
from django.contrib import messages
-from django.urls import reverse_lazy
+from django.shortcuts import redirect
+from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic.edit import CreateView, FormView, UpdateView
from django.views.generic.list import ListView
import pytz
-from newsreader.news.collection.forms import CollectionRuleForm, OPMLImportForm
+from newsreader.news.collection.forms import (
+ CollectionRuleBulkForm,
+ CollectionRuleForm,
+ OPMLImportForm,
+)
from newsreader.news.collection.models import CollectionRule
from newsreader.news.core.models import Category
from newsreader.utils.opml import parse_opml
@@ -17,7 +22,7 @@ class CollectionRuleViewMixin:
def get_queryset(self):
user = self.request.user
- return self.queryset.filter(user=user)
+ return self.queryset.filter(user=user).order_by("name")
class CollectionRuleDetailMixin:
@@ -42,6 +47,7 @@ class CollectionRuleDetailMixin:
class CollectionRuleListView(CollectionRuleViewMixin, ListView):
+ paginate_by = 50
template_name = "collection/rules.html"
context_object_name = "rules"
@@ -59,6 +65,60 @@ class CollectionRuleCreateView(
template_name = "collection/rule-create.html"
+class CollectionRuleBulkView(FormView):
+ form_class = CollectionRuleBulkForm
+
+ def get_redirect_url(self):
+ return reverse("rules")
+
+ def get_success_url(self):
+ return self.get_redirect_url()
+
+ def get_form(self, form_class=None):
+ if form_class is None:
+ form_class = self.get_form_class()
+ return form_class(self.request.user, **self.get_form_kwargs())
+
+ def form_invalid(self, form):
+ url = self.get_redirect_url()
+
+ messages.error(self.request, _("The form contains errors, try again later"))
+
+ return redirect(url)
+
+
+class CollectionRuleBulkEnableView(CollectionRuleBulkView):
+ def form_valid(self, form):
+ response = super().form_valid(form)
+
+ for rule in form.cleaned_data["rules"]:
+ rule.enabled = True
+ rule.save()
+
+ return response
+
+
+class CollectionRuleBulkDisableView(CollectionRuleBulkView):
+ def form_valid(self, form):
+ response = super().form_valid(form)
+
+ for rule in form.cleaned_data["rules"]:
+ rule.enabled = False
+ rule.save()
+
+ return response
+
+
+class CollectionRuleBulkDeleteView(CollectionRuleBulkView):
+ def form_valid(self, form):
+ response = super().form_valid(form)
+
+ for rule in form.cleaned_data["rules"]:
+ rule.delete()
+
+ return response
+
+
class OPMLImportView(FormView):
form_class = OPMLImportForm
success_url = reverse_lazy("rules")
diff --git a/src/newsreader/scss/components/form/_form.scss b/src/newsreader/scss/components/form/_form.scss
index 931fba9..5b97958 100644
--- a/src/newsreader/scss/components/form/_form.scss
+++ b/src/newsreader/scss/components/form/_form.scss
@@ -19,6 +19,14 @@
padding: 15px;
}
+ &__actions {
+ display: flex;
+ justify-content: space-between;
+
+ width: 50%;
+ padding: 15px;
+ }
+
&__title {
font-size: 18px;
}
diff --git a/src/newsreader/scss/components/form/_rules-form.scss b/src/newsreader/scss/components/form/_rules-form.scss
new file mode 100644
index 0000000..44d4765
--- /dev/null
+++ b/src/newsreader/scss/components/form/_rules-form.scss
@@ -0,0 +1,5 @@
+.rules-form {
+ @extend .form;
+
+ width: 90%;
+}
diff --git a/src/newsreader/scss/components/form/index.scss b/src/newsreader/scss/components/form/index.scss
index 2c70cdd..547da89 100644
--- a/src/newsreader/scss/components/form/index.scss
+++ b/src/newsreader/scss/components/form/index.scss
@@ -2,6 +2,7 @@
@import "category-form";
@import "rule-form";
+@import "rules-form";
@import "import-form";
@import "login-form";
diff --git a/src/newsreader/scss/components/index.scss b/src/newsreader/scss/components/index.scss
index 4bddb31..53e0f71 100644
--- a/src/newsreader/scss/components/index.scss
+++ b/src/newsreader/scss/components/index.scss
@@ -12,7 +12,9 @@
@import "section/index";
@import "errorlist/index";
@import "fieldset/index";
+@import "pagination/index";
@import "sidebar/index";
+@import "table/index";
@import "rules/index";
@import "category/index";
diff --git a/src/newsreader/scss/components/pagination/_pagination.scss b/src/newsreader/scss/components/pagination/_pagination.scss
new file mode 100644
index 0000000..d4ba4a9
--- /dev/null
+++ b/src/newsreader/scss/components/pagination/_pagination.scss
@@ -0,0 +1,18 @@
+@import "../../elements/button/mixins";
+
+.pagination {
+ display: flex;
+ justify-content: space-evenly;
+
+ &__previous, &__current, &__next {
+ display: flex;
+ justify-content: space-evenly;
+
+ width: 33%;
+ text-align: center;
+ }
+
+ &__current {
+ @include button-padding;
+ }
+}
diff --git a/src/newsreader/scss/components/pagination/index.scss b/src/newsreader/scss/components/pagination/index.scss
new file mode 100644
index 0000000..d92e61f
--- /dev/null
+++ b/src/newsreader/scss/components/pagination/index.scss
@@ -0,0 +1 @@
+@import "pagination";
diff --git a/src/newsreader/scss/components/table/_rules-table.scss b/src/newsreader/scss/components/table/_rules-table.scss
new file mode 100644
index 0000000..3eaf3b3
--- /dev/null
+++ b/src/newsreader/scss/components/table/_rules-table.scss
@@ -0,0 +1,38 @@
+.rules-table {
+ &__heading {
+ &--select {
+ width: 5%;
+ }
+
+ &--name {
+ width: 20%;
+ }
+
+ &--category {
+ width: 15%;
+ }
+
+ &--url {
+ width: 40%;
+ }
+
+ &--succeeded {
+ width: 15%;
+ }
+
+ &--enabled {
+ width: 10%;
+ }
+
+ &--link {
+ width: 5%;
+ }
+ }
+
+ & .link {
+ display: flex;
+ justify-content: center;
+
+ padding: 10px;
+ }
+}
diff --git a/src/newsreader/scss/components/table/_table.scss b/src/newsreader/scss/components/table/_table.scss
new file mode 100644
index 0000000..60ab7e8
--- /dev/null
+++ b/src/newsreader/scss/components/table/_table.scss
@@ -0,0 +1,32 @@
+@import "../../lib/mixins";
+
+.table {
+ @include rounded;
+
+ table-layout: fixed;
+ background-color: $white;
+ width: 90%;
+ padding: 20px;
+
+ text-align: left;
+ white-space: nowrap;
+
+ &__heading {
+ @extend .h1;
+ }
+
+ &__item {
+ padding: 10px 0;
+
+ border-bottom: 1px solid $border-gray;
+
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ &__footer {
+ width: 80%;
+ padding: 10px 0;
+ }
+}
diff --git a/src/newsreader/scss/components/table/index.scss b/src/newsreader/scss/components/table/index.scss
new file mode 100644
index 0000000..d175a21
--- /dev/null
+++ b/src/newsreader/scss/components/table/index.scss
@@ -0,0 +1,2 @@
+@import "table";
+@import "rules-table";
diff --git a/src/newsreader/scss/elements/button/_button.scss b/src/newsreader/scss/elements/button/_button.scss
index a6bec19..3a06cd3 100644
--- a/src/newsreader/scss/elements/button/_button.scss
+++ b/src/newsreader/scss/elements/button/_button.scss
@@ -1,10 +1,12 @@
+@import "mixins";
+
.button {
display: flex;
align-items: center;
justify-content: center;
- padding: 10px 50px;
+ @include button-padding;
border: none;
border-radius: 2px;
diff --git a/src/newsreader/scss/elements/button/_mixins.scss b/src/newsreader/scss/elements/button/_mixins.scss
new file mode 100644
index 0000000..06a912c
--- /dev/null
+++ b/src/newsreader/scss/elements/button/_mixins.scss
@@ -0,0 +1,3 @@
+@mixin button-padding {
+ padding: 10px 50px;
+}
diff --git a/src/newsreader/scss/elements/link/_link.scss b/src/newsreader/scss/elements/link/_link.scss
index 1843c0b..b485cb3 100644
--- a/src/newsreader/scss/elements/link/_link.scss
+++ b/src/newsreader/scss/elements/link/_link.scss
@@ -10,7 +10,3 @@
a {
@extend .link;
}
-
-.gg-link {
- color: initial;
-}
diff --git a/src/newsreader/scss/lib/_css.gg.scss b/src/newsreader/scss/lib/_css.gg.scss
index 389e533..e7096d5 100644
--- a/src/newsreader/scss/lib/_css.gg.scss
+++ b/src/newsreader/scss/lib/_css.gg.scss
@@ -1 +1,9 @@
@import "~css.gg/icons-scss/icons";
+
+.gg-link {
+ color: initial;
+}
+
+.gg-pen {
+ color: initial;
+}
diff --git a/src/newsreader/scss/lib/_mixins.scss b/src/newsreader/scss/lib/_mixins.scss
new file mode 100644
index 0000000..e2d28aa
--- /dev/null
+++ b/src/newsreader/scss/lib/_mixins.scss
@@ -0,0 +1,3 @@
+@mixin rounded {
+ border-radius: 5px;
+}
diff --git a/src/newsreader/scss/pages/index.scss b/src/newsreader/scss/pages/index.scss
index 872ac89..27f0bc6 100644
--- a/src/newsreader/scss/pages/index.scss
+++ b/src/newsreader/scss/pages/index.scss
@@ -8,5 +8,5 @@
@import "password-reset/index";
@import "register/index";
-@import "rules/index";
@import "rule/index";
+@import "rules/index";
diff --git a/src/newsreader/scss/pages/rules/index.scss b/src/newsreader/scss/pages/rules/index.scss
index 68b92cb..64f46b4 100644
--- a/src/newsreader/scss/pages/rules/index.scss
+++ b/src/newsreader/scss/pages/rules/index.scss
@@ -1,7 +1,5 @@
#rules--page {
- .list__item {
- & .link {
- margin: 0;
- }
+ & .table {
+ width: 100%;
}
}