wbnews 2.2.3__py2.py3-none-any.whl → 2.2.5__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {wbnews-2.2.3.dist-info → wbnews-2.2.5.dist-info}/METADATA +1 -1
  2. wbnews-2.2.5.dist-info/RECORD +3 -0
  3. wbnews/.coveragerc +0 -23
  4. wbnews/__init__.py +0 -1
  5. wbnews/admin.py +0 -27
  6. wbnews/apps.py +0 -9
  7. wbnews/factories.py +0 -33
  8. wbnews/import_export/__init__.py +0 -0
  9. wbnews/import_export/backends/__init__.py +0 -1
  10. wbnews/import_export/backends/news.py +0 -35
  11. wbnews/import_export/handlers/__init__.py +0 -1
  12. wbnews/import_export/handlers/news.py +0 -25
  13. wbnews/import_export/parsers/__init__.py +0 -0
  14. wbnews/import_export/parsers/emails/__init__.py +0 -0
  15. wbnews/import_export/parsers/emails/news.py +0 -48
  16. wbnews/import_export/parsers/emails/utils.py +0 -61
  17. wbnews/import_export/parsers/rss/__init__.py +0 -0
  18. wbnews/import_export/parsers/rss/news.py +0 -63
  19. wbnews/migrations/0001_initial_squashed_0005_alter_news_import_source.py +0 -349
  20. wbnews/migrations/0006_alter_news_language.py +0 -122
  21. wbnews/migrations/0007_auto_20240103_0955.py +0 -43
  22. wbnews/migrations/0008_alter_news_language.py +0 -123
  23. wbnews/migrations/0009_newsrelationship_analysis_newsrelationship_sentiment.py +0 -94
  24. wbnews/migrations/__init__.py +0 -0
  25. wbnews/models/__init__.py +0 -3
  26. wbnews/models/news.py +0 -116
  27. wbnews/models/relationships.py +0 -20
  28. wbnews/models/sources.py +0 -43
  29. wbnews/serializers.py +0 -83
  30. wbnews/signals.py +0 -4
  31. wbnews/tests/__init__.py +0 -0
  32. wbnews/tests/conftest.py +0 -6
  33. wbnews/tests/test_models.py +0 -15
  34. wbnews/tests/tests.py +0 -12
  35. wbnews/urls.py +0 -29
  36. wbnews/viewsets/__init__.py +0 -12
  37. wbnews/viewsets/buttons.py +0 -23
  38. wbnews/viewsets/display.py +0 -133
  39. wbnews/viewsets/endpoints.py +0 -18
  40. wbnews/viewsets/menu.py +0 -23
  41. wbnews/viewsets/titles.py +0 -39
  42. wbnews/viewsets/views.py +0 -140
  43. wbnews-2.2.3.dist-info/RECORD +0 -43
  44. {wbnews-2.2.3.dist-info → wbnews-2.2.5.dist-info}/WHEEL +0 -0
