+
+
+
+
+
diff --git a/src/components/settings/Users/routes.js b/src/components/settings/Users/routes.js
new file mode 100644
index 000000000..6d3517455
--- /dev/null
+++ b/src/components/settings/Users/routes.js
@@ -0,0 +1,29 @@
+import { h } from "vue";
+import { RouterView } from "vue-router";
+
+// Needed for settings enter/leave CSS animation
+const AnimatedRouterView = () => h("div", [ h(RouterView) ]);
+AnimatedRouterView.displayName = "AnimatedRouterView";
+
+export default {
+ path: "users",
+ component: AnimatedRouterView,
+ children: [
+ {
+ path: "",
+ name: "settings.users",
+ component: () => import("./Users.vue")
+ },
+ {
+ path: "add",
+ name: "settings.users.add",
+ component: () => import("./AddUser.vue")
+ },
+ {
+ path: "edit/:id",
+ name: "settings.users.edit",
+ props: true,
+ component: () => import("./EditUser.vue")
+ },
+ ]
+};
diff --git a/src/icon.js b/src/icon.js
index 7bdfe1ca0..b40482783 100644
--- a/src/icon.js
+++ b/src/icon.js
@@ -50,6 +50,8 @@ import {
faInfoCircle,
faClone,
faCertificate,
+ faUserSlash,
+ faUserCheck,
} from "@fortawesome/free-solid-svg-icons";
library.add(
@@ -97,6 +99,8 @@ library.add(
faInfoCircle,
faClone,
faCertificate,
+ faUserSlash,
+ faUserCheck,
);
export { FontAwesomeIcon };
diff --git a/src/lang/en.json b/src/lang/en.json
index c07e06fab..81fecfae0 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -1051,5 +1051,12 @@
"From":"From",
"Can be found on:": "Can be found on: {0}",
"The phone number of the recipient in E.164 format.": "The phone number of the recipient in E.164 format.",
- "Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.":"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies."
-}
+ "Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.",
+ "Users": "Users",
+ "Add New User": "Add New User",
+ "confirmDisableUserMsg": "Are you sure you want to disable this user? The user will not be able to login anymore.",
+ "Create an admin account": "Create an admin account",
+ "Identity": "Identity",
+ "Update Username": "Update Username",
+ "Permissions": "Permissions"
+}
\ No newline at end of file
diff --git a/src/pages/Settings.vue b/src/pages/Settings.vue
index d0ed076e1..6dbd88271 100644
--- a/src/pages/Settings.vue
+++ b/src/pages/Settings.vue
@@ -130,6 +130,13 @@ export default {
security: {
title: this.$t("Security"),
},
+ users: {
+ title: this.$t("Users"),
+ children: {
+ add: { title: this.$t("Add") },
+ edit: { title: this.$t("Edit") }
+ },
+ },
"api-keys": {
title: this.$t("API Keys")
},
diff --git a/src/router.js b/src/router.js
index bda5078e1..53cf6ac1d 100644
--- a/src/router.js
+++ b/src/router.js
@@ -27,6 +27,7 @@ import General from "./components/settings/General.vue";
const Notifications = () => import("./components/settings/Notifications.vue");
import ReverseProxy from "./components/settings/ReverseProxy.vue";
import Tags from "./components/settings/Tags.vue";
+import usersSettingsRoutes from "./components/settings/Users/routes.js";
import MonitorHistory from "./components/settings/MonitorHistory.vue";
const Security = () => import("./components/settings/Security.vue");
import Proxies from "./components/settings/Proxies.vue";
@@ -124,6 +125,7 @@ const routes = [
path: "security",
component: Security,
},
+ usersSettingsRoutes,
{
path: "api-keys",
component: APIKeys,
diff --git a/src/util-frontend.js b/src/util-frontend.js
index d9bf378e5..33fc91a64 100644
--- a/src/util-frontend.js
+++ b/src/util-frontend.js
@@ -213,3 +213,22 @@ export function getToastErrorTimeout() {
return errorTimeout;
}
+
+/**
+ * Get debounced function
+ * @returns {Function} debounced function
+ */
+export function Debounce() {
+ let timeout = null;
+
+ /**
+ * exec callback function after delay if no new call to function happens
+ * @param {Function} callback function to execute after delay
+ * @param {number} [delay=100] delay before execute the callback if no new call to function happens
+ * @returns {void}
+ */
+ return function (callback, delay = 100) {
+ clearTimeout(timeout);
+ timeout = setTimeout(() => callback(), delay);
+ };
+}