| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- # обязательно подключение глобальных массивов
- globalThis.renderFns = require 'pug.json'
- globalThis.stylFns = require 'styl.json'
- # подключение мета информации (строго в данном фиде)
- document.head.insertAdjacentHTML 'beforeend','<meta charset="UTF-8">'
- document.head.insertAdjacentHTML 'beforeend','<meta name="viewport" content="width=device-width, initial-scale=1.0">'
- document.head.insertAdjacentHTML('beforeend','<title> Кохи Борбад - Концертный зал Душанбе</title>')
- # Настройка tailwind
- tailwind.config = require 'tailwind.config.js'
- # подключение основных стилей
- ## tailwind
- document.head.insertAdjacentHTML('beforeend','<style type="text/tailwindcss" page="main">'+stylFns['main.css']+'</style>')
- ## базовой стиль приложения
- document.head.insertAdjacentHTML('beforeend','<style type="text/tailwindcss" page="root">'+stylFns['app/temp.styl']+'</style>')
- # Создаем глобальную шину событий
- class AppEventBus
- constructor: ->
- @events = {}
-
- on: (event, callback) ->
- if !@events[event]
- @events[event] = []
- @events[event].push(callback)
-
- emit: (event, data) ->
- if @events[event]
- for callback in @events[event]
- try
- callback(data)
- catch error
- debug.log "Event bus error: " + error
-
- off: (event, callback) ->
- if @events[event]
- @events[event] = @events[event].filter (cb) -> cb != callback
- # Создаем глобально
- globalThis.EventBus = new AppEventBus()
- # Класс для работы с мультиязычными данными
- class MultilingualData
- constructor: ->
- @currentLanguage = 'ru'
- @availableLanguages = ['ru', 'en', 'tj']
- @fallbackLanguage = 'ru'
-
- # Установка текущего языка
- setLanguage: (language) ->
- if language in @availableLanguages
- @currentLanguage = language
- EventBus.emit('language_changed', language)
- debug.log "Язык изменен на: "+language
-
- # Получение текста для текущего языка
- getText: (textArray, fallback = '') ->
- if not textArray or not Array.isArray(textArray)
- return fallback
-
- languageIndex = @availableLanguages.indexOf(@currentLanguage)
- if languageIndex is -1 or languageIndex >= textArray.length
- languageIndex = @availableLanguages.indexOf(@fallbackLanguage)
-
- return textArray[languageIndex] or fallback
-
- # Получение всех текстов для отладки
- getAllTexts: (textArray) ->
- if not textArray or not Array.isArray(textArray)
- return {}
-
- result = {}
- for lang, index in @availableLanguages
- if textArray[index]
- result[lang] = textArray[index]
- return result
- # Класс для работы с базой данных
- class AppDatabase
- constructor: ->
- @db = null
- @baseUrl = 'https://oleg:631074@couchdb.favt.ru.net'
- @dbName = 'borbad_events'
- @initialized = false
- @multilingual = new MultilingualData()
-
- # Инициализация базы данных
- initialize: ->
- try
- PouchDB = require 'pouchdb'
- @db = new PouchDB(@baseUrl+"/"+@dbName)
-
- # Проверяем соединение
- info = await @db.info()
- debug.log "База данных подключена: "+info.db_name
-
- @initialized = true
- EventBus.emit('database_ready', @db)
-
- catch error
- debug.log "Ошибка подключения к базе данных: "+error
- EventBus.emit('database_error', error)
-
- # Получение документов по типу с мультиязычной обработкой
- getDocumentsByType: (type, options = {}) ->
- if not @initialized
- throw new Error("База данных не инициализирована")
-
- try
- viewName = options.view or 'published_by_domain_language'
- designDoc = options.designDoc or 'multilingual_content'
-
- result = await @db.query(designDoc+'/'+viewName, {
- startkey: [options.domain or 'borbad.s5l.ru', @multilingual.currentLanguage]
- endkey: [options.domain or 'borbad.s5l.ru', @multilingual.currentLanguage, {}]
- include_docs: true
- descending: options.descending or true
- limit: options.limit or 10
- skip: options.skip or 0
- })
-
- # Обрабатываем мультиязычные данные
- processedDocs = result.rows.map (row) =>
- @processMultilingualDocument(row.doc)
-
- return processedDocs
-
- catch error
- debug.log "Ошибка получения документов типа "+type+": "+error
- return []
-
- # Обработка мультиязычного документа
- processMultilingualDocument: (doc) ->
- if not doc
- return null
-
- processedDoc = Object.assign({}, doc)
-
- # Обрабатываем мультиязычные поля
- multilingualFields = ['title', 'content', 'excerpt', 'author', 'name', 'description', 'location']
-
- for field in multilingualFields
- if doc[field] and Array.isArray(doc[field])
- processedDoc[field] = @multilingual.getText(doc[field])
-
- # Обрабатываем вложенные мультиязычные структуры
- if doc.seo
- processedDoc.seo = {}
- if doc.seo.description and Array.isArray(doc.seo.description)
- processedDoc.seo.description = @multilingual.getText(doc.seo.description)
- if doc.seo.title and Array.isArray(doc.seo.title)
- processedDoc.seo.title = @multilingual.getText(doc.seo.title)
- if doc.seo.keywords and Array.isArray(doc.seo.keywords)
- processedDoc.seo.keywords = @multilingual.getText(doc.seo.keywords, [])
-
- # Обрабатываем специфичные данные для разных типов
- if doc.type is 'event' and doc.event_data
- processedDoc.event_data = Object.assign({}, doc.event_data)
- if doc.event_data.location and Array.isArray(doc.event_data.location)
- processedDoc.event_data.location = @multilingual.getText(doc.event_data.location)
- if doc.event_data.price and Array.isArray(doc.event_data.price)
- processedDoc.event_data.price = @multilingual.getText(doc.event_data.price)
-
- if doc.type is 'product' and doc.product_data
- processedDoc.product_data = Object.assign({}, doc.product_data)
- if doc.product_data.price and Array.isArray(doc.product_data.price)
- processedDoc.product_data.price = @multilingual.getText(doc.product_data.price)
-
- if doc.type is 'slide' and doc.slide_data
- processedDoc.slide_data = Object.assign({}, doc.slide_data)
- if doc.slide_data.button_text and Array.isArray(doc.slide_data.button_text)
- processedDoc.slide_data.button_text = @multilingual.getText(doc.slide_data.button_text)
- if doc.slide_data.button_link and Array.isArray(doc.slide_data.button_link)
- processedDoc.slide_data.button_link = @multilingual.getText(doc.slide_data.button_link)
-
- return processedDoc
-
- # Получение блог постов
- getBlogPosts: (options = {}) ->
- options.type = 'blog_post'
- return await @getDocumentsByType('blog_post', options)
-
- # Получение мероприятий
- getEvents: (options = {}) ->
- options.type = 'event'
- options.view = 'by_date_multilingual'
- return await @getDocumentsByType('event', options)
-
- # Получение предстоящих мероприятий
- getUpcomingEvents: (options = {}) ->
- options.type = 'event'
- options.view = 'upcoming_events'
- return await @getDocumentsByType('event', options)
-
- # Получение товаров
- getProducts: (options = {}) ->
- options.type = 'product'
- options.view = 'by_status_multilingual'
- return await @getDocumentsByType('product', options)
-
- # Получение слайдов
- getSlides: (options = {}) ->
- options.type = 'slide'
- options.view = 'active_ordered_multilingual'
- options.descending = false
- return await @getDocumentsByType('slide', options)
-
- # Получение категорий
- getCategories: (options = {}) ->
- if not @initialized
- throw new Error("База данных не инициализирована")
-
- try
- result = await @db.query('categories_hierarchical_multilingual/by_level_multilingual', {
- startkey: [options.domain or 'borbad.s5l.ru', @multilingual.currentLanguage, 0]
- endkey: [options.domain or 'borbad.s5l.ru', @multilingual.currentLanguage, 0, {}]
- include_docs: true
- ascending: true
- })
-
- processedCategories = result.rows.map (row) =>
- @processMultilingualDocument(row.doc)
-
- return processedCategories
-
- catch error
- debug.log "Ошибка получения категорий: "+error
- return []
-
- # Поиск по контенту
- searchContent: (query, options = {}) ->
- if not @initialized
- throw new Error("База данных не инициализирована")
-
- try
- result = await @db.query('universal_multilingual_search/content_search', {
- startkey: [options.domain or 'borbad.s5l.ru', @multilingual.currentLanguage, query.toLowerCase()]
- endkey: [options.domain or 'borbad.s5l.ru', @multilingual.currentLanguage, query.toLowerCase() + "\ufff0"]
- include_docs: true
- limit: options.limit or 20
- })
-
- processedResults = result.rows.map (row) =>
- @processMultilingualDocument(row.doc)
-
- return processedResults
-
- catch error
- debug.log "Ошибка поиска: "+error
- return []
-
- # Получение документа по ID
- getDocumentById: (id) ->
- if not @initialized
- throw new Error("База данных не инициализирована")
-
- try
- doc = await @db.get(id)
- return @processMultilingualDocument(doc)
- catch error
- debug.log "Ошибка получения документа "+id+": "+error
- return null
- # Создаем глобальные экземпляры
- globalThis.AppDB = new AppDatabase()
- globalThis.Multilingual = new MultilingualData()
- # Маршруты
- routes = [
- { path: '/', component: require 'app/pages/Page' }
- { path: '/events', component: require 'app/pages/Events' }
- { path: '/events/:id', component: require 'app/pages/EventDetail' }
- # { path: '/blog', component: require 'app/pages/Blog' }
- # { path: '/blog/:id', component: require 'app/pages/BlogDetail' }
- # { path: '/products', component: require 'app/pages/Products' }
- # { path: '/products/:id', component: require 'app/pages/ProductDetail' }
- { path: '/:slug', component: require 'app/pages/Page' } # Универсальный обработчик страниц
- ]
- # Глобальное определение vuejs приложения
- app = Vue.createApp
- name: 'app'
- data: ()->
- return
- dbReady: false
- loading: true
- error: null
- currentLanguage: 'ru'
- availableLanguages: ['ru', 'en', 'tj']
-
- # Глобальное состояние приложения
- appState:
- slides: []
- featuredEvents: []
- blogPosts: []
- products: []
- categories: []
- loading: true
- error: null
-
- # Состояние модальных окон
- modalState:
- isVisible: false
- component: null
- props: {}
- beforeMount: ()->
- debug.log "start beforeMount"
- # определение контекста vuejs приложения как глобальной переменной _
- globalThis._ = @
-
- # Инициализация базы данных
- AppDB.initialize().then =>
- @dbReady = true
- @loadInitialData()
-
- # Слушаем события смены языка
- EventBus.on 'language_changed', (language) =>
- @currentLanguage = language
- @loadInitialData()
-
- mounted: ->
- debug.log "App mounted"
-
- methods:
- # Загрузка начальных данных
- loadInitialData: ->
- @appState.loading = true
- @appState.error = null
-
- Promise.all([
- @loadSlides()
- @loadFeaturedEvents()
- @loadBlogPosts()
- @loadCategories()
- ]).then =>
- @appState.loading = false
- .catch (error) =>
- @appState.error = "Ошибка загрузки данных: "+error
- @appState.loading = false
-
- # Загрузка слайдов
- loadSlides: ->
- AppDB.getSlides(limit: 6).then (slides) =>
- @appState.slides = slides
- .catch (error) =>
- debug.log "Ошибка загрузки слайдов: "+error
-
- # Загрузка избранных мероприятий
- loadFeaturedEvents: ->
- AppDB.getUpcomingEvents(limit: 4).then (events) =>
- @appState.featuredEvents = events
- .catch (error) =>
- debug.log "Ошибка загрузки мероприятий: "+error
-
- # Загрузка блог постов
- loadBlogPosts: ->
- AppDB.getBlogPosts(limit: 6).then (posts) =>
- @appState.blogPosts = posts
- .catch (error) =>
- debug.log "Ошибка загрузки блог постов: "+error
-
- # Загрузка категорий
- loadCategories: ->
- AppDB.getCategories().then (categories) =>
- @appState.categories = categories
- .catch (error) =>
- debug.log "Ошибка загрузки категорий: "+error
-
- # Смена языка
- changeLanguage: (language) ->
- if language in @availableLanguages
- AppDB.multilingual.setLanguage(language)
- @currentLanguage = language
-
- # Поиск по сайту
- search: (query) ->
- if query and query.length > 2
- AppDB.searchContent(query).then (results) ->
- EventBus.emit('search_results', results)
-
- # Открытие модального окна
- openModal: (component, props = {}) ->
- @modalState.component = component
- @modalState.props = props
- @modalState.isVisible = true
-
- # Закрытие модального окна
- closeModal: ->
- @modalState.isVisible = false
- @modalState.component = null
- @modalState.props = {}
-
- render: (new Function '_ctx', '_cache', renderFns['app/temp.pug'])()
-
- components:
- 'themetoggle': require 'app/shared/ThemeToggle'
- 'multilevelmenu': require 'app/shared/MultiLevelMenu'
- 'imageslider': require 'app/shared/ImageSlider'
- 'app-link': require 'app/shared/AppLink'
- 'language-switcher': require 'app/shared/LanguageSwitcher'
- app.use(VueRouter.createRouter({
- routes: routes
- history: VueRouter.createWebHistory()
- scrollBehavior: (to, from, savedPosition) ->
- if savedPosition
- return savedPosition
- else
- return { x: 0, y: 0 }
- }))
- # подключаем в body ОБЯЗАТЕЛЬНО!!!
- app.mount('body')
|