Compare commits
30 Commits
baghi/base
...
main
Author | SHA1 | Date | |
---|---|---|---|
f5c54cd632 | |||
![]() |
3ee869a66b | ||
![]() |
b21c8549ab | ||
![]() |
851324eb0b | ||
![]() |
1ccf9e09ba | ||
![]() |
f2fee4c45f | ||
![]() |
f00f10ca3d | ||
![]() |
0f155d2f04 | ||
![]() |
1cae9689c5 | ||
![]() |
d1373fb94c | ||
![]() |
be39f7377b | ||
![]() |
16bb8986e0 | ||
![]() |
4f6e31fed7 | ||
![]() |
5ee08b4c7a | ||
![]() |
5f2c8ba4e0 | ||
![]() |
5100db79da | ||
![]() |
ab00e04dd8 | ||
![]() |
c71b5737cd | ||
![]() |
95b2b62095 | ||
![]() |
ca6372b438 | ||
![]() |
cab508f69a | ||
![]() |
19a83a6367 | ||
![]() |
47d58ecdf4 | ||
![]() |
fc1d8b6109 | ||
![]() |
0d0fd2dacd | ||
![]() |
606d3bdc05 | ||
![]() |
436ab75d21 | ||
![]() |
61f02d6883 | ||
![]() |
e7bbe4d628 | ||
![]() |
48320d52af |
|
@ -1,5 +1,5 @@
|
|||
VITE_API_NAME=api/
|
||||
VITE_BASE_URL=http://192.168.23.60/
|
||||
NUXT_PUBLIC_API_NAME=api/
|
||||
NUXT_PUBLIC_BASE_URL=http://192.168.23.60/
|
||||
|
||||
VITE_APP_NAME=Hadith
|
||||
|
||||
|
@ -7,9 +7,9 @@ VITE_APP_NAME=Hadith
|
|||
### Relative pathes for systems sass addressing ###
|
||||
# 0 : majles.tavasi.ir 1: qanon.parliran.ir
|
||||
VITE_BUILD_STATE=0
|
||||
VITE_BUILD_NAME=hadith
|
||||
VITE_BUILD_NAME=haditha
|
||||
|
||||
VITE_IDB_NAME=hadith
|
||||
VITE_IDB_NAME=haditha
|
||||
VITE_IDB_VERSION=1
|
||||
VITE_ENABLE_IDB=1
|
||||
|
3
.gitmodules
vendored
|
@ -7,3 +7,6 @@
|
|||
[submodule "systems/hadith_ui"]
|
||||
path = systems/hadith_ui
|
||||
url = https://git2.tavasi.ir/front/hadith_ui.git
|
||||
[submodule "systems/chat_ui"]
|
||||
path = systems/chat_ui
|
||||
url = https://git2.tavasi.ir/front/chat_ui.git
|
||||
|
|
289
COMPOSITION_API.md
Normal file
|
@ -0,0 +1,289 @@
|
|||
1. Organize Your Code into Logical Sections
|
||||
|
||||
Structure your component script into clear sections to improve readability. A common approach is to group related logic together.
|
||||
Example Structure:
|
||||
|
||||
<script setup>
|
||||
// 1. Imports
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
// 2. Reactive State
|
||||
const count = ref(0)
|
||||
const name = ref('')
|
||||
|
||||
// 3. Computed Properties
|
||||
const doubledCount = computed(() => count.value * 2)
|
||||
|
||||
// 4. Functions / Methods
|
||||
function increment() {
|
||||
count.value++
|
||||
}
|
||||
|
||||
// 5. Lifecycle Hooks
|
||||
onMounted(() => {
|
||||
console.log('Component mounted')
|
||||
})
|
||||
|
||||
// 6. Watchers
|
||||
watch(count, (newValue, oldValue) => {
|
||||
console.log(`Count changed from ${oldValue} to ${newValue}`)
|
||||
})
|
||||
</script>
|
||||
|
||||
---
|
||||
|
||||
2. Use script setup Syntax
|
||||
|
||||
The <script setup> syntax is the recommended way to write Composition API components. It provides a more concise and intuitive syntax.
|
||||
Example:
|
||||
|
||||
<script setup>
|
||||
const message = ref('Hello, Vue 3!')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p>{{ message }}</p>
|
||||
</template>
|
||||
|
||||
---
|
||||
|
||||
3. Use Descriptive Variable and Function Names
|
||||
|
||||
Choose meaningful names for variables, functions, and computed properties to make your code self-documenting.
|
||||
Example:
|
||||
// Bad
|
||||
const x = ref(0)
|
||||
|
||||
// Good
|
||||
const userCount = ref(0)
|
||||
|
||||
---
|
||||
|
||||
4. Extract Reusable Logic into Composables
|
||||
Move reusable logic into composables (custom hooks) to keep your components clean and promote code reuse.
|
||||
Example Composable:
|
||||
|
||||
// composables/useCounter.js
|
||||
import { ref } from 'vue'
|
||||
|
||||
export function useCounter(initialValue = 0) {
|
||||
const count = ref(initialValue)
|
||||
|
||||
function increment() {
|
||||
count.value++
|
||||
}
|
||||
|
||||
function reset() {
|
||||
count.value = initialValue
|
||||
}
|
||||
|
||||
return {
|
||||
count,
|
||||
increment,
|
||||
reset,
|
||||
}
|
||||
}
|
||||
|
||||
Usage in a Component:
|
||||
|
||||
<script setup>
|
||||
import { useCounter } from '~/composables/useCounter'
|
||||
|
||||
const { count, increment } = useCounter()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p>Count: {{ count }}</p>
|
||||
<button @click="increment">Increment</button>
|
||||
</template>
|
||||
|
||||
---
|
||||
|
||||
5. Use ref for Primitive Values and reactive for Objects
|
||||
|
||||
- Use ref for primitive values (e.g., numbers, strings, booleans).
|
||||
- Use reactive for objects or arrays.
|
||||
|
||||
Example:
|
||||
const count = ref(0) // Primitive value
|
||||
const user = reactive({ name: 'John', age: 30 }) // Object
|
||||
|
||||
---
|
||||
|
||||
6. Use Computed Properties for Derived State
|
||||
|
||||
Use computed to create reactive properties that depend on other state. This ensures the derived state is always up-to-date.
|
||||
Example:
|
||||
const firstName = ref('John')
|
||||
const lastName = ref('Doe')
|
||||
|
||||
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
|
||||
|
||||
---
|
||||
|
||||
7. Use Watchers Sparingly
|
||||
|
||||
Watchers (watch and watchEffect) are powerful but can make your code harder to understand if overused. Prefer computed properties or event-driven updates where possible.
|
||||
Example:
|
||||
watch(count, (newValue, oldValue) => {
|
||||
console.log(`Count changed from ${oldValue} to ${newValue}`)
|
||||
})
|
||||
|
||||
---
|
||||
|
||||
8. Group Related Logic Together
|
||||
|
||||
Keep related reactive state, computed properties, and functions together to make your code easier to follow.
|
||||
Example:
|
||||
// User-related logic
|
||||
const user = reactive({ name: 'John', age: 30 })
|
||||
const isAdult = computed(() => user.age >= 18)
|
||||
function updateUser(newName) {
|
||||
user.name = newName
|
||||
}
|
||||
|
||||
-----------
|
||||
|
||||
9. Use Lifecycle Hooks for Side Effects
|
||||
|
||||
Use lifecycle hooks (onMounted, onUnmounted, etc.) for side effects like fetching data or setting up event listeners.
|
||||
Example:
|
||||
onMounted(() => {
|
||||
console.log('Component mounted')
|
||||
fetchData()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
console.log('Component unmounted')
|
||||
cleanup()
|
||||
})
|
||||
|
||||
----------------
|
||||
|
||||
10. Use TypeScript for Better Type Safety
|
||||
If your project uses TypeScript, leverage it to add type safety to your components.
|
||||
Example:
|
||||
<script setup lang="ts">
|
||||
interface User {
|
||||
name: string
|
||||
age: number
|
||||
}
|
||||
|
||||
const user = ref<User>({ name: 'John', age: 30 })
|
||||
</script>
|
||||
|
||||
--------------
|
||||
|
||||
11. Keep Templates Clean
|
||||
|
||||
Avoid putting too much logic in your template. Instead, move complex logic into the script or composables.
|
||||
Example:
|
||||
<template>
|
||||
<div>
|
||||
<p>{{ fullName }}</p>
|
||||
<button @click="increment">Increment</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const firstName = ref('John')
|
||||
const lastName = ref('Doe')
|
||||
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
|
||||
|
||||
function increment() {
|
||||
// Logic here
|
||||
}
|
||||
</script>
|
||||
|
||||
------------
|
||||
|
||||
12. Use provide and inject for Prop Drilling
|
||||
Avoid prop drilling by using provide and inject to share state across deeply nested components.
|
||||
Example:
|
||||
// Parent component
|
||||
import { provide, ref } from 'vue'
|
||||
|
||||
const theme = ref('dark')
|
||||
provide('theme', theme)
|
||||
|
||||
// Child component
|
||||
import { inject } from 'vue'
|
||||
|
||||
const theme = inject('theme')
|
||||
|
||||
-----------------
|
||||
|
||||
13. Use v-model for Two-Way Binding
|
||||
|
||||
Use v-model to simplify two-way binding between parent and child components.
|
||||
Example:
|
||||
<!-- Parent component -->
|
||||
<template>
|
||||
<ChildComponent v-model:name="userName" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const userName = ref('John')
|
||||
</script>
|
||||
|
||||
<!-- Child component -->
|
||||
<template>
|
||||
<input :value="name" @input="$emit('update:name', $event.target.value)" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps(['name'])
|
||||
defineEmits(['update:name'])
|
||||
</script>
|
||||
|
||||
----------
|
||||
|
||||
14. Use defineProps and defineEmits for TypeScript Support
|
||||
|
||||
When using TypeScript, use defineProps and defineEmits to define props and emits with type safety.
|
||||
Example:
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
title: string
|
||||
count: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'update:count', value: number): void
|
||||
}>()
|
||||
</script>
|
||||
|
||||
-------------
|
||||
|
||||
15. Use Scoped Styles
|
||||
|
||||
Use scoped styles (<style scoped>) to ensure styles are component-specific and don’t leak into other components.
|
||||
Example:
|
||||
<style scoped>
|
||||
.button {
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
------------------
|
||||
|
||||
16. Use Environment Variables
|
||||
|
||||
Use environment variables for configuration (e.g., API URLs) to keep your code flexible and secure.
|
||||
Example:
|
||||
const apiUrl = import.meta.env.VITE_API_URL
|
||||
|
||||
-------------
|
||||
|
||||
17. Write Unit Tests
|
||||
|
||||
Write unit tests for your components and composables to ensure they work as expected.
|
||||
Example:
|
||||
import { render } from '@testing-library/vue'
|
||||
import MyComponent from '@/components/MyComponent.vue'
|
||||
|
||||
test('renders correctly', () => {
|
||||
const { getByText } = render(MyComponent)
|
||||
expect(getByText('Hello, Vue 3!')).toBeInTheDocument()
|
||||
})
|
52
GIT_SUBMODULE.md
Normal file
|
@ -0,0 +1,52 @@
|
|||
Add new repo:
|
||||
git submodule add https://git2.tavasi.ir/front/chat_ui.git systems/chat_ui -f
|
||||
|
||||
Cloning a Repository with Submodules
|
||||
If you clone a repository that contains submodules, you'll need to initialize and update the submodules:
|
||||
git clone <repository-url>
|
||||
cd <repository-directory>
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
Or, you can do it in one step:
|
||||
git clone --recurse-submodules <repository-url>
|
||||
|
||||
Updating Submodules
|
||||
To update a submodule to the latest commit on its branch:
|
||||
git submodule update --remote
|
||||
|
||||
## How to Remove an Existing Submodule
|
||||
|
||||
If the path was previously added as a submodule, you need to remove it completely before re-adding it. Follow these steps:
|
||||
|
||||
1. Remove the submodule entry from .gitmodules.
|
||||
2. Remove the submodule from the working tree and index: git rm --cached <path-to-submodule>.
|
||||
3. Delete the submodule directory: rm -rf <path-to-submodule>.
|
||||
4. Stage the .gitmodules changes: git add .gitmodules.
|
||||
5. Commit the changes: git commit -m "Removed submodule <submodule-name>".
|
||||
|
||||
errors:
|
||||
|
||||
# repo already exists and is not a valid git repo
|
||||
|
||||
Check if the path is already tracked
|
||||
git ls-files --stage systems/chat_ui (100644 <hash> 0 <path>)
|
||||
|
||||
If it is, remove it from the index
|
||||
git rm --cached systems/chat_ui
|
||||
|
||||
If system/chat_ui exits, remote it(chat_ui)
|
||||
rm -r systems/chat_ui
|
||||
|
||||
Add the submodule
|
||||
git submodule add https://github.com/example/repo.git systems/chat_ui
|
||||
|
||||
Commit the changes
|
||||
git commit -m "Added submodule at systems/chat_ui"
|
||||
|
||||
Verify the submodule
|
||||
git submodule status
|
||||
|
||||
(Optional) Initialize and Update the Submodule
|
||||
If the submodule was added successfully but not initialized, run:
|
||||
git submodule update --init --recursive
|
68
app.vue
|
@ -2,58 +2,48 @@
|
|||
<UApp :locale="fa_ir">
|
||||
<NuxtLoadingIndicator />
|
||||
<NuxtRouteAnnouncer />
|
||||
<!-- <DevOnly> -->
|
||||
<!-- this component will only be rendered during development -->
|
||||
<!-- <LazyDebugBar /> -->
|
||||
|
||||
<!-- if you ever require to have a replacement during production -->
|
||||
<!-- be sure to test these using `nuxt preview` -->
|
||||
<!-- <template #fallback> -->
|
||||
<!-- <div>empty div for flex.justify-between</div> -->
|
||||
<!-- </template> -->
|
||||
<!-- </DevOnly> -->
|
||||
|
||||
<NuxtLayout>
|
||||
<!-- this component will be rendered on client-side -->
|
||||
<!-- <NuxtClientFallback
|
||||
fallback-tag="span"
|
||||
fallback="NuxtClientFallback"
|
||||
@ssr-error="logSomeError"
|
||||
> -->
|
||||
<NuxtPage />
|
||||
<!-- <BrokeInSsr /> -->
|
||||
<!-- </NuxtClientFallback> -->
|
||||
</NuxtLayout>
|
||||
</UApp>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { fa_ir } from "@nuxt/ui/locale";
|
||||
|
||||
onMounted(() => {
|
||||
// const toast = useToast();
|
||||
// toast.add({
|
||||
// title: "hello world",
|
||||
// });
|
||||
});
|
||||
|
||||
// import { useCounterStore } from "~/stores/counter";
|
||||
// import { storeToRefs } from "pinia";
|
||||
|
||||
// export default {
|
||||
// setup() {
|
||||
// definePageMeta({
|
||||
// colorMode: "light",
|
||||
// });
|
||||
// },
|
||||
// mounted() {
|
||||
// access the `store` variable anywhere in the component ✨
|
||||
// const store = useCounterStore();
|
||||
// const { count, doubleCount } = storeToRefs(store);
|
||||
// const { increment } = store;
|
||||
// console.info(this.$config.public.TAHRIR_ASSETS_URL);
|
||||
// console.info(this.$config.public.PUBLIC_JAHAT_ASSETS_URL);
|
||||
// console.info(this.$config.public.VITE_APP_NAME);
|
||||
// console.info(import.meta.env.VITE_APP_NAME);
|
||||
// console.info(this.$config.public);
|
||||
// console.info(this.$config.public.TITLE);
|
||||
// console.info(this.$config.public.NODE_ENV);
|
||||
// console.info(this.$config.public.VITE_APP_NAME);
|
||||
// console.info(this.$config.public.VITE_BASE_URL);
|
||||
// console.info(this.$config.public.VITE_BASE_URL);
|
||||
// },
|
||||
// setup() {
|
||||
// definePageMeta({
|
||||
// colorMode: "light",
|
||||
// });
|
||||
// },
|
||||
// mounted() {
|
||||
// access the `store` variable anywhere in the component ✨
|
||||
// const store = useCounterStore();
|
||||
// const { count, doubleCount } = storeToRefs(store);
|
||||
// const { increment } = store;
|
||||
// console.info(this.$config.public.TAHRIR_ASSETS_URL);
|
||||
// console.info(this.$config.public.PUBLIC_JAHAT_ASSETS_URL);
|
||||
// console.info(this.$config.public.VITE_APP_NAME);
|
||||
// console.info(import.meta.env.VITE_APP_NAME);
|
||||
// console.info(this.$config.public);
|
||||
// console.info(this.$config.public.TITLE);
|
||||
// console.info(this.$config.public.NODE_ENV);
|
||||
// console.info(this.$config.public.VITE_APP_NAME);
|
||||
// console.info(this.$config.public.VITE_BASE_URL);
|
||||
// console.info(this.$config.public.VITE_BASE_URL);
|
||||
// },
|
||||
// methods: {
|
||||
// logSomeError(error) {
|
||||
// console.info("logSomeError", error);
|
||||
|
|
|
@ -60,3 +60,6 @@
|
|||
|
||||
// responsive
|
||||
@import "responsive/responsive";
|
||||
|
||||
// @import "tailwindcss";
|
||||
// @import "@nuxt/ui";
|
||||
|
|
|
@ -59,3 +59,6 @@
|
|||
|
||||
// responsive
|
||||
@import "responsive/responsive";
|
||||
|
||||
// @import "tailwindcss";
|
||||
// @import "@nuxt/ui";
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
@import "src/assets/common/scss/mixin";
|
||||
@import "src/assets/common/scss/placeholder";
|
||||
// @import "src/assets/common/scss/mixin";
|
||||
// @import "src/assets/common/scss/placeholder";
|
||||
@import "@/assets/common/scss/mixin";
|
||||
@import "@/assets/common/scss/placeholder";
|
||||
|
||||
.admin-system,.task-system,.admin-panel{
|
||||
//@import "main";
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
@import "src/assets/common/scss/mixin";
|
||||
@import "src/assets/common/scss/placeholder";
|
||||
// @import "src/assets/common/scss/mixin";
|
||||
// @import "src/assets/common/scss/placeholder";
|
||||
@import "@/assets/common/scss/mixin";
|
||||
@import "@/assets/common/scss/placeholder";
|
||||
|
||||
.admin-panel {
|
||||
.pages-content-container {
|
||||
|
|
|
@ -106,7 +106,9 @@
|
|||
|
||||
<script>
|
||||
import authMixin from "~/mixins/authMixin";
|
||||
import { required, minLength } from "vuelidate/lib/validators";
|
||||
import { required,minLength } from '@vuelidate/validators'
|
||||
import useVuelidate from '@vuelidate/core'
|
||||
|
||||
|
||||
import { mapState } from "pinia";
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
"{{ userFullname(getFullName) }}" عزیز، خوش آمدید.
|
||||
</div>
|
||||
|
||||
<div v-else> 0{{ getMobile }} </div>
|
||||
<div v-else>0{{ getMobile }}</div>
|
||||
</div>
|
||||
<div class="m-sign-up__text">رمز پیامک شده را وارد کنید</div>
|
||||
<div class="m-sign-up__form">
|
||||
<div class="m-sign-up__form-row m-sign-up__simple-input">
|
||||
<div
|
||||
class="form-group "
|
||||
class="form-group"
|
||||
:class="{ 'form-group--error': $v.code.$error }"
|
||||
>
|
||||
<input
|
||||
|
@ -96,7 +96,7 @@
|
|||
</div>
|
||||
<div class="m-sign-up__button-container">
|
||||
<a @click.prevent="goBack" :href="$t('Back')">{{ $t("Back") }}</a>
|
||||
<button v-on:click="doActivate">
|
||||
<button v-on:click="doActivate">
|
||||
{{ $t("Verify") }}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -106,7 +106,8 @@
|
|||
|
||||
<script>
|
||||
import authMixin from "~/mixins/authMixin";
|
||||
import { required, minLength } from "vuelidate/lib/validators";
|
||||
|
||||
import { required, minLength } from "@vuelidate/validators";
|
||||
import { useCommonStore } from "~/stores/commonStore";
|
||||
import { useAuthStore } from "~/stores/authStore";
|
||||
import { mapState } from "pinia";
|
||||
|
@ -147,7 +148,11 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(useAuthStore,["getMobile", "getFullName", "getResetPasswordState"]),
|
||||
...mapState(useAuthStore, [
|
||||
"getMobile",
|
||||
"getFullName",
|
||||
"getResetPasswordState",
|
||||
]),
|
||||
},
|
||||
methods: {
|
||||
resetErrors() {
|
||||
|
@ -187,9 +192,9 @@ export default {
|
|||
|
||||
const { $eventBus } = useNuxtApp();
|
||||
$eventBus.emit(
|
||||
'authenticated-by-modal',
|
||||
this.$route.query["invite-id"]
|
||||
);
|
||||
"authenticated-by-modal",
|
||||
this.$route.query["invite-id"]
|
||||
);
|
||||
|
||||
// vm.$router.push({
|
||||
// name: "dashboard",
|
||||
|
@ -226,7 +231,7 @@ export default {
|
|||
const vm = this;
|
||||
|
||||
var timeleft = timeInSecond;
|
||||
var downloadTimer = setInterval(function() {
|
||||
var downloadTimer = setInterval(function () {
|
||||
if (timeleft <= 0) {
|
||||
clearInterval(downloadTimer);
|
||||
vm.$refs.countdown.innerHTML = "ارسال مجدد";
|
||||
|
@ -250,7 +255,7 @@ export default {
|
|||
display: inline-block !important;
|
||||
text-align: center !important;
|
||||
border: none !important;
|
||||
background:unset !important;
|
||||
background: unset !important;
|
||||
&[disabled] {
|
||||
min-width: 4em !important;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ import {
|
|||
minLength,
|
||||
maxLength,
|
||||
between,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
|
||||
export default {
|
||||
name: "forget",
|
||||
|
|
|
@ -156,7 +156,7 @@ import {
|
|||
minLength,
|
||||
maxLength,
|
||||
between,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
|
|
|
@ -116,7 +116,7 @@ import {
|
|||
minLength,
|
||||
maxLength,
|
||||
between,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
|
||||
import { mapState, mapActions } from "pinia";
|
||||
import { useCommonStore } from "~/stores/commonStore";
|
||||
|
|
|
@ -207,7 +207,7 @@ import {
|
|||
maxLength,
|
||||
between,
|
||||
sameAs,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
|
||||
export default {
|
||||
mounted(){
|
||||
|
|
|
@ -93,7 +93,7 @@ import {
|
|||
maxLength,
|
||||
between,
|
||||
sameAs,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
|
||||
export default {
|
||||
validations: {
|
||||
|
|
|
@ -110,7 +110,7 @@ import {
|
|||
required,
|
||||
minLength,
|
||||
sameAs,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
import { mapState, mapActions } from "pinia";
|
||||
import { useCommonStore } from "~/stores/commonStore";
|
||||
import { useAuthStore } from "~/stores/authStore";
|
||||
|
|
|
@ -34,12 +34,8 @@
|
|||
|
||||
<script>
|
||||
import authMixin from "~/mixins/authMixin";
|
||||
import {
|
||||
required,
|
||||
minLength,
|
||||
maxLength,
|
||||
between,
|
||||
} from "vuelidate/lib/validators";
|
||||
|
||||
import { required, minLength, maxLength, between } from "@vuelidate/validators";
|
||||
|
||||
export default {
|
||||
name: "forget",
|
||||
|
|
|
@ -116,7 +116,7 @@ import {
|
|||
minLength,
|
||||
maxLength,
|
||||
between,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
|
||||
import { mapState, mapActions } from "pinia";
|
||||
import { useCommonStore } from "~/stores/commonStore";
|
||||
|
|
|
@ -146,7 +146,7 @@ import {
|
|||
maxLength,
|
||||
between,
|
||||
sameAs,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
|
||||
export default {
|
||||
validations: {
|
||||
|
|
|
@ -107,7 +107,7 @@ import {
|
|||
required,
|
||||
minLength,
|
||||
sameAs,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
import { mapState, mapActions } from "pinia";
|
||||
|
||||
export default {
|
||||
|
|
|
@ -44,7 +44,7 @@ import {
|
|||
minLength,
|
||||
maxLength,
|
||||
between,
|
||||
} from "vuelidate/lib/validators";
|
||||
} from "@vuelidate/validators";
|
||||
|
||||
export default {
|
||||
validations: {
|
||||
|
|
|
@ -63,8 +63,8 @@
|
|||
<div class="row">
|
||||
<div class="col-sm-6 mb-2 mb-sm-0 col-md mb-sm-2 mb-md-0">
|
||||
<div class="link-item-container">
|
||||
<a
|
||||
:href="urlResolver('qq309202')"
|
||||
<NuxtLink
|
||||
:to="urlResolver('qq309202')"
|
||||
target="_blank"
|
||||
class="btn link-item"
|
||||
>
|
||||
|
@ -80,13 +80,13 @@
|
|||
<div class="more-text-container">
|
||||
<span class="more-text"> مشاهده بیشتر </span>
|
||||
</div>
|
||||
</a>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 mb-2 mb-sm-0 col-md mb-sm-2 mb-md-0">
|
||||
<div class="link-item-container">
|
||||
<a
|
||||
:href="urlResolver('qq308235')"
|
||||
<NuxtLink
|
||||
:to="urlResolver('qq308235')"
|
||||
target="_blank"
|
||||
class="btn link-item"
|
||||
>
|
||||
|
@ -100,13 +100,13 @@
|
|||
<div class="more-text-container">
|
||||
<span class="more-text"> مشاهده بیشتر </span>
|
||||
</div>
|
||||
</a>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 mb-2 mb-sm-0 col-md">
|
||||
<div class="link-item-container">
|
||||
<a
|
||||
:href="urlResolver('qq38162')"
|
||||
<NuxtLink
|
||||
:to="urlResolver('qq38162')"
|
||||
target="_blank"
|
||||
class="btn link-item"
|
||||
>
|
||||
|
@ -120,13 +120,13 @@
|
|||
<div class="more-text-container">
|
||||
<span class="more-text"> مشاهده بیشتر </span>
|
||||
</div>
|
||||
</a>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 mb-2 mb-sm-0 col-md">
|
||||
<div class="link-item-container">
|
||||
<a
|
||||
:href="urlResolver('qq233930')"
|
||||
<NuxtLink
|
||||
:to="urlResolver('qq233930')"
|
||||
target="_blank"
|
||||
class="btn link-item"
|
||||
>
|
||||
|
@ -140,7 +140,7 @@
|
|||
<div class="more-text-container">
|
||||
<span class="more-text"> مشاهده بیشتر </span>
|
||||
</div>
|
||||
</a>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -156,7 +156,8 @@ import searchApi from "~/apis/searchApi";
|
|||
import { mapState, mapActions } from "pinia";
|
||||
import { useCommonStore } from "~/stores/commonStore";
|
||||
import { useStorage } from "@vueuse/core";
|
||||
import {clearBodyClass} from "@manuals/utilities"
|
||||
import { clearBodyClass } from "@manuals/utilities";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
export default {
|
||||
beforeMount() {
|
||||
|
@ -164,7 +165,7 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
this.setBodyClass("majles-user-panel");
|
||||
let localStoageSearchSchema = useStorage("searchSchema",undefined).value;
|
||||
let localStoageSearchSchema = useStorage("searchSchema", undefined).value;
|
||||
if (localStoageSearchSchema) {
|
||||
let searchSchema = JSON.parse(localStoageSearchSchema);
|
||||
this.schemasSetter(searchSchema);
|
||||
|
@ -255,7 +256,9 @@ export default {
|
|||
},
|
||||
|
||||
urlResolver(_id) {
|
||||
return "";
|
||||
const router = `search/qasection/${_id}/show`;
|
||||
|
||||
return router;
|
||||
// const routeData = this.$router.resolve({
|
||||
// path: "navigation",
|
||||
// params: {
|
||||
|
@ -272,7 +275,6 @@ export default {
|
|||
|
||||
<style lang="scss">
|
||||
@import "../../../assets/majles/scss/majles";
|
||||
|
||||
.custom-class {
|
||||
.dropdown-toggle {
|
||||
color: rgba(0, 0, 0, 0.5) !important;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
>{{ getLabel() }}:</label
|
||||
>
|
||||
<div>
|
||||
<codemirror
|
||||
<!-- <codemirror
|
||||
:options="cmOptions"
|
||||
class="markdown-preview"
|
||||
v-model="textValue"
|
||||
|
@ -12,7 +12,7 @@
|
|||
:id="localFormElement.key"
|
||||
:name="localFormElement.key"
|
||||
ref="myCm"
|
||||
></codemirror>
|
||||
></codemirror> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -21,20 +21,20 @@
|
|||
import { mapState } from "pinia";
|
||||
import formBuilderMixin from "@mixins/formBuilderMixin";
|
||||
|
||||
import { codemirror } from "vue-codemirror";
|
||||
import "vue-codemirror/node_modules/codemirror/lib/codemirror.css";
|
||||
import "vue-codemirror/node_modules/codemirror/mode/markdown/markdown.js";
|
||||
import "vue-codemirror/node_modules/codemirror/mode/javascript/javascript.js";
|
||||
import "vue-codemirror/node_modules/codemirror/mode/css/css.js";
|
||||
import "vue-codemirror/node_modules/codemirror/mode/vue/vue.js";
|
||||
import "vue-codemirror/node_modules/codemirror/mode/htmlmixed/htmlmixed.js";
|
||||
import "vue-codemirror/node_modules/codemirror/addon/edit/closebrackets.js";
|
||||
import "vue-codemirror/node_modules/codemirror/addon/edit/matchbrackets.js";
|
||||
import "vue-codemirror/node_modules/codemirror/addon/edit/closetag.js";
|
||||
import "vue-codemirror/node_modules/codemirror/addon/display/placeholder.js";
|
||||
import "vue-codemirror/node_modules/codemirror/addon/scroll/simplescrollbars.js";
|
||||
import "vue-codemirror/node_modules/codemirror/addon/scroll/simplescrollbars.css";
|
||||
import "vue-codemirror/node_modules/codemirror/addon/selection/active-line.js";
|
||||
// import { codemirror } from "vue-codemirror";
|
||||
// import "vue-codemirror/node_modules/codemirror/lib/codemirror.css";
|
||||
// import "vue-codemirror/node_modules/codemirror/mode/markdown/markdown.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/mode/javascript/javascript.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/mode/css/css.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/mode/vue/vue.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/mode/htmlmixed/htmlmixed.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/addon/edit/closebrackets.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/addon/edit/matchbrackets.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/addon/edit/closetag.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/addon/display/placeholder.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/addon/scroll/simplescrollbars.js";
|
||||
// import "vue-codemirror/node_modules/codemirror/addon/scroll/simplescrollbars.css";
|
||||
// import "vue-codemirror/node_modules/codemirror/addon/selection/active-line.js";
|
||||
|
||||
export default {
|
||||
mixins: [formBuilderMixin],
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div class="row form-group" :key="$attrs.key">
|
||||
<label :for="localFormElement?.key" class="col-md-3">{{
|
||||
localFormElement?.label
|
||||
}}:</label>
|
||||
<label :for="localFormElement?.key" class="col-md-3"
|
||||
>{{ localFormElement?.label }}:</label
|
||||
>
|
||||
|
||||
<div v-if="isInitial" class="dropbox">
|
||||
<input
|
||||
|
@ -57,8 +57,8 @@ const STATUS_INITIAL = 0,
|
|||
STATUS_SUCCESS = 2,
|
||||
STATUS_FAILED = 3;
|
||||
|
||||
import { upload } from "@services/fileUploadService";
|
||||
import { wait } from "@utilities/utilities.js";
|
||||
// import { upload } from "@services/fileUploadService.js";
|
||||
import { wait } from "~/manuals/utilities.js";
|
||||
|
||||
import formBuilderMixin from "@mixins/formBuilderMixin";
|
||||
export default {
|
||||
|
@ -107,16 +107,16 @@ export default {
|
|||
// upload data to the server
|
||||
this.currentStatus = STATUS_SAVING;
|
||||
|
||||
upload(formData)
|
||||
.then(wait(1500)) // DEV ONLY: wait for 1.5s
|
||||
.then((x) => {
|
||||
this.uploadedFiles = [].concat(x);
|
||||
this.currentStatus = STATUS_SUCCESS;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.uploadError = err.response;
|
||||
this.currentStatus = STATUS_FAILED;
|
||||
});
|
||||
// upload(formData)
|
||||
// .then(wait(1500)) // DEV ONLY: wait for 1.5s
|
||||
// .then((x) => {
|
||||
// this.uploadedFiles = [].concat(x);
|
||||
// this.currentStatus = STATUS_SUCCESS;
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// this.uploadError = err.response;
|
||||
// this.currentStatus = STATUS_FAILED;
|
||||
// });
|
||||
},
|
||||
reset() {
|
||||
// reset form to initial state
|
||||
|
|
|
@ -92,7 +92,7 @@ export default {
|
|||
// datePicker: VuePersianDatetimePicker,
|
||||
datePicker: () =>
|
||||
import(
|
||||
"vue-persian-datetime-picker"
|
||||
"vue3-persian-datetime-picker"
|
||||
),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -30,13 +30,15 @@
|
|||
|
||||
<script>
|
||||
import formBuilderMixin from "@mixins/formBuilderMixin";
|
||||
import HttpService from "@services/httpService";
|
||||
// import HttpService from "@services/httpService";
|
||||
|
||||
export default {
|
||||
// props:["listOptions"],
|
||||
|
||||
mixins: [formBuilderMixin],
|
||||
|
||||
created() {
|
||||
this.httpService = useNuxtApp()["$http"];
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(() => {
|
||||
this.setOptions();
|
||||
|
@ -45,7 +47,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
httpService: undefined,
|
||||
httpService: {},
|
||||
optionRendering: false,
|
||||
listOptions: [],
|
||||
};
|
||||
|
@ -173,7 +175,7 @@ export default {
|
|||
if (this.optionRendering) return;
|
||||
|
||||
let vm = this;
|
||||
this.httpService = new HttpService();
|
||||
// this.httpService = new HttpService();
|
||||
|
||||
this.optionRendering = true;
|
||||
|
||||
|
|
|
@ -1,299 +1,309 @@
|
|||
<template>
|
||||
<aside
|
||||
class="nav-sidebar"
|
||||
:class="[
|
||||
{
|
||||
' js-sidebar-collapsed ': isSidebarCollapsed,
|
||||
' sidebar-expanded-mobile ': isMobile && !isSidebarCollapsed,
|
||||
' sidebar-collapsed-desktop ': isDesktop && isSidebarCollapsed,
|
||||
},
|
||||
buildName() + '-sidebar',
|
||||
]"
|
||||
>
|
||||
<!-- #region mobile-header -->
|
||||
|
||||
<div class="mobile-header pt-2 p-0">
|
||||
<NuxtLink to="/" classes="btn mobile-close-sidebar">
|
||||
<img
|
||||
:src="logo"
|
||||
:alt="appLongTitle()"
|
||||
class="img-fluid"
|
||||
style="width: 2em; filter: invert(0)"
|
||||
/>
|
||||
{{ appShortTitle() }}
|
||||
</NuxtLink>
|
||||
|
||||
<button-component
|
||||
@click="sidebarCollapsedSetter(true)"
|
||||
classes="mobile-close-sidebar"
|
||||
buttonText=""
|
||||
>
|
||||
<span class="tavasi tavasi-Component-71--1"></span>
|
||||
</button-component>
|
||||
</div>
|
||||
<!-- #endregion mobile-header -->
|
||||
|
||||
<!-- #region sidebar -->
|
||||
<div
|
||||
class="nav-sidebar-inner-scroll d-flex flex-column firefox-scrollbar justify-content-between"
|
||||
<client-only>
|
||||
<aside
|
||||
class="nav-sidebar"
|
||||
:class="[
|
||||
{
|
||||
' js-sidebar-collapsed ': isSidebarCollapsed,
|
||||
' sidebar-expanded-mobile ': isMobile && !isSidebarCollapsed,
|
||||
' sidebar-collapsed-desktop ': isDesktop && isSidebarCollapsed,
|
||||
},
|
||||
buildName() + '-sidebar',
|
||||
]"
|
||||
>
|
||||
<ClientOnly>
|
||||
<ul class="sidebar-top-level-items">
|
||||
<template v-for="(menuItem, mainKey) in menu">
|
||||
<li
|
||||
v-if="isShowMenuItem(mainKey, menuItem)"
|
||||
class="mb-1"
|
||||
@mouseenter="emitCustomEvent($event, 'in')"
|
||||
@mouseleave="emitCustomEvent($event, 'out')"
|
||||
v-for="(item, key, index) in menuItem"
|
||||
:key="index"
|
||||
:class="['color-' + item.color]"
|
||||
>
|
||||
<template v-if="isShowMenuItem(key, item)">
|
||||
<template v-if="item?.subMenu?.length">
|
||||
<NuxtLink
|
||||
:to="{ name: item.link }"
|
||||
class="has-sub-items gl-link"
|
||||
:class="{ active: $route.name.startsWith(item.link) }"
|
||||
>
|
||||
<!-- <i class="nav-icon-container" :class="item.icon"></i> -->
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + item.icon"
|
||||
>
|
||||
<use :xlink:href="'#icon-' + item.icon"></use>
|
||||
</svg>
|
||||
<span class="nav-item-name">
|
||||
{{ $t(translateKey(item)) }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
<!-- #region mobile-header -->
|
||||
|
||||
<ul class="sidebar-sub-level-items li-child" :id="item.link">
|
||||
<li class="fly-out-top-item active gl-link">
|
||||
<span class="fly-out-top-item-container">
|
||||
<strong class="fly-out-top-item-name">
|
||||
{{ $t(translateKey(item)) }}
|
||||
</strong>
|
||||
<div class="mobile-header pt-2 p-0">
|
||||
<NuxtLink to="/" classes="btn mobile-close-sidebar">
|
||||
<img
|
||||
:src="logo"
|
||||
:alt="appLongTitle()"
|
||||
class="img-fluid"
|
||||
style="width: 2em; filter: invert(0)"
|
||||
/>
|
||||
{{ appShortTitle() }}
|
||||
</NuxtLink>
|
||||
|
||||
<button-component
|
||||
@click="sidebarCollapsedSetter(true)"
|
||||
classes="mobile-close-sidebar"
|
||||
buttonText=""
|
||||
>
|
||||
<span class="tavasi tavasi-Component-71--1"></span>
|
||||
</button-component>
|
||||
</div>
|
||||
<!-- #endregion mobile-header -->
|
||||
|
||||
<!-- #region sidebar -->
|
||||
<div
|
||||
class="nav-sidebar-inner-scroll d-flex flex-column firefox-scrollbar justify-content-between"
|
||||
>
|
||||
<ClientOnly>
|
||||
<ul class="sidebar-top-level-items">
|
||||
<template v-for="(menuItem, mainKey) in menu">
|
||||
<li
|
||||
v-if="isShowMenuItem(mainKey, menuItem)"
|
||||
class="mb-1"
|
||||
@mouseenter="emitCustomEvent($event, 'in')"
|
||||
@mouseleave="emitCustomEvent($event, 'out')"
|
||||
v-for="(item, key, index) in menuItem"
|
||||
:key="index"
|
||||
:class="['color-' + item.color]"
|
||||
>
|
||||
<template v-if="isShowMenuItem(key, item)">
|
||||
<template v-if="item?.subMenu?.length">
|
||||
<NuxtLink
|
||||
:to="{ name: item.link }"
|
||||
class="has-sub-items gl-link"
|
||||
:class="{ active: $route.name.startsWith(item.link) }"
|
||||
>
|
||||
<!-- <i class="nav-icon-container" :class="item.icon"></i> -->
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + item.icon"
|
||||
>
|
||||
<use :xlink:href="'#icon-' + item.icon"></use>
|
||||
</svg>
|
||||
<span class="nav-item-name">
|
||||
{{ $t(translateKey(item)) }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="divider fly-out-top-item"></li>
|
||||
</NuxtLink>
|
||||
|
||||
<li
|
||||
class="li-child"
|
||||
v-for="(child, j) in item.subMenu"
|
||||
:key="j"
|
||||
<ul
|
||||
class="sidebar-sub-level-items li-child"
|
||||
:id="item.link"
|
||||
>
|
||||
<template v-if="child?.subMenu?.length">
|
||||
<NuxtLink
|
||||
:to="{ name: child.link }"
|
||||
class="has-sub-items gl-link"
|
||||
exact-path
|
||||
>
|
||||
<!-- <i class="nav-icon-container" :class="child.icon"></i> -->
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + child.icon"
|
||||
>
|
||||
<use :xlink:href="'#icon-' + child.icon"></use>
|
||||
</svg>
|
||||
<span class="nav-item-name">
|
||||
{{ $t(translateKey(child)) }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
<li class="fly-out-top-item active gl-link">
|
||||
<span class="fly-out-top-item-container">
|
||||
<strong class="fly-out-top-item-name">
|
||||
{{ $t(translateKey(item)) }}
|
||||
</strong>
|
||||
</span>
|
||||
</li>
|
||||
<li class="divider fly-out-top-item"></li>
|
||||
|
||||
<ul class="sidebar-sub-level-items" :id="child.link">
|
||||
<li class="fly-out-top-item active gl-link">
|
||||
<span class="fly-out-top-item-container">
|
||||
<strong class="fly-out-top-item-name">
|
||||
{{ $t(translateKey(child)) }}
|
||||
</strong>
|
||||
</span>
|
||||
</li>
|
||||
<li class="divider fly-out-top-item"></li>
|
||||
|
||||
<li
|
||||
v-for="(descendant, k) in child.subMenu"
|
||||
@click.prevent="navigateTo(descendant)"
|
||||
:key="k"
|
||||
<li
|
||||
class="li-child"
|
||||
v-for="(child, j) in item.subMenu"
|
||||
:key="j"
|
||||
>
|
||||
<template v-if="child?.subMenu?.length">
|
||||
<NuxtLink
|
||||
:to="{ name: child.link }"
|
||||
class="has-sub-items gl-link"
|
||||
exact-path
|
||||
>
|
||||
<NuxtLink
|
||||
exact-path
|
||||
:to="{ name: descendant.link }"
|
||||
:title="descendant.title"
|
||||
class="gl-link btn sub-level-item"
|
||||
<!-- <i class="nav-icon-container" :class="child.icon"></i> -->
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + child.icon"
|
||||
>
|
||||
<!-- <svg-icon-component :iconName="descendant.icon" /> -->
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + descendant.icon"
|
||||
<use :xlink:href="'#icon-' + child.icon"></use>
|
||||
</svg>
|
||||
<span class="nav-item-name">
|
||||
{{ $t(translateKey(child)) }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
|
||||
<ul class="sidebar-sub-level-items" :id="child.link">
|
||||
<li class="fly-out-top-item active gl-link">
|
||||
<span class="fly-out-top-item-container">
|
||||
<strong class="fly-out-top-item-name">
|
||||
{{ $t(translateKey(child)) }}
|
||||
</strong>
|
||||
</span>
|
||||
</li>
|
||||
<li class="divider fly-out-top-item"></li>
|
||||
|
||||
<li
|
||||
v-for="(descendant, k) in child.subMenu"
|
||||
@click.prevent="navigateTo(descendant)"
|
||||
:key="k"
|
||||
>
|
||||
<NuxtLink
|
||||
exact-path
|
||||
:to="{ name: descendant.link }"
|
||||
:title="descendant.title"
|
||||
class="gl-link btn sub-level-item"
|
||||
>
|
||||
<use
|
||||
:xlink:href="'#icon-' + descendant.icon"
|
||||
></use>
|
||||
</svg>
|
||||
<!-- <i
|
||||
<!-- <svg-icon-component :iconName="descendant.icon" /> -->
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + descendant.icon"
|
||||
>
|
||||
<use
|
||||
:xlink:href="'#icon-' + descendant.icon"
|
||||
></use>
|
||||
</svg>
|
||||
<!-- <i
|
||||
class="nav-icon-container "
|
||||
:class="descendant.icon"
|
||||
>
|
||||
<span class="path1"></span
|
||||
><span class="path2"></span>
|
||||
</i> -->
|
||||
<span class="nav-item-name gl-link me-1">
|
||||
{{ descendant.title }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<span class="nav-item-name gl-link me-1">
|
||||
{{ descendant.title }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<NuxtLink
|
||||
v-else
|
||||
exact-path
|
||||
:to="{ name: child.link }"
|
||||
:title="$t(translateKey(child))"
|
||||
class="gl-link btn sub-level-item"
|
||||
>
|
||||
<svg-icon-component :iconName="child.icon" />
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + child.icon"
|
||||
<NuxtLink
|
||||
v-else
|
||||
exact-path
|
||||
:to="{ name: child.link }"
|
||||
:title="$t(translateKey(child))"
|
||||
class="gl-link btn sub-level-item"
|
||||
>
|
||||
<use :xlink:href="'#icon-' + child.icon"></use>
|
||||
</svg>
|
||||
<!-- <i class="nav-icon-container " :class="child.icon">
|
||||
<svg-icon-component :iconName="child.icon" />
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + child.icon"
|
||||
>
|
||||
<use :xlink:href="'#icon-' + child.icon"></use>
|
||||
</svg>
|
||||
<!-- <i class="nav-icon-container " :class="child.icon">
|
||||
<span class="path1"></span><span class="path2"></span>
|
||||
</i> -->
|
||||
<span class="nav-item-name gl-link me-1">
|
||||
{{ $t(translateKey(child)) }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<span class="nav-item-name gl-link me-1">
|
||||
{{ $t(translateKey(child)) }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<NuxtLink
|
||||
v-else
|
||||
:to="{ name: item.link }"
|
||||
:title="$t(translateKey(item))"
|
||||
class="gl-link"
|
||||
exact-path
|
||||
>
|
||||
<!-- <svg-icon-component :iconName="item.icon" /> -->
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + item.icon"
|
||||
<NuxtLink
|
||||
v-else
|
||||
:to="{ name: item.link }"
|
||||
:title="$t(translateKey(item))"
|
||||
class="gl-link"
|
||||
exact-path
|
||||
>
|
||||
<use :xlink:href="'#icon-' + item.icon"></use>
|
||||
</svg>
|
||||
<!-- <i class="nav-icon-container" :class="item.icon">
|
||||
<!-- <svg-icon-component :iconName="item.icon" /> -->
|
||||
<svg
|
||||
class="nav-icon-container"
|
||||
:class="'icon icon-' + item.icon"
|
||||
>
|
||||
<use :xlink:href="'#icon-' + item.icon"></use>
|
||||
</svg>
|
||||
<!-- <i class="nav-icon-container" :class="item.icon">
|
||||
<span class="path1"></span><span class="path2"></span
|
||||
></i> -->
|
||||
<span class="nav-item-name">
|
||||
{{ $t(translateKey(item)) }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
|
||||
<!-- <template v-if="isSidebarCollapsed"> -->
|
||||
<div class="mb-5 mb-md-0">
|
||||
<ul class="sidebar-top-level-items m-0">
|
||||
<li
|
||||
v-if="!isMajlesBuild()"
|
||||
class=""
|
||||
@mouseenter="emitCustomEvent($event, 'in')"
|
||||
@mouseleave="emitCustomEvent($event, 'out')"
|
||||
>
|
||||
<a class="has-sub-items gl-link">
|
||||
<svg
|
||||
v-if="isGuest && showRegister"
|
||||
class="icon icon-personal"
|
||||
>
|
||||
<use
|
||||
class="icon-personal"
|
||||
xlink:href="#icon-personal"
|
||||
></use>
|
||||
</svg>
|
||||
<img
|
||||
v-else
|
||||
class="nav-icon-container img-fluid user-avatar"
|
||||
:src="avatar"
|
||||
/>
|
||||
<span class="nav-item-name">
|
||||
{{ $t(translateKey(item)) }}
|
||||
{{ currentUser?.user_data?.first_name }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</a>
|
||||
|
||||
<!-- <template v-if="isSidebarCollapsed"> -->
|
||||
<div class="mb-5 mb-md-0">
|
||||
<ul class="sidebar-top-level-items m-0">
|
||||
<li
|
||||
v-if="!isMajlesBuild()"
|
||||
class=""
|
||||
@mouseenter="emitCustomEvent($event, 'in')"
|
||||
@mouseleave="emitCustomEvent($event, 'out')"
|
||||
>
|
||||
<a class="has-sub-items gl-link">
|
||||
<svg v-if="isGuest && showRegister" class="icon icon-personal">
|
||||
<use class="icon-personal" xlink:href="#icon-personal"></use>
|
||||
</svg>
|
||||
<img
|
||||
v-else
|
||||
class="nav-icon-container img-fluid user-avatar"
|
||||
:src="avatar"
|
||||
/>
|
||||
<span class="nav-item-name">
|
||||
{{ currentUser?.user_data?.first_name }}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<ul class="sidebar-sub-level-items">
|
||||
<!-- <li class="fly-out-top-item gl-link">
|
||||
<ul class="sidebar-sub-level-items">
|
||||
<!-- <li class="fly-out-top-item gl-link">
|
||||
<h6 class="bg-white text-center py-3">
|
||||
{{ userFullname(currentUser?.user_data) }}
|
||||
</h6>
|
||||
</li> -->
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<NuxtLink
|
||||
v-can="'admin_dahsboard'"
|
||||
:to="{ name: 'admin' }"
|
||||
class="dropdown-item"
|
||||
exact-path
|
||||
>{{ $t("admin") }}</NuxtLink
|
||||
>
|
||||
</li>
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<NuxtLink
|
||||
v-can="'admin_dahsboard'"
|
||||
:to="{ name: 'admin' }"
|
||||
class="dropdown-item"
|
||||
exact-path
|
||||
>{{ $t("admin") }}</NuxtLink
|
||||
>
|
||||
</li>
|
||||
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<a
|
||||
href="install PWA"
|
||||
title="نصب سامانه - در صفحه گوشی یا رایانه"
|
||||
class="dropdown-item"
|
||||
type="button"
|
||||
@click.prevent="checkBeforeInstallingPwa()"
|
||||
>
|
||||
{{ $t("InstallSystem") }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<a
|
||||
href="exit"
|
||||
@click.prevent="logout()"
|
||||
class="dropdown-item"
|
||||
>
|
||||
{{ $t("Exit") }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<a
|
||||
href="/refresh-page"
|
||||
v-if="isNewVersionAvailable"
|
||||
@click="reloadPage()"
|
||||
class="dropdown-item"
|
||||
>
|
||||
<svg style="height: 1em" class="icon icon-reset-form">
|
||||
<use xlink:href="#icon-reset-form"></use>
|
||||
</svg>
|
||||
بروزرسانی
|
||||
</a>
|
||||
</li>
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<a
|
||||
v-if="isGuest && showRegister"
|
||||
title="ثبت نام"
|
||||
href="/login"
|
||||
class="dropdown-item"
|
||||
>ثبت نام
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<template>
|
||||
<li class="">
|
||||
<a
|
||||
href="install PWA"
|
||||
title="نصب سامانه - در صفحه گوشی یا رایانه"
|
||||
class="dropdown-item"
|
||||
@click.prevent="sidebarCollapsedSetter(!isSidebarCollapsed)"
|
||||
class="toggle-sidebar-button"
|
||||
role="button"
|
||||
title="بازکردن"
|
||||
type="button"
|
||||
@click.prevent="checkBeforeInstallingPwa()"
|
||||
>
|
||||
{{ $t("InstallSystem") }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<a
|
||||
href="exit"
|
||||
@click.prevent="logout()"
|
||||
class="dropdown-item"
|
||||
>
|
||||
{{ $t("Exit") }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<a
|
||||
href="/refresh-page"
|
||||
v-if="isNewVersionAvailable"
|
||||
@click="reloadPage()"
|
||||
class="dropdown-item"
|
||||
>
|
||||
<svg style="height: 1em" class="icon icon-reset-form">
|
||||
<use xlink:href="#icon-reset-form"></use>
|
||||
<svg class="icon icon-chevron-double-left">
|
||||
<use xlink:href="#icon-chevron-double-left"></use>
|
||||
</svg>
|
||||
بروزرسانی
|
||||
</a>
|
||||
</li>
|
||||
<li class="fly-out-top-item gl-link">
|
||||
<a
|
||||
v-if="isGuest && showRegister"
|
||||
title="ثبت نام"
|
||||
href="/login"
|
||||
class="dropdown-item"
|
||||
>ثبت نام
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<template>
|
||||
<li class="">
|
||||
<a
|
||||
@click.prevent="sidebarCollapsedSetter(!isSidebarCollapsed)"
|
||||
class="toggle-sidebar-button"
|
||||
role="button"
|
||||
title="بازکردن"
|
||||
type="button"
|
||||
>
|
||||
<svg class="icon icon-chevron-double-left">
|
||||
<use xlink:href="#icon-chevron-double-left"></use>
|
||||
</svg>
|
||||
|
||||
<!-- <svg
|
||||
<!-- <svg
|
||||
class="icon icon-chevron-double-left"
|
||||
data-testid="chevron-double-lg-left-icon"
|
||||
>
|
||||
|
@ -301,43 +311,44 @@
|
|||
href="@assets/common/img/icons.svg#chevron-double-lg-left"
|
||||
></use>
|
||||
</svg> -->
|
||||
<span class="collapse-text me-2">{{ $t("Close") }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
<span class="collapse-text me-2">{{ $t("Close") }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
|
||||
<!-- #endregion sidebar -->
|
||||
<!-- #endregion sidebar -->
|
||||
|
||||
<!-- #region base-modal -->
|
||||
<base-modal-v2
|
||||
v-if="uploadForFirstTime"
|
||||
@close="closeModal"
|
||||
@canel="closeModal()"
|
||||
:showHeaderCloseButton="true"
|
||||
:modalTitle="modalTitle"
|
||||
class="borhan-modal"
|
||||
modalSize="modal-lg"
|
||||
height="30em"
|
||||
overflow="hidden"
|
||||
:showSaveButton="false"
|
||||
:showCloseButton="false"
|
||||
>
|
||||
<settings
|
||||
:uploadForFirstTime="uploadForFirstTime"
|
||||
:menuId="menuId"
|
||||
<!-- #region base-modal -->
|
||||
<base-modal-v2
|
||||
v-if="uploadForFirstTime"
|
||||
@close="closeModal"
|
||||
@canel="closeModal()"
|
||||
@close="closeModal()"
|
||||
@after-select-file="afterSelectFile()"
|
||||
></settings>
|
||||
</base-modal-v2>
|
||||
<!-- #endregion base-modal -->
|
||||
:showHeaderCloseButton="true"
|
||||
:modalTitle="modalTitle"
|
||||
class="borhan-modal"
|
||||
modalSize="modal-lg"
|
||||
height="30em"
|
||||
overflow="hidden"
|
||||
:showSaveButton="false"
|
||||
:showCloseButton="false"
|
||||
>
|
||||
<settings
|
||||
:uploadForFirstTime="uploadForFirstTime"
|
||||
:menuId="menuId"
|
||||
@canel="closeModal()"
|
||||
@close="closeModal()"
|
||||
@after-select-file="afterSelectFile()"
|
||||
></settings>
|
||||
</base-modal-v2>
|
||||
<!-- #endregion base-modal -->
|
||||
|
||||
<SvgIconComponent></SvgIconComponent>
|
||||
</aside>
|
||||
<SvgIconComponent></SvgIconComponent>
|
||||
</aside>
|
||||
</client-only>
|
||||
</template>
|
||||
<script>
|
||||
import { mapState, mapActions } from "pinia";
|
||||
|
|
80
components/other/ImageCropper.vue
Normal file
|
@ -0,0 +1,80 @@
|
|||
<template>
|
||||
<div>
|
||||
<input type="file" accept="image/*" @change="onFileChange" />
|
||||
<div v-if="imageSrc" class="cropper-container">
|
||||
<img ref="image" :src="imageSrc" alt="Image to crop" />
|
||||
</div>
|
||||
<button v-if="imageSrc" @click="cropImage">Crop and Upload</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||
import Cropper from 'cropperjs';
|
||||
import 'cropperjs/dist/cropper.css';
|
||||
|
||||
const imageSrc = ref(null);
|
||||
const image = ref(null);
|
||||
let cropper = null;
|
||||
|
||||
const onFileChange = (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (event) => {
|
||||
imageSrc.value = event.target.result;
|
||||
initCropper();
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
};
|
||||
|
||||
const initCropper = () => {
|
||||
if (cropper) {
|
||||
cropper.destroy();
|
||||
}
|
||||
cropper = new Cropper(image.value, {
|
||||
aspectRatio: 1, // Set aspect ratio (e.g., 1 for square)
|
||||
viewMode: 1, // Restrict the crop box to the size of the image
|
||||
});
|
||||
};
|
||||
|
||||
const cropImage = () => {
|
||||
if (cropper) {
|
||||
const croppedCanvas = cropper.getCroppedCanvas();
|
||||
croppedCanvas.toBlob((blob) => {
|
||||
uploadImage(blob);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const uploadImage = async (blob) => {
|
||||
const formData = new FormData();
|
||||
formData.append('image', blob, 'cropped-image.png');
|
||||
|
||||
try {
|
||||
const response = await $fetch('/api/upload', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
alert('Image uploaded successfully!');
|
||||
console.log('Upload response:', response);
|
||||
} catch (error) {
|
||||
console.error('Error uploading image:', error);
|
||||
alert('Error uploading image');
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (cropper) {
|
||||
cropper.destroy();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cropper-container {
|
||||
max-width: 100%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
|
@ -86,13 +86,13 @@ import repoApi from "~/apis/repoApi";
|
|||
import { mapState } from "pinia";
|
||||
import { useCommonStore } from "~/stores/commonStore";
|
||||
|
||||
import SelectComponentDefault from "~/components/SelectComponentDefault.vue";
|
||||
import SelectComponent from "~/components/SelectComponent.vue";
|
||||
import InputComponent from "~/components/InputComponent.vue";
|
||||
import LabelComponent from "~/components/LabelComponent.vue";
|
||||
import tagsComponent from "~/components/tagsComponent.vue";
|
||||
import DateComponent from "~/components/DateComponent.vue";
|
||||
import TextareaComponent from "~/components/TextareaComponent.vue";
|
||||
import SelectComponentDefault from "~/components/other/SelectComponentDefault.vue";
|
||||
import SelectComponent from "~/components/other/SelectComponent.vue";
|
||||
import InputComponent from "~/components/other/InputComponent.vue";
|
||||
import LabelComponent from "~/components/other/LabelComponent.vue";
|
||||
import tagsComponent from "~/components/other/tagsComponent.vue";
|
||||
import DateComponent from "~/components/other/DateComponent.vue";
|
||||
import TextareaComponent from "~/components/other/TextareaComponent.vue";
|
||||
/**
|
||||
* @vue-data {Object} [listUpdatedText = {}] - متنهای بهروزشده در لیست.
|
||||
* @vue-data {undefined} [httpService = undefined] - سرویس HTTP برای درخواستها.
|
||||
|
|
26
composables/useHadithaSearchComposable.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
// composables/useHadithaSearchComposable.js
|
||||
import { useStorage } from "@vueuse/core";
|
||||
|
||||
export const useHadithaSearchComposable = <T>(url: string, options = {}) => {
|
||||
// Get the authentication token (e.g., from a cookie or local storage)
|
||||
// const token = useCookie('auth-token') // Assuming you store the token in a cookie
|
||||
let token = useStorage("id_token", "GuestAccess");
|
||||
const config = useRuntimeConfig();
|
||||
console.info(config);
|
||||
|
||||
const baseURL =
|
||||
config.public.NUXT_PUBLIC_BASE_URL + config.public.NUXT_PUBLIC_API_NAME;
|
||||
|
||||
// Add headers to the request
|
||||
const headers = {
|
||||
Authorization: token.value,
|
||||
...options.headers, // Merge with any existing headers
|
||||
};
|
||||
|
||||
// Use useFetch with the headers
|
||||
return useFetch<T>(url, {
|
||||
...options,
|
||||
baseURL,
|
||||
headers,
|
||||
});
|
||||
};
|
|
@ -1,44 +1,44 @@
|
|||
import { useStorage } from "@vueuse/core";
|
||||
// import { useStorage } from "@vueuse/core";
|
||||
|
||||
import { ref } from "vue";
|
||||
import { useCommonStore } from "~/stores/commonStore";
|
||||
// import { ref } from "vue";
|
||||
// import { useCommonStore } from "~/stores/commonStore";
|
||||
|
||||
export function useMyComposable() {
|
||||
const count = ref(0);
|
||||
// export function useMyComposable() {
|
||||
// const count = ref(0);
|
||||
|
||||
const increment = () => {
|
||||
count.value++;
|
||||
};
|
||||
// const increment = () => {
|
||||
// count.value++;
|
||||
// };
|
||||
|
||||
const decrement = () => {
|
||||
count.value--;
|
||||
};
|
||||
// const decrement = () => {
|
||||
// count.value--;
|
||||
// };
|
||||
|
||||
return {
|
||||
count,
|
||||
increment,
|
||||
decrement,
|
||||
};
|
||||
}
|
||||
// return {
|
||||
// count,
|
||||
// increment,
|
||||
// decrement,
|
||||
// };
|
||||
// }
|
||||
|
||||
export function useGetSchema() {
|
||||
const commonStore = useCommonStore();
|
||||
// export function useGetSchema() {
|
||||
// const commonStore = useCommonStore();
|
||||
|
||||
try {
|
||||
return useAsyncData("shema", () =>
|
||||
$fetch("/api/ali", {
|
||||
headers: {
|
||||
headers: { Authorization: useStorage("id_token") },
|
||||
},
|
||||
method: "post",
|
||||
body: {
|
||||
organ: commonStore.organNameGetter,
|
||||
system: "search",
|
||||
build_state: buildState(),
|
||||
},
|
||||
})
|
||||
);
|
||||
} catch (err) {
|
||||
console.info(err);
|
||||
}
|
||||
}
|
||||
// try {
|
||||
// return useAsyncData("shema", () =>
|
||||
// $fetch("/api/ali", {
|
||||
// headers: {
|
||||
// headers: { Authorization: useStorage("id_token") },
|
||||
// },
|
||||
// method: "post",
|
||||
// body: {
|
||||
// organ: commonStore.organNameGetter,
|
||||
// system: "search",
|
||||
// build_state: buildState(),
|
||||
// },
|
||||
// })
|
||||
// );
|
||||
// } catch (err) {
|
||||
// console.info(err);
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
<script setup>
|
||||
import { clearBodyClass } from "@manuals/utilities";
|
||||
|
||||
onMounted(() => {
|
||||
clearBodyClass();
|
||||
});
|
||||
onUnmounted(() => {
|
||||
clearBodyClass();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="h-full">
|
||||
<slot name="named-slot"></slot>
|
||||
<slot></slot>
|
||||
</main>
|
||||
</template>
|
|
@ -1,167 +1,177 @@
|
|||
<!-- layouts/default.vue -->
|
||||
<template>
|
||||
<div>
|
||||
<header v-if="buildName() != 'majles'">
|
||||
<!-- //////////////////// begin navbar //////////////////// -->
|
||||
<nav
|
||||
class="navbar navbar-expand-md navbar-light bg-light"
|
||||
:class="{ expanded: !isSidebarCollapsed }"
|
||||
>
|
||||
<!-- sidebar menu toggler -->
|
||||
<button-component
|
||||
@click="sidebarCollapsedSetter(false)"
|
||||
classes="p-0 d-lg-none"
|
||||
buttonText=""
|
||||
<!-- //////////////////// begin navbar //////////////////// -->
|
||||
<template v-if="$attrs.showNavbar">
|
||||
<header v-if="buildName() != 'majles'">
|
||||
<nav
|
||||
class="navbar navbar-expand-md navbar-light bg-light"
|
||||
:class="{ expanded: !isSidebarCollapsed }"
|
||||
>
|
||||
<svg class="icon icon-Component-68--1">
|
||||
<use xlink:href="#icon-Component-68--1"></use>
|
||||
</svg>
|
||||
</button-component>
|
||||
<a
|
||||
class="navbar-brand d-none d-lg-inline-block"
|
||||
style="color: #00b6e3"
|
||||
>{{ navTitle }}</a
|
||||
>
|
||||
<a class="navbar-brand d-lg-none" style="color: #00b6e3">{{
|
||||
navShortTitle
|
||||
}}</a>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-toggle="collapse"
|
||||
data-target="#navbarSupportedContent"
|
||||
aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<!-- sidebar menu toggler -->
|
||||
<button-component
|
||||
@click="sidebarCollapsedSetter(false)"
|
||||
classes="p-0 d-lg-none"
|
||||
buttonText=""
|
||||
>
|
||||
<svg class="icon icon-Component-68--1">
|
||||
<use xlink:href="#icon-Component-68--1"></use>
|
||||
</svg>
|
||||
</button-component>
|
||||
<a
|
||||
class="navbar-brand d-none d-lg-inline-block"
|
||||
style="color: #00b6e3"
|
||||
>{{ navTitle }}</a
|
||||
>
|
||||
<a class="navbar-brand d-lg-none" style="color: #00b6e3">{{
|
||||
navShortTitle
|
||||
}}</a>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarSupportedContent"
|
||||
aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="navbar-collapse" id="navbarSupportedContent">
|
||||
<div class="collapse-mobile-header">
|
||||
<div>
|
||||
<img
|
||||
src="assets/common/img/logo/gray-logo.png"
|
||||
alt="هم فهمی"
|
||||
class="img-fluid"
|
||||
style="width: 2em; filter: invert(0)"
|
||||
/>
|
||||
هم فهمی
|
||||
<div class="navbar-collapse" id="navbarSupportedContent">
|
||||
<div class="collapse-mobile-header">
|
||||
<div>
|
||||
<img
|
||||
src="assets/common/img/logo/gray-logo.png"
|
||||
alt="هم فهمی"
|
||||
class="img-fluid"
|
||||
style="width: 2em; filter: invert(0)"
|
||||
/>
|
||||
هم فهمی
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="btn p-0 me-auto"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarSupportedContent"
|
||||
aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<svg class="icon icon-Component-71--1">
|
||||
<use xlink:href="#icon-Component-71--1"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="btn p-0 mr-auto"
|
||||
type="button"
|
||||
data-toggle="collapse"
|
||||
data-target="#navbarSupportedContent"
|
||||
aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<svg class="icon icon-Component-71--1">
|
||||
<use xlink:href="#icon-Component-71--1"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<ul class="navbar-nav ml-auto mr-md-5">
|
||||
<!-- <li class="nav-item active">
|
||||
<ul class="navbar-nav ms-auto me-md-5">
|
||||
<!-- <li class="nav-item active">
|
||||
<a class="nav-link" href="#"
|
||||
>پیشخوان <span class="sr-only">(current)</span></a
|
||||
>
|
||||
</li> -->
|
||||
<!-- <li class="nav-item">
|
||||
<!-- <li class="nav-item">
|
||||
<a class="nav-link" href="#">سامانهها</a>
|
||||
</li> -->
|
||||
<li class="nav-item dropdown">
|
||||
<a
|
||||
class="nav-link dropdown-toggle"
|
||||
id="navbarDropdown"
|
||||
role="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{{ $t("Systems") }}
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<!-- <my-system class="list" layout="list"></my-system> -->
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a
|
||||
class="nav-link dropdown-toggle"
|
||||
href="#"
|
||||
id="navbarDropdown"
|
||||
role="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{{ $t("Portal") }}
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<li class="nav-item dropdown">
|
||||
<a
|
||||
class="dropdown-item"
|
||||
href="http://pub.hamfahmi.ir/public"
|
||||
target="_blank"
|
||||
>{{ $t("PersonalFolder") }}</a
|
||||
class="nav-link dropdown-toggle"
|
||||
id="navbarDropdown"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{{ $t("Systems") }}
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<!-- <my-system class="list" layout="list"></my-system> -->
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a
|
||||
class="dropdown-item"
|
||||
href="http://pub.hamfahmi.ir/wiki"
|
||||
target="_blank"
|
||||
>{{ $t("WikiFarhangestan") }}</a
|
||||
class="nav-link dropdown-toggle"
|
||||
href="#"
|
||||
id="navbarDropdown"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<a
|
||||
class="dropdown-item"
|
||||
href="http://pub.hamfahmi.ir:91/"
|
||||
target="_blank"
|
||||
>{{ $t("ResearchPortal") }}</a
|
||||
>
|
||||
<a
|
||||
class="dropdown-item"
|
||||
href="http://pub.hamfahmi.ir:94/"
|
||||
target="_blank"
|
||||
>{{ $t("ResearchSoftware") }}</a
|
||||
>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
{{ $t("Portal") }}
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<a
|
||||
class="dropdown-item"
|
||||
href="http://pub.hamfahmi.ir/public"
|
||||
target="_blank"
|
||||
>{{ $t("PersonalFolder") }}</a
|
||||
>
|
||||
<a
|
||||
class="dropdown-item"
|
||||
href="http://pub.hamfahmi.ir/wiki"
|
||||
target="_blank"
|
||||
>{{ $t("WikiFarhangestan") }}</a
|
||||
>
|
||||
<a
|
||||
class="dropdown-item"
|
||||
href="http://pub.hamfahmi.ir:91/"
|
||||
target="_blank"
|
||||
>{{ $t("ResearchPortal") }}</a
|
||||
>
|
||||
<a
|
||||
class="dropdown-item"
|
||||
href="http://pub.hamfahmi.ir:94/"
|
||||
target="_blank"
|
||||
>{{ $t("ResearchSoftware") }}</a
|
||||
>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav ms-md-3 me-auto">
|
||||
<li class="nav-item">
|
||||
<notification></notification>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<select-language-dropdown
|
||||
toggleClass="dropdown-toggle"
|
||||
></select-language-dropdown>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<user-avatar-dropdown
|
||||
class="position-static"
|
||||
></user-avatar-dropdown>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
</template>
|
||||
<!-- //////////////////// end navbar //////////////////// -->
|
||||
|
||||
<ul class="navbar-nav ml-md-3 mr-auto">
|
||||
<li class="nav-item">
|
||||
<notification></notification>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<select-language-dropdown
|
||||
toggleClass="dropdown-toggle"
|
||||
></select-language-dropdown>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<user-avatar-dropdown
|
||||
class="position-static"
|
||||
></user-avatar-dropdown>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- //////////////////// end navbar //////////////////// -->
|
||||
</header>
|
||||
<!-- <the-sidebar :showUserAvatar="true" :menu="menu"></the-sidebar> -->
|
||||
<the-sidebar
|
||||
:showUserAvatar="true"
|
||||
:menu="$attrs.menu"
|
||||
@statusPag="statusPag"
|
||||
></the-sidebar>
|
||||
|
||||
<main class="main-page__content" :class="{ expanded: !isSidebarCollapsed }">
|
||||
<!-- <div class="pages list-page"> -->
|
||||
<!-- <div class="pages-content align-items-stretch p-0"> -->
|
||||
<!-- <div class="flex-grow-1"> -->
|
||||
<slot></slot>
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
</main>
|
||||
<client-only>
|
||||
<main
|
||||
class="main-page__content"
|
||||
:class="{ expanded: !isSidebarCollapsed }"
|
||||
>
|
||||
<!-- <div class="pages list-page"> -->
|
||||
<!-- <div class="pages-content align-items-stretch p-0"> -->
|
||||
<!-- <div class="flex-grow-1"> -->
|
||||
|
||||
<slot></slot>
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
</main>
|
||||
</client-only>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -169,7 +179,7 @@
|
|||
import { mapState, mapActions } from "pinia";
|
||||
import { useCommonStore } from "~/stores/commonStore";
|
||||
|
||||
import {clearBodyClass} from "@manuals/utilities"
|
||||
import { clearBodyClass } from "@manuals/utilities";
|
||||
export default {
|
||||
mounted() {
|
||||
// this.setBodyClass("default-dashboard");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// middleware/redirect.js
|
||||
export default defineNuxtRouteMiddleware((to, from) => {
|
||||
if (buildName() == "hadith" && to.path == '/') return navigateTo({ name: "hadith" });
|
||||
if (buildName() == "haditha" && to.path == '/') return navigateTo({ name: "haditha" });
|
||||
});
|
||||
|
|
|
@ -33,6 +33,8 @@ export default {
|
|||
]),
|
||||
// callFrom : page | modal
|
||||
async authBase(methodName, callFrom = "page") {
|
||||
const toast = useToast();
|
||||
|
||||
// this.$v.$touch();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
@ -51,16 +53,19 @@ export default {
|
|||
|
||||
this[methodName]()
|
||||
.then((res) => {
|
||||
// mySwalToast({
|
||||
// title: res.message,
|
||||
// icon: "success",
|
||||
// timer: 2000,
|
||||
// });
|
||||
toast.add({
|
||||
title: res.message,
|
||||
icon: "success",
|
||||
timer: 2000,
|
||||
});
|
||||
|
||||
if (callFrom == "modal") {
|
||||
// fired event cached in the Group.vue and ChatList.vue
|
||||
const { $eventBus } = useNuxtApp();
|
||||
$eventBus.emit("authenticated-by-modal", route.query["invite-id"]);
|
||||
$eventBus.emit(
|
||||
"authenticated-by-modal",
|
||||
route.query["invite-id"]
|
||||
);
|
||||
}
|
||||
// if redirected from chat system to relogin.
|
||||
else {
|
||||
|
@ -81,10 +86,12 @@ export default {
|
|||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
mySwalToast({
|
||||
toast.add({
|
||||
title: err.message,
|
||||
icon: "error",
|
||||
timer: 2000,
|
||||
});
|
||||
|
||||
this.resetCaptcha();
|
||||
})
|
||||
.finally(() => {
|
||||
|
|
358
mixins/formBuilderMixin.js
Normal file
|
@ -0,0 +1,358 @@
|
|||
export default {
|
||||
props: ["formElement", "keyValue"],
|
||||
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
controls: [
|
||||
// "play-large", // The large play button in the center
|
||||
//'restart', // Restart playback
|
||||
// "rewind", // Rewind by the seek time (default 10 seconds)
|
||||
"play", // Play/pause playback
|
||||
// "fast-forward", // Fast forward by the seek time (default 10 seconds)
|
||||
"progress", // The progress bar and scrubber for playback and buffering
|
||||
"current-time", // The current time of playback
|
||||
// "duration", // The full duration of the media
|
||||
"mute", // Toggle mute
|
||||
"volume", // Volume control
|
||||
// "captions", // Toggle captions
|
||||
"settings", // Settings menu
|
||||
// "pip", // Picture-in-picture (currently Safari only)
|
||||
// "airplay", // Airplay (currently Safari only)
|
||||
"download", // Show a download button with a link to either the current source or a custom URL you specify in your options
|
||||
// "fullscreen", // Toggle fullscreen
|
||||
],
|
||||
speed: { selected: 1, options: [0.75, 1, 1.5, 2] },
|
||||
},
|
||||
hasError: false,
|
||||
localFormElement: {},
|
||||
textValue: "",
|
||||
emit_disable: false,
|
||||
textValuePrev: "",
|
||||
textDate: [],
|
||||
objectValue: {}, // for select component {text, value}
|
||||
isUpdateitem: false,
|
||||
renderKey:1,
|
||||
};
|
||||
},
|
||||
beforeMount() {
|
||||
this.$root.$on("catch-form-builder-event", this.listenEventBus);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$root.$off("catch-form-builder-event", this.listenEventBus);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// this.textValue = this.value;
|
||||
// this.textItem = this.value
|
||||
|
||||
this.disableEmitTemprory(2000);
|
||||
|
||||
this.localFormElement = this.formElement;
|
||||
this.textValuePrev = this.localFormElement.value;
|
||||
this.initTextValue();
|
||||
this.textValuePrev = this.textValue;
|
||||
// this.date = this.textValue; // for DateCompnent
|
||||
},
|
||||
|
||||
watch: {
|
||||
formElement: {
|
||||
handler(newValue) {
|
||||
this.localFormElement = newValue;
|
||||
},
|
||||
deep: true,
|
||||
nested: true,
|
||||
},
|
||||
|
||||
textValue(newVal) {
|
||||
// console.log(this.localFormElement.key, newVal)
|
||||
if (this.textValuePrev == newVal) {
|
||||
return;
|
||||
}
|
||||
let [emitValue, emitValueObject] = this.parseValueToEmit(newVal)
|
||||
|
||||
// if (!this.emit_disable)
|
||||
// console.log(this.localFormElement.key, newVal, emitValue, this.localFormElement.value)
|
||||
if(this.localFormElement.value != emitValue)
|
||||
this.$emit("take-value", emitValue);
|
||||
|
||||
if (emitValueObject) this.parseAffectedToEventBus(emitValueObject); // for select only
|
||||
else this.parseAffectedToEventBus(emitValue);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
incrementRenderKey(){
|
||||
this.renderKey = this.renderKey +1
|
||||
this.$forceUpdate();
|
||||
},
|
||||
|
||||
parseValueToEmit(newVal){
|
||||
let emitValue = newVal;
|
||||
let emitValueObject = undefined;
|
||||
|
||||
if (this.localFormElement?.type == "date") {
|
||||
// console.info(newVal);
|
||||
emitValue = newVal;
|
||||
try {
|
||||
if (this.localFormElement?.savetype == "timestamp") {
|
||||
let dtStr = newVal;
|
||||
// const dtStr = "2012/02/26";
|
||||
const [y, m, d] = dtStr.split(/-|\//);
|
||||
const date = new Date(y, m - 1, d);
|
||||
// emitValue = date.toISOString();
|
||||
emitValue = date.getTime()();
|
||||
}
|
||||
// if( this.localFormElement?.subtype == 'time' )
|
||||
// return "HH:mm"
|
||||
} catch {
|
||||
emitValue = newVal;
|
||||
}
|
||||
// console.info(emitValue);
|
||||
}
|
||||
// input , textarea if multi items
|
||||
else if (this.localFormElement?.isarray) {
|
||||
let delim = this.localFormElement?.delimiter
|
||||
? this.localFormElement.delimiter
|
||||
: "-";
|
||||
|
||||
emitValue = [];
|
||||
newVal
|
||||
.split(delim)
|
||||
.filter((el) => el.trim())
|
||||
.forEach((el) => {
|
||||
emitValue.push(el.trim());
|
||||
});
|
||||
// console.log(emitValue)
|
||||
} else if (this.localFormElement.type == "select" && this.listOptions) {
|
||||
// if(this.localFormElement.key == 'city'){
|
||||
// }
|
||||
emitValue = newVal;
|
||||
//برای ذدخیره در بک کدام مقدار را بفرستد
|
||||
if (this.localFormElement.value_save) {
|
||||
emitValueObject = this.listOptions.find(
|
||||
(item) => item.value == newVal
|
||||
);
|
||||
|
||||
if (emitValueObject && this.localFormElement.value_save == "title") {
|
||||
emitValue = emitValueObject.title ?? emitValueObject.value;
|
||||
} else if (
|
||||
emitValueObject &&
|
||||
this.localFormElement.value_save == "object"
|
||||
) {
|
||||
emitValue = {
|
||||
id: emitValueObject.value,
|
||||
title: emitValueObject.title,
|
||||
};
|
||||
}
|
||||
}
|
||||
} else if (this.localFormElement?.type == "number"){
|
||||
if(this.localFormElement?.step != 1){
|
||||
emitValue = parseFloat(newVal)
|
||||
}
|
||||
else
|
||||
emitValue = parseInt(newVal)
|
||||
}
|
||||
else emitValue = newVal;
|
||||
|
||||
return [emitValue, emitValueObject]
|
||||
|
||||
},
|
||||
listenEventBus({ value, affectedTo }) {
|
||||
// console.log(affectedTo.key, this.localFormElement.key);
|
||||
if (affectedTo.key === this.localFormElement.key) {
|
||||
try {
|
||||
|
||||
// console.log(this.localFormElement.key, affectedTo, value);
|
||||
// console.log(this[affectedTo.action])
|
||||
this[affectedTo.action](value);
|
||||
|
||||
} catch (err) {}
|
||||
}
|
||||
},
|
||||
parseAffectedToEventBus(newValue) {
|
||||
if (!this.localFormElement["affected-to"]) return;
|
||||
|
||||
// console.log("parseAffectedToEvent", newValue);
|
||||
// console.log(newValue);
|
||||
|
||||
let affectedTo = this.localFormElement["affected-to"];
|
||||
// console.log(affectedTo);
|
||||
|
||||
affectedTo.forEach((item_affectedTo) => {
|
||||
let value = newValue;
|
||||
if (
|
||||
typeof newValue == "object" &&
|
||||
item_affectedTo?.param &&
|
||||
newValue[item_affectedTo?.param]
|
||||
)
|
||||
value = newValue[item_affectedTo?.param];
|
||||
|
||||
if (item_affectedTo?.emit) {
|
||||
this.$emit( "action-affected-item", { action:item_affectedTo.emit, key: item_affectedTo.key, value});
|
||||
// console.log("action-affected-item", { action:item_affectedTo.emit, key: item_affectedTo.key, value})
|
||||
} else if (item_affectedTo?.action) {
|
||||
this.$root.$emit("catch-form-builder-event", {
|
||||
value: value,
|
||||
affectedTo: item_affectedTo,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
disableEmitTemprory(timeout = 1000) {
|
||||
this.emit_disable = true;
|
||||
setTimeout(() => {
|
||||
this.emit_disable = false;
|
||||
}, timeout);
|
||||
},
|
||||
|
||||
clearErrors() {
|
||||
return true;
|
||||
},
|
||||
getLabel() {
|
||||
let label = this.localFormElement.label;
|
||||
if (this.localFormElement?.required == "1") label = "*" + label;
|
||||
return label;
|
||||
},
|
||||
validate(ev) {
|
||||
const value = ev.target.value;
|
||||
if (this.localFormElement.validate) {
|
||||
// چک کردن برای وجود الگو
|
||||
if (value) {
|
||||
let pattern = this.localFormElement.validate;
|
||||
// اگر الگوی ورودی معتبر باشد، تنظیم میکنیم که مقدار مطابقت دارد یا خیر
|
||||
this.hasError = new RegExp(pattern).test(value);
|
||||
} else {
|
||||
// اگر مقدار ورودی خالی باشد، خطا بر اساس الزامی بودن فیلد تعیین میشود
|
||||
this.hasError = this.localFormElement?.required ? true : false;
|
||||
}
|
||||
} else {
|
||||
// اگر الگوی validate وجود نداشته باشد، کاری انجام نمیدهیم
|
||||
this.hasError = false;
|
||||
}
|
||||
// اعلان خطا به والد (component اصلی)
|
||||
this.$emit("take-value-validate", this.hasError);
|
||||
},
|
||||
|
||||
initTextValue(newValue=undefined) {
|
||||
// console.log('initTextValue', this.localFormElement.key, newValue)
|
||||
|
||||
let value = "";
|
||||
if(newValue)
|
||||
value = newValue
|
||||
else if(this.localFormElement.value)
|
||||
value = this.localFormElement.value;
|
||||
else if(this.localFormElement.value_defualt)
|
||||
value = this.localFormElement.value_defualt
|
||||
|
||||
|
||||
|
||||
// در همه حالت نباید این باشد اگر لازم شد باید پیش فرض تنظیم شود
|
||||
// ذخیره هم نمیشود ...!!!
|
||||
// if (!value && this.localFormElement.type == "select") {
|
||||
// value = this.listOptions.length > 0 ? this.listOptions[0].value : "";
|
||||
// }
|
||||
// console.log(this.localFormElement.key, value)
|
||||
|
||||
var mValue = value ?? "";
|
||||
|
||||
if (this.localFormElement?.type == "date") {
|
||||
// console.info("setTextValue", mValue);
|
||||
try {
|
||||
var date = "";
|
||||
if (mValue != "") {
|
||||
if (this.localFormElement?.savetype == "timestamp") {
|
||||
let timeWithMiliSeconds = mValue;
|
||||
|
||||
if ( this.isUnixTimestamp(mValue) && mValue.toString().length <= 11) {
|
||||
timeWithMiliSeconds = mValue * 1000;
|
||||
}
|
||||
date = this.$moment(new Date(timeWithMiliSeconds)).format(
|
||||
"YYYY-MM-DD HH:mm"
|
||||
);
|
||||
} else if (
|
||||
this.localFormElement?.savetype == "datetime" ||
|
||||
this.localFormElement?.savetype == "date"
|
||||
) {
|
||||
date = this.$moment(new Date(mValue)).format("YYYY-MM-DD HH:mm");
|
||||
} else date = mValue;
|
||||
}
|
||||
this.textDate = date;
|
||||
mValue = date
|
||||
} catch {
|
||||
this.textDate = mValue;
|
||||
}
|
||||
} else if (this.localFormElement?.isarray) {
|
||||
if (value && Array.isArray(value)) {
|
||||
let delim = this.localFormElement?.delimiter
|
||||
? this.localFormElement.delimiter
|
||||
: "-";
|
||||
mValue = value.join(delim);
|
||||
} else mValue = "";
|
||||
} else if (this.localFormElement.type == "select") {
|
||||
if (this.localFormElement?.value_save == "title" && this.listOptions) {
|
||||
// console.log('value_defualt', this.localFormElement.value_defualt)
|
||||
let finded = this.listOptions.find((item) => {
|
||||
if (item.title == value) {
|
||||
return item;
|
||||
}
|
||||
});
|
||||
|
||||
if (finded) {
|
||||
mValue = finded.value;
|
||||
// console.log('finded', finded)
|
||||
} else {
|
||||
mValue =
|
||||
this.listOptions.length > 0 ? this.listOptions[0].value : "";
|
||||
}
|
||||
} else if (this.localFormElement?.value_save == "object") {
|
||||
mValue = value.value;
|
||||
} else mValue = value ?? "";
|
||||
} else {
|
||||
mValue = value ?? "";
|
||||
}
|
||||
|
||||
//نیازی به ارسال تغییر در واچ نیست
|
||||
if(this.localFormElement.value == value )
|
||||
this.textValuePrev == value
|
||||
|
||||
this.textValue = mValue
|
||||
|
||||
// console.log(' this.textValue', this.localFormElement.key, this.textValue)
|
||||
},
|
||||
isUnixTimestamp(value) {
|
||||
// Check if the value is a number
|
||||
if (typeof value !== "number" && !/^\d+$/.test(value)) {
|
||||
return false;
|
||||
}
|
||||
// Convert to number if it's a string
|
||||
value = parseInt(value);
|
||||
// Unix timestamps are non-negative integers
|
||||
return !isNaN(value) && value >= 0 && value % 1 === 0;
|
||||
},
|
||||
|
||||
sendTextValue() {
|
||||
this.$emit("keydown", {
|
||||
text: this.textValue,
|
||||
key: this.keyValue,
|
||||
isUpdate: this.isUpdateitem,
|
||||
});
|
||||
},
|
||||
|
||||
////ااز هیچا فراخوانی نمیشه لذا کامنت کردم
|
||||
//فقط برای select
|
||||
// takeSelectValue($event, type) {
|
||||
|
||||
// this.objectValue = {
|
||||
// value: $event.target.value,
|
||||
// text: $event.target.selectedOptions[0].text,
|
||||
// };
|
||||
|
||||
// console.log('takeSelectValue',this.localFormElement.key , objectValue)
|
||||
|
||||
// this.$emit("take-select-object", {
|
||||
// type: type,
|
||||
// objectValue: this.objectValue,
|
||||
// });
|
||||
// },
|
||||
},
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
import { mapState, mapActions } from "pinia";
|
||||
import { useCommonStore } from "@stores/commonStore";
|
||||
import { useCommonStore } from "~/stores/commonStore";
|
||||
|
||||
export default {
|
||||
created() {
|
||||
|
|
164
nuxt.config.ts
|
@ -2,6 +2,11 @@
|
|||
import fs from "fs-extra";
|
||||
import path from "path";
|
||||
|
||||
import chat from "./routes/chat";
|
||||
import haditha from "./routes/haditha";
|
||||
import search from "./routes/search";
|
||||
import research from "./routes/research";
|
||||
|
||||
const envs = import.meta.env;
|
||||
let sassEnvVariables = "";
|
||||
|
||||
|
@ -13,20 +18,19 @@ for (let e in envs) {
|
|||
|
||||
// dynamically importing styles.
|
||||
const buildName = import.meta.env.VITE_BUILD_NAME;
|
||||
let mainStyle = `~/assets/common/scss/${buildName}-styles.scss`;
|
||||
|
||||
if (buildName == "hadith")
|
||||
mainStyle = `~/systems/${buildName}_ui/assets/${buildName}/scss/${buildName}.css`;
|
||||
|
||||
export default defineNuxtConfig({
|
||||
hooks: {
|
||||
"build:before": () => {
|
||||
if (buildName == "hadith") {
|
||||
if (buildName == "haditha") {
|
||||
const sourceDir = path.resolve(
|
||||
__dirname,
|
||||
`systems/${buildName}_ui/assets/${buildName}/images`
|
||||
`systems/${buildName.substring(
|
||||
0,
|
||||
buildName.length - 1
|
||||
)}_ui/assets/${buildName}/images`
|
||||
); // Source folder (e.g., assets/images)
|
||||
const targetDir = path.resolve(__dirname, "public/img"); // Target folder (e.g., public/images)
|
||||
const targetDir = path.resolve(__dirname, `public/img/${buildName}`); // Target folder (e.g., public/images)
|
||||
|
||||
// Ensure the target directory exists
|
||||
fs.ensureDirSync(targetDir);
|
||||
|
@ -40,96 +44,15 @@ export default defineNuxtConfig({
|
|||
|
||||
"pages:extend"(pages) {
|
||||
// Add custom routes
|
||||
pages.push(
|
||||
{
|
||||
name: "search",
|
||||
path: "/search",
|
||||
file: "~/systems/search_ui/pages/search/index.vue",
|
||||
},
|
||||
{
|
||||
name: "searchNavigation",
|
||||
path: "/search/lists",
|
||||
file: "~/systems/search_ui/pages/search/lists.vue",
|
||||
},
|
||||
{
|
||||
name: "searchChart",
|
||||
path: "/search/charts",
|
||||
file: "~/systems/search_ui/pages/search/charts.vue",
|
||||
},
|
||||
{
|
||||
name: "showEntity",
|
||||
path: "/search/:key/:id/show",
|
||||
file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue",
|
||||
},
|
||||
{
|
||||
name: "navigationView",
|
||||
path: "/search/:key/:id/list",
|
||||
file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue",
|
||||
},
|
||||
{
|
||||
name: "entityResearch",
|
||||
path: "/search/:key/:id/research",
|
||||
file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue",
|
||||
},
|
||||
{
|
||||
name: "entityResearch",
|
||||
path: "/search/:key/:id/detail",
|
||||
file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue",
|
||||
},
|
||||
// --------------------- start: hadith routes ---------------------
|
||||
{
|
||||
name: "hadith",
|
||||
path: "/hadith",
|
||||
file: "~/systems/hadith_ui/pages/hadith/index.vue",
|
||||
},
|
||||
{
|
||||
name: "hadithSearch",
|
||||
path: "/hadith/search",
|
||||
file: "~/systems/hadith_ui/pages/hadith/search/index.vue",
|
||||
},
|
||||
{
|
||||
name: "hadithChatBot",
|
||||
path: "/hadith/chat-bot",
|
||||
file: "~/systems/hadith_ui/pages/hadith/chat-bot.vue",
|
||||
},
|
||||
{
|
||||
name: "hadithFavorites",
|
||||
path: "/hadith/favorites",
|
||||
file: "~/systems/hadith_ui/pages/hadith/favorites/index.vue",
|
||||
},
|
||||
{
|
||||
name: "hadithLibrary",
|
||||
path: "/hadith/library",
|
||||
file: "~/systems/hadith_ui/pages/hadith/library/index.vue",
|
||||
},
|
||||
{
|
||||
name: "hadithLibraryShow",
|
||||
path: "/hadith/library/:id/:slug?",
|
||||
file: "~/systems/hadith_ui/pages/hadith/library/[id]/[slug]/index.vue",
|
||||
},
|
||||
{
|
||||
name: "hadithAbout",
|
||||
path: "/hadith/about-us",
|
||||
file: "~/systems/hadith_ui/pages/hadith/public-pages/about-us.vue",
|
||||
},
|
||||
{
|
||||
name: "hadithContact",
|
||||
path: "/hadith/contact-us",
|
||||
file: "~/systems/hadith_ui/pages/hadith/public-pages/ContactUs.vue",
|
||||
},
|
||||
{
|
||||
name: "hadithRules",
|
||||
path: "/hadith/rules",
|
||||
file: "~/systems/hadith_ui/pages/hadith/public-pages/rules.vue",
|
||||
}
|
||||
|
||||
// --------------------- end: hadith routes ---------------------
|
||||
);
|
||||
pages.push(...search, ...research, ...haditha, ...chat);
|
||||
},
|
||||
},
|
||||
|
||||
nitro: {
|
||||
compressPublicAssets: true,
|
||||
prerender: {
|
||||
routes: ["/haditha/about-us", "/haditha/contact"], // Pre-render these routes
|
||||
},
|
||||
},
|
||||
|
||||
colorMode: {
|
||||
|
@ -172,6 +95,17 @@ export default defineNuxtConfig({
|
|||
"@nuxt/image",
|
||||
// "@nuxtjs/supabase",
|
||||
],
|
||||
icon: {
|
||||
customCollections: [
|
||||
{
|
||||
prefix: "haditha",
|
||||
dir: `./systems/${buildName.substring(
|
||||
0,
|
||||
buildName.length - 1
|
||||
)}_ui/assets/${buildName}/font-icons`,
|
||||
},
|
||||
],
|
||||
},
|
||||
// ui: {
|
||||
// prefix: 'Nuxt', //Use the prefix option to change the prefix of the components. Default: U
|
||||
// fonts: false, // Use the fonts option to enable or disable the @nuxt/fonts module. Default: true
|
||||
|
@ -185,29 +119,10 @@ export default defineNuxtConfig({
|
|||
// debug: process.env.NODE_ENV === 'development',
|
||||
// mode: 'init'
|
||||
// },
|
||||
image: {
|
||||
inject: true,
|
||||
quality: 80,
|
||||
format: ["webp", "jpeg", "jpg", "png", "gif", "avif"],
|
||||
screens: {
|
||||
xs: 320,
|
||||
sm: 576,
|
||||
md: 768,
|
||||
lg: 1199,
|
||||
xl: 1400,
|
||||
xxl: 1600,
|
||||
"2xl": 1920,
|
||||
},
|
||||
presets: {
|
||||
avatar: {
|
||||
modifiers: {
|
||||
format: "jpg",
|
||||
width: 25,
|
||||
height: 24,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// image: {
|
||||
// provider: "ipx",
|
||||
// quality: 100,
|
||||
// },
|
||||
i18n: {
|
||||
vueI18n: "./i18n.config.ts", // if you are using custom path, default
|
||||
},
|
||||
|
@ -233,7 +148,7 @@ export default defineNuxtConfig({
|
|||
},
|
||||
},
|
||||
css: [
|
||||
mainStyle,
|
||||
customStyleLoader(),
|
||||
// "vue3-persian-datetime-picker/src/picker/assets/scss/style.scss",
|
||||
],
|
||||
alias: {
|
||||
|
@ -253,7 +168,8 @@ export default defineNuxtConfig({
|
|||
"@pages": "~/pages",
|
||||
"@search": "~/systems/search_ui",
|
||||
"@research": "~/systems/research_ui",
|
||||
"@hadith": "~/systems/hadith_ui",
|
||||
"@haditha": "~/systems/hadith_ui",
|
||||
"@chat": "~/systems/chat_ui",
|
||||
},
|
||||
vite: {
|
||||
resolve: {},
|
||||
|
@ -275,6 +191,10 @@ export default defineNuxtConfig({
|
|||
},
|
||||
},
|
||||
},
|
||||
build: {
|
||||
analyze: true,
|
||||
// transpile: ["echarts", "resize-detector", "echarts-wordcloud"],
|
||||
},
|
||||
// postcss: {
|
||||
// plugins: {
|
||||
// tailwindcss: {},
|
||||
|
@ -419,3 +339,13 @@ export default defineNuxtConfig({
|
|||
// console.log(runtimeConfig.public.apiBase)
|
||||
|
||||
// Resolve ~, ~~, @ and @@ aliases located within layers with respect to their layer source and root directories.
|
||||
function customStyleLoader() {
|
||||
let mainStyle = `~/assets/common/scss/${buildName}-styles.scss`;
|
||||
if (buildName == "haditha")
|
||||
mainStyle = `~/systems/${buildName.substring(
|
||||
0,
|
||||
buildName.length - 1
|
||||
)}_ui/assets/${buildName}/scss/${buildName}.css`;
|
||||
|
||||
return mainStyle;
|
||||
}
|
||||
|
|
207
package-lock.json
generated
|
@ -17,6 +17,8 @@
|
|||
"@vueup/vue-quill": "^1.2.0",
|
||||
"axios": "^1.7.7",
|
||||
"bootstrap": "^5.3.3",
|
||||
"codemirror": "^6.0.1",
|
||||
"cropperjs": "^2.0.0",
|
||||
"docx": "^9.1.1",
|
||||
"echarts": "^5.5.1",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
|
@ -29,6 +31,8 @@
|
|||
"i18next-vue": "^5.0.0",
|
||||
"jalali-moment": "^3.3.11",
|
||||
"jquery": "^3.7.1",
|
||||
"lucide": "^0.477.0",
|
||||
"lucide-vue-next": "^0.477.0",
|
||||
"mammoth": "^1.8.0",
|
||||
"mitt": "^3.0.1",
|
||||
"npm": "^11.1.0",
|
||||
|
@ -42,6 +46,7 @@
|
|||
"vue-draggable-next": "^2.2.1",
|
||||
"vue-echarts": "^7.0.3",
|
||||
"vue-i18n": "^10.0.1",
|
||||
"vue-image-upload-resize": "^2.3.0",
|
||||
"vue-jalali-moment": "^1.0.0",
|
||||
"vue-jstree": "^2.1.6",
|
||||
"vue-multiselect": "^3.0.0",
|
||||
|
@ -53,9 +58,12 @@
|
|||
"vue3-persian-datetime-picker": "^1.2.2",
|
||||
"vue3-tree-vue": "^2.0.11",
|
||||
"vuejs-paginate": "^2.1.0",
|
||||
"vuejs-paginate-next": "^1.0.2"
|
||||
"vuejs-paginate-next": "^1.0.2",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/lucide": "^1.2.28",
|
||||
"@iconify-json/vscode-icons": "^1.2.16",
|
||||
"@nuxt/test-utils": "^3.14.4",
|
||||
"@nuxtjs/i18n": "^9.0.0-rc.2",
|
||||
"@types/bootstrap": "^5.2.10",
|
||||
|
@ -667,7 +675,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.3.tgz",
|
||||
"integrity": "sha512-1dNIOmiM0z4BIBwxmxEfA1yoxh1MF/6KPBbh20a5vphGV0ictKlgQsbJs6D6SkR6iJpGbpwRsa6PFMNlg9T9pQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
|
@ -712,7 +719,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.3.tgz",
|
||||
"integrity": "sha512-GSGfKxCo867P7EX1k2LoCrjuQFeqVgPGRRsSl4J4c0KMkD+k1y6WYvTQkzv0iZ8JhLJDujEvlnMchv4CZQLh3Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.35.0",
|
||||
|
@ -724,7 +730,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz",
|
||||
"integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
|
@ -748,6 +753,126 @@
|
|||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element/-/element-2.0.0.tgz",
|
||||
"integrity": "sha512-lsthn0nQq73GExUE7Mg/ss6Q3RXADGDv055hxoLFwvl/wGHgy6ZkYlfLZ/VmgBHC6jDK5IgPBFnqrPqlXWSGBA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-canvas": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-canvas/-/element-canvas-2.0.0.tgz",
|
||||
"integrity": "sha512-GPtGJgSm92crJhhhwUsaMw3rz2KfJWWSz7kRAlufFEV/EHTP5+6r6/Z1BCGRna830i+Avqbm435XLOtA7PVJwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-crosshair": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-crosshair/-/element-crosshair-2.0.0.tgz",
|
||||
"integrity": "sha512-KfPfyrdeFvUC31Ws7ATtcalWWSaMtrC6bMoCipZhqbUOE7wZoL4ecDSL6BUOZxPa74awZUqfzirCDjHvheBfyw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-grid": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-grid/-/element-grid-2.0.0.tgz",
|
||||
"integrity": "sha512-i78SQ0IJTLFveKX6P7svkfMYVdgHrQ8ZmmEw8keFy9n1ZVbK+SK0UHK5FNMRNI/gtVhKJOGEnK/zeyjUdj4Iyw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-handle": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-handle/-/element-handle-2.0.0.tgz",
|
||||
"integrity": "sha512-ZJvW+0MkK9E8xYymGdoruaQn2kwjSHFpNSWinjyq6csuVQiCPxlX5ovAEDldmZ9MWePPtWEi3vLKQOo2Yb0T8g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-image": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-image/-/element-image-2.0.0.tgz",
|
||||
"integrity": "sha512-9BxiTS/aHRmrjopaFQb9mQQXmx4ruhYHGkDZMVz24AXpMFjUY6OpqrWse/WjzD9tfhMFvEdu17b3VAekcAgpeg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-selection": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-selection/-/element-selection-2.0.0.tgz",
|
||||
"integrity": "sha512-ensNnbIfJsJ8bhbJTH/RXtk2URFvTOO4TvfRk461n2FPEC588D7rwBmUJxQg74IiTi4y1JbCI+6j+4LyzYBLCQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/element-image": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-shade": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-shade/-/element-shade-2.0.0.tgz",
|
||||
"integrity": "sha512-jv/2bbNZnhU4W+T4G0c8ADocLIZvQFTXgCf2RFDNhI5UVxurzWBnDdb8Mx8LnVplnkTqO+xUmHZYve0CwgWo+Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/element-selection": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-viewer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-viewer/-/element-viewer-2.0.0.tgz",
|
||||
"integrity": "sha512-zY+3VRN5TvpM8twlphYtXw0tzJL2VgzeK7ufhL1BixVqOdRxwP13TprYIhqwGt9EW/SyJZUiaIu396T89kRX8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/element-image": "^2.0.0",
|
||||
"@cropper/element-selection": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/elements": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/elements/-/elements-2.0.0.tgz",
|
||||
"integrity": "sha512-PQkPo1nUjxLFUQuHYu+6atfHxpX9B41Xribao6wpvmvmNIFML6LQdNqqWYb6LyM7ujsu71CZdBiMT5oetjJVoQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/element-crosshair": "^2.0.0",
|
||||
"@cropper/element-grid": "^2.0.0",
|
||||
"@cropper/element-handle": "^2.0.0",
|
||||
"@cropper/element-image": "^2.0.0",
|
||||
"@cropper/element-selection": "^2.0.0",
|
||||
"@cropper/element-shade": "^2.0.0",
|
||||
"@cropper/element-viewer": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/utils/-/utils-2.0.0.tgz",
|
||||
"integrity": "sha512-cprLYr+7kK3faGgoOsTW9gIn5sefDr2KwOmgyjzIXk+8PLpW8FgFKEg5FoWfRD5zMAmkCBuX6rGKDK3VdUEGrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
|
||||
|
@ -1463,6 +1588,26 @@
|
|||
"url": "https://github.com/sponsors/nzakas"
|
||||
}
|
||||
},
|
||||
"node_modules/@iconify-json/lucide": {
|
||||
"version": "1.2.28",
|
||||
"resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.28.tgz",
|
||||
"integrity": "sha512-SPeAoh1YKhALpNSto/FBspf3GZ0eAr3ka/OI7cJJ5HljLzycIITv0s4Rd2+sRVzFtD1I991mJJmYohQeOSZ+Og==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@iconify/types": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@iconify-json/vscode-icons": {
|
||||
"version": "1.2.16",
|
||||
"resolved": "https://registry.npmjs.org/@iconify-json/vscode-icons/-/vscode-icons-1.2.16.tgz",
|
||||
"integrity": "sha512-hstc2yVq2UJ6v6FrgjftzXRvphGZBsKxvSeXoFLP1Hgx89TPZKrGE5SV6vqsoeIlLYaQ7OZbXmAoVGroTfGmVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@iconify/types": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@iconify/collections": {
|
||||
"version": "1.0.516",
|
||||
"resolved": "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.516.tgz",
|
||||
|
@ -6302,6 +6447,12 @@
|
|||
"integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/blueimp-canvas-to-blob": {
|
||||
"version": "3.29.0",
|
||||
"resolved": "https://registry.npmjs.org/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz",
|
||||
"integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
|
@ -6845,7 +6996,6 @@
|
|||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
|
||||
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/commands": "^6.0.0",
|
||||
|
@ -7112,8 +7262,7 @@
|
|||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/croner": {
|
||||
"version": "9.0.0",
|
||||
|
@ -7133,6 +7282,16 @@
|
|||
"cronstrue": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/cropperjs": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-2.0.0.tgz",
|
||||
"integrity": "sha512-TO2j0Qre01kPHbow4FuTrbdEB4jTmGRySxW49jyEIqlJZuEBfrvCTT0vC3eRB2WBXudDfKi1Onako6DKWKxeAQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cropper/elements": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-fetch": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz",
|
||||
|
@ -10934,6 +11093,21 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lucide": {
|
||||
"version": "0.477.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide/-/lucide-0.477.0.tgz",
|
||||
"integrity": "sha512-lEgt1ni9sKohbLsYWSnM3mKVRkvUrJ3Ijj01RAdM5F0iyvxkCcy3gPrb1G2ux6zE4y20ptcitfMa0OOFXI57gw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/lucide-vue-next": {
|
||||
"version": "0.477.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.477.0.tgz",
|
||||
"integrity": "sha512-C7azIKO7aJKf5MD7OIzV7NRDtnjXH3KSXfyJgGqRIMemuMzW/9esuMxDXIXDhBZcJgRtXMUN0FcJwOJZQ8SywA==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"vue": ">=3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-regexp": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/magic-regexp/-/magic-regexp-0.8.0.tgz",
|
||||
|
@ -20410,6 +20584,16 @@
|
|||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-image-upload-resize": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-image-upload-resize/-/vue-image-upload-resize-2.3.0.tgz",
|
||||
"integrity": "sha512-ElzyAVCluiDt8xSZkSK9FbuLY5mr23JlO4cHyyRo86RfEGLWtvXrTq7vYOgDstT8rNBmnTgNCkPKc0rpmyl1yA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"blueimp-canvas-to-blob": "^3.14.0",
|
||||
"vue": "^2.5.17"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-jalali-moment": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-jalali-moment/-/vue-jalali-moment-1.0.0.tgz",
|
||||
|
@ -21013,6 +21197,15 @@
|
|||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.24.2",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz",
|
||||
"integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
},
|
||||
"node_modules/zrender": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.6.0.tgz",
|
||||
|
|
14
package.json
|
@ -11,8 +11,8 @@
|
|||
"postinstall": "nuxt prepare",
|
||||
"dev-tavasi": "env-cmd -f .env.tavasi nuxt dev --host --inspect",
|
||||
"dev-monir": "env-cmd -f .env.monir nuxt dev --host --inspect",
|
||||
"dev-hadith": "env-cmd -f .env.hadith nuxt dev --host --inspect",
|
||||
"build-hadith": "env-cmd -f .env.hadith nuxt build"
|
||||
"dev-haditha": "env-cmd -f .env.haditha nuxt dev --host --inspect",
|
||||
"build-haditha": "env-cmd -f .env.haditha nuxt build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/image": "^1.8.1",
|
||||
|
@ -25,6 +25,8 @@
|
|||
"@vueup/vue-quill": "^1.2.0",
|
||||
"axios": "^1.7.7",
|
||||
"bootstrap": "^5.3.3",
|
||||
"codemirror": "^6.0.1",
|
||||
"cropperjs": "^2.0.0",
|
||||
"docx": "^9.1.1",
|
||||
"echarts": "^5.5.1",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
|
@ -37,6 +39,8 @@
|
|||
"i18next-vue": "^5.0.0",
|
||||
"jalali-moment": "^3.3.11",
|
||||
"jquery": "^3.7.1",
|
||||
"lucide": "^0.477.0",
|
||||
"lucide-vue-next": "^0.477.0",
|
||||
"mammoth": "^1.8.0",
|
||||
"mitt": "^3.0.1",
|
||||
"npm": "^11.1.0",
|
||||
|
@ -50,6 +54,7 @@
|
|||
"vue-draggable-next": "^2.2.1",
|
||||
"vue-echarts": "^7.0.3",
|
||||
"vue-i18n": "^10.0.1",
|
||||
"vue-image-upload-resize": "^2.3.0",
|
||||
"vue-jalali-moment": "^1.0.0",
|
||||
"vue-jstree": "^2.1.6",
|
||||
"vue-multiselect": "^3.0.0",
|
||||
|
@ -61,9 +66,12 @@
|
|||
"vue3-persian-datetime-picker": "^1.2.2",
|
||||
"vue3-tree-vue": "^2.0.11",
|
||||
"vuejs-paginate": "^2.1.0",
|
||||
"vuejs-paginate-next": "^1.0.2"
|
||||
"vuejs-paginate-next": "^1.0.2",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/lucide": "^1.2.28",
|
||||
"@iconify-json/vscode-icons": "^1.2.16",
|
||||
"@nuxt/test-utils": "^3.14.4",
|
||||
"@nuxtjs/i18n": "^9.0.0-rc.2",
|
||||
"@types/bootstrap": "^5.2.10",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<!-- majles dashbaord -->
|
||||
<search-section v-if="buildName() == 'majles'"></search-section>
|
||||
<!-- monir dashboard -->
|
||||
<default-dashboard></default-dashboard>
|
||||
<default-dashboard v-else></default-dashboard>
|
||||
<!-- </ClientOnly> -->
|
||||
</NuxtLayout>
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||
onRequest({ request, options, error }) {
|
||||
options.baseURL =
|
||||
import.meta.env.VITE_BASE_URL +
|
||||
import.meta.env.VITE_API_NAME +
|
||||
import.meta.env.NUXT_PUBLIC_API_NAME+
|
||||
options.baseURL;
|
||||
|
||||
if (token) {
|
||||
|
|
|
@ -3,12 +3,13 @@ import { useStorage } from "@vueuse/core";
|
|||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
let token = useStorage("id_token", "GuestAccess").value;
|
||||
const config = useRuntimeConfig();
|
||||
|
||||
const api = $fetch.create({
|
||||
onRequest({ request, options, error }) {
|
||||
options.baseURL =
|
||||
import.meta.env.VITE_BASE_URL +
|
||||
import.meta.env.VITE_API_NAME +
|
||||
config.public.NUXT_PUBLIC_BASE_URL +
|
||||
config.public.NUXT_PUBLIC_API_NAME +
|
||||
options.baseURL;
|
||||
|
||||
if (token) {
|
||||
|
@ -40,13 +41,14 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||
getRequest: (url, options = {}) => api(url, { method: "GET", ...options }),
|
||||
postRequest: (url, body, options = {}) =>
|
||||
api(url, { method: "POST", body, ...options }),
|
||||
deleteRequest: (url, options = {}) => api(url, { method: "DELETE", ...options }),
|
||||
deleteRequest: (url, options = {}) =>
|
||||
api(url, { method: "DELETE", ...options }),
|
||||
};
|
||||
|
||||
// Expose to useNuxtApp().$api and useNuxtApp().$http
|
||||
return {
|
||||
provide: {
|
||||
http
|
||||
http,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
@ -4,23 +4,28 @@
|
|||
// createApp.use(Vuelidate);
|
||||
|
||||
import { useVuelidate } from '@vuelidate/core'
|
||||
import { required, minLength } from '@vuelidate/validators'
|
||||
// import { required, minLength } from '@vuelidate/validators'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
nuxtApp.vueApp.use(() => {
|
||||
// // Example of global setup, but typically you'd handle this in the component
|
||||
// const state = reactive({
|
||||
// firstName: ''
|
||||
// })
|
||||
// const rules = {
|
||||
// firstName: {
|
||||
// required,
|
||||
// minLength: minLength(2)
|
||||
// }
|
||||
// }
|
||||
// const v$ = useVuelidate(rules, state)
|
||||
// return v$;
|
||||
// // Return the v$ instance or any other necessary setup
|
||||
})
|
||||
// export default defineNuxtPlugin((nuxtApp) => {
|
||||
// nuxtApp.vueApp.use((useVuelidate) => {
|
||||
// // // Example of global setup, but typically you'd handle this in the component
|
||||
// // const state = reactive({
|
||||
// // firstName: ''
|
||||
// // })
|
||||
// // const rules = {
|
||||
// // firstName: {
|
||||
// // required,
|
||||
// // minLength: minLength(2)
|
||||
// // }
|
||||
// // }
|
||||
// // const v$ = useVuelidate(rules, state)
|
||||
// // return v$;
|
||||
// // // Return the v$ instance or any other necessary setup
|
||||
// })
|
||||
// })
|
||||
|
||||
|
||||
|
||||
export default defineNuxtPlugin(nuxtApp => {
|
||||
nuxtApp.provide('vuelidate', useVuelidate)
|
||||
})
|
||||
|
||||
|
|
Before Width: | Height: | Size: 490 KiB After Width: | Height: | Size: 490 KiB |
Before Width: | Height: | Size: 783 KiB After Width: | Height: | Size: 783 KiB |
Before Width: | Height: | Size: 263 KiB After Width: | Height: | Size: 263 KiB |
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 203 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 198 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 550 B After Width: | Height: | Size: 550 B |
BIN
public/img/haditha/fav-icons/android-icon-144x144.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/img/haditha/fav-icons/android-icon-192x192.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
public/img/haditha/fav-icons/android-icon-36x36.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
public/img/haditha/fav-icons/android-icon-48x48.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
public/img/haditha/fav-icons/android-icon-72x72.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
public/img/haditha/fav-icons/android-icon-96x96.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-114x114.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-120x120.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-144x144.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-152x152.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-180x180.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-57x57.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-60x60.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-72x72.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-76x76.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
public/img/haditha/fav-icons/apple-icon-precomposed.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
public/img/haditha/fav-icons/apple-icon.png
Normal file
After Width: | Height: | Size: 20 KiB |
2
public/img/haditha/fav-icons/browserconfig.xml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
|
BIN
public/img/haditha/fav-icons/favicon-16x16.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
public/img/haditha/fav-icons/favicon-32x32.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
public/img/haditha/fav-icons/favicon-96x96.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
public/img/haditha/fav-icons/favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
41
public/img/haditha/fav-icons/manifest.json
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "App",
|
||||
"icons": [
|
||||
{
|
||||
"src": "\/android-icon-36x36.png",
|
||||
"sizes": "36x36",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image\/png",
|
||||
"density": "4.0"
|
||||
}
|
||||
]
|
||||
}
|
BIN
public/img/haditha/fav-icons/ms-icon-144x144.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/img/haditha/fav-icons/ms-icon-150x150.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/img/haditha/fav-icons/ms-icon-310x310.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
public/img/haditha/fav-icons/ms-icon-70x70.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 269 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 304 KiB After Width: | Height: | Size: 304 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
9
public/img/haditha/robot-indicator.svg
Normal file
|
@ -0,0 +1,9 @@
|
|||
<svg width="16" height="27" viewBox="0 0 16 27" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.79031 13.8107C5.19508 12.8313 7.08122 10.8959 8 8.47239C8.91878 10.8959 10.8049 12.8313 13.2097 13.8107L13.5599 13.9533C10.9698 14.8404 8.92567 16.8559 8 19.427C7.07433 16.8559 5.03017 14.8404 2.44014 13.9533L2.79031 13.8107Z" stroke="url(#paint0_linear_67_6564)" stroke-linejoin="round"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_67_6564" x1="15.0921" y1="7" x2="0.0931545" y2="7.27651" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#D284FF"/>
|
||||
<stop offset="1" stop-color="#4D00FF"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 630 B |
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 174 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
public/img/haditha/section-four_card-five.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
public/img/haditha/section-four_card-four.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
public/img/haditha/section-four_card-one.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
public/img/haditha/section-four_card-three.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
public/img/haditha/section-four_card-two.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
public/img/haditha/section-three-bgi.png
Normal file
After Width: | Height: | Size: 1.1 MiB |