Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
de95979
Add search bar with request
Jun 20, 2023
0195377
Filter works, erronious lines in tree
Jun 22, 2023
d07d52d
Remove extra lines
Jun 22, 2023
04b3107
Force bytes input to be valid with spaces
Jun 22, 2023
e57f46e
Hook bytes request up to front end
Jun 22, 2023
a3c837b
Didn't commit try catch in bytes validation
Jun 22, 2023
2f2751c
Prevent bad bytes format from displaying if entered before valid
Jun 22, 2023
7feb457
semicolon
Jun 22, 2023
c00331a
Merge branch 'master' of github.com:dannyp303/ofrak into feature/sear…
Jun 22, 2023
1b702d3
Update to new search API
Jun 22, 2023
dfe9eb6
Use POST and but search query in body
Jun 22, 2023
7a33d53
Regex works with checkbox among other things
Jun 26, 2023
6b292f5
live update search
Jun 26, 2023
257f1e3
Add case insensitivity option
Jun 26, 2023
a7b34a1
Add tests for search
Jun 26, 2023
30f43b1
Some fortmatting stuff
Jun 26, 2023
dba7a5d
Update frontend/src/ResourceSearchBar.svelte
dannyp303 Jun 26, 2023
2ec9917
update tests to test good and back conditions
Jun 26, 2023
84c0602
removed dead code
Jun 26, 2023
8e16f33
Do input placeholder css properly
Jun 26, 2023
5e6d180
lint
Jun 26, 2023
d077ea8
Move empty search check up
Jun 26, 2023
92f7690
Catch exceptions in search bar
Jun 26, 2023
25b7db1
Update ofrak_core/ofrak/gui/server.py
dannyp303 Jun 27, 2023
1a8ebc7
Update ofrak_core/ofrak/gui/server.py
dannyp303 Jun 27, 2023
d9f1d14
Remove live update
Jun 27, 2023
44edba2
remove dummy filter variable
Jun 27, 2023
14133d2
Skip backend request for empty search
Jun 28, 2023
366ef43
Why is no one else seeing this?
Jun 28, 2023
32ff28a
Use re.escape for no-regex + case ignore
Jun 29, 2023
51dfa0f
make mypy smile
Jun 30, 2023
bf17c9c
Fix the case ignore and tests
Jun 30, 2023
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
137 changes: 137 additions & 0 deletions frontend/src/ResourceSearchBar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<style>
select {
background-color: var(--main-bg-color);
color: inherit;
border: 1px solid;
border-color: inherit;
border-radius: 0;
font-size: inherit;
font-family: var(--font);
box-shadow: none;
}

input {
background: inherit;
color: inherit;
border: 1px solid;
border-bottom: 1px solid var(--main-fg-color);
flex: 1;
text-indent: 0.5em;
}

form {
display: inherit;
flex: 1;
}

label {
display: inherit;
flex: 1;
}

.searchbar {
display: flex;
align-items: left;
width: 100%;
flex-grow: 1;
height: 2em;
}

.optionbar {
padding-bottom: 0;
padding-top: 0;
}
</style>

<script>
import Checkbox from "./Checkbox.svelte";
export let rootResource, searchFilter;
let searchType,
searchQuery,
bytesInput,
regex,
placeholderString,
caseIgnore,
errorMessage;
let searchTypes = ["String", "Bytes"];

$: if (searchQuery && searchType === "Bytes") {
try {
searchQuery = searchQuery.match(/[0-9a-fA-F]{1,2}/g).join(" ");
Comment thread
dannyp303 marked this conversation as resolved.
bytesInput?.setCustomValidity("");
} catch {
searchQuery = "";
bytesInput?.setCustomValidity("Invalid bytes representation.");
}
}

$: if (searchType == "String") {
if (regex) {
placeholderString = "Search for a Regex Pattern";
} else {
placeholderString = "Search for a String";
}
} else if (searchType == "Bytes") {
regex = false; // Regex for bytes not yet implemented
placeholderString = "Search for Bytes";
}
</script>

