Skip to content

Commit

Permalink
Add User Create, Edit & Delete Action
Browse files Browse the repository at this point in the history
  • Loading branch information
lcharette committed Dec 27, 2024
1 parent 16a6d30 commit 8237522
Show file tree
Hide file tree
Showing 24 changed files with 711 additions and 110 deletions.
12 changes: 12 additions & 0 deletions packages/sprinkle-admin/app/assets/composables/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
// Dashboard
export { useDashboardApi } from './useDashboardApi'

// Group
export { useGroupApi } from './useGroupApi'
export { useGroupCreateApi } from './useGroupCreateApi'
export { useGroupDeleteApi } from './useGroupDeleteApi'
export { useGroupEditApi } from './useGroupEditApi'

// Permission
export { usePermissionApi } from './usePermissionApi'

// Role
export { useRoleApi } from './useRoleApi'

// User
export { useUserApi } from './useUserApi'
export { useUserCreateApi } from './useUserCreateApi'
export { useUserDeleteApi } from './useUserDeleteApi'
export { useUserEditApi } from './useUserEditApi'
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ export function useUserApi(route: any) {
{ immediate: true }
)

return { user, error, loading }
return { user, error, loading, fetchApi }
}
46 changes: 46 additions & 0 deletions packages/sprinkle-admin/app/assets/composables/useUserCreateApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ref } from 'vue'
import axios from 'axios'
import { Severity, type AlertInterface } from '@userfrosting/sprinkle-core/interfaces'
import type { UserCreateForm, UserCreateResponse } from '../interfaces'

// TODO : Add validation
// 'schema://requests/user/create.yaml'

/**
* API Composable
*/
export function useUserCreateApi() {
const apiLoading = ref<Boolean>(false)
const apiError = ref<AlertInterface | null>(null)

async function submitUserCreate(data: UserCreateForm) {
apiLoading.value = true
apiError.value = null
return axios
.post<UserCreateResponse>('/api/users', data)
.then((response) => {
return {
success: response.data.success,
message: response.data.message,
user: response.data.user
}
})
.catch((err) => {
apiError.value = {
...{
description: 'An error as occurred',
style: Severity.Danger,
closeBtn: true
},
...err.response.data
}

throw apiError.value
})
.finally(() => {
apiLoading.value = false
})
}

return { submitUserCreate, apiLoading, apiError }
}
43 changes: 43 additions & 0 deletions packages/sprinkle-admin/app/assets/composables/useUserDeleteApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ref } from 'vue'
import axios from 'axios'
import { Severity, type AlertInterface } from '@userfrosting/sprinkle-core/interfaces'
import type { UserDeleteResponse } from '../interfaces'

/**
* API Composable
*/
export function useUserDeleteApi() {
// Form data
const loadingState = ref<Boolean>(false)
const apiError = ref<AlertInterface | null>(null)

async function deleteUser(user_name: string) {
loadingState.value = true
apiError.value = null
return axios
.delete<UserDeleteResponse>('/api/users/u/' + user_name)
.then((response) => {
return {
success: response.data.success,
message: response.data.message
}
})
.catch((err) => {
apiError.value = {
...{
description: 'An error as occurred',
style: Severity.Danger,
closeBtn: true
},
...err.response.data
}

throw apiError.value
})
.finally(() => {
loadingState.value = false
})
}

return { loadingState, apiError, deleteUser }
}
46 changes: 46 additions & 0 deletions packages/sprinkle-admin/app/assets/composables/useUserEditApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ref } from 'vue'
import axios from 'axios'
import { Severity, type AlertInterface } from '@userfrosting/sprinkle-core/interfaces'
import type { UserEditForm, UserEditResponse } from '../interfaces'

// TODO : Add validation
// 'schema://requests/user/edit-info.yaml'

