Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions modules/nuc_api/utils/use_api_errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,44 @@ import type {
} from 'nucleify'
import { useAtomicToast } from 'nucleify'

function apiFailureToError(error: unknown): Error {
if (error instanceof Error) return error
if (typeof error === 'string') return new Error(error)
if (error && typeof error === 'object' && 'data' in error) {
const data = (error as { data: unknown }).data
if (data && typeof data === 'object' && data !== null) {
const d = data as Record<string, unknown>
if (typeof d.error === 'string') return new Error(d.error)
if (typeof d.message === 'string') return new Error(d.message)
if (d.error != null) return new Error(String(d.error))
}
const status = (error as { response?: { status?: number } }).response?.status
if (status != null) return new Error(`Request failed (${status})`)
}
return new Error('Request failed')
}

export function useApiErrors(): UseApiErrorsInterface {
const { flashToast }: UseToastInterface = useAtomicToast()

function apiErrors(error: ErrorResponseInterface | Error | unknown): void {
if (error && typeof error === 'object' && 'data' in error) {
const data = error.data as { error?: string; errors?: string }
const data = error.data as {
error?: string
errors?: string | Record<string, string[]>
}

if (data?.error) {
flashToast(data.error, 'error')
} else if (data?.errors) {
flashToast(data.errors, 'error')
setTimeout(() => {
document
.querySelector('.p-toast-summary')
?.classList.add('validation-errors')
})
if (typeof data.errors !== 'string') {
setTimeout(() => {
document
.querySelector('.p-toast-summary')
?.classList.add('validation-errors')
})
}
} else if (error) {
if (error instanceof Error) {
flashToast(error.message, 'error')
Expand All @@ -33,7 +55,7 @@ export function useApiErrors(): UseApiErrorsInterface {
flashToast('An unknown error occurred', 'error')
}

throw error
throw apiFailureToError(error)
}

if (error instanceof Error) {
Expand Down
4 changes: 2 additions & 2 deletions modules/nuc_dialog/types/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import type {
} from './functions'

export interface NucDialogInterface extends DialogInterface {
entity?: ObjectType
action?: ActionType
entity?: AdTypeType
action?: ActionType | 'share'
title?: string
fields?: Array<{
name: string
Expand Down
31 changes: 31 additions & 0 deletions modules/nuc_share/NucShare.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useEffect } from 'react'

import { AdPopover } from 'atomic'

import { useShareRequests } from './atomic/utils/requests'
import { isMobile } from '../nuc_media/utils/is_mobile'
import { NucSharePopover } from './components/share-popover'
import './_index.scss'

export function NucShare({ position }) {
const { loading, loadAll } = useShareRequests()

useEffect(() => {
loadAll()
}, [loadAll])

if (loading) return null

return (
<AdPopover
dismissable
icon="prime:inbox"
position={position}
popoverClass="share-inbox-popover"
buttonText={isMobile() ? '' : 'Share Inbox'}
buttonClass="share-inbox-toggle"
>
<NucSharePopover />
</AdPopover>
)
}
9 changes: 9 additions & 0 deletions modules/nuc_share/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# <img src="https://nucleify.io/favicon.ico" width="17" height="17" /> &nbsp; nuc_share

Module that contains entity sharing functions.

<br>

<h2> &nbsp; <img src="https://nucleify.io/img/technologies/github.svg" width="25"> &nbsp; Contributors </h2> <br>

<a href="https://github.com/SzymCode" target="_blank"><img src="https://nucleify.io/img/contributors/szymcode.svg" width="30" height="30" /></a>
20 changes: 20 additions & 0 deletions modules/nuc_share/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.share-inbox-popover {
right: 0;
width: 100%;
height: 100%;
z-index: 100;
border-radius: 0;
overflow: hidden;
bottom: 0 !important;

.p-popover-content {
height: 100%;
padding: 0;
}

@media (min-width: $lg) {
height: 100vh;
max-width: 450px;
margin-left: 3px;
}
}
128 changes: 128 additions & 0 deletions modules/nuc_share/app/Http/Controllers/ShareController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

namespace App\Http\Controllers;

use App\Services\ShareService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ShareController extends Controller
{
private ShareService $service;

public function __construct(ShareService $service)
{
$this->service = $service;
}

/**
* Create share request
*/
public function create(Request $request): JsonResponse
{
try {
$validated = $request->validate([
'entity_ids' => 'required|array',
'entity_ids.*' => 'required|integer',
'entity_type' => 'required|string',
'user_ids' => 'required|array',
'user_ids.*' => 'required|integer|exists:users,id',
]);

$result = $this->service->createShareRequest(
$validated['entity_ids'],
$validated['entity_type'],
$validated['user_ids']
);

return response()->json($result);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}

/**
* Get received share requests
*/
public function received(): JsonResponse
{
try {
$requests = $this->service->getReceivedRequests();

return response()->json(['data' => $requests]);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}

/**
* Get sent share requests
*/
public function sent(): JsonResponse
{
try {
$requests = $this->service->getSentRequests();

return response()->json(['data' => $requests]);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}

/**
* Get pending requests count
*/
public function count(): JsonResponse
{
try {
$count = $this->service->getPendingCount();

return response()->json(['count' => $count]);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}

/**
* Accept share request
*/
public function accept(int $id): JsonResponse
{
try {
$result = $this->service->acceptRequest($id);

return response()->json($result);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 400);
}
}

/**
* Reject share request
*/
public function reject(int $id): JsonResponse
{
try {
$result = $this->service->rejectRequest($id);

return response()->json($result);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 400);
}
}

/**
* Cancel sent share request
*/
public function cancel(int $id): JsonResponse
{
try {
$result = $this->service->cancelRequest($id);

return response()->json($result);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 400);
}
}
}
46 changes: 46 additions & 0 deletions modules/nuc_share/app/Models/ShareRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class ShareRequest extends Model
{
protected $fillable = [
'sender_id',
'receiver_id',
'entity_type',
'entity_ids',
'status',
];

protected $casts = [
'entity_ids' => 'array',
];

public function sender(): BelongsTo
{
return $this->belongsTo(User::class, 'sender_id');
}

public function receiver(): BelongsTo
{
return $this->belongsTo(User::class, 'receiver_id');
}

public function scopePending($query)
{
return $query->where('status', 'pending');
}

public function scopeForReceiver($query, int $userId)
{
return $query->where('receiver_id', $userId);
}

public function scopeForSender($query, int $userId)
{
return $query->where('sender_id', $userId);
}
}
Loading