Skip to content

Commit

Permalink
Filter, Sort upd
Browse files Browse the repository at this point in the history
  • Loading branch information
aceberg committed Jan 9, 2025
1 parent 82a15df commit 3ea3e33
Show file tree
Hide file tree
Showing 29 changed files with 267 additions and 226 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
- MobX store
- Goroutine for getting states
- Icons for items
- Filter and Sort update

## [0.1.1] - 2025-01-08
### Added
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

`Start/Stop/Restart/View Logs` for Docker, Systemd, SSH, VMs and anything else

![Screenshot](https://raw.githubusercontent.com/aceberg/AnyAppStart/refs/heads/main/assets/Screenshot_01.png)
![Screenshot](https://raw.githubusercontent.com/aceberg/AnyAppStart/refs/heads/main/assets/Screenshot_00.png)

## More screenshots
<details>
<summary>Expand</summary>

![Screenshot](https://raw.githubusercontent.com/aceberg/AnyAppStart/refs/heads/main/assets/Screenshot_04.png)
![Screenshot](https://raw.githubusercontent.com/aceberg/AnyAppStart/refs/heads/main/assets/Screenshot_03.png)
![Screenshot](https://raw.githubusercontent.com/aceberg/AnyAppStart/refs/heads/main/assets/Screenshot_02.png)
![Screenshot](https://raw.githubusercontent.com/aceberg/AnyAppStart/refs/heads/main/assets/Screenshot_03.png)
![Screenshot](https://raw.githubusercontent.com/aceberg/AnyAppStart/refs/heads/main/assets/Screenshot_04.png)

</details>

Binary file added assets/Screenshot_00.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/Screenshot_02.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/Screenshot_03.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/Screenshot_04.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion backend/internal/service/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func Exec(item models.Item, typesMap map[string]map[string]string) (bool, string

str = strings.Replace(str, "$ITEMNAME", item.Name, -1)

log.Println("String to exec:", str)
log.Println("EXEC:", str)
cmd := exec.Command("sh", "-c", str)

out, err := cmd.CombinedOutput()
Expand Down
7 changes: 3 additions & 4 deletions backend/internal/web/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func apiSaveConf(c *gin.Context) {
err := json.Unmarshal([]byte(str), &config)
check.IfError(err)

log.Println("CONF", config)
// log.Println("CONF", config)
appConfig.Host = config.Host
appConfig.Port = config.Port
appConfig.Theme = config.Theme
Expand Down Expand Up @@ -134,8 +134,8 @@ func apiSaveType(c *gin.Context) {

types := yaml.ReadTypes(appConfig.TypePath)

log.Println("OLD:", oldType)
log.Println("NEW:", newType)
// log.Println("OLD:", oldType)
// log.Println("NEW:", newType)

if oldType.Name == "" && newType.Name != "" { // If new type
types[newType.Name] = toOneType(newType)
Expand All @@ -152,7 +152,6 @@ func apiSaveType(c *gin.Context) {
}
}

log.Println("TYPES:", types)
yaml.WriteTypes(appConfig.TypePath, types)

c.IndentedJSON(http.StatusOK, true)
Expand Down
8 changes: 8 additions & 0 deletions backend/internal/web/functions.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package web

import (
// "log"
"sync"

"github.com/aceberg/AnyAppStart/internal/models"
Expand Down Expand Up @@ -42,18 +43,25 @@ func toOneType(tStruct models.TypeStruct) (tmpMap map[string]string) {

func getAllStates(items []models.Item) (newItems []models.Item) {
var wg sync.WaitGroup
var counter int

types := yaml.ReadTypes(appConfig.TypePath)
newItems = []models.Item{}

for _, item := range items {

counter++
wg.Add(1)
go func() {
defer wg.Done()
item = getOneState(item, types)
// log.Println("Getting state for Item", item.Name)
newItems = append(newItems, item)
counter--
}()
if counter > 3 {
wg.Wait()
}
}
wg.Wait()

Expand Down
2 changes: 1 addition & 1 deletion backend/internal/web/public/assets/index.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 30 additions & 20 deletions backend/internal/web/public/assets/index.js

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"bootstrap": "^5.3.3",
"mobx": "^6.13.5",
"mobx-react-lite": "^4.1.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
border-color: var(--bs-primary);
border-style: solid;
align-content: center;
padding-inline: 10%;
padding-inline: 1.2em;
white-space: nowrap;
/* margin-inline: 0.1px; */
height: 2.5em;
}
.btn-tab:hover {
background-color: #00000015;
Expand All @@ -26,4 +26,11 @@
.btn-tab-main {
border-bottom-color: #00000000;
border-bottom-width: thick;
}

/* GR-FILTER */
.gr-filter {
background-color: #00000000;
cursor: pointer;
border-style: hidden;
}
4 changes: 2 additions & 2 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import Header from './components/Header'
function App() {

return (
<>
<div className="container-lg mb-2">
<Header></Header>
<Body></Body>
</>
</div>
)
}

Expand Down
59 changes: 23 additions & 36 deletions frontend/src/components/Body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,40 @@ import ItemShow from "./ItemShow";
import { filterItems, getGroupsList, sortItems } from "../functions/sortitems";
import BodyTabs from "./BodyTabs";
import { Item } from "../functions/exports";
import { observer } from "mobx-react-lite";
import mobxStore from "../functions/store";
import BodyGroupFilter from "./BodyGroupFilter";

let sortField:keyof Item = "Exec";
let sortWay:boolean = true;
let filterField:keyof Item = "Exec";
let filterOption:string = "";

function Body() {
const Body: React.FC = observer(() => {

const [items, setItems] = useState<Item[]>([]);
const [grList, setGrList] = useState<string[]>([]);
const [updBody, setUpdBody] = useState<boolean>(false);
const [sortTrigger, setSortTrigger] = useState<boolean>(false);

const handleSort = (sortby:keyof Item) => {
const handleSort = (sortBy:keyof Item) => {
setSortTrigger(!sortTrigger);
if (sortby === sortField) {
sortWay = !sortWay;
localStorage.setItem('sort_way', JSON.stringify(sortWay));
if (sortBy === mobxStore.sortField) {
mobxStore.setSortWay(!mobxStore.sortWay);
}
setItems(sortItems(items, sortby, sortWay, sortTrigger));
sortField = sortby;
localStorage.setItem('sort_field', sortField);
setItems(sortItems(items, sortBy, mobxStore.sortWay, sortTrigger));
mobxStore.setSortField(sortBy);
}

const fetchData = async () => {
const str1 = localStorage.getItem('sort_field');
sortField = str1 as keyof Item;
const str = localStorage.getItem('sort_way');
sortWay = str === "true";
const str2 = localStorage.getItem('filter_field');
filterField = str2 as keyof Item;
const str3 = localStorage.getItem('filter_option');
filterOption = str3 as string;

let tmpItems:Item[] = await getItems();
setGrList(getGroupsList(tmpItems));
if (filterOption !== "") {
tmpItems = filterItems(tmpItems, filterField, filterOption);
}

setItems(sortItems(tmpItems, sortField, sortWay, sortTrigger));
tmpItems = filterItems(tmpItems, "Type", mobxStore.getFilterType());
tmpItems = filterItems(tmpItems, "Group", mobxStore.getFilterGroup());

setItems(sortItems(tmpItems, mobxStore.getSortField(), mobxStore.getSortWay(), sortTrigger));
};

useEffect(() => {
fetchData();
setUpdBody(false);
}, [updBody]);
mobxStore.setUpdBody(false);
// console.log("BODY UPD");
}, [mobxStore.updBody]);

useEffect(() => { // Regular update
setInterval(() => {
Expand All @@ -59,11 +46,11 @@ function Body() {
}, []);

return (
<>
<div className="container-lg mt-2">
<div className="row mt-2">
<div className="col-md">
<div className="card border-primary">
<div className="card-header">
<BodyTabs grList={grList} setUpdBody={setUpdBody}></BodyTabs>
<BodyTabs></BodyTabs>
</div>
<div className="card-body table-responsive">
<table className="table table-striped">
Expand All @@ -74,7 +61,7 @@ function Body() {
<th>Type<i onClick={() => handleSort("Type")} className="bi bi-sort-down-alt text-primary shade-hover"></i></th>
<th>Icon</th>
<th>Name<i onClick={() => handleSort("Name")} className="bi bi-sort-down-alt text-primary shade-hover"></i></th>
<th>Group<i onClick={() => handleSort("Group")} className="bi bi-sort-down-alt text-primary shade-hover"></i></th>
<th><BodyGroupFilter grList={grList}></BodyGroupFilter><i onClick={() => handleSort("Group")} className="bi bi-sort-down-alt text-primary shade-hover"></i></th>
<th>&nbsp;&nbsp;Action</th>
<th>Logs</th>
<th>Edit</th>
Expand All @@ -84,17 +71,17 @@ function Body() {
{items?.map((item, i) => (
<tr key={i}>
<td className="text-primary text-opacity-75">{i+1}.</td>
<ItemShow item={item} setUpdBody={setUpdBody}></ItemShow>
<ItemShow item={item}></ItemShow>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
</>
)
}
});

export default Body

25 changes: 25 additions & 0 deletions frontend/src/components/BodyGroupFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import mobxStore from "../functions/store";

function BodyGroupFilter(_props: any) {

const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
const selectedValue = event.target.value;

mobxStore.setFilterGroup(selectedValue);
mobxStore.setUpdBody(true);
}

return (
<>
<select className="gr-filter" defaultValue="Groups" onChange={handleChange}>
<option value="Groups" disabled>Groups</option>
<option value="" title="All Groups">...</option>
{_props.grList?.map((key: string) => (
<option key={key} value={key}>{key}</option>
))}
</select>
</>
)
}

export default BodyGroupFilter
Loading

0 comments on commit 3ea3e33

Please sign in to comment.