mirror of
https://github.com/aquatix/digimarks.git
synced 2025-12-06 22:05:09 +01:00
Compare commits
280 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4225829e3 | |||
| f3dff354fc | |||
| ca71fa66df | |||
| 09ab5acf76 | |||
| e90d35238a | |||
| 3092f83c8b | |||
| a27787e956 | |||
| 21800911db | |||
| 20a3d9f838 | |||
| 0ab3bd2263 | |||
| 32b074b859 | |||
| 5789bbe006 | |||
| 2ef7358ac7 | |||
| d1e590390c | |||
| 7a1bc11004 | |||
| 315c664fcc | |||
| db5944cec4 | |||
|
|
becb734d17 | ||
| 64ee0856c5 | |||
|
|
6c2be3070e | ||
| 426c2eda68 | |||
| b0e53d4a85 | |||
| 1f69d9e53f | |||
|
|
fc27d9f186 | ||
|
|
6341b384bf | ||
| f698ebfe18 | |||
| 9f736ffe82 | |||
| e1a45a21b5 | |||
| 9492d26511 | |||
| f7762ebc7b | |||
| 1c4bc61494 | |||
| 2a87e0aa1f | |||
| 0a24c7d170 | |||
| 2615089acd | |||
| 14bf22f3e5 | |||
| e55fb7bd5f | |||
| 4e1261857d | |||
| f9861c1491 | |||
| 836077ad12 | |||
| 0913ffca2c | |||
| 834f95c34b | |||
| c82e3a02d4 | |||
| 7874002fef | |||
| 6db0355cc7 | |||
|
|
0495296f0f | ||
|
|
a5d225fb56 | ||
| f6401a3e9f | |||
| 46e7fc9899 | |||
| f6befd0700 | |||
| 95ff9c01ca | |||
| b36cd8db6b | |||
| 2b19b770dc | |||
| 6dc74c7102 | |||
| ac7906d781 | |||
| 5d2329ff90 | |||
| a29e14b7a7 | |||
| 5e4a35527b | |||
| 55609aa353 | |||
| 0d86c2608a | |||
| dd1e3a19ff | |||
| 9694ca566b | |||
| 17caef1aed | |||
| 52a01794f6 | |||
| 8148a79d28 | |||
| d6e74ff328 | |||
| 540fd6ba91 | |||
| 3becf27b42 | |||
| fe990ecf63 | |||
| 75080579fd | |||
| 94eb42a882 | |||
| d501c6b4db | |||
| 11e159db8d | |||
| 6516c4af1d | |||
| 63636d3355 | |||
| 52cc93d4c3 | |||
| 6f9d44ce86 | |||
| 718b39a267 | |||
| bfc4fb702a | |||
| 7e2f2f6f6e | |||
| 29c8c875be | |||
| 0f0caed748 | |||
| 971590196e | |||
| 3653b5e424 | |||
| 330523ba3f | |||
| 199b641a38 | |||
| c0c8e35246 | |||
| 6de9ba2642 | |||
| e48f2c98c3 | |||
| 554f651ec8 | |||
| 6def8d60a5 | |||
| 1d531989bb | |||
| fc2712f5e3 | |||
| 76ef520815 | |||
| ea4a7bdcd7 | |||
| aee0515eae | |||
| 3835497918 | |||
| d7b2c28c96 | |||
| fac3a4f747 | |||
| 0548f35b39 | |||
| 8372d6e2a5 | |||
| cd2911e7f0 | |||
| 127d99b1e0 | |||
| bb4f81262e | |||
| 3c697d3162 | |||
| fefb317ddf | |||
| 37ebdda933 | |||
| 3516fbfbb2 | |||
| c4f921ac68 | |||
| fec54c51f7 | |||
| 9f467f8a09 | |||
| cac31e40c9 | |||
| 1e14163d42 | |||
| 88eee28b88 | |||
| 45c95f5f17 | |||
| 9539c48b7b | |||
| 46aa230fae | |||
| c6089f1caa | |||
| 45d44d3bdf | |||
| e4662351c2 | |||
| 62f3ddf654 | |||
| 072ec6c426 | |||
| 5055947351 | |||
| 5f131b15ef | |||
| bd808a9e1d | |||
| 3b019e4368 | |||
| 3af1239326 | |||
| e8ea948566 | |||
| 1c2090f300 | |||
| cdfd0341f0 | |||
| 01d6525861 | |||
| c70e53a658 | |||
| dc76a592e0 | |||
| a4aae2d6c4 | |||
| 389e63bdbb | |||
| 6ba4803ed2 | |||
| 71756f9ea0 | |||
| 67635c199a | |||
| 7b2a861652 | |||
| 53887c8ece | |||
| 2cc2d382c1 | |||
| fa033452f1 | |||
| c14e24430b | |||
| cca4504fd7 | |||
| 7f6dc3f3df | |||
| 4170a7818b | |||
|
|
48e77f551d | ||
| e35d9952bd | |||
| 6933357a61 | |||
| 9578ee624b | |||
| ded047d749 | |||
| 57226b88f5 | |||
| de5d4d30ef | |||
| 60f5a48d89 | |||
| 47f6e36e4b | |||
| 5402dfc320 | |||
| 90f1322c48 | |||
| d1aef0284f | |||
| d7a5bd921f | |||
| b85ee43cc7 | |||
| 8077499eae | |||
| ab06f7e583 | |||
| f309d4acf2 | |||
| 88a9806d44 | |||
| 6f4d270858 | |||
| c354613b60 | |||
| 383c77ee8b | |||
| 0e77afd000 | |||
| f617fb8190 | |||
| 34af0e9ab7 | |||
| 7f866658e3 | |||
| abf9141019 | |||
|
|
8ca54bf364 | ||
| 0be05d07e9 | |||
| a66360a0e3 | |||
| 1545c17472 | |||
| dd0a9d8283 | |||
| 652e3a89af | |||
| 133a139b79 | |||
| b556978640 | |||
| 8bb9e11088 | |||
| 85e94b71e5 | |||
| a895774001 | |||
| 7598ba6a61 | |||
| c5dcf579d3 | |||
| 590095659e | |||
| d5d71b4f51 | |||
| 7f2da49d26 | |||
| 0f0e4e03c3 | |||
| 044f507aa2 | |||
| b0da3a4454 | |||
| 17e1db12bf | |||
| 480f27797f | |||
| 1729ecd540 | |||
| d54b26dafb | |||
| 2c76ffaf12 | |||
| e54a033984 | |||
| 4e0d89c25e | |||
| 30e4f74ed9 | |||
| 1beadb676c | |||
| eea63398ba | |||
| d5021fd7c4 | |||
| c03d0c2458 | |||
| ff08ea4930 | |||
| 2e9457ee1a | |||
| 63dd636c25 | |||
| 412b4a93c7 | |||
| abdc11361a | |||
|
|
7a98de4b3f | ||
|
|
59f5365edc | ||
|
|
b0aedcd6e4 | ||
| 6b61e43c5d | |||
| edc1a86b75 | |||
|
|
570af2d62e | ||
|
|
8a19df2741 | ||
|
|
9e6d67a0ff | ||
| 698a417bac | |||
| 4cdea81f16 | |||
| 0e659a4f16 | |||
| 2cdb0ebccb | |||
| 9e2bdac9ee | |||
| 5288c9fe9c | |||
| 0e60f8f3cb | |||
| 5fd8db8f43 | |||
| 0894770f12 | |||
| 197cb776bf | |||
| c433c2c1e8 | |||
| b5d1377109 | |||
| 85d4466de5 | |||
| 7609becf00 | |||
| a6d6ce5c13 | |||
| e448f69f38 | |||
| 17c36ab8fe | |||
| 9a15a9946c | |||
| 40b7937876 | |||
| 38155cafaa | |||
| b12974fc31 | |||
| d39d793460 | |||
| 7c24057d35 | |||
| 5fde397c4a | |||
| 62117699f8 | |||
| 14052148f7 | |||
| fe44928816 | |||
| e5c3824034 | |||
| d8850d33f4 | |||
| 2117c451b2 | |||
| 9abc17d517 | |||
| 978c34fcf3 | |||
| 7fdc0706bf | |||
| c460f713ca | |||
| 2de7472e27 | |||
| a6082caf0d | |||
| ac0ac849cb | |||
| 390cc0137a | |||
| 2e031db2a7 | |||
| 1b513e98b2 | |||
| bb258a2a68 | |||
| 72ad3c0d04 | |||
| 78bed962d0 | |||
| c70ac6d781 | |||
| 53b96adc79 | |||
| 4e86faf2aa | |||
| 4b17721fb0 | |||
| 870418712f | |||
| 068c6b8d94 | |||
| 60734c55ce | |||
| e5c5e5f5a9 | |||
| 16ed20bd9b | |||
| 5840baa657 | |||
| 0271a9339d | |||
| 8a28d841e3 | |||
| 04447390fc | |||
| 4ee925de45 | |||
| 271f2fa4a0 | |||
| cfbab3f98b | |||
| 62145ecfe2 | |||
| 42e4021ef5 | |||
| e7125c07e9 | |||
| bcc28c6a8e | |||
| fab1554c70 | |||
| 05d636fc08 |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -87,3 +87,13 @@ ENV/
|
|||||||
|
|
||||||
# Rope project settings
|
# Rope project settings
|
||||||
.ropeproject
|
.ropeproject
|
||||||
|
|
||||||
|
# vim
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# digimarks
|
||||||
|
static/favicons
|
||||||
|
tags
|
||||||
|
*.db_*
|
||||||
|
*.db
|
||||||
|
settings.py
|
||||||
|
|||||||
119
CHANGELOG.md
119
CHANGELOG.md
@@ -1,18 +1,125 @@
|
|||||||
|
# Changelog
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- Sorting of bookmarks
|
- Sorting of bookmarks
|
||||||
- Sort by title
|
- Sort by title
|
||||||
- Sort by date
|
- Sort by date
|
||||||
- Logging of actions
|
- Logging of actions
|
||||||
- json/rss views of public tag pages
|
- Add new way of authentication and editing bookmark collections:
|
||||||
|
https://github.com/aquatix/digimarks/issues/8 and https://github.com/aquatix/digimarks/issues/9
|
||||||
|
- Change adding tags to use the MaterializeCSS tags: https://materializecss.com/chips.html
|
||||||
|
- Do calls to the API endpoint of an existing bookmark when editing properties
|
||||||
|
(for example to update tags, title and such, also to already suggest title)
|
||||||
|
- Look into compatibility with del.icio.us, so we can make use of existing browser integration
|
||||||
|
- Add unit tests
|
||||||
|
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- 'lightblue' theme
|
||||||
|
- 'black amoled' theme
|
||||||
|
- Python 3 compatibility (tested with Python 3.5 and 3.6)
|
||||||
|
- Accept 'HTTP 202' responses as 'OK'
|
||||||
|
- API: Added endpoint for 'bookmarks', returning JSON
|
||||||
|
- Top navigation items now have icons too, like the sidebar in mobile view
|
||||||
|
- Download favicons from RealFaviconGenerator: https://realfavicongenerator.net/api/download_website_favicon
|
||||||
|
- Added `/<systemkey>/findmissingfavicons` endpoint to fill in the blanks in the favicon collection
|
||||||
|
- Added fallback favicon image (semitransparent digimarks 'M' logo) for bookmarks without a favicon. No more broken images.
|
||||||
|
- Added theme support for buttons.
|
||||||
|
- Autocompletion in bookmark search field
|
||||||
|
- API: search endpoint
|
||||||
|
- Redirect endpoint for a bookmark, de-referring to its url (`/r/<userkey>/<urlhash>`)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Fixed theming of browser chrome in mobile browsers
|
||||||
|
- Changed link colour of 'dark' theme from blue to orange
|
||||||
|
- Modified card padding so it fits more content
|
||||||
|
- Fixed ability to select a checkbox in the add/edit bookmark form
|
||||||
|
- Made the 404 page theme aware, falls back to default (green) theme
|
||||||
|
- Fixed admin pages not working anymore due to `settings` object name clash
|
||||||
|
- On Add/Edit bookmark and encountering a 301, show a better message about automatically changing the URL with the provided button
|
||||||
|
- Switched to 1.0 (alpha 4) version of MaterializeCSS
|
||||||
|
- jQuery-b-gone: changed all jQuery code to regular JavaScript code/MaterializeCSS framework
|
||||||
|
- Fixed colour of filter text in search field for dark themes
|
||||||
|
- Unified rendering of 'private' and 'public' views of bookmark cards
|
||||||
|
- Code cleanups, readability fixes
|
||||||
|
- digimarks User Agent string to correctly identify ourselves, also preventing servers blocking 'bots'
|
||||||
|
- Text search now also finds matches in the 'note' and 'url' of a bookmark, aside from its title
|
||||||
|
- Main navigation items ('tags' and 'add bookmark') are now buttons, better visible as action items.
|
||||||
|
- Removed item limit for feeds
|
||||||
|
- Form fields are now themed
|
||||||
|
- Disabled browser autocomplete for forms, which generally interfered with editing bookmarks (e.g., tag field) and the search field,
|
||||||
|
which has its own autocomplete now
|
||||||
|
- Changed default theme to the 'freshgreen' variant
|
||||||
|
- Links are now themed in the proper colours everywhere
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Removed dependency on jQuery
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.0] - 2017-07-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Show 404 page if bookmark is not found when editing
|
||||||
|
- Cache buster to force loading of the latest styling
|
||||||
|
- Theming support, default is 'green'
|
||||||
|
- Themes need an extra `theme` field in the User table
|
||||||
|
- Added 'freshgreen' and 'dark' themes
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Make running in a virtualenv optional
|
||||||
|
- Fix for misalignment and size of hamburger icon
|
||||||
|
- Updated Python (pip) dependencies
|
||||||
|
- Updated MaterializeCSS and jQuery
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Removed dependency on more_itertools
|
||||||
|
- Removed dependency on utilkit
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.0] - 2016-12-29
|
||||||
|
|
||||||
|
- json view of public tag pages, returns all items
|
||||||
|
- feed (rss/atom) view of public tag pages, returns latest 15
|
||||||
|
- feed link on public tag page
|
||||||
|
- Support for bookmarklets
|
||||||
|
- UI tweaks
|
||||||
|
- Redesigned cards with bigger favicon. Looks cleaner
|
||||||
|
- Different favicon service with 60x60px icons
|
||||||
|
- Prevent duplicate form submission on add/edit bookmark
|
||||||
|
- Delete bookmark from bookmark card
|
||||||
|
- Undo delete link in "Bookmark has been deleted" message
|
||||||
|
- Delete public tag page
|
||||||
- On tags overview page:
|
- On tags overview page:
|
||||||
- Show which tags have public pages, with link
|
- Show which tags have public pages, with link
|
||||||
- How many bookmarks each tag has
|
- How many bookmarks each tag has
|
||||||
|
- Statistics on:
|
||||||
|
- total tags
|
||||||
|
- number of public tag pages
|
||||||
|
- total number of bookmarks
|
||||||
|
- number of starred bookmarks
|
||||||
|
- number of bookmarks with a non-OK http status
|
||||||
|
- number of deleted bookmarks
|
||||||
|
- Filter on 'star' status, 'broken' status (non-http-200-OK)
|
||||||
|
- Bookmark can have a note now
|
||||||
|
- Note icon on card with text in title (desktop browser)
|
||||||
|
- Filter on bookmarks with a note
|
||||||
|
- Show url domain name along with 'no title' for items without title
|
||||||
|
- Catch connection timeouts and such
|
||||||
|
- Open in new tab/window, prevent
|
||||||
|
http://davidebove.com/blog/2016/05/05/target_blank-the-vulnerability-in-your-browser/
|
||||||
|
- Put the tag selection in a collapsible element to prevent clutter in edit window
|
||||||
|
- Updated MaterializeCSS and jQuery
|
||||||
|
|
||||||
|
|
||||||
## v0.2.0
|
## [0.2.0] - 2016-08-02
|
||||||
|
|
||||||
2016-08-02
|
|
||||||
|
|
||||||
- Favicon courtesy Freepik on flaticon.com
|
- Favicon courtesy Freepik on flaticon.com
|
||||||
- Tag tags for easy adding of tags
|
- Tag tags for easy adding of tags
|
||||||
@@ -23,9 +130,7 @@
|
|||||||
- Option to strip parameters from url (like '?utm_source=social')
|
- Option to strip parameters from url (like '?utm_source=social')
|
||||||
|
|
||||||
|
|
||||||
## v0.1.0
|
## [0.1.0] - 2016-07-26
|
||||||
|
|
||||||
2016-07-26
|
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
- Flask application with functionality to add users, add and edit bookmarks,
|
- Flask application with functionality to add users, add and edit bookmarks,
|
||||||
|
|||||||
19
README.rst
19
README.rst
@@ -1,7 +1,7 @@
|
|||||||
digimarks
|
digimarks
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|PyPI version| |PyPI downloads| |PyPI license| |Code health|
|
|PyPI version| |PyPI license| |Code health| |Codacy|
|
||||||
|
|
||||||
Simple bookmarking service, using a SQLite database to store bookmarks, supporting tags and automatic title fetching.
|
Simple bookmarking service, using a SQLite database to store bookmarks, supporting tags and automatic title fetching.
|
||||||
|
|
||||||
@@ -39,12 +39,24 @@ Usage / example configuration
|
|||||||
Copy ``settings.py`` from example_config to the parent directory and
|
Copy ``settings.py`` from example_config to the parent directory and
|
||||||
configure to your needs (*at the least* change the value of `SYSTEMKEY`).
|
configure to your needs (*at the least* change the value of `SYSTEMKEY`).
|
||||||
|
|
||||||
|
Do not forget to fill in the `MASHAPE_API_KEY` value, which you [can request on the RapidAPI website](https://rapidapi.com/realfavicongenerator/api/realfavicongenerator).
|
||||||
|
|
||||||
Run digimarks as a service under nginx or apache and call the appropriate
|
Run digimarks as a service under nginx or apache and call the appropriate
|
||||||
url's when wanted.
|
url's when wanted.
|
||||||
|
|
||||||
Url's are of the form https://marks.example.com/<userkey>/<action>
|
Url's are of the form https://marks.example.com/<userkey>/<action>
|
||||||
|
|
||||||
|
|
||||||
|
Bookmarklet
|
||||||
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
To easily save a link from your browser, open its bookmark manager and create a new bookmark with as url:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
|
||||||
|
javascript:location.href='http://marks.example.com/1234567890abcdef/add?url='+encodeURIComponent(location.href);
|
||||||
|
|
||||||
|
|
||||||
Creating a new user
|
Creating a new user
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@@ -82,13 +94,14 @@ Attributions
|
|||||||
.. _webhook: https://en.wikipedia.org/wiki/Webhook
|
.. _webhook: https://en.wikipedia.org/wiki/Webhook
|
||||||
.. |PyPI version| image:: https://img.shields.io/pypi/v/digimarks.svg
|
.. |PyPI version| image:: https://img.shields.io/pypi/v/digimarks.svg
|
||||||
:target: https://pypi.python.org/pypi/digimarks/
|
:target: https://pypi.python.org/pypi/digimarks/
|
||||||
.. |PyPI downloads| image:: https://img.shields.io/pypi/dm/digimarks.svg
|
|
||||||
:target: https://pypi.python.org/pypi/digimarks/
|
|
||||||
.. |PyPI license| image:: https://img.shields.io/github/license/aquatix/digimarks.svg
|
.. |PyPI license| image:: https://img.shields.io/github/license/aquatix/digimarks.svg
|
||||||
:target: https://pypi.python.org/pypi/digimarks/
|
:target: https://pypi.python.org/pypi/digimarks/
|
||||||
.. |Code health| image:: https://landscape.io/github/aquatix/digimarks/master/landscape.svg?style=flat
|
.. |Code health| image:: https://landscape.io/github/aquatix/digimarks/master/landscape.svg?style=flat
|
||||||
:target: https://landscape.io/github/aquatix/digimarks/master
|
:target: https://landscape.io/github/aquatix/digimarks/master
|
||||||
:alt: Code Health
|
:alt: Code Health
|
||||||
|
.. |Codacy| image:: https://api.codacy.com/project/badge/Grade/9a34319d917b43219a29e59e9ac75e3b
|
||||||
|
:alt: Codacy Badge
|
||||||
|
:target: https://app.codacy.com/app/aquatix/digimarks?utm_source=github.com&utm_medium=referral&utm_content=aquatix/digimarks&utm_campaign=badger
|
||||||
.. _hook settings: https://github.com/aquatix/digimarks/blob/master/example_config/examples.yaml
|
.. _hook settings: https://github.com/aquatix/digimarks/blob/master/example_config/examples.yaml
|
||||||
.. _vhost for Apache2.4: https://github.com/aquatix/digimarks/blob/master/example_config/apache_vhost.conf
|
.. _vhost for Apache2.4: https://github.com/aquatix/digimarks/blob/master/example_config/apache_vhost.conf
|
||||||
.. _uwsgi.ini: https://github.com/aquatix/digimarks/blob/master/example_config/uwsgi.ini
|
.. _uwsgi.ini: https://github.com/aquatix/digimarks/blob/master/example_config/uwsgi.ini
|
||||||
|
|||||||
0
__init__.py
Normal file
0
__init__.py
Normal file
847
digimarks.py
847
digimarks.py
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
# Virtualenv to use with the wsgi file
|
# Virtualenv to use with the wsgi file (optional)
|
||||||
VENV = '/srv/marks.example.com/venv/bin/activate_this.py'
|
VENV = '/srv/marks.example.com/venv/bin/activate_this.py'
|
||||||
|
|
||||||
PORT = 8086
|
PORT = 8086
|
||||||
@@ -10,6 +10,10 @@ DEBUG = False
|
|||||||
# echo -n "yourstring" | sha1sum
|
# echo -n "yourstring" | sha1sum
|
||||||
SYSTEMKEY = 'S3kr1t'
|
SYSTEMKEY = 'S3kr1t'
|
||||||
|
|
||||||
|
# RapidAPI key for favicons
|
||||||
|
# https://rapidapi.com/realfavicongenerator/api/realfavicongenerator
|
||||||
|
MASHAPE_API_KEY = 'your_MASHAPE_key'
|
||||||
|
|
||||||
LOG_LOCATION = 'digimarks.log'
|
LOG_LOCATION = 'digimarks.log'
|
||||||
#LOG_LOCATION = '/var/log/digimarks/digimarks.log'
|
#LOG_LOCATION = '/var/log/digimarks/digimarks.log'
|
||||||
# How many logs to keep in log rotation:
|
# How many logs to keep in log rotation:
|
||||||
|
|||||||
3
requirements-dev.in
Normal file
3
requirements-dev.in
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
-r requirements.in
|
||||||
|
|
||||||
|
pylint
|
||||||
70
requirements-dev.txt
Normal file
70
requirements-dev.txt
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated by pip-compile with Python 3.10
|
||||||
|
# by the following command:
|
||||||
|
#
|
||||||
|
# pip-compile requirements-dev.in
|
||||||
|
#
|
||||||
|
astroid==2.15.6
|
||||||
|
# via pylint
|
||||||
|
beautifulsoup4==4.12.2
|
||||||
|
# via bs4
|
||||||
|
blinker==1.6.2
|
||||||
|
# via flask
|
||||||
|
bs4==0.0.1
|
||||||
|
# via -r requirements.in
|
||||||
|
certifi==2023.7.22
|
||||||
|
# via requests
|
||||||
|
charset-normalizer==3.2.0
|
||||||
|
# via requests
|
||||||
|
click==8.1.6
|
||||||
|
# via flask
|
||||||
|
dill==0.3.7
|
||||||
|
# via pylint
|
||||||
|
feedgen==0.9.0
|
||||||
|
# via -r requirements.in
|
||||||
|
flask==2.3.2
|
||||||
|
# via -r requirements.in
|
||||||
|
idna==3.4
|
||||||
|
# via requests
|
||||||
|
isort==5.12.0
|
||||||
|
# via pylint
|
||||||
|
itsdangerous==2.1.2
|
||||||
|
# via flask
|
||||||
|
jinja2==3.1.2
|
||||||
|
# via flask
|
||||||
|
lazy-object-proxy==1.9.0
|
||||||
|
# via astroid
|
||||||
|
lxml==4.9.3
|
||||||
|
# via feedgen
|
||||||
|
markupsafe==2.1.3
|
||||||
|
# via
|
||||||
|
# jinja2
|
||||||
|
# werkzeug
|
||||||
|
mccabe==0.7.0
|
||||||
|
# via pylint
|
||||||
|
peewee==3.16.2
|
||||||
|
# via -r requirements.in
|
||||||
|
platformdirs==3.9.1
|
||||||
|
# via pylint
|
||||||
|
pylint==2.17.5
|
||||||
|
# via -r requirements-dev.in
|
||||||
|
python-dateutil==2.8.2
|
||||||
|
# via feedgen
|
||||||
|
requests==2.31.0
|
||||||
|
# via -r requirements.in
|
||||||
|
six==1.16.0
|
||||||
|
# via python-dateutil
|
||||||
|
soupsieve==2.4.1
|
||||||
|
# via beautifulsoup4
|
||||||
|
tomli==2.0.1
|
||||||
|
# via pylint
|
||||||
|
tomlkit==0.11.8
|
||||||
|
# via pylint
|
||||||
|
typing-extensions==4.7.1
|
||||||
|
# via astroid
|
||||||
|
urllib3==2.0.4
|
||||||
|
# via requests
|
||||||
|
werkzeug==2.3.6
|
||||||
|
# via flask
|
||||||
|
wrapt==1.15.0
|
||||||
|
# via astroid
|
||||||
10
requirements.in
Normal file
10
requirements.in
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Core application
|
||||||
|
flask
|
||||||
|
peewee
|
||||||
|
|
||||||
|
# Fetch title etc from links
|
||||||
|
bs4
|
||||||
|
requests
|
||||||
|
|
||||||
|
# Generate (atom) feeds for tags and such
|
||||||
|
feedgen
|
||||||
@@ -1,7 +1,48 @@
|
|||||||
flask
|
#
|
||||||
peewee
|
# This file is autogenerated by pip-compile with Python 3.10
|
||||||
flask-peewee
|
# by the following command:
|
||||||
bs4
|
#
|
||||||
more_itertools
|
# pip-compile requirements.in
|
||||||
requests
|
#
|
||||||
utilkit
|
beautifulsoup4==4.12.2
|
||||||
|
# via bs4
|
||||||
|
blinker==1.6.2
|
||||||
|
# via flask
|
||||||
|
bs4==0.0.1
|
||||||
|
# via -r requirements.in
|
||||||
|
certifi==2023.7.22
|
||||||
|
# via requests
|
||||||
|
charset-normalizer==3.2.0
|
||||||
|
# via requests
|
||||||
|
click==8.1.6
|
||||||
|
# via flask
|
||||||
|
feedgen==0.9.0
|
||||||
|
# via -r requirements.in
|
||||||
|
flask==2.3.2
|
||||||
|
# via -r requirements.in
|
||||||
|
idna==3.4
|
||||||
|
# via requests
|
||||||
|
itsdangerous==2.1.2
|
||||||
|
# via flask
|
||||||
|
jinja2==3.1.2
|
||||||
|
# via flask
|
||||||
|
lxml==4.9.3
|
||||||
|
# via feedgen
|
||||||
|
markupsafe==2.1.3
|
||||||
|
# via
|
||||||
|
# jinja2
|
||||||
|
# werkzeug
|
||||||
|
peewee==3.16.2
|
||||||
|
# via -r requirements.in
|
||||||
|
python-dateutil==2.8.2
|
||||||
|
# via feedgen
|
||||||
|
requests==2.31.0
|
||||||
|
# via -r requirements.in
|
||||||
|
six==1.16.0
|
||||||
|
# via python-dateutil
|
||||||
|
soupsieve==2.4.1
|
||||||
|
# via beautifulsoup4
|
||||||
|
urllib3==2.0.4
|
||||||
|
# via requests
|
||||||
|
werkzeug==2.3.6
|
||||||
|
# via flask
|
||||||
|
|||||||
10
setup.py
10
setup.py
@@ -7,18 +7,18 @@ https://github.com/pypa/sampleproject
|
|||||||
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
# To use a consistent encoding
|
# To use a consistent encoding
|
||||||
from codecs import open
|
from codecs import open as codecopen
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
here = path.abspath(path.dirname(__file__))
|
here = path.abspath(path.dirname(__file__))
|
||||||
|
|
||||||
# Get the long description from the relevant file
|
# Get the long description from the relevant file
|
||||||
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
|
with codecopen(path.join(here, 'README.rst'), encoding='utf-8') as f:
|
||||||
long_description = f.read()
|
long_description = f.read()
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='digimarks', # pip install digimarks
|
name='digimarks', # pip install digimarks
|
||||||
description='Simple bookmarking service, using a SQLite database to store bookmarks, supporting tags and automatic title fetching.',
|
description='Simple bookmarking service, using a SQLite database to store bookmarks, supporting tags, automatic title fetching and REST API calls.',
|
||||||
#long_description=open('README.md', 'rt').read(),
|
#long_description=open('README.md', 'rt').read(),
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ setup(
|
|||||||
# third part for minor release
|
# third part for minor release
|
||||||
# second when api changes
|
# second when api changes
|
||||||
# first when it becomes stable someday
|
# first when it becomes stable someday
|
||||||
version='0.2.0',
|
version='1.1.99',
|
||||||
author='Michiel Scholten',
|
author='Michiel Scholten',
|
||||||
author_email='michiel@diginaut.net',
|
author_email='michiel@diginaut.net',
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ setup(
|
|||||||
|
|
||||||
# as a practice no need to hard code version unless you know program wont
|
# as a practice no need to hard code version unless you know program wont
|
||||||
# work unless the specific versions are used
|
# work unless the specific versions are used
|
||||||
install_requires=['Flask', 'Peewee', 'Flask-Peewee', 'requests', 'utilkit'],
|
install_requires=['Flask', 'Peewee', 'Flask-Peewee', 'requests', 'bs4'],
|
||||||
|
|
||||||
py_modules=['digimarks'],
|
py_modules=['digimarks'],
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* digimarks styling
|
||||||
|
*/
|
||||||
|
|
||||||
/* label color */
|
/** Navigation **/
|
||||||
.input-field label {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
/* label focus color */
|
|
||||||
.input-field input[type=text]:focus + label {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
/* label underline focus color */
|
|
||||||
.input-field input[type=text]:focus {
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
box-shadow: 0 1px 0 0 #000;
|
|
||||||
}
|
|
||||||
/* valid color */
|
|
||||||
.input-field input[type=text].valid {
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
box-shadow: 0 1px 0 0 #000;
|
|
||||||
}
|
|
||||||
/* invalid color */
|
|
||||||
.input-field input[type=text].invalid {
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
box-shadow: 0 1px 0 0 #000;
|
|
||||||
}
|
|
||||||
/* icon prefix focus color */
|
|
||||||
.input-field .prefix.active {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
nav .sidenav-trigger
|
||||||
|
{
|
||||||
|
/* Fix for misalignment of hamburger icon */
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Card title anchor colour */
|
nav .sidenav-trigger i
|
||||||
.white-text .card-title a,
|
{
|
||||||
.white-text a
|
/* Make the hamburger icon great again */
|
||||||
{
|
font-size: 2.7rem;
|
||||||
color: #FFF;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.chip a,
|
/** Cards and tags **/
|
||||||
.white-text .chip a
|
|
||||||
{
|
|
||||||
color: #1b5e20; /* green darken-4 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.card.tiny
|
.card .card-content,
|
||||||
{
|
.card .card-reveal
|
||||||
height: 140px;
|
{
|
||||||
}
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.card .card-reveal .digimark-card-header,
|
.card.tiny
|
||||||
.card .digimark-card-header.activator
|
{
|
||||||
{
|
height: 140px;
|
||||||
cursor: pointer;
|
overflow: hidden;
|
||||||
/*display: block;*/
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.card .digimark-card-content
|
.card.tiny .card-title
|
||||||
{
|
{
|
||||||
padding-top: 10px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card .card-reveal .digimark-card-header,
|
||||||
|
.card .digimark-card-header.activator,
|
||||||
|
.chip.clickable
|
||||||
|
{
|
||||||
|
cursor: pointer;
|
||||||
|
/*display: block;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.card .digimark-card-header-tags
|
||||||
|
{
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-image
|
||||||
|
{
|
||||||
|
min-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-image i,
|
||||||
|
.list-image i
|
||||||
|
{
|
||||||
|
padding: 5px 0 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.horizontal .card-image img.favicon,
|
||||||
|
.list-image img.favicon
|
||||||
|
{
|
||||||
|
height: 60px;
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
|||||||
BIN
static/faviconfallback.png
Normal file
BIN
static/faviconfallback.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 254 B |
@@ -1,7 +1,11 @@
|
|||||||
(function($){
|
/* global M */
|
||||||
$(function(){
|
|
||||||
|
|
||||||
$('.button-collapse').sideNav();
|
var options = {};
|
||||||
|
var elem = document.querySelector(".sidenav");
|
||||||
|
var instance = M.Sidenav.init(elem, options);
|
||||||
|
|
||||||
}); // end of document ready
|
elem = document.querySelector(".collapsible");
|
||||||
})(jQuery); // end of jQuery name space
|
instance = M.Collapsible.init(elem, {
|
||||||
|
// inDuration: 1000,
|
||||||
|
// outDuration: 1000
|
||||||
|
});
|
||||||
|
|||||||
@@ -8,41 +8,104 @@
|
|||||||
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"/>
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"/>
|
||||||
|
|
||||||
<!-- Chrome, Firefox OS and Opera -->
|
<!-- Chrome, Firefox OS and Opera -->
|
||||||
<meta name="theme-color" content="#2e7d32" />
|
<meta name="theme-color" content="{{ theme.BROWSERCHROME }}" />
|
||||||
<!-- Windows Phone -->
|
<!-- Windows Phone -->
|
||||||
<meta name="msapplication-navbutton-color" content="#2e7d32">
|
<meta name="msapplication-navbutton-color" content="{{ theme.BROWSERCHROME }}">
|
||||||
<!-- iOS Safari -->
|
<!-- iOS Safari -->
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
|
|
||||||
|
<meta name="referrer" content="never">
|
||||||
|
<meta name="referrer" content="no-referrer">
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
<link href='https://fonts.googleapis.com/css?family=Roboto+Mono&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
|
<link href='https://fonts.googleapis.com/css?family=Roboto+Mono&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
|
||||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/css/materialize.min.css" type="text/css" rel="stylesheet" media="screen,projection"/>
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css" type="text/css" rel="stylesheet" media="screen,projection"/>
|
||||||
<link href="{{ url_for('static', filename='css/digimarks.css') }}" type="text/css" rel="stylesheet" media="screen,projection"/>
|
<style>
|
||||||
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
|
a
|
||||||
|
{
|
||||||
|
color: {{ theme.LINK_TEXT }};
|
||||||
|
}
|
||||||
|
.card-content a
|
||||||
|
{
|
||||||
|
color: {{ theme.CARD_LINK }};
|
||||||
|
}
|
||||||
|
.chip a
|
||||||
|
{
|
||||||
|
color: {{ theme.CHIP_TEXT }};
|
||||||
|
}
|
||||||
|
/* label color */
|
||||||
|
.input-field .prefix ~ input, .input-field .prefix ~ textarea, .input-field .prefix ~ label, .input-field .prefix ~ .validate ~ label, .input-field .prefix ~ .autocomplete-content, .input-field input[type=text]
|
||||||
|
{
|
||||||
|
color: {{ theme.TEXTHEX }};
|
||||||
|
}
|
||||||
|
/* label focus color */
|
||||||
|
.input-field input[type=text]:focus + label,
|
||||||
|
.input-field .prefix ~ input[type=text]:focus + label
|
||||||
|
{
|
||||||
|
color: {{ theme.BUTTON }};
|
||||||
|
}
|
||||||
|
/* label underline focus color */
|
||||||
|
.input-field input[type=text]:focus,
|
||||||
|
.input-field .prefix ~ input[type=text]:focus,
|
||||||
|
.input-field input[type=text].autocomplete:focus
|
||||||
|
{
|
||||||
|
border-bottom: 1px solid {{ theme.BUTTON }};
|
||||||
|
box-shadow: 0 1px 0 0 {{ theme.BUTTON }};
|
||||||
|
}
|
||||||
|
/* icon prefix focus color */
|
||||||
|
.input-field .prefix.active
|
||||||
|
{
|
||||||
|
color: {{ theme.BUTTON }};
|
||||||
|
}
|
||||||
|
.btn, .btn:visited
|
||||||
|
{
|
||||||
|
background-color: {{ theme.BUTTON }};
|
||||||
|
}
|
||||||
|
.btn:hover, .btn:active
|
||||||
|
{
|
||||||
|
background-color: {{ theme.BUTTON_ACTIVE }};
|
||||||
|
}
|
||||||
|
.deletebtn
|
||||||
|
{
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
.deletebtn:hover
|
||||||
|
{
|
||||||
|
background-color: #ef5350; /* red lighten-1 */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="{{ url_for('static', filename='css/digimarks.css') }}?20180330" type="text/css" rel="stylesheet" media="screen,projection"/>
|
||||||
|
{% if not sortmethod %}
|
||||||
|
{% set sortmethod = None %}
|
||||||
|
{% endif %}
|
||||||
|
{% if not show_as %}
|
||||||
|
{% set show_as = None %}
|
||||||
|
{% endif %}
|
||||||
</head>
|
</head>
|
||||||
<body class="grey lighten-4">
|
<body class="{{ theme.BODY }} {{ theme.TEXT }}">
|
||||||
<nav class="green darken-3" role="navigation">
|
<nav class="{{ theme.NAV }}" role="navigation">
|
||||||
<div class="nav-wrapper container"><a id="logo-container" href="{% if userkey %}{{ url_for('bookmarks', userkey=userkey) }}{% else %}{{ url_for('index') }}{% endif %}" class="brand-logo">digimarks</a>
|
<div class="nav-wrapper container"><a id="logo-container" href="{% if userkey %}{{ url_for('bookmarks_page', userkey=userkey, sortmethod=sortmethod, show_as=show_as) }}{% else %}{{ url_for('index') }}{% endif %}" class="brand-logo">digimarks</a>
|
||||||
<ul class="right hide-on-med-and-down">
|
<ul class="right hide-on-med-and-down">
|
||||||
{% if userkey %}
|
{% if userkey %}
|
||||||
<li><a href="{{ url_for('tags', userkey=userkey) }}">Tags</a></li>
|
<li><a href="{{ url_for('tags_page', userkey=userkey) }}" class="waves-effect waves-light btn"><i class="material-icons left">label</i>Tags</a></li>
|
||||||
<li><a href="{{ url_for('addbookmark', userkey=userkey) }}">Add bookmark</a></li>
|
<li><a href="{{ url_for('addbookmark', userkey=userkey) }}" class="waves-effect waves-light btn"><i class="material-icons left">add</i>Add bookmark</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul id="nav-mobile" class="side-nav">
|
{% if userkey %}
|
||||||
{% if userkey %}
|
<ul id="nav-mobile" class="sidenav">
|
||||||
<li><a href="{{ url_for('tags', userkey=userkey) }}">Tags</a></li>
|
<li><a class="waves-effect" href="{{ url_for('bookmarks_page', userkey=userkey) }}"><i class="material-icons left">turned_in</i>Home</a></li>
|
||||||
<li><a href="{{ url_for('addbookmark', userkey=userkey) }}">Add bookmark</a></li>
|
<li><a class="waves-effect" href="{{ url_for('tags_page', userkey=userkey) }}"><i class="material-icons left">label</i>Tags</a></li>
|
||||||
{% endif %}
|
<li><a class="waves-effect" href="{{ url_for('addbookmark', userkey=userkey) }}"><i class="material-icons left">add</i>Add bookmark</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
|
<a href="#" data-target="nav-mobile" class="sidenav-trigger"><i class="material-icons">menu</i></a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="section no-pad-bot" id="index-banner">
|
<div class="section no-pad-bot" id="index-banner">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="header grey-text lighten-5">
|
<div class="header {{ theme.PAGEHEADER }}">
|
||||||
<h1>{% block pageheader %}Bookmarks{% endblock %}</h1>
|
<h1>{% block pageheader %}Bookmarks{% endblock %}</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,8 +118,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/js/materialize.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||||
<script src="{{ url_for('static', filename='js/init.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/init.js') }}?20180309"></script>
|
||||||
|
|
||||||
|
{% block extrajs %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -16,16 +16,16 @@
|
|||||||
|
|
||||||
{% if tag and publictag %}
|
{% if tag and publictag %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12"><a href="{{ url_for('publictag', tagkey=publictag.tagkey) }}">Public link</a></div>
|
<div class="col s12"><a href="{{ url_for('publictag_page', tagkey=publictag.tagkey) }}">Public link</a></div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if message %}
|
{% if message %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<div class="card-panel orange lighten-2">
|
<div class="card-panel {{ theme.MESSAGE_BACKGROUND }}">
|
||||||
<span class="white-text">
|
<span class="{{ theme.MESSAGE_TEXT }}">
|
||||||
{{ message }}
|
{{ message|safe }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,95 +33,81 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<form action="{{ url_for('bookmarks', userkey=userkey) }}" method="POST">
|
<form action="{{ url_for('bookmarks_page', userkey=userkey) }}" name="filterForm" method="POST" autocomplete="off">
|
||||||
<div class="input-field col l10 m10 s8">
|
<div class="input-field col l9 m9 s8">
|
||||||
<input placeholder="filter" type="text" name="filter" id="filter" value="{{ filter }}" class="validate" />
|
<input placeholder="search text" type="text" name="filter_text" id="filter_text" class="autocomplete" value="{{ filter_text }}" autocomplete="false" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-field col l2 m2 s4">
|
<div class="input-field col l3 m3 s4">
|
||||||
<p class="left-align"><button class="btn waves-effect waves-light" type="submit" name="submit">Filter</button></p>
|
<p class="right-align"><button class="btn waves-effect waves-light" type="submit" name="submitBtn" title="Find"><i class="material-icons">search</i></button>
|
||||||
|
{% if show_as and show_as == 'list' %}
|
||||||
|
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod=filtermethod, sortmethod=sortmethod, show_as=None) }}" class="waves-effect waves-light btn" title="Show as cards"><i class="material-icons">apps</i></a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod=filtermethod, sortmethod=sortmethod, show_as='list') }}" class="waves-effect waves-light btn" title="Show as list"><i class="material-icons">reorder</i></a>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if tags %}
|
{% if tags %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<p>
|
<div class="col s12">
|
||||||
{% for tag in tags %}
|
<ul class="collapsible" data-collapsible="expandable">
|
||||||
<div class="chip">
|
<li>
|
||||||
<a href="{{ url_for('tag', userkey=userkey, tag=tag) }}">{{ tag }}</a>
|
<div class="collapsible-header"><i class="material-icons">label</i>Filter on star/problem/comment/tag</div>
|
||||||
|
<div class="collapsible-body" style="padding: 10px;">
|
||||||
|
<div class="chip">
|
||||||
|
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod='starred') }}"><i class="tiny material-icons {{ theme.STAR }}">star</i></a>
|
||||||
|
</div>
|
||||||
|
<div class="chip">
|
||||||
|
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod='broken') }}"><i class="tiny material-icons {{ theme.PROBLEM }}">report_problem</i></a>
|
||||||
|
</div>
|
||||||
|
<div class="chip">
|
||||||
|
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod='note') }}"><i class="tiny material-icons {{ theme.COMMENT }}">comment</i></a>
|
||||||
|
</div>
|
||||||
|
{% for tag in tags %}
|
||||||
|
<div class="chip">
|
||||||
|
<a href="{{ url_for('tag_page', userkey=userkey, tag=tag) }}">{{ tag }}</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="row">
|
{% if show_as and show_as == 'list' %}
|
||||||
{% for bookmark in bookmarks %}
|
{% include 'list.html' %}
|
||||||
<div class="col s12 m6 l4">
|
{% else %}
|
||||||
{#
|
{% include 'cards.html' %}
|
||||||
<div class="thumbnail">
|
{% endif %}
|
||||||
<a href="{{ bookmark.url }}" title="{{ bookmark.url }}">
|
|
||||||
<img style="width:450px;" src="{{ bookmark.image }}" />
|
|
||||||
</a>
|
|
||||||
<p><a href="{{ bookmark.url }}">{{ bookmark.url|urlize(25) }}</a></p>
|
|
||||||
<p>{{ bookmark.created_date.strftime("%m/%d/%Y %H:%M") }}</p>
|
|
||||||
</div>
|
|
||||||
#}
|
|
||||||
<div class="card tiny green darken-3">
|
|
||||||
<div class="card-content white-text">
|
|
||||||
<span class="digimark-card-header activator">
|
|
||||||
{% for tag in bookmark.tags_list %}
|
|
||||||
<div class="chip">
|
|
||||||
<a href="{{ url_for('tag', userkey=userkey, tag=tag) }}">{{ tag }}</a>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
<i class="material-icons right">more_vert</i>
|
|
||||||
</span>
|
|
||||||
<div class="valign-wrapper digimark-card-content">
|
|
||||||
<div class="valign">
|
|
||||||
{% if bookmark.http_status != 200 %}
|
|
||||||
<i class="tiny material-icons" title="HTTP status {{ bookmark.http_status }}">report_problem</i>
|
|
||||||
{% endif %}
|
|
||||||
{% if bookmark.favicon %}
|
|
||||||
<img src="{{ url_for('static', filename='favicons/' + bookmark.favicon) }}" />
|
|
||||||
{% endif %}
|
|
||||||
<a href="{{ bookmark.url }}" title="{{ bookmark.url }}" rel="noreferrer">
|
|
||||||
{% if bookmark.starred == True %}
|
|
||||||
<i class="tiny material-icons yellow-text">star</i>
|
|
||||||
{% endif %}
|
|
||||||
{% if bookmark.title %}
|
|
||||||
{{ bookmark.title }}
|
|
||||||
{% else %}
|
|
||||||
[ no title ]
|
|
||||||
{% endif %}
|
|
||||||
</a></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-reveal green darken-3">
|
|
||||||
<span class="card-title white-text valign-wrapper">Added @ {{ bookmark.created_date.strftime('%Y-%m-%d %H:%M') }}<i class="material-icons right">close</i></span>
|
|
||||||
<div class="white-text valign">
|
|
||||||
{% if bookmark.favicon %}
|
|
||||||
<img src="{{ url_for('static', filename='favicons/' + bookmark.favicon) }}" />
|
|
||||||
{% endif %}
|
|
||||||
<a href="{{ url_for('editbookmark', userkey=userkey, urlhash=bookmark.url_hash) }}" style="padding: 3px"><i class="tiny material-icons">mode_edit</i> EDIT</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{#
|
<div class="fixed-action-btn" style="bottom: 20px; right: 20px;">
|
||||||
<div class="pagination">
|
<a class="btn-floating btn-large {{ theme.FAB }}" href="{{ url_for('addbookmark', userkey=userkey) }}">
|
||||||
{% if page > 1 %}<a href="./?page={{ page - 1 }}">Previous</a>{% endif %}
|
|
||||||
{% if pagination.get_pages() > page %}<a href="./?page={{ page + 1 }}">Next</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
#}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="fixed-action-btn" style="bottom: 45px; right: 24px;">
|
|
||||||
<a class="btn-floating btn-large red" href="{{ url_for('addbookmark', userkey=userkey) }}">
|
|
||||||
<i class="large material-icons">add</i>
|
<i class="large material-icons">add</i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% block extrajs %}
|
||||||
|
<script>
|
||||||
|
function submitFilter() {
|
||||||
|
document.filterForm.submit();
|
||||||
|
}
|
||||||
|
/* Search filter autocomplete */
|
||||||
|
var options = {
|
||||||
|
onAutocomplete: submitFilter,
|
||||||
|
minLength: 3,
|
||||||
|
limit: 10,
|
||||||
|
data: {
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var elem = document.querySelector('.autocomplete');
|
||||||
|
var instance = M.Autocomplete.init(elem, options);
|
||||||
|
/* TODO: fetch from API
|
||||||
|
instance.updateData({
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
</script>
|
||||||
|
<script src="{{ url_for('bookmarks_js', userkey=userkey) }}" ></script>
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
11
templates/bookmarks.js
Normal file
11
templates/bookmarks.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
var elem = document.querySelector('.autocomplete');
|
||||||
|
var instance = M.Autocomplete.getInstance(elem);
|
||||||
|
instance.updateData({
|
||||||
|
{% for bookmark in bookmarks %}
|
||||||
|
{% if bookmark.favicon %}
|
||||||
|
"{{ bookmark.title | replace('"', '\\"') | replace('\n', '') | replace('\r', '') }}": "{{ url_for('static', filename='favicons/' + bookmark.favicon) }}",
|
||||||
|
{% else %}
|
||||||
|
"{{ bookmark.title | replace('"', '\\"') | replace('\n', '') | replace('\r', '') }}": null,
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
});
|
||||||
65
templates/cards.html
Normal file
65
templates/cards.html
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<div class="row">
|
||||||
|
{% for bookmark in bookmarks %}
|
||||||
|
<div class="col s12 m6 l4">
|
||||||
|
<div class="card horizontal tiny {{ theme.CARD_BACKGROUND }}">
|
||||||
|
<div class="card-image">
|
||||||
|
{% if bookmark.favicon %}
|
||||||
|
<div><img src="{{ url_for('static', filename='favicons/' + bookmark.favicon) }}" class="favicon" /></div>
|
||||||
|
{% else %}
|
||||||
|
<div><img src="{{ url_for('static', filename='faviconfallback.png') }}" class="favicon" /></div>
|
||||||
|
{% endif %}
|
||||||
|
{% if bookmark.http_status != 200 and bookmark.http_status != 304 %}
|
||||||
|
<div><i class="small material-icons {{ theme.PROBLEM }}" title="HTTP status {{ bookmark.http_status }}">report_problem</i></div>
|
||||||
|
{% endif %}
|
||||||
|
{% if bookmark.starred == True %}
|
||||||
|
<div><i class="small material-icons {{ theme.STAR }}">star</i></div>
|
||||||
|
{% endif %}
|
||||||
|
{% if bookmark.note %}
|
||||||
|
<div><i class="small material-icons {{ theme.CARD_TEXT }}" title="{{ bookmark.note|truncate(100) }}">comment</i></div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="card-stacked">
|
||||||
|
<div class="card-content {{ theme.CARD_TEXT }}">
|
||||||
|
<span class="digimark-card-header activator">
|
||||||
|
<i class="material-icons right">more_vert</i>
|
||||||
|
</span>
|
||||||
|
<div class="digimark-card-content">
|
||||||
|
<a href="{{ bookmark.url }}" title="{{ bookmark.url }}" rel="noreferrer noopener" target="_blank">
|
||||||
|
{% if bookmark.title %}
|
||||||
|
{{ bookmark.title }}
|
||||||
|
{% else %}
|
||||||
|
{{ bookmark.get_uri_domain() }} (no title)
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-reveal {{ theme.CARD_BACKGROUND }}">
|
||||||
|
<span class="card-title {{ theme.CARD_TEXT }}">Added @ {{ bookmark.created_date.strftime('%Y-%m-%d %H:%M') }}<i class="material-icons right">close</i></span>
|
||||||
|
{% if editable %}
|
||||||
|
<div class="{{ theme.CARD_TEXT }}" style="padding-top: 10px;">
|
||||||
|
<a href="{{ url_for('editbookmark', userkey=userkey, urlhash=bookmark.url_hash) }}" style="padding: 3px"><i class="tiny material-icons">mode_edit</i> EDIT</a>
|
||||||
|
<a href="{{ url_for('deletingbookmark', userkey=userkey, urlhash=bookmark.url_hash) }}" style="padding: 3px" class="red-text"><i class="tiny material-icons">delete</i> DELETE</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if showtags %}
|
||||||
|
<div class="digimark-card-header-tags">
|
||||||
|
{% for tag in bookmark.tags_list %}
|
||||||
|
<div class="chip">
|
||||||
|
<a href="{{ url_for('tag_page', userkey=userkey, tag=tag) }}">{{ tag }}</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{#
|
||||||
|
<div class="pagination">
|
||||||
|
{% if page > 1 %}<a href="./?page={{ page - 1 }}">Previous</a>{% endif %}
|
||||||
|
{% if pagination.get_pages() > page %}<a href="./?page={{ page + 1 }}">Next</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
#}
|
||||||
|
</div>
|
||||||
@@ -3,13 +3,19 @@
|
|||||||
{% block pageheader %}{{ action }}{% endblock %}
|
{% block pageheader %}{{ action }}{% endblock %}
|
||||||
{% block pagecontent %}
|
{% block pagecontent %}
|
||||||
|
|
||||||
{% if bookmark.http_status != 200 %}
|
{% if bookmark.http_status != 200 and bookmark.http_status != 202 and bookmark.http_status != 304 %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<div class="card-panel red darken-1">
|
<div class="card-panel {{ theme.ERRORMESSAGE_BACKGROUND }}">
|
||||||
<span class="white-text">
|
<span class="{{ theme.ERRORMESSAGE_TEXT }}">
|
||||||
{% if bookmark.http_status == 404 %}
|
{% if bookmark.http_status == 404 %}
|
||||||
<i class="material-icons">report_problem</i> URL not found (404), broken/outdated link?
|
<i class="material-icons">report_problem</i> URL not found (404), broken/outdated link?
|
||||||
|
{% elif bookmark.http_status == 301 %}
|
||||||
|
<i class="material-icons">report_problem</i> HTTP status (301), moved permanently. Use button for new target
|
||||||
|
{% elif bookmark.http_status == 302 %}
|
||||||
|
<i class="material-icons">report_problem</i> HTTP status (302), moved temporarily. Use button for new target
|
||||||
|
{% elif bookmark.http_status == bookmark.HTTP_CONNECTIONERROR %}
|
||||||
|
<i class="material-icons">report_problem</i> Connection error, server might have been offline at the time of last edit
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="material-icons">report_problem</i> HTTP status {{ bookmark.http_status }}
|
<i class="material-icons">report_problem</i> HTTP status {{ bookmark.http_status }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -22,8 +28,8 @@
|
|||||||
{% if message %}
|
{% if message %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<div class="card-panel orange lighten-2">
|
<div class="card-panel {{ theme.MESSAGE_BACKGROUND }}">
|
||||||
<span class="white-text">
|
<span class="{{ theme.MESSAGE_TEXT }}">
|
||||||
{{ message }}
|
{{ message }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -31,64 +37,82 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if formaction and formaction == 'edit' %}
|
{% if formaction and formaction == 'edit' %}
|
||||||
<form action="{{ url_for('editingbookmark', userkey=userkey, urlhash=bookmark.url_hash) }}" method="POST">
|
<form class="digimark" id="digimark" action="{{ url_for('editingbookmark', userkey=userkey, urlhash=bookmark.url_hash) }}" method="POST" onsubmit="return onSubmitForm();" autocomplete="off">
|
||||||
{% else %}
|
{% else %}
|
||||||
<form action="{{ url_for('addingbookmark', userkey=userkey) }}" method="POST">
|
<form class="digimark" id="digimark" action="{{ url_for('addingbookmark', userkey=userkey) }}" method="POST" onsubmit="return onSubmitForm();" autocomplete="off">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
<div class="input-field col s12">
|
<div class="input-field col s12">
|
||||||
<i class="material-icons prefix">description</i>
|
<i class="material-icons prefix">description</i>
|
||||||
<input placeholder="title" type="text" name="title" id="title" value="{{ bookmark.title }}" class="validate" />
|
<input placeholder="title (leave empty for autofetch)" type="text" name="title" id="title" value="{{ bookmark.title }}" autocomplete="false" />
|
||||||
<label for="title">Title</label>
|
<label for="title">Title</label>
|
||||||
|
{# <span class="helper-text">Leave title empty for autofetching from the page</span>#}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-field col s12">
|
<div class="input-field col s12">
|
||||||
<i class="material-icons prefix">turned_in</i>
|
<i class="material-icons prefix">turned_in</i>
|
||||||
<input placeholder="url" type="text" name="url" id="url" value="{{ bookmark.url }}" class="validate" />
|
<input placeholder="url" type="text" name="url" id="url" value="{{ bookmark.url }}" autocomplete="false" />
|
||||||
<label for="url">URL</label>
|
<label for="url">URL</label>
|
||||||
|
{% if bookmark.get_redirect_uri() %}
|
||||||
|
<div>
|
||||||
|
<a class="waves-effect waves-light btn" id="btn_urlupdate" onclick="updateURL()"><i class="material-icons left">turned_in</i>{{ bookmark.get_redirect_uri() }}</a>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function updateURL() {
|
||||||
|
var text = document.getElementById('url');
|
||||||
|
text.value = '{{ bookmark.get_redirect_uri() }}';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-field col s12">
|
||||||
|
<i class="material-icons prefix">comment</i>
|
||||||
|
<input placeholder="note" type="text" name="note" id="note" value="{{ bookmark.note }}" autocomplete="false" />
|
||||||
|
<label for="note">Note</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-field col s12">
|
<div class="input-field col s12">
|
||||||
<i class="material-icons prefix">label</i>
|
<i class="material-icons prefix">label</i>
|
||||||
<input placeholder="tags, divided by comma's" type="text" name="tags" id="tags" value="{{ bookmark.tags }}" class="validate" />
|
<input placeholder="tags, divided by comma's" type="text" name="tags" id="tags" value="{{ bookmark.tags }}" autocomplete="false" />
|
||||||
<label for="tags">Tags</label>
|
<label for="tags">Tags</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if tags %}
|
{% if tags %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
{% for tag in tags %}
|
<ul class="collapsible" data-collapsible="expandable">
|
||||||
<div class="chip" id="tag_{{ tag }}">
|
<li>
|
||||||
{{ tag }}
|
<div class="collapsible-header"><i class="material-icons">label</i>Existing tags</div>
|
||||||
</div>
|
<div class="collapsible-body" style="padding: 10px;">
|
||||||
{% endfor %}
|
{% for tag in tags %}
|
||||||
|
<div class="chip clickable" id="chip_{{ tag }}" onclick="addTag('{{ tag }}');">
|
||||||
|
{{ tag }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% for tag in tags %}
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function () {
|
|
||||||
$('#tag_{{ tag }}').on('click', function () {
|
|
||||||
var text = $('#tags');
|
|
||||||
text.val(text.val() + ', {{ tag }}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<div class="input-field col s12">
|
<div class="col s12">
|
||||||
{#<i class="material-icons prefix">star</i>#}
|
{#<i class="material-icons prefix">star</i>#}
|
||||||
<input type="checkbox" name="starred" id="starred" {% if bookmark.starred == True %}checked{% endif %} />
|
<label>
|
||||||
<label for="starred">Starred</label>
|
<input type="checkbox" name="starred" id="starred" {% if bookmark.starred == True %}checked{% endif %} />
|
||||||
|
<span>Starred</span>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-field col s12">
|
<div class="col s12">
|
||||||
<input type="checkbox" name="strip" id="strip" />
|
<label>
|
||||||
<label for="strip">Strip parameters from url (like <em>?utm_source=social</em> - can break the link!)</label>
|
<input type="checkbox" name="strip" id="strip" />
|
||||||
|
<span>Strip parameters from url (like <em>?utm_source=social</em> - can break the link!)</span>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if bookmark.url_hash %}
|
{% if bookmark.url_hash %}
|
||||||
@@ -119,15 +143,33 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="input-field col l2 m3 s4">
|
<div class="input-field col l2 m3 s4">
|
||||||
<p class="left-align"><button class="btn waves-effect waves-light" type="submit" name="submit">Save <i class="material-icons right">send</i></button></p>
|
<p class="left-align"><button class="btn waves-effect waves-light" type="submit" name="submit" id="submit">Save <i class="material-icons right">send</i></button></p>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
{% if bookmark.url_hash %}
|
{% if bookmark.url_hash %}
|
||||||
<div class="input-field col l2 m3 s4">
|
</form>
|
||||||
|
<div class="input-field col l4 m4 s6">
|
||||||
<form action="{{ url_for('deletingbookmark', userkey=userkey, urlhash=bookmark.url_hash) }}" method="POST">
|
<form action="{{ url_for('deletingbookmark', userkey=userkey, urlhash=bookmark.url_hash) }}" method="POST">
|
||||||
<p class="left-align"><button class="btn waves-effect waves-light" type="submit" name="delete">Delete <i class="material-icons right">delete</i></button></p>
|
<p class="left-align"><button class="btn waves-effect waves-light deletebtn" type="submit" name="delete">Delete <i class="material-icons right">delete</i></button></p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
|
||||||
|
<script>
|
||||||
|
function onSubmitForm()
|
||||||
|
{
|
||||||
|
var theForm = document.getElementById('digimark');
|
||||||
|
var submitButton = document.getElementById('submit');
|
||||||
|
theForm.onsubmit = submitButton.setAttribute("disabled", true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function addTag(tagText)
|
||||||
|
{
|
||||||
|
var text = document.getElementById('tags');
|
||||||
|
text.value = text.value + ', ' + tagText;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
62
templates/list.html
Normal file
62
templates/list.html
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<div class="row">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
<th>Bookmark</th>
|
||||||
|
<th>Added</th>
|
||||||
|
{% if showtags %}
|
||||||
|
<th>Tags</th>
|
||||||
|
{% endif %}
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for bookmark in bookmarks %}
|
||||||
|
<tr>
|
||||||
|
<td class="list-image">
|
||||||
|
{% if bookmark.favicon %}
|
||||||
|
<img src="{{ url_for('static', filename='favicons/' + bookmark.favicon) }}" class="favicon" />
|
||||||
|
{% else %}
|
||||||
|
<img src="{{ url_for('static', filename='faviconfallback.png') }}" class="favicon" />
|
||||||
|
{% endif %}
|
||||||
|
{% if bookmark.http_status != 200 and bookmark.http_status != 304 %}
|
||||||
|
<i class="small material-icons {{ theme.PROBLEM }}" title="HTTP status {{ bookmark.http_status }}">report_problem</i>
|
||||||
|
{% endif %}
|
||||||
|
{% if bookmark.starred == True %}
|
||||||
|
<i class="small material-icons {{ theme.STAR }}">star</i>
|
||||||
|
{% endif %}
|
||||||
|
{% if bookmark.note %}
|
||||||
|
<i class="small material-icons {{ theme.CARD_TEXT }}" title="{{ bookmark.note|truncate(100) }}">comment</i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ bookmark.url }}" title="{{ bookmark.url }}" rel="noreferrer noopener" target="_blank">
|
||||||
|
{% if bookmark.title %}
|
||||||
|
{{ bookmark.title }}
|
||||||
|
{% else %}
|
||||||
|
{{ bookmark.get_uri_domain() }} (no title)
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ bookmark.created_date.strftime('%Y-%m-%d %H:%M') }}</td>
|
||||||
|
{% if showtags %}
|
||||||
|
<td>
|
||||||
|
{% for tag in bookmark.tags_list %}
|
||||||
|
<div class="chip">
|
||||||
|
<a href="{{ url_for('tag_page', userkey=userkey, tag=tag) }}">{{ tag }}</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
<td>
|
||||||
|
{% if editable %}
|
||||||
|
<a href="{{ url_for('editbookmark', userkey=userkey, urlhash=bookmark.url_hash) }}" class="waves-effect waves-light btn" title="Edit"><i class="tiny material-icons">mode_edit</i></a>
|
||||||
|
<a href="{{ url_for('deletingbookmark', userkey=userkey, urlhash=bookmark.url_hash) }}" class="waves-effect waves-light btn red" title="DELETE"><i class="tiny material-icons">delete</i></a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
@@ -19,38 +19,11 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for bookmark in bookmarks %}
|
<div class="col s12">
|
||||||
<div class="col s12 m6 l4">
|
<a href="{{ url_for('publictag_feed', tagkey=tagkey) }}"><i class="material-icons tiny">rss_feed</i> feed</a>
|
||||||
<div class="card green darken-3">
|
|
||||||
<div class="card-content white-text">
|
|
||||||
<span class="card-title activator"><i class="material-icons right">more_vert</i></span>
|
|
||||||
{% if bookmark.http_status != 200 %}
|
|
||||||
<i class="material-icons" title="HTTP status {{ bookmark.http_status }}">report_problem</i>
|
|
||||||
{% endif %}
|
|
||||||
{% if bookmark.favicon %}
|
|
||||||
<img src="{{ url_for('static', filename='favicons/' + bookmark.favicon) }}" />
|
|
||||||
{% endif %}
|
|
||||||
<p><a href="{{ bookmark.url }}" title="{{ bookmark.url }}" rel="noreferrer">
|
|
||||||
{% if bookmark.starred == True %}
|
|
||||||
<i class="material-icons">star</i>
|
|
||||||
{% endif %}
|
|
||||||
{% if bookmark.title %}
|
|
||||||
{{ bookmark.title }}
|
|
||||||
{% else %}
|
|
||||||
[ no title ]
|
|
||||||
{% endif %}
|
|
||||||
</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="card-reveal green darken-3">
|
|
||||||
<span class="card-title white-text">Added @ {{ bookmark.created_date.strftime('%Y-%m-%d %H:%M') }}<i class="material-icons right">close</i></span>
|
|
||||||
<div class="white-text">
|
|
||||||
{% if bookmark.favicon %}
|
|
||||||
<img src="{{ url_for('static', filename='favicons/' + bookmark.favicon) }}" />
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% include 'cards.html' %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
16
templates/redirect.html
Normal file
16
templates/redirect.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Redirecting - digimarks</title>
|
||||||
|
<meta name="referrer" content="never">
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta http-equiv=refresh content="3; URL={{ url }}">
|
||||||
|
<style>
|
||||||
|
body { background-color: #000; color: #FFF; }
|
||||||
|
a { color: #fb8c00; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>You're being redirected. If nothing happens, <a href="{{ url }}">click here instead</a>.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -4,11 +4,62 @@
|
|||||||
{% block pagecontent %}
|
{% block pagecontent %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
{% for tag in tags %}
|
<div class="col s12">
|
||||||
<div class="chip">
|
<table class="centered">
|
||||||
<a href="{{ url_for('tag', userkey=userkey, tag=tag) }}">{{ tag }}</a>
|
<thead>
|
||||||
</div>
|
<tr>
|
||||||
{% endfor %}
|
<th><i class="material-icons" title="Unique labels">label</i></th>
|
||||||
|
<th><i class="material-icons green-text" title="Public tag pages">present_to_all</i></th>
|
||||||
|
<th><i class="material-icons" title="Total bookmarks">turned_in</i></th>
|
||||||
|
<th><i class="material-icons" title="Bookmarks with notes">comment</i></th>
|
||||||
|
<th><i class="material-icons yellow-text" title="Starred bookmarks">star</i></th>
|
||||||
|
<th><i class="material-icons orange-text" title="HTTP status is not 200 OK">warning</i></th>
|
||||||
|
<th><i class="material-icons red-text" title="Deleted bookmarks">delete</i></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{{ totaltags }}</td>
|
||||||
|
<td>{{ totalpublic }}</td>
|
||||||
|
<td>{{ totalbookmarks }}</td>
|
||||||
|
<td>{{ totalnotes }}</td>
|
||||||
|
<td>{{ totalstarred }}</td>
|
||||||
|
<td>{{ totalhttperrorstatus }}</td>
|
||||||
|
<td>{{ totaldeleted }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Tag</th>
|
||||||
|
<th>Public link</th>
|
||||||
|
<th>Number of bookmarks</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for tag in tags %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('tag_page', userkey=userkey, tag=tag['tag']) }}">{{ tag['tag'] }}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if tag['publictag'] %}
|
||||||
|
<a href="{{ url_for('publictag_page', tagkey=tag['publictag'].tagkey) }}">Public link</a> (<a href="{{ url_for('removepublictag', tag=tag['tag'], tagkey=tag['publictag'].tagkey, userkey=userkey) }}">Delete</a> <i class="tiny material-icons red-text">warning</i>)
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url_for('addpublictag', userkey=userkey, tag=tag['tag']) }}">Create</a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ tag['total'] }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
10
wsgi.py
10
wsgi.py
@@ -1,7 +1,13 @@
|
|||||||
# Activate virtualenv
|
# Activate virtualenv
|
||||||
import settings
|
import settings
|
||||||
activate_this = settings.VENV
|
activate_this = getattr(settings, 'VENV', None)
|
||||||
execfile(activate_this, dict(__file__=activate_this))
|
# FIXME: python 2 *and* python 3 compatibility
|
||||||
|
# Python 2
|
||||||
|
#if activate_this:
|
||||||
|
# execfile(activate_this, dict(__file__=activate_this))
|
||||||
|
# Python 3
|
||||||
|
with open(activate_this) as file_:
|
||||||
|
exec(file_.read(), dict(__file__=activate_this))
|
||||||
|
|
||||||
from digimarks import app as application
|
from digimarks import app as application
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user