diff --git a/frontend/locales/en.ts b/frontend/locales/en.ts
index 77b600116..c9fbb3555 100644
--- a/frontend/locales/en.ts
+++ b/frontend/locales/en.ts
@@ -353,6 +353,7 @@ const msgs: LocaleMessageObject = {
duplicateColor: 'This project already has a channel with this color',
duplicateName: 'This project already has a channel with this name',
tooLongName: 'Channel name is too long',
+ cannotDelete: 'You cannot delete this channel',
},
},
manage: {
diff --git a/frontend/pages/_author/_slug/channels.vue b/frontend/pages/_author/_slug/channels.vue
index 28dccc520..67376705d 100644
--- a/frontend/pages/_author/_slug/channels.vue
+++ b/frontend/pages/_author/_slug/channels.vue
@@ -11,7 +11,7 @@
mdi-format-list-numbered{{ $t('channel.manage.versionCount') }} |
mdi-file-find{{ $t('channel.manage.reviewed') }} |
mdi-pencil{{ $t('channel.manage.edit') }} |
- mdi-delete{{ $t('channel.manage.trash') }} |
+ mdi-delete{{ $t('channel.manage.trash') }} |
@@ -31,9 +31,10 @@
-
-
- {{ $t('channel.manage.deleteButton') }}
+ |
+
+ {{ $t('channel.manage.deleteButton') }}
+
|
@@ -80,10 +81,9 @@ export default class ProjectChannelsPage extends HangarProjectMixin {
editChannel(channel: ProjectChannel) {
if (!channel.id) return;
- const id = channel.id;
this.$api
.requestInternal(`channels/${this.project.id}/edit`, true, 'post', {
- id,
+ id: channel.id,
name: channel.name,
color: channel.color,
nonReviewed: channel.nonReviewed,
@@ -94,9 +94,14 @@ export default class ProjectChannelsPage extends HangarProjectMixin {
.catch(this.$util.handleRequestError);
}
- // TODO deleteChannel
- deleteChannel(name: String) {
- console.log('delete channel ', name);
+ deleteChannel(channel: ProjectChannel) {
+ if (!channel.id) return;
+ this.$api
+ .requestInternal(`channels/${this.project.id}/delete/${channel.id}`, true, 'post')
+ .then(() => {
+ this.$nuxt.refresh();
+ })
+ .catch(this.$util.handleRequestError);
}
addChannel(channel: ProjectChannel) {
diff --git a/src/main/java/io/papermc/hangar/controller/internal/ChannelController.java b/src/main/java/io/papermc/hangar/controller/internal/ChannelController.java
index 2351f61d4..20ce5da24 100644
--- a/src/main/java/io/papermc/hangar/controller/internal/ChannelController.java
+++ b/src/main/java/io/papermc/hangar/controller/internal/ChannelController.java
@@ -51,7 +51,7 @@ public class ChannelController extends HangarController {
}
@Unlocked
- @ResponseStatus(HttpStatus.OK)
+ @ResponseStatus(HttpStatus.CREATED)
@PermissionRequired(type = PermissionType.PROJECT, perms = NamedPermission.EDIT_TAGS, args = "{#projectId}")
@PostMapping(path = "/{projectId}/create", consumes = MediaType.APPLICATION_JSON_VALUE)
public void createChannel(@PathVariable long projectId, @Valid @RequestBody ChannelForm channelForm) {
@@ -65,4 +65,12 @@ public class ChannelController extends HangarController {
public void editChannel(@PathVariable long projectId, @Valid @RequestBody EditChannelForm channelForm) {
channelService.editProjectChannel(channelForm.getId(), channelForm.getName(), channelForm.getColor(), projectId, channelForm.isNonReviewed());
}
+
+ @Unlocked
+ @ResponseStatus(HttpStatus.OK)
+ @PermissionRequired(type = PermissionType.PROJECT,perms = NamedPermission.EDIT_TAGS, args = "{#projectId}")
+ @PostMapping("/{projectId}/delete/{channelId}")
+ public void deleteChannel(@PathVariable long projectId, @PathVariable long channelId) {
+ channelService.deleteProjectChannel(projectId, channelId);
+ }
}
diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectsDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectsDAO.java
index a2971aa0e..a9de22d45 100644
--- a/src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectsDAO.java
+++ b/src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectsDAO.java
@@ -100,6 +100,13 @@ public interface HangarProjectsDAO {
" WHERE lower(p.owner_name) = lower(:author) AND lower(p.slug) = lower(:slug)")
List getHangarProjectFlags(String author, String slug);
+ @RegisterConstructorMapper(HangarChannel.class)
+ @SqlQuery("SELECT pc.*," +
+ " (SELECT count(*) FROM project_versions pv WHERE pv.channel_id = pc.id) as version_count" +
+ " FROM project_channels pc" +
+ " WHERE pc.id = :channelId")
+ HangarChannel getHangarChannel(long channelId);
+
@RegisterConstructorMapper(HangarChannel.class)
@SqlQuery("SELECT pc.*," +
" (SELECT count(*) FROM project_versions pv WHERE pv.channel_id = pc.id) as version_count" +
diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectChannelsDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectChannelsDAO.java
index fd1c456cd..67053ab89 100644
--- a/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectChannelsDAO.java
+++ b/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectChannelsDAO.java
@@ -25,6 +25,9 @@ public interface ProjectChannelsDAO {
@SqlUpdate("UPDATE project_channels SET name = :name, color = :color, non_reviewed = :nonReviewed WHERE id = :id")
void update(@BindBean ProjectChannelTable projectChannelTable);
+ @SqlUpdate("DELETE FROM project_channels WHERE id = :id")
+ void delete(@BindBean ProjectChannelTable projectChannelTable);
+
@SqlQuery("SELECT * FROM project_channels WHERE project_id = :projectId")
List getProjectChannels(long projectId);
diff --git a/src/main/java/io/papermc/hangar/service/internal/projects/ChannelService.java b/src/main/java/io/papermc/hangar/service/internal/projects/ChannelService.java
index 6b122b3e0..db8eedf5c 100644
--- a/src/main/java/io/papermc/hangar/service/internal/projects/ChannelService.java
+++ b/src/main/java/io/papermc/hangar/service/internal/projects/ChannelService.java
@@ -35,16 +35,17 @@ public class ChannelService extends HangarService {
}
if (existingChannels.stream().anyMatch(ch -> ch.getColor() == color)) {
- throw new HangarApiException(HttpStatus.BAD_REQUEST, "channel.modal.error.duplicateColor");
+ throw new HangarApiException(HttpStatus.CONFLICT, "channel.modal.error.duplicateColor");
}
if (existingChannels.stream().anyMatch(ch -> ch.getName().equalsIgnoreCase(name))) {
- throw new HangarApiException(HttpStatus.BAD_REQUEST, "channel.modal.error.duplicateName");
+ throw new HangarApiException(HttpStatus.CONFLICT, "channel.modal.error.duplicateName");
}
}
public ProjectChannelTable createProjectChannel(String name, Color color, long projectId, boolean nonReviewed) {
validateChannel(name, color, projectId, nonReviewed, projectChannelsDAO.getProjectChannels(projectId));
+ // TODO user action logging
return projectChannelsDAO.insert(new ProjectChannelTable(name, color, projectId, nonReviewed));
}
@@ -58,6 +59,20 @@ public class ChannelService extends HangarService {
projectChannelTable.setColor(color);
projectChannelTable.setNonReviewed(nonReviewed);
projectChannelsDAO.update(projectChannelTable);
+ // TODO user action logging
+ }
+
+ public void deleteProjectChannel(long projectId, long channelId) {
+ HangarChannel hangarChannel = hangarProjectsDAO.getHangarChannel(channelId);
+ if (hangarChannel == null) {
+ throw new HangarApiException(HttpStatus.NOT_FOUND);
+ }
+ if (hangarChannel.getVersionCount() != 0 || getProjectChannels(projectId).size() == 1) {
+ // Cannot delete channels with versions or if its the last channel
+ throw new HangarApiException(HttpStatus.BAD_REQUEST, "channel.modal.error.cannotDelete");
+ }
+ projectChannelsDAO.delete(hangarChannel);
+ // TODO user action logging
}
public List getProjectChannels(long projectId) {