|
@@ -5,7 +5,7 @@ globalThis.stylFns = require 'styl.json'
|
|
|
# подключение мета информации (строго в данном фиде)
|
|
# подключение мета информации (строго в данном фиде)
|
|
|
document.head.insertAdjacentHTML 'beforeend','<meta charset="UTF-8">'
|
|
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','<meta name="viewport" content="width=device-width, initial-scale=1.0">'
|
|
|
-document.head.insertAdjacentHTML('beforeend','<title>Кохи Борбад - Концертный зал Душанбе</title>')
|
|
|
|
|
|
|
+document.head.insertAdjacentHTML('beforeend','<title> Кохи Борбад - Концертный зал Душанбе</title>')
|
|
|
|
|
|
|
|
# Настройка tailwind
|
|
# Настройка tailwind
|
|
|
tailwind.config = require 'tailwind.config.js'
|
|
tailwind.config = require 'tailwind.config.js'
|
|
@@ -16,114 +16,401 @@ document.head.insertAdjacentHTML('beforeend','<style type="text/tailwindcss" p
|
|
|
## базовой стиль приложения
|
|
## базовой стиль приложения
|
|
|
document.head.insertAdjacentHTML('beforeend','<style type="text/tailwindcss" page="root">'+stylFns['app/temp.styl']+'</style>')
|
|
document.head.insertAdjacentHTML('beforeend','<style type="text/tailwindcss" page="root">'+stylFns['app/temp.styl']+'</style>')
|
|
|
|
|
|
|
|
-# Подключаем ядро системы
|
|
|
|
|
-CouchDBService = require 'app/core/CouchdbClass'
|
|
|
|
|
|
|
+# Создаем глобальную шину событий
|
|
|
|
|
+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 = [
|
|
routes = [
|
|
|
- { path: '/', component: require 'app/pages/Home' }
|
|
|
|
|
- { path: '/events', component: require 'app/pages/Events' }
|
|
|
|
|
- { path: '/events/:id', component: require 'app/pages/EventDetail' }
|
|
|
|
|
- { path: '/about', component: require 'app/pages/About' }
|
|
|
|
|
- { path: '/contacts', component: require 'app/pages/Contacts' }
|
|
|
|
|
|
|
+ { path: '/', component: require 'app/pages/Home' }
|
|
|
|
|
+ { 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: '/about', component: require 'app/pages/About' }
|
|
|
|
|
+ { path: '/contacts', component: require 'app/pages/Contacts' }
|
|
|
]
|
|
]
|
|
|
|
|
|
|
|
# Глобальное определение vuejs приложения
|
|
# Глобальное определение vuejs приложения
|
|
|
app = Vue.createApp
|
|
app = Vue.createApp
|
|
|
- name: 'app'
|
|
|
|
|
- data: ()->
|
|
|
|
|
|
|
+ name: 'app'
|
|
|
|
|
+ data: ()->
|
|
|
return
|
|
return
|
|
|
- theme: 'light'
|
|
|
|
|
|
|
+ dbReady: false
|
|
|
|
|
+ loading: true
|
|
|
|
|
+ error: null
|
|
|
|
|
+ currentLanguage: 'ru'
|
|
|
|
|
+ availableLanguages: ['ru', 'en', 'tj']
|
|
|
|
|
+
|
|
|
|
|
+ # Глобальное состояние приложения
|
|
|
appState:
|
|
appState:
|
|
|
- events: []
|
|
|
|
|
|
|
+ slides: []
|
|
|
featuredEvents: []
|
|
featuredEvents: []
|
|
|
- sliderEvents: []
|
|
|
|
|
|
|
+ blogPosts: []
|
|
|
|
|
+ products: []
|
|
|
|
|
+ categories: []
|
|
|
loading: true
|
|
loading: true
|
|
|
error: null
|
|
error: null
|
|
|
- modalState:
|
|
|
|
|
|
|
+
|
|
|
|
|
+ # Состояние модальных окон
|
|
|
|
|
+ modalState:
|
|
|
isVisible: false
|
|
isVisible: false
|
|
|
component: null
|
|
component: null
|
|
|
props: {}
|
|
props: {}
|
|
|
- couchDBService: new CouchDBService()
|
|
|
|
|
- beforeMount: ()->
|
|
|
|
|
|
|
+ beforeMount: ()->
|
|
|
debug.log "start beforeMount"
|
|
debug.log "start beforeMount"
|
|
|
# определение контекста vuejs приложения как глобальной переменной _
|
|
# определение контекста vuejs приложения как глобальной переменной _
|
|
|
globalThis._ = @
|
|
globalThis._ = @
|
|
|
- render: (new Function '_ctx', '_cache', renderFns['app/temp.pug'])()
|
|
|
|
|
- mounted: ->
|
|
|
|
|
- # Предзагрузка темы
|
|
|
|
|
- if localStorage.theme == 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
|
|
|
|
- @theme = 'dark'
|
|
|
|
|
- document.documentElement.classList.add('dark')
|
|
|
|
|
- else
|
|
|
|
|
- @theme = 'light'
|
|
|
|
|
- document.documentElement.classList.remove('dark')
|
|
|
|
|
-
|
|
|
|
|
- # Загрузка данных из CouchDB
|
|
|
|
|
- @loadEventsData()
|
|
|
|
|
- methods:
|
|
|
|
|
- toggleTheme: ->
|
|
|
|
|
- @theme = if @theme == 'light' then 'dark' else 'light'
|
|
|
|
|
- localStorage.setItem 'theme', @theme
|
|
|
|
|
- document.documentElement.classList.toggle 'dark'
|
|
|
|
|
|
|
|
|
|
|
|
+ # Инициализация базы данных
|
|
|
|
|
+ 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 = {}) ->
|
|
openModal: (component, props = {}) ->
|
|
|
@modalState.component = component
|
|
@modalState.component = component
|
|
|
@modalState.props = props
|
|
@modalState.props = props
|
|
|
@modalState.isVisible = true
|
|
@modalState.isVisible = true
|
|
|
|
|
|
|
|
|
|
+ # Закрытие модального окна
|
|
|
closeModal: ->
|
|
closeModal: ->
|
|
|
@modalState.isVisible = false
|
|
@modalState.isVisible = false
|
|
|
@modalState.component = null
|
|
@modalState.component = null
|
|
|
@modalState.props = {}
|
|
@modalState.props = {}
|
|
|
|
|
|
|
|
- loadEventsData: ->
|
|
|
|
|
- @appState.loading = true
|
|
|
|
|
- @couchDBService.getAllEvents()
|
|
|
|
|
- .then (events) =>
|
|
|
|
|
- @appState.events = events
|
|
|
|
|
- @appState.featuredEvents = events.filter((event) -> event.isFeatured).slice(0, 6)
|
|
|
|
|
- @appState.sliderEvents = events.filter((event) -> event.inSlider).map (event) ->
|
|
|
|
|
- id: event._id
|
|
|
|
|
- image: event.image || '/images/default-event.jpg'
|
|
|
|
|
- title: event.title
|
|
|
|
|
- description: event.shortDescription || event.description
|
|
|
|
|
- cta: event.cta || 'Подробнее'
|
|
|
|
|
- category: event.category
|
|
|
|
|
- @appState.error = null
|
|
|
|
|
- .catch (error) =>
|
|
|
|
|
- debug.log "Ошибка загрузки данных: "+error
|
|
|
|
|
- @appState.error = 'Не удалось загрузить данные мероприятий'
|
|
|
|
|
- .finally =>
|
|
|
|
|
- @appState.loading = false
|
|
|
|
|
-
|
|
|
|
|
- getEvents: -> @appState.events
|
|
|
|
|
- getFeaturedEvents: -> @appState.featuredEvents
|
|
|
|
|
- getSliderEvents: -> @appState.sliderEvents
|
|
|
|
|
- isLoading: -> @appState.loading
|
|
|
|
|
- hasError: -> @appState.error
|
|
|
|
|
- components:
|
|
|
|
|
- 'themetoggle': require 'app/shared/ThemeToggle'
|
|
|
|
|
- 'multilevelmenu': require 'app/shared/MultiLevelMenu'
|
|
|
|
|
- 'imageslider': require 'app/shared/ImageSlider'
|
|
|
|
|
- 'modalwindow': require 'app/shared/ModalWindow'
|
|
|
|
|
- 'formvalidator': require 'app/shared/FormValidator'
|
|
|
|
|
- 'filtersort': require 'app/shared/FilterSort'
|
|
|
|
|
- 'eventdetailmodal': require 'app/shared/EventDetailModal'
|
|
|
|
|
- 'successmodal': require 'app/shared/SuccessModal'
|
|
|
|
|
- 'app-link': require 'app/shared/AppLink'
|
|
|
|
|
|
|
+ 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({
|
|
app.use(VueRouter.createRouter({
|
|
|
- routes: routes
|
|
|
|
|
- history: VueRouter.createWebHistory()
|
|
|
|
|
- scrollBehavior: (to, from, savedPosition) ->
|
|
|
|
|
- if savedPosition
|
|
|
|
|
- return savedPosition
|
|
|
|
|
- else
|
|
|
|
|
- return { x: 0, y: 0 }
|
|
|
|
|
|
|
+ routes: routes
|
|
|
|
|
+ history: VueRouter.createWebHistory()
|
|
|
|
|
+ scrollBehavior: (to, from, savedPosition) ->
|
|
|
|
|
+ if savedPosition
|
|
|
|
|
+ return savedPosition
|
|
|
|
|
+ else
|
|
|
|
|
+ return { x: 0, y: 0 }
|
|
|
}))
|
|
}))
|
|
|
|
|
|
|
|
# подключаем в body ОБЯЗАТЕЛЬНО!!!
|
|
# подключаем в body ОБЯЗАТЕЛЬНО!!!
|
|
|
app.mount('body')
|
|
app.mount('body')
|
|
|
-
|
|
|
|
|
-debug.log "Vue application initialized successfully"
|
|
|