remove usernames
This commit is contained in:
@@ -288,6 +288,16 @@ export const routes = [
|
||||
component: () =>
|
||||
import("@/views/dashboard/UserList.vue"),
|
||||
},
|
||||
{
|
||||
path: "create",
|
||||
name: "dashboard-user-create",
|
||||
meta: {
|
||||
title: "Create User",
|
||||
middleware: "authenticated",
|
||||
},
|
||||
component: () =>
|
||||
import("@/views/dashboard/UserEdit.vue"),
|
||||
},
|
||||
{
|
||||
path: ":id",
|
||||
name: "dashboard-user-edit",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</h1>
|
||||
<SMToolbar>
|
||||
<div>
|
||||
<div class="author">By {{ article.user.username }}</div>
|
||||
<div class="author">By {{ article.user.display_name }}</div>
|
||||
<div class="date">{{ formattedDate(article.publish_at) }}</div>
|
||||
</div>
|
||||
<SMButton
|
||||
@@ -47,7 +47,7 @@ const applicationStore = useApplicationStore();
|
||||
*/
|
||||
let article: Ref<Article> = ref({
|
||||
title: "",
|
||||
user: { username: "" },
|
||||
user: { display_name: "" },
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
<template v-if="!formDone">
|
||||
<h1>Forgot Password</h1>
|
||||
<p>
|
||||
Enter your username below to receive a password reset
|
||||
link to your email address.
|
||||
Enter your email below to receive a password reset link.
|
||||
</p>
|
||||
<SMForm v-model="form" @submit="handleSubmit">
|
||||
<SMInput control="username" />
|
||||
<SMInput control="email" />
|
||||
<SMButtonRow>
|
||||
<template #left>
|
||||
<div class="small">
|
||||
@@ -31,9 +30,9 @@
|
||||
<template v-else>
|
||||
<h1>Email Sent!</h1>
|
||||
<p class="text-center">
|
||||
If that username has been registered, you will receive
|
||||
an email with a reset password link in the next few
|
||||
minutes.
|
||||
If that email address has been registered, you will
|
||||
receive an email with a reset password link in the next
|
||||
few minutes.
|
||||
</p>
|
||||
<SMRow class="pb-2">
|
||||
<SMColumn class="justify-content-center">
|
||||
@@ -56,13 +55,13 @@ import SMButtonRow from "../components/SMButtonRow.vue";
|
||||
import SMInput from "../components/SMInput.vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Min, Required } from "../helpers/validate";
|
||||
import { And, Email, Required } from "../helpers/validate";
|
||||
|
||||
// const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();
|
||||
const formDone = ref(false);
|
||||
let form = reactive(
|
||||
Form({
|
||||
username: FormControl("", And([Required(), Min(4)])),
|
||||
email: FormControl("", And([Required(), Email()])),
|
||||
})
|
||||
);
|
||||
|
||||
@@ -76,7 +75,7 @@ const handleSubmit = async () => {
|
||||
await api.post({
|
||||
url: "/users/forgotPassword",
|
||||
body: {
|
||||
username: form.controls.username.value,
|
||||
email: form.controls.email.value,
|
||||
// captcha_token: captcha,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<SMPage>
|
||||
<SMRow>
|
||||
<SMFormCard class="mt-5">
|
||||
<template v-if="!formDone">
|
||||
<h1>Forgot Username</h1>
|
||||
<p>
|
||||
Enter your email address, and if an account exists, we
|
||||
will email you your username.
|
||||
</p>
|
||||
<SMForm v-model="form" @submit="handleSubmit">
|
||||
<SMInput control="email" />
|
||||
<SMButtonRow>
|
||||
<template #left>
|
||||
<div class="small">
|
||||
<span class="pr-1">Remember?</span
|
||||
><router-link :to="{ name: 'login' }"
|
||||
>Log in</router-link
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<SMButton
|
||||
type="submit"
|
||||
label="Send"
|
||||
icon="arrow-forward-outline" />
|
||||
</template>
|
||||
</SMButtonRow>
|
||||
</SMForm>
|
||||
</template>
|
||||
<template v-else>
|
||||
<h1>Email Sent!</h1>
|
||||
<p class="text-center">
|
||||
If that email has a registered account, you should
|
||||
receive it shortly.
|
||||
</p>
|
||||
<SMRow class="pb-2">
|
||||
<SMColumn class="justify-content-center">
|
||||
<SMButton :to="{ name: 'home' }" label="Home" />
|
||||
</SMColumn>
|
||||
</SMRow>
|
||||
</template>
|
||||
</SMFormCard>
|
||||
</SMRow>
|
||||
</SMPage>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue";
|
||||
// import { useReCaptcha } from "vue-recaptcha-v3";
|
||||
import SMButton from "../components/SMButton.vue";
|
||||
import SMFormCard from "../components/SMFormCard.vue";
|
||||
import SMForm from "../components/SMForm.vue";
|
||||
import SMButtonRow from "../components/SMButtonRow.vue";
|
||||
import SMInput from "../components/SMInput.vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Email, Required } from "../helpers/validate";
|
||||
|
||||
// const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();
|
||||
const formDone = ref(false);
|
||||
let form = reactive(
|
||||
Form({
|
||||
email: FormControl("", And([Required(), Email()])),
|
||||
})
|
||||
);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
form.loading(true);
|
||||
|
||||
try {
|
||||
// await recaptchaLoaded();
|
||||
// const captcha = await executeRecaptcha("submit");
|
||||
|
||||
await api.post({
|
||||
url: "/users/forgotUsername",
|
||||
body: {
|
||||
email: form.controls.email.value,
|
||||
// captcha_token: captcha,
|
||||
},
|
||||
});
|
||||
|
||||
formDone.value = true;
|
||||
} catch (error) {
|
||||
form.apiErrors(error);
|
||||
}
|
||||
|
||||
form.loading(false);
|
||||
};
|
||||
</script>
|
||||
@@ -9,11 +9,7 @@
|
||||
</p>
|
||||
</template>
|
||||
<template #body>
|
||||
<SMInput control="username" autofocus>
|
||||
<router-link to="/forgot-username"
|
||||
>Forgot username?</router-link
|
||||
>
|
||||
</SMInput>
|
||||
<SMInput control="email" autofocus> </SMInput>
|
||||
<SMInput control="password" type="password">
|
||||
<router-link to="/forgot-password"
|
||||
>Forgot password?</router-link
|
||||
@@ -54,7 +50,7 @@ import SMInput from "../components/SMInput.vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { LoginResponse } from "../helpers/api.types";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Min, Required } from "../helpers/validate";
|
||||
import { And, Email, Required } from "../helpers/validate";
|
||||
import { useUserStore } from "../store/UserStore";
|
||||
import SMButtonRow from "../components/SMButtonRow.vue";
|
||||
|
||||
@@ -63,7 +59,7 @@ const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
let form = reactive(
|
||||
Form({
|
||||
username: FormControl("", And([Required(), Min(4)])),
|
||||
email: FormControl("", And([Required(), Email()])),
|
||||
password: FormControl("", Required()),
|
||||
})
|
||||
);
|
||||
@@ -81,7 +77,7 @@ const handleSubmit = async () => {
|
||||
let result = await api.post({
|
||||
url: "/login",
|
||||
body: {
|
||||
username: form.controls.username.value,
|
||||
email: form.controls.email.value,
|
||||
password: form.controls.password.value,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<SMContainer :center="true">
|
||||
<SMForm v-if="!userRegistered" v-model="form" @submit="handleSubmit">
|
||||
<SMFormCard full>
|
||||
<SMFormCard>
|
||||
<template #header>
|
||||
<h2>Register</h2>
|
||||
<p>
|
||||
@@ -10,36 +10,9 @@
|
||||
</p>
|
||||
</template>
|
||||
<template #body>
|
||||
<SMRow>
|
||||
<SMColumn>
|
||||
<SMInput control="username" autofocus />
|
||||
</SMColumn>
|
||||
<SMColumn>
|
||||
<SMInput
|
||||
control="password"
|
||||
type="password"></SMInput>
|
||||
</SMColumn>
|
||||
</SMRow>
|
||||
<SMRow>
|
||||
<SMColumn>
|
||||
<SMInput control="first_name" />
|
||||
</SMColumn>
|
||||
<SMColumn>
|
||||
<SMInput control="last_name" />
|
||||
</SMColumn>
|
||||
</SMRow>
|
||||
<SMRow>
|
||||
<SMColumn>
|
||||
<SMInput control="email" />
|
||||
</SMColumn>
|
||||
<SMColumn>
|
||||
<SMInput control="phone"
|
||||
><template #help
|
||||
>This field is optional</template
|
||||
>
|
||||
</SMInput>
|
||||
</SMColumn>
|
||||
</SMRow>
|
||||
<SMInput control="email" autofocus />
|
||||
<SMInput control="password" type="password" />
|
||||
<SMInput control="display_name" label="Display Name" />
|
||||
</template>
|
||||
<template #footer-space-between>
|
||||
<div class="small">
|
||||
@@ -125,7 +98,6 @@ let form = reactive(
|
||||
first_name: FormControl("", Required()),
|
||||
last_name: FormControl("", Required()),
|
||||
email: FormControl("", And([Required(), Email()])),
|
||||
phone: FormControl("", Phone()),
|
||||
username: FormControl("", And([Min(4), Custom(checkUsername)])),
|
||||
password: FormControl("", And([Required(), Password()])),
|
||||
})
|
||||
@@ -135,20 +107,14 @@ const handleSubmit = async () => {
|
||||
form.loading(true);
|
||||
|
||||
try {
|
||||
// await recaptchaLoaded();
|
||||
// const captcha = await executeRecaptcha("submit");
|
||||
|
||||
await api.post({
|
||||
url: "/register",
|
||||
body: {
|
||||
first_name: form.controls.first_name.value,
|
||||
last_name: form.controls.last_name.value,
|
||||
email: form.controls.email.value,
|
||||
phone: form.controls.phone.value,
|
||||
username: form.controls.username.value,
|
||||
password: form.controls.password.value,
|
||||
display_name: form.controls.username.value,
|
||||
// captcha_token: captcha,
|
||||
display_name: form.controls.display_name.value,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<template v-if="!formDone">
|
||||
<h1>Resend Verify Email</h1>
|
||||
<SMForm v-model="form" @submit="handleSubmit">
|
||||
<SMInput control="username" />
|
||||
<SMInput control="email" />
|
||||
<SMButtonRow>
|
||||
<template #left>
|
||||
<div class="small">
|
||||
@@ -27,9 +27,9 @@
|
||||
<template v-else>
|
||||
<h1>Email Sent!</h1>
|
||||
<p class="text-center">
|
||||
If that username has been registered, and you still need
|
||||
to verify your email, you will receive an email with a
|
||||
new verify code.
|
||||
If that email address has been registered, and you still
|
||||
need to verify your email, you will receive an email
|
||||
with a new verify code.
|
||||
</p>
|
||||
<SMButtonRow>
|
||||
<template #right>
|
||||
@@ -52,13 +52,13 @@ import SMButtonRow from "../components/SMButtonRow.vue";
|
||||
import SMInput from "../components/SMInput.vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { Required } from "../helpers/validate";
|
||||
import { And, Email, Required } from "../helpers/validate";
|
||||
|
||||
// const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();
|
||||
const formDone = ref(false);
|
||||
let form = reactive(
|
||||
Form({
|
||||
username: FormControl("", Required()),
|
||||
email: FormControl("", And([Required(), Email()])),
|
||||
})
|
||||
);
|
||||
|
||||
@@ -72,7 +72,7 @@ const handleSubmit = async () => {
|
||||
await api.post({
|
||||
url: "/users/resendVerifyEmailCode",
|
||||
body: {
|
||||
username: form.controls.username.value,
|
||||
email: form.controls.email.value,
|
||||
// captcha_token: captcha,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -301,7 +301,7 @@ const loadOptionsAuthors = async () => {
|
||||
api.get({
|
||||
url: "/users",
|
||||
params: {
|
||||
fields: "id,username,first_name,last_name",
|
||||
fields: "id,display_name",
|
||||
limit: 100,
|
||||
},
|
||||
})
|
||||
@@ -312,7 +312,7 @@ const loadOptionsAuthors = async () => {
|
||||
authors.value = {};
|
||||
|
||||
data.users.forEach((item) => {
|
||||
authors.value[item.id] = `${item.username}`;
|
||||
authors.value[item.id] = `${item.display_name}`;
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
<SMMastHead
|
||||
:title="pageHeading"
|
||||
:back-link="
|
||||
route.params.id
|
||||
route.params.id || isCreatingUser
|
||||
? { name: 'dashboard-user-list' }
|
||||
: { name: 'dashboard' }
|
||||
"
|
||||
:back-title="route.params.id ? 'Back to Users' : 'Back to Dashboard'" />
|
||||
:back-title="
|
||||
route.params.id || isCreatingUser
|
||||
? 'Back to Users'
|
||||
: 'Back to Dashboard'
|
||||
" />
|
||||
<SMContainer>
|
||||
<SMForm :model-value="form" @submit="handleSubmit">
|
||||
<SMRow>
|
||||
<SMColumn><SMInput control="username" disabled /></SMColumn>
|
||||
<SMColumn><SMInput control="display_name" /></SMColumn>
|
||||
</SMRow>
|
||||
<SMRow>
|
||||
@@ -90,9 +93,10 @@ const route = useRoute();
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const isCreatingUser = route.path.endsWith("/create");
|
||||
|
||||
let form = reactive(
|
||||
Form({
|
||||
username: FormControl("", And([Required()])),
|
||||
display_name: FormControl("", And([Required()])),
|
||||
first_name: FormControl("", And([Required()])),
|
||||
last_name: FormControl("", And([Required()])),
|
||||
@@ -122,7 +126,6 @@ const loadData = async () => {
|
||||
const data = result.data as UserResponse;
|
||||
|
||||
if (data && data.user) {
|
||||
form.controls.username.value = data.user.username;
|
||||
form.controls.first_name.value = data.user.first_name;
|
||||
form.controls.last_name.value = data.user.last_name;
|
||||
form.controls.display_name.value = data.user.display_name;
|
||||
@@ -134,8 +137,7 @@ const loadData = async () => {
|
||||
} finally {
|
||||
form.loading(false);
|
||||
}
|
||||
} else {
|
||||
form.controls.username.value = userStore.username;
|
||||
} else if (isCreatingUser == false) {
|
||||
form.controls.first_name.value = userStore.firstName;
|
||||
form.controls.last_name.value = userStore.lastName;
|
||||
form.controls.display_name.value = userStore.displayName;
|
||||
@@ -150,34 +152,56 @@ const loadData = async () => {
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
form.loading(true);
|
||||
const result = await api.put({
|
||||
url: "/users/{id}",
|
||||
params: {
|
||||
id: userStore.id,
|
||||
},
|
||||
body: {
|
||||
first_name: form.controls.first_name.value,
|
||||
last_name: form.controls.last_name.value,
|
||||
display_name: form.controls.display_name.value,
|
||||
email: form.controls.email.value,
|
||||
phone: form.controls.phone.value,
|
||||
},
|
||||
});
|
||||
const id = route.params.id ? route.params.id : userStore.id;
|
||||
|
||||
const data = result.data as UserResponse;
|
||||
if (isCreatingUser == false) {
|
||||
const result = await api.put({
|
||||
url: "/users/{id}",
|
||||
params: {
|
||||
id: id,
|
||||
},
|
||||
body: {
|
||||
first_name: form.controls.first_name.value,
|
||||
last_name: form.controls.last_name.value,
|
||||
display_name: form.controls.display_name.value,
|
||||
email: form.controls.email.value,
|
||||
phone: form.controls.phone.value,
|
||||
},
|
||||
});
|
||||
|
||||
if (data && data.user) {
|
||||
userStore.setUserDetails(data.user);
|
||||
const data = result.data as UserResponse;
|
||||
|
||||
if (route.params.id && data && data.user) {
|
||||
userStore.setUserDetails(data.user);
|
||||
}
|
||||
|
||||
useToastStore().addToast({
|
||||
title: "Details Updated",
|
||||
content: "The user has been updated.",
|
||||
type: "success",
|
||||
});
|
||||
} else {
|
||||
await api.post({
|
||||
url: "/users",
|
||||
params: {
|
||||
id: id,
|
||||
},
|
||||
body: {
|
||||
first_name: form.controls.first_name.value,
|
||||
last_name: form.controls.last_name.value,
|
||||
display_name: form.controls.display_name.value,
|
||||
email: form.controls.email.value,
|
||||
phone: form.controls.phone.value,
|
||||
},
|
||||
});
|
||||
|
||||
useToastStore().addToast({
|
||||
title: "User Created",
|
||||
content: "The user has been created.",
|
||||
type: "success",
|
||||
});
|
||||
}
|
||||
|
||||
useToastStore().addToast({
|
||||
title: route.params.id ? "Details Updated" : "User Created",
|
||||
content: route.params.id
|
||||
? "The user has been updated."
|
||||
: "The user has been created.",
|
||||
type: "success",
|
||||
});
|
||||
|
||||
router.push({ name: "dashboard" });
|
||||
} catch (err) {
|
||||
form.apiErrors(err);
|
||||
|
||||
@@ -1,91 +1,154 @@
|
||||
<template>
|
||||
<SMPage permission="admin/users" :page-error="pageError">
|
||||
<SMPage permission="admin/users">
|
||||
<SMMastHead
|
||||
title="Users"
|
||||
:back-link="{ name: 'dashboard' }"
|
||||
back-title="Return to Dashboard" />
|
||||
<SMContainer>
|
||||
<SMTable
|
||||
:headers="headers"
|
||||
:items="items"
|
||||
@row-click="handleRowClick">
|
||||
<template #item-actions="item">
|
||||
<SMButton
|
||||
label="Edit"
|
||||
:dropdown="{
|
||||
download: 'Download',
|
||||
delete: 'Delete',
|
||||
}"
|
||||
size="medium" />
|
||||
</template>
|
||||
</SMTable>
|
||||
<SMContainer class="flex-grow-1">
|
||||
<SMToolbar>
|
||||
<SMButton
|
||||
:to="{ name: 'dashboard-user-create' }"
|
||||
type="primary"
|
||||
label="Create User" />
|
||||
<SMInput
|
||||
v-model="itemSearch"
|
||||
label="Search"
|
||||
class="toolbar-search"
|
||||
@keyup.enter="handleSearch">
|
||||
<template #append>
|
||||
<SMButton
|
||||
type="primary"
|
||||
label="Search"
|
||||
icon="search-outline"
|
||||
@click="handleSearch" />
|
||||
</template>
|
||||
</SMInput>
|
||||
</SMToolbar>
|
||||
<SMLoading large v-if="itemsLoading" />
|
||||
<template v-else>
|
||||
<SMPagination
|
||||
v-if="items.length < itemsTotal"
|
||||
v-model="itemsPage"
|
||||
:total="itemsTotal"
|
||||
:per-page="itemsPerPage" />
|
||||
<SMNoItems v-if="items.length == 0" text="No Media Found" />
|
||||
<SMTable
|
||||
:headers="headers"
|
||||
:items="items"
|
||||
@row-click="handleEdit">
|
||||
<template #item-actions="item">
|
||||
<SMButton
|
||||
label="Edit"
|
||||
:dropdown="{
|
||||
delete: 'Delete',
|
||||
}"
|
||||
size="medium"
|
||||
@click="handleActionButton(item, $event)" />
|
||||
</template>
|
||||
</SMTable>
|
||||
</template>
|
||||
</SMContainer>
|
||||
</SMPage>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { ref, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { openDialog } from "../../components/SMDialog";
|
||||
import DialogConfirm from "../../components/dialogs/SMDialogConfirm.vue";
|
||||
import { api } from "../../helpers/api";
|
||||
import { api, getApiResultData } from "../../helpers/api";
|
||||
import { SMDate } from "../../helpers/datetime";
|
||||
import SMTable from "../../components/SMTable.vue";
|
||||
import SMMastHead from "../../components/SMMastHead.vue";
|
||||
import { useToastStore } from "../../store/ToastStore";
|
||||
import SMNoItems from "../../components/SMNoItems.vue";
|
||||
import SMButton from "../../components/SMButton.vue";
|
||||
import SMInput from "../../components/SMInput.vue";
|
||||
import SMToolbar from "../../components/SMToolbar.vue";
|
||||
import { updateRouterParams } from "../../helpers/url";
|
||||
import { User, UserCollection } from "../../helpers/api.types";
|
||||
import SMLoading from "../../components/SMLoading.vue";
|
||||
import SMPagination from "../../components/SMPagination.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const searchValue = ref("");
|
||||
const pageError = ref(0);
|
||||
|
||||
const items = ref([]);
|
||||
const itemsLoading = ref(false);
|
||||
const itemSearch = ref((route.query.search as string) || "");
|
||||
const itemsTotal = ref(0);
|
||||
const itemsPerPage = 25;
|
||||
const itemsPage = ref(parseInt((route.query.page as string) || "1"));
|
||||
|
||||
const headers = [
|
||||
{ text: "Username", value: "username", sortable: true },
|
||||
{ text: "Display name", value: "display_name", sortable: true },
|
||||
{ text: "First name", value: "first_name", sortable: true },
|
||||
{ text: "Last name", value: "last_name", sortable: true },
|
||||
{ text: "Email", value: "email", sortable: true },
|
||||
{ text: "Phone", value: "phone", sortable: true },
|
||||
{ text: "Joined", value: "created_at", sortable: true },
|
||||
// { text: "Last logged in", value: "lastAttended", width: 200},
|
||||
{ text: "Actions", value: "actions" },
|
||||
];
|
||||
|
||||
const items = ref([]);
|
||||
const formLoading = ref(false);
|
||||
const serverItemsLength = ref(0);
|
||||
const serverOptions = ref({
|
||||
page: 1,
|
||||
rowsPerPage: 25,
|
||||
sortBy: null,
|
||||
sortType: null,
|
||||
/**
|
||||
* Watch if page number changes.
|
||||
*/
|
||||
watch(itemsPage, () => {
|
||||
handleLoad();
|
||||
});
|
||||
|
||||
const handleRowClick = (item) => {
|
||||
router.push({ name: "dashboard-user-edit", params: { id: item.id } });
|
||||
/**
|
||||
* Handle searching for item.
|
||||
*/
|
||||
const handleSearch = () => {
|
||||
itemsPage.value = 1;
|
||||
handleLoad();
|
||||
};
|
||||
|
||||
const loadFromServer = async () => {
|
||||
formLoading.value = true;
|
||||
/**
|
||||
* Handle user selecting option in action button.
|
||||
*
|
||||
* @param {Event} item The event item.
|
||||
* @param option
|
||||
*/
|
||||
const handleActionButton = (item: Event, option: string): void => {
|
||||
if (option.length == 0) {
|
||||
handleEdit(item);
|
||||
} else if (option.toLowerCase() == "delete") {
|
||||
handleDelete(item);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle loading the page and list
|
||||
*/
|
||||
const handleLoad = async () => {
|
||||
itemsLoading.value = true;
|
||||
items.value = [];
|
||||
itemsTotal.value = 0;
|
||||
|
||||
updateRouterParams(router, {
|
||||
search: itemSearch.value,
|
||||
page: itemsPage.value == 1 ? "" : itemsPage.value.toString(),
|
||||
});
|
||||
|
||||
try {
|
||||
let params = {};
|
||||
if (serverOptions.value.sortBy) {
|
||||
params["sort"] = serverOptions.value.sortBy;
|
||||
if (
|
||||
serverOptions.value.sortType &&
|
||||
serverOptions.value.sortType === "desc"
|
||||
) {
|
||||
params["sort"] = "-" + params["sort"];
|
||||
}
|
||||
let params = {
|
||||
page: itemsPage.value,
|
||||
limit: itemsPerPage,
|
||||
};
|
||||
|
||||
if (itemSearch.value.length > 0) {
|
||||
params[
|
||||
"filter"
|
||||
] = `title:${itemSearch.value},OR,content:${itemSearch.value}`;
|
||||
}
|
||||
|
||||
params["page"] = serverOptions.value.page;
|
||||
params["limit"] = serverOptions.value.rowsPerPage;
|
||||
|
||||
let res = await api.get({
|
||||
let result = await api.get({
|
||||
url: "/users",
|
||||
params: params,
|
||||
});
|
||||
items.value = res.data.users;
|
||||
|
||||
const userCollection = getApiResultData<UserCollection>(result);
|
||||
items.value = userCollection.users;
|
||||
|
||||
items.value.forEach((row) => {
|
||||
if (row.created_at !== "undefined") {
|
||||
@@ -96,44 +159,22 @@ const loadFromServer = async () => {
|
||||
}
|
||||
});
|
||||
|
||||
serverItemsLength.value = res.data.total;
|
||||
itemsTotal.value = userCollection.total;
|
||||
} catch (err) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
formLoading.value = false;
|
||||
itemsLoading.value = false;
|
||||
};
|
||||
|
||||
loadFromServer();
|
||||
|
||||
watch(
|
||||
serverOptions,
|
||||
() => {
|
||||
loadFromServer();
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
const headerItemClassNameFunction = (header) => {
|
||||
if (["position", "actions"].includes(header.value))
|
||||
return "easy-data-table-cell-center";
|
||||
return "";
|
||||
};
|
||||
|
||||
const bodyItemClassNameFunction = (column) => {
|
||||
if (["position", "actions"].includes(column))
|
||||
return "easy-data-table-cell-center";
|
||||
return "";
|
||||
};
|
||||
|
||||
const handleEdit = (user) => {
|
||||
const handleEdit = (user: User) => {
|
||||
router.push({ name: "dashboard-user-edit", params: { id: user.id } });
|
||||
};
|
||||
|
||||
const handleDelete = async (user) => {
|
||||
const handleDelete = async (user: User) => {
|
||||
let result = await openDialog(DialogConfirm, {
|
||||
title: "Delete User?",
|
||||
text: `Are you sure you want to delete the user <strong>${user.username}</strong>?`,
|
||||
text: `Are you sure you want to delete the user <strong>${user.display_name}</strong>?`,
|
||||
cancel: {
|
||||
type: "secondary",
|
||||
label: "Cancel",
|
||||
@@ -147,7 +188,7 @@ const handleDelete = async (user) => {
|
||||
if (result == true) {
|
||||
try {
|
||||
await api.delete(`users${user.id}`);
|
||||
loadFromServer();
|
||||
handleLoad();
|
||||
|
||||
useToastStore().addToast({
|
||||
title: "User Deleted",
|
||||
@@ -163,6 +204,33 @@ const handleDelete = async (user) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleLoad();
|
||||
</script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
<style lang="scss">
|
||||
.page-dashboard-user-list {
|
||||
.toolbar-search {
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
// .table tr {
|
||||
// td:first-of-type,
|
||||
// td:nth-of-type(2) {
|
||||
// word-break: break-all;
|
||||
// }
|
||||
|
||||
// td:not(:first-of-type) {
|
||||
// white-space: nowrap;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
.page-dashboard-user-list {
|
||||
.toolbar-search {
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>Hey {{ $user?->username }},</h2></td>
|
||||
<td><h2>Hey {{ $user?->display_name }},</h2></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Hey {{ $user?->username }},
|
||||
Hey {{ $user?->display_name }},
|
||||
|
||||
We just need to confirm that this is your new email address.
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>Yo {{ $user?->username }}</h2></td>
|
||||
<td><h2>Yo {{ $user?->display_name }}</h2></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 2rem">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Yo {{ $user?->username }}
|
||||
Yo {{ $user?->display_name }}
|
||||
|
||||
Just a quick word that your email has been changed to {{ $new_email }}.
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>Yo {{ $user?->username }}</h2></td>
|
||||
<td><h2>Yo {{ $user?->display_name }}</h2></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 2rem">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Yo {{ $user?->username }}
|
||||
Yo {{ $user?->display_name }}
|
||||
|
||||
Just a quick word that your password has been changed.
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>Welcome {{ $user?->username }},</h2></td>
|
||||
<td><h2>Welcome {{ $user?->display_name }},</h2></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Welcome {{ $user?->username }},
|
||||
Welcome {{ $user?->display_name }},
|
||||
|
||||
We've heard you would like to try out our workshops and courses!
|
||||
Before we can let you loose on our website, we need to make sure you are a real person and not a pesky robot or cat.
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>Yo {{ $user?->username }}</h2></td>
|
||||
<td><h2>Yo {{ $user?->display_name }}</h2></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Yo {{ $user?->username }}
|
||||
Yo {{ $user?->display_name }}
|
||||
|
||||
We all forget things sometimes! But you can reset your password typing the following into your browser https://www.stemmechanics.com.au/reset-password and entering the following code:
|
||||
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
lang="{{ str_replace('_', '-', app()->getLocale()) }}"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:v="urn:schemas-microsoft-com:vml"
|
||||
xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||
>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>STEMMechanics - Forgot Password</title>
|
||||
<link
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;700;800&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<!--[if gte mso 9]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG />
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Nunito:wght@400;700;800&display=swap");
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table
|
||||
cellspacing="0"
|
||||
cellpadding="0"
|
||||
border="0"
|
||||
role="presentation"
|
||||
style="
|
||||
width: 100%;
|
||||
padding: 2rem;
|
||||
font-size: 1.1rem;
|
||||
color: #000000;
|
||||
font-family: Nunito, Arial, Helvetica, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
"
|
||||
>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.stemmechanics.com.au/">
|
||||
<img
|
||||
alt="STEMMechanics Logo"
|
||||
src="{{ $message->embed(public_path('assets').'/logo.webp') }}"
|
||||
width="400"
|
||||
height="62"
|
||||
/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
@if (count($usernames) > 2)
|
||||
<h2>Yo {{ $usernames[0] }}, {{ $usernames[1] }}, or is it {{ $usernames[count($usernames)-1] }}?</h2>
|
||||
@elseif (count($usernames) > 1)
|
||||
<h2>Yo {{ $usernames[0] }}, or is it {{ $usernames[1] }}?</h2>
|
||||
@else
|
||||
<h2>Yo {{ $usernames[0] }},</h2>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 2rem;">
|
||||
@if (count($usernames) == 1)
|
||||
Guess what, your username is <strong>{{ $usernames[0] }}</strong>.
|
||||
@else
|
||||
We have the following usernames registered to this email address:
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 2rem;">
|
||||
<ul>
|
||||
@foreach($usernames as $username)
|
||||
<li>{{ $username }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
align="center"
|
||||
style="
|
||||
font-size: 90%;
|
||||
text-align: center;
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
border-top: 1px solid #ddd;
|
||||
"
|
||||
>
|
||||
Need help or got feedback?
|
||||
<a href="https://www.stemmechanics.com.au/contact"
|
||||
>Contact us</a
|
||||
>
|
||||
or touch base at
|
||||
<a href="https://twitter.com/stemmechanics"
|
||||
>@stemmechanics</a
|
||||
>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
align="center"
|
||||
style="
|
||||
font-size: 80%;
|
||||
text-align: center;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 2rem;
|
||||
"
|
||||
>
|
||||
Sent by STEMMechanics ·
|
||||
<a href="https://www.stemmechanics.com.au/"
|
||||
>Visit our Website</a
|
||||
>
|
||||
·
|
||||
<a href="https://twitter.com/stemmechanics"
|
||||
>@stemmechanics</a
|
||||
><br />PO Box 36, Edmonton, QLD 4869, Australia
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
@if (count($usernames) > 2)
|
||||
Yo {{ $usernames[0] }}, {{ $usernames[1] }}, or is it {{ $usernames[count($usernames)-1] }}?
|
||||
@elseif (count($usernames) > 1)
|
||||
Yo {{ $usernames[0] }} or is it {{ $usernames[1] }}?
|
||||
@else
|
||||
Yo {{ $usernames[0] }},
|
||||
@endif
|
||||
|
||||
@if (count($usernames) == 1)
|
||||
Guess what, your username is {{ $usernames[0] }}.
|
||||
@else
|
||||
We have the following usernames registered to this email address:
|
||||
|
||||
@foreach($usernames as $username)
|
||||
- {{ $username }}
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
Need help or got feedback? Contact us at https://www.stemmechanics.com.au/contact or touch base on twitter at @stemmechanics
|
||||
|
||||
--
|
||||
Sent by STEMMechanics
|
||||
https://www.stemmechanics.com.au/
|
||||
PO Box 36, Edmonton, QLD 4869, Australia
|
||||
@@ -1,116 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
lang="{{ str_replace('_', '-', app()->getLocale()) }}"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:v="urn:schemas-microsoft-com:vml"
|
||||
xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||
>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>STEMMechanics - Forgot Password</title>
|
||||
<link
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;700;800&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<!--[if gte mso 9]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG />
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Nunito:wght@400;700;800&display=swap");
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table
|
||||
cellspacing="0"
|
||||
cellpadding="0"
|
||||
border="0"
|
||||
role="presentation"
|
||||
style="
|
||||
width: 100%;
|
||||
padding: 2rem;
|
||||
font-size: 1.1rem;
|
||||
color: #000000;
|
||||
font-family: Nunito, Arial, Helvetica, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
"
|
||||
>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.stemmechanics.com.au/">
|
||||
<img
|
||||
alt="STEMMechanics Logo"
|
||||
src="{{ $message->embed(public_path('assets').'/logo.webp') }}"
|
||||
width="400"
|
||||
height="62"
|
||||
/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<p></p>
|
||||
<td><h2>Howdy there,</h2></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 2rem">
|
||||
At your request, you are now subscribed to our newsletter giving you tips, tricks and letting you know when new workshops are scheduled.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 2rem">
|
||||
If this wasn't you, you can unsubscribe by visiting <a href="https://www.stemmechanics.com.au/unsubscribe?email={{ $email }}">stemmechanics.com.au/unsubscribe</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
align="center"
|
||||
style="
|
||||
font-size: 90%;
|
||||
text-align: center;
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
border-top: 1px solid #ddd;
|
||||
"
|
||||
>
|
||||
Need help or got feedback?
|
||||
<a href="https://www.stemmechanics.com.au/contact"
|
||||
>Contact us</a
|
||||
>
|
||||
or touch base at
|
||||
<a href="https://twitter.com/stemmechanics"
|
||||
>@stemmechanics</a
|
||||
>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
align="center"
|
||||
style="
|
||||
font-size: 80%;
|
||||
text-align: center;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 2rem;
|
||||
"
|
||||
>
|
||||
Sent by STEMMechanics ·
|
||||
<a href="https://www.stemmechanics.com.au/"
|
||||
>Visit our Website</a
|
||||
>
|
||||
·
|
||||
<a href="https://twitter.com/stemmechanics"
|
||||
>@stemmechanics</a
|
||||
><br />PO Box 36, Edmonton, QLD 4869, Australia
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +0,0 @@
|
||||
Howdy there,
|
||||
|
||||
At your request, you are now subscribed to our newsletter giving you tips, tricks and letting you know when new workshops are scheduled.
|
||||
|
||||
If this wasn't you, you can unsubscribe by visiting the following URL in your browser:
|
||||
|
||||
https://www.stemmechanics.com.au/unsubscribe
|
||||
|
||||
Need help or got feedback? Contact us at https://www.stemmechanics.com.au/contact or touch base on twitter at @stemmechanics
|
||||
|
||||
--
|
||||
Sent by STEMMechanics
|
||||
https://www.stemmechanics.com.au/
|
||||
PO Box 36, Edmonton, QLD 4869, Australia
|
||||
@@ -1,111 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
lang="{{ str_replace('_', '-', app()->getLocale()) }}"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:v="urn:schemas-microsoft-com:vml"
|
||||
xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||
>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>STEMMechanics - Forgot Password</title>
|
||||
<link
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;700;800&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<!--[if gte mso 9]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG />
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Nunito:wght@400;700;800&display=swap");
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table
|
||||
cellspacing="0"
|
||||
cellpadding="0"
|
||||
border="0"
|
||||
role="presentation"
|
||||
style="
|
||||
width: 100%;
|
||||
padding: 2rem;
|
||||
font-size: 1.1rem;
|
||||
color: #000000;
|
||||
font-family: Nunito, Arial, Helvetica, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
"
|
||||
>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.stemmechanics.com.au/">
|
||||
<img
|
||||
alt="STEMMechanics Logo"
|
||||
src="{{ $message->embed(public_path('assets').'/logo.webp') }}"
|
||||
width="400"
|
||||
height="62"
|
||||
/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<p></p>
|
||||
<td><h2>Howdy there,</h2></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 2rem">
|
||||
At your request, you are now unsubscribed from our newsletter.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
align="center"
|
||||
style="
|
||||
font-size: 90%;
|
||||
text-align: center;
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
border-top: 1px solid #ddd;
|
||||
"
|
||||
>
|
||||
Need help or got feedback?
|
||||
<a href="https://www.stemmechanics.com.au/contact"
|
||||
>Contact us</a
|
||||
>
|
||||
or touch base at
|
||||
<a href="https://twitter.com/stemmechanics"
|
||||
>@stemmechanics</a
|
||||
>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
align="center"
|
||||
style="
|
||||
font-size: 80%;
|
||||
text-align: center;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 2rem;
|
||||
"
|
||||
>
|
||||
Sent by STEMMechanics ·
|
||||
<a href="https://www.stemmechanics.com.au/"
|
||||
>Visit our Website</a
|
||||
>
|
||||
·
|
||||
<a href="https://twitter.com/stemmechanics"
|
||||
>@stemmechanics</a
|
||||
><br />PO Box 36, Edmonton, QLD 4869, Australia
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,10 +0,0 @@
|
||||
Howdy there,
|
||||
|
||||
At your request, you have been unsubscribed from our newsletter.
|
||||
|
||||
Need help or got feedback? Contact us at https://www.stemmechanics.com.au/contact or touch base on twitter at @stemmechanics
|
||||
|
||||
--
|
||||
Sent by STEMMechanics
|
||||
https://www.stemmechanics.com.au/
|
||||
PO Box 36, Edmonton, QLD 4869, Australia
|
||||
Reference in New Issue
Block a user