New feature visibility - public/draft (#10)
* New feature visibility - public/draft * fix bg for dark mode
This commit is contained in:
parent
5b92ac2633
commit
36e038a23b
|
@ -21,7 +21,7 @@ class PublicFormController extends Controller
|
||||||
|
|
||||||
public function show(Request $request, string $slug)
|
public function show(Request $request, string $slug)
|
||||||
{
|
{
|
||||||
$form = Form::whereSlug($slug)->firstOrFail();
|
$form = Form::whereSlug($slug)->whereVisibility('public')->firstOrFail();
|
||||||
if ($form->workspace == null) {
|
if ($form->workspace == null) {
|
||||||
// Workspace deleted
|
// Workspace deleted
|
||||||
return $this->error([
|
return $this->error([
|
||||||
|
|
|
@ -40,7 +40,7 @@ class AnswerFormRequest extends FormRequest
|
||||||
*/
|
*/
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
return !$this->form->is_closed && !$this->form->max_number_of_submissions_reached;
|
return !$this->form->is_closed && !$this->form->max_number_of_submissions_reached && $this->form->visibility === 'public';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,6 +29,7 @@ abstract class UserFormRequest extends \Illuminate\Foundation\Http\FormRequest
|
||||||
'title' => 'required|string|max:60',
|
'title' => 'required|string|max:60',
|
||||||
'description' => 'nullable|string|max:2000',
|
'description' => 'nullable|string|max:2000',
|
||||||
'tags' => 'nullable|array',
|
'tags' => 'nullable|array',
|
||||||
|
'visibility' => ['required',Rule::in(Form::VISIBILITY)],
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
'notifies' => 'boolean',
|
'notifies' => 'boolean',
|
||||||
|
|
|
@ -42,6 +42,7 @@ class FormResource extends JsonResource
|
||||||
'can_be_indexed' => $this->can_be_indexed,
|
'can_be_indexed' => $this->can_be_indexed,
|
||||||
'password' => $this->password,
|
'password' => $this->password,
|
||||||
'tags' => $this->tags,
|
'tags' => $this->tags,
|
||||||
|
'visibility' => $this->visibility,
|
||||||
'notification_emails' => $this->notification_emails,
|
'notification_emails' => $this->notification_emails,
|
||||||
'slack_webhook_url' => $this->slack_webhook_url,
|
'slack_webhook_url' => $this->slack_webhook_url,
|
||||||
] : [];
|
] : [];
|
||||||
|
|
|
@ -20,6 +20,7 @@ class Form extends Model
|
||||||
const DARK_MODE_VALUES = ['auto', 'light', 'dark'];
|
const DARK_MODE_VALUES = ['auto', 'light', 'dark'];
|
||||||
const THEMES = ['default', 'simple', 'notion'];
|
const THEMES = ['default', 'simple', 'notion'];
|
||||||
const WIDTHS = ['centered', 'full'];
|
const WIDTHS = ['centered', 'full'];
|
||||||
|
const VISIBILITY = ['public', 'draft'];
|
||||||
|
|
||||||
use HasFactory, HasSlug, SoftDeletes;
|
use HasFactory, HasSlug, SoftDeletes;
|
||||||
|
|
||||||
|
@ -45,6 +46,7 @@ class Form extends Model
|
||||||
'title',
|
'title',
|
||||||
'description',
|
'description',
|
||||||
'tags',
|
'tags',
|
||||||
|
'visibility',
|
||||||
|
|
||||||
// Customization
|
// Customization
|
||||||
'theme',
|
'theme',
|
||||||
|
|
|
@ -58,6 +58,7 @@ class FormFactory extends Factory
|
||||||
return [
|
return [
|
||||||
'title' => $this->faker->text(30),
|
'title' => $this->faker->text(30),
|
||||||
'description' => $this->faker->randomHtml(1),
|
'description' => $this->faker->randomHtml(1),
|
||||||
|
'visibility' => 'public',
|
||||||
'notifies' => false,
|
'notifies' => false,
|
||||||
'send_submission_confirmation' => false,
|
'send_submission_confirmation' => false,
|
||||||
'webhook_url' => null,
|
'webhook_url' => null,
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('forms', function (Blueprint $table) {
|
||||||
|
$table->string('visibility')->default('public');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('forms', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('visibility');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -27,6 +27,11 @@
|
||||||
placeholder="Select Tag(s)" :multiple="true" :allowCreation="true"
|
placeholder="Select Tag(s)" :multiple="true" :allowCreation="true"
|
||||||
:options="allTagsOptions"
|
:options="allTagsOptions"
|
||||||
/>
|
/>
|
||||||
|
<select-input name="visibility" label="Visibility" :form="form" class="mt-3 mb-6"
|
||||||
|
help="Only public form will be accessible"
|
||||||
|
placeholder="Select Visibility" :required="true"
|
||||||
|
:options="visibilityOptions"
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
v-if="copyFormOptions.length > 0"
|
v-if="copyFormOptions.length > 0"
|
||||||
class="group mt-3 cursor-pointer relative w-full rounded-lg border-transparent flex-1 appearance-none border border-gray-300 dark:border-gray-600 w-full py-2 px-4 bg-white text-gray-700 dark:bg-notion-dark-light dark:text-gray-300 dark:placeholder-gray-500 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:border-transparent focus:ring-opacity-100"
|
class="group mt-3 cursor-pointer relative w-full rounded-lg border-transparent flex-1 appearance-none border border-gray-300 dark:border-gray-600 w-full py-2 px-4 bg-white text-gray-700 dark:bg-notion-dark-light dark:text-gray-300 dark:placeholder-gray-500 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:border-transparent focus:ring-opacity-100"
|
||||||
|
@ -86,7 +91,17 @@ export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
showCopyFormSettingsModal: false,
|
showCopyFormSettingsModal: false,
|
||||||
copyFormId: null
|
copyFormId: null,
|
||||||
|
visibilityOptions: [
|
||||||
|
{
|
||||||
|
name: "Public",
|
||||||
|
value: "public"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Draft (form won't be accessible)",
|
||||||
|
value: "draft"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,7 @@ export default {
|
||||||
this.form = new Form({
|
this.form = new Form({
|
||||||
title: 'My Form',
|
title: 'My Form',
|
||||||
description: null,
|
description: null,
|
||||||
|
visibility: 'public',
|
||||||
workspace_id: this.workspace?.id,
|
workspace_id: this.workspace?.id,
|
||||||
properties: [],
|
properties: [],
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<div v-if="form" class="sm:px-6">
|
<div v-if="form" class="sm:px-6">
|
||||||
<h2 class="text-nt-blue text-3xl font-bold z-10 mt-6 mb-3">
|
<h2 class="text-nt-blue text-3xl font-bold z-10 mt-6 mb-3">
|
||||||
{{ form.title }}
|
{{ form.title }}
|
||||||
|
<span v-if="form.visibility=='draft'" class="float-right text-white p-2 text-xs inline rounded-lg font-semibold mr-2 bg-gray-400 dark:bg-gray-700">Draft (not public)</span>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p class="mb-3">
|
<p class="mb-3">
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-if="enrichedForms && enrichedForms.length" class="border border border-gray-300 dark:bg-notion-dark-light rounded-md w-full">
|
<div v-if="enrichedForms && enrichedForms.length" class="border border border-gray-300 dark:bg-notion-dark-light rounded-md w-full">
|
||||||
<div v-for="(form, index) in enrichedForms" :key="form.id"
|
<div v-for="(form, index) in enrichedForms" :key="form.id"
|
||||||
class="p-4 w-full mx-auto border-gray-300 hover:bg-blue-100 dark:hover:bg-blue-900 transition-colors cursor-pointer relative" :class="{'border-t':index!==0}"
|
class="p-4 w-full mx-auto border-gray-300 hover:bg-blue-100 dark:hover:bg-blue-900 transition-colors cursor-pointer relative"
|
||||||
|
:class="{'border-t':index!==0, 'bg-gray-50 dark:bg-gray-400':form.visibility=='draft'}"
|
||||||
>
|
>
|
||||||
<div class="items-center space-x-4 truncate">
|
<div class="items-center space-x-4 truncate">
|
||||||
<p class="truncate float-left">
|
<p class="truncate float-left">
|
||||||
|
|
|
@ -61,3 +61,26 @@ it('can submit form till max submissions count is not reached at limit', functio
|
||||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||||
->assertStatus(403);
|
->assertStatus(403);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can not open draft form', function () {
|
||||||
|
$user = $this->actingAsUser();
|
||||||
|
$workspace = $this->createUserWorkspace($user);
|
||||||
|
$form = $this->createForm($user, $workspace, [
|
||||||
|
'visibility' => 'draft'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->getJson(route('forms.show', $form->slug))
|
||||||
|
->assertStatus(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can not submit draft form', function () {
|
||||||
|
$user = $this->actingAsUser();
|
||||||
|
$workspace = $this->createUserWorkspace($user);
|
||||||
|
$form = $this->createForm($user, $workspace, [
|
||||||
|
'visibility' => 'draft'
|
||||||
|
]);
|
||||||
|
$formData = FormSubmissionDataFactory::generateSubmissionData($form);
|
||||||
|
|
||||||
|
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||||
|
->assertStatus(403);
|
||||||
|
});
|
Loading…
Reference in New Issue