@@ -1,94 +0,0 @@
1
- # Generated by Django 5.0.9 on 2024-10-24 11:00
2
-
3
- import django.contrib.postgres.fields
4
- from django.db import migrations, models
5
-
6
-
7
- def migrate_new_source(apps, schema_editor):
8
- from wbcore.contrib.io.models import (
9
- DataBackend,
10
- ImportSource,
11
- ParserHandler,
12
- Source,
13
- )
14
-
15
- parser_handler = ParserHandler.objects.get(parser="wbnews.import_export.parsers.rss.news")
16
- io_news_sources = Source.objects.filter(parser_handler=parser_handler)
17
- crontab = io_news_sources.last().crontab
18
- data_backend = DataBackend.objects.get(backend_class_path="wbnews.import_export.backends.news")
19
- default_news_source, created = Source.objects.get_or_create(
20
- data_backend=data_backend,
21
- defaults={
22
- "crontab": crontab,
23
- "title": "RSS Feeds -> News",
24
- },
25
- )
26
- default_news_source.parser_handler.set([parser_handler])
27
- ImportSource.objects.filter(source__in=io_news_sources).update(source=default_news_source)
28
- io_news_sources.exclude(id=default_news_source.id).delete()
29
- NewsSource = apps.get_model("wbnews", "NewsSource")
30
- NewsSource.objects.filter(title__icontains="Email").update(type="EMAIL")
31
- NewsSource.objects.filter(type="RSS").filter(url__isnull=True, identifier__isnull=False).update(
32
- url=models.F("identifier")
33
- )
34
-
35
- unvalid_rss_feeds = [
36
- "https://www.dailytelegraph.com.au/help-rss",
37
- "https://techcrunch.com/rssfeeds/",
38
- "https://www.bbc.co.uk/news/",
39
- "https://www.nytimes.com/section/technology",
40
- "http://online.wsj.com/page/2_0006.html",
41
- "http://online.wsj.com",
42
- "https://www.bbc.co.uk/news/technology",
43
- "https://www.bbc.co.uk/news/world",
44
- "https://www.bbc.co.uk/news/business",
45
- "https://www.techworld.com/news/rss",
46
- ]
47
- NewsSource.objects.filter(url__in=unvalid_rss_feeds).update(is_active=False)
48
-
49
-
50
- class Migration(migrations.Migration):
51
- dependencies = [
52
- ("wbnews", "0008_alter_news_language"),
53
- ]
54
-
55
- operations = [
56
- migrations.AddField(
57
- model_name="newsrelationship",
58
- name="analysis",
59
- field=models.TextField(blank=True, null=True),
60
- ),
61
- migrations.AddField(
62
- model_name="newsrelationship",
63
- name="sentiment",
64
- field=models.PositiveIntegerField(blank=True, null=True),
65
- ),
66
- migrations.AddField(
67
- model_name="newssource",
68
- name="clean_content",
69
- field=models.BooleanField(default=False),
70
- ),
71
- migrations.AddField(
72
- model_name="newssource",
73
- name="is_active",
74
- field=models.BooleanField(default=True),
75
- ),
76
- migrations.AddField(
77
- model_name="newssource",
78
- name="type",
79
- field=models.CharField(choices=[("RSS", "RSS"), ("EMAIL", "EMAIL")], default="RSS", max_length=6),
80
- ),
81
- migrations.AlterField(
82
- model_name="newssource",
83
- name="description",
84
- field=models.TextField(blank=True, default=""),
85
- ),
86
- migrations.AlterField(
87
- model_name="newssource",
88
- name="tags",
89
- field=django.contrib.postgres.fields.ArrayField(
90
- base_field=models.CharField(max_length=16), blank=True, default=list, size=None
91
- ),
92
- ),
93
- migrations.RunPython(migrate_new_source),
94
- ]
File without changes
wbnews/models/__init__.py DELETED
@@ -1,3 +0,0 @@
1
- from .news import News
2
- from .relationships import NewsRelationship
3
- from .sources import NewsSource
wbnews/models/news.py DELETED
@@ -1,116 +0,0 @@
1
- from typing import Any
2
-
3
- from celery import chord, shared_task
4
- from celery.canvas import Signature
5
- from django.conf.global_settings import LANGUAGES
6
- from django.contrib.postgres.fields import ArrayField
7
- from django.db import models
8
- from django.db.models.signals import post_save
9
- from django.dispatch import receiver
10
- from django.utils.translation import gettext_lazy as _
11
- from wbcore.contrib.ai.llm.decorators import llm
12
- from wbcore.contrib.io.mixins import ImportMixin
13
- from wbcore.models import WBModel
14
- from wbnews.import_export.handlers.news import NewsImportHandler
15
- from wbnews.models.llm.cleaned_news import clean_news_config, summarized_news_config
16
- from wbnews.models.relationships import NewsRelationship
17
- from wbnews.models.sources import NewsSource
18
- from wbnews.signals import create_news_relationships
19
-
20
-
21
- @shared_task
22
- def create_relationship(chain_results: list[list[dict[str, Any]]], news_id: int):
23
- objs = []
24
- for relationships in chain_results:
25
- for relationship in relationships:
26
- objs.append(NewsRelationship(news_id=news_id, **relationship))
27
- NewsRelationship.objects.bulk_create(
28
- objs,
29
- ignore_conflicts=True,
30
- unique_fields=["content_type", "object_id", "news"],
31
- )
32
-
33
-
34
- @llm([clean_news_config, summarized_news_config])
35
- class News(ImportMixin, WBModel):
36
- errors = {
37
- "relationship_signal": "using the fetch_new_relationships signal must return a list of tuples, sender: {0} did not."
38
- }
39
- import_export_handler_class = NewsImportHandler
40
-
41
- datetime = models.DateTimeField(verbose_name=_("Datetime"))
42
- title = models.CharField(max_length=500, verbose_name=_("Title"))
43
- description = models.TextField(blank=True, verbose_name=_("Description"))
44
- summary = models.TextField(blank=True, verbose_name=_("Summary"))
45
- language = models.CharField(max_length=16, choices=LANGUAGES, blank=True, null=True, verbose_name=_("Language"))
46
- link = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("Link"))
47
- tags = ArrayField(models.CharField(max_length=16), default=list)
48
- enclosures = ArrayField(models.URLField(), default=list)
49
- source = models.ForeignKey(
50
- "wbnews.NewsSource", on_delete=models.CASCADE, related_name="news", verbose_name=_("Source")
51
- )
52
- image_url = models.URLField(blank=True, null=True)
53
-
54
- class Meta:
55
- unique_together = ["title", "source", "datetime"]
56
-
57
- def __str__(self) -> str:
58
- return f"{self.title} ({self.source.title})"
59
-
60
- def update_and_create_news_relationships(self, synchronous: bool = False):
61
- """
62
- This methods fires the signal to fetch the possible relationship to be linked to the news
63
- """
64
- tasks = []
65
- for sender, task_signature in create_news_relationships.send(sender=News, instance=self):
66
- assert isinstance(task_signature, Signature), self.errors["relationship_signal"].format(sender)
67
- tasks.append(task_signature)
68
- if tasks:
69
- res = chord(tasks, create_relationship.s(self.id))
70
- if synchronous:
71
- res.apply()
72
- else:
73
- res.apply_async()
74
-
75
- # TODO: Consider moving this into a get_or_create queryset method on NewsSource?
76
- @classmethod
77
- def source_dict_to_model(cls, data: dict) -> NewsSource:
78
- sources = NewsSource.objects
79
- if "id" in data:
80
- return sources.get(id=data["id"])
81
- if identifier := data.get("identifier"):
82
- sources = sources.filter(identifier=identifier)
83
- elif url := data.get("url"):
84
- sources = sources.filter(url=url)
85
- elif title := data.get("title"):
86
- sources = sources.filter(title=title)
87
- if sources.count() == 1:
88
- return sources.first()
89
- else:
90
- return NewsSource.objects.create(**data)
91
-
92
- @classmethod
93
- def get_representation_endpoint(cls) -> str:
94
- return "wbnews:news-list"
95
-
96
- @classmethod
97
- def get_representation_value_key(cls) -> str:
98
- return "id"
99
-
100
- @classmethod
101
- def get_representation_label_key(cls) -> str:
102
- return "{{title}} ({{datetime}})"
103
-
104
- @classmethod
105
- def get_endpoint_basename(cls) -> str:
106
- return "wbnews:news"
107
-
108
-
109
- @receiver(post_save, sender="wbnews.News")
110
- def post_save_create_news_relationships(sender: type, instance: "News", raw: bool, created: bool, **kwargs):
111
- """
112
- Post save to lazy create relationship between an instrument and a news upon creation
113
- """
114
-
115
- if not raw and created:
116
- instance.update_and_create_news_relationships()
@@ -1,20 +0,0 @@
1
- from django.contrib.contenttypes.fields import GenericForeignKey
2
- from django.contrib.contenttypes.models import ContentType
3
- from django.db import models
4
-
5
-
6
- class NewsRelationship(models.Model):
7
- news = models.ForeignKey(to="wbnews.News", related_name="relationships", on_delete=models.CASCADE)
8
- content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
9
- object_id = models.PositiveIntegerField()
10
- content_object = GenericForeignKey("content_type", "object_id")
11
-
12
- sentiment = models.PositiveIntegerField(null=True, blank=True)
13
- analysis = models.TextField(null=True, blank=True)
14
-
15
- def __str__(self) -> str:
16
- return f"{self.news.title} -> {self.content_object}"
17
-
18
- class Meta:
19
- verbose_name = "News Relationship"
20
- indexes = [models.Index(fields=["content_type", "object_id"])]
wbnews/models/sources.py DELETED
@@ -1,43 +0,0 @@
1
- from django.contrib.postgres.fields import ArrayField
2
- from django.db import models
3
- from wbcore.models import WBModel
4
-
5
-
6
- class NewsSource(WBModel):
7
- class Type(models.TextChoices):
8
- RSS = "RSS", "RSS"
9
- EMAIL = "EMAIL", "EMAIL"
10
-
11
- type = models.CharField(default=Type.RSS, choices=Type.choices, max_length=6)
12
- title = models.CharField(max_length=255)
13
- identifier = models.CharField(max_length=255, unique=True, blank=True, null=True)
14
- tags = ArrayField(models.CharField(max_length=16), default=list, blank=True)
15
- image = models.URLField(blank=True, null=True)
16
- description = models.TextField(default="", blank=True)
17
- author = models.CharField(max_length=255, default="")
18
- clean_content = models.BooleanField(default=False)
19
- url = models.URLField(
20
- blank=True,
21
- null=True,
22
- unique=True,
23
- )
24
- is_active = models.BooleanField(default=True)
25
-
26
- def __str__(self):
27
- return f"{self.title}"
28
-
29
- @classmethod
30
- def get_representation_endpoint(cls) -> str:
31
- return "wbnews:sourcerepresentation-list"
32
-
33
- @classmethod
34
- def get_representation_value_key(cls) -> str:
35
- return "id"
36
-
37
- @classmethod
38
- def get_representation_label_key(cls) -> str:
39
- return "{{title}}"
40
-
41
- @classmethod
42
- def get_endpoint_basename(cls) -> str:
43
- return "wbnews:source"
wbnews/serializers.py DELETED
@@ -1,83 +0,0 @@
1
- from django.utils.translation import gettext_lazy as _
2
- from rest_framework.reverse import reverse
3
- from wbcore import serializers as wb_serializers
4
-
5
- from .models import News, NewsSource
6
-
7
-
8
- class SourceRepresentationSerializer(wb_serializers.RepresentationSerializer):
9
- _detail = wb_serializers.HyperlinkField(reverse_name="wbnews:source-detail")
10
-
11
- class Meta:
12
- model = NewsSource
13
- fields = ("id", "title", "_detail")
14
-
15
-
16
- class SourceModelSerializer(wb_serializers.ModelSerializer):
17
- title = wb_serializers.CharField(read_only=True, label=_("Title"))
18
- identifier = wb_serializers.CharField(read_only=True, label=_("Identifier"))
19
- image = wb_serializers.CharField(read_only=True)
20
- description = wb_serializers.CharField(read_only=True, label=_("Description"))
21
- author = wb_serializers.CharField(read_only=True, label=_("Author"))
22
- updated = wb_serializers.DateTimeField(read_only=True, label=_("Updated"))
23
-
24
- @wb_serializers.register_resource()
25
- def news(self, instance, request, user):
26
- return {"news": reverse("wbnews:source-news-list", args=[instance.id], request=request)}
27
-
28
- class Meta:
29
- model = NewsSource
30
- fields = ("id", "title", "identifier", "image", "description", "author", "updated", "_additional_resources")
31
-
32
-
33
- class NewsRepresentationSerializer(wb_serializers.RepresentationSerializer):
34
- _detail = wb_serializers.HyperlinkField(reverse_name="wbnews:news-detail")
35
-
36
- class Meta:
37
- model = News
38
- fields = ("id", "datetime", "title", "_detail")
39
-
40
-
41
- class NewsModelSerializer(wb_serializers.ModelSerializer):
42
- _source = SourceRepresentationSerializer(source="source")
43
- image_url = wb_serializers.ImageURLField()
44
-
45
- @wb_serializers.register_resource()
46
- def open_link(self, instance, request, user):
47
- if instance.link:
48
- return {"open_link": instance.link}
49
- return {}
50
-
51
- # link = wb_serializers.URL()
52
- class Meta:
53
- model = News
54
- fields = (
55
- "id",
56
- "datetime",
57
- "title",
58
- "description",
59
- "summary",
60
- "link",
61
- "language",
62
- "image_url",
63
- "source",
64
- "_source",
65
- "_additional_resources",
66
- )
67
-
68
-
69
- class NewsRelationshipModelSerializer(wb_serializers.ModelSerializer):
70
- sentiment = wb_serializers.IntegerField(required=False)
71
- analysis = wb_serializers.TextField(required=False)
72
-
73
- class Meta:
74
- model = News
75
- fields = (
76
- "id",
77
- "datetime",
78
- "sentiment",
79
- "analysis",
80
- "title",
81
- "description",
82
- "summary",
83
- )
wbnews/signals.py DELETED
@@ -1,4 +0,0 @@
1
- from django.db.models.signals import ModelSignal
2
-
3
- # this signal is gather the news relationship to efficiently handle the insertion.
4
- create_news_relationships = ModelSignal(use_caching=False)
wbnews/tests/__init__.py DELETED
File without changes
wbnews/tests/conftest.py DELETED
@@ -1,6 +0,0 @@
1
- from pytest_factoryboy import register
2
- from wbcore.tests.conftest import *
3
- from wbnews.factories import NewsFactory, NewsSourceFactory
4
-
5
- register(NewsSourceFactory)
6
- register(NewsFactory)
@@ -1,15 +0,0 @@
1
- import pytest
2
-
3
-
4
- @pytest.mark.django_db
5
- class TestSource:
6
- @pytest.mark.parametrize("news_source__title", ["source1"])
7
- def test_str(self, news_source):
8
- assert str(news_source) == f"{news_source.title}"
9
-
10
-
11
- @pytest.mark.django_db
12
- class TestNews:
13
- @pytest.mark.parametrize("news__title", ["new1"])
14
- def test_str(self, news):
15
- assert str(news) == f"{news.title} ({news.source.title})"
wbnews/tests/tests.py DELETED
@@ -1,12 +0,0 @@
1
- import pytest
2
- from wbcore.test import GenerateTest, default_config
3
-
4
- config = {}
5
- for key, value in default_config.items():
6
- config[key] = list(filter(lambda x: x.__module__.startswith("wbnews"), value))
7
-
8
-
9
- @pytest.mark.django_db
10
- @GenerateTest(config)
11
- class TestProject:
12
- pass
wbnews/urls.py DELETED
@@ -1,29 +0,0 @@
1
- from django.urls import include, path
2
- from wbcore.routers import WBCoreRouter
3
- from wbnews.viewsets import views
4
-
5
- router = WBCoreRouter()
6
- router.register(r"newsrepresentation", views.NewsRepresentationViewSet, basename="newsrepresentation")
7
- router.register(r"newssourcerepresentation", views.SourceRepresentationViewSet, basename="sourcerepresentation")
8
- router.register(r"news", views.NewsModelViewSet, basename="news")
9
- router.register(r"newssource", views.SourceModelViewSet, basename="source")
10
- router.register(r"newsrelationship", views.NewsRelationshipModelViewSet, basename="newsrelationship")
11
-
12
-
13
- source_router = WBCoreRouter()
14
- source_router.register(r"news", views.NewsSourceModelViewSet, basename="source-news")
15
-
16
- urlpatterns = [
17
- path("", include(router.urls)),
18
- path("source/<int:source_id>/", include(source_router.urls)),
19
- path(
20
- "contentnews/<int:content_type>/<int:content_id>/",
21
- views.NewsModelViewSet.as_view({"get": "list"}),
22
- name="news_content_object",
23
- ),
24
- path(
25
- "contentnewsrelationship/<int:content_type>/<int:content_id>/",
26
- views.NewsRelationshipModelViewSet.as_view({"get": "list"}),
27
- name="news_relationship_content_object",
28
- ),
29
- ]
@@ -1,12 +0,0 @@
1
- from .buttons import NewsButtonConfig
2
- from .display import NewsDisplayConfig, NewsSourceDisplayConfig, SourceDisplayConfig
3
- from .endpoints import NewsEndpointConfig, NewsSourceEndpointConfig
4
- from .menu import NEWS_MENUITEM, NEWSSOURCE_MENUITEM
5
- from .titles import NewsSourceModelTitleConfig, NewsTitleConfig, SourceModelTitleConfig
6
- from .views import (
7
- NewsModelViewSet,
8
- NewsRepresentationViewSet,
9
- SourceModelViewSet,
10
- SourceRepresentationViewSet,
11
- NewsRelationshipModelViewSet,
12
- )
@@ -1,23 +0,0 @@
1
- from django.dispatch import receiver
2
- from django.utils.translation import gettext as _
3
- from rest_framework.reverse import reverse
4
- from wbcore.contrib.icons import WBIcon
5
- from wbcore.metadata.configs import buttons as bt
6
- from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
7
- from wbcore.signals.instance_buttons import add_extra_button
8
-
9
-
10
- class NewsButtonConfig(ButtonViewConfig):
11
- def get_custom_list_instance_buttons(self):
12
- return {bt.HyperlinkButton(key="open_link", label=_("Open News"), icon=WBIcon.LINK.icon)}
13
-
14
- def get_custom_instance_buttons(self):
15
- return self.get_custom_list_instance_buttons()
16
-
17
-
18
- @receiver(add_extra_button)
19
- def add_new_extra_button(sender, instance, request, view, pk=None, **kwargs):
20
- if instance and pk and view:
21
- content_type = view.get_content_type()
22
- endpoint = reverse("wbnews:news_relationship_content_object", args=[content_type.id, pk], request=request)
23
- return bt.WidgetButton(endpoint=endpoint, label="News", icon=WBIcon.NEWSPAPER.icon)
@@ -1,133 +0,0 @@
1
- from typing import Optional
2
-
3
- from django.utils.translation import gettext as _
4
- from wbcore.metadata.configs import display as dp
5
- from wbcore.metadata.configs.display.instance_display.shortcuts import (
6
- Display,
7
- create_simple_display,
8
- create_simple_section,
9
- )
10
- from wbcore.metadata.configs.display.instance_display.utils import repeat_field
11
- from wbcore.metadata.configs.display.view_config import DisplayViewConfig
12
-
13
-
14
- class SourceDisplayConfig(DisplayViewConfig):
15
- def get_list_display(self) -> Optional[dp.ListDisplay]:
16
- return dp.ListDisplay(
17
- fields=[
18
- dp.Field(key="title", label=_("Title")),
19
- dp.Field(key="identifier", label=_("RSS feed")),
20
- dp.Field(key="author", label=_("Author")),
21
- dp.Field(key="description", label=_("Description")),
22
- dp.Field(key="updated", label=_("Last Update")),
23
- ]
24
- )
25
-
26
- def get_instance_display(self) -> Display:
27
- return create_simple_display(
28
- [
29
- ["title", "identifier"],
30
- ["author", "updated"],
31
- [repeat_field(2, "description")],
32
- [repeat_field(2, "news_section")],
33
- ],
34
- [create_simple_section("news_section", "News", [["news"]], "news", collapsed=False)],
35
- )
36
-
37
-
38
- class NewsDisplayConfig(DisplayViewConfig):
39
- def get_instance_display(self) -> Display:
40
- return create_simple_display(
41
- [
42
- ["datetime", "source"],
43
- ["language", "link"],
44
- [repeat_field(2, "summary")],
45
- [repeat_field(2, "description")],
46
- ]
47
- )
48
-
49
- def get_list_display(self) -> Optional[dp.ListDisplay]:
50
- return dp.ListDisplay(
51
- fields=[
52
- dp.Field(key="datetime", label=_("Datetime")),
53
- dp.Field(key="title", label=_("Title")),
54
- dp.Field(key="summary", label=_("Summary")),
55
- dp.Field(key="description", label=_("Description")),
56
- # dp.Field(key="tags", label=_("Edited")),
57
- dp.Field(key="source", label=_("Source")),
58
- dp.Field(key="language", label=_("Language")),
59
- dp.Field(key="image_url", label=_("Image")),
60
- ]
61
- )
62
-
63
-
64
- class NewsRelationshipDisplayConfig(DisplayViewConfig):
65
- def get_instance_display(self) -> Display:
66
- return create_simple_display(
67
- [
68
- ["datetime", "source"],
69
- ["language", "link"],
70
- [repeat_field(2, "summary")],
71
- [repeat_field(2, "description")],
72
- ]
73
- )
74
-
75
- def get_list_display(self) -> Optional[dp.ListDisplay]:
76
- POSITIVE = "#96DD99"
77
- SLIGHTLY_POSITIVE = "#FFEE8C"
78
- SLIGHTLY_NEGATIVE = "#FF964F"
79
- NEGATIVE = "#FF6961"
80
-
81
- return dp.ListDisplay(
82
- fields=[
83
- dp.Field(key="datetime", label=_("Datetime")),
84
- dp.Field(key="analysis", label=_("Analysis")),
85
- dp.Field(key="title", label=_("Title")),
86
- dp.Field(key="summary", label=_("Summary")),
87
- dp.Field(key="description", label=_("Description")),
88
- ],
89
- formatting=[
90
- dp.Formatting(
91
- column="sentiment",
92
- formatting_rules=[
93
- dp.FormattingRule(condition=("==", 4), style={"backgroundColor": POSITIVE}),
94
- dp.FormattingRule(condition=("==", 3), style={"backgroundColor": SLIGHTLY_POSITIVE}),
95
- dp.FormattingRule(condition=("==", 2), style={"backgroundColor": SLIGHTLY_NEGATIVE}),
96
- dp.FormattingRule(condition=("==", 1), style={"backgroundColor": NEGATIVE}),
97
- ],
98
- )
99
- ],
100
- legends=[
101
- dp.Legend(
102
- items=[
103
- dp.LegendItem(icon=POSITIVE, label=_("Positive")),
104
- dp.LegendItem(icon=SLIGHTLY_POSITIVE, label=_("Slightly Positive")),
105
- dp.LegendItem(icon=SLIGHTLY_NEGATIVE, label=_("Slightly Negative")),
106
- dp.LegendItem(icon=NEGATIVE, label=_("Negative")),
107
- ]
108
- )
109
- ],
110
- )
111
-
112
-
113
- class NewsSourceDisplayConfig(DisplayViewConfig):
114
- def get_instance_display(self) -> Display:
115
- return create_simple_display(
116
- [
117
- [repeat_field(2, "title")],
118
- ["datetime", "language", "link"],
119
- [repeat_field(2, "description")],
120
- ]
121
- )
122
-
123
- def get_list_display(self) -> Optional[dp.ListDisplay]:
124
- return dp.ListDisplay(
125
- fields=[
126
- dp.Field(key="datetime", label=_("Datetime")),
127
- dp.Field(key="title", label=_("Title")),
128
- dp.Field(key="description", label=_("Description")),
129
- dp.Field(key="language", label=_("Language")),
130
- # dp.Field(key="tags", label="_(Edited")),
131
- # dp.Field(key="link", label="_(Link"))
132
- ]
133
- )
@@ -1,18 +0,0 @@
1
- from rest_framework.reverse import reverse
2
- from wbcore.metadata.configs.endpoints import EndpointViewConfig
3
-
4
-
5
- class NewsEndpointConfig(EndpointViewConfig):
6
- def get_endpoint(self, **kwargs):
7
- return None
8
-
9
- def get_list_endpoint(self, **kwargs):
10
- return reverse("wbnews:news-list", request=self.request)
11
-
12
- def get_instance_endpoint(self, **kwargs):
13
- return self.get_list_endpoint()
14
-
15
-
16
- class NewsSourceEndpointConfig(NewsEndpointConfig):
17
- def get_list_endpoint(self, **kwargs):
18
- return reverse("wbnews:source-news-list", args=[self.view.kwargs["source_id"]], request=self.request)
wbnews/viewsets/menu.py DELETED
@@ -1,23 +0,0 @@
1
- from django.utils.translation import gettext_lazy as _
2
- from wbcore.menus import ItemPermission, MenuItem
3
- from wbcore.permissions.shortcuts import is_internal_user
4
-
5
- NEWS_MENUITEM = MenuItem(
6
- label=_("News"),
7
- endpoint="wbnews:news-list",
8
- permission=ItemPermission(permissions=["wbnews.view_news"]),
9
- )
10
- NEWSSOURCE_MENUITEM = MenuItem(
11
- label=_("Sources"),
12
- endpoint="wbnews:source-list",
13
- permission=ItemPermission(
14
- method=lambda request: is_internal_user(request.user), permissions=["wbnews.view_newssource"]
15
- ),
16
- add=MenuItem(
17
- label=_("Create Source"),
18
- endpoint="wbnews:source-list",
19
- permission=ItemPermission(
20
- method=lambda request: is_internal_user(request.user), permissions=["wbnews.add_newssource"]
21
- ),
22
- ),
23
- )