Compare commits

...

375 Commits

Author SHA1 Message Date
reverend f078afcdcd Env file 2022-01-01 13:43:24 +01:00
reverend 163e9beb51 Documention für pipenv scripts 2021-12-31 23:42:04 +01:00
reverend 6ba225bee3 Version id compliant to PEP 440 2021-12-31 23:34:42 +01:00
reverend a4f80820c9 Hotfix for Migration Error 2021-12-31 23:27:35 +01:00
reverend 0f7b799c11 More / Better Scripts for Task Running 2021-12-31 23:27:06 +01:00
reverend b23dc8a627 Generating Migrations für new Release 0.1.4 2021-12-31 18:37:54 +01:00
reverend 3e2ab1e12d Merge branch 'develop' Release 0.1.4 2021-12-31 16:55:40 +01:00
reverend 78efe9bebb #58 Voting UI is bugged when no vote was submitted 2021-12-31 15:56:31 +01:00
reverend 1de203ad40 More Detailed view of user's vote 2021-12-31 01:15:37 +01:00
reverend 399fa70ab6 #42 Tests for Level-System / Homepage 2021-12-31 00:35:19 +01:00
reverend c6a28c7b66 Inlcuding Material Design Icons 2021-12-30 23:20:29 +01:00
reverend 9980a2d190 #42 Place Voting / Level 2021-12-30 23:20:05 +01:00
Marcus Scholz 1bc283bd8d Changed clone url after repo migration. 2021-10-18 09:58:50 +02:00
reverend 4c43f87560 Removing annoying warning since Django update 3.2 2021-10-02 01:54:43 +02:00
reverend c8399b9ce4 #54 Scaling image up while cropping 2021-10-02 01:54:21 +02:00
reverend f7dab77229 #42 Testing place detail for level 2021-10-02 01:31:12 +02:00
reverend 8d96214a92 Nose testing sutie 2021-10-02 01:30:53 +02:00
reverend 6678f8ff02 Nose testing suite 2021-10-02 01:30:44 +02:00
reverend 4cd0635d5f #42 Testing place level on place list 2021-10-02 00:50:32 +02:00
reverend e11151858b #42 Fined tuned list of eligible to see places 2021-10-02 00:03:45 +02:00
reverend 84b01f3a9a #42 Place submitter and super users should be able to see a place 2021-10-01 23:44:46 +02:00
reverend 3f4bf9475c #42 Restricting Acces to Place requests 2021-10-01 23:41:34 +02:00
reverend b607335299 #42 Checking ListView for Levels 2021-10-01 22:38:44 +02:00
reverend b1cd8fd0cc #47 Settings Place Hero when creating a place 2021-10-01 21:44:35 +02:00
reverend a7a3ddfe63 #42 Excluding Level from Forms 2021-10-01 21:14:53 +02:00
reverend 1c6366fb43 Migrations between development systems make life just more painful 2021-10-01 19:36:48 +02:00
reverend 565a70bbac Migrations between development systems make life just more painful 2021-10-01 19:36:29 +02:00
reverend 749aa61828 Migrations between development systems make life just more painful 2021-10-01 19:36:11 +02:00
reverend e2754dc56c No django migrations in development branches, screws everything up 2021-10-01 19:31:06 +02:00
Leonhard Strohmidel fefc38fa9c Migration Script 2021-10-01 09:40:53 +02:00
Leonhard Strohmidel 58ab70ba42 #42 Levels for places 2021-10-01 09:40:42 +02:00
Leonhard Strohmidel c63b0ebb87 Mehr Urbex-Codex (German only) 2021-10-01 09:29:09 +02:00
Leonhard Strohmidel 0852e35b57 #42 Level for Users 2021-10-01 09:28:45 +02:00
reverend e52247d80b Trying to make artifacts publicly available 2021-07-16 13:54:03 +02:00
reverend 2ac90bd35c Archiving build artefacts 2021-07-16 13:35:32 +02:00
reverend 3685db6892 Im dumb 2021-07-16 13:31:03 +02:00
reverend d5789cef75 Screw it, building is not handled by pipenv 2021-07-16 13:28:58 +02:00
reverend 5fca4dc52a Setuptools outside of venv 2021-07-16 13:24:01 +02:00
reverend cbf45af5f5 setuptools dev depedency 2021-07-16 13:20:03 +02:00
reverend 244b4d2917 relative paths instead of cd 2021-07-16 13:17:23 +02:00
reverend d8b0ce1ac2 Manual merging current models 2021-07-16 13:15:19 +02:00
reverend 8da6964b3c Setting Up pipenv in building 2021-07-16 13:11:10 +02:00
reverend ccd701ea60 Pipfile script for migrations 2021-07-16 13:08:42 +02:00
reverend 170971c44b Privilege escalation attack inc 2021-07-16 13:06:10 +02:00
reverend 7196820122 Trying out other agents for building 2021-07-16 13:02:07 +02:00
reverend a02d4f5e86 yes yes indeed 2021-07-10 14:43:56 +02:00
reverend a7043651e0 , 2021-07-10 13:44:09 +02:00
reverend bcf3377190 Trying to use pipenv in jenkins 2021-07-10 13:42:26 +02:00
reverend ceabe3f6f8 No manual sync with repo since this is done by jenkins 2021-07-10 13:34:29 +02:00
reverend 6b33d20f90 :: 2021-07-10 13:32:56 +02:00
reverend 1d787a3b1d . 2021-07-10 13:31:34 +02:00
reverend 1960bf3792 . 2021-07-10 13:30:10 +02:00
reverend 0c3898163e ... 2021-07-10 13:27:46 +02:00
reverend 2c6676d2c9 Havin' fun with jenkins 2021-07-10 13:25:58 +02:00
reverend 52f9df8b2a Jenkinsfile to build a snapshot 2021-07-10 13:22:11 +02:00
reverend ab669b9f5e Changes in MapContext 2021-06-25 11:04:18 +02:00
reverend 0fe98d4f8f Testing place views 2021-06-25 11:04:01 +02:00
reverend 51addd8fbb Testing messgaes 2021-06-12 17:06:09 +02:00
reverend 29d2813fcc Some weird bug only occuring when testing 2021-06-12 17:05:54 +02:00
reverend cc9343270a explorers -> explorer 2021-06-12 17:05:32 +02:00
reverend 4f465b3162 400 Response when submitting invalid place data and testing more edge cases 2021-06-12 15:52:52 +02:00
reverend b0bf40aa0b More tests of views 2021-06-12 15:07:14 +02:00
reverend 822a536ebe Fixing idention 2021-05-16 13:03:46 +02:00
reverend 5b9672e21e Testing PlaceAssetCreateView 2021-05-16 13:03:41 +02:00
reverend 0a5d22d4d9 More comments 2021-05-15 23:27:33 +02:00
reverend 9c86eab14c Testing home view 2021-05-15 23:27:25 +02:00
reverend 29d067002e Mixin Test does not rely on actual place view 2021-05-15 23:26:27 +02:00
reverend f5f5980f9b Tests for global templates 2021-05-15 23:26:02 +02:00
reverend 10c08a2f5e Current CSS 2021-04-10 08:24:33 +02:00
reverend 50f60be10a Shifting index 2021-04-10 08:24:23 +02:00
reverend 8b32b56dd9 Custom Widget to select content/invisible radio input 2021-04-10 08:24:08 +02:00
reverend 74d842a668 #47 Settinge of Place Hero Image 2021-04-10 08:23:36 +02:00
reverend 2ac39f719f Removing debug 2021-04-09 19:51:45 +02:00
reverend 9b6121e448 Small fix 2021-04-09 19:51:17 +02:00
reverend a139594863 Fixin Partial and Set Tag 2021-04-06 19:15:22 +02:00
reverend f2eb048f0b Small check is this partial is used within place 2021-04-06 19:14:58 +02:00
reverend 120e63808a Replace include with partial tag 2021-04-06 19:14:36 +02:00
reverend 201ef73639 Accidently removed place url 2021-04-04 17:03:26 +02:00
reverend af7afd0311 Accidently removed the add image tile 2021-04-04 17:01:00 +02:00
reverend cf6346fdf0 Fixed #49 2021-04-04 16:56:18 +02:00
reverend d641d7b44d Backwards compatibality 2021-04-04 16:55:56 +02:00
reverend d35cb8131a Merge branch 'master' into develop 2021-04-03 23:07:16 +02:00
reverend ceeae9e8c9 rudimentary implementation of a lightbox 2021-04-03 23:03:44 +02:00
reverend 092b91825f Following new naming https://is.gd/cRmcip 2021-04-02 22:06:52 +02:00
reverend 52271811ad using block in partial 2021-04-02 22:00:21 +02:00
reverend fb1237f111 set variable and partial template tag 2021-04-02 22:00:13 +02:00
reverend bae4e13137 Partial for PlaceImageGrid 2021-04-02 17:22:28 +02:00
reverend b752454233 #39 Partial for Images 2021-04-02 17:21:00 +02:00
Marcus Scholz 36eb9566d9 Fixed 404 because of misnamed font file. 2020-12-26 14:33:57 +01:00
Marcus Scholz b876435d8c Removed 'the mother of all debugging' again. :D 2020-12-25 19:50:34 +01:00
Marcus Scholz 224eb87d76 Changed migration file reference after renaming it. 2020-12-25 19:47:05 +01:00
Marcus Scholz a78f123d1f Merge commit 'a22c988e948438415d1a58cac627243ae24785f4' into develop 2020-12-25 19:39:05 +01:00
Marcus Scholz a22c988e94 Added visited_places attribute to Explorer. 2020-12-25 19:36:11 +01:00
Marcus Scholz 7f2283325c gory migration fuckery (rename) 2020-12-25 19:35:35 +01:00
Marcus Scholz 6b7c71ef30 Addid visited_places system. (mostly copy&paste) :P 2020-12-25 19:32:54 +01:00
Marcus Scholz 067bf36118 SVG paths updated. 2020-12-25 19:20:44 +01:00
Marcus Scholz 9eef044af9 Renamed favorite* svgs. 2020-12-25 19:19:01 +01:00
Marcus Scholz a4780a22f2 Changed urlpattern tree. 2020-12-25 18:17:05 +01:00
reverend 947f6520aa CSS für Profil 2020-12-25 18:07:54 +01:00
Marcus Scholz 0d1d829abe Regrouped views. 2020-12-25 17:56:17 +01:00
Marcus Scholz 59cfa82ce9 Resorted and -grouped urls. 2020-12-25 17:54:15 +01:00
Marcus Scholz d47c85795c FU migrations! 2020-12-25 17:33:45 +01:00
Marcus Scholz 8e80614eee Merge commit 'c5f6355f193df939ebb1b158be6b4dc2ba425a60' into develop 2020-12-25 16:51:49 +01:00
reverend 6a1e2d975b New Icon 2020-12-25 16:24:28 +01:00
Marcus Scholz c5f6355f19 Updated translations (de). 2020-12-25 16:07:50 +01:00
Marcus Scholz dac63e99ba Added Edit button to profile page. 2020-12-25 16:00:29 +01:00
Marcus Scholz 9f369456d5 Changed easy_thumbnails image/thumb deletion. Now working. 2020-12-25 15:42:02 +01:00
Marcus Scholz 011a58f6b3 Use thumbnail in profile_update. 2020-12-25 14:29:38 +01:00
Marcus Scholz 67ce6cb50b Added working explorer_profile_image upload. 2020-12-25 14:06:53 +01:00
reverend 5df7cc5ec6 #46 Large Map 2020-12-25 13:29:34 +01:00
reverend e242dc4add Partial takes parameter to change size of map 2020-12-25 13:29:18 +01:00
Marcus Scholz 86cc7f23fe description_fuckery. 2020-12-25 13:19:34 +01:00
reverend f73fa616d0 Minor reordering 2020-12-25 13:05:59 +01:00
reverend 629a609ff5 Forgott imports for #45 2020-12-25 13:00:30 +01:00
reverend 04fe93c7bb #45 Redirect after asset deletion 2020-12-25 12:57:05 +01:00
Marcus Scholz 3eaa186b66 Delete profile_image on user_deletion. 2020-12-25 12:53:52 +01:00
reverend b42be489dc #44 Text in place teaser is cut of 2020-12-25 12:39:13 +01:00
Marcus Scholz cc59254ba4 Added clean_username function to validate form. 2020-12-25 12:24:09 +01:00
Marcus Scholz 67a6517716 Comment improved. 2020-12-25 11:14:54 +01:00
Marcus Scholz 0f5474c2d3 half-working :P 2020-12-25 11:14:21 +01:00
Marcus Scholz 17e71b71d4 Fix typo. 2020-12-25 08:04:35 +01:00
Marcus Scholz b1aa4473e9 Added failsafe, if there is no profile_image. 2020-12-25 02:11:02 +01:00
Marcus Scholz 871acd1dce Improved class comment. 2020-12-25 01:41:09 +01:00
Marcus Scholz 14ca45d111 Comments for customizations of UserChangeForm. 2020-12-25 01:36:14 +01:00
Marcus Scholz c71fe4cf2d Added new translations (de) 2020-12-25 01:31:43 +01:00
Marcus Scholz 7359bf5fab ExplorerChangeForms, with deactivated username field. 2020-12-25 01:31:01 +01:00
Marcus Scholz 4f0182fc3e Minor textual changes for consistency. 2020-12-25 01:28:23 +01:00
Marcus Scholz 30f259fb4d WIP-commit of translations to test against fuzzy detection. 2020-12-24 23:51:40 +01:00
Marcus Scholz 53f89caef5 Added a ModelForm to change profile details. 2020-12-24 20:31:52 +01:00
Marcus Scholz 3855fb28d7 Rename ExplorerCreationForm to SignupVoucherForm. 2020-12-24 20:25:05 +01:00
Marcus Scholz 3a20a60f05 Remove obsolete ExplorerChangeForm. 2020-12-24 20:22:33 +01:00
Marcus Scholz 648264c9fc Remove obsoleted imports. 2020-12-24 20:13:06 +01:00
reverend dc79b9d05c #43 Lat/Long Check when place is submitted 2020-12-24 19:47:17 +01:00
Marcus Scholz a7c8848fd6 Allow user to provide his first and last name on registration. 2020-12-24 19:36:41 +01:00
reverend b845cc054a Small Tweaks 2020-12-24 19:25:37 +01:00
Marcus Scholz 07ea2f164c Name and E-Mail is only shown when populated in profile. 2020-12-24 19:13:55 +01:00
Marcus Scholz b0396f5223 Added bio and email link to profile template. 2020-12-24 19:04:04 +01:00
Marcus Scholz 88bffbef8e Added Explorer bio / description field. 2020-12-24 18:53:30 +01:00
Marcus Scholz 2022a924c4 Added output of profile image to profile_page. 2020-12-24 18:30:29 +01:00
Marcus Scholz d5827b2006 Fixed filename generation. 2020-12-24 18:14:40 +01:00
Marcus Scholz a9013d9673 Pulled favorite_places out of explorer instance. 2020-12-24 18:03:31 +01:00
Marcus Scholz 0c38ca9a15 Revert changes, as it was redundant. 2020-12-24 18:03:07 +01:00
Marcus Scholz 734d09df90 Add favorite_places to user profile page. 2020-12-24 17:59:05 +01:00
Marcus Scholz e601b9bf6b Merge commit '6f6bd6376d1ef2410a728cff2e9b883560c7f5c1' into feature/30-user-profile-fields 2020-12-24 17:34:09 +01:00
Marcus Scholz 6f6bd6376d Merge branch 'develop' of mowoe.com:reverend/lostplaces-backend into develop 2020-12-24 17:33:02 +01:00
reverend dc2a703c39 More fuckery 2020-12-24 17:27:48 +01:00
reverend 063777ece4 Merge branch '27-Favorite-System' into develop 2020-12-24 17:27:20 +01:00
reverend 4675e5814f Indention and stupid mistakes fix 2020-12-24 17:26:07 +01:00
Marcus Scholz 35e0f912fe Add profile_pic 2020-12-24 17:24:02 +01:00
Marcus Scholz 07fe1bc3ca Rename place_image_path function. 2020-12-24 17:23:20 +01:00
reverend 4a43a4bf37 typo 2020-12-24 16:43:43 +01:00
reverend 61cf148417 Displaying favorite icon on detail page 2020-12-24 16:43:33 +01:00
reverend d547ee9db3 favorite partial 2020-12-24 16:43:14 +01:00
reverend c7b699f615 Changed link location in place teaser 2020-12-24 16:43:01 +01:00
reverend 86f95a5dd0 New icon 2020-12-24 16:42:34 +01:00
reverend 916c4b80f7 Filed not required in django admin 2020-12-24 16:42:27 +01:00
reverend b31dc9fc5f Url name changed 2020-12-24 16:41:30 +01:00
reverend 8f048369bf Favorite/Unfavorite Views 2020-12-24 15:56:33 +01:00
reverend f974469996 formatting 2020-12-24 15:56:02 +01:00
reverend dbbd7b0802 rename migrationfile 2020-12-24 15:55:37 +01:00
Marcus Scholz d04e986419 Added display of name and e-mail. 2020-12-24 15:33:46 +01:00
Marcus Scholz cbbda88850 Remove debug output. 2020-12-24 15:13:40 +01:00
Marcus Scholz 981c440ce3 Fix voucher class description 2020-12-24 15:13:31 +01:00
Marcus Scholz c7368f5c44 Merge commit '20dd880a11a008ba95cd5aedce59590445430831' into develop 2020-12-24 14:57:09 +01:00
reverend abca946883 Model for favorite system 2020-12-24 14:48:11 +01:00
reverend 196fb02436 Release 2020-12-19 15:31:29 +01:00
reverend 9be993d9ba New Migrations for release 2020-12-19 15:31:22 +01:00
reverend 20dd880a11 Indention Error 2020-12-19 15:31:13 +01:00
reverend 946c3091c0 Typo "fix" 2020-12-19 15:31:04 +01:00
reverend 4bacd1a28d Recopied migration files 2020-12-19 14:47:59 +01:00
reverend 086789aa88 delete miration for release 2020-12-19 14:35:20 +01:00
reverend 3c5b447d4c New CSS 2020-11-29 19:23:44 +01:00
reverend cfbb876d2c #41 2020-11-29 19:23:39 +01:00
reverend 4e0bfef483 Incorporating Profile View into Project 2020-11-29 19:23:22 +01:00
reverend ccdb49c8ea Profile View 2020-11-29 19:22:55 +01:00
reverend 90dd281f7c Common functionalities 2020-11-29 19:22:38 +01:00
reverend d9df6e67a8 Hassling with migrations 2020-11-29 19:22:27 +01:00
reverend cd20e730ba Merge branch 'master' into develop 2020-11-27 07:58:53 +01:00
reverend c613d15e89 Updated Readme 2020-11-27 07:57:56 +01:00
reverend 2380398fa9 #36 and #37 Place Teaser 2020-10-12 20:57:04 +02:00
Marcus Scholz 4c5b9c7648 Dumped a nice missing-image image. Needs resizing and logic. 2020-10-11 23:08:14 +02:00
Marcus Scholz 91a3f3171d Merge branch 'feature/localization' into develop 2020-10-11 21:57:30 +02:00
Marcus Scholz 01f7dad37c Translated Model fields - primarily for backend. 2020-10-11 21:56:14 +02:00
Marcus Scholz 2bfdf5c172 Translated place deletion question with blrocktrans in a more natural way. 2020-10-11 21:55:38 +02:00
Marcus Scholz 15f6a30cd6 Streamlined translations ... again :P 2020-10-11 21:27:27 +02:00
Marcus Scholz 812c921a42 Merge commit 'dafe7eee3489e3a7c17b6560fc2aa09648773ecd' into feature/localization 2020-10-11 17:20:53 +02:00
Marcus Scholz dafe7eee34 Deleted mishap. 2020-10-11 09:47:34 +02:00
Marcus Scholz 7943537276 Translated an additional bunch of messages. 2020-10-11 07:50:15 +02:00
Marcus Scholz 62c1c84bb2 Minor code styling issue. 2020-10-11 07:49:50 +02:00
Marcus Scholz df36fd8ed0 Fixed the fixes' translation ;-) 2020-10-11 07:15:33 +02:00
Marcus Scholz 8713ed587d Small indentation fix. 2020-10-11 07:13:16 +02:00
Marcus Scholz 7271ea2cd9 Merge branch 'feature/localization' into develop 2020-10-11 07:09:59 +02:00
Marcus Scholz dff2e67991 Ops. Forgot one file. 2020-10-11 07:05:17 +02:00
Marcus Scholz 65880d1472 Renamed migration file with typo. 2020-10-11 07:04:32 +02:00
Marcus Scholz 326e34a4b8 Fixed i18n to invalidate decimal geocoords. 2020-10-11 06:55:12 +02:00
Marcus Scholz 3a213c87b5 Added a German Urbex codec. 2020-10-11 06:44:06 +02:00
Marcus Scholz 1b197b2e12 Added query for German language to FlatView. 2020-10-11 06:15:40 +02:00
Marcus Scholz 092378b24a Rename localized flat pages to include langcode. 2020-10-11 06:14:55 +02:00
Marcus Scholz 561c70668d Merge remote-tracking branch 'origin/develop' into develop 2020-10-11 02:46:16 +02:00
Marcus Scholz cb15789b95 Several typos. 2020-10-11 02:26:58 +02:00
Marcus Scholz dd07cbd57d Translated photoalbum model fields. 2020-10-11 02:23:51 +02:00
Marcus Scholz 52f9638d74 Translated model fields. 2020-10-11 02:07:14 +02:00
Marcus Scholz e52c3f4d4b Translated voucher messages, added filename help_text. 2020-10-11 01:39:38 +02:00
Marcus Scholz bac61d5cdc Translated permission_denied_message. 2020-10-11 01:12:52 +02:00
Marcus Scholz 2d6ee4aef5 Translated place update button. 2020-10-11 00:37:43 +02:00
Marcus Scholz 475a255851 Translated Submit and Create buttons. 2020-10-11 00:26:10 +02:00
Marcus Scholz f95c7973d7 Translated home_unauth texts. 2020-10-11 00:13:33 +02:00
Marcus Scholz aad31c2fa7 Changed and translated "Made by" in footer. 2020-10-10 23:49:30 +02:00
Marcus Scholz 3fa6170f0c Use shorter trans tag instead of translate. 2020-10-10 23:46:26 +02:00
Marcus Scholz f73b264a2a Added blocktranslate tags to unauth_home. 2020-10-10 23:43:59 +02:00
Marcus Scholz e91e8c8894 Translated some footer text. 2020-10-10 23:40:58 +02:00
Marcus Scholz eea01cd569 Translated Delete action via variable. 2020-10-10 23:40:21 +02:00
reverend 4e366d94c9 Fixing Error on sign up 2020-10-06 22:53:35 +02:00
Marcus Scholz da60d81e90 Addes help_texts and translations. 2020-10-06 17:01:29 +02:00
Marcus Scholz 2e73cb92d4 Fixed typo. Added those translations. 2020-10-05 20:31:13 +02:00
reverend 773390b09f Moved files so only the app is packed 2020-10-04 23:23:02 +02:00
reverend ac0121d96e removed old config 2020-10-04 23:22:53 +02:00
reverend a0c4f2cad3 Merge branch 'develop' into master 2020-10-04 22:19:01 +02:00
reverend 86fbee4116 Merge from master 2020-10-04 22:12:53 +02:00
reverend ab3ecae54b Voucher is_valid property 2020-10-04 22:12:44 +02:00
reverend ae915681ac Testing is_expired 2020-10-04 22:12:24 +02:00
reverend cfbe54a4e5 Making expireable a abstract model 2020-10-04 22:11:37 +02:00
Marcus Scholz a976b59732 Hotfix. 2020-10-04 21:58:23 +02:00
Marcus Scholz d6006b17d9 Fuzzy prevented translations from working. Fixed. 2020-10-04 21:56:57 +02:00
Marcus Scholz c911f7958a Translated pagination. 2020-10-04 21:50:19 +02:00
Marcus Scholz f592aba75d Enabled available translations in settings.py. Honors Browser's preference. 2020-10-04 21:19:05 +02:00
Marcus Scholz 190eb5eef7 Makemessages and last translations. 2020-10-04 21:02:05 +02:00
Marcus Scholz 979900ab07 updated .gitignore, minor fix. 2020-10-04 19:00:18 +02:00
reverend 66bd9f648b Merge branch 'develop' into master 2020-10-04 15:43:41 +02:00
reverend 76b514e1e6 #40 Hotfix Error when signing up 2020-10-04 15:42:06 +02:00
Marcus Scholz b758d53a63 Fixed early load of i18n. 2020-10-03 15:22:11 +02:00
reverend dabec5185f Merge branch 'feature/localization' of mowoe.com:reverend/lostplaces-backend into feature/localization 2020-10-01 23:11:27 +02:00
reverend c189183e72 More translations 2020-10-01 23:11:25 +02:00
Marcus Scholz 60ad323e7a Added translation tags. 2020-10-01 23:05:34 +02:00
reverend 2d2e356f1c Merge branch 'feature/localization' of mowoe.com:reverend/lostplaces-backend into feature/localization 2020-10-01 22:59:05 +02:00
reverend 710663b490 Loading tag 2020-10-01 22:58:06 +02:00
Marcus Scholz 24c2ac8347 Added translation tags. 2020-10-01 22:56:44 +02:00
reverend e0a0fa29d2 Generated message file 2020-10-01 22:10:48 +02:00
reverend 53817e9dc4 Loading Middleware 2020-10-01 22:10:38 +02:00
reverend 556931d2b1 Defining Strings to be translated 2020-10-01 22:10:31 +02:00
reverend 485eb7b886 Bumping version 2020-10-01 22:06:12 +02:00
reverend a2004bd789 #24 Ordering of places in list 2020-09-29 21:41:36 +02:00
Marcus Scholz e32b3f6595 Merge branch 'develop' of mowoe.com:reverend/lostplaces-backend into develop 2020-09-29 21:28:53 +02:00
Marcus Scholz 12f60bcfdf Added can_modify_place_asset template tag. 2020-09-29 20:40:46 +02:00
reverend b3b8ee3104 Styling fixes 2020-09-29 20:40:41 +02:00
reverend 9613f553e9 #19 OSM-Map Styling 2020-09-29 20:21:27 +02:00
Marcus Scholz 1a8a7cc4f0 Merge branch 'feature/submit_cancel_partial' into develop 2020-09-28 22:14:42 +02:00
Marcus Scholz 702ebd9137 Implanted submit/cancel partial into templates. 2020-09-28 22:12:39 +02:00
Marcus Scholz aa3922da50 Added custom button text variable. 2020-09-28 22:10:07 +02:00
Marcus Scholz d6c609d107 Added submit/cancel partial. Cancel redirects to referror or home. 2020-09-28 21:54:09 +02:00
Marcus Scholz 61566714a3 Merge branch 'develop' of mowoe.com:reverend/lostplaces-backend into develop 2020-09-28 21:00:20 +02:00
Marcus Scholz f4ae5c9f77 Merge branch 'temp/migration' into develop 2020-09-28 21:00:06 +02:00
Marcus Scholz cfe3d222e6 Added a few last tags to DB. 2020-09-28 20:59:10 +02:00
Marcus Scholz e0d6d81907 Adapted testdata doc. 2020-09-28 20:51:41 +02:00
Marcus Scholz 5e8e865a99 New testdata. Changed geo coords. 2020-09-28 20:48:51 +02:00
Marcus Scholz 3061540396 Fuck me hard, git. 2020-09-28 20:40:09 +02:00
Marcus Scholz bb119e8636 Fresh and clean initial migration. 2020-09-28 20:30:41 +02:00
Marcus Scholz 14a98deff3 delete testdata. 2020-09-28 20:09:17 +02:00
Marcus Scholz 4919c90ae8 Completely new and fresh initial migration. 2020-09-28 20:05:30 +02:00
Marcus Scholz 5c47587189 Pruned ALL THE SHIT. 2020-09-28 20:05:01 +02:00
Marcus Scholz 3223637471 dirty-save 2020-09-28 19:21:09 +02:00
reverend 389e3eac43 Typos 2020-09-27 23:58:25 +02:00
reverend 302e8bb994 More Documentation 2020-09-27 23:56:45 +02:00
Marcus Scholz 992f8a7b37 Moved Delete and Alter after datamigration. 2020-09-27 21:01:11 +02:00
Marcus Scholz c8c3852323 Added basic (empty) 3-way migration. 2020-09-27 20:34:39 +02:00
Marcus Scholz 8d9ab8b088 Add migrations back into repo - preparation for release. 2020-09-27 20:33:56 +02:00
reverend 45185b9236 Recent css 2020-09-27 17:13:15 +02:00
reverend 5f33ec5824 Deletion of place images 2020-09-26 16:08:56 +02:00
reverend e217d3254e Small Teaak 2020-09-26 16:08:47 +02:00
reverend 263416a401 Abstraction for PlaceImageCreation (multiple images) 2020-09-26 16:08:37 +02:00
reverend b4bd86ed44 View for submitting additionale place images 2020-09-26 09:48:06 +02:00
reverend 277cac323e CSS for adding and deleting images 2020-09-26 09:47:34 +02:00
reverend 5f304b91f3 Squashed commit of the following:
commit 0d62e72d72922a84e41c9f2cc21977b794784d1c
Merge: 79fee63 85f2a81
Author: reverend <reverend@reverend2048.de>
Date:   Tue Sep 22 21:55:18 2020 +0200

    Merge branch 'develop' into refactor/models

commit 79fee631d7ac28509067ecdd74078f1a2f6e0be2
Author: reverend <reverend@reverend2048.de>
Date:   Tue Sep 22 21:54:32 2020 +0200

    Updating references for related name

commit 8e07e79df2de2601f2e2eadfdd37eb7c719c51b0
Author: reverend <reverend@reverend2048.de>
Date:   Tue Sep 22 21:53:31 2020 +0200

    Generating of related names fix

commit 5fd804f37a805ae4707e13c3d941bdde3660afea
Merge: 8cc1d3e 3b526c9
Author: reverend <reverend@reverend2048.de>
Date:   Tue Sep 22 21:01:48 2020 +0200

    Merge branch 'develop' into refactor/models

commit 8cc1d3e690211dba6451e86569f00078b23e0621
Author: reverend <reverend@reverend2048.de>
Date:   Tue Sep 22 20:21:08 2020 +0200

    Tests

commit 7c0591e5397f892b1f6fb80725a693c21f90468a
Author: reverend <reverend@reverend2048.de>
Date:   Fri Sep 18 23:53:39 2020 +0200

    Testing PlaceAsset

commit 2e7b49ad1a15173565c81e7eb8bb3f35b9f622a6
Author: reverend <reverend@reverend2048.de>
Date:   Fri Sep 18 22:25:08 2020 +0200

    Restructuring models

commit eb7d03b08b326f9115e70d0fd9ed5d0fc229a362
Author: reverend <reverend@reverend2048.de>
Date:   Fri Sep 18 22:01:54 2020 +0200

    Abstract class Expireable

commit 2b51e741bb5734c5a578beeadef7819fe58b2223
Author: reverend <reverend@reverend2048.de>
Date:   Fri Sep 18 21:54:07 2020 +0200

    Abstract Model for PlaceAsset (i.e. Photoalbums)
2020-09-22 21:56:51 +02:00
Marcus Scholz 85f2a81ebb Merge branch 'develop' of mowoe.com:reverend/lostplaces-backend into develop 2020-09-22 20:49:00 +02:00
Marcus Scholz 8de23a3f3b Test if linked place matches. 2020-09-22 20:48:56 +02:00
reverend 3b526c9c6f Merge branch 'develop' of mowoe.com:reverend/lostplaces-backend into develop 2020-09-22 20:10:06 +02:00
reverend 516e7a04ad More documentation 2020-09-22 20:10:03 +02:00
Marcus Scholz 84f13ced80 Obsoleted file with info now in Readme.md 2020-09-22 19:43:32 +02:00
Marcus Scholz dcd92f7d2a Imported from frontend with changed file / fontnames. 2020-09-22 19:41:28 +02:00
Marcus Scholz 2a944eeefe Updated fonts. 2020-09-22 19:41:04 +02:00
Marcus Scholz dc93539e23 Added a list of included ressources. 2020-09-22 19:40:48 +02:00
Marcus Scholz dd58c76aba Fix #13 by allowing map zoom only on focus. 2020-09-22 18:13:42 +02:00
Marcus Scholz 106ef6dac8 Updated OpenLayers to 6.4.3 - incl. source hint. 2020-09-22 13:07:30 +02:00
Marcus Scholz 2bc99c78c2 Translated headings to English. 2020-09-22 12:51:08 +02:00
Marcus Scholz 0185c13a95 New testdata dump with 11 places. 2020-09-21 21:37:45 +02:00
Marcus Scholz 9632040ade Typos and missing docstrings. 2020-09-21 21:37:28 +02:00
Marcus Scholz 85a34b20f9 Added additional tests for album links. 2020-09-20 02:19:05 +02:00
Marcus Scholz e25f3da5a5 Fixed syntax error, that broke pipenv (update) 2020-09-19 23:31:25 +02:00
Marcus Scholz 4c9234d07a Text formatting. 2020-09-19 23:29:39 +02:00
Marcus Scholz f5853f7777 Added python docstrings. 2020-09-19 22:50:07 +02:00
Marcus Scholz eb7fe88d59 Renamed PlaceImageCreateForm to PlaceImageForm. 2020-09-18 23:50:25 +02:00
reverend 2a3ee3de8d #9 Using morge 404 2020-09-18 23:32:52 +02:00
Marcus Scholz 00ab65d648 Added working tests. 2020-09-18 23:02:59 +02:00
Marcus Scholz 79854f3fa1 Basic fist tests for PhotoAlbum model. 2020-09-18 22:39:18 +02:00
Marcus Scholz 618a152f23 Switched to timezone-aware now() function. 2020-09-18 22:04:19 +02:00
Marcus Scholz ce91a19068 Merge commit '17b531e181e691055797ec95a030c399f4dbcb8f' into develop 2020-09-18 21:26:55 +02:00
Marcus Scholz 17b531e181 Removed __str__ repr of Voucher and PlaceImage. 2020-09-18 21:26:05 +02:00
Marcus Scholz 222c97d63c Added voucher validity boolean icon display. 2020-09-18 21:19:31 +02:00
Marcus Scholz 6a1229a4ba Added valid column to VouchersAdmin. 2020-09-18 21:03:05 +02:00
Marcus Scholz 2bff4db1d7 Added Voucher expiration check in form using model property. 2020-09-18 21:02:45 +02:00
Marcus Scholz a3b123a207 Added valid property to VoucherModel. 2020-09-18 21:02:07 +02:00
Marcus Scholz e698f3b224 Added VouchersAdmin and PlaceImagesAdmin. 2020-09-18 20:40:58 +02:00
Marcus Scholz c66baaa765 Simplified PlaceImage __str__ repr. 2020-09-18 20:37:54 +02:00
reverend 815be3126e Issue #16 Tag Suggestion 2020-09-18 20:35:01 +02:00
Marcus Scholz 715e953182 Changed __str__ repr of Vouchers. 2020-09-18 20:30:25 +02:00
Marcus Scholz 86915f6ec5 Added list display of Places and PhotoAlbums admin pages. 2020-09-18 20:21:30 +02:00
Marcus Scholz 30b42de86f Delete PlaceImage files including thumbnails on deletion. 2020-09-18 13:40:54 +02:00
Marcus Scholz 21217b067f Add comments and relocate thumbnails, set quality. 2020-09-18 10:47:41 +02:00
Marcus Scholz 9b160d2df0 Sharpen thumbnails. 2020-09-18 10:47:16 +02:00
Marcus Scholz 74a9ee4f39 Resize original images, name files with placename in filename, sharpen. 2020-09-18 10:47:00 +02:00
Marcus Scholz b0e775d299 Removed session data from testdata dump. 2020-09-17 22:21:25 +02:00
Marcus Scholz d6b82f1556 Fixed missing "latest locations" on Home when logged in. 2020-09-17 22:02:37 +02:00
Marcus Scholz 3f642daf89 Added first sample testdata + doc doc hints. 2020-09-17 21:27:19 +02:00
Marcus Scholz 858cfe1d3c minor settings 2020-09-17 17:06:44 +02:00
Marcus Scholz 943d647a47 Added basic setup.cfg with source dir for coverage. 2020-09-17 16:14:47 +02:00
reverend d96cf9470a Developer Documentatino for models 2020-09-15 21:07:53 +02:00
Marcus Scholz c8b3cff5a6 Updated Readme according to change of name and user model. 2020-09-14 17:37:21 +02:00
reverend 547179b0ca Squashed commit of the following:
commit 97b044cafb7f17f23b3b1beedcf70af209a60ddc
Author: reverend <reverend@reverend2048.de>
Date:   Mon Sep 14 17:25:40 2020 +0200

    Updating gitignore

commit 4891d80486e1f95db8ae66385c7c97426a3ca1a4
Author: reverend <reverend@reverend2048.de>
Date:   Mon Sep 14 17:25:20 2020 +0200

    Updating Readme

commit f05c43abbdc7eb30896ad6d10fe80fd6483338d9
Author: reverend <reverend@reverend2048.de>
Date:   Mon Sep 14 17:23:30 2020 +0200

    Renaming Module

commit fd5ad2ee9f8cbacd565da45b257928192ffc651c
Author: reverend <reverend@reverend2048.de>
Date:   Mon Sep 14 17:23:16 2020 +0200

    Renaming module references

commit 828a0dd5dd73723b84b77908497903ed26b6966b
Author: reverend <reverend@reverend2048.de>
Date:   Mon Sep 14 17:21:20 2020 +0200

    Renaming Project
2020-09-14 17:26:17 +02:00
reverend 0765f6606f Pipenv scripts and not pinning python version 2020-09-14 15:29:26 +02:00
reverend 12881d9345 Renaming MapablePoint 2020-09-14 15:18:21 +02:00
reverend 79ed029db0 Rephrasing 2020-09-14 15:16:31 +02:00
reverend 1a8da002cf Formatting 2020-09-13 20:39:32 +02:00
reverend c828d04f05 Mixins for testing abstract model/partials in views 2020-09-13 20:27:05 +02:00
reverend f919fe30fa Renaming map config 2020-09-13 20:15:49 +02:00
reverend b3db6643b9 Refactoring 2020-09-13 19:43:47 +02:00
reverend cea3a909b5 Using abstract modls 2020-09-13 19:29:30 +02:00
reverend b52d96a55e More and better test failure messages 2020-09-13 19:17:04 +02:00
reverend 1fb71a172e Refactoring 2020-09-13 19:12:32 +02:00
reverend 27520c7ca4 Refactored ModelTestCaseMixin 2020-09-13 18:37:21 +02:00
reverend af14cce3f8 Minor code restructuring 2020-09-13 15:49:15 +02:00
reverend 75bcc91037 Refactoring places images related name 2020-09-13 14:39:21 +02:00
reverend c78ff60231 Refactoring ModelTestCase 2020-09-13 13:31:41 +02:00
reverend 09eb8794b8 Refactoring test_float_field 2020-09-13 13:30:47 +02:00
reverend 470e54da8d Refactoring test_char_field 2020-09-13 13:30:11 +02:00
reverend 19299598c3 Refactoring test_field 2020-09-13 13:29:27 +02:00
reverend f1c51ab8a7 Testing messages 2020-09-13 13:28:22 +02:00
reverend b77c5d1d7f Comments and refactoring viewtestmixin 2020-09-13 12:49:26 +02:00
reverend 05481fc0c8 Refactoring _has_context_key 2020-09-13 12:41:31 +02:00
reverend 6b00452830 Refactoring 2020-09-13 12:39:46 +02:00
reverend 7e4c5dcf24 Adding more methods to viewtestcase 2020-09-13 12:39:02 +02:00
reverend c0f30e56f7 Small tweak 2020-09-13 11:02:53 +02:00
reverend 9852646fff Renaming IsPlaceSubmitter 2020-09-13 10:57:53 +02:00
reverend c2d678847e Renaming IsAuthenticated 2020-09-13 10:56:18 +02:00
reverend e77edf18ac Testing Abstract classes 2020-09-13 10:27:01 +02:00
reverend 3780aa6cf1 Abtract classes 2020-09-12 12:24:27 +02:00
reverend 21124ec2ad adapting list views 2020-09-12 12:02:25 +02:00
reverend 0ee5fc59d3 Adapting tests 2020-09-12 12:02:17 +02:00
reverend b8dfef691e Fixing bug; Place did not show up on map 2020-09-12 11:58:45 +02:00
reverend a1886b0b60 Adapting home view 2020-09-12 11:47:42 +02:00
reverend e1002b5315 Adapting place detail view 2020-09-12 11:42:31 +02:00
reverend fed90d4f7b Refactoring osm map 2020-09-12 11:42:18 +02:00
reverend dcfb329c5a Adapted template 2020-09-12 11:35:30 +02:00
reverend b8a21a8baa Changed average_latlon 2020-09-12 11:34:49 +02:00
reverend 7f73035b02 Refactoring tagging 2020-09-12 11:24:16 +02:00
reverend 317437fedc Testing PlaceListView 2020-09-12 11:02:39 +02:00
reverend 26286984c2 Base functions for testing views 2020-09-12 11:02:23 +02:00
reverend 9ae31c0146 Removing obsolote code 2020-09-12 11:02:01 +02:00
reverend 87fd8fa96f Small fix 2020-09-12 11:01:34 +02:00
reverend c3401e732f Removed obosolete code 2020-09-12 11:01:24 +02:00
reverend 4ee7373b3f Testing Placeimage file change 2020-09-12 08:48:53 +02:00
reverend 64c0c5f8e6 Setting Up Test Data mor in a Unit way 2020-09-12 08:39:06 +02:00
reverend 18a597c726 Merge branch 'develop' into testing 2020-09-12 08:38:37 +02:00
Leonhard Strohmidel baca596603 sync 2020-09-11 23:07:19 +02:00
Marcus Scholz d993387216 Fixed text repr of Explorer model due to user model change. 2020-09-11 22:43:03 +02:00
Marcus Scholz aed2856df3 Made the test timezone aware, DateTimeFiled(auto_now_add) already was. 2020-09-11 22:22:03 +02:00
Marcus Scholz c78858c152 Changed class attibutes to match test expectation. 2020-09-11 22:03:20 +02:00
Marcus Scholz f49581259e Typo in class name. 2020-09-11 19:32:07 +02:00
Marcus Scholz f5bf642cd6 Ups, not for the settings file. 2020-09-11 19:23:13 +02:00
Marcus Scholz 7687acb366 Changed scope (?) of remaining local imports. 2020-09-11 19:15:39 +02:00
reverend e655e1598a Trying to test deletion, wip 2020-09-11 12:09:51 +02:00
reverend 64ed38332f Refactoring and testing __str__ 2020-09-11 12:09:34 +02:00
reverend d438303aec file for model tests 2020-09-11 12:08:43 +02:00
reverend 38b3736951 New Model tests 2020-09-11 12:08:27 +02:00
reverend 6be060ea40 Refactoring and more keywords to test 2020-09-11 12:08:15 +02:00
reverend 5c5756150f More dev dep 2020-09-11 12:07:57 +02:00
190 changed files with 62243 additions and 3205 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
DJANGO_SUPERUSER_PASSWORD=develop

11
.gitignore vendored
View File

@ -9,8 +9,8 @@ db.sqlite3
db.sqlite3-journal
db.sqlite3.bak
# user uploaded files
media
uploads
static_files
### Django.Python Stack ###
# Byte-compiled / optimized / DLL files
@ -65,12 +65,6 @@ coverage.xml
# Translations
*.mo
# Django stuff:
# exclude migrations from repository. These should be created locally, matching local DB requirements.
# lostplaces/manage.py makemigrations && lostplaces/manage.py migrate
lostplaces/lostplaces_app/migrations/
# pyenv
.python-version
@ -85,7 +79,6 @@ Pipfile.lock
__pypackages__/
# Environments
.env
.venv
env/
venv/
@ -97,4 +90,4 @@ venv.bak/
.vscode
# twine / pypi
.pypirc
.pypirc

42
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,42 @@
pipeline {
agent {
docker {
image 'kennethreitz/pipenv'
args '--user root --privileged'
}
}
stages {
stage('setup') {
steps {
script {
sh 'pipenv install'
sh 'pipenv install --dev'
sh 'pip install setuptools'
}
}
}
stage('migration') {
steps {
script {
sh 'pipenv run makemigrations'
}
}
}
stage('build') {
steps {
script {
sh 'pipenv run build'
}
}
}
}
post {
success {
archiveArtifacts artifacts: 'dist/*.whl', fingerprint: false
}
}
}

18
LICENSE
View File

@ -1,7 +1,19 @@
Copyright 2020 Reverend, Commander1024
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View File

@ -1,5 +0,0 @@
include LICENSE
include Readme.rst
include Pipfile
recursive-include lostplaces_app/static *
recursive-include lostplaces_app/templates *

22
Pipfile
View File

@ -10,7 +10,11 @@ autopep8 = "*"
pipenv = "*"
wheel = "*"
twine = "*"
pandoc ="*"
pandoc = "*"
pylint-django = "*"
setuptools = "*"
django-nose = "*"
invoke = "*"
[packages]
django = "*"
@ -18,6 +22,16 @@ easy-thumbnails = "*"
image = "*"
django-widget-tweaks = "*"
django-taggit = "*"
# Commented out to not explicitly specify Python 3 subversion.
# [requires]
# python_version = "3.8"
[scripts]
test = "django_lostplaces/manage.py test lostplaces"
server = "django_lostplaces/manage.py runserver --ipv6"
dbshell = "django_lostplaces/manage.py dbshell"
showmigrations = "django_lostplaces/manage.py showmigrations"
makemigrations = "django_lostplaces/manage.py makemigrations --no-input"
migrate = "django_lostplaces/manage.py migrate"
build = "django_lostplaces/setup.py bdist_wheel --universal"
createsuperuser = "django_lostplaces/manage.py createsuperuser --noinput --username admin --email admin@example.org"
createsuperuser_prompt = "django_lostplaces/manage.py createsuperuser"
quickstart = "invoke quickstart"
security = "pipenv check"

View File

@ -2,14 +2,17 @@
lostplaces-backend is a django (3.x) based webproject. It once wants to become a software which allows a group of urban explorers to manage, document and share the locations of lost places while not exposing too much / any information to the public.
The software is currently in early development status, neither scope, datalmodel(s) nor features are finalized yet. Therefore we would not recommend to download or install this piece of software anywhere - except your local django dev server.
The software is currently in early development status, neither scope, datamodel(s) nor features are finalized yet. Therefore we would not recommend to download or install this piece of software anywhere - except your local django dev server.
We value privacy as a whole, all ressources the frontend requires will be shipped with lostplace's distribution. We also try to minimze the use of JavaScript as far as we can and try to offer JS-less alternatives where we can.
We value privacy as a whole, all resources the frontend requires will be shipped with lostplace's distribution. We also try to minimize the use of JavaScript as far as we can and try to offer JS-less alternatives where we can.
## Contact
If you run into any issues, have any questions or If you are interested in this project in general, feel free to get in touch with us via [reverend@reverend2048.de](mailto:reverend@reverend2048.de), we do speak English and German.
## Features
- Manage lost places with lots of usefull information.
- Manage lost places with lots of useful information.
- OSM-Maps
- Sensitive information is not accesiable for anonymous (not logged in) users.
- Sensitive information is not accessible for anonymous (not logged in) users.
- User self registration using a voucher system, only people you invite can join your instance.
- Collaboration, every user can add informations like tags, photos and external links to your place.
@ -21,11 +24,18 @@ Right now it depends on the following non-core Python 3 libraries. These can be
* [image](https://github.com/francescortiz/image) Image cropping for django.
* [django-widget-tweaks](https://github.com/jazzband/django-widget-tweaks) Tweak the form field rendering in templates, not in python-level form definitions.
* [django-taggit](https://github.com/jazzband/django-taggit) A simpler approach to tagging with Django.
### Bundled Dependencies
We also leverage some other great OpenSource projects' code. We bundle those in the distribution to obsolete the need to pull those files from monitored CDNs.
* [OpenLayers](https://openlayers.org/) [6.4.3] OpenLayers makes it easy to put a dynamic map in any web page. It can display map tiles, vector data and markers loaded from any source.
* [Crimson Pro font](https://github.com/Fonthausen/CrimsonPro) [1.002] Crimson Pro is a serif typeface family: Contemporary, clear, classic and rounded/open.
* [Montserrat](https://github.com/JulietaUla/Montserrat) [7.210] A beautiful sans serif typeface.
# Installing a development instance
## Clone the repository
`git clone https://git.mowoe.com/reverend/lostplaces-backend.git`
`git clone https://git.commander1024.de/Commander1024/lostplaces-backend`
## Setting up a (pipenv) virtual environment for development
After having obtained the repository contents (either via .zip download or git clone), you can easily setup a [pipenv](https://docs.pipenv.org/) virtual environment. The repo provides a Pipfile for easy dependency management that does not mess with your system.
@ -34,10 +44,10 @@ After having obtained the repository contents (either via .zip download or git c
$ cd lostplaces-backend
$ pipenv install
$ pipenv shell
(lostplaces-backend) $ lostplaces/manage.py makemigrations
(lostplaces-backend) $ lostplaces/manage.py migrate
(lostplaces-backend) $ lostplaces/manage.py createsuperuser
(lostplaces-backend) $ lostplaces/manage.py runserver --ipv6
(lostplaces-backend) $ django_lostplaces/manage.py makemigrations
(lostplaces-backend) $ django_lostplaces/manage.py migrate
(lostplaces-backend) $ django_lostplaces/manage.py createsuperuser
(lostplaces-backend) $ django_lostplaces/manage.py runserver --ipv6
```
## Returning to the venv
@ -45,9 +55,9 @@ $ pipenv shell
$ cd lostplaces-backend
$ pipenv shell
(lostplaces-backend) $ pipenv update # If dependencies changed, or updates available
(lostplaces-backend) $ lostplaces/manage.py makemigrations # If datamodels changed
(lostplaces-backend) $ lostplaces/manage.py migrate # If datamodels changed
(lostplaces-backend) $ lostplaces/manage.py runserver --ipv6
(lostplaces-backend) $ django_lostplaces/manage.py makemigrations # If datamodels changed
(lostplaces-backend) $ django_lostplaces/manage.py migrate # If datamodels changed
(lostplaces-backend) $ django_lostplaces/manage.py runserver --ipv6
```
Visit: [admin](http://localhost:8000/admin) for administrative backend or
@ -55,6 +65,21 @@ Visit: [admin](http://localhost:8000/admin) for administrative backend or
Happy developing ;-)
# Pipenv Scripts
This project comes with a bunch of convinient scripts, like:
|Script|Description|
|---|---|
|test|Runs the tests|
|server|Starts a **development** server|
|dbshell|Opens a shell session in the database|
|showmigrations|Lists all Migrations|
|makemigrations|Creates a migration|
|migrate|Applies unapplied migrations|
|build|Builds this project into a wheel file|
|createsuperuser|Creates a superuser with the username **admin** and the password **develop**. This is for development and demo instances only!
|quickstart|Runs *migrate*, *createsuperuser* and *server*|
# Installing a productive instance
Currently there are two ways to deploy the lostplaces project:
@ -63,25 +88,27 @@ Currently there are two ways to deploy the lostplaces project:
## Cloning the repository
Essentially, this is the same as installing a development instance, but without the development server (manage.py runserver) and something powerfull (Apache, NGINX) instead. You have to configure the webserve to work with the *SGI Api respectivly, reference [django's guide for deployment](https://docs.djangoproject.com/en/3.1/howto/deployment/) for further information.
Essentially, this is the same as installing a development instance, but without the development server (manage.py runserver) and something powerful (Apache, NGINX) instead. You have to configure the webserver to work with the *SGI Api respectively, reference [django's guide for deployment](https://docs.djangoproject.com/en/3.1/howto/deployment/) for further information.
You also should setup a dedicated database server, the built-in SQLite file is not recommened for production use. Reference [django's guide for databases](https://docs.djangoproject.com/en/3.1/ref/databases/) for further information.
You also should setup a dedicated database server, the built-in SQLite file is not recommended for production use. Reference [django's guide for databases](https://docs.djangoproject.com/en/3.1/ref/databases/) for further information.
Before making the django instance public, you should tweak the config `settings.py`:
1. Change the secret key, the one found in the config is already public. Choose something secure (i.e. [this](https://duckduckgo.com/?q=password+generator+64)).
2. Turn off debug mode by setting `DEBUG = False`.
3. Tune the localization settings, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/i18n/).
Run `lostplaces/managy.py collectstatic` and you should be ready to go.
Run `django_lostplaces/managy.py collectstatic` and you should be ready to go.
## Installing the lostplaces_app to an existing django instance
## Installing lostplaces to an existing django instance
### Installing django and the lostplaces app
### Installing django and the django_lostplaces app
If you haven't already setup a django instance, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/install/).
After that, download the desired release (probably the latest one) [from the realeases page](https://git.mowoe.com/reverend/lostplaces-backend/releases) and install it using `pip install --user name-of-the-file.tar.gz`
Afterwards, either
- download the desired release [from the releases page](https://git.mowoe.com/reverend/lostplaces-backend/releases) and install it using `pip install --user name-of-the-file.tar.gz`
- or install the latest release using `pip install django-lostplaces`
*Note: You can run pip install without the --user flag, which will require root privileges and introduces potential security issues.*
@ -93,7 +120,7 @@ Now configure your `settings.py` as follows:
```python
INSTALLED_APPS = [
...
'lostplaces_app',
'django_lostplaces',
'easy_thumbnails',
'widget_tweaks',
'django_taggit'
@ -110,28 +137,22 @@ MEDIA_URL = '/uploads/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
```
3. Set the user model (this will be changed in the next release):
```python
AUTH_USER_MODEL = 'lostplaces_app.Explorer'
```
4. Set the URL's for login, for example:
3. Set the URL's for login, for example:
```python
LOGIN_URL = reverse_lazy('login')
LOGIN_REDIRECT_URL = reverse_lazy('lostplaces_home')
LOGOUT_REDIRECT_URL = reverse_lazy('lostplaces_home')
LOGIN_REDIRECT_URL = reverse_lazy('django_lostplaces_home')
LOGOUT_REDIRECT_URL = reverse_lazy('django_lostplaces_home')
```
### Configuring the URL's
In the `urls.py` configure the `urlpatter` like this:
In the `urls.py` configure the `urlpatterns` like this:
```python
urlpatterns = [
path('admin/', admin.site.urls),
path('signup/', SignUpView.as_view(), name='signup'), # If you want to use lostplaces' sign up view.
path('explorers/', include('django.contrib.auth.urls')), # You can change the 'explorers/' to whatever you desire.
path('', include('lostplaces_app.urls')), # In this configuration lostplaces will be at the top level of you website, change '' to 'lostplaces/', if you don't want this.
path('', include('django_lostplaces.urls')), # In this configuration django_lostplaces will be at the top level of you website, change '' to 'django_lostplaces/', if you don't want this.
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # So django can deliver user uploaded files.
```
@ -139,5 +160,7 @@ Before making the django instance public, you should tweak the config `settings.
1. Change the secret key, the one found in the config is already public. Choose something secure (i.e. [this](https://duckduckgo.com/?q=password+generator+64)).
2. Turn off debug mode by setting `DEBUG = False`.
3. Tune the localization settings, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/i18n/).
4. Set a new (random) SECRET_KEY in settings.py, e. g.: `base64 /dev/urandom | head -c50`
Run `lostplaces/managy.py collectstatic` you should be ready to go.
Run `django_lostplaces/manage.py collectstatic` you should be ready to go.

View File

@ -0,0 +1,6 @@
exclude
include LICENSE
include Readme.rst
include Pipfile
recursive-include lostplaces/static *
recursive-include lostplaces/templates *

View File

@ -14,6 +14,6 @@ import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lostplaces.settings')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_lostplaces.settings')
application = get_asgi_application()

View File

@ -18,6 +18,8 @@ https://docs.djangoproject.com/en/3.1/ref/settings/
import os
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@ -38,7 +40,7 @@ ALLOWED_HOSTS = ['localhost']
# Application definition
INSTALLED_APPS = [
'lostplaces_app',
'lostplaces',
'easy_thumbnails',
'widget_tweaks',
'taggit',
@ -47,7 +49,15 @@ INSTALLED_APPS = [
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles'
'django.contrib.staticfiles',
'django_nose'
]
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
NOSE_ARGS = [
'--with-coverage',
'--cover-package=lostplaces',
]
MIDDLEWARE = [
@ -58,9 +68,10 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware',
]
ROOT_URLCONF = 'lostplaces.urls'
ROOT_URLCONF = 'django_lostplaces.urls'
TEMPLATES = [
{
@ -78,7 +89,7 @@ TEMPLATES = [
},
]
WSGI_APPLICATION = 'lostplaces.wsgi.application'
WSGI_APPLICATION = 'django_lostplaces.wsgi.application'
# Database
@ -124,6 +135,11 @@ USE_L10N = True
USE_TZ = True
LANGUAGES = [
('de', _('German')),
('en', _('English')),
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
@ -131,9 +147,15 @@ USE_TZ = True
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
# Upload directory
MEDIA_URL = '/uploads/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
# Thumbnails
THUMBNAIL_MEDIA_ROOT = os.path.join(MEDIA_ROOT, 'thumbs/')
THUMBNAIL_MEDIA_URL = os.path.join(MEDIA_URL, 'thumbs/')
THUMBNAIL_QUALITY = 75
# Templates to use for authentication
LOGIN_URL = reverse_lazy('login')
LOGIN_REDIRECT_URL = reverse_lazy('lostplaces_home')

View File

@ -23,11 +23,11 @@ from django.conf.urls.static import static
from django.urls import path, include
from django.views.generic.base import TemplateView
from lostplaces_app.views import SignUpView
from lostplaces.views import SignUpView
urlpatterns = [
path('admin/', admin.site.urls),
path('signup/', SignUpView.as_view(), name='signup'),
path('explorers/', include('django.contrib.auth.urls')),
path('', include('lostplaces_app.urls')),
path('explorer/', include('django.contrib.auth.urls')),
path('', include('lostplaces.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -14,6 +14,6 @@ import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lostplaces.settings')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_lostplaces.settings')
application = get_wsgi_application()

View File

@ -0,0 +1,155 @@
# django lostplaces documentation for developer
Greetings,
this documentation is for anyone who wants to work with this projects codebase or is just curious about how it works.
## Models
The models contain an custom user profile, some abstract base models and the models holding the actual data for this project
### Explorer user profile
Location: `lostplaces.models.models.Explorer`
Import from: `lostplaces.models.Explorer`
#### Super Classes
- django's `models.Model`
The class `lostplaces.models.Explorer` is our custom user profile. It has an ForeignKey pointing at django's default user model instead of providing an entire custom user model. That way this django app does not conflict with any other app that brings it's own user model.
You can access the explorer profile by accessing the 'explorer' attribute of any user instance
```python
user.explorer
```
Currently the explorer profile is used by the abstract model 'Submittable' and has the following realated names/fiels:
- [places](###place) A list containing all (lost) places the user has submitted
- [placeimages](###placeimages) A list containing all images relating a place that a user has submitted
- [photoalbums](###photoalbums) A list of all photo albums a explorere has submitted
### Taggable
Location: `lostplaces.models.abstract_models.Taggable`
Import from: `lostplaces.models.Taggable`
#### Super Classes
- django's `models.Model`
The abstract model Taggable represents an model that is taggable. It depends on the django app [taggit](https://github.com/jazzband/django-taggit). It only consists of one field:
- `tag`: TaggableManager, allows the sub class to be tagged, blank=True allows the admin form to be submitted without any tags
### Mapable
Location: `lostplaces.models.abstract_models.Mapable`
Import from: `lostplaces.models.Mapable`
#### Super Classes
- django's `models.Model`
The abstract model Mapable represents an model that can be displayed on a map. It consists of tree attributes
`name`
Name of the object, displayed on the map, max length 50 characters
`latitude`
Latitude of the referenced location, -90 <= value <= 90
`longitude`
Longitude of the referenced location -180 <= value <= 180
A mapable model has to provide its own get_absolute_url, in order to provide a link when clicked.
### Submittable
Location: `lostplaces.models.abstract_models.Submittable`
Import from: `lostplaces.models.Submittable`
#### Super Classes
- django's `models.Model`
The abstract model Submittable represents an model that can be submitted by an user. It knows who submitted something and when:
`submitted_by`
Referencing the explorer profile, see [Explorer](##explorer-user-profile). If the explorer profile is deleted, this instance is kept (on_delete=models.SET_NULL). The related_name is set to the class name, lower case appending an s (%(class)ss)
`submitted_when`
When the object was submitted, automatically set by django (auto_now_add=True)
### Expireable
Location: `lostplaces.models.abstract_models.Expireable`
Import from: `lostplaces.models.Expireable`
#### Super Classes
- django's `models.Model`
This abstract model represents an object that can expire. It is currently used by the Voucher model. I consists of two fields:
`created_when`
The date the object was created, automatically set by django (auto_now_add=True)
`expires_when`
The date the object expires.
### Voucher
Locatoin: `lostplaces.models.Voucher`
Import from: `lostplaces.models.Voucher`
#### Super Classes
- django's `models.Model`
- [lostplaces.models.Expireable](###expireable)
A voucher code is needed to sign up using lostplaces sign up form. The model contains
`code`
The voucher code, max length 30 characters
`created_when`
When the voucher was created automatically set by django (auto_now_add=True)
`expires_when`
Till what date the voucher remains valid
### Place
Location: `lostplaces.models.place.Place`
Import from: `lostplaces.models.Place`
#### Super Classes
- django's `models.Model`
- [lostplaces.models.Submittable](###submittable)-
- [lostplaces.models.Taggable](###taggable)
- [lostlaces.models.Mapable]
The place model is the heart of this project. It stores all information about a place needed.
`location`
Human readable location description (town, village, street), max length 50 characters
`description`
Describing the place in detail
The place model uses these abstract super classes
- Submittable, see [Submittable](##submittable) for additional fields
- Taggable, see [Taggable](##taggable) for additional fields
- Mapable, see [Mapable](##mapable) for additional fields
The average_latlon function takes a list of places and returns the center point of all these places.
### PlaceAsset
Location: `lostplaces.models.PlaceAsset`
Import from: `lostplaces.models.place.PlaceAsset`
#### Super Classes
- django's `models.Model`
- [lostplaces.models.Submittable](###submittable)
A PlaceAsset is anything that belongs to a place. The PlaceImage model for exmpaple is a subclass of PlaceAsset. A PlaceAsset is supposed to be submittable by every user. Only the user who has submitted the asset, the place the asset belongs to or both can delete a asset.
An PlaceAsset has the following fields
`place`
The Place this PlaceAsset belongs to
The PlaceAsset model is a subclass of Submittable, see [Submittable](###submittable) for more details.
### External Link
Loacation: `lostplaces.models.external_link.ExternalLink`
Import From: `lostplaces.models.ExternalLink`
#### Super Classes
- django's `models.Model`
- [lostplaces.models.Submittable](###submittable)
- [lostplaces.models.PlaceAsset](###placeasset)
This model represents an URL to an external website. External Link is an PlaceAsset, see [above](###placeasset) for more details. External Link has to fields
`url`
the URL to the target
`label`
the label that is shown on the website
### PhotoAlbum
Loacation: `lostplaces.models.external_link.PhototAlbum`
Import From: `lostplaces.models.PhotoAlbum`
#### Super Classes
- django's `models.Model`
- [lostplaces.models.Submittable](###submittable)
- [lostplaces.models.PlaceAsset](###placeasset)
- [lostplaces.models.ExternalLink](###externallink)
A photo album is a link to an external site that is meant to contain photos of the place it is referenced in. It
does not have any fields, just the ones inherited from it's super class [ExternalLink](###externallink).

View File

@ -0,0 +1,12 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.conf import settings
settings.THUMBNAIL_ALIASES = {
'': {
'thumbnail': {'size': (300, 200), 'sharpen': True, 'crop': True, 'upscale': True},
'hero': {'size': (700, 466), 'sharpen': True, 'crop': True},
'large': {'size': (1920, 1920), 'sharpen': True, 'crop': False},
},
}

View File

@ -0,0 +1,38 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' Classes and modules for the administrative backend. '''
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.utils import timezone
from lostplaces.models import *
# Register your models here.
class VoucherAdmin(admin.ModelAdmin):
fields = ['code', 'expires_when', 'created_when']
readonly_fields = ['created_when']
list_display = ('__str__', 'code', 'created_when', 'expires_when', 'valid')
def valid(self, instance):
return timezone.now() <= instance.expires_when
valid.boolean = True
class PhotoAlbumsAdmin(admin.ModelAdmin):
list_display = ('label', 'place', 'url' )
class PlacesAdmin(admin.ModelAdmin):
list_display = ('name', 'submitted_by', 'submitted_when')
class PlaceImagesAdmin(admin.ModelAdmin):
list_display = ('__str__', 'place', 'submitted_by')
admin.site.register(Explorer)
admin.site.register(Voucher, VoucherAdmin)
admin.site.register(Place, PlacesAdmin)
admin.site.register(PlaceImage, PlaceImagesAdmin)
admin.site.register(PhotoAlbum, PhotoAlbumsAdmin)
admin.site.register(PlaceVoting)

View File

@ -0,0 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.apps import AppConfig
class LostplacesAppConfig(AppConfig):
default_auto_field = 'django.db.models.AutoField'
name = 'lostplaces'

View File

@ -0,0 +1,25 @@
from django.shortcuts import redirect
def get_all_subclasses(cls):
'''
Gets all subclasses recursively, does not contain
abstract classes
'''
subclass_list = []
for subclass in cls.__subclasses__():
if not subclass._meta.abstract:
subclass_list.append(subclass)
subclass_list += get_all_subclasses(subclass)
return subclass_list
def redirect_referer_or(request, url='/'):
'''
Returns a django redirect to the requests referer,
if there is no referer the redirect will poin to the given url
Default url is /
'''
referer = request.META.get('HTTP_REFERER')
if referer is not None:
return redirect(referer)
else:
return redirect(url)

View File

@ -0,0 +1,124 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' (web)forms that can be used elsewhere. '''
from django import forms
from django.db import models
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from lostplaces import widgets
from lostplaces.models import Place, PlaceImage, Voucher, Explorer
class SignupVoucherForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name')
voucher = forms.CharField(
max_length=30,
help_text=_('The Voucher you got from an administrator')
)
def is_valid(self):
super_result = super().is_valid()
submitted_voucher = self.cleaned_data.get('voucher')
try:
fetched_voucher = Voucher.objects.get(code=submitted_voucher)
except Voucher.DoesNotExist:
self.add_error('voucher', _('Invalid voucher'))
return False
if not fetched_voucher.valid:
self.add_error('voucher', _('Expired voucher'))
return False
fetched_voucher.delete()
return super_result
class ExplorerUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = [ 'username', 'first_name', 'last_name', 'email' ]
''' Hide password hint.'''
password = None
''' Display username, but display it non-editable and not required. '''
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].required = False
self.fields['username'].help_text = None
self.fields['username'].widget.attrs['disabled'] = 'disabled'
def clean_username(self):
# As shown in the above answer.
instance = getattr(self, 'instance', None)
if instance:
return instance.username
else:
return self.cleaned_data.get('username', None)
class ExplorerChangeForm(forms.ModelForm):
class Meta:
model = Explorer
fields = '__all__'
exclude = ['user', 'favorite_places', 'level']
class PlaceForm(forms.ModelForm):
class Meta:
model = Place
fields = '__all__'
exclude = ['submitted_by', 'level']
widgets = {
'hero': widgets.SelectContent()
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if 'instance' in kwargs:
self.fields['hero'].queryset = PlaceImage.objects.filter(place=kwargs['instance'])
self.fields['hero'].widget.attrs['item_template'] = 'partials/select_place_image_item.html'
latitude = forms.DecimalField(
widget=forms.NumberInput(attrs={'min':-90,'max': 90,'type': 'number', 'step': 'any'})
)
longitude = forms.DecimalField(
widget=forms.NumberInput(attrs={'min':-180,'max': 180,'type': 'number', 'step': 'any'})
)
class PlaceImageForm(forms.ModelForm):
class Meta:
model = PlaceImage
fields = ['filename']
widgets = {
'filename': forms.ClearableFileInput(attrs={'multiple': True})
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['filename'].required = False
class PlaceSetHeroForm(forms.ModelForm):
class Meta:
model = Place
fields = ['hero']
widgets = {
'hero': widgets.SelectContent()
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['hero'].queryset = PlaceImage.objects.filter(place=kwargs['instance'])
self.fields['hero'].widget.attrs['item_template'] = 'partials/select_place_image_item.html'
class TagSubmitForm(forms.Form):
tag_list = forms.CharField(
max_length=500,
required=False,
widget=forms.TextInput(attrs={'autocomplete':'off'})
)

View File

@ -0,0 +1,472 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Reverend <reverend@reverend2048.de>, 2020.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-12-25 16:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Commander1024 <commander@commander1024.de>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: de-DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: forms.py:19
msgid "The Voucher you got from an administrator"
msgstr "Der Einladungs-Code, den Dir ein Administrator gegeben hat"
#: forms.py:28
msgid "Invalid voucher"
msgstr "Ungültiger Voucher"
#: forms.py:32
msgid "Expired voucher"
msgstr "Abgelaufener Voucher"
#: models/abstract_models.py:29 templates/explorer/profile.html:31
msgid "Name"
msgstr "Name"
#: models/abstract_models.py:36
msgid "Latitude"
msgstr "Breitengrad"
#: models/abstract_models.py:37
msgid "Latitude in decimal format: e. g. 41.40338"
msgstr "Breitengrad in dezimaler Form: z. B. 51.95021"
#: models/abstract_models.py:44
msgid "Longitude"
msgstr "Längengrad"
#: models/abstract_models.py:45
msgid "Longitude in decimal format: e. g. 2.17403"
msgstr "Breitengrad in dezimaler Form: z. B. 7.4840155"
#: models/abstract_models.py:59
msgid "Submission date"
msgstr "Einreichungsdatum"
#: models/abstract_models.py:67
msgid "Submitter"
msgstr "Einreicher"
#: models/abstract_models.py:79
msgid "Creation date"
msgstr "Erstellungsdatum"
#: models/abstract_models.py:82
msgid "Expiration date"
msgstr "Ablaufdatum"
#: models/external_links.py:13
msgid "URL"
msgstr "Adresse (URL)"
#: models/external_links.py:17
msgid "link text"
msgstr "Linktext"
#: models/models.py:47
msgid "Biography"
msgstr "Beschreibung"
#: models/models.py:48
msgid "Describe yourself, your preferences, etc. in a few sentences."
msgstr "Beschreibe Dich selbst, Deine Vorlieben, usw. in ein paar Sätzen."
#: models/models.py:56
msgid "Profile image"
msgstr "Profilbild"
#: models/models.py:57
msgid "Optional profile image for display in Explorer profile"
msgstr "Optionales Profilbild zur Anzeige im Explorerprofil"
#: models/place.py:21
msgid "Location"
msgstr "Ort"
#: models/place.py:24
msgid ""
"Description of the place: e.g. how to get there, where to be careful, the "
"place's history..."
msgstr ""
"Beschreibung des Places: z. B. wie man hin kommt, wo man vorsichtig sein "
"sollte, seine Geschichte..."
#: models/place.py:25 models/place.py:84
msgid "Description"
msgstr "Beschreibung"
#: models/place.py:90
msgid "Filename(s)"
msgstr "Dateiname(n)"
#: models/place.py:91
msgid "Optional: One or more images to upload"
msgstr "Optional: Ein oder mehrere Bilder zum Hochladen"
#: templates/403.html:4
msgid "Forbidden"
msgstr "Nicht Erlaubt"
#: templates/403.html:14
msgid "You will be redirected in 5 seconds"
msgstr "Du wirst in 5 Sekunden weitergeleitet"
#: templates/403.html:14
msgid "Go Back"
msgstr "Zurück"
#: templates/explorer/profile.html:41
msgid "E-mail"
msgstr "E-Mail"
#: templates/explorer/profile.html:52
msgid "Joined"
msgstr "Beigetreten"
#: templates/explorer/profile.html:60
#, fuzzy
#| msgid "All Places"
msgid "Places"
msgstr "Alle Places"
#: templates/explorer/profile.html:68
msgid "Place assets"
msgstr ""
#: templates/explorer/profile.html:76
#, fuzzy
#| msgid "Edit Explorer profile"
msgid "Edit Profile"
msgstr "Explorerprofil bearbeiten"
#: templates/explorer/profile.html:87
msgid "Favorite places"
msgstr "Favoriten"
#: templates/explorer/profile.html:103
msgid "Places submitted by"
msgstr "Places hinzugefügt von"
#: templates/explorer/profile.html:118
msgid "Images submitted by"
msgstr "Bilder hinzugefügt von"
#: templates/explorer/profile.html:140
msgid "Photo albums submitted by"
msgstr "Fotoalben hinzugefügt von"
#: templates/explorer/profile_update.html:6
#: templates/explorer/profile_update.html:12
msgid "Edit Explorer profile"
msgstr "Explorerprofil bearbeiten"
#: templates/explorer/profile_update.html:48
#: templates/place/place_update.html:42
msgid "Update"
msgstr "Aktualisieren"
#: templates/global.html:32
msgid "Logout"
msgstr "Ausloggen"
#: templates/global.html:33
msgid "Profile"
msgstr "Profil"
#: templates/global.html:35
msgid "Admin"
msgstr "Admin"
#: templates/global.html:40 templates/registration/login.html:4
#: templates/registration/login.html:10 templates/registration/login.html:23
msgid "Login"
msgstr "Anmelden"
#: templates/global.html:41 templates/registration/login.html:29
#: templates/signup.html:6 templates/signup.html:12 templates/signup.html:49
msgid "Sign up"
msgstr "Registrieren"
#: templates/global.html:51 templates/home.html:10
msgid "Home"
msgstr "Startseite"
#: templates/global.html:52
msgid "UrBex Codex"
msgstr "UrBex Codex"
#: templates/global.html:57 templates/place/place_create.html:5
#: templates/place/place_create.html:10
msgid "Create place"
msgstr "Place erstellen"
#: templates/global.html:58
msgid "All places"
msgstr "Alle Places"
#: templates/home.html:20 templates/home_unauth.html:20
msgid "Explore the latest places"
msgstr "Neueste Places erkunden"
#: templates/home_unauth.html:11
msgid ""
"You can create, view and share your lost places with other members of this "
"site. You can upload photos, place links to your web galleries and "
"contribute your knowledge by tagging other places or commenting on them. You "
"will find detailed information on where these locations are, how to get "
"there and what to expect from them. This might even include detailed "
"information on the surroundings or the history of a lost place."
msgstr ""
"Du kannst Deine Lost Places erstellen, ansehen und mit anderen Mitgliedern "
"auf dieser Seite teilen. Du kannst Photos hochladen, Links zu Deinen Web-"
"Fotoalben setzen und Dein Wissen teilen indem Du andere Places mit Tags "
"versiehst oder sie kommentierst. Du wirst detaillierte Informationen dazu "
"finden, wo diese Orte sind, wie Du dorthin gelangst und was Dich dort "
"erwartet. Dies können sogar detaillierte Informationen zur Umgebung oder der "
"Geschichte eines Lost Places sein."
#: templates/home_unauth.html:15
#, python-format
msgid ""
"Since vandalism is a growing problem these days, no sensitive information is "
"available to the public. You have to <a class=\"LP-Link\" href="
"\"%(signup_url)s\"><span class=\"LP-Link__Text\">sign up</span></a> with a "
"voucher code as an invitation to join this community. Only admins can create "
"these codes. Usually you are given a code when we know you in real life in "
"person and when we trust you. A request from an unknown person will most "
"probably be denied."
msgstr ""
"Weil Vandalismus dieser Tage ein wachsendes Problem ist, sind keine "
"sensiblen Informationen öffentlich verfügbar. Du musst Dich mit einem "
"Voucher-Code als Einladung <a class=\"LP-Link\" href=\"%(signup_url)s"
"\"><span class=\"LP-Link__Text\">registrieren</span></a>um dieser Community "
"beizutreten. Nur Administratoren können diese Codes erstellen. Üblicherweise "
"bekommst Du einen Code, wenn wir Dich im echten Leben kennen und Dir "
"vertrauen. Eine Anfrage von einer unbekannten Person wird "
"höchstwahrscheinlich abgelehnt."
#: templates/partials/form/submit.html:3
msgid "Submit"
msgstr "Abschicken"
#: templates/partials/form/submit.html:7
msgid "Cancel"
msgstr "Abbrechen"
#: templates/partials/icons/place_favorite.html:6
msgid "Remove from favorites"
msgstr "Aus den Favoriten entfernen"
#: templates/partials/icons/place_favorite.html:10
msgid "Save as favorite"
msgstr "In den Favoriten speichern"
#: templates/partials/nav/footer.html:64
msgid "Made by"
msgstr "Erstellt von"
#: templates/partials/nav/footer.html:65
msgid "and"
msgstr "und"
#: templates/partials/nav/footer.html:68
msgid "Privacy Policy"
msgstr "Datenschutzerklärung"
#: templates/partials/nav/footer.html:70
msgid "Imprint"
msgstr "Impressum"
#: templates/partials/nav/pagination.html:11
#: templates/partials/nav/pagination.html:24
msgid "First"
msgstr "Erste"
#: templates/partials/nav/pagination.html:17
#: templates/partials/nav/pagination.html:30
msgid "Previous"
msgstr "Vorherige"
#: templates/partials/nav/pagination.html:50
#: templates/partials/nav/pagination.html:63
msgid "Next"
msgstr "Nächste"
#: templates/partials/nav/pagination.html:56
#: templates/partials/nav/pagination.html:68
msgid "Last"
msgstr "Letzte"
#: templates/partials/tagging.html:30 templates/partials/tagging.html:34
msgid "Add tags"
msgstr "Tags hinzufügen"
#: templates/partials/welcome.html:4
msgid "Start"
msgstr "Start"
#: templates/partials/welcome.html:8
msgid "Welcome to our Urban Exploration community catalogue,"
msgstr "Willkommen auf unserem Urban Exploration Community-Katalog,"
#: templates/partials/welcome.html:12
msgid "explorer"
msgstr "Explorer"
#: templates/partials/welcome.html:17
msgid "We strictly follow our"
msgstr "Bitte lies unseren"
#: templates/partials/welcome.html:18
msgid "UrBex codex"
msgstr "UrBex Codex"
#: templates/partials/welcome.html:19
msgid "and expect you to do so, too."
msgstr "bevor du Places erkundest"
#: templates/photo_album/photo_album_create.html:4
msgid "Submit a photo album"
msgstr "Fotoalbum hinzufügen"
#: templates/photo_album/photo_album_create.html:8
#: templates/place/place_detail.html:18 templates/place/place_update.html:5
#: templates/place/place_update.html:10
msgid "Edit place"
msgstr "Place bearbeiten"
#: templates/photo_album/photo_album_create.html:10
#: templates/place/place_delete.html:11 templates/place/place_detail.html:19
msgid "Delete place"
msgstr "Place löschen"
#: templates/photo_album/photo_album_create.html:16
msgid "Submit a photo album for"
msgstr "Fotoalbum hinzufügen zu"
#: templates/place/place_create.html:42
msgid "Create"
msgstr "Erstellen"
#: templates/place/place_delete.html:5
msgid "Delete lost place"
msgstr "Lost Place löschen"
#: templates/place/place_delete.html:15
#, python-format
msgid "Are you sure you want to delete %(place_name)s?"
msgstr "Bist Du sicher, dass Du %(place_name)s löschen möchtest?"
#: templates/place/place_delete.html:19
msgid "Delete"
msgstr "Löschen"
#: templates/place/place_detail.html:46
msgid "Map links"
msgstr "Kartenlinks"
#: templates/place/place_detail.html:58
msgid "Photo albums"
msgstr "Fotoalben"
#: templates/place/place_detail.html:84
msgid "Add photo album"
msgstr "Fotoalbum hinzufügen"
#: templates/place/place_detail.html:93
msgid "Images"
msgstr "Bilder"
#: templates/place/place_list.html:10
msgid "All Places"
msgstr "Alle Places"
#: templates/place/place_list.html:16
msgid "Our lost places"
msgstr "Unsere Lost Places"
#: templates/place_image/place_image_create.html:7
msgid "Submit images to a place"
msgstr "Bilder zu einem Place hinzufügen"
#: templates/registration/login.html:29
msgid "No account, yet?"
msgstr "Noch kein Konto?"
#: views/base_views.py:25
msgid "Please login to proceed"
msgstr "Bitte log Dich ein um fortzufahren"
#: views/explorer_views.py:78
#, fuzzy
#| msgid "Successfully updated place"
msgid "Successfully updated Explorer profile"
msgstr "Place erfolgreich aktualisiert"
#: views/explorer_views.py:84 views/place_views.py:105
msgid "Please fill in all required fields."
msgstr "Bitte füll alle benötigten Felder aus."
#: views/place_image_views.py:26
msgid "Image(s) submitted successfully"
msgstr "Bild(er) erfolgreich hinzugefügt"
#: views/place_image_views.py:41
msgid "Image deleted successfully"
msgstr "Bild erfolgreich gelöscht"
#: views/place_image_views.py:42
msgid "You are not allowed to delete this image"
msgstr "Du darfst dieses Bild nicht löschen"
#: views/place_views.py:62
msgid "Successfully updated place"
msgstr "Place erfolgreich aktualisiert"
#: views/place_views.py:63
msgid "You are not allowed to edit this place"
msgstr "Du darfst diesen Place nicht bearbeiten"
#: views/place_views.py:97
msgid "Successfully created place"
msgstr "Place erfolgreich erstellt"
#: views/place_views.py:112
msgid "Successfully deleted place"
msgstr "Place erfolgreich gelöscht"
#: views/place_views.py:114
msgid "You are not allowed to delete this place"
msgstr "Du darfst diesen Place nicht löschen"
#: views/views.py:29
msgid "User created"
msgstr "Benutzer erstellt"
#: views/views.py:54
msgid "Photo album link submitted"
msgstr "Fotoalbum-Link hinzugefügt"
#: views/views.py:59
msgid "Photo album link deleted"
msgstr "Fotoalbum-Link gelöscht"
#: views/views.py:60
msgid "You are not allowed to edit this photo album link"
msgstr "Du darfst diesen Fotoalbum-Link nicht bearbeiten"
#, fuzzy
#~| msgid "Filename(s)"
#~ msgid "Filename"
#~ msgstr "Dateiname(n)"

View File

@ -0,0 +1,90 @@
# Generated by Django 3.1.1 on 2020-09-28 18:39
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import easy_thumbnails.fields
import lostplaces.models.place
import taggit.managers
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('taggit', '0003_taggeditem_add_unique_index'),
]
operations = [
migrations.CreateModel(
name='Expireable',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_when', models.DateTimeField(auto_now_add=True)),
('expires_when', models.DateTimeField()),
],
),
migrations.CreateModel(
name='Explorer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='explorer', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Place',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50)),
('latitude', models.FloatField(validators=[django.core.validators.MinValueValidator(-90), django.core.validators.MaxValueValidator(90)])),
('longitude', models.FloatField(validators=[django.core.validators.MinValueValidator(-180), django.core.validators.MaxValueValidator(180)])),
('submitted_when', models.DateTimeField(auto_now_add=True, null=True)),
('location', models.CharField(max_length=50)),
('description', models.TextField()),
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='places', to='lostplaces.explorer')),
('tags', taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Voucher',
fields=[
('expireable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='lostplaces.expireable')),
('code', models.CharField(max_length=30, unique=True)),
],
bases=('lostplaces.expireable',),
),
migrations.CreateModel(
name='PlaceImage',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('submitted_when', models.DateTimeField(auto_now_add=True, null=True)),
('description', models.TextField(blank=True)),
('filename', easy_thumbnails.fields.ThumbnailerImageField(upload_to=lostplaces.models.place.generate_place_image_filename)),
('place', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='placeimages', to='lostplaces.place')),
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='placeimages', to='lostplaces.explorer')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='PhotoAlbum',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('submitted_when', models.DateTimeField(auto_now_add=True, null=True)),
('url', models.URLField()),
('label', models.CharField(max_length=100)),
('place', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='photoalbums', to='lostplaces.place')),
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='photoalbums', to='lostplaces.explorer')),
],
options={
'abstract': False,
},
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 3.1.1 on 2020-10-04 19:37
# Edited by reverend
import datetime
from django.db import migrations, models
import django.utils.timezone
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('lostplaces', '0001_initial'),
]
operations = [
migrations.DeleteModel(
name='Voucher'
),
migrations.DeleteModel(
name='Expireable'
)
]

View File

@ -0,0 +1,25 @@
# Generated by Django 3.1.1 on 2020-10-04 19:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lostplaces', '0002_remove_vouchers'),
]
operations = [
migrations.CreateModel(
name='Voucher',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_when', models.DateTimeField(auto_now_add=True)),
('expires_when', models.DateTimeField()),
('code', models.CharField(max_length=30, unique=True)),
],
options={
'abstract': False,
},
),
]

View File

@ -0,0 +1,102 @@
# Generated by Django 3.1.1 on 2020-12-19 13:53
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import easy_thumbnails.fields
import lostplaces.models.place
class Migration(migrations.Migration):
dependencies = [
('lostplaces', '0003_voucher'),
]
operations = [
migrations.AlterField(
model_name='photoalbum',
name='label',
field=models.CharField(max_length=100, verbose_name='link text'),
),
migrations.AlterField(
model_name='photoalbum',
name='submitted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='photoalbums', to='lostplaces.explorer', verbose_name='Submitter'),
),
migrations.AlterField(
model_name='photoalbum',
name='submitted_when',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date'),
),
migrations.AlterField(
model_name='photoalbum',
name='url',
field=models.URLField(verbose_name='URL'),
),
migrations.AlterField(
model_name='place',
name='description',
field=models.TextField(help_text="Description of the place: e.g. how to get there, where to be careful, the place's history...", verbose_name='Description'),
),
migrations.AlterField(
model_name='place',
name='latitude',
field=models.FloatField(help_text='Latitude in decimal format: e. g. 41.40338', validators=[django.core.validators.MinValueValidator(-90), django.core.validators.MaxValueValidator(90)], verbose_name='Latitude'),
),
migrations.AlterField(
model_name='place',
name='location',
field=models.CharField(max_length=50, verbose_name='Location'),
),
migrations.AlterField(
model_name='place',
name='longitude',
field=models.FloatField(help_text='Longitude in decimal format: e. g. 2.17403', validators=[django.core.validators.MinValueValidator(-180), django.core.validators.MaxValueValidator(180)], verbose_name='Longitude'),
),
migrations.AlterField(
model_name='place',
name='name',
field=models.CharField(max_length=50, verbose_name='Name'),
),
migrations.AlterField(
model_name='place',
name='submitted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='places', to='lostplaces.explorer', verbose_name='Submitter'),
),
migrations.AlterField(
model_name='place',
name='submitted_when',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date'),
),
migrations.AlterField(
model_name='placeimage',
name='description',
field=models.TextField(blank=True, verbose_name='Description'),
),
migrations.AlterField(
model_name='placeimage',
name='filename',
field=easy_thumbnails.fields.ThumbnailerImageField(help_text='Optional: One or more images to upload', upload_to=lostplaces.models.place.generate_image_upload_path, verbose_name='Filename(s)'),
),
migrations.AlterField(
model_name='placeimage',
name='submitted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='placeimages', to='lostplaces.explorer', verbose_name='Submitter'),
),
migrations.AlterField(
model_name='placeimage',
name='submitted_when',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date'),
),
migrations.AlterField(
model_name='voucher',
name='created_when',
field=models.DateTimeField(auto_now_add=True, verbose_name='Creation date'),
),
migrations.AlterField(
model_name='voucher',
name='expires_when',
field=models.DateTimeField(verbose_name='Expiration date'),
),
]

View File

@ -0,0 +1,85 @@
# Generated by Django 3.2.10 on 2021-12-31 17:20
from django.db import migrations, models
import django.db.models.deletion
import easy_thumbnails.fields
import lostplaces.models.models
import lostplaces.models.place
class Migration(migrations.Migration):
dependencies = [
('lostplaces', '0004_release_0_1_3'),
]
operations = [
migrations.AddField(
model_name='explorer',
name='bio',
field=models.TextField(blank=True, help_text='Describe yourself, your preferences, etc. in a few sentences.', null=True, verbose_name='Biography / Description'),
),
migrations.AddField(
model_name='explorer',
name='favorite_places',
field=models.ManyToManyField(blank=True, related_name='explorer_favorites', to='lostplaces.Place', verbose_name='Explorers favorite places'),
),
migrations.AddField(
model_name='explorer',
name='level',
field=models.IntegerField(choices=[(1, 'Newbie'), (2, 'Scout'), (3, 'Explorer'), (4, 'Journalist'), (5, 'Housekeeper')], default=1),
),
migrations.AddField(
model_name='explorer',
name='profile_image',
field=easy_thumbnails.fields.ThumbnailerImageField(blank=True, help_text='Optional profile image for display in Explorer profile', null=True, upload_to=lostplaces.models.generate_profile_image_filename, verbose_name='Profile image'),
),
migrations.AddField(
model_name='explorer',
name='visited_places',
field=models.ManyToManyField(blank=True, related_name='explorer_visits', to='lostplaces.Place', verbose_name='Explorers visited places'),
),
migrations.AddField(
model_name='place',
name='hero',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='place_heros', to='lostplaces.placeimage'),
),
migrations.AddField(
model_name='place',
name='level',
field=models.IntegerField(choices=[(1, 'Ruin'), (2, 'Vandalized'), (3, 'Natures Treasure'), (4, 'Lost in History'), (5, 'Time Capsule')], default=5),
),
migrations.AlterField(
model_name='placeimage',
name='filename',
field=easy_thumbnails.fields.ThumbnailerImageField(help_text='Optional: One or more images to upload', upload_to=lostplaces.models.place.generate_place_image_filename, verbose_name='Images'),
),
migrations.CreateModel(
name='PlaceVoting',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('submitted_when', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date')),
('created_when', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
('expires_when', models.DateTimeField(verbose_name='Expiration date')),
('vote', models.IntegerField(choices=[(1, 'Ruin'), (2, 'Vandalized'), (3, 'Natures Treasure'), (4, 'Lost in History'), (5, 'Time Capsule')])),
('place', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='placevotings', to='lostplaces.place')),
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='placevotings', to='lostplaces.explorer', verbose_name='Submitter')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='DummyAsset',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('submitted_when', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date')),
('name', models.CharField(max_length=50)),
('place', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dummyassets', to='lostplaces.place')),
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='dummyassets', to='lostplaces.explorer', verbose_name='Submitter')),
],
options={
'abstract': False,
},
),
]

View File

@ -0,0 +1,4 @@
from lostplaces.models.abstract_models import *
from lostplaces.models.place import *
from lostplaces.models.external_links import *
from lostplaces.models.models import *

View File

@ -0,0 +1,87 @@
from django.utils import timezone
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.validators import MaxValueValidator, MinValueValidator
from taggit.managers import TaggableManager
class Taggable(models.Model):
'''
This abstract model represtens an object that is taggable
using django-taggit
'''
class Meta:
abstract = True
tags = TaggableManager(blank=True)
class Mapable(models.Model):
'''
This abstract model class represents an object that can be
displayed on a map.
'''
class Meta:
abstract = True
name = models.CharField(
max_length=50,
verbose_name=_('Name'),
)
latitude = models.FloatField(
validators=[
MinValueValidator(-90),
MaxValueValidator(90)
],
verbose_name=_('Latitude'),
help_text=_('Latitude in decimal format: e. g. 41.40338')
)
longitude = models.FloatField(
validators=[
MinValueValidator(-180),
MaxValueValidator(180)
],
verbose_name=_('Longitude'),
help_text=_('Longitude in decimal format: e. g. 2.17403')
)
class Submittable(models.Model):
'''
This abstract model class represents an object that can be submitted by
an explorer.
'''
class Meta:
abstract = True
submitted_when = models.DateTimeField(
auto_now_add=True,
null=True,
verbose_name=_('Submission date')
)
submitted_by = models.ForeignKey(
'Explorer',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='%(class)ss',
verbose_name=_('Submitter')
)
class Expireable(models.Model):
"""
Base class for things that can expire, i.e. Vouchers
"""
class Meta:
abstract = True
created_when = models.DateTimeField(
auto_now_add=True,
verbose_name=_('Creation date')
)
expires_when = models.DateTimeField(
verbose_name=_('Expiration date')
)
@property
def is_expired(self):
return timezone.now() > self.expires_when

View File

@ -0,0 +1,21 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from lostplaces.models.place import PlaceAsset
class ExternalLink(PlaceAsset):
class Meta:
abstract = True
url = models.URLField(
max_length=200,
verbose_name=_('URL')
)
label = models.CharField(
max_length=100,
verbose_name=_('link text')
)
class PhotoAlbum(ExternalLink):
pass

View File

@ -0,0 +1,145 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
(Data)models which describe the structure of data to be saved into
database.
'''
import os
import uuid
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
from lostplaces.models.abstract_models import Expireable
from lostplaces.models.place import Place
from easy_thumbnails.fields import ThumbnailerImageField
from easy_thumbnails.files import get_thumbnailer
def generate_profile_image_filename(instance, filename):
"""
Callback for generating filename for uploaded explorer profile images.
Returns filename as: explorer_pk-username.jpg
"""
return 'explorers/' + str(instance.user.pk) + '-' + str(instance.user.username) + '.' + filename.split('.')[-1]
EXPLORER_LEVELS = (
(1, 'Newbie'),
(2, 'Scout'),
(3, 'Explorer'),
(4, 'Journalist'),
(5, 'Housekeeper')
)
class Explorer(models.Model):
"""
Profile that is linked to the Django user.
Every user has a profile.
Provides additional attributes for user profile.
"""
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
related_name='explorer'
)
bio = models.TextField(
blank=True,
null=True,
verbose_name=_('Biography / Description'),
help_text=_('Describe yourself, your preferences, etc. in a few sentences.')
)
profile_image = ThumbnailerImageField(
blank=True,
null=True,
upload_to=generate_profile_image_filename,
resize_source=dict(size=(400, 400),
sharpen=True),
verbose_name=_('Profile image'),
help_text=_('Optional profile image for display in Explorer profile')
)
favorite_places = models.ManyToManyField(
Place,
related_name='explorer_favorites',
verbose_name='Explorers favorite places',
blank=True
)
visited_places = models.ManyToManyField(
Place,
related_name='explorer_visits',
verbose_name='Explorers visited places',
blank=True
)
level = models.IntegerField(
default=1,
choices=EXPLORER_LEVELS
)
def get_places_eligible_to_see(self):
if self.user.is_superuser:
return Place.objects.all()
return Place.objects.all().filter(level__lte=self.level) | self.places.all()
def is_eligible_to_see(self, place):
return (
self.user.is_superuser or
place.submitted_by == self or
place in self.get_places_eligible_to_see()
)
def __str__(self):
return self.user.username
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Explorer.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.explorer.save()
@receiver(pre_save, sender=Explorer)
def auto_delete_file_on_change(sender, instance, **kwargs):
"""
Deletes old file from filesystem
when corresponding `Explorer` object is updated
with new file.
"""
if not instance.pk:
return False
try:
old_file = Explorer.objects.get(pk=instance.pk).profile_image
except Explorer.DoesNotExist:
return False
new_file = instance.profile_image
if not old_file == new_file:
old_file.delete(save=False)
class Voucher(Expireable):
"""
Vouchers are authorization tokens to allow the registration of new users.
A voucher has a code, a creation and a deletion date, which are all
positional. Creation date is being set automatically during voucher
creation.
created_when = models.DateTimeField(auto_now_add=True)
expires_when = models.DateTimeField()
"""
code = models.CharField(unique=True, max_length=30)
@property
def valid(self):
return not self.is_expired
def __str__(self):
return "Voucher " + str(self.code)

View File

@ -0,0 +1,219 @@
import os
from math import floor
from django.db import models
from django.urls import reverse
from django.dispatch import receiver
from django.db.models.signals import post_delete, pre_save
from django.utils.translation import ugettext_lazy as _
from lostplaces.models.abstract_models import Submittable, Taggable, Mapable, Expireable
from easy_thumbnails.fields import ThumbnailerImageField
from easy_thumbnails.files import get_thumbnailer
PLACE_LEVELS = (
(1, 'Ruin'),
(2, 'Vandalized'),
(3, 'Natures Treasure'),
(4, 'Lost in History'),
(5, 'Time Capsule')
)
class Place(Submittable, Taggable, Mapable):
"""
Place defines a lost place (location, name, description etc.).
"""
location = models.CharField(
max_length=50,
verbose_name=_('Location'),
)
description = models.TextField(
help_text=_('Description of the place: e.g. how to get there, where to be careful, the place\'s history...'),
verbose_name=_('Description'),
)
hero = models.ForeignKey(
'PlaceImage',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='place_heros'
)
level = models.IntegerField(
default=5,
choices=PLACE_LEVELS
)
def get_hero_image(self):
if self.hero:
return self.hero
elif len(self.placeimages.all()) > 0:
return self.placeimages.first()
else:
return None
def get_absolute_url(self):
return reverse('place_detail', kwargs={'pk': self.pk})
def get_hero_index_in_queryset(self):
'''
Calculates the index of the hero image within
the list / queryset of images. Necessary for
the lightbox.
'''
for i in range(0, len(self.placeimages.all())):
image = self.placeimages.all()[i]
if image == self.hero:
return i
return None
@classmethod
# Get center position of LP-geocoordinates.
def average_latlon(cls, place_list):
amount = len(place_list)
# Init fill values to prevent None
# China Corner in Münster
# Where I almost always eat lunch
# (Does'nt help losing wheight, tho)
longitude = 7.6295628132604385
latitude = 51.961922091398904
if amount > 0:
for place in place_list:
longitude += place.longitude
latitude += place.latitude
return {'latitude':latitude / amount, 'longitude': longitude / amount}
return {'latitude': latitude, 'longitude': longitude}
def calculate_place_level(self):
self.remove_expired_votes()
if self.placevotings.count() == 0:
self.level = 5
self.save()
return
level = 0
for vote in self.placevotings.all():
level += vote.vote
self.level = floor(level / self.placevotings.count())
self.save()
def remove_expired_votes(self):
for vote in self.placevotings.all():
if vote.is_expired:
vote.delete()
def __str__(self):
return self.name
def generate_place_image_filename(instance, filename):
"""
Callback for generating filename for uploaded place images.
Returns filename as: place_pk-placename{-number}.jpg
"""
return 'places/' + str(instance.place.pk) + '-' + str(instance.place.name) + '.' + filename.split('.')[-1]
def generate_image_upload_path(instance, filename):
return generate_place_image_filename(instance, filename)
class PlaceAsset(Submittable):
"""
Assets to a place, i.e. images
"""
class Meta:
abstract = True
place = models.ForeignKey(
Place,
on_delete=models.CASCADE,
related_name='%(class)ss',
null=True
)
class DummyAsset(PlaceAsset):
name = models.CharField(max_length=50)
class PlaceImage(PlaceAsset):
"""
PlaceImage defines an image file object that points to a file in uploads/.
Intermediate image sizes are generated as defined in THUMBNAIL_ALIASES.
PlaceImage references a Place to which it belongs.
"""
description = models.TextField(
blank=True,
verbose_name=_('Description'),
)
filename = ThumbnailerImageField(
upload_to=generate_place_image_filename,
resize_source=dict(size=(2560, 2560),
sharpen=True),
verbose_name=_('Images'),
help_text=_('Optional: One or more images to upload')
)
place = models.ForeignKey(
Place,
on_delete=models.CASCADE,
related_name='placeimages'
)
def __str__(self):
"""
Returning the name of the corresponding place + id
of this image as textual representation of this instance
"""
return 'Image ' + str(self.place.name)
# These two auto-delete files from filesystem when they are unneeded:
@receiver(post_delete, sender=PlaceImage)
def auto_delete_file_on_delete(sender, instance, **kwargs):
"""
Deletes file (including thumbnails) from filesystem
when corresponding `PlaceImage` object is deleted.
"""
if instance.filename:
# Get and delete all files and thumbnails from instance
thumbmanager = get_thumbnailer(instance.filename)
thumbmanager.delete(save=False)
@receiver(pre_save, sender=PlaceImage)
def auto_delete_file_on_change(sender, instance, **kwargs):
"""
Deletes old file from filesystem
when corresponding `PlaceImage` object is updated
with new file.
"""
if not instance.pk:
return False
try:
old_file = PlaceImage.objects.get(pk=instance.pk).filename
except PlaceImage.DoesNotExist:
return False
# No need to delete thumbnails, as they will be overwritten on regeneration.
new_file = instance.filename
if not old_file == new_file:
old_file.delete(save=False)
class PlaceVoting(PlaceAsset, Expireable):
vote = models.IntegerField(choices=PLACE_LEVELS)
def get_human_readable_level(self):
return PLACE_LEVELS[self.vote - 1][1]
def get_all_choices(self):
return reversed(PLACE_LEVELS)

View File

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 264 KiB

View File

@ -1,5 +1,4 @@
Copyright (c) 2010, Sebastian Kosch (sebastian@aldusleaf.org),
with Reserved Font Name "Crimson" and "Crimson Text".
Copyright 2018 The Crimson Pro Project Authors (https://github.com/Fonthausen/CrimsonPro)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,93 @@
Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 108 KiB

View File

Before

Width:  |  Height:  |  Size: 816 B

After

Width:  |  Height:  |  Size: 816 B

View File

Before

Width:  |  Height:  |  Size: 351 B

After

Width:  |  Height:  |  Size: 351 B

View File

Before

Width:  |  Height:  |  Size: 641 B

After

Width:  |  Height:  |  Size: 641 B

View File

Before

Width:  |  Height:  |  Size: 850 B

After

Width:  |  Height:  |  Size: 850 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 914 B

After

Width:  |  Height:  |  Size: 914 B

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 368.16 368.16" style="enable-background:new 0 0 368.16 368.16;" xml:space="preserve">
<g>
<g>
<g>
<path d="M184.08,0c-74.992,0-136,61.008-136,136c0,24.688,11.072,51.24,11.536,52.36c3.576,8.488,10.632,21.672,15.72,29.4
l93.248,141.288c3.816,5.792,9.464,9.112,15.496,9.112s11.68-3.32,15.496-9.104l93.256-141.296
c5.096-7.728,12.144-20.912,15.72-29.4c0.464-1.112,11.528-27.664,11.528-52.36C320.08,61.008,259.072,0,184.08,0z
M293.8,182.152c-3.192,7.608-9.76,19.872-14.328,26.8l-93.256,141.296c-1.84,2.792-2.424,2.792-4.264,0L88.696,208.952
c-4.568-6.928-11.136-19.2-14.328-26.808C74.232,181.816,64.08,157.376,64.08,136c0-66.168,53.832-120,120-120
c66.168,0,120,53.832,120,120C304.08,157.408,293.904,181.912,293.8,182.152z"/>
<path d="M184.08,64.008c-39.704,0-72,32.304-72,72c0,39.696,32.296,72,72,72c39.704,0,72-32.304,72-72
C256.08,96.312,223.784,64.008,184.08,64.008z M184.08,192.008c-30.872,0-56-25.12-56-56s25.128-56,56-56s56,25.12,56,56
S214.952,192.008,184.08,192.008z"/>
</g>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 368.16 368.16"
style="enable-background:new 0 0 368.16 368.16;"
xml:space="preserve"
sodipodi:docname="pin_filled.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"><metadata
id="metadata47"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs45" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="712"
id="namedview43"
showgrid="false"
inkscape:zoom="1.4803346"
inkscape:cx="184.08"
inkscape:cy="181.37791"
inkscape:window-x="0"
inkscape:window-y="28"
inkscape:window-maximized="1"
inkscape:current-layer="Capa_1" />
<g
id="g10">
<g
id="g8">
<g
id="g6">
<path
d="M184.08,0c-74.992,0-136,61.008-136,136c0,24.688,11.072,51.24,11.536,52.36c3.576,8.488,10.632,21.672,15.72,29.4 l93.248,141.288c3.816,5.792,9.464,9.112,15.496,9.112s11.68-3.32,15.496-9.104l93.256-141.296 c5.096-7.728,12.144-20.912,15.72-29.4c0.464-1.112,11.528-27.664,11.528-52.36C320.08,61.008,259.072,0,184.08,0z M293.8,182.152c-3.192,7.608-9.76,19.872-14.328,26.8l-93.256,141.296c-1.84,2.792-2.424,2.792-4.264,0L88.696,208.952 c-4.568-6.928-11.136-19.2-14.328-26.808C74.232,181.816,64.08,157.376,64.08,136c0-66.168,53.832-120,120-120 c66.168,0,120,53.832,120,120C304.08,157.408,293.904,181.912,293.8,182.152z"
id="path2" />
<path
d="M184.08,64.008c-39.704,0-72,32.304-72,72c0,39.696,32.296,72,72,72c39.704,0,72-32.304,72-72 C256.08,96.312,223.784,64.008,184.08,64.008z M184.08,192.008c-30.872,0-56-25.12-56-56s25.128-56,56-56s56,25.12,56,56 S214.952,192.008,184.08,192.008z"
id="path4" />
</g>
</g>
</g>
<g
id="g12">
</g>
<g
id="g14">
</g>
<g
id="g16">
</g>
<g
id="g18">
</g>
<g
id="g20">
</g>
<g
id="g22">
</g>
<g
id="g24">
</g>
<g
id="g26">
</g>
<g
id="g28">
</g>
<g
id="g30">
</g>
<g
id="g32">
</g>
<g
id="g34">
</g>
<g
id="g36">
</g>
<g
id="g38">
</g>
<g
id="g40">
</g>
<path
style="fill:#d40000;stroke-width:0.675523"
d="M 183.2356,15.407728 C 148.115,15.680007 113.56046,32.165752 91.281357,59.335191 67.968201,87.080284 57.903075,125.97636 67.012946,161.30636 c 5.002813,21.56622 16.217838,40.96402 28.671518,59.02158 29.047926,44.21623 57.936976,88.55418 87.673836,132.30559 2.75528,0.71398 3.44582,-3.87416 5.23173,-5.36255 32.63958,-48.91094 65.16056,-97.91511 96.89098,-147.42174 14.94799,-26.09698 23.38967,-57.3347 16.79888,-87.25041 C 297.41258,88.732147 285.50707,66.159988 267.48079,49.622901 254.86863,36.299556 238.35251,27.47624 221.24564,21.334387 209.00763,17.320382 196.11719,15.285641 183.2356,15.407728 Z m 2.03448,49.555941 c 27.46439,-0.566602 54.10132,17.912787 64.54543,43.490751 4.10895,9.11958 5.7106,19.04018 5.10583,29.01713 0.83931,19.32103 -8.79389,38.15287 -22.74612,51.10133 -14.02478,12.97799 -33.27348,19.77398 -52.19585,18.33769 -29.18994,-0.56334 -56.21632,-22.71956 -64.31454,-50.57715 -3.46488,-10.42859 -2.56691,-21.58508 -1.94784,-32.37905 3.96475,-21.34187 17.606,-41.232363 37.2523,-51.078299 10.71386,-5.480174 22.38724,-8.587404 34.30079,-7.912402 z"
id="path91" /></svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 488 B

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 717 B

After

Width:  |  Height:  |  Size: 717 B

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
.ol-box{box-sizing:border-box;border-radius:2px;border:2px solid #00f}.ol-mouse-position{top:8px;right:8px;position:absolute}.ol-scale-line{background:rgba(0,60,136,.3);border-radius:4px;bottom:8px;left:8px;padding:2px;position:absolute}.ol-scale-line-inner{border:1px solid #eee;border-top:none;color:#eee;font-size:10px;text-align:center;margin:1px;will-change:contents,width;transition:all .25s}.ol-scale-bar{position:absolute;bottom:8px;left:8px}.ol-scale-step-marker{width:1px;height:15px;background-color:#000;float:right;z-Index:10}.ol-scale-step-text{position:absolute;bottom:-5px;font-size:12px;z-Index:11;color:#000;text-shadow:-2px 0 #fff,0 2px #fff,2px 0 #fff,0 -2px #fff}.ol-scale-text{position:absolute;font-size:14px;text-align:center;bottom:25px;color:#000;text-shadow:-2px 0 #fff,0 2px #fff,2px 0 #fff,0 -2px #fff}.ol-scale-singlebar{position:relative;height:10px;z-Index:9;box-sizing:border-box;border:1px solid #000}.ol-unsupported{display:none}.ol-unselectable,.ol-viewport{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.ol-selectable{-webkit-touch-callout:default;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.ol-grabbing{cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:grabbing}.ol-grab{cursor:move;cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.ol-control{position:absolute;background-color:rgba(255,255,255,.4);border-radius:4px;padding:2px}.ol-control:hover{background-color:rgba(255,255,255,.6)}.ol-zoom{top:.5em;left:.5em}.ol-rotate{top:.5em;right:.5em;transition:opacity .25s linear,visibility 0s linear}.ol-rotate.ol-hidden{opacity:0;visibility:hidden;transition:opacity .25s linear,visibility 0s linear .25s}.ol-zoom-extent{top:4.643em;left:.5em}.ol-full-screen{right:.5em;top:.5em}.ol-control button{display:block;margin:1px;padding:0;color:#fff;font-size:1.14em;font-weight:700;text-decoration:none;text-align:center;height:1.375em;width:1.375em;line-height:.4em;background-color:rgba(0,60,136,.5);border:none;border-radius:2px}.ol-control button::-moz-focus-inner{border:none;padding:0}.ol-zoom-extent button{line-height:1.4em}.ol-compass{display:block;font-weight:400;font-size:1.2em;will-change:transform}.ol-touch .ol-control button{font-size:1.5em}.ol-touch .ol-zoom-extent{top:5.5em}.ol-control button:focus,.ol-control button:hover{text-decoration:none;background-color:rgba(0,60,136,.7)}.ol-zoom .ol-zoom-in{border-radius:2px 2px 0 0}.ol-zoom .ol-zoom-out{border-radius:0 0 2px 2px}.ol-attribution{text-align:right;bottom:.5em;right:.5em;max-width:calc(100% - 1.3em)}.ol-attribution ul{margin:0;padding:0 .5em;color:#000;text-shadow:0 0 2px #fff}.ol-attribution li{display:inline;list-style:none}.ol-attribution li:not(:last-child):after{content:" "}.ol-attribution img{max-height:2em;max-width:inherit;vertical-align:middle}.ol-attribution button,.ol-attribution ul{display:inline-block}.ol-attribution.ol-collapsed ul{display:none}.ol-attribution:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-attribution.ol-uncollapsible{bottom:0;right:0;border-radius:4px 0 0}.ol-attribution.ol-uncollapsible img{margin-top:-.2em;max-height:1.6em}.ol-attribution.ol-uncollapsible button{display:none}.ol-zoomslider{top:4.5em;left:.5em;height:200px}.ol-zoomslider button{position:relative;height:10px}.ol-touch .ol-zoomslider{top:5.5em}.ol-overviewmap{left:.5em;bottom:.5em}.ol-overviewmap.ol-uncollapsible{bottom:0;left:0;border-radius:0 4px 0 0}.ol-overviewmap .ol-overviewmap-map,.ol-overviewmap button{display:inline-block}.ol-overviewmap .ol-overviewmap-map{border:1px solid #7b98bc;height:150px;margin:2px;width:150px}.ol-overviewmap:not(.ol-collapsed) button{bottom:1px;left:2px;position:absolute}.ol-overviewmap.ol-collapsed .ol-overviewmap-map,.ol-overviewmap.ol-uncollapsible button{display:none}.ol-overviewmap:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-overviewmap-box{border:2px dotted rgba(0,60,136,.7)}.ol-overviewmap .ol-overviewmap-box:hover{cursor:move}
/*# sourceMappingURL=ol.css.map */

View File

@ -0,0 +1 @@
{"version":3,"sources":["src/ol/ol.css"],"names":[],"mappings":"AAAA,QACE,WAAY,WACZ,cAAe,IACf,OAAQ,IAAI,MAAM,KAGpB,mBACE,IAAK,IACL,MAAO,IACP,SAAU,SAGZ,eACE,WAAY,kBACZ,cAAe,IACf,OAAQ,IACR,KAAM,IACN,QAAS,IACT,SAAU,SAEZ,qBACE,OAAQ,IAAI,MAAM,KAClB,WAAY,KACZ,MAAO,KACP,UAAW,KACX,WAAY,OACZ,OAAQ,IACR,YAAa,QAAQ,CAAE,MACvB,WAAY,IAAI,KAElB,cACE,SAAU,SACV,OAAQ,IACR,KAAM,IAER,sBACE,MAAO,IACP,OAAQ,KACR,iBAAkB,KAClB,MAAO,MACP,QAAS,GAEX,oBACE,SAAU,SACV,OAAQ,KACR,UAAW,KACX,QAAS,GACT,MAAO,KACP,YAAa,KAAK,EAAE,IAAO,CAAE,EAAE,IAAI,IAAO,CAAE,IAAI,EAAE,IAAO,CAAE,EAAE,KAAK,KAEpE,eACE,SAAU,SACV,UAAW,KACX,WAAY,OACZ,OAAQ,KACR,MAAO,KACP,YAAa,KAAK,EAAE,IAAO,CAAE,EAAE,IAAI,IAAO,CAAE,IAAI,EAAE,IAAO,CAAE,EAAE,KAAK,KAEpE,oBACE,SAAU,SACV,OAAQ,KACR,QAAS,EACT,WAAY,WACZ,OAAQ,IAAI,MAAM,KAGpB,gBACE,QAAS,KAEG,iBAAd,aACE,sBAAuB,KACvB,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,4BAA6B,YAE/B,eACE,sBAAuB,QACvB,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KAEf,aACE,OAAQ,iBACR,OAAQ,cACR,OAAQ,SAEV,SACE,OAAQ,KACR,OAAQ,aACR,OAAQ,UACR,OAAQ,KAEV,YACE,SAAU,SACV,iBAAkB,qBAClB,cAAe,IACf,QAAS,IAEX,kBACE,iBAAkB,qBAEpB,SACE,IAAK,KACL,KAAM,KAER,WACE,IAAK,KACL,MAAO,KACP,WAAY,QAAQ,KAAK,MAAM,CAAE,WAAW,GAAG,OAEjD,qBACE,QAAS,EACT,WAAY,OACZ,WAAY,QAAQ,KAAK,MAAM,CAAE,WAAW,GAAG,OAAO,KAExD,gBACE,IAAK,QACL,KAAM,KAER,gBACE,MAAO,KACP,IAAK,KAGP,mBACE,QAAS,MACT,OAAQ,IACR,QAAS,EACT,MAAO,KACP,UAAW,OACX,YAAa,IACb,gBAAiB,KACjB,WAAY,OACZ,OAAQ,QACR,MAAO,QACP,YAAa,KACb,iBAAkB,kBAClB,OAAQ,KACR,cAAe,IAEjB,qCACE,OAAQ,KACR,QAAS,EAEX,uBACE,YAAa,MAEf,YACE,QAAS,MACT,YAAa,IACb,UAAW,MACX,YAAa,UAEf,6BACE,UAAW,MAEb,0BACE,IAAK,MAGP,yBADA,yBAEE,gBAAiB,KACjB,iBAAkB,kBAEpB,qBACE,cAAe,IAAI,IAAI,EAAE,EAE3B,sBACE,cAAe,EAAE,EAAE,IAAI,IAIzB,gBACE,WAAY,MACZ,OAAQ,KACR,MAAO,KACP,UAAW,mBAGb,mBACE,OAAQ,EACR,QAAS,EAAE,KACX,MAAO,KACP,YAAa,EAAE,EAAE,IAAI,KAEvB,mBACE,QAAS,OACT,WAAY,KAEd,0CACE,QAAS,IAEX,oBACE,WAAY,IACZ,UAAW,QACX,eAAgB,OAEE,uBAApB,mBACE,QAAS,aAEX,gCACE,QAAS,KAEX,mCACE,WAAY,qBAEd,iCACE,OAAQ,EACR,MAAO,EACP,cAAe,IAAI,EAAE,EAEvB,qCACE,WAAY,MACZ,WAAY,MAEd,wCACE,QAAS,KAGX,eACE,IAAK,MACL,KAAM,KACN,OAAQ,MAEV,sBACE,SAAU,SACV,OAAQ,KAGV,yBACE,IAAK,MAGP,gBACE,KAAM,KACN,OAAQ,KAEV,iCACE,OAAQ,EACR,KAAM,EACN,cAAe,EAAE,IAAI,EAAE,EAEzB,oCACA,uBACE,QAAS,aAEX,oCACE,OAAQ,IAAI,MAAM,QAClB,OAAQ,MACR,OAAQ,IACR,MAAO,MAET,0CACE,OAAQ,IACR,KAAM,IACN,SAAU,SAEZ,iDACA,wCACE,QAAS,KAEX,mCACE,WAAY,qBAEd,oBACE,OAAQ,IAAI,OAAO,kBAGrB,0CACE,OAAQ"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
{% extends 'global.html'%}
{% load i18n %}
{% block title %}{% translate 'Forbidden' %}{% endblock %}
{% block additional_head %}
{% if request.META.HTTP_REFERER %}
<meta http-equiv="refresh" content="5;url={{ request.META.HTTP_REFERER }}" />
{% endif %}
{% endblock additional_head %}
{% block maincontent %}
{% if request.META.HTTP_REFERER %}
<p class="LP-Headline">{% translate 'You will be redirected in 5 seconds' %}</p><p class="LP-Headline"><a href="{{ request.META.HTTP_REFERER }}" class="LP-Link">{% translate 'Go Back' %}</a></p>
{% endif %}
{% endblock maincontent %}

View File

@ -0,0 +1,128 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
{% load svg_icon %}
{% block maincontent %}
<div class="LP-UserProfile">
<div class="LP-UserProfile__Bio">
<h2 class="LP-Headline">Bio</h2>
<p class="LP-Paragraph">{{explorer.bio}}</p>
</div>
<div class="LP-UserProfile__Info">
<div class="LP-UserInfo">
<div class="LP-UserInfo__UserName">
<h1 class="LP-Headline">{{explorer.user.username}}</h1>
</div>
<div class="LP-UserInfo__Meta">
<table>
<tr>
{% if explorer.profile_image %}
<figure class="LP-UserInfo__Image">
<img src="{{ explorer.profile_image.url }}" class="LP-Image" />
</figure>
{% endif %}
<tr>
{% if explorer.user.first_name %}
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% trans 'Name' %}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">{{explorer.user.first_name}} {{explorer.user.last_name}}</span>
</td>
{% endif %}
</tr>
<tr>
{% if explorer.user.email %}
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% trans 'E-mail' %}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">
<a href="mailto:{{explorer.user.email}}" class="LP-Link">{{explorer.user.email}}</a>
</span>
</td>
{% endif %}
</tr>
<tr>
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% translate 'Joined' %}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">{{explorer.user.date_joined|date:'d.m.Y'}}</span>
</td>
</tr>
<tr>
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% translate 'Places'%}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">{{place_count}}</span>
</td>
</tr>
<tr>
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% translate 'Place Assets'%}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">{{asset_count}}</span>
</td>
</tr>
</table>
<div class="LP-UserInfo__Edit">
<a href="{% url 'explorer_profile_update' %}" class="LP-Button LP-Button--fullWidth LP-Link">{% trans 'Edit Profile' %}</a>
</div>
</div>
</div>
</div>
</div>
<section class="LP-Section">
<div class="LP-PlaceList">
<h1 class="LP-Headline">{% translate 'Places submitted by' %} {{explorer.user.username}}</h1>
<ul class="LP-PlaceList__List">
{% for place in place_list %}
<li class="LP-PlaceList__Item">
<a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link">
{% include 'partials/place_teaser.html' with place=place extended=True %}
</a>
</li>
{% endfor %}
</ul>
{% include 'partials/nav/pagination.html' %}
</div>
</section>
<section class="LP-Section">
{% translate 'Images submitted by' as submitted_by %}
{% include 'partials/placeImageGrid.html' with headline=submitted_by|add:' '|add:explorer.user.username image_list=assets.placeimages.all%}
</section>
<section class=" LP-Section">
<h1 class="LP-Headline">{% translate 'Photo albums submitted by' %} {{explorer.user.username}}</h1>
<div class="LP-LinkList">
<ul class="LP-LinkList__Container">
{% for photo_album in assets.photoalbums.all %}
<li class="LP-LinkList__Item">
<a target="_blank" href="{{photo_album.url}}" class="LP-Link">
<span class="LP-Text">{{photo_album.label}}</span>
</a>
{% if user.explorer == photo_album.submitted_by%}
<a href="{% url 'photo_album_delete' pk=photo_album.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete Photo Album">
<div class="RV-Iconized__Container RV-Iconized__Container--small">
{% icon 'trash' className="RV-Iconized__Icon" %}
</div>
</a>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
</section>
{% endblock maincontent %}

View File

@ -0,0 +1,55 @@
{% extends 'global.html'%}
{% load i18n %}
{% load thumbnail %}
{% load widget_tweaks %}
# {% block title %}{% trans 'Edit Explorer profile' %}{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST" enctype="multipart/form-data">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">{% trans 'Edit Explorer profile' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.username %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.email %}
</div>
</div>
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.first_name %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.last_name %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_change_form.bio %}
</div>
</div>
<div class="LP-Form__Composition">
{% if explorer_image %}
<div class="LP-Form__Field">
<img src="{% thumbnail explorer_image 200x200 %}"/>
</div>
{% endif %}
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_change_form.profile_image %}
</div>
</div>
{% trans 'Update' as action %}
<div class="LP-Form__Composition LP-Form__Composition--buttons">
{% include 'partials/form/submit.html' with referrer=request.META.HTTP_REFERER action=action %}
</div>
</fieldset>
</form>
{% endblock maincontent %}

View File

@ -0,0 +1,74 @@
{% extends 'global.html'%}
# {% block title %}UrBex Codex{% endblock %}
{% block maincontent %}
<header class="LP-TextSection__Headline">
<h1 class="LP-Headline">Nimm nichts mit - außer Deinen Bildern. Laß nichts da - außer Deinen Fußspuren!</h1>
</header>
<article class="LP-TextSection LP-TextSection__Text">
<p>Das sollte doch eigentlich eindeutig sein, oder? Aber wie wir alle wissen, hat jedes Schild eine Geschichte. Wir haben zu viel sinnlose Zerstörung gesehen, sodass wir uns dazu entschieden haben, einen grundlegenden Urban Exploration Codex niederzuschreiben.</p>
<h2 class="LP-Headline">Zu deiner eigenen Sicherheit</h2>
<ol class="LP-UnorderedList">
<li>
<b>Wir gehen selten alleine</b>, ein bisschen rumlaufen und Fotos machen klingt erstmal ungefährlich. Du weißt aber nie in welchem Zustand die Anlage ist oder wer sich dort aufhält. Den Fuß umknickt, an Scherben geschnitten oder vielleicht auf einen unerwarteten Bewohner oder Sicherheitspersonal getroffen. In solchen Situationen ist immer besser jemanden an deiner Seite zu haben, der dich nicht im Stich lässt.
</li>
<li>
<b>Wir sagen vor einer Tour mindestens einer Person unseres Vertrauens, wo wir sind</b> (Koordinaten!), wie lange wir uns dort aufhalten werden und was wir dort tun. Wir verabreden, daß wir uns bei einem längeren Aufenthalt dort regelmäßig melden, oder aber ein "okay" geben, wenn wir die Location wieder verlassen haben. Wenn wir uns verspäten, dann denken wir daran, eine entsprechende Nachricht abzusetzen. Unsere Kontaktperson soll nach einer gewissen Zeit, wenn sie nichts von mir hört, für Hilfe sorgen.
</li>
<li>
<b>In einer Location verhalten wir uns vorsichtig.</b> Wir werfen nichts in Löcher oder aus Fenstern und berühren auch keine elektrischen Anlagen. Nicht immer ist der Strom wirklich abgeschaltet. Deswegen öffnen wor auch keine Flaschen und andere Behälter. Wir gehen niemals ohne Licht in einen dunklen Raum, und nehmen immer eine Reservelampe mit.
</li>
<li>
<b>Wir bereiten unsere Tour sorgfältig vor.</b> Es ist ärgerlich, wenn die Kamera-Akkus nicht geladen sind - aber gefährlich ist es keineswegs. Es ist aber lebensgefährlich, wenn ein verschmutzter Nagel durch eine Sohle getreten wird. Sicherheitsschuhe zu tragen ist eine gute Idee. Wenn wir unter Tage gehen, nehmen wir angemessenes Equipment mit um uns zu schützen — z. B. einen Gaswarner oder vllt. sogar einen Geigerzähler.
</li>
<li>
<b>Wir rennen nicht vor bewaffnetem Personal weg</b>, insbesondere nicht der Polizei! Eine Anzeige ist ätzend und das reden mit den Beamten ist mit Sicherheit unangenehm, flieht ihr die Szene, macht euch das aber noch verdächtiger. Mal ganz davon abgesehen dass die Polizei in der Überzahl ist und euch wahrscheinlich sowie fasst.
</li>
</ol>
<h2 class="LP-Headline">Damit ein Lostplace auch lost bleibt</h2>
<ol class="LP-UnorderedList">
<li>
<b>Wir respektieren fremdes Eigentum</b>, so wie wir das von anderen auch verlangen. Deswegen öffnen wir keinen Zugang gewaltsam, oder beschädigen eine Verschlusseinrichtung. Wir betreten ein Grundstück oder ein Gebäude / eine Anlage / eine Ruine nur dann, wenn wir davon ausgehen können, nicht gegen den Willen des Eigentümers dort zu sein. Eine gut erhaltene Umzäunung, oder ein ständiger Wachschutz sprechen dafür, dass der Eigentümer sich noch mit seiner Anlage befasst. Längst umgesunkene Zäune, Ruinen im letzten Stadium eines Verfalls sprecher dafür, dass dem Eigentümer das eher Wurst ist.
</li>
<li>
<b>Wir nehmen von einer Location nichts mit</b>, auch keine "kleinen Andenken", und lassen nichts da - auch keine Kippen, keine Verpackungen - nichts.
<b>Wir verändern am Ort nichts, nehmen nichts weg und fügen nichts hinzu.</b>
</li>
<li>
<b>Wir rauchen möglichst nicht.</b> Nicht nur, weil es stinkt und Müll verursacht. Es gibt immer die Chance, irgendwas durch Funkenflug anzuzünden. Lass es trockene Blätter an einem heißen Sommertag oder (potentielle) entflammbare Materialien in Industrieanlagen sein.
</li>
<li>
<b>Sprayen ist ein absolutes "no-go"!</b>
</li>
<li>
<b>Wir parken nicht so, daß Dritte auf unser Vorhaben aufmerksam werden.</b> Unser Hobby braucht keine öffentliche Aufmerksamkeit, die sich auf illegales Betreten von Grundstücken richtet (und illegal dürfte das Betreten ja meist sein ...).
</li>
<li>
<b>Wir verraten unsere Locations nicht</b> und veröffentlichen ausschließlich Fotos, bei denen Geodaten aus den Dateien (EXIF) entfernt worden sind. Deswegen posten wir unterwegs nur dann vom Smartphone, wenn wir absolut sicher sind, dass keine Koordinaten im Bild enthalten sind.
</li>
<li>
<b>Vor allem halten wir die Klappe</b> und geben nicht mit einer tollen, noch unberührt aussehenden Location an. Deine "Freunde" in Facebook kennst Du oft nicht mal persönlich, schon gar nicht in einer Gruppe. Nichts verbreitet sich schneller als ein "Geheimnis", das unter dem Siegel des Vertrauens weitergegeben wurde. Willst Du daran schuld sein, daß hirnbefreite Sprayer auch diesen Ort demolieren?
</li>
<li>
<b>Wir sorgen durch Argumente und Überzeugung dafür, daß unsere Begleiter sich ebenso verhalten!</b> In erster Linie versuchen wir durch unser eigenes Verhalten zu überzeugen.
</li>
</ol>
<h2 class="LP-Headline">Rechtliches (für Deutschland)</h2>
<ol class="LP-UnorderedList">
<li>
<b>Das Betreten von fremden Grundstücken ist nicht zwangsläufig Illegal.</b> In Deutschland gibt es keinen Tatbestand des Einbruchs, lediglich die dabei begangen Vergehen. Machst du nichts kaputt und stiehlst du auch nichts kann dir nur Hausfriedensbruch zur Lasst gelegt werden. Hausfriedensbruch ist in Deutschland anzeigepflichtig, werdet ihr erwischt notieren sich die Beamten eure Personalien und melden euren Besuch dem Eigentümer des Grundstücks. Dieser Entscheidet ob er gegen euch Anzeige erstattet oder nicht. Erfahrungsgemäß sind den meisten Eigentümern ein paar Leute die nur Fotos machen ziemlich egal, darauf soltet ihr euch aber nicht verlassen.
</li>
<li>
<b>Nehmt einen Ausweis mit</b> solltet ihr erwischt werden müssen die Beamten eure Identität erfassen. Gelingt das nicht vor Ort, werdet ihr einen Ausflug auf die nächste Polizeiwache machen. Darauf haben weder ihr nocht die Beamten lust.
</li>
<li>
<b>Graffiti ist Sachbeschädigung</b> also lasst es lieber sein.
</li>
</ol>
</article>
{% endblock maincontent %}

View File

@ -29,22 +29,22 @@
<b>In a location we are careful not to endanger ourselves or others.</b> We don't throw anything into holes or out of windows, and we don't touch electrical equipment. You can't tell from its look or sound if the power is really switched off. Therefore we do not open bottles and other containers. We never go into a dark room without light, and always have a spare lamp with us.
</li>
<li>
<b>Before my tour we tell at least one person of my trust where we are</b> (coordinates!), how long we will be there and what we will do there. We arrange that we will contact him regularly if we stay there for a longer period of time, or give an "okay" when we have left the location again. If we am late, we will remember to send a message to that effect. Our contact person is supposed to provide help after a certain period of time if he does not hear from me.
<b>Before our tour we tell at least one person of our trust where we are</b> (coordinates!), how long we will be there and what we will do there. We arrange that we will contact him regularly if we stay there for a longer period of time, or give an "okay" when we have left the location again. If we am late, we will remember to send a message to that effect. Our contact person is supposed to provide help after a certain period of time if he does not hear from me.
</li>
<li>
<b>We prepare my tour carefully.</b> It is annoying when the camera batteries are not charged — but it is not dangerous at all. But it is life-threatening if you step unto a dirty nail that perforates your shoe. It is wise to wear sturdy shoes. When we go underground, we take appropiate equipment with us to protect ourselves — e. g. a gas warner or even a geiger counter.
<b>We prepare out tour carefully.</b> It is annoying when the camera batteries are not charged — but it is not dangerous at all. But it is life-threatening if you step unto a dirty nail that perforates your shoe. It is wise to wear sturdy shoes. When we go underground, we take appropiate equipment with us to protect ourselves — e. g. a gas warner or even a geiger counter.
</li>
<li>
<b>We do not park in such a way that third parties become aware of my intention.</b> Our hobby does not need public attention, which is directed to illegal entering of properties (and illegal entering is probably the most common way ...).
<b>We do not park in such a way that third parties become aware of our intention.</b> Our hobby does not need public attention, which is directed to illegal entering of properties (and illegal entering is probably the most common way ...).
</li>
<li>
<b>We do not disclose our locations</b> and only publish photos where geodata has been removed from the files (EXIF). Therefore we only post from my smartphone when we am absolutely sure that no coordinates are contained in the picture.
<b>We do not disclose our locations</b> and only publish photos where geodata has been removed from the files (EXIF). Therefore we only post from our smartphone when we am absolutely sure that no coordinates are contained in the picture.
</li>
<li>
<b>Above all, we keep my mouth shut</b> and don't brag about a great, still untouched looking location. You often don't even know your "friends" in Facebook personally, especially not in a group. Nothing spreads faster than a "secret" that has been passed on under the seal of trust. Do you want to be responsible for brainless sprayers destroying this place too?
<b>Above all, we keep our mouth shut</b> and don't brag about a great, still untouched looking location. You often don't even know your "friends" in Facebook personally, especially not in a group. Nothing spreads faster than a "secret" that has been passed on under the seal of trust. Do you want to be responsible for brainless sprayers destroying this place too?
</li>
<li>
<b>We make sure through argument and conviction that my companions behave the same way!</b> First and foremost we try to convince through our own behavior.
<b>We make sure through argument and conviction that our companions behave the same way!</b> First and foremost we try to convince through our own behavior.
</li>
</ul>
</article>

View File

@ -0,0 +1,4 @@
<form method={{form.method}}>
{{form}}
<input type="submit"/>
</form>

View File

@ -1,4 +1,6 @@
{% load static %}
{% load i18n %}
{% load lostplaces%}
<!DOCTYPE html>
<html lang="en">
@ -10,6 +12,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{% static 'main.css' %}">
<link rel="stylesheet" href="{% static 'materialdesignicons.css' %}">
<link rel="icon" type="image/png" href="{% static 'favicon.ico' %}">
<title>
{% block title %}Urban Exploration{% endblock %}
@ -28,15 +31,16 @@
<span class="LP-Paragraph">
{% if user.is_authenticated %}
Hi {{ user.username }}!
<a class="LP-Link" href="{% url 'logout' %}"><span class="LP-Link__Text">logout</span></a>
<a class="LP-Link" href="{% url 'logout' %}"><span class="LP-Link__Text">{% translate 'Logout' %}</span></a> |
<a class="LP-Link" href="{% url 'explorer_profile' explorer_id=user.pk%}"><span class="LP-Link__Text">{% translate 'Profile' %}</span></a>
{% if user.is_superuser %}
<a class="LP-Link" href="{% url 'admin:index' %}" target="_blank"><span class="LP-Link__Text">admin</span></a>
| <a class="LP-Link" href="{% url 'admin:index' %}" target="_blank"><span class="LP-Link__Text">{% translate 'Admin' %}</span></a>
{% endif %}
{% else %}
You are not logged in.
<a class="LP-Link" href="{% url 'login' %}"><span class="LP-Link__Text">login</span></a> |
<a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">signup</span></a>
<a class="LP-Link" href="{% url 'login' %}"><span class="LP-Link__Text">{% translate 'Login' %}</span></a> |
<a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">{% translate 'Sign up' %}</span></a>
{% endif %}
</span>
</div>
@ -46,14 +50,14 @@
<aside class="LP-Main__Sidebar">
<nav class="LP-Menu LP-Menu--sidebar">
<ul class="LP-Menu__List">
<li class="LP-Menu__Item"><a href="{% url 'lostplaces_home' %}" class="LP-Link"><span class="LP-Link__Text">Home</span></a></li>
<li class="LP-Menu__Item"><a href="{% url 'flatpage' slug='codex' %}" class="LP-Link"><span class="LP-Link__Text">UrBex codex</span></a></li>
<li class="LP-Menu__Item"><a href="{% url 'lostplaces_home' %}" class="LP-Link"><span class="LP-Link__Text">{% translate 'Home' %}</span></a></li>
<li class="LP-Menu__Item"><a href="{% url 'flatpage' slug='codex' %}" class="LP-Link"><span class="LP-Link__Text">{% translate 'UrBex Codex' %}</span></a></li>
{% block additional_menu_items %}
{% endblock additional_menu_items %}
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_create'%}" class="LP-Link"><span class="LP-Link__Text">Create place</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_list'%}" class="LP-Link"><span class="LP-Link__Text">See all places</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_create'%}" class="LP-Link"><span class="LP-Link__Text">{% translate 'Create place' %}</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_list'%}" class="LP-Link"><span class="LP-Link__Text">{% translate 'All places' %}</span></a></li>
</ul>
</nav>
</aside>
@ -85,7 +89,7 @@
</div>
{% block footer %}
{% include 'partials/nav/footer.html' %}
{% partial 'nav/footer' %}
{% endblock footer %}
</body>

View File

@ -0,0 +1,32 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
{% load lostplaces %}
{% block additional_head %}
<link rel="stylesheet" href="{% static 'maps/ol.css' %}" type="text/css">
<script src="{% static 'maps/ol.js' %}"></script>
{% endblock additional_head %}
# {% block title %}{% translate 'Home' %}{% endblock %}
{% block maincontent %}
{% partial 'welcome' %}
<article class="LP-TextSection">
</article>
{% partial 'osm_map' %}
{% set config mapping_config %}
{% set modifier 'wide' %}
{% endpartial %}
<div class="LP-PlaceGrid">
<h1 class="LP-Headline LP-Headline">{% translate 'Explore the latest places' %}</h1>
<ul class="LP-PlaceGrid__Grid">
{% for place in place_list %}
<li class="LP-PlaceGrid__Item">
{% include 'partials/place_teaser.html' with place=place%}
</li>
{% endfor %}
</ul>
</div>
{% endblock maincontent %}

View File

@ -0,0 +1,46 @@
{% extends 'global.html'%}
{% load i18n %}
{% load lostplaces%}
# {% block title %}Start{% endblock %}
{% block maincontent %}
{% partial 'welcome' %}
<article class="LP-TextSection">
<p class="LP-Paragraph">
{% blocktranslate %}You can create, view and share your lost places with other members of this site. You can upload photos, place links to your web galleries and contribute your knowledge by tagging other places or commenting on them. You will find detailed information on where these locations are, how to get there and what to expect from them. This might even include detailed information on the surroundings or the history of a lost place.{% endblocktranslate %}
</p>
{% url 'signup' as signup_url %}
<p class="LP-Paragraph">
{% blocktranslate %}Since vandalism is a growing problem these days, no sensitive information is available to the public. You have to <a class="LP-Link" href="{{signup_url}}"><span class="LP-Link__Text">sign up</span></a> with a voucher code as an invitation to join this community. Only admins can create these codes. Usually you are given a code when we know you in real life in person and when we trust you. A request from an unknown person will most probably be denied.{% endblocktranslate %}
</p>
</article>
<div class="LP-PlaceGrid">
<h1 class="LP-Headline LP-Headline">{% translate 'Explore the latest places' %}</h1>
<ul class="LP-PlaceGrid__Grid">
{% for place in place_list %}
<li class="LP-PlaceGrid__Item">
<a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link">
<article class="LP-PlaceTeaser">
<div class="LP-PlaceTeaser__Image">
{% partial 'image' %}
{% set source_url place.placeimages.first.filename.thumbnail.url %}
{% endpartial %}
</div>
<div class="LP-PlaceTeaser__Meta">
<div class="LP-PlaceTeaser__Info">
<span class="LP-PlaceTeaser__Title">
<h1 class="LP-Headline LP-Headline--teaser">{{place.name|truncatechars:19}}</h1>
</span>
</div>
</div>
</article>
</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock maincontent %}

View File

@ -0,0 +1,16 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
{% block additional_head %}
<link rel="stylesheet" href="{% static 'maps/ol.css' %}" type="text/css">
<script src="{% static 'maps/ol.js' %}"></script>
{% endblock additional_head %}
# {% block title %}{% trans 'Map' %}{% endblock %}
{% block maincontent %}
{% include 'partials/osm_map.html' with config=mapping_config modifier='full' %}
{% endblock maincontent %}

View File

@ -2,9 +2,7 @@
<div class="LP-Input {% if classes%}{{classes}}{% endif %} {% if field.errors %} LP-Input--error {% endif %}">
<label for="{{field.id_for_label}}" class="LP-Input__Label">{{field.label}}</label>
{% with class="LP-Input__Field "%}
{% render_field field class=class%}
{% endwith %}
{% render_field field class+='LP-Input__Field' %}
<span class="LP-Input__Message">
{% if field.errors %}

View File

@ -0,0 +1,9 @@
{% load i18n %}
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">{% if action %}{{ action }}{% else %}{% translate 'Submit' %}{% endif %}</button>
</div>
<div class="LP-Form__Field LP-Form__Button LP-Input">
<a class="LP-Link" href="{% if referer %}{{ referer }}{% else %}{% url 'lostplaces_home' %}{% endif %}">
<button type="button" class="LP-Button LP-Button--cancel">{% translate 'Cancel' %}</button>
</a>
</div>

View File

@ -0,0 +1,14 @@
{%load static %}
{% load i18n %}
{% if request.user %}
{% if place in request.user.explorer.favorite_places.all %}
<a href="{% url 'place_unfavorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Remove from favorites' %}">
<img class="LP-Icon" src="{% static '/icons/favorite_filled.svg' %}" />
</a>
{%else%}
<a href="{% url 'place_favorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Save as favorite' %}">
<img class="LP-Icon" src="{% static '/icons/favorite.svg' %}" />
</a>
{% endif %}
{% endif %}

Some files were not shown because too many files have changed in this diff Show More