Skip to content

Commit

Permalink
Develop aspen usr cmpts (#250)
Browse files Browse the repository at this point in the history
* toggle list of owned components, select_all works properly as well as the search bar for owned components, Appoint new Party is only visible to owner of the component, project endpoint works without system

* removed useless code

* Update CHANGELOG

* Update title of Speedy SSP CUI template

Co-authored-by: Greg Elin <[email protected]>
  • Loading branch information
SergioJFalcon and gregelin authored Jun 13, 2022
1 parent 9c7e045 commit b293962
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 56 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Release adds support for private components and integrations with third party se
* Only Component owner can edit user permissions.
* Display the control framework along side of controls in component control listing page.
* Remove icons from project listing.
* Add Component search filter to filter results to components owned by user.

**Developer changes**

Expand Down
4 changes: 2 additions & 2 deletions api/siteapp/serializers/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ class DetailedProjectsSerializer(SimpleProjectsSerializer):
organization = DetailedOrganizationSerializer()
portfolio = SimplePortfolioSerializer()
tags = SimpleTagSerializer(many=True)
system = SimpleSystemSerializer()
# system = SimpleSystemSerializer()
root_task = TaskSerializer()

class Meta:
model = Project
fields = SimpleProjectsSerializer.Meta.fields + ['organization', 'portfolio', 'system', 'tags', 'root_task']
fields = SimpleProjectsSerializer.Meta.fields + ['organization', 'portfolio', 'tags', 'root_task']


class SimpleProjectMembershipSerializer(ReadOnlySerializer):
Expand Down
26 changes: 22 additions & 4 deletions controls/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,11 +452,25 @@ def get_context_data(self, **kwargs):
@login_required
def component_library(request):
"""Display the library of components"""
owned_elements_id = []

for element in Element.objects.all().exclude(element_type='system').distinct():
if element.is_owner(request.user):
owned_elements_id.append(element.id)

owned_elements_list = Element.objects.filter(id__in=owned_elements_id)

query = request.GET.get('search')
# Setting a breakpoint in the code.
if query:
try:
element_list = Element.objects.filter(Q(name__icontains=query) | Q(tags__label__icontains=query)).exclude(element_type='system').distinct()
if request.GET.get('owner'):
# Search by owner
element_list = Element.objects.filter(id__in=owned_elements_id)
element_list = element_list.filter(Q(name__icontains=query) | Q(tags__label__icontains=query)).exclude(element_type='system').distinct()
else:
element_list = Element.objects.filter(Q(name__icontains=query) | Q(tags__label__icontains=query)).exclude(element_type='system').distinct()

except:
logger.info(f"Ah, you are not using Postgres for your Database!")
element_list = Element.objects.filter(Q(name__icontains=query) | Q(tags__label__icontains=query)).exclude(element_type='system').distinct()
Expand All @@ -471,17 +485,23 @@ def component_library(request):

# Pagination
ele_paginator = Paginator(element_list_private_removed, 15)
owned_ele_paginator = Paginator(owned_elements_list, 15)
page_number = request.GET.get('page')

try:
page_obj = ele_paginator.page(page_number)
owned_page_obj = owned_ele_paginator.page(page_number)
except PageNotAnInteger:
page_obj = ele_paginator.page(1)
owned_page_obj = owned_ele_paginator.page(1)
except EmptyPage:
page_obj = ele_paginator.page(ele_paginator.num_pages)

owned_page_obj = owned_ele_paginator.page(owned_ele_paginator.num_pages)

context = {
"page_obj": page_obj,
"owned_page_obj": owned_page_obj,
"start": False,
"import_form": ImportOSCALComponentForm(),
"total_comps": Element.objects.exclude(element_type='system').count(),
}
Expand Down Expand Up @@ -1183,8 +1203,6 @@ def system_element(request, system_id, element_id):
hasSentRequest = True
except Proposal.DoesNotExist:
proposal = None



# Retrieve control ids
catalog_controls = Catalog.GetInstance(catalog_key=catalog_key).get_controls_all()
Expand Down
24 changes: 14 additions & 10 deletions frontend/src/components/cmpt_parties/cmpt_parties.js
Original file line number Diff line number Diff line change
Expand Up @@ -863,16 +863,20 @@ export const ComponentParties = ({ elementId, poc_users, isOwner }) => {
<div style={{width: "calc(100% - 1rem - 25px)", marginTop: "1rem" }}>
<div style={{ width: "100%", marginBottom: "1rem", display: "flex", justifyContent: "space-between" }}>
<h2>Parties</h2>
<Button
style={{ width: "150px", height: "40px", marginTop: "0.5rem" }}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
handleNewPartyModal();
}}
>
Appoint new party
</Button>
{ isOwner ?
<Button
style={{ width: "150px", height: "40px", marginTop: "0.5rem" }}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
handleNewPartyModal();
}}
>
Appoint new party
</Button>
:
null
}
</div>
<DataGrid
className={dgClasses.root}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
id: ssp_cui
format: markdown
title: ManTech CUI SSP
title: CUI SSP
...

