qr code generator

This commit is contained in:
Čarodej
2022-01-19 09:00:54 +01:00
parent 09449539fa
commit 89e886b40c
9 changed files with 104 additions and 16 deletions

View File

@@ -64,7 +64,7 @@
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=7f623c8a4002f17eecef", "/chunks/plan-settings.js": "/chunks/plan-settings.js?id=7f623c8a4002f17eecef",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=7eff560fea52770a642f", "/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=7eff560fea52770a642f",
"/chunks/plans.js": "/chunks/plans.js?id=293e7e8d59da542a9710", "/chunks/plans.js": "/chunks/plans.js?id=293e7e8d59da542a9710",
"/chunks/platform.js": "/chunks/platform.js?id=1cd6e357b28006f2c0d0", "/chunks/platform.js": "/chunks/platform.js?id=995d87d771ab3755300d",
"/chunks/platform~chunks/shared.js": "/chunks/platform~chunks/shared.js?id=eb52b5029ab2132cc7a8", "/chunks/platform~chunks/shared.js": "/chunks/platform~chunks/shared.js?id=eb52b5029ab2132cc7a8",
"/chunks/platform~chunks/shared~chunks/shared-with-me~chunks/team-folders.js": "/chunks/platform~chunks/shared~chunks/shared-with-me~chunks/team-folders.js?id=ca9ca67afd5839597647", "/chunks/platform~chunks/shared~chunks/shared-with-me~chunks/team-folders.js": "/chunks/platform~chunks/shared~chunks/shared-with-me~chunks/team-folders.js?id=ca9ca67afd5839597647",
"/chunks/profile.js": "/chunks/profile.js?id=8688d9c7ff850e6989e6", "/chunks/profile.js": "/chunks/profile.js?id=8688d9c7ff850e6989e6",
@@ -1031,5 +1031,24 @@
"/chunks/platform~chunks/shared.ea85f5cfae919a076286.hot-update.js": "/chunks/platform~chunks/shared.ea85f5cfae919a076286.hot-update.js", "/chunks/platform~chunks/shared.ea85f5cfae919a076286.hot-update.js": "/chunks/platform~chunks/shared.ea85f5cfae919a076286.hot-update.js",
"/chunks/platform~chunks/shared.84634b8388c060112c1b.hot-update.js": "/chunks/platform~chunks/shared.84634b8388c060112c1b.hot-update.js", "/chunks/platform~chunks/shared.84634b8388c060112c1b.hot-update.js": "/chunks/platform~chunks/shared.84634b8388c060112c1b.hot-update.js",
"/chunks/platform~chunks/shared.bad4a30908dd6677cf57.hot-update.js": "/chunks/platform~chunks/shared.bad4a30908dd6677cf57.hot-update.js", "/chunks/platform~chunks/shared.bad4a30908dd6677cf57.hot-update.js": "/chunks/platform~chunks/shared.bad4a30908dd6677cf57.hot-update.js",
"/chunks/platform~chunks/shared.7344fdb67d1d2c382527.hot-update.js": "/chunks/platform~chunks/shared.7344fdb67d1d2c382527.hot-update.js" "/chunks/platform~chunks/shared.7344fdb67d1d2c382527.hot-update.js": "/chunks/platform~chunks/shared.7344fdb67d1d2c382527.hot-update.js",
"/chunks/platform.9935a3fb40cb1a6c789a.hot-update.js": "/chunks/platform.9935a3fb40cb1a6c789a.hot-update.js",
"/chunks/platform.5b66195d24b17de302b0.hot-update.js": "/chunks/platform.5b66195d24b17de302b0.hot-update.js",
"/chunks/platform.79d4290d27451ea79ccb.hot-update.js": "/chunks/platform.79d4290d27451ea79ccb.hot-update.js",
"/chunks/platform.7a437caaafe827fe07cc.hot-update.js": "/chunks/platform.7a437caaafe827fe07cc.hot-update.js",
"/chunks/platform.7187684ae9b0faa2a7f1.hot-update.js": "/chunks/platform.7187684ae9b0faa2a7f1.hot-update.js",
"/chunks/platform.bb37cb7d93d79c9e6a5a.hot-update.js": "/chunks/platform.bb37cb7d93d79c9e6a5a.hot-update.js",
"/chunks/platform.74e0ff5ead757ff49708.hot-update.js": "/chunks/platform.74e0ff5ead757ff49708.hot-update.js",
"/chunks/platform.ea1c3e65c26938bba387.hot-update.js": "/chunks/platform.ea1c3e65c26938bba387.hot-update.js",
"/chunks/platform.54c9d7a94fbee65e2da7.hot-update.js": "/chunks/platform.54c9d7a94fbee65e2da7.hot-update.js",
"/chunks/platform.1c70eca57aee433b8aa9.hot-update.js": "/chunks/platform.1c70eca57aee433b8aa9.hot-update.js",
"/chunks/platform.42f9d03cdae6611c56cd.hot-update.js": "/chunks/platform.42f9d03cdae6611c56cd.hot-update.js",
"/chunks/platform.ff639c6b90300df114a8.hot-update.js": "/chunks/platform.ff639c6b90300df114a8.hot-update.js",
"/chunks/platform.67a4de439a33f4a20333.hot-update.js": "/chunks/platform.67a4de439a33f4a20333.hot-update.js",
"/chunks/platform.a266c10be8a18abd0620.hot-update.js": "/chunks/platform.a266c10be8a18abd0620.hot-update.js",
"/chunks/platform.1cdf2801a1dc08744bfb.hot-update.js": "/chunks/platform.1cdf2801a1dc08744bfb.hot-update.js",
"/chunks/platform.59a13c955f76e3699f76.hot-update.js": "/chunks/platform.59a13c955f76e3699f76.hot-update.js",
"/chunks/platform.7a1f473c56b980ad30a0.hot-update.js": "/chunks/platform.7a1f473c56b980ad30a0.hot-update.js",
"/chunks/platform.2dff6a153cfe9e102eea.hot-update.js": "/chunks/platform.2dff6a153cfe9e102eea.hot-update.js",
"/chunks/platform.9fc0238e5466745ede6c.hot-update.js": "/chunks/platform.9fc0238e5466745ede6c.hot-update.js"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -59,7 +59,7 @@
</ValidationObserver> </ValidationObserver>
<!--Copy generated link--> <!--Copy generated link-->
<AppInputText v-if="isGeneratedShared" :title="$t('shared_form.label_share_vie_email')" class="px-6" :is-last="true"> <AppInputText v-if="isGeneratedShared" :title="$t('shared_form.label_share_vie_email')" :is-last="true">
<CopyShareLink :item="pickedItem" /> <CopyShareLink :item="pickedItem" />
</AppInputText> </AppInputText>
</PopupContent> </PopupContent>

