Refactor Docker configuration and development setup
- Update .dockerignore with comprehensive ignore patterns for API and client - Modify docker-compose files to improve service configurations - Enhance Nginx configuration for development and production environments - Refactor Dockerfile.api with improved build process - Add docker-setup.sh script for simplified Docker deployment - Update update-credentials.vue page with improved UI - Remove hCaptcha dependency from package-lock.json - Update PHP configuration and entrypoint scripts
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
/Dockerfile
|
||||
/.dockerignore
|
||||
@@ -30,7 +30,7 @@
|
||||
/>
|
||||
|
||||
<!-- Remember Me -->
|
||||
<div class="relative flex items-start mt-5">
|
||||
<div class="relative flex items-center mt-3">
|
||||
<CheckboxInput
|
||||
v-model="remember"
|
||||
class="w-full md:w-1/2"
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
<!-- Submit Button -->
|
||||
<v-button
|
||||
class="w-full flex"
|
||||
class="w-full flex mt-2"
|
||||
:loading="form.busy || loading"
|
||||
>
|
||||
Log in to continue
|
||||
|
||||
3
client/middleware/feature-flags.global.js
vendored
3
client/middleware/feature-flags.global.js
vendored
@@ -3,7 +3,8 @@ import { useFeatureFlagsStore } from '~/stores/featureFlags'
|
||||
export default defineNuxtRouteMiddleware(async () => {
|
||||
const featureFlagsStore = useFeatureFlagsStore()
|
||||
|
||||
if (import.meta.server && Object.keys(featureFlagsStore.flags).length === 0) {
|
||||
// Load flags if they haven't been loaded yet
|
||||
if (!featureFlagsStore.isLoaded) {
|
||||
await featureFlagsStore.fetchFlags()
|
||||
}
|
||||
})
|
||||
8
client/middleware/self-hosted-credentials.js
vendored
8
client/middleware/self-hosted-credentials.js
vendored
@@ -1,5 +1,11 @@
|
||||
export default defineNuxtRouteMiddleware(() => {
|
||||
export default defineNuxtRouteMiddleware(async () => {
|
||||
const authStore = useAuthStore()
|
||||
const featureFlagsStore = useFeatureFlagsStore()
|
||||
|
||||
// Ensure feature flags are loaded
|
||||
if (!featureFlagsStore.isLoaded) {
|
||||
await featureFlagsStore.fetchFlags()
|
||||
}
|
||||
|
||||
if (useFeatureFlag('self_hosted')) {
|
||||
if (authStore.check && authStore.user?.email === 'admin@opnform.com') {
|
||||
|
||||
13
client/package-lock.json
generated
13
client/package-lock.json
generated
@@ -8,7 +8,6 @@
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@codemirror/lang-html": "^6.4.9",
|
||||
"@hcaptcha/vue3-hcaptcha": "^1.3.0",
|
||||
"@iconify-json/material-symbols": "^1.2.4",
|
||||
"@nuxt/ui": "^2.19.2",
|
||||
"@pinia/nuxt": "^0.5.5",
|
||||
@@ -1338,18 +1337,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@hcaptcha/vue3-hcaptcha": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@hcaptcha/vue3-hcaptcha/-/vue3-hcaptcha-1.3.0.tgz",
|
||||
"integrity": "sha512-IEonS6JiYdU7uy6aeib8cYtMO4nj8utwStbA9bWHyYbOvOvhpkV+AW8vfSKh6SntYxqle/TRwhv+kU9p92CfsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"vue": "^3.2.19"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@headlessui/tailwindcss": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/tailwindcss/-/tailwindcss-0.2.1.tgz",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="bg-white">
|
||||
<div class="bg-white" v-if="workspace">
|
||||
<div class="flex bg-gray-50 pb-5 border-b">
|
||||
<div class="w-full md:w-4/5 lg:w-3/5 md:mx-auto md:max-w-4xl p-4">
|
||||
<div class="pt-4 pb-0">
|
||||
@@ -8,7 +8,7 @@
|
||||
Your Forms
|
||||
</h2>
|
||||
<v-button
|
||||
v-if="!workspace.is_readonly"
|
||||
v-if="!workspace?.is_readonly"
|
||||
v-track.create_form_click
|
||||
:to="{ name: 'forms-create' }"
|
||||
>
|
||||
@@ -87,7 +87,7 @@
|
||||
again.
|
||||
</div>
|
||||
<v-button
|
||||
v-if="!workspace.is_readonly && forms.length === 0"
|
||||
v-if="!workspace?.is_readonly && forms.length === 0"
|
||||
v-track.create_form_click
|
||||
class="mt-4"
|
||||
:to="{ name: 'forms-create' }"
|
||||
@@ -182,7 +182,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="!workspace.is_pro"
|
||||
v-if="!workspace?.is_pro"
|
||||
class="px-4"
|
||||
>
|
||||
<UAlert
|
||||
|
||||
@@ -1,62 +1,74 @@
|
||||
<template>
|
||||
<modal
|
||||
:show="showModal"
|
||||
max-width="lg"
|
||||
@close="logout"
|
||||
>
|
||||
<div class="">
|
||||
<h2 class="font-medium text-3xl mb-3">
|
||||
<div class=" bg-gray-50 flex flex-col justify-center sm:px-6 lg:px-8 py-10 flex-grow">
|
||||
<div class="sm:mx-auto sm:w-full sm:max-w-md">
|
||||
<h2 class="text-center text-3xl font-bold tracking-tight text-gray-900">
|
||||
Welcome to OpnForm!
|
||||
</h2>
|
||||
<p class="text-sm text-gray-600">
|
||||
<p class="mt-2 text-center text-sm text-gray-600">
|
||||
You're using the self-hosted version of OpnForm and need to set up your account.
|
||||
Please enter your email and create a password to continue.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form
|
||||
class="mt-4"
|
||||
@submit.prevent="updateCredentials"
|
||||
@keydown="form.onKeydown($event)"
|
||||
>
|
||||
<!-- Email -->
|
||||
<text-input
|
||||
name="email"
|
||||
:form="form"
|
||||
label="Email"
|
||||
:required="true"
|
||||
placeholder="Your email address"
|
||||
/>
|
||||
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
||||
<div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
|
||||
<form
|
||||
@submit.prevent="updateCredentials"
|
||||
@keydown="form.onKeydown($event)"
|
||||
>
|
||||
<!-- Email -->
|
||||
<text-input
|
||||
name="email"
|
||||
:form="form"
|
||||
label="Email"
|
||||
:required="true"
|
||||
placeholder="Your email address"
|
||||
/>
|
||||
|
||||
<!-- Password -->
|
||||
<text-input
|
||||
native-type="password"
|
||||
placeholder="Your password"
|
||||
name="password"
|
||||
:form="form"
|
||||
label="Password"
|
||||
:required="true"
|
||||
/>
|
||||
<!-- Password -->
|
||||
<text-input
|
||||
native-type="password"
|
||||
placeholder="Your password"
|
||||
name="password"
|
||||
:form="form"
|
||||
label="Password"
|
||||
:required="true"
|
||||
/>
|
||||
|
||||
<!-- Password Confirmation-->
|
||||
<text-input
|
||||
native-type="password"
|
||||
:form="form"
|
||||
:required="true"
|
||||
placeholder="Enter confirm password"
|
||||
name="password_confirmation"
|
||||
label="Confirm Password"
|
||||
/>
|
||||
<!-- Password Confirmation-->
|
||||
<text-input
|
||||
native-type="password"
|
||||
:form="form"
|
||||
:required="true"
|
||||
placeholder="Enter confirm password"
|
||||
name="password_confirmation"
|
||||
label="Confirm Password"
|
||||
/>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<v-button
|
||||
class="mx-auto"
|
||||
:loading="form.busy || loading"
|
||||
>
|
||||
Update Credentials
|
||||
</v-button>
|
||||
</form>
|
||||
</modal>
|
||||
<!-- Submit Button -->
|
||||
<div class="mt-6">
|
||||
<v-button
|
||||
class="w-full justify-center"
|
||||
:loading="form.busy || loading"
|
||||
>
|
||||
Update Credentials
|
||||
</v-button>
|
||||
</div>
|
||||
|
||||
<!-- Cancel Link -->
|
||||
<div class="mt-4 text-center">
|
||||
<button
|
||||
type="button"
|
||||
class="text-sm text-gray-600 hover:text-gray-900"
|
||||
@click="logout"
|
||||
>
|
||||
Cancel and return to login
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -67,7 +79,7 @@ const workspacesStore = useWorkspacesStore()
|
||||
const formsStore = useFormsStore()
|
||||
const user = computed(() => authStore.user)
|
||||
const router = useRouter()
|
||||
const showModal = ref(true)
|
||||
const loading = ref(false)
|
||||
const form = useForm({
|
||||
name: "",
|
||||
email: "",
|
||||
@@ -82,6 +94,7 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
const updateCredentials = () => {
|
||||
loading.value = true
|
||||
form
|
||||
.post("update-credentials")
|
||||
.then(async (data) => {
|
||||
@@ -95,11 +108,13 @@ const updateCredentials = () => {
|
||||
console.error(error)
|
||||
useAlert().error(error.response._data.message)
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
authStore.logout()
|
||||
showModal.value = false
|
||||
router.push({ name: "login" })
|
||||
}
|
||||
</script>
|
||||
6
client/stores/featureFlags.js
vendored
6
client/stores/featureFlags.js
vendored
@@ -3,11 +3,15 @@ import { ref } from 'vue'
|
||||
|
||||
export const useFeatureFlagsStore = defineStore('feature_flags', () => {
|
||||
const flags = ref({})
|
||||
const isLoaded = ref(false)
|
||||
|
||||
async function fetchFlags() {
|
||||
if (isLoaded.value) return
|
||||
|
||||
try {
|
||||
const { data } = await useOpnApi('content/feature-flags')
|
||||
flags.value = data.value
|
||||
isLoaded.value = true
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch feature flags:', error)
|
||||
}
|
||||
@@ -20,5 +24,5 @@ export const useFeatureFlagsStore = defineStore('feature_flags', () => {
|
||||
}, flags.value)
|
||||
}
|
||||
|
||||
return { flags, fetchFlags, getFlag }
|
||||
return { flags, isLoaded, fetchFlags, getFlag }
|
||||
})
|
||||
Reference in New Issue
Block a user