Ship v1 of standard query library (#898)

* Implement detail page for standard query lib

* Add alt text for image

* Replace id with css class

* Implement query-libary page for fleetdm.com

* Remove console.log

* Implement client-side search for query library

* Add responsive breakppoints

* Fix input tag
This commit is contained in:
gillespi314 2021-05-28 16:57:04 -05:00 committed by GitHub
parent 1512089384
commit 0c236fd701
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 31 deletions

View file

@ -3,6 +3,9 @@ parasails.registerPage('query-library', {
// ║║║║║ ║ ║╠═╣║ ╚═╗ ║ ╠═╣ ║ ║╣
// ╩╝╚╝╩ ╩ ╩╩ ╩╩═╝ ╚═╝ ╩ ╩ ╩ ╩ ╚═╝
data: {
inputTextValue: '',
inputTimers: {},
searchString: '', // The user input string to be searched against the query library
selectedPurpose: 'all', // Initially set to all, the user may select a different option to filter queries by purpose (e.g., "all queries", "information", "detection")
selectedPlatform: 'all', // Initially set to all, the user may select a different option to filter queries by platform (e.g., "all platforms", "macOS", "Windows", "Linux")
},
@ -12,6 +15,14 @@ parasails.registerPage('query-library', {
return _.filter(this.queries, (query) => this.isIncluded(query.platforms, this.selectedPlatform) && this.isIncluded(query.purpose, this.selectedPurpose));
},
searchResults: function () {
return this.search(this.filteredQueries, this.searchString);
},
queriesList: function () {
return this.searchResults;
}
},
// ╦ ╦╔═╗╔═╗╔═╗╦ ╦╔═╗╦ ╔═╗
@ -28,10 +39,6 @@ parasails.registerPage('query-library', {
// ║║║║ ║ ║╣ ╠╦╝╠═╣║ ║ ║║ ║║║║╚═╗
// ╩╝╚╝ ╩ ╚═╝╩╚═╩ ╩╚═╝ ╩ ╩╚═╝╝╚╝╚═╝
methods: {
//…
clickCard: function (querySlug) {
window.location = '/sandbox/queries/' + querySlug.toLowerCase(); // TODO remove sandbox from path before deploy to production
},
isIncluded: function (queryProperty, selectedOption) {
if (selectedOption.startsWith('all') || selectedOption === '') {
@ -43,6 +50,31 @@ parasails.registerPage('query-library', {
return _.isString(queryProperty) && queryProperty.toLowerCase().includes(selectedOption.toLowerCase());
},
search: function (library, searchString) {
const searchTerms = _.isString(searchString) ? searchString.toLowerCase().split(' ') : [];
return library.filter((item) => {
const description = _.isString(item.description) ? item.description.toLowerCase() : '';
return _.some(searchTerms, (term) => description.includes(term));
});
},
setSearchString: function () {
this.searchString = this.inputTextValue;
},
delayInput: function(callback, ms, label) {
let inputTimers = this.inputTimers;
return function () {
label = label || 'defaultTimer';
_.has(inputTimers, label) ? clearTimeout(inputTimers[label]) : 0;
inputTimers[label] = setTimeout(callback, ms);
};
},
clickCard: function (querySlug) {
window.location = '/sandbox/queries/' + querySlug.toLowerCase(); // TODO remove sandbox from path before deploy to production
},
}
});

View file

@ -27,6 +27,10 @@
border: none;
}
input {
max-width: 176px;
}
.filter-and-search-bar {
margin-left: 30px;
margin-right: 30px;
@ -42,7 +46,8 @@
}
.row {
min-height: 70px;;
min-height: 70px;
align-items: center;
}
.card.results {
@ -51,13 +56,11 @@
border-radius: 8px;
border-bottom: 1px solid;
border-color: #E2E4EA;
;
}
.card.results:hover {
background-color: #F1F0FF;
&:hover {
background-color: #F1F0FF;
cursor: pointer;
}
}
.card.call-to-action {

View file

@ -21,7 +21,7 @@
</div>
</div>
<div class="col-3 mx-5 my-5">
<div class="col-3 mx-5 my-5 d-none d-md-block">
<!-- TODO: refactor as page script to type-check and normalize"-->
<div class="query-sidebar border-bottom mb-3">
<h5 permalink="support">Platforms</h5>

View file

@ -5,31 +5,38 @@
<h2 class="mb-3">Standard query library</h2>
<h6 class="font-weight-light pb-3">Fleet's standard query library includes a growing collection of useful queries for organizations deploying Fleet and osquery.</h6>
<div class="filter-and-search-bar container">
<div class="row">
<div class="filter-purpose">
<span>Show
<select class="mr-1" v-model="selectedPurpose">
<option value="all" selected>all queries</option>
<option value="information">informational</option>
<option value="detection">detection</option>
</select>
</span>
<div class="row justify-content-between">
<div class="col-8 d-flex px-0">
<div class="filter-purpose">
<span>Show
<select class="mr-1" v-model="selectedPurpose">
<option value="all" selected>all queries</option>
<option value="information">informational</option>
<option value="detection">detection</option>
</select>
</span>
</div>
<div class="filter-platform">
<span> compatible with
<select class="mr-1" v-model="selectedPlatform">
<option value="all" selected>all platforms</option>
<option value="macOS">macOS</option>
<option value="Windows">Windows</option>
<option value="Linux">Linux</option>
</select>
</span>
</div>
</div>
<div class="filter-platform">
<span> compatible with
<select class="mr-1" v-model="selectedPlatform">
<option value="all" selected>all platforms</option>
<option value="macOS">macOS</option>
<option value="Windows">Windows</option>
<option value="Linux">Linux</option>
</select>
</span>
<div class="col-3 px-0 d-none d-lg-block justify-content-end">
<div class="search ">
<input v-model="inputTextValue" placeholder="Search" @keydown.self="delayInput(setSearchString, 1000, 'defaultTimer')()"/>
</div>
</div>
</div>
</div>
<div class="results">
<div class="category__informational">
<div v-for="query of filteredQueries">
<div v-for="query of queriesList">
<div class="card results" @click="clickCard(query.slug)">
<div class="card-body">
<div class="row justify-content-between align-items-center">