platzky 1.2.0__tar.gz → 1.2.2__tar.gz

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 (48) hide show
  1. {platzky-1.2.0 → platzky-1.2.2}/PKG-INFO +1 -1
  2. {platzky-1.2.0 → platzky-1.2.2}/platzky/models.py +19 -9
  3. {platzky-1.2.0 → platzky-1.2.2}/platzky/seo/seo.py +3 -2
  4. platzky-1.2.2/platzky/static/styles.css +174 -0
  5. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/base.html +6 -7
  6. {platzky-1.2.0 → platzky-1.2.2}/pyproject.toml +1 -1
  7. platzky-1.2.0/platzky/static/styles.css +0 -60
  8. {platzky-1.2.0 → platzky-1.2.2}/LICENSE +0 -0
  9. {platzky-1.2.0 → platzky-1.2.2}/README.md +0 -0
  10. {platzky-1.2.0 → platzky-1.2.2}/platzky/__init__.py +0 -0
  11. {platzky-1.2.0 → platzky-1.2.2}/platzky/admin/admin.py +0 -0
  12. {platzky-1.2.0 → platzky-1.2.2}/platzky/admin/fake_login.py +0 -0
  13. {platzky-1.2.0 → platzky-1.2.2}/platzky/admin/templates/admin.html +0 -0
  14. {platzky-1.2.0 → platzky-1.2.2}/platzky/admin/templates/login.html +0 -0
  15. {platzky-1.2.0 → platzky-1.2.2}/platzky/admin/templates/module.html +0 -0
  16. {platzky-1.2.0 → platzky-1.2.2}/platzky/blog/__init__.py +0 -0
  17. {platzky-1.2.0 → platzky-1.2.2}/platzky/blog/blog.py +0 -0
  18. {platzky-1.2.0 → platzky-1.2.2}/platzky/blog/comment_form.py +0 -0
  19. {platzky-1.2.0 → platzky-1.2.2}/platzky/config.py +0 -0
  20. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/README.md +0 -0
  21. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/__init__.py +0 -0
  22. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/db.py +0 -0
  23. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/db_loader.py +0 -0
  24. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/github_json_db.py +0 -0
  25. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/google_json_db.py +0 -0
  26. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/graph_ql_db.py +0 -0
  27. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/json_db.py +0 -0
  28. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/json_file_db.py +0 -0
  29. {platzky-1.2.0 → platzky-1.2.2}/platzky/db/mongodb_db.py +0 -0
  30. {platzky-1.2.0 → platzky-1.2.2}/platzky/engine.py +0 -0
  31. {platzky-1.2.0 → platzky-1.2.2}/platzky/locale/en/LC_MESSAGES/messages.po +0 -0
  32. {platzky-1.2.0 → platzky-1.2.2}/platzky/locale/pl/LC_MESSAGES/messages.po +0 -0
  33. {platzky-1.2.0 → platzky-1.2.2}/platzky/platzky.py +0 -0
  34. {platzky-1.2.0 → platzky-1.2.2}/platzky/plugin/plugin.py +0 -0
  35. {platzky-1.2.0 → platzky-1.2.2}/platzky/plugin/plugin_loader.py +0 -0
  36. {platzky-1.2.0 → platzky-1.2.2}/platzky/static/blog.css +0 -0
  37. {platzky-1.2.0 → platzky-1.2.2}/platzky/telemetry.py +0 -0
  38. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/404.html +0 -0
  39. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/blog.html +0 -0
  40. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/body_meta.html +0 -0
  41. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/dynamic_css.html +0 -0
  42. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/feed.xml +0 -0
  43. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/head_meta.html +0 -0
  44. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/page.html +0 -0
  45. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/post.html +0 -0
  46. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/robots.txt +0 -0
  47. {platzky-1.2.0 → platzky-1.2.2}/platzky/templates/sitemap.xml +0 -0
  48. {platzky-1.2.0 → platzky-1.2.2}/platzky/www_handler.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: platzky
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: Not only blog engine
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -160,29 +160,32 @@ class Post(BaseModel):
160
160
  slug: URL-friendly unique identifier for the post
161
161
  title: Post title
162
162
  contentInMarkdown: Post content in Markdown format
163
- comments: List of comments on this post
164
163
  excerpt: Short summary or preview of the post
165
- tags: List of tags for categorization
166
- language: Language code for the post content
167
164
  coverImage: Cover image for the post
168
- date: Datetime when the post was published (timezone-aware recommended)
165
+ language: Language code for the post content (defaults to 'en')
166
+ comments: Optional list of comments on this post
167
+ tags: Optional list of tags for categorization
168
+ date: Optional datetime when the post was published (timezone-aware recommended)
169
169
  """
170
170
 
171
171
  author: str
172
172
  slug: str
173
173
  title: str
174
174
  contentInMarkdown: str
175
- comments: list[Comment]
176
175
  excerpt: str
177
- tags: list[str]
178
- language: str
179
- coverImage: Image
180
- date: DateTimeField
176
+ coverImage: Image = Field(default_factory=Image)
177
+ language: str = "en"
178
+ comments: list[Comment] = Field(default_factory=list)
179
+ tags: list[str] = Field(default_factory=list)
180
+ date: DateTimeField | None = None
181
181
 
182
182
  def __lt__(self, other: object) -> bool:
183
183
  """Compare posts by date for sorting.
