Compare commits

..

288 Commits

Author SHA1 Message Date
ce0e47786f Squash migrations 2021-01-23 19:11:28 +00:00
0ed7dc4834 Small alignment fix in asset list 2021-01-23 17:43:33 +00:00
4ca4ea9812 Should fix calendar breaking in production 2021-01-23 17:41:06 +00:00
fe38d5cf36 Add icons to H&S menu items 2021-01-23 17:25:56 +00:00
72221e46bc Further minor fixes to versioning 2020-12-27 18:48:45 +00:00
0e656b4c41 FIX: Stupid typo in versioning.py 2020-12-27 18:42:24 +00:00
a0c6793cf6 Why does this work
Indeed, it may not
2020-12-27 18:28:02 +00:00
80837c3d9a Fixing tests for new logic etc 2020-12-27 17:50:53 +00:00
c027182962 More moving of event size logic 2020-12-14 21:58:21 +00:00
dd95447008 Javascript required shenanigans for RA power 2020-12-13 17:18:35 +00:00
13fcadaf79 Start move of event size logic to RA from Ec 2020-12-13 16:48:06 +00:00
124b7a8e51 Add space for power/rigging plans to be linked to RAs 2020-12-13 16:26:08 +00:00
dfdbcb651f Test fixes 2020-12-13 16:07:33 +00:00
e0615f318c Implement some of Jonny's suggested changes
TODO:
- Define event size at RA time, pass through to EC
- Have later power questions be context dependent
2020-11-16 18:31:37 +00:00
97b29bc549 Merge branch 'master' into bs4 2020-11-15 16:54:21 +00:00
0aa10d86cd Improvements to profile detail page 2020-11-15 16:53:11 +00:00
06e22b0d61 Update emergency contact number 2020-11-15 16:01:39 +00:00
ac916247a6 Allow H&S for non-events 2020-11-12 12:47:47 +00:00
bbc4d1d390 FEAT: Implement #413 show associated assets on cable type detail pg
Closes #413
2020-10-30 00:44:18 +00:00
4b76b77806 FIX: Do not naively cache event table
Not that easy, it turns out. Duh.
2020-10-25 21:54:13 +00:00
44fef39a2e Fix recent change stream list mutation issue 2020-10-25 18:18:24 +00:00
d06895bf96 Fix one test, break another... 2020-10-25 16:26:05 +00:00
e9a29f9444 Implement Jerb's wording changes 2020-10-24 20:33:14 +01:00
14e12f0fb9 Made radio button focus much more obvious on dark theme 2020-10-24 20:24:40 +01:00
7f9a7bba8b Fix cable test 2020-10-24 19:52:26 +01:00
20d4ddd5cf Rework version name method to avoid blank names on eventchecklist vehicles/crew 2020-10-24 19:38:11 +01:00
e6eed9f2f2 First pass at porting calendar from FC V3 to V5
Two major versions and all they did was rename a bunch of names...TWICE.
2020-10-19 00:13:06 +01:00
320ace1a0e Use borders rather than block colors for coloured tables under darktheme 2020-10-18 23:03:05 +01:00
ab2c2f65f0 Fix event table success logic
Yay for copy paste fails >.>
2020-10-18 12:28:28 +01:00
8a4fcdcecb First pass at making the calendar less crap 2020-10-18 11:56:00 +01:00
529941224e Make version changes badges more readable 2020-10-18 11:23:16 +01:00
59756ab86a Remove animation on prefers-reduced-motion/low referesh rate devices
Also normalises handling of asset list cable table & improves its use of space on large devices
2020-10-18 11:15:04 +01:00
7736a2d3cc Fix horizontal-ness on some forms 2020-10-17 18:59:55 +01:00
30df597144 Remove enforced linebreak on status chips 2020-10-17 18:15:15 +01:00
4bb1c0a2a4 More search and replace for BS changes
Thought I'd got them all. Clearly not!
2020-10-17 18:11:42 +01:00
848e8c8ccd Remove lingering use of 'page-header'
BS removed that style
2020-10-17 17:59:23 +01:00
0fee753284 Put rounded corners back where they belong 2020-10-17 17:45:09 +01:00
bb4d31477e Fix caching 2020-10-15 17:32:18 +01:00
3d7ff435c9 Display note icon on event detail page 2020-10-15 14:57:50 +01:00
a950b941ca Move status color logic back to template
Cause that somehow makes it work better??
2020-10-15 14:57:50 +01:00
f57dc9f765 Fix autocompleter.js to properly disable edit links again 2020-10-14 13:30:23 +01:00
8b2f2a9354 Fix tests / default to headless tests
(fingers crossed)
2020-10-13 09:46:24 +01:00
d255e1f89f First pass at clearer display of asset list filters 2020-10-12 23:03:33 +01:00
fd85d50679 Remove flash of content when loading new rig page 2020-10-12 22:16:09 +01:00
2cb5453b82 H&S Details takes up free space on non-internal events 2020-10-12 21:47:18 +01:00
0f019e26a0 Same perm check for generic details 2020-10-12 21:44:02 +01:00
e926731e67 Generic list only displays edit button if user has perm 2020-10-12 21:38:31 +01:00
b69883cc90 Give keyholders supplier edit perm 2020-10-12 21:18:59 +01:00
a0e1702de4 (probably) fix tests 2020-10-12 10:16:15 +01:00
8c8c580bfb Clearer logic for RA inverted fields 2020-10-10 14:25:15 +01:00
49a2bc83ab Make venue/date editable on EC
For multi venue, multi day events

Defaults to date and venue set on the event. Also made power MIC default to that set in RA
2020-10-10 14:15:26 +01:00
026e2a0b03 Fix migration 2020-10-10 12:39:48 +01:00
3cb0d82130 Initial pass at soop-consult confirmation screen for RAs 2020-10-10 12:35:55 +01:00
5a5bb4328d Minor typo fixes 2020-10-10 10:24:21 +01:00
58b1867a13 Curses! 2020-10-09 17:55:23 +01:00
d7678f6b6f Update polyfill for datetime-local
Bloody Firefox. We love to hate you. Proper CSS of the fill to come, SoonTM.

Closes #391
2020-10-09 17:38:07 +01:00
7f3a169875 FIX: Set duplicated event status to provisional
Closes #398.

Flip flop. Flip flop.
2020-10-09 16:45:33 +01:00
5a99560310 Buggerit millennium hand and shrimp
Knew I was gonna forget to fix the tests
2020-10-09 13:06:25 +01:00
12a60e1f50 Correct handling of spaces in paperwork filenames
Also normalises display of Invoice IDs. Partial fix for #391.
2020-10-09 12:48:59 +01:00
934c07be72 Fix dependency hell
Probably
2020-10-09 11:52:52 +01:00
3602da9203 Fixes fixes fixes 2020-10-09 09:42:15 +01:00
f41064abfa Upgrade dependencies 2020-10-09 09:25:23 +01:00
ee9dbf8944 Display tick/cross rather than true/false in boolean version diffs 2020-10-09 01:37:30 +01:00
565e757758 And now the same for generic forms 2020-10-09 01:26:42 +01:00
5af075946a One of these days I'll remember to test BEFORE pushing... 2020-10-08 23:29:11 +01:00
5d56f4f7b0 Also apply better approach to generic detail pages 2020-10-08 23:15:55 +01:00
3903481b3d Better approach to generic list templates + other deduplication 2020-10-08 22:54:30 +01:00
af7d3c4070 Revert "Prevent creating duplicate revisions on event"
Apparently it was too strong at preventing dupes...

This reverts commit cce0ad0f9f.

# Conflicts:
#	RIGS/models.py
2020-10-07 17:31:17 +01:00
025a31f15a Minor test fixes 2020-10-07 17:29:31 +01:00
2db2cc6659 Template improvements 2020-10-07 17:05:51 +01:00
cce0ad0f9f Prevent creating duplicate revisions on event
Potential fix for #322 - I couldn't reproduce even before this change...
2020-10-07 17:05:40 +01:00
ae13cabe09 Properly handle eventauthorisations in new versioning
It's not great, not terrible...
2020-10-07 16:46:28 +01:00
abf3cfe1ce Fix tests 2020-10-06 23:04:25 +01:00
7c79a6afdd Rigboard Timing display tweaks 2020-10-06 16:53:45 +01:00
350a301b36 Kill off excess whitespace on rigboard 2020-10-06 16:42:36 +01:00
2f8e09906b Switch rigboard new button to primary 2020-10-06 16:18:27 +01:00
50ae3022cd Redo light theme palette 2020-10-06 16:12:23 +01:00
f147f19140 Fix event checklist on mobile 2020-10-06 16:08:38 +01:00
0b751d62df Mobile fixes for search 2020-10-06 16:08:31 +01:00
acf814e49e Rework button tag 2020-09-30 09:08:50 +01:00
f70421b8ca Fix tests 2020-09-30 09:08:20 +01:00
84c4ec03de Minor event detail fixes 2020-09-29 19:24:22 +01:00
813b1dac85 Allow multiple event checklists per event
TODO: Status chip now needs rethinking
2020-09-29 18:08:55 +01:00
0117002b01 Initial work on BS4 button templatetag
Newfeatureitis strikes again
2020-09-29 17:41:40 +01:00
932180f99f Fix rigboard validation tests 2020-09-29 17:41:01 +01:00
70de16ed5c Fix errors being squashed 2020-09-29 17:37:54 +01:00
8424424d49 Fix #326 (again) 2020-09-29 17:17:53 +01:00
a78bb19015 Asset detail template improvements 2020-09-28 10:38:59 +01:00
bea762b12b Begin to improve event checklist on mobile 2020-09-28 10:32:57 +01:00
70cc554094 Begin to change add buttons success -> primary
Also change search primary -> info to avoid clash
2020-09-28 10:32:45 +01:00
1dad8d2ba5 Tweak asset list markup 2020-09-28 10:32:00 +01:00
c38105a76e Use template filter for consistent removal of 'None links'
Plus cleaner template markup! More HTML-in-Python tho, which always feels a bit CSS-in-JS
2020-09-28 10:31:43 +01:00
6936b94ce6 Put power threshold values in a collapse 2020-09-28 10:30:58 +01:00
74066e9484 Remove database ID from generic list 2020-09-28 09:22:10 +01:00
018397d28e Add ability to mark event checklists as Large Event
This just disables the checks to allow the rest of it to be filled out for large events, though I expect paper forms may still be used...
2020-09-25 22:06:06 +01:00
143b654210 Major improvements/fixes to authorisation templates 2020-09-25 21:29:00 +01:00
2a1bb57c74 More fixes 2020-09-19 18:03:24 +01:00
77c82efce6 More tweaks 2020-09-19 13:46:55 +01:00
1ea8090668 Minor fixes 2020-09-19 13:39:58 +01:00
31f63ba5c7 Invoice template improvements 2020-09-18 12:33:10 +01:00
9739af765f Curse youuuuu pep8 2020-09-17 12:04:41 +01:00
b90be708d0 Fix for my fix 2020-09-17 11:31:32 +01:00
dcc0e53062 Various misc fixes 2020-09-17 09:32:57 +01:00
ce5a92dfa8 Add revision history to invoices/payments.
Also patches previously introduced reversion permissions hole.