# 1. Document Revision History
Expand Down
156 changes: 117 additions & 39 deletions templates/components/component_library.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,21 @@
{% endblock %}

{% block contextbar %}{% endblock %}

{% block body %}

<div class="portfolio-top">
<div class="container">
<div class="portfolio-main">
<a id="component-new" href="{% url 'new_element' %}" class="btn btn-success">Create a Component</a>
<a id="component-import-oscal" class="btn btn-success" onclick="show_import_component_modal(); return false;" href="#">Import OSCAL Component</a>
<a id="import_records_link" href="{% url 'import_records' %}" class="btn btn-success">Manage Import Records</a>
</div>

<h2 class="">Component Library</h2>

<form action="{% url 'component_library' %}" method="GET" role="search">
<div class="form-inline pull-right create-nav">
<div class="form-group">
<div class="input-group" id="searchbox-input">
<input id="searchbox" name="search" value="{{ request.GET.search }}" type="text" placeholder="search components" spellcheck="false" aria-labelledby="searchbox-input" />
<input id="owner" type="checkbox" name="owner" {% if start %}checked{% endif %} />
<span id="searchicon" class="glyphicon glyphicon-search" href="{% url 'component_library' %}"></span>
{% if request.GET.search %}
<a id="searchclear" class="glyphicon glyphicon-remove" href="{% url 'component_library' %}"></a>
Expand All @@ -50,85 +47,161 @@ <h2 class="">Component Library</h2>
</div>
</div>
</form>

<div id="switch-to-owner-components" style="float:right;margin-right:1rem;">
<button onclick="return switchData();">
Toggle to owned Components
</button>
</div>
{% if page_obj|length > 0 %}
<p>You have access to {{ total_comps }} components.</p>
{% else %}
<p>You do not have access to any components.</p>
{% endif %}

<form action="{% url 'compare_components' %}" name="compare_form" onsubmit="return clearStorage()" method="POST">
{% csrf_token %}
<input type="hidden" name="hiddenChecks" id="hiddenChecks" value="" />
<div id="" class="row">
<button id="compare-components" href="{% url 'compare_components' %}" class="btn btn-info"><em class="glyphicon glyphicon-sort"></em> Compare Components</button>
<button id="compare-select" onclick="select_all(true); return false;" href="#" class="btn btn-success">Select all</button>
<button id="compare-deselect" onclick="select_all(false); return false;" href="#" class=" btn btn-danger">Deselect all</button>
<button id="compare-select" onclick="select_all(true); return false;" href="#" class="btn btn-success">Select all</button>
<button id="compare-deselect" onclick="select_all(false); return false;" href="#" class=" btn btn-danger">Deselect all</button>

<div id="" class="col-xs-12"><span>{% include 'components/paginate_comp.html' %}</span></div>

</div>

