| db.session.add(new_tool) | db.session.add(new_tool) | ||||
| db.session.commit() | db.session.commit() | ||||
| if request.form.get('linked_practice_id'): | |||||
| tool = Resource.query.filter_by(type='tool').filter_by(name=name).first() | |||||
| first_resource_id = tool.id | |||||
| second_resource_id = request.form.get('linked_practice_id') | |||||
| new_relationship = Relationship(first_resource_id=first_resource_id, second_resource_id=second_resource_id) | |||||
| # add the new relationship to the database | |||||
| db.session.add(new_relationship) | |||||
| db.session.commit() | |||||
| if request.form.getlist('linked_resources'): | |||||
| for linked_resource in request.form.getlist('linked_resources'): | |||||
| tool = Resource.query.filter_by(type='tool').filter_by(name=name).first() | |||||
| first_resource_id = tool.id | |||||
| second_resource_id = linked_resource | |||||
| new_relationship = Relationship(first_resource_id=first_resource_id, second_resource_id=second_resource_id) | |||||
| # add the new relationship to the database | |||||
| db.session.add(new_relationship) | |||||
| db.session.commit() | |||||
| elif request.form.get('resource_type') == 'practice': | elif request.form.get('resource_type') == 'practice': | ||||
| type = 'practice' | type = 'practice' |
| def get_linked_resources(resource_id): | def get_linked_resources(resource_id): | ||||
| relationships = Relationship.query.filter_by(first_resource_id=resource_id).all() | relationships = Relationship.query.filter_by(first_resource_id=resource_id).all() | ||||
| if relationships: | if relationships: | ||||
| links = [] | |||||
| for relationship in relationships: | for relationship in relationships: | ||||
| resource_id = relationship.second_resource_id | |||||
| links = Resource.query.filter_by(id=resource_id).all() | |||||
| return links | |||||
| resource_id = relationship.second_resource_id | |||||
| links.extend(Resource.query.filter_by(id=resource_id).all()) | |||||
| return links | |||||
| else: | else: | ||||
| relationships = Relationship.query.filter_by(second_resource_id=resource_id).all() | relationships = Relationship.query.filter_by(second_resource_id=resource_id).all() | ||||
| if relationships: | if relationships: | ||||
| links = [] | |||||
| for relationship in relationships: | for relationship in relationships: | ||||
| resource_id = relationship.first_resource_id | resource_id = relationship.first_resource_id | ||||
| links = Resource.query.filter_by(id=resource_id).all() | |||||
| return links | |||||
| links.extend(Resource.query.filter_by(id=resource_id).all()) | |||||
| return links | |||||
| # function to delete a single resource | # function to delete a single resource | ||||
| def delete_resource(resource_id): | def delete_resource(resource_id): |
| /* | |||||
| # @name: main.js | |||||
| # @version: 0.1 | |||||
| # @creation_date: 2022-04-07 | |||||
| # @license: The MIT License <https://opensource.org/licenses/MIT> | |||||
| # @author: Simon Bowie <ad7588@coventry.ac.uk> | |||||
| # @purpose: JavaScript functions for various functions | |||||
| # @acknowledgements: | |||||
| # https://stackoverflow.com/questions/67942546/bootstrap-5-select-dropdown-with-the-multiple-attribute-collapsed | |||||
| */ | |||||
| // Dynamic HTML forms based on dropdown menu | |||||
| $("#resource_type").change(function() { | |||||
| var $ = jQuery.noConflict(); | |||||
| var resource_type = $(this).val(); | |||||
| $(".resource_type_input").hide("fast", function() { | |||||
| $("#resource_type_" + resource_type).show("slow"); | |||||
| }); | |||||
| }); | |||||
| // Testing a couple of ways to expand text | |||||
| var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) | |||||
| var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { | |||||
| return new bootstrap.Tooltip(tooltipTriggerEl) | |||||
| }) | |||||
| var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')) | |||||
| var popoverList = popoverTriggerList.map(function (popoverTriggerEl) { | |||||
| return new bootstrap.Popover(popoverTriggerEl) | |||||
| }) |
| --bs-bg-opacity: 1; | --bs-bg-opacity: 1; | ||||
| background-color: rgba(var(--bs-practice-rgb),var(--bs-bg-opacity))!important; | background-color: rgba(var(--bs-practice-rgb),var(--bs-bg-opacity))!important; | ||||
| } | } | ||||
| .drop { | |||||
| position: relative; | |||||
| -webkit-user-select: none; | |||||
| -moz-user-select: none; | |||||
| -ms-user-select: none; | |||||
| user-select: none; | |||||
| } | |||||
| .drop.open { | |||||
| z-index: 100; | |||||
| } | |||||
| .drop.open .drop-screen { | |||||
| z-index: 100; | |||||
| display: block; | |||||
| } | |||||
| .drop.open .drop-options { | |||||
| z-index: 200; | |||||
| max-height: 200px; | |||||
| } | |||||
| .drop.open .drop-display { | |||||
| z-index: 200; | |||||
| border-color: #465; | |||||
| } | |||||
| .drop select { | |||||
| display: none; | |||||
| } | |||||
| .drop .drop-screen { | |||||
| position: fixed; | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| background: #000; | |||||
| top: 0px; | |||||
| left: 0px; | |||||
| opacity: 0; | |||||
| display: none; | |||||
| z-index: 1; | |||||
| } | |||||
| .link { | |||||
| text-align: center; | |||||
| margin: 20px 0px; | |||||
| color:#8CACD7; | |||||
| } | |||||
| .drop .drop-display { | |||||
| position: relative; | |||||
| padding: 0px 20px 5px 5px; | |||||
| border: 4px solid #444; | |||||
| width: 100%; | |||||
| background: #FFF; | |||||
| z-index: 1; | |||||
| margin: 0px; | |||||
| font-size: 16px; | |||||
| min-height: 58px; | |||||
| } | |||||
| .drop .drop-display:hover:after { | |||||
| opacity: 0.75; | |||||
| } | |||||
| .drop .drop-display:after { | |||||
| font-family: 'Material Icons'; | |||||
| content: "\e5c6"; | |||||
| position: absolute; | |||||
| right: 10px; | |||||
| top: 12px; | |||||
| font-size: 24px; | |||||
| color: #444; | |||||
| } | |||||
| .drop .drop-display .item { | |||||
| position: relative; | |||||
| display: inline-block; | |||||
| border: 2px solid #333; | |||||
| margin: 5px 5px -4px 0px; | |||||
| padding: 0px 25px 0px 10px; | |||||
| overflow: hidden; | |||||
| height: 40px; | |||||
| line-height: 36px; | |||||
| } | |||||
| .drop .drop-display .item .btnclose { | |||||
| color: #444; | |||||
| position: absolute; | |||||
| font-size: 16px; | |||||
| right: 5px; | |||||
| top: 10px; | |||||
| cursor: pointer; | |||||
| } | |||||
| .drop .drop-display .item .btnclose:hover { | |||||
| opacity: 0.75; | |||||
| } | |||||
| .drop .drop-display .item.remove { | |||||
| -webkit-animation: removeSelected 0.2s, hide 1s infinite; | |||||
| animation: removeSelected 0.2s, hide 1s infinite; | |||||
| -webkit-animation-delay: 0s, 0.2s; | |||||
| animation-delay: 0s, 0.2s; | |||||
| } | |||||
| .drop .drop-display .item.add { | |||||
| -webkit-animation: addSelected 0.2s; | |||||
| animation: addSelected 0.2s; | |||||
| } | |||||
| .drop .drop-display .item.hide { | |||||
| display: none; | |||||
| } | |||||
| .drop .drop-options { | |||||
| background: #444; | |||||
| box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25); | |||||
| position: absolute; | |||||
| width: 100%; | |||||
| max-height: 0px; | |||||
| overflow-y: auto; | |||||
| transition: all 0.25s linear; | |||||
| z-index: 1; | |||||
| } | |||||
| .drop .drop-options a { | |||||
| display: block; | |||||
| height: 40px; | |||||
| line-height: 40px; | |||||
| padding: 0px 20px; | |||||
| color: white; | |||||
| position: relative; | |||||
| max-height: 40px; | |||||
| transition: all 1s; | |||||
| overflow: hidden; | |||||
| } | |||||
| .drop .drop-options a:hover { | |||||
| background: #465; | |||||
| cursor: pointer; | |||||
| } | |||||
| .drop .drop-options a.remove { | |||||
| -webkit-animation: removeOption 0.2s; | |||||
| animation: removeOption 0.2s; | |||||
| max-height: 0px; | |||||
| } | |||||
| .drop .drop-options a.add { | |||||
| -webkit-animation: addOption 0.2s; | |||||
| animation: addOption 0.2s; | |||||
| } | |||||
| .drop .drop-options a.hide { | |||||
| display: none; | |||||
| } | |||||
| @-webkit-keyframes pop { | |||||
| from { | |||||
| -webkit-transform: scale(0); | |||||
| transform: scale(0); | |||||
| } | |||||
| to { | |||||
| -webkit-transform: scale(1); | |||||
| transform: scale(1); | |||||
| } | |||||
| } | |||||
| @keyframes pop { | |||||
| from { | |||||
| -webkit-transform: scale(0); | |||||
| transform: scale(0); | |||||
| } | |||||
| to { | |||||
| -webkit-transform: scale(1); | |||||
| transform: scale(1); | |||||
| } | |||||
| } | |||||
| @-webkit-keyframes removeOption { | |||||
| from { | |||||
| max-height: 40px; | |||||
| } | |||||
| to { | |||||
| max-height: 0px; | |||||
| } | |||||
| } | |||||
| @keyframes removeOption { | |||||
| from { | |||||
| max-height: 40px; | |||||
| } | |||||
| to { | |||||
| max-height: 0px; | |||||
| } | |||||
| } | |||||
| @-webkit-keyframes addOption { | |||||
| from { | |||||
| max-height: 0px; | |||||
| } | |||||
| to { | |||||
| max-height: 40px; | |||||
| } | |||||
| } | |||||
| @keyframes addOption { | |||||
| from { | |||||
| max-height: 0px; | |||||
| } | |||||
| to { | |||||
| max-height: 40px; | |||||
| } | |||||
| } | |||||
| @-webkit-keyframes removeSelected { | |||||
| from { | |||||
| -webkit-transform: scale(1); | |||||
| transform: scale(1); | |||||
| } | |||||
| to { | |||||
| -webkit-transform: scale(0); | |||||
| transform: scale(0); | |||||
| } | |||||
| } | |||||
| @keyframes removeSelected { | |||||
| from { | |||||
| -webkit-transform: scale(1); | |||||
| transform: scale(1); | |||||
| } | |||||
| to { | |||||
| -webkit-transform: scale(0); | |||||
| transform: scale(0); | |||||
| } | |||||
| } | |||||
| @-webkit-keyframes addSelected { | |||||
| from { | |||||
| -webkit-transform: scale(0); | |||||
| transform: scale(0); | |||||
| } | |||||
| to { | |||||
| -webkit-transform: scale(1); | |||||
| transform: scale(1); | |||||
| } | |||||
| } | |||||
| @keyframes addSelected { | |||||
| from { | |||||
| -webkit-transform: scale(0); | |||||
| transform: scale(0); | |||||
| } | |||||
| to { | |||||
| -webkit-transform: scale(1); | |||||
| transform: scale(1); | |||||
| } | |||||
| } | |||||
| @-webkit-keyframes hide { | |||||
| from, to { | |||||
| max-height: 0px; | |||||
| max-width: 0px; | |||||
| padding: 0px; | |||||
| margin: 0px; | |||||
| border-width: 0px; | |||||
| } | |||||
| } | |||||
| @keyframes hide { | |||||
| from, to { | |||||
| max-height: 0px; | |||||
| max-width: 0px; | |||||
| padding: 0px; | |||||
| margin: 0px; | |||||
| border-width: 0px; | |||||
| } | |||||
| } |
| <!-- Bootstrap CSS --> | <!-- Bootstrap CSS --> | ||||
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> | <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> | ||||
| <link href="{{ url_for('static',filename='styles/custom.css') }}" rel="stylesheet"> | <link href="{{ url_for('static',filename='styles/custom.css') }}" rel="stylesheet"> | ||||
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.14.0-beta2/css/bootstrap-select.min.css" integrity="sha512-mR/b5Y7FRsKqrYZou7uysnOdCIJib/7r5QeJMFvLNHNhtye3xJp1TdJVPLtetkukFn227nKpXD9OjUc09lx97Q==" crossorigin="anonymous" referrerpolicy="no-referrer" /> | |||||
| </head> | </head> | ||||
| <body class="d-flex flex-column min-vh-100"> | <body class="d-flex flex-column min-vh-100"> | ||||
| <!-- jQuery first, then Popper JS, then Bootstrap JS --> | <!-- jQuery first, then Popper JS, then Bootstrap JS --> | ||||
| <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script> | <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script> | ||||
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> | <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> | ||||
| <script> | |||||
| $("#resource_type").change(function() { | |||||
| var resource_type = $(this).val(); | |||||
| $(".resource_type_input").hide("fast", function() { | |||||
| $("#resource_type_" + resource_type).show("slow"); | |||||
| }); | |||||
| }); | |||||
| </script> | |||||
| <script> | |||||
| // Initialize tooltips | |||||
| var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) | |||||
| var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { | |||||
| return new bootstrap.Tooltip(tooltipTriggerEl) | |||||
| }) | |||||
| </script> | |||||
| <script> | |||||
| var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')) | |||||
| var popoverList = popoverTriggerList.map(function (popoverTriggerEl) { | |||||
| return new bootstrap.Popover(popoverTriggerEl) | |||||
| }) | |||||
| </script> | |||||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.14.0-beta2/js/bootstrap-select.min.js" integrity="sha512-FHZVRMUW9FsXobt+ONiix6Z0tIkxvQfxtCSirkKc5Sb4TKHmqq1dZa8DphF0XqKb3ldLu/wgMa8mT6uXiLlRlw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> | |||||
| <script src="{{ url_for('static',filename='js/main.js') }}"></script> | |||||
| </body> | </body> | ||||
| </html> | </html> |
| </div> | </div> | ||||
| <div class="mb-3 mt-3"> | <div class="mb-3 mt-3"> | ||||
| <label for="linked_practice_id">Linked practices</label> | |||||
| <select class="form-select" aria-label="Linked practices" name="linked_practice_id"> | |||||
| <option selected>Select a linked practice</option> | |||||
| <label for="linked_practice_id">Linked resources</label> | |||||
| <!--<select class="form-select" aria-label="Linked practices" name="linked_practice_id" multiple="multiple" id="linked_practice_id">--> | |||||
| <select name="linked_resources" id="linked_resources" aria-label="Linked resources" class="selectpicker" data-live-search="true" multiple> | |||||
| <optgroup label="Practices"> | |||||
| {% for practice_dropdown in practice_dropdown %} | {% for practice_dropdown in practice_dropdown %} | ||||
| <option value="{{ practice_dropdown['id'] }}">{{ practice_dropdown['name'] }}</option> | <option value="{{ practice_dropdown['id'] }}">{{ practice_dropdown['name'] }}</option> | ||||
| {% endfor %} | {% endfor %} | ||||
| </optgroup> | |||||
| </select> | </select> | ||||
| </div> | </div> | ||||
| </div> | </div> |