<div class="searchbar">
<select bind:value="{searchType}">
{#each searchTypes as type}
<option value="{type}">
{type}
</option>
{/each}
</select>
<form
on:submit|preventDefault="{async (e) => {
try {
if (searchType == 'String') {
if (searchQuery === '') {
searchFilter = null;
} else {
searchFilter = await rootResource.search_for_string(
searchQuery,
regex,
caseIgnore
);
}
} else if (searchType == 'Bytes') {
if (searchQuery === '') {
searchFilter = null;
} else {
searchFilter = await rootResource.search_for_bytes(
searchQuery,
false
);
}
}
} catch (err) {
try {
errorMessage = JSON.parse(err.message).message;
} catch (_) {
errorMessage = err.message;
}
console.log('Search Failed!');
console.log(errorMessage);
}
}}"
>
<label>
<input placeholder="{placeholderString}" bind:value="{searchQuery}" />
</label>
</form>
</div>

<div class="optionbar">
{#if searchType == "String"}
<Checkbox checked="{false}" bind:value="{regex}" leftbox="{true}">
Pattern
</Checkbox>
<Checkbox checked="{false}" bind:value="{caseIgnore}" leftbox="{true}">
Ignore Case
</Checkbox>
{/if}
</div>
167 changes: 86 additions & 81 deletions frontend/src/ResourceTreeNode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@
selectNextSibling = () => {},
selectPreviousSibling = () => {},
collapsed = true,
childrenCollapsed = true;
childrenCollapsed = true,
searchFilter;
let firstChild,
childrenPromise,
commentsPromise,
Expand Down Expand Up @@ -156,7 +157,6 @@
lastModified = resourceNodeDataMap[self_id].lastModified;
allModified = resourceNodeDataMap[self_id].allModified;
}

function updateRootModel() {
rootResource.update();
rootResource = rootResource;
Expand Down Expand Up @@ -230,84 +230,89 @@
});
</script>

