Search & Notebook Tagging - Mct4820 (#5203)
* implement new search and tagging for notebooks * add example tags, remove inspector reference * include annotations in mct * fix performance tests Co-authored-by: John Hill <john.c.hill@nasa.gov> Co-authored-by: unlikelyzero <jchill2@gmail.com> Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
@@ -18,6 +18,9 @@
|
||||
}"
|
||||
>
|
||||
<CreateButton class="l-shell__create-button" />
|
||||
<GrandSearch
|
||||
ref="grand-search"
|
||||
/>
|
||||
<indicators class="l-shell__head-section l-shell__indicators" />
|
||||
<button
|
||||
class="l-shell__head__collapse-button c-icon-button"
|
||||
@@ -122,6 +125,7 @@ import Inspector from '../inspector/Inspector.vue';
|
||||
import MctTree from './mct-tree.vue';
|
||||
import ObjectView from '../components/ObjectView.vue';
|
||||
import CreateButton from './CreateButton.vue';
|
||||
import GrandSearch from './search/GrandSearch.vue';
|
||||
import multipane from './multipane.vue';
|
||||
import pane from './pane.vue';
|
||||
import BrowseBar from './BrowseBar.vue';
|
||||
@@ -136,6 +140,7 @@ export default {
|
||||
MctTree,
|
||||
ObjectView,
|
||||
CreateButton,
|
||||
GrandSearch,
|
||||
multipane,
|
||||
pane,
|
||||
BrowseBar,
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<div class="c-search c-search--major">
|
||||
<input
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
};
|
||||
</script>
|
||||
@@ -1,10 +0,0 @@
|
||||
/******************************* SEARCH */
|
||||
.c-search {
|
||||
input[type=search] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&--major {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
class="c-tree-and-search__search"
|
||||
>
|
||||
<search
|
||||
v-show="isSelectorTree"
|
||||
ref="shell-search"
|
||||
class="c-search"
|
||||
:value="searchValue"
|
||||
|
||||
148
src/ui/layout/search/AnnotationSearchResult.vue
Normal file
148
src/ui/layout/search/AnnotationSearchResult.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2022, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="c-gsearch-result c-gsearch-result--annotation"
|
||||
>
|
||||
<div
|
||||
class="c-gsearch-result__type-icon"
|
||||
:class="resultTypeIcon"
|
||||
></div>
|
||||
<div
|
||||
class="c-gsearch-result__body"
|
||||
aria-label="Annotation Search Result"
|
||||
>
|
||||
<div
|
||||
class="c-gsearch-result__title"
|
||||
@click="clickedResult"
|
||||
>
|
||||
{{ getResultName }}
|
||||
</div>
|
||||
|
||||
<ObjectPath
|
||||
ref="location"
|
||||
:read-only="false"
|
||||
/>
|
||||
|
||||
<div class="c-gsearch-result__tags">
|
||||
<div
|
||||
v-for="(tag, index) in result.fullTagModels"
|
||||
:key="index"
|
||||
class="c-tag"
|
||||
:class="{ '--is-not-search-match': !isSearchMatched(tag) }"
|
||||
:style="{ backgroundColor: tag.backgroundColor, color: tag.foregroundColor }"
|
||||
>
|
||||
{{ tag.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="c-gsearch-result__more-options-button">
|
||||
<button class="c-icon-button icon-3-dots"></button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ObjectPath from '../../components/ObjectPath.vue';
|
||||
import objectPathToUrl from '../../../tools/url';
|
||||
|
||||
export default {
|
||||
name: 'AnnotationSearchResult',
|
||||
components: {
|
||||
ObjectPath
|
||||
},
|
||||
inject: ['openmct'],
|
||||
props: {
|
||||
result: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
domainObject() {
|
||||
return this.result.targetModels[0];
|
||||
},
|
||||
getResultName() {
|
||||
if (this.result.annotationType === this.openmct.annotation.ANNOTATION_TYPES.NOTEBOOK) {
|
||||
const targetID = Object.keys(this.result.targets)[0];
|
||||
const entryIdToFind = this.result.targets[targetID].entryId;
|
||||
const notebookModel = this.result.targetModels[0].configuration.entries;
|
||||
|
||||
const sections = Object.values(notebookModel);
|
||||
for (const section of sections) {
|
||||
const pages = Object.values(section);
|
||||
for (const entries of pages) {
|
||||
for (const entry of entries) {
|
||||
if (entry.id === entryIdToFind) {
|
||||
return entry.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "Could not find any matching Notebook entries";
|
||||
} else {
|
||||
return this.result.targetModels[0].name;
|
||||
}
|
||||
},
|
||||
resultTypeIcon() {
|
||||
return this.openmct.types.get(this.result.type).definition.cssClass;
|
||||
},
|
||||
tagBackgroundColor() {
|
||||
return this.result.fullTagModels[0].backgroundColor;
|
||||
},
|
||||
tagForegroundColor() {
|
||||
return this.result.fullTagModels[0].foregroundColor;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const selectionObject = {
|
||||
context: {
|
||||
item: this.domainObject
|
||||
}
|
||||
};
|
||||
this.$refs.location.updateSelection([[selectionObject]]);
|
||||
},
|
||||
methods: {
|
||||
clickedResult() {
|
||||
const objectPath = this.domainObject.originalPath;
|
||||
const resultUrl = objectPathToUrl(this.openmct, objectPath);
|
||||
this.openmct.router.navigate(resultUrl);
|
||||
},
|
||||
isSearchMatched(tag) {
|
||||
if (this.result.matchingTagKeys) {
|
||||
return this.result.matchingTagKeys.includes(tag.tagID);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
145
src/ui/layout/search/GrandSearch.vue
Normal file
145
src/ui/layout/search/GrandSearch.vue
Normal file
@@ -0,0 +1,145 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2022, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="GrandSearch"
|
||||
aria-label="OpenMCT Search"
|
||||
class="c-gsearch"
|
||||
role="searchbox"
|
||||
>
|
||||
<search
|
||||
ref="shell-search"
|
||||
class="c-gsearch__input"
|
||||
tabindex="0"
|
||||
:value="searchValue"
|
||||
@input="searchEverything"
|
||||
@clear="searchEverything"
|
||||
@click="showSearchResults"
|
||||
/>
|
||||
<SearchResultsDropDown
|
||||
ref="searchResultsDropDown"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import search from '../../components/search.vue';
|
||||
import SearchResultsDropDown from './SearchResultsDropDown.vue';
|
||||
|
||||
export default {
|
||||
name: 'GrandSearch',
|
||||
components: {
|
||||
search,
|
||||
SearchResultsDropDown
|
||||
},
|
||||
inject: ['openmct'],
|
||||
props: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchValue: '',
|
||||
searchLoading: false,
|
||||
annotationSearchResults: [],
|
||||
objectSearchResults: []
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
destroyed() {
|
||||
document.body.removeEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
methods: {
|
||||
async searchEverything(value) {
|
||||
// if an abort controller exists, regardless of the value passed in,
|
||||
// there is an active search that should be canceled
|
||||
if (this.abortSearchController) {
|
||||
this.abortSearchController.abort();
|
||||
delete this.abortSearchController;
|
||||
}
|
||||
|
||||
this.searchValue = value;
|
||||
this.searchLoading = true;
|
||||
// clear any previous search results
|
||||
this.annotationSearchResults = [];
|
||||
this.objectSearchResults = [];
|
||||
|
||||
if (this.searchValue) {
|
||||
await this.getSearchResults();
|
||||
} else {
|
||||
this.searchLoading = false;
|
||||
this.$refs.searchResultsDropDown.showResults(this.annotationSearchResults, this.objectSearchResults);
|
||||
}
|
||||
},
|
||||
getPathsForObjects(objectsNeedingPaths) {
|
||||
return Promise.all(objectsNeedingPaths.map(async (domainObject) => {
|
||||
const keyStringForObject = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
const originalPathObjects = await this.openmct.objects.getOriginalPath(keyStringForObject);
|
||||
|
||||
return {
|
||||
originalPath: originalPathObjects,
|
||||
...domainObject
|
||||
};
|
||||
}));
|
||||
},
|
||||
async getSearchResults() {
|
||||
// an abort controller will be passed in that will be used
|
||||
// to cancel an active searches if necessary
|
||||
this.abortSearchController = new AbortController();
|
||||
const abortSignal = this.abortSearchController.signal;
|
||||
try {
|
||||
this.annotationSearchResults = await this.openmct.annotation.searchForTags(this.searchValue, abortSignal);
|
||||
const fullObjectSearchResults = await Promise.all(this.openmct.objects.search(this.searchValue, abortSignal));
|
||||
const aggregatedObjectSearchResults = fullObjectSearchResults.flat();
|
||||
const aggregatedObjectSearchResultsWithPaths = await this.getPathsForObjects(aggregatedObjectSearchResults);
|
||||
const filterAnnotations = aggregatedObjectSearchResultsWithPaths.filter(result => {
|
||||
return result.type !== 'annotation';
|
||||
});
|
||||
this.objectSearchResults = filterAnnotations;
|
||||
this.showSearchResults();
|
||||
} catch (error) {
|
||||
console.error(`😞 Error searching`, error);
|
||||
this.searchLoading = false;
|
||||
|
||||
if (this.abortSearchController) {
|
||||
delete this.abortSearchController;
|
||||
}
|
||||
}
|
||||
},
|
||||
showSearchResults() {
|
||||
this.$refs.searchResultsDropDown.showResults(this.annotationSearchResults, this.objectSearchResults);
|
||||
document.body.addEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
handleOutsideClick(event) {
|
||||
// if click event is detected outside the dropdown while the
|
||||
// dropdown is visible, this will collapse the dropdown.
|
||||
if (this.$refs.GrandSearch) {
|
||||
const clickedInsideDropdown = this.$refs.GrandSearch.contains(event.target);
|
||||
if (!clickedInsideDropdown && this.$refs.searchResultsDropDown._data.resultsShown) {
|
||||
this.$refs.searchResultsDropDown._data.resultsShown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
102
src/ui/layout/search/ObjectSearchResult.vue
Normal file
102
src/ui/layout/search/ObjectSearchResult.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2022, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="c-gsearch-result c-gsearch-result--object"
|
||||
role="presentation"
|
||||
>
|
||||
<div
|
||||
class="c-gsearch-result__type-icon"
|
||||
:class="resultTypeIcon"
|
||||
></div>
|
||||
<div
|
||||
class="c-gsearch-result__body"
|
||||
role="option"
|
||||
:aria-label="`${resultName} ${resultType} result`"
|
||||
>
|
||||
<div
|
||||
class="c-gsearch-result__title"
|
||||
:name="resultName"
|
||||
@click="clickedResult"
|
||||
>
|
||||
{{ resultName }}
|
||||
</div>
|
||||
|
||||
<ObjectPath
|
||||
ref="objectpath"
|
||||
:read-only="false"
|
||||
/>
|
||||
</div>
|
||||
<div class="c-gsearch-result__more-options-button">
|
||||
<button class="c-icon-button icon-3-dots"></button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ObjectPath from '../../components/ObjectPath.vue';
|
||||
import objectPathToUrl from '../../../tools/url';
|
||||
|
||||
export default {
|
||||
name: 'ObjectSearchResult',
|
||||
components: {
|
||||
ObjectPath
|
||||
},
|
||||
inject: ['openmct'],
|
||||
props: {
|
||||
result: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
resultName() {
|
||||
return this.result.name;
|
||||
},
|
||||
resultTypeIcon() {
|
||||
return this.openmct.types.get(this.result.type).definition.cssClass;
|
||||
},
|
||||
resultType() {
|
||||
return this.result.type;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const selectionObject = {
|
||||
context: {
|
||||
item: this.result
|
||||
}
|
||||
};
|
||||
this.$refs.objectpath.updateSelection([[selectionObject]]);
|
||||
},
|
||||
methods: {
|
||||
clickedResult() {
|
||||
const objectPath = this.result.originalPath;
|
||||
const resultUrl = objectPathToUrl(this.openmct, objectPath);
|
||||
this.openmct.router.navigate(resultUrl);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
99
src/ui/layout/search/SearchResultsDropDown.vue
Normal file
99
src/ui/layout/search/SearchResultsDropDown.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2022, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="(annotationResults && annotationResults.length) ||
|
||||
(objectResults && objectResults.length)"
|
||||
class="c-gsearch__dropdown"
|
||||
>
|
||||
<div
|
||||
v-show="resultsShown"
|
||||
class="c-gsearch__results-wrapper"
|
||||
>
|
||||
<div class="c-gsearch__results">
|
||||
<div
|
||||
v-if="objectResults && objectResults.length"
|
||||
ref="objectResults"
|
||||
class="c-gsearch__results-section"
|
||||
role="listbox"
|
||||
>
|
||||
<div class="c-gsearch__results-section-title">Object Results</div>
|
||||
<object-search-result
|
||||
v-for="(objectResult, index) in objectResults"
|
||||
:key="index"
|
||||
:result="objectResult"
|
||||
@click.native="selectedResult"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="annotationResults && annotationResults.length"
|
||||
ref="annotationResults"
|
||||
>
|
||||
<div class="c-gsearch__results-section-title">Annotation Results</div>
|
||||
<annotation-search-result
|
||||
v-for="(annotationResult, index) in annotationResults"
|
||||
:key="index"
|
||||
:result="annotationResult"
|
||||
@click.native="selectedResult"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AnnotationSearchResult from './AnnotationSearchResult.vue';
|
||||
import ObjectSearchResult from './ObjectSearchResult.vue';
|
||||
|
||||
export default {
|
||||
name: 'SearchResultsDropDown',
|
||||
components: {
|
||||
AnnotationSearchResult,
|
||||
ObjectSearchResult
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
resultsShown: false,
|
||||
annotationResults: [],
|
||||
objectResults: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
selectedResult() {
|
||||
this.resultsShown = false;
|
||||
},
|
||||
showResults(passedAnnotationResults, passedObjectResults) {
|
||||
if ((passedAnnotationResults && passedAnnotationResults.length)
|
||||
|| (passedObjectResults && passedObjectResults.length)) {
|
||||
this.resultsShown = true;
|
||||
this.annotationResults = passedAnnotationResults;
|
||||
this.objectResults = passedObjectResults;
|
||||
} else {
|
||||
this.resultsShown = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
template: 'Dropdown'
|
||||
};
|
||||
</script>
|
||||
137
src/ui/layout/search/search.scss
Normal file
137
src/ui/layout/search/search.scss
Normal file
@@ -0,0 +1,137 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2022, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************* EXPANDED SEARCH 2022 */
|
||||
.c-gsearch {
|
||||
.l-shell__head & {
|
||||
// Search input in the shell head
|
||||
width: 20%;
|
||||
|
||||
.c-search {
|
||||
background: rgba($colorHeadFg, 0.2);
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__results-wrapper {
|
||||
@include menuOuter();
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: $interiorMarginLg;
|
||||
min-width: 500px;
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
&__results,
|
||||
&__results-section {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
&__results {
|
||||
// Holds n __results-sections
|
||||
padding-right: $interiorMargin; // Fend off scrollbar
|
||||
overflow-y: auto;
|
||||
|
||||
> * + * {
|
||||
margin-top: $interiorMarginLg;
|
||||
}
|
||||
}
|
||||
|
||||
&__results-section {
|
||||
> * + * {
|
||||
margin-top: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
|
||||
&__results-section-title {
|
||||
@include propertiesHeader();
|
||||
}
|
||||
}
|
||||
|
||||
.c-gsearch-result {
|
||||
display: flex;
|
||||
padding: $interiorMargin $interiorMarginSm;
|
||||
|
||||
> * + * {
|
||||
margin-left: $interiorMarginLg;
|
||||
}
|
||||
|
||||
+ .c-gsearch-result {
|
||||
border-top: 1px solid $colorInteriorBorder;
|
||||
}
|
||||
|
||||
&__type-icon,
|
||||
&__more-options-button {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
&__type-icon {
|
||||
color: $colorItemTreeIcon;
|
||||
font-size: 2.2em;
|
||||
|
||||
// TEMP: uses object-label component, hide label part
|
||||
.c-object-label__name {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__more-options-button {
|
||||
display: none; // TEMP until enabled
|
||||
}
|
||||
|
||||
&__body {
|
||||
flex: 1 1 auto;
|
||||
|
||||
> * + * {
|
||||
margin-top: $interiorMarginSm;
|
||||
}
|
||||
|
||||
.c-location {
|
||||
font-size: 0.9em;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
&__tags {
|
||||
display: flex;
|
||||
|
||||
> * + * {
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
border-radius: $basicCr;
|
||||
color: pullForward($colorBodyFg, 30%);
|
||||
cursor: pointer;
|
||||
font-size: 1.15em;
|
||||
padding: 3px $interiorMarginSm;
|
||||
|
||||
&:hover {
|
||||
background-color: $colorItemTreeHoverBg;
|
||||
}
|
||||
}
|
||||
|
||||
.c-tag {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user