mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
refactor: settings routes and actions
This commit is contained in:
parent
a60c725d38
commit
4838300086
@ -8,6 +8,7 @@ import (
|
||||
"github.com/muety/wakapi/utils"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
@ -16,6 +17,8 @@ func Init() {
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
type action func(w http.ResponseWriter, r *http.Request) (int, string, string)
|
||||
|
||||
var templates map[string]*template.Template
|
||||
|
||||
func loadTemplates() {
|
||||
|
@ -42,16 +42,7 @@ func NewSettingsHandler(userService services.IUserService, summaryService servic
|
||||
|
||||
func (h *SettingsHandler) RegisterRoutes(router *mux.Router) {
|
||||
router.Methods(http.MethodGet).HandlerFunc(h.GetIndex)
|
||||
router.Path("/credentials").Methods(http.MethodPost).HandlerFunc(h.PostCredentials)
|
||||
router.Path("/aliases").Methods(http.MethodPost).HandlerFunc(h.PostAlias)
|
||||
router.Path("/aliases/delete").Methods(http.MethodPost).HandlerFunc(h.DeleteAlias)
|
||||
router.Path("/language_mappings").Methods(http.MethodPost).HandlerFunc(h.PostLanguageMapping)
|
||||
router.Path("/language_mappings/delete").Methods(http.MethodPost).HandlerFunc(h.DeleteLanguageMapping)
|
||||
router.Path("/reset").Methods(http.MethodPost).HandlerFunc(h.PostResetApiKey)
|
||||
router.Path("/badges").Methods(http.MethodPost).HandlerFunc(h.PostToggleBadges)
|
||||
router.Path("/user/delete").Methods(http.MethodPost).HandlerFunc(h.DeleteUser)
|
||||
router.Path("/wakatime_integration").Methods(http.MethodPost).HandlerFunc(h.PostSetWakatimeApiKey)
|
||||
router.Path("/regenerate").Methods(http.MethodPost).HandlerFunc(h.PostRegenerateSummaries)
|
||||
router.Methods(http.MethodPost).HandlerFunc(h.PostIndex)
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) RegisterAPIRoutes(router *mux.Router) {}
|
||||
@ -64,7 +55,73 @@ func (h *SettingsHandler) GetIndex(w http.ResponseWriter, r *http.Request) {
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r))
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *SettingsHandler) PostIndex(w http.ResponseWriter, r *http.Request) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
if err := r.ParseForm(); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("missing form values"))
|
||||
return
|
||||
}
|
||||
|
||||
action := r.PostForm.Get("action")
|
||||
r.PostForm.Del("action")
|
||||
|
||||
actionFunc := h.dispatchAction(action)
|
||||
if actionFunc == nil {
|
||||
logbuch.Warn("failed to dispatch action '%s'", action)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("unknown action requests"))
|
||||
return
|
||||
}
|
||||
|
||||
status, successMsg, errorMsg := actionFunc(w, r)
|
||||
|
||||
// action responded itself
|
||||
if status == -1 {
|
||||
return
|
||||
}
|
||||
|
||||
if errorMsg != "" {
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError(errorMsg))
|
||||
return
|
||||
}
|
||||
if successMsg != "" {
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess(successMsg))
|
||||
return
|
||||
}
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r))
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) dispatchAction(action string) action {
|
||||
switch action {
|
||||
case "change_password":
|
||||
return h.actionChangePassword
|
||||
case "reset_apikey":
|
||||
return h.actionResetApiKey
|
||||
case "delete_alias":
|
||||
return h.actionDeleteAlias
|
||||
case "add_alias":
|
||||
return h.actionAddAlias
|
||||
case "delete_mapping":
|
||||
return h.actionDeleteLanguageMapping
|
||||
case "add_mapping":
|
||||
return h.actionAddLanguageMapping
|
||||
case "toggle_badges":
|
||||
return h.actionToggleBadges
|
||||
case "toggle_wakatime":
|
||||
return h.actionSetWakatimeApiKey
|
||||
case "regenerate_summaries":
|
||||
return h.actionRegenerateSummaries
|
||||
case "delete_account":
|
||||
return h.actionDeleteUser
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) actionChangePassword(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
@ -73,41 +130,29 @@ func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request
|
||||
|
||||
var credentials models.CredentialsReset
|
||||
if err := r.ParseForm(); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("missing parameters"))
|
||||
return
|
||||
return http.StatusBadRequest, "", "missing parameters"
|
||||
}
|
||||
if err := credentialsDecoder.Decode(&credentials, r.PostForm); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("missing parameters"))
|
||||
return
|
||||
return http.StatusBadRequest, "", "missing parameters"
|
||||
}
|
||||
|
||||
if !utils.CompareBcrypt(user.Password, credentials.PasswordOld, h.config.Security.PasswordSalt) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("invalid credentials"))
|
||||
return
|
||||
return http.StatusUnauthorized, "", "invalid credentials"
|
||||
}
|
||||
|
||||
if !credentials.IsValid() {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("invalid parameters"))
|
||||
return
|
||||
return http.StatusBadRequest, "", "invalid parameters"
|
||||
}
|
||||
|
||||
user.Password = credentials.PasswordNew
|
||||
if hash, err := utils.HashBcrypt(user.Password, h.config.Security.PasswordSalt); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||
return
|
||||
return http.StatusInternalServerError, "", "internal server error"
|
||||
} else {
|
||||
user.Password = hash
|
||||
}
|
||||
|
||||
if _, err := h.userSrvc.Update(user); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||
return
|
||||
return http.StatusInternalServerError, "", "internal server error"
|
||||
}
|
||||
|
||||
login := &models.Login{
|
||||
@ -116,75 +161,28 @@ func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
encoded, err := h.config.Security.SecureCookie.Encode(models.AuthCookieKey, login.Username)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||
return
|
||||
return http.StatusInternalServerError, "", "internal server error"
|
||||
}
|
||||
|
||||
http.SetCookie(w, h.config.CreateCookie(models.AuthCookieKey, encoded, "/"))
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("password was updated successfully"))
|
||||
return http.StatusOK, "password was updated successfully", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) DeleteLanguageMapping(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *SettingsHandler) actionResetApiKey(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
id, err := strconv.Atoi(r.PostFormValue("mapping_id"))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("could not delete mapping"))
|
||||
return
|
||||
if _, err := h.userSrvc.ResetApiKey(user); err != nil {
|
||||
return http.StatusInternalServerError, "", "internal server error"
|
||||
}
|
||||
|
||||
if mapping, err := h.languageMappingSrvc.GetById(uint(id)); err != nil || mapping == nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("mapping not found"))
|
||||
return
|
||||
} else if mapping.UserID != user.ID {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("not allowed to delete mapping"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.languageMappingSrvc.Delete(&models.LanguageMapping{ID: uint(id)}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("could not delete mapping"))
|
||||
return
|
||||
}
|
||||
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("mapping deleted successfully"))
|
||||
msg := fmt.Sprintf("your new api key is: %s", user.ApiKey)
|
||||
return http.StatusOK, msg, ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) PostLanguageMapping(w http.ResponseWriter, r *http.Request) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
extension := r.PostFormValue("extension")
|
||||
language := r.PostFormValue("language")
|
||||
|
||||
if extension[0] == '.' {
|
||||
extension = extension[1:]
|
||||
}
|
||||
|
||||
mapping := &models.LanguageMapping{
|
||||
UserID: user.ID,
|
||||
Extension: extension,
|
||||
Language: language,
|
||||
}
|
||||
|
||||
if _, err := h.languageMappingSrvc.Create(mapping); err != nil {
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("mapping already exists"))
|
||||
return
|
||||
}
|
||||
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("mapping added successfully"))
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) DeleteAlias(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *SettingsHandler) actionDeleteAlias(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
@ -197,19 +195,15 @@ func (h *SettingsHandler) DeleteAlias(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if aliases, err := h.aliasSrvc.GetByUserAndKeyAndType(user.ID, aliasKey, uint8(aliasType)); err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("aliases not found"))
|
||||
return
|
||||
return http.StatusNotFound, "", "aliases not found"
|
||||
} else if err := h.aliasSrvc.DeleteMulti(aliases); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("could not delete aliases"))
|
||||
return
|
||||
return http.StatusInternalServerError, "", "could not delete aliases"
|
||||
}
|
||||
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("aliases deleted successfully"))
|
||||
return http.StatusOK, "aliases deleted successfully", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) PostAlias(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *SettingsHandler) actionAddAlias(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
@ -229,32 +223,76 @@ func (h *SettingsHandler) PostAlias(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if _, err := h.aliasSrvc.Create(alias); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
// TODO: distinguish between bad request, conflict and server error
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("invalid input"))
|
||||
return
|
||||
return http.StatusBadRequest, "", "invalid input"
|
||||
}
|
||||
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("alias added successfully"))
|
||||
return http.StatusOK, "alias added successfully", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) PostResetApiKey(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *SettingsHandler) actionDeleteLanguageMapping(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
if _, err := h.userSrvc.ResetApiKey(user); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||
return
|
||||
id, err := strconv.Atoi(r.PostFormValue("mapping_id"))
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, "", "could not delete mapping"
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("your new api key is: %s", user.ApiKey)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess(msg))
|
||||
if mapping, err := h.languageMappingSrvc.GetById(uint(id)); err != nil || mapping == nil {
|
||||
return http.StatusNotFound, "", "mapping not found"
|
||||
} else if mapping.UserID != user.ID {
|
||||
return http.StatusForbidden, "", "not allowed to delete mapping"
|
||||
}
|
||||
|
||||
if err := h.languageMappingSrvc.Delete(&models.LanguageMapping{ID: uint(id)}); err != nil {
|
||||
return http.StatusInternalServerError, "", "could not delete mapping"
|
||||
}
|
||||
|
||||
return http.StatusOK, "mapping deleted successfully", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) PostSetWakatimeApiKey(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *SettingsHandler) actionAddLanguageMapping(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
extension := r.PostFormValue("extension")
|
||||
language := r.PostFormValue("language")
|
||||
|
||||
if extension[0] == '.' {
|
||||
extension = extension[1:]
|
||||
}
|
||||
|
||||
mapping := &models.LanguageMapping{
|
||||
UserID: user.ID,
|
||||
Extension: extension,
|
||||
Language: language,
|
||||
}
|
||||
|
||||
if _, err := h.languageMappingSrvc.Create(mapping); err != nil {
|
||||
return http.StatusConflict, "", "mapping already exists"
|
||||
}
|
||||
|
||||
return http.StatusOK, "mapping added successfully", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) actionToggleBadges(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
if _, err := h.userSrvc.ToggleBadges(user); err != nil {
|
||||
return http.StatusInternalServerError, "", "internal server error"
|
||||
}
|
||||
|
||||
return http.StatusOK, "", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) actionSetWakatimeApiKey(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
@ -264,35 +302,39 @@ func (h *SettingsHandler) PostSetWakatimeApiKey(w http.ResponseWriter, r *http.R
|
||||
|
||||
// Healthcheck, if a new API key is set, i.e. the feature is activated
|
||||
if (user.WakatimeApiKey == "" && apiKey != "") && !h.validateWakatimeKey(apiKey) {
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("failed to connect to WakaTime, API key invalid?"))
|
||||
return
|
||||
return http.StatusBadRequest, "", "failed to connect to WakaTime, API key invalid?"
|
||||
}
|
||||
|
||||
if _, err := h.userSrvc.SetWakatimeApiKey(user, apiKey); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||
return
|
||||
return http.StatusInternalServerError, "", "internal server error"
|
||||
}
|
||||
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("Wakatime API Key updated successfully"))
|
||||
return http.StatusOK, "Wakatime API Key updated successfully", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) PostToggleBadges(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *SettingsHandler) actionRegenerateSummaries(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
if _, err := h.userSrvc.ToggleBadges(user); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||
return
|
||||
|
||||
logbuch.Info("clearing summaries for user '%s'", user.ID)
|
||||
if err := h.summarySrvc.DeleteByUser(user.ID); err != nil {
|
||||
logbuch.Error("failed to clear summaries: %v", err)
|
||||
return http.StatusInternalServerError, "", "failed to delete old summaries"
|
||||
}
|
||||
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r))
|
||||
if err := h.aggregationSrvc.Run(map[string]bool{user.ID: true}); err != nil {
|
||||
logbuch.Error("failed to regenerate summaries: %v", err)
|
||||
return http.StatusInternalServerError, "", "failed to generate aggregations"
|
||||
|
||||
}
|
||||
|
||||
return http.StatusOK, "summaries are being regenerated – this may take a few seconds", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) DeleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *SettingsHandler) actionDeleteUser(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
@ -310,31 +352,7 @@ func (h *SettingsHandler) DeleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
http.SetCookie(w, h.config.GetClearCookie(models.AuthCookieKey, "/"))
|
||||
http.Redirect(w, r, fmt.Sprintf("%s/?success=%s", h.config.Server.BasePath, "Your account will be deleted in a few minutes. Sorry to you go."), http.StatusFound)
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) PostRegenerateSummaries(w http.ResponseWriter, r *http.Request) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
|
||||
logbuch.Info("clearing summaries for user '%s'", user.ID)
|
||||
if err := h.summarySrvc.DeleteByUser(user.ID); err != nil {
|
||||
logbuch.Error("failed to clear summaries: %v", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("failed to delete old summaries"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.aggregationSrvc.Run(map[string]bool{user.ID: true}); err != nil {
|
||||
logbuch.Error("failed to regenerate summaries: %v", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("failed to generate aggregations"))
|
||||
return
|
||||
}
|
||||
|
||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("summaries are being regenerated – this may take a few seconds"))
|
||||
return -1, "", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) validateWakatimeKey(apiKey string) bool {
|
||||
|
@ -64,7 +64,8 @@
|
||||
Change Password
|
||||
</h2>
|
||||
|
||||
<form class="mt-10" action="settings/credentials" method="post">
|
||||
<form class="mt-10" action="" method="post">
|
||||
<input type="hidden" name="action" value="change_password">
|
||||
<div class="mb-8">
|
||||
<label class="inline-block text-sm mb-1 text-gray-500" for="password_old">Current Password</label>
|
||||
<input class="shadow appearance-none bg-gray-800 focus:bg-gray-700 text-gray-300 border-green-700 focus:border-gray-500 border rounded w-full py-1 px-3"
|
||||
@ -96,7 +97,8 @@
|
||||
Reset API Key
|
||||
</h2>
|
||||
|
||||
<form class="mt-6" action="settings/reset" method="post">
|
||||
<form class="mt-6" action="" method="post">
|
||||
<input type="hidden" name="action" value="reset_apikey">
|
||||
<div class="text-gray-300 text-sm mb-4">
|
||||
<strong>⚠️ Caution:</strong> Resetting your API key requires you to update your <span
|
||||
class="font-mono">.wakatime.cfg</span> files on all of your computers to make the WakaTime
|
||||
@ -141,7 +143,8 @@
|
||||
are mapped to <span class="underline">{{ $alias.Type | typeName }}</span> <span
|
||||
class="text-white text-xs bg-gray-900 rounded py-1 px-2 font-mono">{{ $alias.Key }}</span>.
|
||||
</div>
|
||||
<form class="float-right" action="settings/aliases/delete" method="post">
|
||||
<form class="float-right" action="" method="post">
|
||||
<input type="hidden" name="action" value="delete_alias">
|
||||
<input type="hidden" id="delete_alias_key" name="key" required value="{{ $alias.Key }}">
|
||||
<input type="hidden" id="delete_alias_type" name="type" required value="{{ $alias.Type }}">
|
||||
<button type="submit"
|
||||
@ -155,7 +158,8 @@
|
||||
{{end}}
|
||||
|
||||
<h3 class="inline-block font-semibold text-md border-b border-green-700 text-white mb-2">Add Rule</h3>
|
||||
<form action="settings/aliases" method="post">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="action" value="add_alias">
|
||||
<div class="flex items-center mt-2 w-full text-gray-500 text-sm">
|
||||
<span class="mr-2">Map</span>
|
||||
<select name="type" id="select-type"
|
||||
@ -203,7 +207,8 @@
|
||||
then change the <span class="underline">language</span> to <span
|
||||
class="text-white text-xs bg-gray-900 rounded py-1 px-2 font-mono mr-1">{{ $mapping.Language }}</span>
|
||||
</div>
|
||||
<form class="float-right" action="settings/language_mappings/delete" method="post">
|
||||
<form class="float-right" action="" method="post">
|
||||
<input type="hidden" name="action" value="delete_mapping">
|
||||
<input type="hidden" id="mapping_id" name="mapping_id" required value="{{ $mapping.ID }}">
|
||||
<button type="submit"
|
||||
class="py-1 px-3 rounded border border-red-500 hover:border-red-600 text-gray-400 text-sm">
|
||||
@ -216,7 +221,8 @@
|
||||
{{end}}
|
||||
|
||||
<h3 class="inline-block font-semibold text-md border-b border-green-700 text-white">Add Rule</h3>
|
||||
<form action="settings/language_mappings" method="post">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="action" value="add_mapping">
|
||||
<div class="flex items-center w-full text-gray-500 text-sm">
|
||||
<span class="mr-2">When filename ends in</span>
|
||||
<input class="shadow appearance-nonshadow appearance-none bg-gray-800 focus:bg-gray-700 text-gray-300 border-green-700 focus:border-gray-500 border rounded py-1 px-3"
|
||||
@ -241,7 +247,8 @@
|
||||
Badges
|
||||
</div>
|
||||
|
||||
<form class="mt-6" action="settings/badges" method="post">
|
||||
<form class="mt-6" action="" method="post">
|
||||
<input type="hidden" name="action" value="toggle_badges">
|
||||
<div class="text-gray-300 text-sm mb-4">
|
||||
{{ if .User.BadgesEnabled }}
|
||||
<p>Badges are currently enabled. You can disable the feature by deactivating the respective API
|
||||
@ -328,7 +335,8 @@
|
||||
target="_blank">get your API key</a> and paste it here.</p>
|
||||
</div>
|
||||
|
||||
<form action="settings/wakatime_integration" method="post">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="action" value="toggle_wakatime">
|
||||
|
||||
{{ $placeholderText := "Paste your WakaTime API key here ..." }}
|
||||
{{ if .User.WakatimeApiKey }}
|
||||
@ -390,7 +398,8 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-6 flex justify-center">
|
||||
<form action="settings/regenerate" method="post" id="form-regenerate-summaries">
|
||||
<form action="" method="post" id="form-regenerate-summaries">
|
||||
<input type="hidden" name="action" value="regenerate_summaries">
|
||||
<button type="button" class="py-1 px-3 rounded bg-red-500 hover:bg-red-600 text-white text-sm"
|
||||
id="btn-regenerate-summaries">
|
||||
Clear & Regenerate
|
||||
@ -408,8 +417,9 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-6 flex justify-center">
|
||||
<form action="settings/user/delete" method="post" id="form-delete-user">
|
||||
<button type="button" onclick="console.log('boom')" class="py-1 px-3 rounded bg-red-500 hover:bg-red-600 text-white text-sm"
|
||||
<form action="" method="post" id="form-delete-user">
|
||||
<input type="hidden" name="action" value="delete_account">
|
||||
<button type="button" class="py-1 px-3 rounded bg-red-500 hover:bg-red-600 text-white text-sm"
|
||||
id="btn-confirm-delete-user">
|
||||
Delete my Account
|
||||
</button>
|
||||
|
Loading…
Reference in New Issue
Block a user