Supersedes and closes #337.
2020-09-16 11:37:56 +01:00
fd926aef85 Fix broken invoice list template 2020-09-15 10:39:01 +01:00
1ecc508b0d Fix wrong variable name in settings.py 2020-09-15 10:29:28 +01:00
a5516ee350 Cleanup & Squash migrations 2020-09-15 10:01:52 +01:00
5487b73006 Much better coverage of H&S things 2020-09-15 01:23:45 +01:00
6426880708 Pages/start of tests for EventChecklists 2020-09-14 16:26:02 +01:00
aa0184a5dc Initial work on RA tests 2020-09-12 14:00:03 +01:00
eb7d8e49e8 Merge branch 'master' into bs4
# Conflicts:
#	RIGS/templates/RIGS/index.html
#	requirements.txt
2020-09-12 11:19:46 +01:00
b959ca13a5 Formatting... 2020-09-12 10:30:33 +01:00
d8e6f2f9c1 Why does this work
Bloody overzealous autoformatter...
2020-09-12 10:26:47 +01:00
1cf910752f Modify auth test so it doesn't try and test for external authorisations
Cause that's not a thing
2020-09-12 10:14:16 +01:00
cf7ada3d9e Test fixes 2020-09-12 10:08:47 +01:00
ba6dbc6980 Rethink rigboard color logic again
Also revert some broken stuff
2020-09-12 10:07:58 +01:00
6d836ee4dd Fix cable table template 2020-09-12 10:07:31 +01:00
e602058771 Fix list templates
TODO: Sensible place to define the 'expected answer' stuff.
2020-09-03 13:02:30 +01:00
c1182efa54 Use template filter for notes 2020-09-01 15:15:15 +01:00
87e831a468 Event properties internal/authorised always return a explicit boolean rather than sometimes None 2020-09-01 15:02:16 +01:00
1d5429052f Restrict versioning to one level of depth for speed
Also fixed the template for nested changes
2020-09-01 13:41:12 +01:00
6ee9efa39e Audit template fixes 2020-09-01 13:13:44 +01:00
945e521feb Do event table color logic at python level 2020-08-31 13:45:32 +01:00
689124a891 Templating improvements to RA/EC stuff 2020-08-31 13:09:47 +01:00
8842c2c3d9 Worst case points on checklist 2020-08-30 20:50:06 +01:00
f3c2ce2519 Validation of power reqs 2020-08-30 12:26:50 +01:00
bfe80db85e Misc fixes 2020-08-30 10:48:19 +01:00
9198724748 Medium event power stuff done, barring worst case stuff 2020-08-29 23:56:08 +01:00
dbe0d35400 Event checklist crew works
Mostly - its not happy with timezones
2020-08-29 22:01:23 +01:00
1feb9449ed Cleanup 2020-08-29 17:31:41 +01:00
d708207ab9 Versioning module now does magic
Automatic creation of views/urls for anything registered with reversion, with a small amount of hackage to preserve legacy stuff. (and the DAMNED asset IDs!) I would never get distracted...
2020-08-29 16:24:11 +01:00
8ea96674db Initial work on new checklist handling. No more JSON! 2020-08-29 13:56:57 +01:00
de04498517 Insert a divider between still-out dry hires and actually upcoming events on rigboard 2020-08-27 17:38:26 +01:00
828964ecb6 Alter rig_count to not include un-checked-in dry hires 2020-08-27 17:08:51 +01:00
3438489934 Add new line functionality for vehicles/drivers
Might it have been easier to create 'dummy' models like with EventItems? Probably...
2020-08-27 02:20:46 +01:00
9cf081efc7 Proof of concept for JSON parsing/storage
\o/
2020-08-25 16:00:19 +01:00
8bb08724b6 Initial shenanigans on storing my overly fancy EC form 2020-08-24 17:25:25 +01:00
da60cad911 Mooooore status chips, mooore 2020-08-24 13:43:03 +01:00
a6ac55baaf Add a button for creating and instantly voiding invoices
Handy dandy for when you have loads of cancelled events, like say, a pandemic
2020-08-24 12:25:24 +01:00
d3f55523da Start work on event checklist 2020-08-14 17:30:57 +01:00
d3d7c052af Invalidate RA review if it is edited after review 2020-08-14 16:04:27 +01:00
902476ebab Fix Power MIC being lost on RA edit
Why it is subtly different to the Event Update behaviour? Who knows
2020-08-06 10:51:44 +01:00
4514de137a Add reviewing to revision history, fix RA editing not working
Also actually commit all the files, that helps
2020-08-05 22:31:50 +01:00
92377227e0 Start RA 'mark review' feature 2020-08-05 20:51:31 +01:00
b88554a57f Style fixes to asset list 2020-08-04 19:09:47 +01:00
9d6948e326 Fixed search for events 2020-08-04 19:03:38 +01:00
67bf60e246 Properly fixed popover darktheme 2020-08-04 19:00:12 +01:00
2e60c5e7bf Do not use Django 'required' for radio selects
As this requires them to be True, whereas we just need to require that an option be entered.
2020-07-03 17:09:32 +01:00
d09f3994fc Bunch of dark mode fixes from test page 2020-07-03 16:42:40 +01:00
79eb0cbff0 Add bootstrap 4 test page 2020-07-03 14:40:42 +01:00
d800a781a5 Fixes to revisions for RAs 2020-07-02 20:13:24 +01:00
721439d095 More RA fixes 2020-07-02 19:26:27 +01:00
b57b918247 Remove the defaults from the RA fields + make them required 2020-07-02 19:20:20 +01:00
1dfaa4d7a8 Disable mobile event table PoC for now 2020-07-02 19:00:45 +01:00
1138cfcde5 Make supplier detail use the generic template 2020-06-25 19:31:51 +01:00
cd168d93ed Match darktheme palette to forum darktheme palette
Why reinvent the wheel.
2020-06-25 19:15:09 +01:00
a4ef69af3c Dark theme palette shenanigans
I just can't decide
2020-06-25 18:59:24 +01:00
be48dd31f9 Testing something re notes
I wonder if I can make that global, rather than per-template...
2020-06-25 18:59:24 +01:00
a6cee78198 Genercise detail pages 2020-06-25 17:51:00 +01:00
d50d2bd0ad Move dark theme SCSS to separate file, fix inactive pagination styling 2020-06-25 14:40:12 +01:00
3ceb48876d Fix reload loops when CSS/JS is changed 2020-06-25 14:20:36 +01:00
8820ed1e67 Remove the dark header from light theme 2020-06-24 12:23:41 +01:00
86fe8a8e1b further darktheme fixes 2020-06-24 12:15:47 +01:00
8a9eefb722 Fix table colors for dry hires 2020-06-24 12:11:11 +01:00
b28377e1f5 Dark mode colour improvements 2020-06-24 12:05:17 +01:00
141e1c94d7 Fix tests for search improvements 2020-06-19 11:22:06 +01:00
eafb394f55 Move closemodal into PyRIGS 2020-06-19 11:10:01 +01:00
84618deac0 FEAT: Improve 'omni'search
- Partialised template
- Added to assets header
- Added ability to search assets/suppliers
- Improved selection logic
- Have it display current query
2020-06-19 11:07:25 +01:00
e4e8823a1a Fix navbar alignment 2020-06-19 10:38:13 +01:00
cb1a8e1627 Fix for a situation that should be impossible 2020-06-19 10:38:02 +01:00
c65330cb91 Update dependencies 2020-06-19 10:37:47 +01:00
6e7fa267bc Add global ctrl/meta-enter shortcut for form submission
Wants rewriting for better efficiency, but hey, it works!
2020-06-15 16:15:23 +01:00
9e1d146b7a Update dependencies
Mirrors/supersedes 0e67da82e2
2020-06-05 18:24:29 +01:00
aedb4c24db Use locmem cache in sqlite environments
Otherwise the tests just lock up totally. Should close #162
2020-06-04 23:36:31 +01:00
1239fbf185 Fix lingering naive time 2020-06-04 23:28:33 +01:00
7035731655 Add ability to filter event archive by status
Closes #168.
2020-06-04 22:58:19 +01:00
a7c4b90161 Display venue notes in event detail
Notes are no use if nobody reads them. Not sure on this one.
2020-06-03 15:17:07 +01:00
9e93d895ba Add H&S Details to Event Detail View 2020-06-03 15:15:23 +01:00
d31900c5c3 Refactor RA creation stuff, again 2020-06-03 15:15:02 +01:00
3768f4a613 Start RA list template 2020-05-30 17:19:11 +01:00
6867359146 Initial work on caching activity feed
Server side that is. Ref #162.
2020-05-30 15:50:32 +01:00
e45324f5b4 Refactor activity feed template logic
Yay for removing arbitrary if/else chains!
2020-05-30 14:07:50 +01:00
156e639bac Initial work at coercing activity feed into showing RAs
Also shows Asset/Supplier on the homepage feed.
2020-05-29 15:45:16 +01:00
0e2adf3f0d Use correct view for RA history 2020-05-29 15:18:52 +01:00
eb0c027ff9 Expand detail template 2020-05-29 15:15:37 +01:00
93504997fe FIX: Undo breakage causing autopep8
o.O
2020-05-28 23:19:22 +01:00
d3b3d1c9d7 Move text definitions to somewhere more authoratitive 2020-05-28 23:02:47 +01:00
4cfd83eeb3 Different approach to RA linking 2020-05-28 21:46:39 +01:00
00226e9c22 FIX: Don't set every boolean input to radios 2020-05-28 21:46:16 +01:00
b75b6a6736 Initial work at integrating the risk assessment
#136. No clever database structure as yet...
2020-05-28 18:55:22 +01:00
1b1775d0f5 Fix sample command 2020-05-27 18:49:03 -04:00
14d211326e FIX: CI Locale Issues 2020-05-27 18:38:58 -04:00
4081918598 Fix some asset template things 2020-05-27 17:06:50 +02:00
b742d3f8c4 More dark theme wangling 2020-05-27 17:01:55 +02:00
06d7ef0b79 Merge remote-tracking branch 'origin/bs4' into bs4 2020-05-27 04:26:15 +02:00
06f67f4f32 Very initial work at togglable darktheme.
Dammit @alexdaniel654 just when I had my scope creep kinda under control. It'll be v. nice to have though...!
2020-05-27 04:24:58 +02:00
Matthew Smith
170c2f6d8c Fixed Pep8 - I promise I'll make a pre-commit hook sometime! 2020-05-27 01:59:18 +01:00
Matthew Smith
f37228e058 Fixed RIGS tests not being run 2020-05-27 01:53:14 +01:00
Matthew Smith
6d47be72fe Added screenshot recording of test failures 2020-05-27 01:47:10 +01:00
6ded711dd5 Try disabling chrome cache 2020-05-26 15:26:03 +01:00
920ea0d058 What about if I did this 2020-05-26 15:10:27 +01:00
e45e58321c Revert to old submit wait behaviour 2020-05-26 15:02:44 +01:00
3f78b9f05f That was even less clever of me 2020-05-26 14:39:12 +01:00
0bbc23853d Well that wasn't clever of me 2020-05-26 13:42:37 +01:00
7356d020b2 Minor test futzing 2020-05-26 13:35:50 +01:00
08f40bce9e Update python version
Trying to get CI to match my local environment as much as possible...
2020-05-26 01:39:15 +01:00
1d0e8e14e5 Of course | is part of YAML syntax, of course...
Maybe this works.
2020-05-26 01:23:38 +01:00
b52709f412 Make CI use latest (stable) chromedriver rather than some ancient one
Since Travis uses the latest stable chrome, should always match. Bash oneliner \o/
2020-05-26 00:52:42 +01:00
c4c4291050 Fix asset creation test + actually verify its results 2020-05-26 00:22:06 +01:00
07641a2520 Ensure submit button is scrolled to in tests 2020-05-26 00:17:02 +01:00
fd6aee83cf Fix the remaining tests 2020-05-25 22:49:07 +01:00
177c37ffbc Dedupe generic search logic 2020-05-25 22:47:25 +01:00
d070f97696 Fully replace test_functional 2020-05-25 16:16:38 +01:00
2f7389d8bb Really ought to get a pre-commit hook for pep8... 2020-05-25 13:40:53 +01:00
18fde7c16a FIX: Don't show asset buttons/history for basic users 2020-05-25 13:36:42 +01:00
f06dc56b40 Refactor calendar tests 2020-05-25 13:32:09 +01:00
e6d06db2a1 FIX: Prevent setting access time after start time
Cherry pick of d274ea4606. Will close #405.
2020-05-25 01:16:26 +01:00
544b6df35c Fix some tests
And some things that were actually borked
2020-05-24 22:16:50 +01:00
c9ea1bb75d pep8 2020-05-24 19:24:51 +01:00
928d5cd8e6 Deduplication of testing code 2020-05-24 19:16:09 +01:00
cc225b2eb7 Refactor date validation test
So close to killing test_functional.EventTest!
2020-05-24 00:27:41 +01:00
3c0005ddb0 Initial port of duplicate testing
Needs the latter half rewriting once we have an EventDetail POM
2020-05-23 23:48:11 +01:00
Matthew Smith
8ffb5ab23e Updated bootstrap-select for BS4 2020-05-22 00:38:04 +01:00
34bf49876b Upgrade bootstrap-select 2020-05-21 22:57:28 +01:00
813db2c474 Initial refactor of event item testing 2020-05-21 22:48:46 +01:00
919975e1ba Fix event item adding
Bit too heavy handed with the deduplication there Arona
2020-05-21 22:18:04 +01:00
0d0c783e07 Desaturate theme colors even more
Much closer to BS3
2020-05-21 21:26:56 +01:00
c23d18cd45 Init other tests, more rigs test faffery 2020-05-21 21:19:53 +01:00
5a3547ea74 Initial work on event create test reimpl 2020-05-21 02:40:14 +01:00
e3c1da9d13 Start on new tests 2020-05-11 23:04:13 +01:00
3f48c51aeb Fix migrations
TODO - need to ensure moved models are *moved* rather than deleted and recreated!
2020-04-15 19:42:42 +01:00
abb8dc25ec Test Refactor Part 1 - Shuffle things around 2020-04-15 19:40:49 +01:00
70995a0d0b Merge branch 'master' into bs4
# Conflicts:
#	assets/models.py
#	assets/templates/asset_update.html
#	assets/templates/partials/asset_buttons.html
#	assets/templates/partials/asset_list_table_body.html
#	assets/views.py
#	templates/base_assets.html
2020-04-15 16:28:44 +01:00
5e60675115 Python Format/import opt 2020-04-12 20:10:35 +01:00
f308a095f3 Breakout (most) user stuff to separate module
The model remains in RIGS for now, as it's pretty painful to move...
2020-04-12 19:22:03 +01:00
2bf643cd7a Use the right autocompleter.js... 2020-04-12 18:47:09 +01:00
c8d0c0d5d0 Asset form fixes 2020-04-06 15:17:14 +01:00
176324ed79 Tweak versioning templates to allow ID overrides
Asset specific templates begone. Still need to bring back the ID formatting for the Rigboard.
2020-04-06 14:59:10 +01:00
d216dd4c74 Versioning template improvements
//TODO Rather than have seperate asset templates, convert 'id' into a template variable
2020-04-06 03:15:43 +01:00
55e37d8c69 Tweak asset list to be more in line with other lists 2020-04-06 02:50:36 +01:00
7aa19cc7ab Asset list table improvements 2020-04-06 02:43:20 +01:00
4c40226bcf Fixed fullcalendar print css not included 2020-04-06 02:43:20 +01:00
d351d9eb7b Item table fixes 2020-04-06 02:43:19 +01:00
de210caa36 First pass at mobile-ising the generic list 2020-03-25 00:51:03 +00:00
0271840f4d Improvements to event table mobile 2020-03-24 22:54:35 +00:00
7a08f2d889 Tweak some colours to be a bit less OTT
I need to work out if I can seperate background and primary colours like BS3 did
2020-03-24 22:54:34 +00:00
ee7ba3ea19 Improvements to generic lists 2020-03-22 12:47:32 +00:00
41b0387e49 Reduced overall font size a touch 2020-03-22 12:15:55 +00:00
50ca782569 Start reworking invoice things 2020-03-18 18:38:37 +00:00
0144bd37fc Start to seperate versioning into its own app 2020-03-18 17:36:09 +00:00
959097286c Stop the navbar from sticking to the top of screen 2020-03-18 15:18:50 +00:00
264b306b2f Add a skip link for keyboard users
Someone might use it...
2020-03-18 15:07:29 +00:00
e42989637e Ditch custom loading in favour of BS4 inbuilt
It's less pretty/cool...I may bring it back in future but this'll do for now.
2020-03-18 01:46:13 +00:00
12d8b46f86 First pass at reworked rigboard layout on mobile 2020-03-18 01:39:21 +00:00
89ddb09459 Port (most) RIGS urls to path() 2020-03-18 00:40:45 +00:00
f4f8c6b417 Delete obsolete code 2020-03-18 00:30:23 +00:00
36556dea33 Add the usual set of fields to supplier and update form accordingly 2020-03-17 20:07:14 +00:00
b9d318e675 Whitelist ins/del tags in activity popovers 2020-03-17 18:41:26 +00:00
b8931a64c8 Remove unused dependencies 2020-03-16 23:27:25 +00:00
cfe0a264e7 Pagination fixes 2020-03-16 23:24:03 +00:00
8fbe9f9026 Bring colours back to the rigboard 2020-03-16 23:12:21 +00:00
fe0e4063d7 Work on event archive template 2020-03-16 22:47:38 +00:00
0bd4b281d1 Convert some urls to path 2020-03-16 22:47:26 +00:00
7de778a57e Work on event creation form 2020-03-16 22:35:59 +00:00
88b34740f6 Asset list/CRUD template updates 2020-03-16 21:45:04 +00:00
e0e4e8d11e pycodestyle 2020-03-16 21:19:09 +00:00
c1d277be9c Authorisation template work 2020-03-15 23:08:49 +00:00
4a71dd0d95 AssetList template update 2020-03-15 21:33:05 +00:00
2bfecb9c0f Improvements to generic list + use for supplier 2020-03-15 18:38:51 +00:00
3814f5abfc Generic list template 2020-03-15 18:25:05 +00:00
4c34e4e43e Reimpl custom css - Open Sans is back! 2020-03-15 17:14:12 +00:00
3f36f66b8a Fix up header search 2020-03-15 15:19:39 +00:00
7cef4d03c0 Contain the navbar 2020-03-15 13:48:30 +00:00
6970c5c490 Activity feed updates 2020-03-15 10:33:08 +00:00
b8ea3d3d42 Dependency update 2020-03-15 10:10:39 +00:00
366a14408b More messing with the rigboard 2020-03-15 03:10:33 +00:00
270b1fc5bb Various template changes 2020-03-15 02:53:12 +00:00
7786512dc2 Inital work on adding development livereload 2020-03-15 01:35:00 +00:00
88ac1b93ae Re-enable calendar 2020-03-10 18:03:05 +00:00
4d845309c9 btn-default -> btn-secondary 2020-03-10 17:20:13 +00:00
3b8789e49e More refactoring of rigboard 2020-03-10 16:46:53 +00:00
1526a2f22b Start to move search bar into header
Broken because my scripts are all over the place
2020-03-10 14:33:50 +00:00
fe71f7640f Migrate user urls to PyRIGS module 2020-03-10 14:08:47 +00:00
b57716f7fc Port from glyphicons to Font Awesome
Mmmm pretty
2020-03-09 23:18:56 +00:00
320c43e472 Initial refactor of rigboard template 2020-03-09 22:44:54 +00:00
1e5fcbdba0 Mostly reimplement rigboard navbar 2020-03-09 22:36:22 +00:00
1df1784d02 Move rigboard templates up a level
Also:
- Find and replace panel -> card
- Some base template work
- gulpfile things, added dep on django-gulp
2020-03-09 21:44:09 +00:00
6c72f070f2 Begin moving to NPM/Gulp based build system
There are too many options.
2020-03-07 23:00:45 +00:00
53 changed files with 6132 additions and 6263 deletions

