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

Added preset renaming #148

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import cz.forgottenempire.servermanager.modpreset.dtos.PresetListResponseDto;
import cz.forgottenempire.servermanager.modpreset.dtos.PresetResponseDto;
import cz.forgottenempire.servermanager.modpreset.dtos.UpdatePresetRequestDto;
import cz.forgottenempire.servermanager.modpreset.dtos.RenamePresetRequestDto;
import cz.forgottenempire.servermanager.workshop.WorkshopMod;
import cz.forgottenempire.servermanager.workshop.WorkshopModsService;
import java.util.Collection;
Expand Down Expand Up @@ -89,6 +90,24 @@ public ResponseEntity<PresetResponseDto> updatePreset(
return ResponseEntity.ok(modPresetMapper.mapToModPresetDto(modPreset));
}

@PutMapping("/rename/{id}")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe PATCH would be more accurate as just a one attribute is being changed. PUT would be appropriate when the whole preset would be replaced, including the mods.

I'd go for either of these solutions:

  1. Change this endpoint to @PatchMapping("/rename/{id}")
  2. Reuse the existing endpoint @PutMapping("/{id}") and also send the mods in the body when renaming the preset.

I'd personally prefer option 2), but I'm fine with either one.

public ResponseEntity<PresetResponseDto> renamePreset(
@PathVariable Long id,
@Valid @RequestBody RenamePresetRequestDto requestDto
) {
ModPreset modPreset = modPresetsService.getModPreset(id)
.orElseThrow(() -> new NotFoundException("Mod preset " + id + " not found"));

if (!modPreset.getName().equals(requestDto.getName())) {
validatePresetName(requestDto.getName());
}

modPreset.setName(requestDto.getName());
modPreset = modPresetsService.updatePreset(modPreset);
return ResponseEntity.ok(modPresetMapper.mapToModPresetDto(modPreset));
}


@DeleteMapping("/{id}")
public ResponseEntity<?> deletePreset(@PathVariable Long id) {
modPresetsService.deletePreset(id);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cz.forgottenempire.servermanager.modpreset.dtos;

import jakarta.validation.constraints.NotEmpty;
import lombok.Data;

import java.util.List;

@Data
public class RenamePresetRequestDto {

@NotEmpty
private String name;
}
41 changes: 39 additions & 2 deletions frontend/src/components/mods/PresetsManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {Backdrop, Box, CircularProgress, Divider, Modal, Stack, Toolbar} from "@
import Typography from "@mui/material/Typography";
import IconButton from '@mui/material/IconButton';
import DeleteIcon from '@mui/icons-material/Delete';
import EditIcon from '@mui/icons-material/Edit';
import SERVER_NAMES from "../../util/serverNames";
import {toast} from "material-react-toastify";
import ListBuilder from "../../UI/ListBuilder/ListBuilder";
Expand All @@ -29,6 +28,10 @@ import DownloadIcon from '@mui/icons-material/Download';
import {ModPresetDto, ModPresetModDto} from "../../dtos/ModPresetDto";
import {ModDto} from "../../dtos/ModDto.ts";
import {ServerType} from "../../dtos/ServerDto.ts";
import DriveFileRenameOutlineOutlinedIcon from '@mui/icons-material/DriveFileRenameOutlineOutlined';
import RenamePresetDialog from "./RenamePresetDialog";
import MemoryIcon from "@mui/icons-material/Memory";
import {renameModPreset} from "../../services/modPresetsService";

export default function PresetsManagement() {
const [initialLoading, setInitialLoading] = useState(true);
Expand All @@ -38,6 +41,8 @@ export default function PresetsManagement() {
const [selectedMods, setSelectedMods] = useState<Array<ModPresetModDto>>([]);
const [availableMods, setAvailableMods] = useState<Array<ModPresetModDto>>([]);
const [isUploadInProgress, setIsUploadInProgress] = useState(false);
const [renamePresetDialogOpen, setRenamePresetDialogOpen] = useState(false);
const [selectedPresetId, setSelectedPresetId] = useState<string | null>(null);

useEffect(() => {
async function fetchPresets() {
Expand Down Expand Up @@ -177,6 +182,29 @@ export default function PresetsManagement() {
}
}

const handlePresedDialogOpen = (presetId: string) => {
setSelectedPresetId(presetId);
setRenamePresetDialogOpen(true);
}

const handlePresedDialogClose = () => {
setRenamePresetDialogOpen(false);
setSelectedPresetId(null);
}

const handleRenameNewPreset = async (presetName: string, presetId: string) => {
setRenamePresetDialogOpen(false);
setSelectedPresetId(null);

const request = {
name: presetName,
}

await renameModPreset(presetId, request);
toast.success(`Preset '${presetName}' successfully renamed`);
window.location.reload();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using window.location.reload() is not ideal to re-render the changes. Instead, you should modify the state of the component, in this case the presets state.

Something like this should work:

const newPresets = [...presets]; // create a copy of the original state
const renamedPreset = newPresets.find(preset => preset.id === presetId); // find the renamed preset by ID
renamedPreset.name = presetName; // edit the preset name
setPresets(newPresets); // set the new state with renamed preset

This should automatically re-render the component with the new state.

}

return (
<>
<Backdrop open={isUploadInProgress}>
Expand Down Expand Up @@ -233,7 +261,13 @@ export default function PresetsManagement() {
<TableCell>
<IconButton aria-label="edit"
onClick={() => handleOpenEdit(preset)}>
<EditIcon color="primary"/>
<MemoryIcon color="primary"/>
</IconButton>
</TableCell>
<TableCell>
<IconButton aria-label="rename"
onClick={() => handlePresedDialogOpen(preset.id as string)}>
<DriveFileRenameOutlineOutlinedIcon color="primary"/>
</IconButton>
</TableCell>
<TableCell>
Expand Down Expand Up @@ -264,6 +298,9 @@ export default function PresetsManagement() {
/>
</Box>
</Modal>
<RenamePresetDialog open={renamePresetDialogOpen} onClose={handlePresedDialogClose}
onConfirmClicked={handleRenameNewPreset} presetId={selectedPresetId}
/>
</>
)
}
53 changes: 53 additions & 0 deletions frontend/src/components/mods/RenamePresetDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {ChangeEvent, useState} from "react";
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';

type RenamePresetDialogProps = {
open: boolean,
onConfirmClicked: (name: string, id: string) => void,
onClose: () => void,
presetId: string | null
}

const RenamePresetDialog = (props: RenamePresetDialogProps) => {
const [presetName, setPresetName] = useState("");

const handlePresetNameChange = (e: ChangeEvent<HTMLInputElement>) => {
setPresetName(e.target.value);
}

const handleConfirmClicked = () => {
if (props.presetId) { // Ensure the ID is available
props.onConfirmClicked(presetName, props.presetId);
setPresetName(""); // Reset the input field
FyWolf marked this conversation as resolved.
Show resolved Hide resolved
}
};

return (
<Dialog open={props.open} onClose={props.onClose} fullWidth maxWidth="xs">
<DialogTitle>Rename preset</DialogTitle>
<DialogContent>
<TextField
autoFocus
margin="dense"
id="name"
label="Preset name"
fullWidth
variant="standard"
value={presetName}
onChange={handlePresetNameChange}
/>
</DialogContent>
<DialogActions>
<Button onClick={props.onClose}>Cancel</Button>
<Button onClick={handleConfirmClicked}>Confirm</Button>
</DialogActions>
</Dialog>
);
};

export default RenamePresetDialog;
4 changes: 4 additions & 0 deletions frontend/src/dtos/ModPresetDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ export interface ModPresetModDto {
id: number,
name: string,
shortName: string
}

export interface ModPresetRenameDto {
name: string
}
6 changes: 5 additions & 1 deletion frontend/src/services/modPresetsService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import http from "./httpService";
import config from "../config";
import {ModPresetRequestDto} from "../dtos/ModPresetDto.ts";
import {ModPresetRequestDto, ModPresetRenameDto} from "../dtos/ModPresetDto.ts";

const apiEndpoint = config.apiUrl + "/mod/preset";

Expand All @@ -25,6 +25,10 @@ export function updateModPreset(id: string, preset: ModPresetRequestDto) {
return http.put(apiEndpoint + "/" + id, preset);
}

export function renameModPreset(id: string, preset: ModPresetRenameDto) {
return http.put(apiEndpoint + "/rename/" + id, preset);
}

export function deleteModPreset(id: string) {
return http.delete(apiEndpoint + "/" + id);
}
Expand Down