184
184
 
185
185
  Uses datetime comparison to ensure robust and correct ordering.
186
+ Posts without dates are treated as "less than" dated posts, meaning they
187
+ appear last when using descending sort (reverse=True, newest-first) and
188
+ first when using ascending sort.
186
189
 
187
190
  Args:
188
191
  other: Another Post instance to compare against
@@ -192,6 +195,13 @@ class Post(BaseModel):
192
195
  or NotImplemented if comparing with a non-Post object
193
196
  """
194
197
  if isinstance(other, Post):
198
+ # Posts without dates are sorted last
199
+ if self.date is None and other.date is None:
200
+ return False
201
+ if self.date is None:
202
+ return True # None is "less than" any date (sorted last)
203
+ if other.date is None:
204
+ return False
195
205
  return self.date < other.date
196
206
  return NotImplemented
197
207
 
@@ -59,8 +59,9 @@ def create_seo_blueprint(
59
59
  # TODO: Add get_list_of_posts for faster getting just list of it
60
60
  for post in db.get_all_posts(lang):
61
61
  slug = post.slug
62
- datet = post.date.date().isoformat()
63
- url = {"loc": f"{host_base}{blog_prefix}/{slug}", "lastmod": datet}
62
+ url: dict[str, str] = {"loc": f"{host_base}{blog_prefix}/{slug}"}
63
+ if post.date is not None:
64
+ url["lastmod"] = post.date.date().isoformat()
64
65
  dynamic_urls.append(url)
65
66
  return dynamic_urls
66
67
 
@@ -0,0 +1,174 @@
1
+ html {
2
+ height: 100%;
3
+ overflow: hidden;
4
+ }
5
+
6
+ body {
7
+ height: 100%;
8
+ overflow: hidden;
9
+ }
10
+
11
+ /* Prevent page-level scrollbar */
12
+ .container-fluid {
13
+ overflow: hidden;
14
+ max-height: 100vh;
15
+ }
16
+
17
+ .logo {
18
+ max-height: 6rem;
19
+ max-width: 50vw;
20
+ }
21
+
22
+ #main-row {
23
+ position: relative;
24
+ flex-grow: 1;
25
+ z-index: 0;
26
+ overflow: hidden;
27
+ }
28
+
29
+ /* Main content area scrolling */
30
+ main {
31
+ overflow-y: auto;
32
+ min-height: 0;
33
+ }
34
+
35
+ /* Constrain left panel column to main-row height */
36
+ .col-auto.left-panel {
37
+ max-height: 100%;
38
+ overflow: hidden;
39
+ }
40
+
41
+ .left-panel-contents {
42
+ padding: 0 16px 16px 16px;
43
+ }
44
+
45
+ /* Panel body scrolling */
46
+ #left-panel .offcanvas-body {
47
+ padding-top: 0;
48
+ overflow-y: auto;
49
+ flex: 1;
50
+ min-height: 0;
51
+ scrollbar-width: thin;
52
+ scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
53
+ }
54
+
55
+ /* Panel header with close button - consistent spacing */
56
+ #left-panel .offcanvas-header {
57
+ padding: 8px 16px;
58
+ min-height: auto;
59
+ flex-shrink: 0;
60
+ }
61
+
62
+ /* Modern close button */
63
+ #left-panel .btn-close {
64
+ width: 32px;
65
+ height: 32px;
66
+ padding: 0;
67
+ background-color: rgba(255, 255, 255, 0.15);
68
+ border-radius: 50%;
69
+ opacity: 1;
70
+ transition: background-color 0.2s ease, transform 0.2s ease;
71
+ }
72
+
73
+ #left-panel .btn-close:hover {
74
+ background-color: rgba(255, 255, 255, 0.25);
75
+ transform: scale(1.05);
76
+ }
77
+
78
+ #left-panel .btn-close:focus {
79
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
80
+ }
81
+
82
+ /* Custom scrollbar for panel body (webkit) */
83
+ #left-panel .offcanvas-body::-webkit-scrollbar {
84
+ width: 6px;
85
+ }
86
+
87
+ #left-panel .offcanvas-body::-webkit-scrollbar-track {
88
+ background: transparent;
89
+ }
90
+
91
+ #left-panel .offcanvas-body::-webkit-scrollbar-thumb {
92
+ background-color: rgba(255, 255, 255, 0.3);
93
+ border-radius: 3px;
94
+ }
95
+
96
+ #left-panel .offcanvas-body::-webkit-scrollbar-thumb:hover {
97
+ background-color: rgba(255, 255, 255, 0.5);
98
+ }
99
+
100
+ /* Filter category groups */
101
+ #filter-form form > div {
102
+ margin-bottom: 20px;
103
+ padding-bottom: 0;
104
+ }
105
+
106
+ /* Filter category header container */
107
+ #filter-form form > div > div:first-child {
108
+ margin-bottom: 10px;
109
+ padding-bottom: 6px;
110
+ border-bottom: 1px solid rgba(255, 255, 255, 0.15);
111
+ }
112
+
113
+ /* Filter category title */
114
+ #filter-form form > div > div:first-child > span {
115
+ font-size: 0.75rem;
116
+ font-weight: 600;
117
+ text-transform: uppercase;
118
+ letter-spacing: 0.5px;
119
+ opacity: 0.85;
120
+ }
121
+
122
+ /* Filter checkbox labels */
123
+ #filter-form form > div > label {
124
+ display: flex;
125
+ align-items: center;
126
+ padding: 6px 8px;
127
+ margin: 0 -8px;
128
+ cursor: pointer;
129
+ transition: background-color 0.15s ease;
130
+ border-radius: 4px;
131
+ }
132
+
133
+ #filter-form form > div > label:hover {
134
+ background-color: rgba(255, 255, 255, 0.1);
135
+ }
136
+
137
+ @media only screen and (min-width: 992px) {
138
+ #left-panel {
139
+ position: relative;
140
+ inline-size: 220px;
141
+ max-width: 220px;
142
+ width: 220px;
143
+ display: flex;
144
+ flex-direction: column;
145
+ max-height: 100%;
146
+ }
147
+
148
+ /* Add some top padding on desktop to match mobile visual balance */
149
+ #left-panel .offcanvas-body {
150
+ padding-top: 8px;
151
+ }
152
+ }
153
+
154
+ .language-indicator-text {
155
+ color: white;
156
+ font-weight: normal;
157
+ }
158
+
159
+ .offcanvas-lg.offcanvas-start {
160
+ top: auto;
161
+ width: auto;
162
+ }
163
+
164
+ .dropdown-menu {
165
+ z-index: 1;
166
+ }
167
+
168
+ .btn {
169
+ padding: 0;
170
+ }
171
+
172
+ i.fi {
173
+ margin: 0 0.5em;
174
+ }
@@ -71,22 +71,21 @@
71
71
 
72
72
  <div class="row g-0" id="main-row">
73
73
  {% if self.left_panel() %}
74
- <div class="col-lg-2 left-panel" >
74
+ <div class="col-auto left-panel" >
75
75
  <div id="left-panel" class="left-panel offcanvas-lg offcanvas-start" aria-modal="true" role="dialog">
76
- <div class="offcanvas-body d-flex">
76
+ <div class="offcanvas-header d-lg-none justify-content-end">
77
+ <button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" data-bs-target="#left-panel" aria-label="{{ _('Close left panel') }}"></button>
78
+ </div>
79
+ <div class="offcanvas-body">
77
80
  <div class="left-panel-contents">
78
81
  {% block left_panel %}{% endblock %}
79
82
  </div>
80
- <div class="offcanvas-header justify-content-between align-items-start">
81
- <button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" data-bs-target="#left-panel" ></button>
82
- </div>
83
-
84
83
  </div>
85
84
  </div>
86
85
 
87
86
  </div>
88
87
  {% endif %}
89
- <div class="h-100 {% if self.left_panel() %} col-lg-10 {% else %} col-lg-12 {% endif %}">
88
+ <div class="h-100 {% if self.left_panel() %} col {% else %} col-lg-12 {% endif %}">
90
89
  <main class="h-100">
91
90
  {% block content %}{% endblock %}
92
91
  </main>
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "platzky"
3
- version = "1.2.0"
3
+ version = "1.2.2"
4
4
  description = "Not only blog engine"
5
5
  authors = []
6
6
  license = "MIT"
@@ -1,60 +0,0 @@
1
- html,
2
- body {
3
- height: 100%;
4
- }
5
-
6
- .logo {
7
- max-height: 6rem;
8
- max-width: 50vw;
9
- }
10
-
11
- #main-row {
12
- position: relative;
13
- flex-grow: 1;
14
- z-index: 0;
15
- }
16
-
17
- .left-panel-contents {
18
- padding: 16px;
19
- }
20
-
21
- @media only screen and (min-width: 768px) {
22
- #left-panel {
23
- inline-size: calc(100vw * 0.1666666667);
24
- }
25
- }
26
-
27
- .language-indicator-text {
28
- color: white;
29
- font-weight: normal;
30
- }
31
-
32
- .offcanvas-lg.offcanvas-start {
33
- top: auto;
34
- width: auto;
35
- }
36
-
37
- #filter-form form > div {
38
- padding-bottom: 1rem;
39
- }
40
-
41
- #filter-form form div > span {
42
- font-weight: bold;
43
- padding-bottom: 0.5rem;
44
- }
45
-
46
- .dropdown-menu {
47
- z-index: 1;
48
- }
49
-
50
- .btn {
51
- padding: 0;
52
- }
53
-
54
- .btn-close {
55
- opacity: 1;
56
- }
57
-
58
- i.fi {
59
- margin: 0 0.5em;
60
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes