ronantakizawa/codereview-bench huggingface dataset:
Repository: louislam/uptime-kuma
File: server/notification-providers/send-grid.js (JavaScript)

Code before:
        },
      };

      let personalizations = {
        to: [{ email: notification.sendgridToEmail }],
      };

      // Add CC recipients if provided
      if (notification.sendgridCcEmail) {
        personalizations.cc = notification.sendgridCcEmail
          .split(",")
          .map((email) => ({ email: email.trim() }));
      }

      // Add BCC recipients if provided
      if (notification.sendgridBccEmail) {
        personalizations.bcc = notification.sendgridBccEmail
          .split(",")
          .map((email) => ({ email: email.trim() }));
      }

      let data = {
        personalizations: [personalizations],
        from: { email: notification.sendgridFromEmail },
        subject:
          notification.sendgridSubject ||
          "Notification from Your Uptime Kuma",
        content: [
          {
            type: "text/plain",
            value: msg,
          },
        ],
      };

      await axios.post(
        "https://api.sendgrid.com/v3/mail/send",
        data,
        config
      );
      return okMsg;
    } catch (error) {
      this.throwGeneralAxiosError(error);
    }
  }
}

module.exports = SendGrid;


Review comment (suggestion):
Please make the default more clear to our users by setting it like this instead.

(Read: leave this code, but also add a default in the frontend)

Here is an example how you do this:
https://github.com/louislam/uptime-kuma/blob/85dfe1f5d17dad5e035eb3620b8f516b2bcf79cd/src/components/notifications/TechulusPush.vue#L66-L69

Code after:
                },
            };

            let personalizations = {
                to: [{ email: notification.sendgridToEmail }],
            };

            // Add CC recipients if provided
            if (notification.sendgridCcEmail) {
                personalizations.cc = notification.sendgridCcEmail
                    .split(",")
                    .map((email) => ({ email: email.trim() }));
            }

            // Add BCC recipients if provided
            if (notification.sendgridBccEmail) {
                personalizations.bcc = notification.sendgridBccEmail
                    .split(",")
                    .map((email) => ({ email: email.trim() }));
            }

            let data = {
                personalizations: [ personalizations ],
                from: { email: notification.sendgridFromEmail.trim() },
                subject:
          notification.sendgridSubject ||
          "Notification from Your Uptime Kuma",
                content: [
                    {
                        type: "text/plain",
                        value: msg,
                    },
                ],
            };

            await axios.post(
                "https://api.sendgrid.com/v3/mail/send",
                data,
                config
            );
            return okMsg;
        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
}

module.exports = SendGrid;
Repository: louislam/uptime-kuma
File: src/components/notifications/SendGrid.vue (Vue)

Code before:
    </div>
    <div class="mb-3">
        <label for="sendgrid-bcc-email" class="form-label">{{ $t("smtpBCC") }}</label>
        <input id="sendgrid-bcc-email" v-model="$parent.notification.sendgridBccEmail" type="email" class="form-control">
        <small class="form-text text-muted">{{ $t("Separate multiple email addresses with commas") }}</small>
    </div>
    <div class="mb-3">
        <label for="sendgrid-subject" class="form-label">{{ $t("Subject:") }}</label>
        <input id="sendgrid-subject" v-model="$parent.notification.sendgridSubject" type="text" class="form-control">
        <small class="form-text text-muted">{{ $t("leave blank for default subject") }}</small>
    </div>
    <i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
        <a href="https://docs.sendgrid.com/api-reference/mail-send/mail-send" target="_blank">https://docs.sendgrid.com/api-reference/mail-send/mail-send</a>
    </i18n-t>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,
    },
    mounted() {
        if (typeof this.$parent.notification.sendgridSubject === "undefined") {
            this.$parent.notification.sendgridSubject = "Uptime-Kuma";
        }
    },
};
</script>


Review comment (suggestion):
The backend has the following as a default. We schould only have one default. Which one is better?

```suggestion
            this.$parent.notification.sendgridSubject = "Notification from Your Uptime Kuma";
```

Code after:
    </div>
    <div class="mb-3">
        <label for="sendgrid-bcc-email" class="form-label">{{ $t("smtpBCC") }}</label>
        <input id="sendgrid-bcc-email" v-model="$parent.notification.sendgridBccEmail" type="email" class="form-control">
        <small class="form-text text-muted">{{ $t("Separate multiple email addresses with commas") }}</small>
    </div>
    <div class="mb-3">
        <label for="sendgrid-subject" class="form-label">{{ $t("Subject:") }}</label>
        <input id="sendgrid-subject" v-model="$parent.notification.sendgridSubject" type="text" class="form-control">
        <small class="form-text text-muted">{{ $t("leave blank for default subject") }}</small>
    </div>
    <i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
        <a href="https://docs.sendgrid.com/api-reference/mail-send/mail-send" target="_blank">https://docs.sendgrid.com/api-reference/mail-send/mail-send</a>
    </i18n-t>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,
    },
    mounted() {
        if (typeof this.$parent.notification.sendgridSubject === "undefined") {
            this.$parent.notification.sendgridSubject = "Notification from Your Uptime Kuma";
        }
    },
};
</script>
Repository: louislam/uptime-kuma
File: src/components/HeartbeatBar.vue (Vue)

Code before:

.wrap {
    overflow: hidden;
    width: 100%;
    white-space: nowrap;
}

.hp-bar-big {
    .beat-hover-area {
        display: inline-block;

        &:not(.empty):hover {
            transition: all ease-in-out 0.15s;
            opacity: 0.8;
            transform: scale(var(--hover-scale));
        }

        .beat {
            background-color: $primary;
            border-radius: $border-radius;
            pointer-events: none;

            &.empty {
                background-color: aliceblue;
            }

            &.down {
                background-color: $danger;
            }

            &.pending {
                background-color: $warning;
            }

            &.maintenance {
                background-color: $maintenance;
            }
        }
    }
}

.dark {
    .hp-bar-big .beat.empty {
        background-color: #848484;
    }
}

.word {
    color: $secondary-text;
    font-size: 12px;
}

Review comment (suggestion):
Added `pointer-events: none` beecause the tooltip momentarily disappears when crossing between the beat-hover-area and the beat.

Code after:

.wrap {
    overflow: hidden;
    width: 100%;
    white-space: nowrap;
}

.hp-bar-big {
    .beat-hover-area {
        display: inline-block;

        &:not(.empty):hover {
            transition: all ease-in-out 0.15s;
            opacity: 0.8;
            transform: scale(var(--hover-scale));
        }

        .beat {
            background-color: $primary;
            border-radius: $border-radius;

            /*
            pointer-events needs to be changed because
            tooltip momentarily disappears when crossing between .beat-hover-area and .beat
            */
            pointer-events: none;

            &.empty {
                background-color: aliceblue;
            }

            &.down {
                background-color: $danger;
            }

            &.pending {
                background-color: $warning;
            }

            &.maintenance {
                background-color: $maintenance;
            }
        }
    }
}

.dark {
    .hp-bar-big .beat.empty {
        background-color: #848484;
    }
}
Repository: louislam/uptime-kuma
File: src/components/HeartbeatBar.vue (Vue)

Code before:
};
</script>

<style lang="scss" scoped>
@import "../assets/vars.scss";

.wrap {
    overflow: hidden;
    width: 100%;
    white-space: nowrap;
}

.hp-bar-big {
    .beat-hover-area {
        display: inline-block;

        &:not(.empty):hover {
            transition: all ease-in-out 0.15s;
            opacity: 0.8;
            transform: scale(var(--hover-scale));
        }

        .beat {
            background-color: $primary;
            border-radius: $border-radius;
            /* Added because the tooltip momentarily disappears when crossing between the beat-hover-area and the beat */
            pointer-events: none;

            &.empty {
                background-color: aliceblue;
            }

            &.down {
                background-color: $danger;
            }

            &.pending {
                background-color: $warning;
            }

            &.maintenance {
                background-color: $maintenance;
            }
        }
    }
}

.dark {
    .hp-bar-big .beat.empty {
        background-color: #848484;
    }

Review comment (suggestion):
my comment introduced a linting issue

```suggestion

                        /*
                        pointer-events needs to be changed because
                        tooltip momentarily disappears when crossing between .beat-hover-area and .beat
                        */
```

Code after:
};
</script>

<style lang="scss" scoped>
@import "../assets/vars.scss";

.wrap {
    overflow: hidden;
    width: 100%;
    white-space: nowrap;
}

.hp-bar-big {
    .beat-hover-area {
        display: inline-block;

        &:not(.empty):hover {
            transition: all ease-in-out 0.15s;
            opacity: 0.8;
            transform: scale(var(--hover-scale));
        }

        .beat {
            background-color: $primary;
            border-radius: $border-radius;

            /*
            pointer-events needs to be changed because
            tooltip momentarily disappears when crossing between .beat-hover-area and .beat
            */
            pointer-events: none;

            &.empty {
                background-color: aliceblue;
            }

            &.down {
                background-color: $danger;
            }

            &.pending {
                background-color: $warning;
            }

            &.maintenance {
                background-color: $maintenance;
            }
        }
    }
}
Repository: louislam/uptime-kuma
File: src/components/HeartbeatBar.vue (Vue)

Code before:
@import "../assets/vars.scss";

.wrap {
    overflow: hidden;
    width: 100%;
    white-space: nowrap;
}

.hp-bar-big {
    .beat-hover-area {
        display: inline-block;

        &:not(.empty):hover {
            transition: all ease-in-out 0.15s;
            opacity: 0.8;
            transform: scale(var(--hover-scale));
        }

        .beat {
            background-color: $primary;
            border-radius: $border-radius;

                        /*
                        pointer-events needs to be changed because
                        tooltip momentarily disappears when crossing between .beat-hover-area and .beat
                        */
            pointer-events: none;

            &.empty {
                background-color: aliceblue;
            }

            &.down {
                background-color: $danger;
            }

            &.pending {
                background-color: $warning;
            }

            &.maintenance {
                background-color: $maintenance;
            }
        }
    }
}

.dark {
    .hp-bar-big .beat.empty {
        background-color: #848484;
    }

Review comment (suggestion):
fixed more linting

```suggestion
            /*
            pointer-events needs to be changed because
            tooltip momentarily disappears when crossing between .beat-hover-area and .beat
            */
```

Code after:
@import "../assets/vars.scss";

.wrap {
    overflow: hidden;
    width: 100%;
    white-space: nowrap;
}

.hp-bar-big {
    .beat-hover-area {
        display: inline-block;

        &:not(.empty):hover {
            transition: all ease-in-out 0.15s;
            opacity: 0.8;
            transform: scale(var(--hover-scale));
        }

        .beat {
            background-color: $primary;
            border-radius: $border-radius;

            /*
            pointer-events needs to be changed because
            tooltip momentarily disappears when crossing between .beat-hover-area and .beat
            */
            pointer-events: none;

            &.empty {
                background-color: aliceblue;
            }

            &.down {
                background-color: $danger;
            }

            &.pending {
                background-color: $warning;
            }

            &.maintenance {
                background-color: $maintenance;
            }
        }
    }
}

.dark {
    .hp-bar-big .beat.empty {
        background-color: #848484;
    }
Repository: louislam/uptime-kuma
File: src/pages/List.vue (Vue)

Code before:
<template>
    <transition name="slide-fade" appear>
        <MonitorList :scrollbar="true" />
    </transition>
</template>

<script>
import MonitorList from "../components/MonitorList.vue";

export default {
    components: {
        MonitorList,
    },
    watch: {
        "$root.isMobile"(newVal) {
            if (!newVal && this.$route.path === "/list") {
                this.$router.push("/dashboard");
            }
        }
    },
    mounted() {
        if (!this.$root.isMobile && this.$route.path === "/list") {
            this.$router.push("/dashboard");
        }
    },

};
</script>

<style lang="scss" scoped>
@import "../assets/vars";

.shadow-box {
    padding: 20px;
}

</style>


Review comment (suggestion):
I suggest you tu use `replace` instead of `push`. You'll avoid having the `/list` and the `/dashboard` in the browser history (you'll instead only have `/dashboard`).

`this.$router.replace({ path: "/new_path" })`

Doc: https://router.vuejs.org/guide/essentials/navigation.html#Replace-current-location

Code after:
<template>
    <transition name="slide-fade" appear>
        <MonitorList :scrollbar="true" />
    </transition>
</template>

<script>
import MonitorList from "../components/MonitorList.vue";

export default {
    components: {
        MonitorList,
    },
    watch: {
        "$root.isMobile"(newVal) {
            if (!newVal && this.$route.path === "/list") {
                this.$router.replace({ path: "/dashboard" });
            }
        },
    },
    mounted() {
        if (!this.$root.isMobile && this.$route.path === "/list") {
            this.$router.replace({ path: "/dashboard" });
        }
    },
};
</script>

<style lang="scss" scoped>
@import "../assets/vars";

.shadow-box {
    padding: 20px;
}
</style>
Repository: louislam/uptime-kuma
File: server/monitor-types/sip-options.js (JavaScript)

Code before:
const { MonitorType } = require("./monitor-type");
const { UP } = require("../../src/util");
const { exec } = require("promisify-child-process");

class SIPMonitorType extends MonitorType {
    name = "sip-options";
    supportsConditions = false;

    /**
     * Run the monitoring check on the given monitor
     * @param {Monitor} monitor Monitor to check
     * @param {Heartbeat} heartbeat Monitor heartbeat to update
     * @param {UptimeKumaServer} _server Uptime Kuma server
     * @returns {Promise<void>}
     * @throws Will throw an error if the command execution encounters any error.
     */
    async check(monitor, heartbeat, _server) {
        try {
            let sipsakOutput = await this.runSipSak(monitor.hostname, monitor.port, 3000);
            this.parseSipsakResponse(sipsakOutput, heartbeat);
        } catch (err) {
            throw new Error(`Error checking Sipsak: ${err} ${err.message} ${err.stack}`);
        }
    }

    /**
     * Runs Sipsak options ping
     * @param {string} hostname SIP server address to send options.

Review comment (suggestion):
```suggestion
const { execFile } = require("promisify-child-process");
```

Code after:
const { MonitorType } = require("./monitor-type");
const { UP } = require("../../src/util");
const { execFile } = require("promisify-child-process");

class SIPMonitorType extends MonitorType {
    name = "sip-options";
    supportsConditions = false;

    /**
     * Run the monitoring check on the given monitor
     * @param {Monitor} monitor Monitor to check
     * @param {Heartbeat} heartbeat Monitor heartbeat to update
     * @param {UptimeKumaServer} _server Uptime Kuma server
     * @returns {Promise<void>}
     * @throws Will throw an error if the command execution encounters any error.
     */
    async check(monitor, heartbeat, _server) {
        let sipsakOutput = await this.runSipSak(monitor.hostname, monitor.port, 3000);
        this.parseSipsakResponse(sipsakOutput, heartbeat);
    }

    /**
     * Runs Sipsak options ping
     * @param {string} hostname SIP server address to send options.
     * @param {number} port SIP server port
     * @param {number} timeout timeout of options reply
     * @returns {Promise<string>} A Promise that resolves to the output of the Sipsak options ping
     * @throws Will throw an error if the command execution encounters any error.
Repository: louislam/uptime-kuma
File: server/database.js (JavaScript)

Code before:
            log.info("db", "Aggregate Table Migration Completed");
        } else {
            log.info("db", "No data to migrate");
        }
    }

    /**
     * Remove all non-important heartbeats from heartbeat table, keep last 24-hour or {KEEP_LAST_ROWS} rows for each monitor
     * @param {boolean} detailedLog Log detailed information
     * @returns {Promise<void>}
     */
    static async clearHeartbeatData(detailedLog = false) {
        let monitors = await R.getAll("SELECT id FROM monitor");
        const sqlHourOffset = Database.sqlHourOffset();

        for (let monitor of monitors) {
            if (detailedLog) {
                log.info("db", "Deleting non-important heartbeats for monitor " + monitor.id);
            }
            await R.exec(`
                DELETE FROM heartbeat
                WHERE monitor_id = ?
                AND important = 0
                AND time < ${sqlHourOffset}
                AND id NOT IN (
                    SELECT id FROM (
                        SELECT id
                        FROM heartbeat
                        WHERE monitor_id = ?
                        ORDER BY time DESC
                        LIMIT ?
                    )  AS limited_ids
                )
            `, [
                monitor.id,
                -24,
                monitor.id,
                100,
            ]);
        }
    }

}

module.exports = Database;


Review comment (suggestion):
Let's document why this is done this way too

```suggestion
                    SELECT id FROM ( -- written this way for Maria's support
```


Code after:
            log.info("db", "Aggregate Table Migration Completed");
        } else {
            log.info("db", "No data to migrate");
        }
    }

    /**
     * Remove all non-important heartbeats from heartbeat table, keep last 24-hour or {KEEP_LAST_ROWS} rows for each monitor
     * @param {boolean} detailedLog Log detailed information
     * @returns {Promise<void>}
     */
    static async clearHeartbeatData(detailedLog = false) {
        let monitors = await R.getAll("SELECT id FROM monitor");
        const sqlHourOffset = Database.sqlHourOffset();

        for (let monitor of monitors) {
            if (detailedLog) {
                log.info("db", "Deleting non-important heartbeats for monitor " + monitor.id);
            }
            await R.exec(`
                DELETE FROM heartbeat
                WHERE monitor_id = ?
                AND important = 0
                AND time < ${sqlHourOffset}
                AND id NOT IN (
                    SELECT id FROM ( -- written this way for Maria's support
                        SELECT id
                        FROM heartbeat
                        WHERE monitor_id = ?
                        ORDER BY time DESC
                        LIMIT ?
                    )  AS limited_ids
                )
            `, [
                monitor.id,
                -24,
                monitor.id,
                100,
            ]);
        }
    }

}

