added hideControls setting
This commit is contained in:
		
							parent
							
								
									cfaff31d97
								
							
						
					
					
						commit
						7be389704d
					
				| 
						 | 
				
			
			@ -43,6 +43,7 @@ func NewSettings() *Settings {
 | 
			
		|||
		Meta: MetaConfig{
 | 
			
		||||
			AppName:                    "Acme",
 | 
			
		||||
			AppUrl:                     "http://localhost:8090",
 | 
			
		||||
			HideControls:               false,
 | 
			
		||||
			SenderName:                 "Support",
 | 
			
		||||
			SenderAddress:              "support@example.com",
 | 
			
		||||
			VerificationTemplate:       defaultVerificationTemplate,
 | 
			
		||||
| 
						 | 
				
			
			@ -270,6 +271,7 @@ func (c S3Config) Validate() error {
 | 
			
		|||
type MetaConfig struct {
 | 
			
		||||
	AppName                    string        `form:"appName" json:"appName"`
 | 
			
		||||
	AppUrl                     string        `form:"appUrl" json:"appUrl"`
 | 
			
		||||
	HideControls               bool          `form:"hideControls" json:"hideControls"`
 | 
			
		||||
	SenderName                 string        `form:"senderName" json:"senderName"`
 | 
			
		||||
	SenderAddress              string        `form:"senderAddress" json:"senderAddress"`
 | 
			
		||||
	VerificationTemplate       EmailTemplate `form:"verificationTemplate" json:"verificationTemplate"`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -174,7 +174,7 @@ func TestSettingsRedactClone(t *testing.T) {
 | 
			
		|||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expected := `{"meta":{"appName":"test123","appUrl":"http://localhost:8090","senderName":"Support","senderAddress":"support@example.com","verificationTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eThank you for joining us at {APP_NAME}.\u003c/p\u003e\n\u003cp\u003eClick on the button below to verify your email address.\u003c/p\u003e\n\u003cp\u003e\n  \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eVerify\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\n  Thanks,\u003cbr/\u003e\n  {APP_NAME} team\n\u003c/p\u003e","subject":"Verify your {APP_NAME} email","actionUrl":"{APP_URL}/_/#/users/confirm-verification/{TOKEN}"},"resetPasswordTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eClick on the button below to reset your password.\u003c/p\u003e\n\u003cp\u003e\n  \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eReset password\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ci\u003eIf you didn't ask to reset your password, you can ignore this email.\u003c/i\u003e\u003c/p\u003e\n\u003cp\u003e\n  Thanks,\u003cbr/\u003e\n  {APP_NAME} team\n\u003c/p\u003e","subject":"Reset your {APP_NAME} password","actionUrl":"{APP_URL}/_/#/users/confirm-password-reset/{TOKEN}"},"confirmEmailChangeTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eClick on the button below to confirm your new email address.\u003c/p\u003e\n\u003cp\u003e\n  \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eConfirm new email\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ci\u003eIf you didn't ask to change your email address, you can ignore this email.\u003c/i\u003e\u003c/p\u003e\n\u003cp\u003e\n  Thanks,\u003cbr/\u003e\n  {APP_NAME} team\n\u003c/p\u003e","subject":"Confirm your {APP_NAME} new email address","actionUrl":"{APP_URL}/_/#/users/confirm-email-change/{TOKEN}"}},"logs":{"maxDays":7},"smtp":{"enabled":false,"host":"smtp.example.com","port":587,"username":"","password":"******","tls":true},"s3":{"enabled":false,"bucket":"","region":"","endpoint":"","accessKey":"","secret":"******","forcePathStyle":false},"adminAuthToken":{"secret":"******","duration":1209600},"adminPasswordResetToken":{"secret":"******","duration":1800},"userAuthToken":{"secret":"******","duration":1209600},"userPasswordResetToken":{"secret":"******","duration":1800},"userEmailChangeToken":{"secret":"******","duration":1800},"userVerificationToken":{"secret":"******","duration":604800},"emailAuth":{"enabled":true,"exceptDomains":null,"onlyDomains":null,"minPasswordLength":8},"googleAuth":{"enabled":false,"allowRegistrations":true,"clientSecret":"******"},"facebookAuth":{"enabled":false,"allowRegistrations":true,"clientSecret":"******"},"githubAuth":{"enabled":false,"allowRegistrations":true,"clientSecret":"******"},"gitlabAuth":{"enabled":false,"allowRegistrations":true,"clientSecret":"******"}}`
 | 
			
		||||
	expected := `{"meta":{"appName":"test123","appUrl":"http://localhost:8090","hideControls":false,"senderName":"Support","senderAddress":"support@example.com","verificationTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eThank you for joining us at {APP_NAME}.\u003c/p\u003e\n\u003cp\u003eClick on the button below to verify your email address.\u003c/p\u003e\n\u003cp\u003e\n  \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eVerify\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\n  Thanks,\u003cbr/\u003e\n  {APP_NAME} team\n\u003c/p\u003e","subject":"Verify your {APP_NAME} email","actionUrl":"{APP_URL}/_/#/users/confirm-verification/{TOKEN}"},"resetPasswordTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eClick on the button below to reset your password.\u003c/p\u003e\n\u003cp\u003e\n  \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eReset password\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ci\u003eIf you didn't ask to reset your password, you can ignore this email.\u003c/i\u003e\u003c/p\u003e\n\u003cp\u003e\n  Thanks,\u003cbr/\u003e\n  {APP_NAME} team\n\u003c/p\u003e","subject":"Reset your {APP_NAME} password","actionUrl":"{APP_URL}/_/#/users/confirm-password-reset/{TOKEN}"},"confirmEmailChangeTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eClick on the button below to confirm your new email address.\u003c/p\u003e\n\u003cp\u003e\n  \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eConfirm new email\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ci\u003eIf you didn't ask to change your email address, you can ignore this email.\u003c/i\u003e\u003c/p\u003e\n\u003cp\u003e\n  Thanks,\u003cbr/\u003e\n  {APP_NAME} team\n\u003c/p\u003e","subject":"Confirm your {APP_NAME} new email address","actionUrl":"{APP_URL}/_/#/users/confirm-email-change/{TOKEN}"}},"logs":{"maxDays":7},"smtp":{"enabled":false,"host":"smtp.example.com","port":587,"username":"","password":"******","tls":true},"s3":{"enabled":false,"bucket":"","region":"","endpoint":"","accessKey":"","secret":"******","forcePathStyle":false},"adminAuthToken":{"secret":"******","duration":1209600},"adminPasswordResetToken":{"secret":"******","duration":1800},"userAuthToken":{"secret":"******","duration":1209600},"userPasswordResetToken":{"secret":"******","duration":1800},"userEmailChangeToken":{"secret":"******","duration":1800},"userVerificationToken":{"secret":"******","duration":604800},"emailAuth":{"enabled":true,"exceptDomains":null,"onlyDomains":null,"minPasswordLength":8},"googleAuth":{"enabled":false,"allowRegistrations":true,"clientSecret":"******"},"facebookAuth":{"enabled":false,"allowRegistrations":true,"clientSecret":"******"},"githubAuth":{"enabled":false,"allowRegistrations":true,"clientSecret":"******"},"gitlabAuth":{"enabled":false,"allowRegistrations":true,"clientSecret":"******"}}`
 | 
			
		||||
 | 
			
		||||
	if encodedStr := string(encoded); encodedStr != expected {
 | 
			
		||||
		t.Fatalf("Expected %v, got \n%v", expected, encodedStr)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
    import Toasts from "@/components/base/Toasts.svelte";
 | 
			
		||||
    import Toggler from "@/components/base/Toggler.svelte";
 | 
			
		||||
    import Confirmation from "@/components/base/Confirmation.svelte";
 | 
			
		||||
    import { pageTitle, appName } from "@/stores/app";
 | 
			
		||||
    import { pageTitle, appName, hideControls } from "@/stores/app";
 | 
			
		||||
    import { admin } from "@/stores/admin";
 | 
			
		||||
    import { setErrors } from "@/stores/errors";
 | 
			
		||||
    import { resetConfirmation } from "@/stores/confirmation";
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@
 | 
			
		|||
    let showAppSidebar = false;
 | 
			
		||||
 | 
			
		||||
    $: if ($admin?.id) {
 | 
			
		||||
        loadAppName();
 | 
			
		||||
        loadSettings();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function handleRouteLoading(e) {
 | 
			
		||||
| 
						 | 
				
			
			@ -42,18 +42,19 @@
 | 
			
		|||
        replace("/");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async function loadAppName() {
 | 
			
		||||
    async function loadSettings() {
 | 
			
		||||
        if (!$admin?.id) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            const settings = await ApiClient.settings.getAll({
 | 
			
		||||
                $cancelKey: "loadAppName",
 | 
			
		||||
                $cancelKey: "initialAppSettings",
 | 
			
		||||
            });
 | 
			
		||||
            $appName = settings?.meta?.appName || "";
 | 
			
		||||
            $hideControls = !!settings?.meta?.hideControls;
 | 
			
		||||
        } catch (err) {
 | 
			
		||||
            console.warn("Failed to load app name.", err);
 | 
			
		||||
            console.warn("Failed to load app settings.", err);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
<script>
 | 
			
		||||
    import { hideControls } from "@/stores/app";
 | 
			
		||||
    import { collections, activeCollection } from "@/stores/collections";
 | 
			
		||||
    import CollectionUpsertPanel from "@/components/collections/CollectionUpsertPanel.svelte";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -63,12 +64,14 @@
 | 
			
		|||
        {/each}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <footer class="sidebar-footer">
 | 
			
		||||
        <button type="button" class="btn btn-block btn-outline" on:click={() => collectionPanel?.show()}>
 | 
			
		||||
            <i class="ri-add-line" />
 | 
			
		||||
            <span class="txt">New collection</span>
 | 
			
		||||
        </button>
 | 
			
		||||
    </footer>
 | 
			
		||||
    {#if !$hideControls}
 | 
			
		||||
        <footer class="sidebar-footer">
 | 
			
		||||
            <button type="button" class="btn btn-block btn-outline" on:click={() => collectionPanel?.show()}>
 | 
			
		||||
                <i class="ri-add-line" />
 | 
			
		||||
                <span class="txt">New collection</span>
 | 
			
		||||
            </button>
 | 
			
		||||
        </footer>
 | 
			
		||||
    {/if}
 | 
			
		||||
</aside>
 | 
			
		||||
 | 
			
		||||
<CollectionUpsertPanel bind:this={collectionPanel} />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@
 | 
			
		|||
        loadCollections,
 | 
			
		||||
    } from "@/stores/collections";
 | 
			
		||||
    import tooltip from "@/actions/tooltip";
 | 
			
		||||
    import { pageTitle } from "@/stores/app";
 | 
			
		||||
    import { pageTitle, hideControls } from "@/stores/app";
 | 
			
		||||
    import PageWrapper from "@/components/base/PageWrapper.svelte";
 | 
			
		||||
    import Searchbar from "@/components/base/Searchbar.svelte";
 | 
			
		||||
    import RefreshButton from "@/components/base/RefreshButton.svelte";
 | 
			
		||||
| 
						 | 
				
			
			@ -68,15 +68,19 @@
 | 
			
		|||
            <div class="icon">
 | 
			
		||||
                <i class="ri-database-2-line" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <h1 class="m-b-10">Create your first collection to add records!</h1>
 | 
			
		||||
            <button
 | 
			
		||||
                type="button"
 | 
			
		||||
                class="btn btn-expanded-lg btn-lg"
 | 
			
		||||
                on:click={() => collectionUpsertPanel?.show()}
 | 
			
		||||
            >
 | 
			
		||||
                <i class="ri-add-line" />
 | 
			
		||||
                <span class="txt">Create new collection</span>
 | 
			
		||||
            </button>
 | 
			
		||||
            {#if $hideControls}
 | 
			
		||||
                <h1 class="m-b-10">You don't have any collections yet.</h1>
 | 
			
		||||
            {:else}
 | 
			
		||||
                <h1 class="m-b-10">Create your first collection to add records!</h1>
 | 
			
		||||
                <button
 | 
			
		||||
                    type="button"
 | 
			
		||||
                    class="btn btn-expanded-lg btn-lg"
 | 
			
		||||
                    on:click={() => collectionUpsertPanel?.show()}
 | 
			
		||||
                >
 | 
			
		||||
                    <i class="ri-add-line" />
 | 
			
		||||
                    <span class="txt">Create new collection</span>
 | 
			
		||||
                </button>
 | 
			
		||||
            {/if}
 | 
			
		||||
        </div>
 | 
			
		||||
    </PageWrapper>
 | 
			
		||||
{:else}
 | 
			
		||||
| 
						 | 
				
			
			@ -90,14 +94,16 @@
 | 
			
		|||
            </nav>
 | 
			
		||||
 | 
			
		||||
            <div class="inline-flex gap-5">
 | 
			
		||||
                <button
 | 
			
		||||
                    type="button"
 | 
			
		||||
                    class="btn btn-secondary btn-circle"
 | 
			
		||||
                    use:tooltip={{ text: "Edit collection", position: "right" }}
 | 
			
		||||
                    on:click={() => collectionUpsertPanel?.show($activeCollection)}
 | 
			
		||||
                >
 | 
			
		||||
                    <i class="ri-settings-4-line" />
 | 
			
		||||
                </button>
 | 
			
		||||
                {#if !$hideControls}
 | 
			
		||||
                    <button
 | 
			
		||||
                        type="button"
 | 
			
		||||
                        class="btn btn-secondary btn-circle"
 | 
			
		||||
                        use:tooltip={{ text: "Edit collection", position: "right" }}
 | 
			
		||||
                        on:click={() => collectionUpsertPanel?.show($activeCollection)}
 | 
			
		||||
                    >
 | 
			
		||||
                        <i class="ri-settings-4-line" />
 | 
			
		||||
                    </button>
 | 
			
		||||
                {/if}
 | 
			
		||||
 | 
			
		||||
                <RefreshButton on:refresh={() => recordsList?.load()} />
 | 
			
		||||
            </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,9 @@
 | 
			
		|||
<script>
 | 
			
		||||
    import ApiClient from "@/utils/ApiClient";
 | 
			
		||||
    import CommonHelper from "@/utils/CommonHelper";
 | 
			
		||||
    import { pageTitle, appName } from "@/stores/app";
 | 
			
		||||
    import { pageTitle, appName, hideControls } from "@/stores/app";
 | 
			
		||||
    import { addSuccessToast } from "@/stores/toasts";
 | 
			
		||||
    import tooltip from "@/actions/tooltip";
 | 
			
		||||
    import PageWrapper from "@/components/base/PageWrapper.svelte";
 | 
			
		||||
    import Field from "@/components/base/Field.svelte";
 | 
			
		||||
    import SettingsSidebar from "@/components/settings/SettingsSidebar.svelte";
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +55,7 @@
 | 
			
		|||
 | 
			
		||||
    function init(settings = {}) {
 | 
			
		||||
        $appName = settings?.meta?.appName;
 | 
			
		||||
        $hideControls = !!settings?.meta?.hideControls;
 | 
			
		||||
 | 
			
		||||
        formSettings = {
 | 
			
		||||
            meta: settings?.meta || {},
 | 
			
		||||
| 
						 | 
				
			
			@ -108,6 +110,20 @@
 | 
			
		|||
                        <input type="number" id={uniqueId} required bind:value={formSettings.logs.maxDays} />
 | 
			
		||||
                    </Field>
 | 
			
		||||
 | 
			
		||||
                    <Field class="form-field form-field-toggle" name="meta.hideControls" let:uniqueId>
 | 
			
		||||
                        <input type="checkbox" id={uniqueId} bind:checked={formSettings.meta.hideControls} />
 | 
			
		||||
                        <label for={uniqueId}>
 | 
			
		||||
                            <span class="txt">Hide collection create and edit controls</span>
 | 
			
		||||
                            <i
 | 
			
		||||
                                class="ri-information-line link-hint"
 | 
			
		||||
                                use:tooltip={{
 | 
			
		||||
                                    text: `This is useful to prevent making accidental schema changes on a production environment.`,
 | 
			
		||||
                                    position: "right",
 | 
			
		||||
                                }}
 | 
			
		||||
                            />
 | 
			
		||||
                        </label>
 | 
			
		||||
                    </Field>
 | 
			
		||||
 | 
			
		||||
                    <div class="col-lg-12 flex">
 | 
			
		||||
                        <div class="flex-fill" />
 | 
			
		||||
                        {#if hasChanges}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
    import ApiClient from "@/utils/ApiClient";
 | 
			
		||||
    import CommonHelper from "@/utils/CommonHelper";
 | 
			
		||||
    import tooltip from "@/actions/tooltip";
 | 
			
		||||
    import { pageTitle } from "@/stores/app";
 | 
			
		||||
    import { pageTitle, hideControls } from "@/stores/app";
 | 
			
		||||
    import PageWrapper from "@/components/base/PageWrapper.svelte";
 | 
			
		||||
    import Searchbar from "@/components/base/Searchbar.svelte";
 | 
			
		||||
    import RefreshButton from "@/components/base/RefreshButton.svelte";
 | 
			
		||||
| 
						 | 
				
			
			@ -116,14 +116,16 @@
 | 
			
		|||
                <div class="breadcrumb-item">{$pageTitle}</div>
 | 
			
		||||
            </nav>
 | 
			
		||||
 | 
			
		||||
            <button
 | 
			
		||||
                type="button"
 | 
			
		||||
                class="btn btn-secondary btn-circle"
 | 
			
		||||
                use:tooltip={{ text: "Edit profile collection", position: "right" }}
 | 
			
		||||
                on:click={() => collectionUpsertPanel?.show(profileCollection)}
 | 
			
		||||
            >
 | 
			
		||||
                <i class="ri-settings-4-line" />
 | 
			
		||||
            </button>
 | 
			
		||||
            {#if !$hideControls}
 | 
			
		||||
                <button
 | 
			
		||||
                    type="button"
 | 
			
		||||
                    class="btn btn-secondary btn-circle"
 | 
			
		||||
                    use:tooltip={{ text: "Edit profile collection", position: "right" }}
 | 
			
		||||
                    on:click={() => collectionUpsertPanel?.show(profileCollection)}
 | 
			
		||||
                >
 | 
			
		||||
                    <i class="ri-settings-4-line" />
 | 
			
		||||
                </button>
 | 
			
		||||
            {/if}
 | 
			
		||||
 | 
			
		||||
            <RefreshButton on:refresh={() => loadUsers()} />
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,3 +3,5 @@ import { writable } from "svelte/store";
 | 
			
		|||
export const pageTitle = writable('');
 | 
			
		||||
 | 
			
		||||
export const appName = writable('');
 | 
			
		||||
 | 
			
		||||
export const hideControls = writable(false);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue