diff --git a/internal/apimodules/raffle/api.go b/internal/apimodules/raffle/api.go
index 2f4c07a..9f6a2a7 100644
--- a/internal/apimodules/raffle/api.go
+++ b/internal/apimodules/raffle/api.go
@@ -117,6 +117,25 @@ var apiRoutes = []plugins.HTTPRouteRegistrationArgs{
},
},
+ {
+ Description: "Resets the raffle (remove entries, reset status & start/close time) given by its ID",
+ HandlerFunc: handleWrap(func(w http.ResponseWriter, r *http.Request, ids map[string]uint64) (any, error) {
+ return nil, errors.Wrap(dbc.Reset(ids["id"]), "resetting raffle")
+ }, []string{"id"}),
+ Method: http.MethodPut,
+ Module: moduleName,
+ Name: "Reset Raffle",
+ Path: "/{id}/reset",
+ RequiresWriteAuth: true,
+ ResponseType: plugins.HTTPRouteResponseTypeNo200,
+ RouteParams: []plugins.HTTPRouteParamDocumentation{
+ {
+ Description: "ID of the raffle to reset",
+ Name: "id",
+ },
+ },
+ },
+
{
Description: "Duplicates the raffle given by its ID",
HandlerFunc: handleWrap(func(w http.ResponseWriter, r *http.Request, ids map[string]uint64) (any, error) {
diff --git a/internal/apimodules/raffle/database.go b/internal/apimodules/raffle/database.go
index ff717bc..48c0700 100644
--- a/internal/apimodules/raffle/database.go
+++ b/internal/apimodules/raffle/database.go
@@ -194,6 +194,7 @@ func (d *dbClient) Clone(raffleID uint64) error {
return errors.Wrap(err, "getting raffle")
}
+ raffle.AutoStartAt = nil
raffle.CloseAt = nil
raffle.Entries = nil
raffle.ID = 0
@@ -528,6 +529,33 @@ func (d *dbClient) Reopen(raffleID uint64, duration time.Duration) error {
return nil
}
+// Reset resets the raffle participants, the status, start / close
+// times while preserving the rest of the settings
+func (d *dbClient) Reset(raffleID uint64) error {
+ raffle, err := d.Get(raffleID)
+ if err != nil {
+ return errors.Wrap(err, "getting raffle")
+ }
+
+ raffle.AutoStartAt = nil
+ raffle.CloseAt = nil
+ raffle.Entries = nil
+ raffle.Status = raffleStatusPlanned
+
+ if err = helpers.RetryTransaction(d.db.DB(), func(tx *gorm.DB) error {
+ if err = tx.Delete(&raffleEntry{}, "raffle_id = ?", raffleID).Error; err != nil {
+ return errors.Wrap(err, "deleting raffle entries")
+ }
+
+ return tx.Save(raffle).Error
+ }); err != nil {
+ return errors.Wrap(err, "saving cleaned raffle")
+ }
+
+ frontendNotify(frontendNotifyEventRaffleChange)
+ return nil
+}
+
// Start fetches the given raffle, updates its CloseAt attribute
// in case it is not already set, sets the raffle to active, updates
// the raffle in the database and notes its channel/keyword combo
diff --git a/src/raffle.vue b/src/raffle.vue
index 2c4c27f..f07104e 100644
--- a/src/raffle.vue
+++ b/src/raffle.vue
@@ -79,6 +79,18 @@
/>
+
+
+
+
this.$root.toastError('Could not re-pick winner!'))
},
+ resetRaffle(id) {
+ this.$bvModal.msgBoxConfirm('Do you really want to reset this raffle?', {
+ buttonSize: 'sm',
+ cancelTitle: 'NO',
+ centered: true,
+ okTitle: 'YES',
+ okVariant: 'danger',
+ size: 'sm',
+ title: 'Please Confirm',
+ })
+ .then(val => {
+ if (!val) {
+ return
+ }
+
+ return axios.put(`raffle/${id}/reset`, {}, this.$root.axiosOptions)
+ .then(() => this.$root.toastSuccess('Raffle reset'))
+ .catch(err => this.$bus.$emit(constants.NOTIFY_FETCH_ERROR, err))
+ })
+ },
+
saveRaffle() {
if (this.models.raffle.id) {
return axios.put(`raffle/${this.models.raffle.id}`, this.transformRaffleToDB(this.models.raffle), this.$root.axiosOptions)