<div id="tab-content" class="row rows-header">
<div id="" class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xl-4">Component</div>
<div id="" class="col-xs-5 col-sm-5 col-md-5 col-lg-5 col-xl-5">Description</div>
<div id="" class="col-xs-1 col-sm-1 col-md-1 col-lg-1 col-xl-1">Select</div>
<div id="" class="col-xs-2 col-sm-2 col-md-2 col-lg-2 col-xl-2"><span class="pull-right">Statements</span></div>
</div>
<div id="checkbox-container">
{% for component in page_obj %}
<div id="tab-content" class="row row-control" style="">
<div id="" class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xl-4">
<div>
<a href={% url 'component_library_component' element_id=component.id %}>{{ component.name }}</a>
{% if component.private == True %}<span class="glyphicon glyphicon-lock small" style="color:gray;" title="Private"></span>{% endif %}
<div id="components-list" style="display:hidden;">
<div id="checkbox-container">
{% for component in page_obj %}
<div id="tab-content" class="row row-control" style="">
<div id="" class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xl-4">
<div>
<a href={% url 'component_library_component' element_id=component.id %}>{{ component.name }}</a>
{% if component.private == True %}<span class="glyphicon glyphicon-lock small" style="color:gray;" title="Private"></span>{% endif %}
</div>
</div>
<div id="" class="col-xs-5 col-sm-5 col-md-5 col-lg-5 col-xl-5">
{% if component.description %}{{ component.description }}{% else %}<span class="not-provided">No description provided.</span>{% endif %}
<div>{% for tag in component.tags.all %}<span class="component-tag"><a href="{% url 'component_library' %}?search={{ tag.label }}">{{ tag.label }}</a></span> {% endfor %}</div>
</div>
<div id="" aria-label="Select component to compare" class="col-xs-1 col-sm-1 col-md-1 col-lg-1 col-xl-1">
{% comment %} <label for="comp_comparison_{{ forloop.counter }}" aria-label="Checkbox to select component"></label> {% endcomment %}
<input aria-label="Checkbox for selecting a component" type="checkbox" id="comp_comparison_{{ forloop.counter }}" name="compareCheckbox" onchange="addCheck()" value="{{ component.id }}">
</div>
<div id="" class="pull-right col-xs-2 col-sm-2 col-md-2 col-lg-2 col-xl-2">
<span class="pull-right">{% if component.get_control_impl_smts_prototype_count > 0 %}{{ component.get_control_impl_smts_prototype_count }} control{{ component.get_control_impl_smts_prototype_count|pluralize }}</span>{% else %}
<span class="not-provided">No statements</span>{% endif %}
</div>
</div>
</div>
<div id="" class="col-xs-5 col-sm-5 col-md-5 col-lg-5 col-xl-5">
{% if component.description %}{{ component.description }}{% else %}<span class="not-provided">No description provided.</span>{% endif %}
<div>{% for tag in component.tags.all %}<span class="component-tag"><a href="{% url 'component_library' %}?search={{ tag.label }}">{{ tag.label }}</a></span> {% endfor %}</div>
</div>
<div id="" aria-label="Select component to compare" class="col-xs-1 col-sm-1 col-md-1 col-lg-1 col-xl-1">
{% comment %} <label for="comp_comparison_{{ forloop.counter }}" aria-label="Checkbox to select component"></label> {% endcomment %}
<input aria-label="Checkbox for selecting a component" type="checkbox" id="comp_comparison_{{ forloop.counter }}" name="compareCheckbox" onchange="addCheck()" value="{{ component.id }}">
</div>
<div id="" class="pull-right col-xs-2 col-sm-2 col-md-2 col-lg-2 col-xl-2">
<span class="pull-right">{% if component.get_control_impl_smts_prototype_count > 0 %}{{ component.get_control_impl_smts_prototype_count }} control{{ component.get_control_impl_smts_prototype_count|pluralize }}</span>{% else %}
<span class="not-provided">No statements</span>{% endif %}
</div>
{% endfor %}
</div>
</div>
<div id="owned-components-list" style="display:hidden;">
<div id="owned-checkbox-container">
{% for component in owned_page_obj %}
<div id="tab-content" class="row row-control" style="">
<div id="" class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xl-4">
<div>
<a href={% url 'component_library_component' element_id=component.id %}>{{ component.name }}</a>
{% if component.private == True %}<span class="glyphicon glyphicon-lock small" style="color:gray;" title="Private"></span>{% endif %}
</div>
</div>
<div id="" class="col-xs-5 col-sm-5 col-md-5 col-lg-5 col-xl-5">
{% if component.description %}{{ component.description }}{% else %}<span class="not-provided">No description provided.</span>{% endif %}
<div>{% for tag in component.tags.all %}<span class="component-tag"><a href="{% url 'component_library' %}?search={{ tag.label }}">{{ tag.label }}</a></span> {% endfor %}</div>
</div>
<div id="" aria-label="Select component to compare" class="col-xs-1 col-sm-1 col-md-1 col-lg-1 col-xl-1">
{% comment %} <label for="comp_comparison_{{ forloop.counter }}" aria-label="Checkbox to select component"></label> {% endcomment %}
<input aria-label="Checkbox for selecting a component" type="checkbox" id="comp_owner_comparison_{{ forloop.counter }}" name="compareCheckbox" onchange="addCheck()" value="{{ component.id }}">
</div>
<div id="" class="pull-right col-xs-2 col-sm-2 col-md-2 col-lg-2 col-xl-2">
<span class="pull-right">{% if component.get_control_impl_smts_prototype_count > 0 %}{{ component.get_control_impl_smts_prototype_count }} control{{ component.get_control_impl_smts_prototype_count|pluralize }}</span>{% else %}
<span class="not-provided">No statements</span>{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</form>

{% include "components/import-component-modal.html" %}
</div>
{% include "components/import-component-modal.html" %}

</div>
</div>

{{ block.super }}

{% endblock %}

{% block scripts %}
<script>

function switchData(){
var $owned_submit = $("#owned-components-list")
var $all_list = $("#components-list")
var $owner = $("#owner")

if(document.getElementById("owner").checked){
let data_val = document.getElementById("owner").checked = false;
$owned_submit.toggle();
$all_list.toggle();
$owned_cbs = $('input[name="owner"]').click(function () {
$owned_submit.toggle();
$all_list.toggle();
});
localStorage.clear()
select_all(false)
return true;

} else {
let data_val = document.getElementById("owner").checked = true;
$owned_submit.toggle();
$all_list.toggle();
$owned_cbs = $('input[name="owner"]').click(function () {
$owned_submit.toggle();
$all_list.toggle();
});
localStorage.clear()
select_all(false)
return false;
}
}

//Hide submit button until 1 checkbox is checked
$(document).ready(function () {
var $owned_submit = $("#owned-components-list").hide()
var $owner_input = $("#owner").hide()
var checkBoxValues = JSON.parse(localStorage.getItem('checkBoxValues'))
// If are no previously checked components then hide button
var $submit = $("#compare-components").hide()
if (checkBoxValues !== null) {
$submit.toggle();
} else {
$cbs = $('input[name="compareCheckbox"]').click(function () {

$submit.toggle($cbs.is(":checked"));
});
}
});



function select_all(val) {
// select and deselect with toggle
var checkBoxValues = JSON.parse(localStorage.getItem('checkBoxValues')) || {};
var $checkboxes = $("#checkbox-container :checkbox");//$('input[type=checkbox]')
$checkboxes.prop('checked', val);
var $ownedCheckboxes = $("#owned-checkbox-container :checkbox");//$('input[type=checkbox]')
$ownedCheckboxes.prop('checked', val);

addStorage($checkboxes, checkBoxValues);

if(document.getElementById("owner").checked){
addStorage($ownedCheckboxes, checkBoxValues)
} else {
addStorage($checkboxes, checkBoxValues)
}
var compare_btn = $("#compare-components")
if ($checkboxes.prop('checked') && compare_btn.is(":hidden")) {
compare_btn.toggle()
Expand All @@ -141,10 +214,15 @@ <h2 class="">Component Library</h2>
function addCheck() {
// maintain in localstorage checkboxes that have been checked
var checkBoxValues = JSON.parse(localStorage.getItem('checkBoxValues')) || {};

var $checkboxes = $("#checkbox-container :checkbox");
addStorage($checkboxes, checkBoxValues)
var $owned_checkboxes = $("#owned-checkbox-container :checkbox");

if(document.getElementById("owner").checked){
addStorage($owned_checkboxes, checkBoxValues)
} else {
addStorage($checkboxes, checkBoxValues)
}

}

function addStorage($checkboxes, checkBoxValues) {
Expand Down

0 comments on commit b293962

Please sign in to comment.