module.exports = Database;
Repository: louislam/uptime-kuma
File: server/notification-providers/pushover.js (JavaScript)

Code before:
            "expire": "3600",
            "html": 1,
        };

        const baseURL = await setting("primaryBaseURL");
        if (baseURL && monitorJSON) {
            data["url"] = baseURL + getMonitorRelativeURL(monitorJSON.id);
            data["url_title"] = "Link to Monitor";
        }

        if (notification.pushoverdevice) {
            data.device = notification.pushoverdevice;
        }
        if (notification.pushoverttl) {
            data.ttl = notification.pushoverttl;
        }

        try {
            if (heartbeatJSON == null) {
                await axios.post(url, data);
                return okMsg;
            }

            if (heartbeatJSON.status === UP) {
                data.sound = notification.pushoversounds_up;
            }

            data.message += `\n<b>Time (${heartbeatJSON["timezone"]})</b>: ${heartbeatJSON["localDateTime"]}`;
            await axios.post(url, data);
            return okMsg;

        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
}

module.exports = Pushover;


Review comment (suggestion):
```suggestion
                // default = DOWN => DOWN-sound is also played for non-UP/DOWN notiifcations
                data.sound = notification.pushoversounds_up;
```

Code after:
            "expire": "3600",
            "html": 1,
        };

        const baseURL = await setting("primaryBaseURL");
        if (baseURL && monitorJSON) {
            data["url"] = baseURL + getMonitorRelativeURL(monitorJSON.id);
            data["url_title"] = "Link to Monitor";
        }

        if (notification.pushoverdevice) {
            data.device = notification.pushoverdevice;
        }
        if (notification.pushoverttl) {
            data.ttl = notification.pushoverttl;
        }

        try {
            if (heartbeatJSON == null) {
                await axios.post(url, data);
                return okMsg;
            }

            if (heartbeatJSON.status === UP && notification.pushoversounds_up) {
                // default = DOWN => DOWN-sound is also played for non-UP/DOWN notiifcations
                data.sound = notification.pushoversounds_up;
            }

            data.message += `\n<b>Time (${heartbeatJSON["timezone"]})</b>: ${heartbeatJSON["localDateTime"]}`;
            await axios.post(url, data);
            return okMsg;

        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
}

module.exports = Pushover;