/**
* API Composable
*/
export function useUserEditApi() {
const apiLoading = ref<Boolean>(false)
const apiError = ref<AlertInterface | null>(null)

async function submitUserEdit(user_name: string, data: UserEditForm) {
apiLoading.value = true
apiError.value = null
return axios
.put<UserEditResponse>('/api/users/u/' + user_name, data)
.then((response) => {
return {
success: response.data.success,
message: response.data.message,
user: response.data.user
}
})
.catch((err) => {
apiError.value = {
...{
description: 'An error as occurred',
style: Severity.Danger,
closeBtn: true
},
...err.response.data
}

throw apiError.value
})
.finally(() => {
apiLoading.value = false
})
}

return { submitUserEdit, apiLoading, apiError }
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { GroupInterface } from '@userfrosting/sprinkle-account/interfaces'

/**
* Interfaces - What the API expects and what it returns
*/
Expand All @@ -11,5 +13,5 @@ export interface GroupCreateForm {
export interface GroupCreateResponse {
success: boolean
message: string
group: GroupCreateForm
group: GroupInterface
}
19 changes: 19 additions & 0 deletions packages/sprinkle-admin/app/assets/interfaces/UserCreateApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { UserInterface } from '@userfrosting/sprinkle-account/interfaces'

/**
* Interfaces - What the API expects and what it returns
*/
export interface UserCreateForm {
user_name: string
group_id: number
first_name: string
last_name: string
email: string
locale: string
}

export interface UserCreateResponse {
success: boolean
message: string
user: UserInterface
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface UserDeleteResponse {
success: boolean
message: string
}
19 changes: 19 additions & 0 deletions packages/sprinkle-admin/app/assets/interfaces/UserEditApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { UserInterface } from '@userfrosting/sprinkle-account/interfaces'

/**
* Interfaces - What the API expects and what it returns
*/
export interface UserEditForm {
user_name: string
group_id: number | null
first_name: string
last_name: string
email: string
locale: string
}

export interface UserEditResponse {
success: boolean
message: string
user: UserInterface
}
3 changes: 3 additions & 0 deletions packages/sprinkle-admin/app/assets/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ export type { GroupEditForm, GroupEditResponse } from './GroupEditApi'
export type { PermissionApi } from './PermissionApi'
export type { RoleApi } from './RoleApi'
export type { UserApi } from './UserApi'
export type { UserCreateForm, UserCreateResponse } from './UserCreateApi'
export type { UserDeleteResponse } from './UserDeleteApi'
export type { UserEditForm, UserEditResponse } from './UserEditApi'
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use UserFrosting\Alert\AlertStream;
use UserFrosting\Config\Config;
use UserFrosting\Fortress\RequestSchema;
use UserFrosting\Fortress\RequestSchema\RequestSchemaInterface;
use UserFrosting\Fortress\Transformer\RequestDataTransformer;
use UserFrosting\Fortress\Validator\ServerSideValidator;
use UserFrosting\I18n\Translator;
use UserFrosting\Sprinkle\Account\Authenticate\Authenticator;
use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\GroupInterface;
use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface;
Expand Down Expand Up @@ -59,7 +59,7 @@ class UserCreateAction
* @param \UserFrosting\Event\EventDispatcher $eventDispatcher
*/
public function __construct(
protected AlertStream $alert,
protected Translator $translator,
protected Authenticator $authenticator,
protected Config $config,
protected Connection $db,
Expand All @@ -86,8 +86,12 @@ public function __construct(
public function __invoke(Request $request, Response $response): Response
{
$this->validateAccess();
$this->handle($request);
$payload = json_encode([], JSON_THROW_ON_ERROR);
$user = $this->handle($request)->toArray();
$payload = json_encode([
'success' => true,
'message' => $this->translator->translate('USER.CREATED', $user),
'user' => $user,
], JSON_THROW_ON_ERROR);
$response->getBody()->write($payload);

return $response->withHeader('Content-Type', 'application/json');
Expand All @@ -97,8 +101,10 @@ public function __invoke(Request $request, Response $response): Response
* Handle the request.
*
* @param Request $request
*
* @return UserInterface
*/
protected function handle(Request $request): void
protected function handle(Request $request): UserInterface
{
// Get POST parameters.
$params = (array) $request->getParsedBody();
Expand Down Expand Up @@ -156,7 +162,7 @@ protected function handle(Request $request): void
$this->userValidation->validate($user);

// Ready to save
$this->db->transaction(function () use ($user, $data, $currentUser) {
$user = $this->db->transaction(function () use ($user, $data, $currentUser) {
// Store new user to database
$user->save();

Expand All @@ -175,8 +181,10 @@ protected function handle(Request $request): void
$this->passwordEmail->send($user);
}

$this->alert->addMessage('success', 'USER.CREATED');
return $user;
});

return $user;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
use Illuminate\Database\Connection;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use UserFrosting\Alert\AlertStream;
use UserFrosting\Config\Config;
use UserFrosting\I18n\Translator;
use UserFrosting\Sprinkle\Account\Authenticate\Authenticator;
use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface;
use UserFrosting\Sprinkle\Account\Exceptions\AccountException;
Expand Down Expand Up @@ -47,7 +47,7 @@ class UserDeleteAction
* Inject dependencies.
*/
public function __construct(
protected AlertStream $alert,
protected Translator $translator,
protected Authenticator $authenticator,
protected Config $config,
protected Connection $db,
Expand All @@ -65,7 +65,10 @@ public function __construct(
public function __invoke(UserInterface $user, Response $response): Response
{
$this->handle($user);
$payload = json_encode([], JSON_THROW_ON_ERROR);
$payload = json_encode([
'success' => true,
'message' => $this->translator->translate('DELETION_SUCCESSFUL', $user->toArray()),
], JSON_THROW_ON_ERROR);
$response->getBody()->write($payload);

return $response->withHeader('Content-Type', 'application/json');
Expand Down Expand Up @@ -107,10 +110,6 @@ protected function handle(UserInterface $user): void
'user_id' => $currentUser->id,
]);
});

$this->alert->addMessage('success', 'DELETION_SUCCESSFUL', [
'user_name' => $username,
]);
}

/**
Expand Down
Loading

0 comments on commit 8237522

Please sign in to comment.