View File

@@ -1,9 +1,6 @@
[run]
source =
./
plugins =
django_coverage_plugin
omit =
*/migrations/*
*/tests/*

View File

@@ -1,83 +0,0 @@
name: Django CI
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
build:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]')"
strategy:
matrix:
test-group: ["RIGS.tests.test_unit RIGS.tests.test_models RIGS.tests.test_functional", "versioning.tests.test_versioning", "users.tests.test_users"]
parallel: [true]
include:
- test-group: "assets.tests.test_assets"
parallel: false
- test-group: "RIGS.tests.test_interaction"
parallel: false
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Cache python deps
uses: actions/cache@v2
with:
path: ${{ env.pythonLocation }}
key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}
- name: Setup Chromedriver
if: \!${{ matrix.parallel }}
run: |
wget https://chromedriver.storage.googleapis.com/2.36/chromedriver_linux64.zip
unzip chromedriver_linux64.zip
export PATH=$PATH:$(pwd)
chmod +x chromedriver
export PATH=$PATH:/usr/lib/chromium-browser/
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install pycodestyle coverage coveralls django_coverage_plugin
pip install --upgrade --upgrade-strategy eager -r requirements.txt
python manage.py collectstatic --noinput
- name: Basic Checks
run: |
pycodestyle . --exclude=migrations,importer*
python manage.py check
python manage.py makemigrations --check --dry-run
- name: Run Tests
if: \!${{ matrix.parallel }}
run: coverage run manage.py test ${{ matrix.test-group }} --verbosity=2
- uses: actions/upload-artifact@v2
if: failure() # Screenshots only make sense for the non-parallel, i.e. interaction tests anyway
with:
name: failure-screenshots ${{ matrix.test-group }}
path: screenshots/
retention-days: 5
- name: Run Tests (Parallel)
if: ${{ matrix.parallel }}
run: coverage run manage.py test ${{ matrix.test-group }} --parallel --verbosity=2
- name: Upload Coverage
run: coveralls --service=github
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_FLAG_NAME: ${{ matrix.test-group }}
COVERALLS_PARALLEL: true
coveralls:
name: Indicate completion to coveralls.io
needs: build
runs-on: ubuntu-latest
container: python:3-slim
steps:
- name: Finished
run: |
pip3 install --upgrade coveralls
coveralls --service=github --finish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.idea/.name generated Normal file
View File

@@ -0,0 +1 @@
PyRIGS

5
.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/pyrigs.iml" filepath="$PROJECT_DIR$/.idea/pyrigs.iml" />
</modules>
</component>
</project>

5
.idea/scopes/scope_settings.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<component name="DependencyValidationManager">
<state>
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</state>
</component>

7
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

1156
.rubocop.yml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,7 @@
*.sqlite3
*.scss
*.md
*.rb
Vagrantfile
config/vagrant/*
config/vagrant.yml

37
.travis.yml Normal file
View File

@@ -0,0 +1,37 @@
language: python
python:
"3.8"
cache: pip
addons:
chrome: stable
before_install:
- export LANGUAGE=en_GB.UTF-8
install:
- |
latest=$(wget -qO- https://chromedriver.storage.googleapis.com/LATEST_RELEASE)
wget https://chromedriver.storage.googleapis.com/$latest/chromedriver_linux64.zip
- unzip chromedriver_linux64.zip
- export PATH=$PATH:$(pwd)
- chmod +x chromedriver
- pip install -r requirements.txt
- pip install coveralls codeclimate-test-reporter pycodestyle
before_script:
- export PATH=$PATH:/usr/lib/chromium-browser/
- python manage.py collectstatic --noinput
script:
- pycodestyle . --exclude=migrations,importer*
- python manage.py check
- python manage.py makemigrations --check --dry-run
- coverage run manage.py test --verbosity=2
after_success:
- coveralls
- codeclimate-test-reporter
notifications:
webhooks: https://fathomless-fjord-24024.herokuapp.com/notify

View File

@@ -13,7 +13,6 @@ import os
import raven
import secrets
import datetime
from envparse import env
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
@@ -21,15 +20,15 @@ BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY', default='gxhy(a#5mhp289_=6xx$7jh=eh$ymxg^ymc+di*0c*geiu3p_e')
SECRET_KEY = os.environ.get('SECRET_KEY') if os.environ.get(
'SECRET_KEY') else 'gxhy(a#5mhp289_=6xx$7jh=eh$ymxg^ymc+di*0c*geiu3p_e'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG', cast=bool, default=True)
DEBUG = bool(int(os.environ.get('DEBUG'))) if os.environ.get('DEBUG') else True
STAGING = env('STAGING', cast=bool, default=False)
STAGING = bool(int(os.environ.get('STAGING'))) if os.environ.get('STAGING') else False
CI = env('CI', cast=bool, default=False)
CI = bool(int(os.environ.get('CI'))) if os.environ.get('CI') else False
ALLOWED_HOSTS = ['pyrigs.nottinghamtec.co.uk', 'rigs.nottinghamtec.co.uk', 'pyrigs.herokuapp.com']
@@ -175,7 +174,10 @@ else:
}
RAVEN_CONFIG = {
'dsn': env('RAVEN_DSN', default=""),
'dsn': os.environ.get('RAVEN_DSN'),
# If you are using git, you can also automatically configure the
# release based on the git info.
# 'release': raven.fetch_git_sha(os.path.dirname(os.path.dirname(__file__))),
}
# User system
@@ -188,8 +190,10 @@ LOGOUT_URL = '/user/logout/'
ACCOUNT_ACTIVATION_DAYS = 7
# reCAPTCHA settings
RECAPTCHA_PUBLIC_KEY = env('RECAPTCHA_PUBLIC_KEY', default="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI") # If not set, use development key
RECAPTCHA_PRIVATE_KEY = env('RECAPTCHA_PUBLIC_KEY', default="6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe") # If not set, use development key
RECAPTCHA_PUBLIC_KEY = os.environ.get('RECAPTCHA_PUBLIC_KEY',
"6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI") # If not set, use development key
RECAPTCHA_PRIVATE_KEY = os.environ.get('RECAPTCHA_PRIVATE_KEY',
"6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe") # If not set, use development key
NOCAPTCHA = True
SILENCED_SYSTEM_CHECKS = ['captcha.recaptcha_test_key_error']
@@ -198,13 +202,13 @@ SILENCED_SYSTEM_CHECKS = ['captcha.recaptcha_test_key_error']
EMAILER_TEST = False
if not DEBUG or EMAILER_TEST:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = env('EMAIL_HOST')
EMAIL_PORT = env('EMAIL_PORT', cast=int, default=25)
EMAIL_HOST_USER = env('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')
EMAIL_USE_TLS = env('EMAIL_USE_TLS', cast=bool, default=False)
EMAIL_USE_SSL = env('EMAIL_USE_SSL', cast=bool, default=False)
DEFAULT_FROM_EMAIL = env('EMAIL_FROM')
EMAIL_HOST = os.environ.get('EMAIL_HOST')
EMAIL_PORT = int(os.environ.get('EMAIL_PORT', 25))
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
EMAIL_USE_TLS = bool(int(os.environ.get('EMAIL_USE_TLS', 0)))
EMAIL_USE_SSL = bool(int(os.environ.get('EMAIL_USE_SSL', 0)))
DEFAULT_FROM_EMAIL = os.environ.get('EMAIL_FROM')
else:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
@@ -263,3 +267,10 @@ USE_GRAVATAR = True
TERMS_OF_HIRE_URL = "http://www.nottinghamtec.co.uk/terms.pdf"
AUTHORISATION_NOTIFICATION_ADDRESS = 'productions@nottinghamtec.co.uk'
RISK_ASSESSMENT_URL = os.environ.get('RISK_ASSESSMENT_URL') if os.environ.get(
'RISK_ASSESSMENT_URL') else "http://example.com"
RISK_ASSESSMENT_SECRET = os.environ.get('RISK_ASSESSMENT_SECRET') if os.environ.get(
'RISK_ASSESSMENT_SECRET') else secrets.token_hex(15)
IMGUR_UPLOAD_CLIENT_ID = os.environ.get('IMGUR_UPLOAD_CLIENT_ID', '')
IMGUR_UPLOAD_CLIENT_SECRET = os.environ.get('IMGUR_UPLOAD_CLIENT_SECRET', '')

View File

@@ -6,6 +6,7 @@ import os
import pytz
from datetime import date, time, datetime, timedelta
from django.conf import settings
import imgurpython
import PyRIGS.settings
import sys
import pathlib
@@ -20,8 +21,13 @@ def create_datetime(year, month, day, hour, min):
def create_browser():
options = webdriver.ChromeOptions()
options.add_argument("--window-size=1920,1080")
# No caching, please and thank you
options.add_argument("--aggressive-cache-discard")
options.add_argument("--disk-cache-size=0")
# God Save The Queen
options.add_argument("--lang=en_GB")
options.add_argument("--headless")
if settings.CI:
if os.environ.get('CI', False):
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(options=options)
return driver
@@ -58,7 +64,19 @@ def screenshot_failure(func):
if not pathlib.Path("screenshots").is_dir():
os.mkdir("screenshots")
self.driver.save_screenshot(screenshot_file)
print("Error in test {} is at path {}".format(screenshot_name, screenshot_file), file=sys.stderr)
if settings.IMGUR_UPLOAD_CLIENT_ID != "":
config = {
'album': None,
'name': screenshot_name,
'title': screenshot_name,
'description': ""
}
client = imgurpython.ImgurClient(settings.IMGUR_UPLOAD_CLIENT_ID, settings.IMGUR_UPLOAD_CLIENT_SECRET)
image = client.upload_from_path(screenshot_file, config=config)
print("Error in test {} is at url {}".format(screenshot_name, image['link']), file=sys.stderr)
else:
print("Error in test {} is at path {}".format(screenshot_name, screenshot_file), file=sys.stderr)
raise e
return wrapper_func

View File

@@ -1,6 +1,5 @@
from pypom import Region
from django.utils import timezone
from django.conf import settings
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.remote.webelement import WebElement
@@ -20,22 +19,18 @@ def parse_bool_from_string(string):
else:
return False
# 12-Hour vs 24-Hour Time. Affects widget display
def get_time_format():
# Default
time_format = "%H%M"
if settings.CI: # The CI is American
time_format = "%I%M%p"
time_format = "%H:%M"
# If system is 12hr
if timezone.now().strftime("%p"):
time_format = "%I:%M %p"
return time_format
def get_date_format():
date_format = "%d%m%Y"
if settings.CI: # And try as I might I can't stop it being so
date_format = "%m%d%Y"
return date_format
class BootstrapSelectElement(Region):
_main_button_locator = (By.CSS_SELECTOR, 'button.dropdown-toggle')
_option_box_locator = (By.CSS_SELECTOR, 'ul.dropdown-menu')
@@ -155,13 +150,13 @@ class DatePicker(Region):
def set_value(self, value):
self.root.clear()
self.root.send_keys(value.strftime(get_date_format()))
self.root.send_keys(value.strftime("%d%m%Y"))
class TimePicker(Region):
@property
def value(self):
return datetime.datetime.strptime(self.root.get_attribute("value"), "%H:%M")
return datetime.datetime.strptime(self.root.get_attribute("value"), get_time_format())
def set_value(self, value):
self.root.clear()
@@ -171,12 +166,12 @@ class TimePicker(Region):
class DateTimePicker(Region):
@property
def value(self):
return datetime.datetime.strptime(self.root.get_attribute("value"), "%Y-%m-%d %H:%M")
return datetime.datetime.strptime(self.root.get_attribute("value"), "%Y-%m-%d " + get_time_format())
def set_value(self, value):
self.root.clear()
date = value.date().strftime(get_date_format())
date = value.date().strftime("%d%m%Y")
time = value.time().strftime(get_time_format())
self.root.send_keys(date)

View File

@@ -1,5 +1,5 @@
# TEC PA & Lighting - PyRIGS #
![Build Status](https://github.com/nottinghamtec/PyRIGS/workflows/Django%20CI/badge.svg)
[![Build Status](https://travis-ci.org/nottinghamtec/PyRIGS.svg?branch=master)](https://travis-ci.org/nottinghamtec/PyRIGS)
[![Coverage Status](https://coveralls.io/repos/github/nottinghamtec/PyRIGS/badge.svg)](https://coveralls.io/github/nottinghamtec/PyRIGS)
Welcome to TEC PA & Lighting's PyRIGS program. This is a reimplementation of the previous Rig Information Gathering System (RIGS) that was developed using Ruby on Rails. PyRIGS is our in house app for the centralisation of information on our events and now assets.

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 one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
/*!
* Bootstrap alert.js v4.6.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Bootstrap alert.js v4.5.2 (https://getbootstrap.com/)
* Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery"),require("./util.js")):"function"==typeof define&&define.amd?define(["jquery","./util"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).Alert=t(e.jQuery,e.Util)}(this,(function(e,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=n(e),l=n(t);function u(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var a="bs.alert",o=r.default.fn.alert,i=function(){function e(e){this._element=e}var t,n,o,i=e.prototype;return i.close=function(e){var t=this._element;e&&(t=this._getRootElement(e)),this._triggerCloseEvent(t).isDefaultPrevented()||this._removeElement(t)},i.dispose=function(){r.default.removeData(this._element,a),this._element=null},i._getRootElement=function(e){var t=l.default.getSelectorFromElement(e),n=!1;return t&&(n=document.querySelector(t)),n||(n=r.default(e).closest(".alert")[0]),n},i._triggerCloseEvent=function(e){var t=r.default.Event("close.bs.alert");return r.default(e).trigger(t),t},i._removeElement=function(e){var t=this;if(r.default(e).removeClass("show"),r.default(e).hasClass("fade")){var n=l.default.getTransitionDurationFromElement(e);r.default(e).one(l.default.TRANSITION_END,(function(n){return t._destroyElement(e,n)})).emulateTransitionEnd(n)}else this._destroyElement(e)},i._destroyElement=function(e){r.default(e).detach().trigger("closed.bs.alert").remove()},e._jQueryInterface=function(t){return this.each((function(){var n=r.default(this),l=n.data(a);l||(l=new e(this),n.data(a,l)),"close"===t&&l[t](this)}))},e._handleDismiss=function(e){return function(t){t&&t.preventDefault(),e.close(this)}},t=e,o=[{key:"VERSION",get:function(){return"4.6.0"}}],(n=null)&&u(t.prototype,n),o&&u(t,o),e}();return r.default(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',i._handleDismiss(new i)),r.default.fn.alert=i._jQueryInterface,r.default.fn.alert.Constructor=i,r.default.fn.alert.noConflict=function(){return r.default.fn.alert=o,i._jQueryInterface},i}));
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery"),require("./util.js")):"function"==typeof define&&define.amd?define(["jquery","./util.js"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).Alert=t(e.jQuery,e.Util)}(this,(function(e,t){"use strict";function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e,t=t&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t;var r=e.fn.alert,o=function(){function r(e){this._element=e}var o,l,i,a=r.prototype;return a.close=function(e){var t=this._element;e&&(t=this._getRootElement(e)),this._triggerCloseEvent(t).isDefaultPrevented()||this._removeElement(t)},a.dispose=function(){e.removeData(this._element,"bs.alert"),this._element=null},a._getRootElement=function(n){var r=t.getSelectorFromElement(n),o=!1;return r&&(o=document.querySelector(r)),o||(o=e(n).closest(".alert")[0]),o},a._triggerCloseEvent=function(t){var n=e.Event("close.bs.alert");return e(t).trigger(n),n},a._removeElement=function(n){var r=this;if(e(n).removeClass("show"),e(n).hasClass("fade")){var o=t.getTransitionDurationFromElement(n);e(n).one(t.TRANSITION_END,(function(e){return r._destroyElement(n,e)})).emulateTransitionEnd(o)}else this._destroyElement(n)},a._destroyElement=function(t){e(t).detach().trigger("closed.bs.alert").remove()},r._jQueryInterface=function(t){return this.each((function(){var n=e(this),o=n.data("bs.alert");o||(o=new r(this),n.data("bs.alert",o)),"close"===t&&o[t](this)}))},r._handleDismiss=function(e){return function(t){t&&t.preventDefault(),e.close(this)}},o=r,i=[{key:"VERSION",get:function(){return"4.5.2"}}],(l=null)&&n(o.prototype,l),i&&n(o,i),r}();return e(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',o._handleDismiss(new o)),e.fn.alert=o._jQueryInterface,e.fn.alert.Constructor=o,e.fn.alert.noConflict=function(){return e.fn.alert=r,o._jQueryInterface},o}));

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 one or more lines are too long

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 one or more lines are too long

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 one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
/*!
* Bootstrap popover.js v4.6.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Bootstrap popover.js v4.5.2 (https://getbootstrap.com/)
* Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("jquery"),require("./tooltip.js")):"function"==typeof define&&define.amd?define(["jquery","./tooltip"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).Popover=e(t.jQuery,t.Tooltip)}(this,(function(t,e){"use strict";function n(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var o=n(t),r=n(e);function i(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}function u(){return(u=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(t[o]=n[o])}return t}).apply(this,arguments)}var f="popover",a="bs.popover",l="."+a,s=o.default.fn[f],c=new RegExp("(^|\\s)bs-popover\\S+","g"),p=u({},r.default.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),d=u({},r.default.DefaultType,{content:"(string|element|function)"}),h={HIDE:"hide"+l,HIDDEN:"hidden"+l,SHOW:"show"+l,SHOWN:"shown"+l,INSERTED:"inserted"+l,CLICK:"click"+l,FOCUSIN:"focusin"+l,FOCUSOUT:"focusout"+l,MOUSEENTER:"mouseenter"+l,MOUSELEAVE:"mouseleave"+l},y=function(t){var e,n;function r(){return t.apply(this,arguments)||this}n=t,(e=r).prototype=Object.create(n.prototype),e.prototype.constructor=e,e.__proto__=n;var u,s,y,v=r.prototype;return v.isWithContent=function(){return this.getTitle()||this._getContent()},v.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-popover-"+t)},v.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},v.setContent=function(){var t=o.default(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(".popover-body"),e),t.removeClass("fade show")},v._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},v._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(c);null!==e&&e.length>0&&t.removeClass(e.join(""))},r._jQueryInterface=function(t){return this.each((function(){var e=o.default(this).data(a),n="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new r(this,n),o.default(this).data(a,e)),"string"==typeof t)){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},u=r,y=[{key:"VERSION",get:function(){return"4.6.0"}},{key:"Default",get:function(){return p}},{key:"NAME",get:function(){return f}},{key:"DATA_KEY",get:function(){return a}},{key:"Event",get:function(){return h}},{key:"EVENT_KEY",get:function(){return l}},{key:"DefaultType",get:function(){return d}}],(s=null)&&i(u.prototype,s),y&&i(u,y),r}(r.default);return o.default.fn[f]=y._jQueryInterface,o.default.fn[f].Constructor=y,o.default.fn[f].noConflict=function(){return o.default.fn[f]=s,y._jQueryInterface},y}));
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("jquery"),require("./tooltip.js")):"function"==typeof define&&define.amd?define(["jquery","./tooltip.js"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).Popover=e(t.jQuery,t.Tooltip)}(this,(function(t,e){"use strict";function n(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}function o(){return(o=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(t[o]=n[o])}return t}).apply(this,arguments)}t=t&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t,e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e;var r="popover",i=".bs.popover",s=t.fn[r],p=new RegExp("(^|\\s)bs-popover\\S+","g"),u=o({},e.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),a=o({},e.DefaultType,{content:"(string|element|function)"}),l={HIDE:"hide"+i,HIDDEN:"hidden"+i,SHOW:"show"+i,SHOWN:"shown"+i,INSERTED:"inserted"+i,CLICK:"click"+i,FOCUSIN:"focusin"+i,FOCUSOUT:"focusout"+i,MOUSEENTER:"mouseenter"+i,MOUSELEAVE:"mouseleave"+i},c=function(e){var o,s;function c(){return e.apply(this,arguments)||this}s=e,(o=c).prototype=Object.create(s.prototype),o.prototype.constructor=o,o.__proto__=s;var f,h,d,y=c.prototype;return y.isWithContent=function(){return this.getTitle()||this._getContent()},y.addAttachmentClass=function(e){t(this.getTipElement()).addClass("bs-popover-"+e)},y.getTipElement=function(){return this.tip=this.tip||t(this.config.template)[0],this.tip},y.setContent=function(){var e=t(this.getTipElement());this.setElementContent(e.find(".popover-header"),this.getTitle());var n=this._getContent();"function"==typeof n&&(n=n.call(this.element)),this.setElementContent(e.find(".popover-body"),n),e.removeClass("fade show")},y._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},y._cleanTipClass=function(){var e=t(this.getTipElement()),n=e.attr("class").match(p);null!==n&&n.length>0&&e.removeClass(n.join(""))},c._jQueryInterface=function(e){return this.each((function(){var n=t(this).data("bs.popover"),o="object"==typeof e?e:null;if((n||!/dispose|hide/.test(e))&&(n||(n=new c(this,o),t(this).data("bs.popover",n)),"string"==typeof e)){if(void 0===n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},f=c,d=[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return u}},{key:"NAME",get:function(){return r}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return l}},{key:"EVENT_KEY",get:function(){return i}},{key:"DefaultType",get:function(){return a}}],(h=null)&&n(f.prototype,h),d&&n(f,d),c}(e);return t.fn[r]=c._jQueryInterface,t.fn[r].Constructor=c,t.fn[r].noConflict=function(){return t.fn[r]=s,c._jQueryInterface},c}));

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 one or more lines are too long

View File

@@ -1,6 +1,6 @@
/*!
* Bootstrap util.js v4.6.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Bootstrap util.js v4.5.2 (https://getbootstrap.com/)
* Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).Util=e(t.jQuery)}(this,(function(t){"use strict";function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t),r="transitionend";function o(t){var e=this,r=!1;return n.default(this).one(i.TRANSITION_END,(function(){r=!0})),setTimeout((function(){r||i.triggerTransitionEnd(e)}),t),this}var i={TRANSITION_END:"bsTransitionEnd",getUID:function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var e=n.default(t).css("transition-duration"),r=n.default(t).css("transition-delay"),o=parseFloat(e),i=parseFloat(r);return o||i?(e=e.split(",")[0],r=r.split(",")[0],1e3*(parseFloat(e)+parseFloat(r))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){n.default(t).trigger(r)},supportsTransitionEnd:function(){return Boolean(r)},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var r in n)if(Object.prototype.hasOwnProperty.call(n,r)){var o=n[r],a=e[r],u=a&&i.isElement(a)?"element":null==(l=a)?""+l:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(o).test(u))throw new Error(t.toUpperCase()+': Option "'+r+'" provided type "'+u+'" but expected type "'+o+'".')}var l},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){var e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?i.findShadowRoot(t.parentNode):null},jQueryDetection:function(){if(void 0===n.default)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=n.default.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};return i.jQueryDetection(),n.default.fn.emulateTransitionEnd=o,n.default.event.special[i.TRANSITION_END]={bindType:r,delegateType:r,handle:function(t){if(n.default(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}},i}));
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).Util=e(t.jQuery)}(this,(function(t){"use strict";t=t&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t;function e(e){var r=this,o=!1;return t(this).one(n.TRANSITION_END,(function(){o=!0})),setTimeout((function(){o||n.triggerTransitionEnd(r)}),e),this}var n={TRANSITION_END:"bsTransitionEnd",getUID:function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(e){if(!e)return 0;var n=t(e).css("transition-duration"),r=t(e).css("transition-delay"),o=parseFloat(n),i=parseFloat(r);return o||i?(n=n.split(",")[0],r=r.split(",")[0],1e3*(parseFloat(n)+parseFloat(r))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(e){t(e).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,r){for(var o in r)if(Object.prototype.hasOwnProperty.call(r,o)){var i=r[o],a=e[o],u=a&&n.isElement(a)?"element":null==(s=a)?""+s:{}.toString.call(s).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(i).test(u))throw new Error(t.toUpperCase()+': Option "'+o+'" provided type "'+u+'" but expected type "'+i+'".')}var s},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){var e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?n.findShadowRoot(t.parentNode):null},jQueryDetection:function(){if(void 0===t)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var e=t.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1===e[0]&&9===e[1]&&e[2]<1||e[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};return n.jQueryDetection(),t.fn.emulateTransitionEnd=e,t.event.special[n.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(e){if(t(e.target).is(this))return e.handleObj.handler.apply(this,arguments)}},n}));

View File

@@ -304,43 +304,3 @@ class UserPage(BasePage):
def generate_key(self):
self.find_element(*self._generation_button_selector).click()
class CalendarPage(BasePage):
URL_TEMPLATE = 'rigboard/calendar'
_go_locator = (By.ID, 'go-to-date-button')
_today_selector = (By.ID, 'today-button')
_prev_selector = (By.ID, 'prev-button')
_next_selector = (By.ID, 'next-button')
_month_selector = (By.ID, 'month-button')
_week_selector = (By.ID, 'week-button')
_day_selector = (By.ID, 'day-button')
def go(self):
return self.find_element(*self._go_locator).click()
@property
def target_date(self):
return regions.DatePicker(self, self.find_element(By.ID, 'go-to-date-input'))
def today(self):
return self.find_element(*self._today_selector).click()
def prev(self):
return self.find_element(*self._prev_selector).click()
def next(self):
return self.find_element(*self._next_selector).click()
def month(self):
return self.find_element(*self._month_selector).click()
def week(self):
return self.find_element(*self._week_selector).click()
def day(self):
return self.find_element(*self._day_selector).click()

View File

@@ -645,18 +645,7 @@ class TestCalendar(BaseRigboardTest):
else:
self.assertNotContains(response, "TE E" + str(test) + " ")
def test_calendar_buttons(self): # If FullCalendar fails to load for whatever reason, the buttons don't work
self.page = pages.CalendarPage(self.driver, self.live_server_url).open()
self.assertIn(timezone.now().strftime("%Y-%m"), self.driver.current_url)
target_date = datetime.date(2020, 1, 1)
self.page.target_date.set_value(target_date)
self.page.go()
self.assertIn(self.page.target_date.value.strftime("%Y-%m"), self.driver.current_url)
self.page.next()
target_date += datetime.timedelta(days=32)
self.assertIn(target_date.strftime("%m"), self.driver.current_url)
# Wow - that was a lot of tests
@screenshot_failure_cls

134
Vagrantfile vendored Normal file
View File

@@ -0,0 +1,134 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
require 'yaml'
unless File.exist?('config/vagrant.yml')
raise "There is no config/vagrant.yml file.\nCopy config/vagrant.template.yml, make any changes you need, then try again."
end
settings = YAML.load_file 'config/vagrant.yml'
$script = <<SCRIPT
echo Beginning Vagrant provisioning...
date > /etc/vagrant_provisioned_at
SCRIPT
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = '2'
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
config.vm.provision 'shell', inline: $script
# Every Vagrant development environment requires a box. You can search for
# boxes at https://atlas.hashicorp.com/search.
config.vm.box = 'ubuntu/trusty64'
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
config.vm.synced_folder ".", "/vagrant"
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:5000" will access port 5000 on the guest machine.
config.vm.network "forwarded_port", guest: 5000, host: 5000
# PostgreSQL Server port forwarding
config.vm.network "forwarded_port", host: 15432, guest: 5432
# You can provision with just one of these scripts by user its name, eg:
# $ vagrant provision --provision-with postgresql
config.vm.provision 'build',
type: 'shell',
path: 'config/vagrant/build_dependency_setup.sh'
config.vm.provision 'git',
type: 'shell',
path: 'config/vagrant/git_setup.sh'
config.vm.provision 'postgresql',
type: 'shell',
path: 'config/vagrant/postgresql_setup.sh',
args: [
settings['db']['name'],
settings['db']['user'],
settings['db']['password'],
]
config.vm.provision 'python',
type: 'shell',
path: 'config/vagrant/python_setup.sh'
config.vm.provision 'virtualenv',
type: 'shell',
path: 'config/vagrant/virtualenv_setup.sh',
args: [
settings['virtualenv']['envname'],
]
# Will install foreman and, if there's a Procfile, start it:
config.vm.provision 'foreman',
type: 'shell',
path: 'config/vagrant/foreman_setup.sh',
run: 'always',
args: [
settings['virtualenv']['envname'],
settings['django']['settings_module'],
settings['foreman']['procfile'],
]
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
vb.memory = "1024"
end
#
# View the documentation for the provider you are using for more
# information on available options.
# Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
# such as FTP and Heroku are also available. See the documentation at
# https://docs.vagrantup.com/v2/push/atlas.html for more information.
# config.push.define "atlas" do |push|
# push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
# end
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# sudo apt-get update
# sudo apt-get install -y apache2
# SHELL
end

View File

@@ -4,7 +4,7 @@
"scripts": {
"postdeploy": "python manage.py migrate && python manage.py generateSampleData"
},
"stack": "heroku-20",
"stack": "heroku-18",
"env": {
"DEBUG": {
"required": true
@@ -51,4 +51,4 @@
"url": "heroku/python"
}
]
}
}

View File

@@ -1,5 +1,6 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_assets.html' %}
{% load widget_tweaks %}
{% block title %}Audit Asset {{ object.asset_id }}{% endblock %}
{% block content %}
<script>

View File

@@ -209,8 +209,6 @@ class AssetAuditList(AssetList):
_errors_selector = (By.CLASS_NAME, "alert-danger")
# Don't use the usual success selector - that tries and fails to hit the '10m long cable' helper button...
_submit_locator = (By.ID, "id_mark_audited")
_close_selector = (By.XPATH, "//button[@data-dismiss='modal']")
form_items = {
'asset_id': (regions.TextBox, (By.ID, 'id_asset_id')),
'description': (regions.TextBox, (By.ID, 'id_description')),
@@ -242,10 +240,6 @@ class AssetAuditList(AssetList):
self.root.find_element(*self._submit_locator).click()
# self.wait.until(lambda x: not self.is_displayed) TODO
def close(self):
previous_errors = self.errors
self.page.find_element(*self._close_selector).click()
def remove_all_required(self):
self.driver.execute_script("Array.from(document.getElementsByTagName(\"input\")).forEach(function (el, ind, arr) { el.removeAttribute(\"required\")});")
self.driver.execute_script("Array.from(document.getElementsByTagName(\"select\")).forEach(function (el, ind, arr) { el.removeAttribute(\"required\")});")

View File

@@ -136,7 +136,7 @@ class TestAssetForm(AutoLoginTest):
self.page.purchased_from_selector.set_option(self.supplier.name, True)
self.page.purchase_price = "12.99"
self.page.salvage_value = "99.12"
self.page.date_acquired = acquired = datetime.date(2020, 5, 2)
self.page.date_acquired = acquired = datetime.date(2020, 5, 20)
self.page.parent_selector.toggle()
self.assertTrue(self.page.parent_selector.is_open)
@@ -294,26 +294,31 @@ class TestAssetAudit(AutoLoginTest):
asset_id = "1111"
self.page.set_query(asset_id)
self.page.search()
mdl = self.page.modal
self.wait.until(EC.visibility_of_element_located((By.ID, 'modal')))
# Do it wrong on purpose to check error display
self.page.modal.remove_all_required()
self.page.modal.description = ""
self.page.modal.submit()
mdl.remove_all_required()
mdl.description = ""
mdl.submit()
# self.wait.until(EC.visibility_of_element_located((By.ID, 'modal')))
self.wait.until(animation_is_finished())
self.assertIn("This field is required.", self.page.modal.errors["Description"])
# self.assertTrue(self.driver.find_element_by_id('modal').is_displayed())
self.assertIn("This field is required.", mdl.errors["Description"])
# Now do it properly
self.page.modal.description = new_desc = "A BIG hammer"
self.page.modal.submit()
submit_time = timezone.now()
new_desc = "A BIG hammer"
mdl.description = new_desc
mdl.submit()
self.wait.until(EC.invisibility_of_element_located((By.ID, 'modal')))
self.assertFalse(self.driver.find_element_by_id('modal').is_displayed())
# Check data is correct
audited = models.Asset.objects.get(asset_id=asset_id)
audited = models.Asset.objects.get(asset_id="1111")
self.assertEqual(audited.description, new_desc)
# Make sure audit 'log' was filled out
self.assertEqual(self.profile.initials, audited.last_audited_by.initials)
self.assertEqual(submit_time.replace(microsecond=0), audited.last_audited_at.replace(microsecond=0))
self.assertEqual(timezone.now().date(), audited.last_audited_at.date())
self.assertEqual(timezone.now().hour, audited.last_audited_at.hour)
self.assertEqual(timezone.now().minute, audited.last_audited_at.minute)
# Check we've removed it from the 'needing audit' list
self.assertNotIn(asset_id, self.page.assets)
@@ -321,17 +326,18 @@ class TestAssetAudit(AutoLoginTest):
self.assertEqual(len(models.Asset.objects.filter(last_audited_at=None)), len(self.page.assets))
asset_row = self.page.assets[0]
self.driver.find_element(By.XPATH, "//a[contains(@class,'btn') and contains(., 'Audit')]").click()
self.driver.find_element(By.XPATH, "//*[@id='asset_table_body']/tr[1]/td[4]/a").click()
self.wait.until(EC.visibility_of_element_located((By.ID, 'modal')))
self.assertEqual(self.page.modal.asset_id, asset_row.id)
self.page.modal.close()
# First close button is for the not found error
self.page.find_element(By.XPATH, '//*[@id="modal"]/div/div/div[1]/button').click()
self.wait.until(EC.invisibility_of_element_located((By.ID, 'modal')))
self.assertFalse(self.driver.find_element_by_id('modal').is_displayed())
# Make sure audit log was NOT filled out
audited = models.Asset.objects.get(asset_id=asset_row.id)
self.assertEqual(None, audited.last_audited_by)
def test_audit_search(self):
# Check that a failed search works
self.page.set_query("NOTFOUND")
self.page.search()
@@ -380,31 +386,30 @@ class Test404(TestCase):
self.assertEqual(response.status_code, 404)
# TODO refactor this for all of RIGS
class TestAccessLevels(TestCase):
@override_settings(DEBUG=True)
def setUp(self):
super().setUp()
# Shortcut to create the levels - bonus side effect of testing the command (hopefully) matches production
call_command('generateSampleData')
# Create an asset with ID 1 to make things easier in loops (we can always use pk=1)
self.category = models.AssetCategory.objects.create(name="Number One")
self.status = models.AssetStatus.objects.create(name="Probably Fine", should_show=True)
models.Asset.objects.create(asset_id="1", description="Half Price Fish", status=self.status, category=self.category, date_acquired=datetime.date(2020, 2, 1))
# Nothing should be available to the unauthenticated
def test_unauthenticated(self):
self.client.logout()
for url in filter(lambda url: url.name is not None and "json" not in str(url), urls.urlpatterns):
pattern = str(url.pattern)
request_url = ""
if ":pk>" in pattern:
request_url = reverse(url.name, kwargs={'pk': 1})
else:
request_url = reverse(url.name)
if request_url:
for url in urls.urlpatterns:
if url.name is not None:
pattern = str(url.pattern)
if "json" in url.name or pattern:
# TODO
pass
elif ":pk>" in pattern:
request_url = reverse(url.name, kwargs={'pk': 9})
else:
request_url = reverse(url.name)
response = self.client.get(request_url, HTTP_HOST='example.com')
self.assertEqual(response.status_code, 302)
response = self.client.get(request_url, follow=True, HTTP_HOST='example.com')
self.assertContains(response, 'Login')
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'login')
def test_basic_access(self):
self.assertTrue(self.client.login(username="basic", password="basic"))
@@ -450,19 +455,6 @@ class TestAccessLevels(TestCase):
# def test_finance_access(self): Level not used in assets currently
def test_page_titles(self):
self.assertTrue(self.client.login(username="superuser", password="superuser"))
for url in filter(lambda url: url.name is not None and not any(s in url.name for s in ["json", "embed"]), urls.urlpatterns):
request_url = ""
if ":pk>" in str(url.pattern):
request_url = reverse(url.name, kwargs={'pk': "1"})
else:
request_url = reverse(url.name)
response = self.client.get(request_url)
if hasattr(response, "context_data") and "page_title" in response.context_data:
expected_title = response.context_data["page_title"]
self.assertContains(response, '<title>{} | Rig Information Gathering System</title>'.format(expected_title))
class TestFormValidation(TestCase):
@classmethod

View File

@@ -211,11 +211,6 @@ class AssetAudit(AssetEdit):
template_name = 'asset_audit.html'
form_class = forms.AssetAuditForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_title"] = "Audit Asset: {}".format(self.object.display_id)
return context
def get_success_url(self):
# TODO For some reason this doesn't stick when done in form_valid??
asset = self.get_object()

11
config/vagrant.yml Normal file
View File

@@ -0,0 +1,11 @@
django:
settings_module: PyRIGS.settings
virtualenv:
envname: myvirtualenv
foreman:
procfile: Procfile
db:
name: postgres_db
user: postgres_db
password: postgres_db

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
# Via https://github.com/kiere/vagrant-heroku-cedar-14/blob/master/config/vagrant/build_dependency_setup.sh
echo "=== Begin Vagrant Provisioning using 'config/vagrant/build_dependency_setup.sh'"
# Install build dependencies for a sane build environment
apt-get -y update
apt-get -y install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
# Other things that we may need installed before anything else.
apt-get install -y libmemcached-dev
apt-get build-dep python-lxml
echo "=== End Vagrant Provisioning using 'config/vagrant/build_dependency_setup.sh'"

View File

@@ -0,0 +1,36 @@
#!/bin/bash
# Install and (if there's a Procfile) start foreman.
# Needs to come after the virtualenv has been set up.
# Expects three arguments:
VIRTUALENV_NAME=$1
DJANGO_SETTINGS_MODULE=$2
PROCFILE=$3
echo "=== Begin Vagrant Provisioning using 'config/vagrant/foreman_setup.sh'"
gem install foreman --no-ri --no-rdoc
if ! grep -Fq "DJANGO_SETTINGS_MODULE" /home/vagrant/.bashrc; then
echo "export DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE}" >> /home/vagrant/.bashrc
fi
if [[ -f /vagrant/$PROCFILE ]]; then
echo "Procfile found; starting foreman."
export DJANGO_SETTINGS_MODULE="$DJANGO_SETTINGS_MODULE"
# Ensure the virtualenv settings in .profile are loaded:
source /home/vagrant/.profile
# Run with & to release the terminal.
# Although that may also rely on the Procfile's processes having their
# output sent to a file, not stdout/stderr.
foreman start -f /vagrant/$PROCFILE &
else
echo "No Procfile found; not starting foreman."
fi
echo "=== End Vagrant Provisioning using 'config/vagrant/foreman_setup.sh'"

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Via https://github.com/kiere/vagrant-heroku-cedar-14/blob/master/config/vagrant/git_setup.sh
echo "=== Begin Vagrant Provisioning using 'config/vagrant/git_setup.sh'"
# Install Git if not available
if [ -z `which git` ]; then
echo "===== Installing Git"
apt-get -y update
apt-get -y install git-core
fi
echo "=== End Vagrant Provisioning using 'config/vagrant/git_setup.sh'"

View File

@@ -0,0 +1,112 @@
#!/bin/sh -e
# Expects three arguments:
# $1 - database name
# $2 - database user
# #3 - database user password
# Via https://github.com/kiere/vagrant-heroku-cedar-14/blob/master/config/vagrant/postgresql_setup.sh
echo "=== Begin Vagrant Provisioning using 'config/vagrant/postgresql_setup.sh'"
APP_DB_NAME=$1
APP_DB_USER=$2
APP_DB_PASS=$3
# Edit the following to change the version of PostgreSQL that is installed
PG_VERSION=9.4
###########################################################
# Changes below this line are probably not necessary
###########################################################
print_db_usage () {
echo "Your PostgreSQL database has been setup and can be accessed on your local machine on the forwarded port (default: 15432)"
echo " Host: localhost"
echo " Port: 15432"
echo " Database: $APP_DB_NAME"
echo " Username: $APP_DB_USER"
echo " Password: $APP_DB_PASS"
echo ""
echo "Admin access to postgres user via VM:"
echo " vagrant ssh"
echo " sudo su - postgres"
echo ""
echo "psql access to app database user via VM:"
echo " vagrant ssh"
echo " sudo su - postgres"
echo " PGUSER=$APP_DB_USER PGPASSWORD=$APP_DB_PASS psql -h localhost $APP_DB_NAME"
echo ""
echo "Env variable for application development:"
echo " DATABASE_URL=postgresql://$APP_DB_USER:$APP_DB_PASS@localhost:15432/$APP_DB_NAME"
echo ""
echo "Local command to access the database via psql:"
echo " PGUSER=$APP_DB_USER PGPASSWORD=$APP_DB_PASS psql -h localhost -p 15432 $APP_DB_NAME"
}
export DEBIAN_FRONTEND=noninteractive
PROVISIONED_ON=/etc/vm_provision_on_timestamp
if [ -f "$PROVISIONED_ON" ]
then
echo "VM was already provisioned at: $(cat $PROVISIONED_ON)"
echo "To run system updates manually login via 'vagrant ssh' and run 'apt-get update && apt-get upgrade'"
echo ""
print_db_usage
exit
fi
PG_REPO_APT_SOURCE=/etc/apt/sources.list.d/pgdg.list
if [ ! -f "$PG_REPO_APT_SOURCE" ]
then
# Add PG apt repo:
echo "deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main" > "$PG_REPO_APT_SOURCE"
# Add PGDG repo key:
wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | apt-key add -
fi
# Update package list and upgrade all packages
apt-get update
apt-get -y upgrade
apt-get -y install "postgresql-$PG_VERSION" "postgresql-contrib-$PG_VERSION"
apt-get -y install libpq-dev # For building ruby 'pg' gem
PG_CONF="/etc/postgresql/$PG_VERSION/main/postgresql.conf"
PG_HBA="/etc/postgresql/$PG_VERSION/main/pg_hba.conf"
PG_DIR="/var/lib/postgresql/$PG_VERSION/main"
# Edit postgresql.conf to change listen address to '*':
sed -i "s/#listen_addresses = 'localhost'/listen_addresses = '*'/" "$PG_CONF"
# Append to pg_hba.conf to add password auth:
echo "host all all all md5" >> "$PG_HBA"
# Explicitly set default client_encoding
echo "client_encoding = utf8" >> "$PG_CONF"
# Restart so that all new config is loaded:
service postgresql restart
cat << EOF | su - postgres -c psql
-- Create the database user:
CREATE USER $APP_DB_USER PASSWORD '$APP_DB_PASS';
EOF
cat << EOF | su - postgres -c psql
-- Create the database:
CREATE DATABASE $APP_DB_NAME WITH OWNER=$APP_DB_USER
LC_COLLATE='en_US.utf8'
LC_CTYPE='en_US.utf8'
ENCODING='UTF8'
TEMPLATE=template0;
EOF
# Tag the provision time:
date > "$PROVISIONED_ON"
echo "Successfully created PostgreSQL dev virtual machine."
echo ""
print_db_usage
echo "=== End Vagrant Provisioning using 'config/vagrant/postgresql_setup.sh'"

View File

@@ -0,0 +1,23 @@
#!/bin/bash
# Install python and required python modules.
# pip and virtualenv are in virtualenv_setup.sh
# Initial part of this via
# https://github.com/torchbox/vagrant-django-base/blob/master/install.sh
echo "=== Begin Vagrant Provisioning using 'config/vagrant/python_setup.sh'"
apt-get update -y
# Python dev packages
apt-get install -y python python-dev python-setuptools python-pip
# Dependencies for image processing with Pillow (drop-in replacement for PIL)
# supporting: jpeg, tiff, png, freetype, littlecms
apt-get install -y libjpeg-dev libtiff-dev zlib1g-dev libfreetype6-dev liblcms2-dev
# lxml dependencies
apt-get install -y libxml2-dev libxslt1-dev python-dev
echo "=== End Vagrant Provisioning using 'config/vagrant/python_setup.sh'"

View File

@@ -0,0 +1,66 @@
#!/bin/bash
# This will:
# * Install pip, virtualenv and virtualenvwrapper.
# * Set up virtualenvwrapper's paths etc.
# * Create a new virtualenv.
# * Install any pip requirements from the requirements.txt file.
# Expects one argument, the name of the virtualenv.
# The name we'll use for the virtualenv in which we'll install requirements:
VENV_NAME=$1
echo "=== Begin Vagrant Provisioning using 'config/vagrant/virtualenv_setup.sh'"
# virtualenv global setup
if ! command -v pip; then
easy_install -U pip
fi
if [[ ! -f /usr/local/bin/virtualenv ]]; then
easy_install virtualenv virtualenvwrapper
fi
# If it doesn't look like .bashrc has the required virtualenvwrapper lines in,
# then add them.
if ! grep -Fq "WORKON_HOME" /home/vagrant/.profile; then
echo "Adding virtualenvwrapper locations to .profile"
if [[ -d /vagrant/config/virtualenvwrapper/vagrant ]]; then
echo "export VIRTUALENVWRAPPER_HOOK_DIR=/vagrant/config/virtualenvwrapper/vagrant" >> /home/vagrant/.profile
fi
echo "export WORKON_HOME=/home/vagrant/.virtualenvs" >> /home/vagrant/.profile
echo "export PROJECT_HOME=/home/vagrant/Devel" >> /home/vagrant/.profile
echo "source /usr/local/bin/virtualenvwrapper.sh" >> /home/vagrant/.profile
fi
# Get .virtualenvwrapper env variables set up:
source /home/vagrant/.profile
if [[ -d /home/vagrant/.virtualenvs/$VENV_NAME ]]; then
echo "Activating virtualenv $VENV_NAME."
workon $VENV_NAME
else
echo "Making new virtualenv $VENV_NAME."
# Also switches to the virtualenv:
mkvirtualenv $VENV_NAME
# So that we can install things with pip while ssh'd in as vagrant user:
sudo chown -R vagrant:vagrant /home/vagrant/.virtualenvs/$VENV_NAME/
# Automatically switch to the virtual env on log in:
echo "workon $VENV_NAME" >> /home/vagrant/.profile
fi
# If we have a requirements.txt file in this project, then install
# everything in it with pip in a new virtualenv.
if [[ -f /vagrant/requirements.txt ]]; then
echo "Installing from ./requirements.txt with pip."
pip install -r /vagrant/requirements.txt
fi
echo "=== End Vagrant Provisioning using 'config/vagrant/virtualenv_setup.sh'"

9729
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"version": "1.0.0",
"repository": "https://github.com/nottinghamtec/PyRIGS",
"author": "Tom Price",
"license": "Custom",
"license": "MIT",
"dependencies": {
"@forevolve/bootstrap-dark": "^1.0.0-alpha.1075",
"@fortawesome/fontawesome-free": "^5.13.1",
@@ -16,6 +16,8 @@
"dark-mode-switch": "^1.0.0",
"flatpickr": "^4.6.6",
"fullcalendar": "^5.3.2",
"gulp-if": "^3.0.0",
"gulp-rename": "^2.0.0",
"jquery": "^3.5.1",
"jquery-ui-dist": "^1.12.1",
"konami": "^1.6.2",
@@ -28,9 +30,7 @@
"gulp": "^4.0.2",
"gulp-clean-css": "^4.3.0",
"gulp-flatten": "^0.4.0",
"gulp-if": "^3.0.0",
"gulp-postcss": "^8.0.0",
"gulp-rename": "^2.0.0",
"gulp-sass": "^4.1.0",
"gulp-sourcemaps": "^2.6.5",
"gulp-terser": "^1.2.0",

View File

@@ -1,20 +1,21 @@
ansicolors==1.1.8
asgiref==3.3.1
asgiref==3.2.10
backports.tempfile==1.0
backports.weakref==1.0.post1
beautifulsoup4==4.9.3
cachetools==4.2.1
certifi==2020.12.5
chardet==4.0.0
cachetools==4.1.1
certifi==2020.6.20
chardet==3.0.4
configparser==5.0.1
contextlib2==0.6.0.post1
coverage==5.3
cssselect==1.1.0
cssutils==1.0.2
diff-match-patch==20200713
dj-database-url==0.5.0
dj-static==0.0.6
Django==3.1.5
django-debug-toolbar==3.2
Django==3.1.2
django-debug-toolbar==3.1.1
django-filter==2.4.0
django-gulp==4.1.0
django-ical==1.7.1
@@ -22,57 +23,58 @@ django-livereload==1.7
django-livereload-server==0.3.2
django-recaptcha==2.0.6
django-recurrence==1.10.3
django-registration-redux==2.9
django-reversion==3.0.9
django-registration-redux==2.8
django-reversion==3.0.8
django-toolbelt==0.0.1
django-widget-tweaks==1.4.8
envparse==0.2.0
env-tools==2.2.0
gunicorn==20.0.4
icalendar==4.0.7
idna==2.10
importlib-metadata==3.4.0
lxml==4.6.2
Markdown==3.3.3
msgpack==1.0.2
packaging==20.8
pep517==0.9.1
Pillow==8.1.0
imgurpython==1.1.7
importlib-metadata==2.0.0
lxml==4.5.2
Markdown==3.3
msgpack==1.0.0
packaging==20.4
pep517==0.8.2
Pillow==7.2.0
pluggy==0.13.1
premailer==3.7.0
progress==1.5
psutil==5.8.0
psutil==5.7.2
psycopg2==2.8.6
psycopg2-binary==2.8.6
Pygments==2.7.4
Pygments==2.7.1
pyparsing==2.4.7
PyPDF2==1.26.0
PyPOM==2.2.0
python-dateutil==2.8.1
pytoml==0.1.21
pytz==2020.5
pytz==2020.1
raven==6.10.0
reportlab==3.5.60
requests==2.25.1
reportlab==3.5.53
requests==2.24.0
retrying==1.3.3
selenium==3.141.0
simplejson==3.17.2
six==1.15.0
soupsieve==2.1
soupsieve==2.0.1
sqlparse==0.4.1
static3==0.7.0
svg2rlg==0.3
tini==3.0.1
tornado==6.1
urllib3==1.26.2
tornado==6.0.4
urllib3==1.25.10
whitenoise==5.2.0
yolk==0.4.3
z3c.rml==4.1.2
zipp==3.4.0
z3c.rml==3.10.0
zipp==3.3.0
zope.component==4.6.2
zope.deferredimport==4.3.1
zope.deprecation==4.4.0
zope.event==4.5.0
zope.hookable==5.0.1
zope.interface==5.2.0
zope.interface==5.1.2
zope.proxy==4.3.5
zope.schema==6.0.1
zope.schema==6.0.0

View File

@@ -1 +1 @@
python-3.9.1
python-3.8.2