View File

@@ -5,8 +5,11 @@
<!--Qr Code--> <!--Qr Code-->
<div v-if="pickedItem && activeSection === 'qr-code'"> <div v-if="pickedItem && activeSection === 'qr-code'">
<PopupContent> <PopupContent class="flex justify-center items-center">
<img src="/qr.png" alt="qr code" class="w-36 mx-auto"> <div v-if="! qrCode" class="relative my-8">
<Spinner />
</div>
<div v-if="qrCode" v-html="qrCode" class="my-5 overflow-hidden rounded-xl"></div>
</PopupContent> </PopupContent>
<PopupActions> <PopupActions>
@@ -155,6 +158,7 @@
import AppInputSwitch from "../Admin/AppInputSwitch" import AppInputSwitch from "../Admin/AppInputSwitch"
import AppInputText from "../Admin/AppInputText" import AppInputText from "../Admin/AppInputText"
import {required} from 'vee-validate/dist/rules' import {required} from 'vee-validate/dist/rules'
import Spinner from "../FilesView/Spinner"
import {events} from '/resources/js/bus' import {events} from '/resources/js/bus'
import {mapGetters} from 'vuex' import {mapGetters} from 'vuex'
import axios from 'axios' import axios from 'axios'
@@ -179,6 +183,7 @@
SwitchInput, SwitchInput,
ButtonBase, ButtonBase,
required, required,
Spinner,
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
@@ -215,6 +220,7 @@
shareOptions: undefined, shareOptions: undefined,
pickedItem: undefined, pickedItem: undefined,
emails: undefined, emails: undefined,
qrCode: undefined,
isConfirmedDestroy: false, isConfirmedDestroy: false,
canChangePassword: false, canChangePassword: false,
isMoreOptions: false, isMoreOptions: false,
@@ -223,6 +229,13 @@
} }
}, },
methods: { methods: {
getQrCode() {
axios.get(`/api/share/${this.shareOptions.token}/qr`)
.then(response => {
this.qrCode = response.data
})
.catch(() => this.$isSomethingWrong())
},
showSection(section = undefined) { showSection(section = undefined) {
this.activeSection = section this.activeSection = section
}, },
@@ -321,6 +334,9 @@
if (args.section) if (args.section)
this.activeSection = args.section this.activeSection = args.section
if (args.section === 'qr-code')
this.getQrCode()
this.canChangePassword = args.item.data.relationships.shared.data.attributes.protected this.canChangePassword = args.item.data.relationships.shared.data.attributes.protected
}) })

