Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add search module bar into landscape screen #11151

Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5a80fe0
test: add test to confirm if the search module bar is rendered
renanfranca Oct 14, 2024
6d5dd35
feat: add search module bar into Landscape.html
renanfranca Oct 14, 2024
b483833
refactor: change test name
renanfranca Oct 14, 2024
ee160c6
test: add test to highlight first module found in landscape search
renanfranca Oct 14, 2024
2f937ec
feat: add search functionality to landscape view
renanfranca Oct 14, 2024
2781978
refactor: use @input instead of watch with v-model to perform search
renanfranca Oct 14, 2024
db0f054
refactor: simplify landscape component validation logic
renanfranca Oct 14, 2024
99e674f
test: add test that should remove the highlight when the input is cle…
renanfranca Oct 15, 2024
ee79a65
test: add test for search query not matching any modules
renanfranca Oct 15, 2024
66782fc
refactor: extract search test setup and perform search into helper fu…
renanfranca Oct 15, 2024
00a80de
feat: add scrollIntoView feature to LandscapeScroller.ts
renanfranca Oct 15, 2024
db90461
test: add tests that should scroll the screen to the highlighted modu…
renanfranca Oct 15, 2024
d8611f3
feat: add scroll to highlighted module
renanfranca Oct 15, 2024
7f40b21
test: fix mocks of the elements out of Viewport or in Viewport
renanfranca Oct 15, 2024
84d2192
feat: improve scrolling behavior for highlighted module
renanfranca Oct 15, 2024
5435a11
test: fix the landscape-container mock to test the scroll to highligh…
renanfranca Oct 15, 2024
4f6cb62
test: refactor the search module bar scroll tests to avoid code dupli…
renanfranca Oct 16, 2024
bfc1a44
refactor: remove unnecessary if branch to avoid creating tests solely…
renanfranca Oct 17, 2024
43917fd
refactor: change methods order to make it easier to read and understa…
renanfranca Oct 17, 2024
ca83a5f
test: add test to highlight the first feature found
renanfranca Oct 17, 2024
ad3886c
test: remove unnecessary mockRestore call since every test is atomic …
renanfranca Oct 17, 2024
ae72bba
feat: reset the landscape container position to the initial landscape…
renanfranca Oct 17, 2024
a8dc881
refactor: improve code quality and readability from highlightModule m…
renanfranca Oct 17, 2024
0c97983
feat: scroll smooth when reset the landscapeContainer position in Lan…
renanfranca Oct 17, 2024
2397e03
feat: add styles to the search module bar and highlight around the fo…
renanfranca Oct 17, 2024
346328d
feat: add z-index to anchor-point be on top of the highlighted module…
renanfranca Oct 18, 2024
ef1eca3
refactor: move the highlight module pulse animation to _animation.scss
renanfranca Oct 18, 2024
814ef62
refactor: move .-search-highlighted to a better location in _landscap…
renanfranca Oct 18, 2024
d5181a1
refactor: create scss variable for the attention highlight color in _…
renanfranca Oct 18, 2024
7c39321
feat: hide the search module bar when the screen size is small
renanfranca Oct 18, 2024
5b730a8
feat: remove the .-search-highlight animation because it is overlayin…
renanfranca Oct 18, 2024
aa6544a
Update src/main/webapp/app/module/primary/landscape/Landscape.compone…
renanfranca Oct 18, 2024
dcbe6f2
refactor: use Optional at the definition of highlightedModule const i…
renanfranca Oct 21, 2024
8baa2e4
refactor: use Optional at the return definition of findModule arrow f…
renanfranca Oct 21, 2024
4126d09
refactor: improve highlightModule arrow function to avoid the use of …
renanfranca Oct 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/style/atom/chip/_chip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ $jhlite-anchor-point-border-size: 3px;
%anchor-point {
position: absolute;
top: calc(50% - $jhlite-anchor-point-size);
z-index: 2;
outline: solid 1px var(--jhlite-chip-default-anchor-color);
border: $jhlite-anchor-point-border-size solid var(--jhlite-chip-bg-color);
border-radius: $jhlite-anchor-point-size;
Expand Down
50 changes: 50 additions & 0 deletions src/main/style/organism/landscape/_landscape.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
@use '../../token/breakpoint';
@use '../../token/colors';
@use '../../token/size';

$jhlite-landscape-padding: 20px;
$jhipster-landscape-preset-selection-top-position: 85px;
Expand Down Expand Up @@ -38,6 +40,26 @@ $jhlite-landscape-primary-alternative-color: colors.$jhlite-global-primary-alter
background: var(--jhlite-chip-bg-color);
}

.jhipster-landscape-content {
&--header {
display: none;
}
}

.jhipster-landscape-search-container {
display: flex;
flex-grow: 1;
justify-content: center;
}

.jhipster-landscape-search {
display: flex;
align-items: center;
border-radius: size.$jhlite-global-size-field-radius;
box-shadow: 0 2px 10px rgb(0 0 0 / 10%);
padding: 10px;
}

.jhipster-landscape-connectors {
position: absolute;
top: $jhlite-landscape-padding;
Expand Down Expand Up @@ -157,8 +179,36 @@ $jhlite-landscape-primary-alternative-color: colors.$jhlite-global-primary-alter
margin-bottom: 15px;
}
}

.-search-highlighted {
border-radius: size.$jhlite-global-size-field-radius;
box-shadow: 0 0 0 size.$jhlite-global-size-field-border-focus colors.$jhlite-attention-highlight-color;
}
}

.jhipster-landscape {
position: relative;
}

@media screen and (min-width: breakpoint.$jhlite-global-breakpoint-small-medium) {
.jhipster-landscape {
.jhipster-landscape-content {
display: flex;
flex-direction: column;
height: 100%;

&--header {
display: flex;
align-items: center;
padding: 20px 0;
}

&--modules {
display: flex;
flex-grow: 1;
min-height: 0;
overflow: auto;
}
}
}
}
1 change: 1 addition & 0 deletions src/main/style/token/_colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,4 @@ $jhlite-valid-highlight-start-color: #3ebf5a;
$jhlite-valid-highlight-end-color: $jhlite-global-color-success;
$jhlite-invalid-highlight-start-color: #bf3e3e;
$jhlite-invalid-highlight-end-color: $jhlite-global-color-error;
$jhlite-attention-highlight-color: #ffd700;
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export default defineComponent({
const selectedPreset = ref<Preset | null>(null);
const selectedPresetName = computed(() => selectedPreset.value?.name ?? '');

const highlightedModule = ref<ModuleSlug | null>(null);

onMounted(() => {
modules
.landscape()
Expand Down Expand Up @@ -262,7 +264,7 @@ export default defineComponent({

const landscapeClass = (): string => {
const hasEmphasizedModule = emphasizedModule.value !== undefined;
return `jhipster-landscape-map jhlite-menu-content-template--content${hasEmphasizedModule ? ' has-emphasized-module' : ''}`;
return `jhipster-landscape-map jhipster-landscape-content--modules ${hasEmphasizedModule ? ' has-emphasized-module' : ''}`;
};

const modeSwitchClass = (mode: DisplayMode): string => {
Expand Down Expand Up @@ -308,7 +310,8 @@ export default defineComponent({
selectionClass(module) +
applicationClass(module) +
flavorClass() +
anchorPointClass(module)
anchorPointClass(module) +
searchHighlightClass(module)
);
};

Expand Down Expand Up @@ -384,6 +387,13 @@ export default defineComponent({
return ' ' + modeClass();
};

const searchHighlightClass = (module: LandscapeElementId): string => {
if (highlightedModule.value && module.get() === highlightedModule.value.get()) {
return ' -search-highlighted';
}
return '';
};

const modeClass = (): string => {
switch (selectedMode.value) {
case 'COMPACTED':
Expand Down Expand Up @@ -463,11 +473,7 @@ export default defineComponent({
return true;
}

if (missingMandatoryProperty()) {
return true;
}

return false;
return missingMandatoryProperty();
};

const selectedNewModulesCount = (): number => {
Expand Down Expand Up @@ -592,6 +598,44 @@ export default defineComponent({
return document?.activeElement?.tagName === 'INPUT';
};

const performSearch = (query: string) => {
highlightModule(query);
};

const highlightModule = (query: string) => {
if (!query) {
highlightedModule.value = null;
nextTick().then(resetLandscapeContainerPosition);
return;
}

const foundModule = findModule(query);
highlightedModule.value = foundModule ? new ModuleSlug(foundModule) : null;

if (foundModule) {
const moduleElement = landscapeElements.value.get(foundModule)!;
nextTick().then(() => scrollToHighlightedModule(moduleElement));
}
};

const findModule = (query: string): string | null => {
return [...landscapeElements.value.keys()].find(key => key.toLowerCase().includes(query.toLowerCase())) || null;
};

const resetLandscapeContainerPosition = (): void | PromiseLike<void> => landscapeScroller.scrollSmooth(landscapeContainer.value, 0, 0);

const scrollToHighlightedModule = (moduleElement: HTMLElement): void => {
const rect = moduleElement.getBoundingClientRect();
const containerRect = landscapeContainer.value.getBoundingClientRect();

const verticallyOutOfView = rect.top < containerRect.top || rect.bottom > containerRect.bottom;
const horizontallyOutOfView = rect.left < containerRect.left || rect.right > containerRect.right;

if (verticallyOutOfView || horizontallyOutOfView) {
landscapeScroller.scrollIntoView(moduleElement);
}
};

return {
levels,
isFeature,
Expand Down Expand Up @@ -633,6 +677,7 @@ export default defineComponent({
grabbing,
canLoadMiniMap,
selectedPresetName,
performSearch,
};
},
});
135 changes: 77 additions & 58 deletions src/main/webapp/app/module/primary/landscape/Landscape.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,68 +25,87 @@
<div class="jhipster-landscape-preset-selection">
<LandscapePresetConfigurationVue :selectedPresetName="selectedPresetName" @selected="selectModulesFromPreset" />
</div>

<div
:class="landscapeClass()"
ref="landscapeContainer"
data-selector="landscape-container"
@mousedown="startGrabbing"
@mousemove="grabbing"
@mouseup="stopGrabbing"
@mouseleave="stopGrabbing"
>
<div class="jhipster-landscape-levels">
<ul class="jhipster-landscape-levels--level" :class="modeClass()" v-for="level in levels.value()">
<li class="jhipster-landscape-element" v-for="element in level.elements" :class="modeClass()">
<div
class="jhipster-landscape-feature"
:class="elementFlavor(element.slug())"
:data-selector="`${element.slugString()}-feature`"
v-if="isFeature(element)"
:ref="el => landscapeElements.set(element.slugString(), el)"
>
<h2 class="jhipster-landscape-feature--title" :class="modeClass()">{{ element.slugString() }}</h2>
<ul class="jhipster-landscape-feature--modules">
<li class="jhipster-landscape-feature--module" v-for="module in element.modules">
<LandscapeModuleVue
:module="module"
:landscapeElements="landscapeElements"
:moduleFlavor="elementFlavor(module.slug())"
@over="emphasizeModule(module.slug())"
@out="deEmphasizeModule()"
@clicked="toggleModule(module.slug())"
@apply="applyModule(module.slug())"
/>
</li>
</ul>
<div class="jhlite-menu-content-template--content">
<div class="jhipster-landscape-content">
<div class="jhipster-landscape-content--header">
<div class="jhipster-landscape-search-container">
<div class="jhipster-landscape-search">
<div class="jhlite-field--field">
<input
type="text"
class="jhlite-input-text"
placeholder="Search modules..."
@input="performSearch($event.target.value)"
data-selector="landscape-search-input"
/>
</div>
</div>
</div>
</div>

<LandscapeModuleVue
:module="element"
:landscapeElements="landscapeElements"
:moduleFlavor="elementFlavor(element.slug())"
@over="emphasizeModule(element.slug())"
@out="deEmphasizeModule()"
@clicked="toggleModule(element.slug())"
@apply="applyModule(element.slug())"
v-else
<div
:class="landscapeClass()"
ref="landscapeContainer"
data-selector="landscape-container"
@mousedown="startGrabbing"
@mousemove="grabbing"
@mouseup="stopGrabbing"
@mouseleave="stopGrabbing"
>
<div class="jhipster-landscape-levels">
<ul class="jhipster-landscape-levels--level" :class="modeClass()" v-for="level in levels.value()">
<li class="jhipster-landscape-element" v-for="element in level.elements" :class="modeClass()">
<div
class="jhipster-landscape-feature"
:class="elementFlavor(element.slug())"
:data-selector="`${element.slugString()}-feature`"
v-if="isFeature(element)"
:ref="el => landscapeElements.set(element.slugString(), el)"
>
<h2 class="jhipster-landscape-feature--title" :class="modeClass()">{{ element.slugString() }}</h2>
<ul class="jhipster-landscape-feature--modules">
<li class="jhipster-landscape-feature--module" v-for="module in element.modules">
<LandscapeModuleVue
:module="module"
:landscapeElements="landscapeElements"
:moduleFlavor="elementFlavor(module.slug())"
@over="emphasizeModule(module.slug())"
@out="deEmphasizeModule()"
@clicked="toggleModule(module.slug())"
@apply="applyModule(module.slug())"
/>
</li>
</ul>
</div>

<LandscapeModuleVue
:module="element"
:landscapeElements="landscapeElements"
:moduleFlavor="elementFlavor(element.slug())"
@over="emphasizeModule(element.slug())"
@out="deEmphasizeModule()"
@clicked="toggleModule(element.slug())"
@apply="applyModule(element.slug())"
v-else
/>
</li>
</ul>
</div>

<svg
class="jhipster-landscape-connectors"
:style="`width: ${landscapeSize.width}px; height: ${landscapeSize.height}px`"
data-selector="landscape-connectors"
>
<path
v-for="connector in landscapeConnectors"
class="jhipster-landscape-connectors--line"
:class="elementFlavor(connector.startingElement)"
:d="connector.path"
/>
</li>
</ul>
</svg>
</div>
</div>

<svg
class="jhipster-landscape-connectors"
:style="`width: ${landscapeSize.width}px; height: ${landscapeSize.height}px`"
data-selector="landscape-connectors"
>
<path
v-for="connector in landscapeConnectors"
class="jhipster-landscape-connectors--line"
:class="elementFlavor(connector.startingElement)"
:d="connector.path"
/>
</svg>
</div>

<div class="jhlite-menu-content-template--menu">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,12 @@ export class LandscapeScroller {
scroll(element: HTMLElement, scrollX: number, scrollY: number) {
element.scroll(scrollX, scrollY);
}

scrollSmooth(element: HTMLElement, scrollX: number, scrollY: number) {
element.scroll({ left: scrollX, top: scrollY, behavior: 'smooth' });
}

scrollIntoView(element: HTMLElement) {
element.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' });
}
}
Loading
Loading