{#await childrenPromise then children}
{#if children?.length > 0}
<button
on:click="{() => {
resourceNodeDataMap[self_id].collapsed = !collapsed;
}}"
>
{#if collapsed}
[+{children.length}]
{:else}
[-]
{/if}
<!-- Ugly next line is required to prevent Svelte from adding space after the button -->
</button>{/if}{/await}<button
on:click="{onClick}"
on:dblclick="{onDoubleClick}"
class:selected="{$selected === self_id}"
class:lastModified="{resourceNodeDataMap[self_id].lastModified}"
class:allModified="{resourceNodeDataMap[self_id].allModified}"
id="{self_id}"
>
{rootResource.get_caption()}
</button>
{#await commentsPromise then comments}
{#each comments as comment}
<div class="comment">
<Hoverable let:hovering>
<button
title="Delete this comment"
on:click="{onDeleteClick(comment[0])}"
>
<Icon
class="comment_icon"
url="{hovering ? '/icons/trash_can.svg' : '/icons/comment.svg'}"
/>
</button></Hoverable
>{comment[1]}
</div>
{/each}
{/await}

{#await childrenPromise}
<LoadingText />
{:then children}
{#if !collapsed && children.length > 0}
<ul>
{#each children.slice(0, kiddoChunksize) as child, i}
<li>
<div>
<svelte:self
rootResource="{child}"
collapsed="{childrenCollapsed}"
childrenCollapsed="{childrenCollapsed}"
selectNextSibling="{i ===
Math.min(kiddoChunksize, children.length) - 1
? selectNextSibling
: () => {
$selected = children[i + 1]?.resource_id;
}}"
selectPreviousSibling="{i === 0
? () => {
$selected = self_id;
}
: () => {
$selected = children[i - 1]?.resource_id;
}}"
bind:resourceNodeDataMap="{resourceNodeDataMap}"
{#if searchFilter == null || searchFilter.includes(self_id)}
{#await childrenPromise then children}
{#if children?.length > 0}
<button
on:click="{() => {
resourceNodeDataMap[self_id].collapsed = !collapsed;
}}"
>
{#if collapsed}
[+{children.length}]
{:else}
[-]
{/if}
<!-- Ugly next line is required to prevent Svelte from adding space after the button -->
</button>{/if}{/await}<button
on:click="{onClick}"
on:dblclick="{onDoubleClick}"
class:selected="{$selected === self_id}"
class:lastModified="{resourceNodeDataMap[self_id].lastModified}"
class:allModified="{resourceNodeDataMap[self_id].allModified}"
id="{self_id}"
>
{rootResource.get_caption()}
</button>
{#await commentsPromise then comments}
{#each comments as comment}
<div class="comment">
<Hoverable let:hovering>
<button
title="Delete this comment"
on:click="{onDeleteClick(comment[0])}"
>
<Icon
class="comment_icon"
url="{hovering ? '/icons/trash_can.svg' : '/icons/comment.svg'}"
/>
</button></Hoverable
>{comment[1]}
</div>
{/each}
{/await}

{#await childrenPromise}
<LoadingText />
{:then children}
{#if !collapsed && children.length > 0}
<ul>
{#each children.slice(0, kiddoChunksize) as child, i}
{#if searchFilter == null || searchFilter.includes(child.get_id())}
<li>
<div>
<svelte:self
rootResource="{child}"
collapsed="{childrenCollapsed}"
childrenCollapsed="{childrenCollapsed}"
selectNextSibling="{i ===
Math.min(kiddoChunksize, children.length) - 1
? selectNextSibling
: () => {
$selected = children[i + 1]?.resource_id;
}}"
selectPreviousSibling="{i === 0
? () => {
$selected = self_id;
}
: () => {
$selected = children[i - 1]?.resource_id;
}}"
bind:resourceNodeDataMap="{resourceNodeDataMap}"
searchFilter="{searchFilter}"
/>
</div>
</li>
{/if}
{/each}
{#if children.length > kiddoChunksize}
<div class="morebutton">
<button on:click="{() => (kiddoChunksize += 512)}">
Show 512 more children...
</button>
</div>
</li>
{/each}
{#if children.length > kiddoChunksize}
<div class="morebutton">
<button on:click="{() => (kiddoChunksize += 512)}">
Show 512 more children...
</button>
</div>
{/if}
</ul>
{/if}
{/await}
{/if}
</ul>
{/if}
{/await}
{/if}
33 changes: 27 additions & 6 deletions frontend/src/ResourceTreeView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,36 @@
overflow: auto;
}

.resources {
flex-grow: 1;
}

.treebox {
flex-grow: 1;
padding-left: 1em;
overflow-x: auto;
white-space: nowrap;
text-align: left;
}

.searchbar {
flex-grow: 1;
padding-left: 1em;
padding-bottom: 0.5em;
}
</style>

<script>
import ResourceSearchBar from "./ResourceSearchBar.svelte";
import ResourceTreeNode from "./ResourceTreeNode.svelte";
import ResourceTreeToolbar from "./ResourceTreeToolbar.svelte";

export let rootResource,
modifierView,
bottomLeftPane,
resourceNodeDataMap = {};

let searchFilter;
</script>

<div class="hbox">
Expand All @@ -53,11 +66,19 @@
bind:bottomLeftPane="{bottomLeftPane}"
/>
</div>

<div class="treebox">
<ResourceTreeNode
rootResource="{rootResource}"
bind:resourceNodeDataMap="{resourceNodeDataMap}"
/>
<div class="resources">
<div class="searchbar">
<ResourceSearchBar
rootResource="{rootResource}"
bind:searchFilter="{searchFilter}"
/>
</div>
<div class="treebox">
<ResourceTreeNode
rootResource="{rootResource}"
bind:searchFilter="{searchFilter}"
bind:resourceNodeDataMap="{resourceNodeDataMap}"
/>
</div>
</div>
</div>
Loading