View File

@@ -24,6 +24,7 @@ use Domain\Browsing\Controllers\BrowseLatestFilesController;
use Domain\Browsing\Controllers\BrowseSharedItemsController; use Domain\Browsing\Controllers\BrowseSharedItemsController;
use Domain\Browsing\Controllers\BrowseTrashContentController; use Domain\Browsing\Controllers\BrowseTrashContentController;
use Domain\Homepage\Controllers\SendContactMessageController; use Domain\Homepage\Controllers\SendContactMessageController;
use Domain\Sharing\Controllers\GetShareLinkViaQrCodeController;
use App\Users\Controllers\Authentication\RegisterUserController; use App\Users\Controllers\Authentication\RegisterUserController;
// Pages // Pages
@@ -67,6 +68,7 @@ Route::group(['middleware' => ['auth:sanctum']], function () {
}); });
// Share // Share
Route::get('/share/{token}/qr', GetShareLinkViaQrCodeController::class);
Route::post('/share/{token}/email', ShareViaEmailController::class); Route::post('/share/{token}/email', ShareViaEmailController::class);
Route::apiResource('/share', ShareController::class); Route::apiResource('/share', ShareController::class);

View File

@@ -1,20 +1,20 @@
<?php <?php
namespace Domain\Invoices\Controllers; namespace Domain\Invoices\Controllers;
use App\Http\Controllers\Controller;
use App\Users\Actions\FormatUsageEstimatesAction;
use Domain\Settings\Models\Setting; use Domain\Settings\Models\Setting;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\Foundation\Application;
use App\Users\Actions\FormatUsageEstimatesAction;
use VueFileManager\Subscription\Domain\Transactions\Models\Transaction; use VueFileManager\Subscription\Domain\Transactions\Models\Transaction;
class GetInvoiceController extends Controller class GetInvoiceController extends Controller
{ {
public function __construct( public function __construct(
public FormatUsageEstimatesAction $formatUsageEstimates, public FormatUsageEstimatesAction $formatUsageEstimates,
) {} ) {
}
public function __invoke(Transaction $invoice): View|Factory|Application public function __invoke(Transaction $invoice): View|Factory|Application
{ {
@@ -34,4 +34,4 @@ class GetInvoiceController extends Controller
->with('settings', $settings) ->with('settings', $settings)
->with('invoice', $invoice); ->with('invoice', $invoice);
} }
} }

View File

@@ -0,0 +1,33 @@
<?php
namespace Domain\Sharing\Controllers;
use BaconQrCode\Writer;
use Illuminate\Http\Response;
use BaconQrCode\Renderer\Color\Rgb;
use App\Http\Controllers\Controller;
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\RendererStyle\Fill;
use BaconQrCode\Renderer\Image\SvgImageBackEnd;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
class GetShareLinkViaQrCodeController extends Controller
{
public function __invoke($token): Response
{
// Get share url
$url = url('/share', ['token' => $token]);
// Generate qr code
$svg = (new Writer(
new ImageRenderer(
new RendererStyle(192, 2, null, null, Fill::uniformColor(new Rgb(255, 255, 255), new Rgb(0, 0, 0))),
new SvgImageBackEnd
)
))->writeString($url);
$qrCode = trim(substr($svg, strpos($svg, "\n") + 1));
// Return qr code
return response($qrCode, 201);
}
}

View File

@@ -1,4 +1,5 @@
<?php <?php
namespace Tests\App\Users; namespace Tests\App\Users;
use Storage; use Storage;
@@ -121,7 +122,7 @@ class UserAccountTest extends TestCase
collect(config('vuefilemanager.avatar_sizes')) collect(config('vuefilemanager.avatar_sizes'))
->each( ->each(
fn ($size) => Storage::disk('local') fn($size) => Storage::disk('local')
->assertExists("avatars/{$size['name']}-{$user->settings->getRawOriginal('avatar')}") ->assertExists("avatars/{$size['name']}-{$user->settings->getRawOriginal('avatar')}")
); );
} }
@@ -141,7 +142,7 @@ class UserAccountTest extends TestCase
->assertStatus(200) ->assertStatus(200)
->assertExactJson([ ->assertExactJson([
'data' => [ 'data' => [
'id' => (string) $user->id, 'id' => (string)$user->id,
'type' => 'user', 'type' => 'user',
'attributes' => [ 'attributes' => [
'avatar' => [ 'avatar' => [
@@ -163,7 +164,7 @@ class UserAccountTest extends TestCase
'created_at' => format_date($user->created_at, '%d. %b. %Y'), 'created_at' => format_date($user->created_at, '%d. %b. %Y'),
'updated_at' => format_date($user->updated_at, '%d. %B. %Y'), 'updated_at' => format_date($user->updated_at, '%d. %B. %Y'),
], ],
'meta' => [ 'meta' => [
'restrictions' => [ 'restrictions' => [
'canCreateFolder' => true, 'canCreateFolder' => true,
'canCreateTeamFolder' => true, 'canCreateTeamFolder' => true,
@@ -178,7 +179,7 @@ class UserAccountTest extends TestCase
], ],
'settings' => [ 'settings' => [
'data' => [ 'data' => [
'id' => (string) $user->id, 'id' => (string)$user->id,
'type' => 'settings', 'type' => 'settings',
'attributes' => [ 'attributes' => [
'avatar' => $user->settings->avatar, 'avatar' => $user->settings->avatar,
@@ -188,6 +189,8 @@ class UserAccountTest extends TestCase
'city' => $user->settings->city, 'city' => $user->settings->city,
'postal_code' => $user->settings->postal_code, 'postal_code' => $user->settings->postal_code,
'country' => $user->settings->country, 'country' => $user->settings->country,
'first_name' => $user->settings->first_name,
'last_name' => $user->settings->last_name,
'phone_number' => $user->settings->phone_number, 'phone_number' => $user->settings->phone_number,
'timezone' => $user->settings->timezone, 'timezone' => $user->settings->timezone,
], ],

View File

@@ -11,6 +11,21 @@ use Domain\Sharing\Notifications\SharedSendViaEmail;
class UserShareTest extends TestCase class UserShareTest extends TestCase
{ {
/**
* @test
*/
public function it_generate_qr_code()
{
$user = User::factory()
->hasSettings()
->create();
$this
->actingAs($user)
->get('/api/share/123456789/qr')
->assertCreated();
}
/** /**
* @test * @test
*/ */