diff --git a/client/client-app.js b/client/client-app.js
index d2b59038..a0cd3a84 100644
--- a/client/client-app.js
+++ b/client/client-app.js
@@ -168,6 +168,7 @@ Vue.component('page-selector', () => import(/* webpackPrefetch: true, webpackChu
Vue.component('profile', () => import(/* webpackChunkName: "profile" */ './components/profile.vue'))
Vue.component('register', () => import(/* webpackChunkName: "register" */ './components/register.vue'))
Vue.component('v-card-chin', () => import(/* webpackPrefetch: true, webpackChunkName: "ui-extra" */ './components/common/v-card-chin.vue'))
+Vue.component('search-results', () => import(/* webpackPrefetch: true, webpackChunkName: "ui-extra" */ './components/common/search-results.vue'))
Vue.component('nav-footer', () => import(/* webpackChunkName: "theme-page" */ './themes/' + process.env.CURRENT_THEME + '/components/nav-footer.vue'))
Vue.component('nav-sidebar', () => import(/* webpackChunkName: "theme-page" */ './themes/' + process.env.CURRENT_THEME + '/components/nav-sidebar.vue'))
diff --git a/client/components/admin/admin-contribute.vue b/client/components/admin/admin-contribute.vue
index 4861b466..aeeec3d3 100644
--- a/client/components/admin/admin-contribute.vue
+++ b/client/components/admin/admin-contribute.vue
@@ -151,6 +151,16 @@
v-list-tile-action
v-btn(icon, href='https://lokalise.co', target='_blank')
v-icon(color='grey') public
+ v-divider
+ v-list-tile
+ v-list-tile-avatar(tile)
+ img(src='https://static.requarks.io/logo/netlify.svg', alt='Netlify')
+ v-list-tile-content
+ v-list-tile-title Netlify
+ v-list-tile-sub-title Deploy modern static websites with Netlify. Get CDN, Continuous deployment, 1-click HTTPS, and all the services you need.
+ v-list-tile-action
+ v-btn(icon, href='https://wwwnetlify.com', target='_blank')
+ v-icon(color='grey') public
diff --git a/client/components/admin/admin-search.vue b/client/components/admin/admin-search.vue
index d0abe78c..33e63dd9 100644
--- a/client/components/admin/admin-search.vue
+++ b/client/components/admin/admin-search.vue
@@ -6,7 +6,7 @@
img(src='/svg/icon-search.svg', alt='Search Engine', style='width: 80px;')
.admin-header-title
.headline.primary--text Search Engine
- .subheading.grey--text Configure the search capabilities of your wiki #[v-chip(label, color='primary', small).white--text coming soon]
+ .subheading.grey--text Configure the search capabilities of your wiki
v-spacer
v-btn(outline, color='grey', @click='refresh', large)
v-icon refresh
@@ -17,74 +17,69 @@
v-icon(left) check
span {{$t('common:actions.apply')}}
- v-card.mt-3
- v-tabs(color='grey darken-2', fixed-tabs, slider-color='white', show-arrows, dark)
- v-tab(key='settings'): v-icon settings
- v-tab(v-for='engine in activeEngines', :key='engine.key') {{ engine.title }}
+ v-flex(lg3, xs12)
+ v-card
+ v-toolbar(flat, color='primary', dark, dense)
+ .subheading Search Engine
+ v-card-text
+ v-radio-group.my-0(v-model='selectedEngine')
+ v-radio.my-1(
+ v-for='(engine, n) in engines'
+ :key='engine.key'
+ :label='engine.title'
+ :value='engine.key'
+ color='primary'
+ hide-details
+ )
- v-tab-item(key='settings', :transition='false', :reverse-transition='false')
- v-card.pa-3(flat, tile)
- .body-2.grey--text.text--darken-1 Select which search engine to enable:
- .caption.grey--text.pb-2 Some search engines require additional configuration in their dedicated tab (when selected).
- v-form
- v-radio-group(v-model='selectedEngine')
- v-radio.my-1(
- v-for='(engine, n) in engines'
- :key='engine.key'
- :label='engine.title'
- :value='engine.key'
- color='primary'
- hide-details
- disabled
- )
-
- v-tab-item(v-for='(engine, n) in activeEngines', :key='engine.key', :transition='false', :reverse-transition='false')
- v-card.pa-3(flat, tile)
- v-form
- .enginelogo
- img(:src='engine.logo', :alt='engine.title')
- v-subheader.pl-0 {{engine.title}}
- .caption {{engine.description}}
- .caption: a(:href='engine.website') {{engine.website}}
- v-divider.mt-3
- v-subheader.pl-0 Engine Configuration
- .body-1.ml-3(v-if='!engine.config || engine.config.length < 1') This engine has no configuration options you can modify.
- template(v-else, v-for='cfg in logger.config')
- v-select(
- v-if='cfg.value.type === "string" && cfg.value.enum'
- outline
- background-color='grey lighten-2'
- :items='cfg.value.enum'
- :key='cfg.key'
- :label='cfg.value.title'
- v-model='cfg.value.value'
- prepend-icon='settings_applications'
- :hint='cfg.value.hint ? cfg.value.hint : ""'
- persistent-hint
- :class='cfg.value.hint ? "mb-2" : ""'
- )
- v-switch(
- v-else-if='cfg.value.type === "boolean"'
- :key='cfg.key'
- :label='cfg.value.title'
- v-model='cfg.value.value'
- color='primary'
- prepend-icon='settings_applications'
- :hint='cfg.value.hint ? cfg.value.hint : ""'
- persistent-hint
- )
- v-text-field(
- v-else
- outline
- background-color='grey lighten-2'
- :key='cfg.key'
- :label='cfg.value.title'
- v-model='cfg.value.value'
- prepend-icon='settings_applications'
- :hint='cfg.value.hint ? cfg.value.hint : ""'
- persistent-hint
- :class='cfg.value.hint ? "mb-2" : ""'
- )
+ v-flex(lg9, xs12)
+ v-card.wiki-form
+ v-toolbar(color='primary', dense, flat, dark)
+ .subheading {{engine.title}}
+ v-card-text
+ .enginelogo
+ img(:src='engine.logo', :alt='engine.title')
+ .caption.pt-3 {{engine.description}}
+ .caption.pb-3: a(:href='engine.website') {{engine.website}}
+ v-divider.mt-3
+ v-subheader.pl-0 Engine Configuration
+ .body-1.ml-3(v-if='!engine.config || engine.config.length < 1') This engine has no configuration options you can modify.
+ template(v-else, v-for='cfg in engine.config')
+ v-select(
+ v-if='cfg.value.type === "string" && cfg.value.enum'
+ outline
+ background-color='grey lighten-2'
+ :items='cfg.value.enum'
+ :key='cfg.key'
+ :label='cfg.value.title'
+ v-model='cfg.value.value'
+ prepend-icon='settings_applications'
+ :hint='cfg.value.hint ? cfg.value.hint : ""'
+ persistent-hint
+ :class='cfg.value.hint ? "mb-2" : ""'
+ )
+ v-switch.mb-3(
+ v-else-if='cfg.value.type === "boolean"'
+ :key='cfg.key'
+ :label='cfg.value.title'
+ v-model='cfg.value.value'
+ color='primary'
+ prepend-icon='settings_applications'
+ :hint='cfg.value.hint ? cfg.value.hint : ""'
+ persistent-hint
+ )
+ v-text-field(
+ v-else
+ outline
+ background-color='grey lighten-2'
+ :key='cfg.key'
+ :label='cfg.value.title'
+ v-model='cfg.value.value'
+ prepend-icon='settings_applications'
+ :hint='cfg.value.hint ? cfg.value.hint : ""'
+ persistent-hint
+ :class='cfg.value.hint ? "mb-2" : ""'
+ )
+
+
diff --git a/client/graph/common/common-pages-query-search.gql b/client/graph/common/common-pages-query-search.gql
new file mode 100644
index 00000000..e36445b3
--- /dev/null
+++ b/client/graph/common/common-pages-query-search.gql
@@ -0,0 +1,15 @@
+query ($query: String!) {
+ pages {
+ search(query:$query) {
+ results {
+ id
+ title
+ description
+ path
+ locale
+ }
+ suggestions
+ totalHits
+ }
+ }
+}
diff --git a/client/scss/global.scss b/client/scss/global.scss
index 5bb1cd7e..72a04902 100644
--- a/client/scss/global.scss
+++ b/client/scss/global.scss
@@ -6,3 +6,27 @@
$tablet: 769px !default;
$desktop: 980px !default;
$widescreen: 1180px !default;
+
+$grid-breakpoints: (
+ 'xs': 0,
+ 'sm': 600px,
+ 'md': 960px,
+ 'lg': 1280px - 16px,
+ 'xl': 1920px - 16px
+) !default;
+
+$display-breakpoints: (
+ 'print-only': 'only print',
+ 'screen-only': 'only screen',
+ 'xs-only': 'only screen and (max-width: #{map-get($grid-breakpoints, 'sm') - 1})',
+ 'sm-only': 'only screen and (min-width: #{map-get($grid-breakpoints, 'sm')}) and (max-width: #{map-get($grid-breakpoints, 'md') - 1})',
+ 'sm-and-down': 'only screen and (max-width: #{map-get($grid-breakpoints, 'md') - 1})',
+ 'sm-and-up': 'only screen and (min-width: #{map-get($grid-breakpoints, 'sm')})',
+ 'md-only': 'only screen and (min-width: #{map-get($grid-breakpoints, 'md')}) and (max-width: #{map-get($grid-breakpoints, 'lg') - 1})',
+ 'md-and-down': 'only screen and (max-width: #{map-get($grid-breakpoints, 'lg') - 1})',
+ 'md-and-up': 'only screen and (min-width: #{map-get($grid-breakpoints, 'md')})',
+ 'lg-only': 'only screen and (min-width: #{map-get($grid-breakpoints, 'lg')}) and (max-width: #{map-get($grid-breakpoints, 'xl') - 1})',
+ 'lg-and-down': 'only screen and (max-width: #{map-get($grid-breakpoints, 'xl') - 1})',
+ 'lg-and-up': 'only screen and (min-width: #{map-get($grid-breakpoints, 'lg')})',
+ 'xl-only': 'only screen and (min-width: #{map-get($grid-breakpoints, 'xl')})'
+) !default;
diff --git a/client/static/svg/icon-no-results.svg b/client/static/svg/icon-no-results.svg
new file mode 100644
index 00000000..2d1d0462
--- /dev/null
+++ b/client/static/svg/icon-no-results.svg
@@ -0,0 +1,8 @@
+
+
diff --git a/client/static/svg/icon-selective-highlighting.svg b/client/static/svg/icon-selective-highlighting.svg
new file mode 100644
index 00000000..232d157d
--- /dev/null
+++ b/client/static/svg/icon-selective-highlighting.svg
@@ -0,0 +1,40 @@
+
+
+
diff --git a/client/store/site.js b/client/store/site.js
index 72813eda..68035a93 100644
--- a/client/store/site.js
+++ b/client/store/site.js
@@ -6,7 +6,11 @@ const state = {
company: '',
dark: siteConfig.darkMode,
mascot: true,
- title: siteConfig.title
+ title: siteConfig.title,
+ search: '',
+ searchIsLoading: false,
+ searchRestrictLocale: false,
+ searchRestrictPath: false
}
export default {
diff --git a/client/themes/default/components/page.vue b/client/themes/default/components/page.vue
index ab78fc25..a8a29733 100644
--- a/client/themes/default/components/page.vue
+++ b/client/themes/default/components/page.vue
@@ -117,6 +117,7 @@
span Print Format
v-spacer
nav-footer
+ search-results
v-fab-transition
v-btn(v-if='upBtnShown', fab, fixed, bottom, right, small, @click='$vuetify.goTo(0, scrollOpts)', color='primary')
v-icon arrow_upward
diff --git a/dev/docker-postgres/docker-compose.yml b/dev/docker-postgres/docker-compose.yml
index 06383e06..414b5d2c 100644
--- a/dev/docker-postgres/docker-compose.yml
+++ b/dev/docker-postgres/docker-compose.yml
@@ -27,12 +27,28 @@ services:
ports:
- "3001:8080"
+ solr:
+ image: solr:7-alpine
+ logging:
+ driver: "none"
+ networks:
+ - wikinet
+ ports:
+ - "8983:8983"
+ volumes:
+ - solr-data:/opt/solr/server/solr/mycores
+ entrypoint:
+ - docker-entrypoint.sh
+ - solr-precreate
+ - wiki
+
wiki:
build:
context: .
dockerfile: dev/docker-postgres/Dockerfile
depends_on:
- db
+ - solr
networks:
- wikinet
ports:
@@ -47,3 +63,4 @@ networks:
volumes:
db-data:
+ solr-data:
diff --git a/package.json b/package.json
index 604b0a8b..28ff2b62 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,8 @@
"dependency-graph": "0.8.0",
"diff": "4.0.1",
"diff2html": "2.7.0",
- "dotize": "^0.3.0",
+ "dotize": "0.3.0",
+ "elasticsearch": "15.4.1",
"express": "4.16.4",
"express-brute": "1.0.1",
"file-type": "10.7.1",
@@ -146,6 +147,7 @@
"semver": "5.6.0",
"serve-favicon": "2.5.0",
"simple-git": "1.107.0",
+ "solr-node": "1.1.3",
"sqlite3": "4.0.6",
"subscriptions-transport-ws": "0.9.15",
"twemoji": "11.3.0",
diff --git a/server/app/data.yml b/server/app/data.yml
index 59104295..c76d2663 100644
--- a/server/app/data.yml
+++ b/server/app/data.yml
@@ -45,6 +45,8 @@ defaults:
maxAge: 600
methods: 'GET,POST'
origin: true
+ search:
+ maxHits: 100
localeNamespaces:
- admin
- auth
diff --git a/server/core/kernel.js b/server/core/kernel.js
index 6926fa7b..8fb1b250 100644
--- a/server/core/kernel.js
+++ b/server/core/kernel.js
@@ -69,6 +69,7 @@ module.exports = {
await WIKI.models.storage.refreshTargetsFromDisk()
await WIKI.auth.activateStrategies()
+ await WIKI.models.searchEngines.initEngine()
await WIKI.models.storage.initTargets()
WIKI.scheduler.start()
},
diff --git a/server/graph/resolvers/page.js b/server/graph/resolvers/page.js
index 00413a90..df79cb3f 100644
--- a/server/graph/resolvers/page.js
+++ b/server/graph/resolvers/page.js
@@ -16,7 +16,18 @@ module.exports = {
offsetPage: args.offsetPage || 0,
offsetSize: args.offsetSize || 100
})
- }
+ },
+ async search (obj, args, context) {
+ if (WIKI.data.searchEngine) {
+ return WIKI.data.searchEngine.query(args.query, args)
+ } else {
+ return {
+ results: [],
+ suggestions: [],
+ totalHits: 0
+ }
+ }
+ },
},
PageMutation: {
async create(obj, args, context) {
diff --git a/server/graph/schemas/page.graphql b/server/graph/schemas/page.graphql
index b9c9babe..1e16d4c3 100644
--- a/server/graph/schemas/page.graphql
+++ b/server/graph/schemas/page.graphql
@@ -20,6 +20,12 @@ type PageQuery {
offsetPage: Int
offsetSize: Int
): PageHistoryResult @auth(requires: ["manage:system", "read:pages"])
+
+ search(
+ query: String!
+ path: String
+ locale: String
+ ): PageSearchResponse! @auth(requires: ["manage:system", "read:pages"])
}
# -----------------------------------------------
@@ -88,3 +94,17 @@ type PageHistoryResult {
trail: [PageHistory]
total: Int!
}
+
+type PageSearchResponse {
+ results: [PageSearchResult]!
+ suggestions: [String]!
+ totalHits: Int!
+}
+
+type PageSearchResult {
+ id: Int!
+ title: String!
+ description: String!
+ path: String!
+ locale: String!
+}
diff --git a/server/models/searchEngines.js b/server/models/searchEngines.js
index e827c998..44d63aa9 100644
--- a/server/models/searchEngines.js
+++ b/server/models/searchEngines.js
@@ -95,6 +95,19 @@ module.exports = class SearchEngine extends Model {
}
}
+ static async initEngine() {
+ const searchEngine = await WIKI.models.searchEngines.query().findOne('isEnabled', true)
+ if (searchEngine) {
+ WIKI.data.searchEngine = require(`../modules/search/${searchEngine.key}/engine`)
+ WIKI.data.searchEngine.config = searchEngine.config
+ try {
+ await WIKI.data.searchEngine.init()
+ } catch (err) {
+ WIKI.logger.warn(err)
+ }
+ }
+ }
+
static async pageEvent({ event, page }) {
const searchEngines = await WIKI.models.storage.query().where('isEnabled', true)
if (searchEngines && searchEngines.length > 0) {
diff --git a/server/modules/search/algolia/definition.yml b/server/modules/search/algolia/definition.yml
index 0d92a779..50cbb501 100644
--- a/server/modules/search/algolia/definition.yml
+++ b/server/modules/search/algolia/definition.yml
@@ -4,4 +4,20 @@ description: Algolia is a powerful search-as-a-service solution, made easy to us
author: requarks.io
logo: https://static.requarks.io/logo/algolia.svg
website: https://www.algolia.com/
-props: {}
+props:
+ appId:
+ type: String
+ title: App ID
+ hint: Your Algolia Application ID, found under API Keys
+ order: 1
+ apiKey:
+ type: String
+ title: Admin API Key
+ hint: Your Algolia Admin API Key, found under API Keys.
+ order: 2
+ indexName:
+ type: String
+ title: Index Name
+ hint: The name of the index you created under Indices.
+ default: wiki
+ order: 3
diff --git a/server/modules/search/db/definition.yml b/server/modules/search/db/definition.yml
index 05e5e75e..56a63196 100644
--- a/server/modules/search/db/definition.yml
+++ b/server/modules/search/db/definition.yml
@@ -1,6 +1,6 @@
key: db
-title: Database (built-in)
-description: Default database-based search engine.
+title: Database - Basic
+description: Default basic database-based search engine.
author: requarks.io
logo: https://static.requarks.io/logo/database.svg
website: https://www.requarks.io/
diff --git a/server/modules/search/db/engine.js b/server/modules/search/db/engine.js
index e7369ccd..1721a3bd 100644
--- a/server/modules/search/db/engine.js
+++ b/server/modules/search/db/engine.js
@@ -1,26 +1,121 @@
+const _ = require('lodash')
+
module.exports = {
activate() {
-
+ // not used
},
deactivate() {
-
+ // not used
},
- query() {
-
+ /**
+ * INIT
+ */
+ init() {
+ // not used
},
- created() {
-
+ /**
+ * SUGGEST
+ *
+ * @param {String} q Query
+ * @param {Object} opts Additional options
+ */
+ async suggest(q, opts) {
+ const results = await WIKI.models.pages.query()
+ .column('title')
+ .where(builder => {
+ builder.where('isPublished', true)
+ if (opts.locale) {
+ builder.andWhere('locale', opts.locale)
+ }
+ if (opts.path) {
+ builder.andWhere('path', 'like', `${opts.path}%`)
+ }
+ builder.andWhere('title', 'like', `%${q}%`)
+ })
+ .limit(10)
+ return _.uniq(_.filter(_.flatten(results.map(r => r.title.split(' '))), w => w.indexOf(q) >= 0))
},
- updated() {
+ /**
+ * QUERY
+ *
+ * @param {String} q Query
+ * @param {Object} opts Additional options
+ */
+ async query(q, opts) {
+ const results = await WIKI.models.pages.query()
+ .column('id', 'title', 'description', 'path', 'localeCode as locale')
+ .where(builder => {
+ builder.where('isPublished', true)
+ if (opts.locale) {
+ builder.andWhere('localeCode', opts.locale)
+ }
+ if (opts.path) {
+ builder.andWhere('path', 'like', `${opts.path}%`)
+ }
+ // TODO: Add user permissions filtering
+ builder.andWhere(builder => {
+ switch(WIKI.config.db.type) {
+ case 'postgres':
+ builder.where('title', 'ILIKE', `%${q}%`)
+ builder.orWhere('description', 'ILIKE', `%${q}%`)
+ break
+ case 'mysql':
+ case 'mariadb':
+ builder.whereRaw(`title LIKE '%?%' COLLATE utf8_general_ci`, [q])
+ builder.orWhereRaw(`description LIKE '%?%' COLLATE utf8_general_ci`, [q])
+ break
+ // TODO: MSSQL handling
+ default:
+ builder.where('title', 'LIKE', `%${q}%`)
+ builder.orWhere('description', 'LIKE', `%${q}%`)
+ break
+ }
+ })
+ })
+ .limit(WIKI.config.search.maxHits)
+ return {
+ results,
+ suggestions: [],
+ totalHits: results.length
+ }
},
- deleted() {
-
+ /**
+ * CREATE
+ *
+ * @param {Object} page Page to create
+ */
+ async created(page) {
+ // not used
},
- renamed() {
-
+ /**
+ * UPDATE
+ *
+ * @param {Object} page Page to update
+ */
+ async updated(page) {
+ // not used
},
- rebuild() {
-
+ /**
+ * DELETE
+ *
+ * @param {Object} page Page to delete
+ */
+ async deleted(page) {
+ // not used
+ },
+ /**
+ * RENAME
+ *
+ * @param {Object} page Page to rename
+ */
+ async renamed(page) {
+ // not used
+ },
+ /**
+ * REBUILD INDEX
+ */
+ async rebuild() {
+ // not used
}
}
diff --git a/server/modules/search/elasticsearch/definition.yml b/server/modules/search/elasticsearch/definition.yml
index 3f559933..a10b066f 100644
--- a/server/modules/search/elasticsearch/definition.yml
+++ b/server/modules/search/elasticsearch/definition.yml
@@ -4,4 +4,41 @@ description: Elasticsearch is a distributed, RESTful search and analytics engine
author: requarks.io
logo: https://static.requarks.io/logo/elasticsearch.svg
website: https://www.elastic.co/products/elasticsearch
-props: {}
+props:
+ apiVersion:
+ type: String
+ title: API Version
+ hint: Should match the version of the Elasticsearch nodes you are connecting to
+ order: 1
+ enum:
+ - '6.6'
+ - '6.5'
+ - '6.4'
+ - '6.3'
+ default: '6.6'
+ host:
+ type: String
+ title: Host(s)
+ hint: Comma-separated list of Elasticsearch hosts to connect to
+ order: 2
+ user:
+ type: String
+ title: Username
+ order: 3
+ pass:
+ type: String
+ title: Password
+ order: 4
+ sniff:
+ type: Boolean
+ title: Sniff on start
+ hint: 'Should Wiki.js attempt to detect the rest of the cluster on first connect? (Default: off)'
+ default: false
+ order: 5
+ sniffInterval:
+ type: Number
+ title: Sniff Interval
+ hint: '0 = disabled, Interval in seconds to check for updated list of nodes in cluster. (Default: 0)'
+ order: 6
+ default: 0
+
diff --git a/server/modules/search/postgres/definition.yml b/server/modules/search/postgres/definition.yml
new file mode 100644
index 00000000..085eabc9
--- /dev/null
+++ b/server/modules/search/postgres/definition.yml
@@ -0,0 +1,30 @@
+key: postgres
+title: Database - PostgreSQL
+description: Advanced PostgreSQL-based search engine.
+author: requarks.io
+logo: https://static.requarks.io/logo/postgresql.svg
+website: https://www.requarks.io/
+props:
+ dictLanguage:
+ type: String
+ title: Dictionnary Language
+ hint: Language to use when creating and querying text search vectors.
+ default: english
+ enum:
+ - simple
+ - danish
+ - dutch
+ - english
+ - finnish
+ - french
+ - german
+ - hungarian
+ - italian
+ - norwegian
+ - portuguese
+ - romanian
+ - russian
+ - spanish
+ - swedish
+ - turkish
+ order: 1
diff --git a/server/modules/search/postgres/engine.js b/server/modules/search/postgres/engine.js
new file mode 100644
index 00000000..d3178be5
--- /dev/null
+++ b/server/modules/search/postgres/engine.js
@@ -0,0 +1,72 @@
+const _ = require('lodash')
+
+module.exports = {
+ activate() {
+ // not used
+ },
+ deactivate() {
+ // not used
+ },
+ /**
+ * INIT
+ */
+ init() {
+ // not used
+ },
+ /**
+ * SUGGEST
+ *
+ * @param {String} q Query
+ * @param {Object} opts Additional options
+ */
+ async suggest(q, opts) {
+
+ },
+ /**
+ * QUERY
+ *
+ * @param {String} q Query
+ * @param {Object} opts Additional options
+ */
+ async query(q, opts) {
+
+ },
+ /**
+ * CREATE
+ *
+ * @param {Object} page Page to create
+ */
+ async created(page) {
+ // not used
+ },
+ /**
+ * UPDATE
+ *
+ * @param {Object} page Page to update
+ */
+ async updated(page) {
+ // not used
+ },
+ /**
+ * DELETE
+ *
+ * @param {Object} page Page to delete
+ */
+ async deleted(page) {
+ // not used
+ },
+ /**
+ * RENAME
+ *
+ * @param {Object} page Page to rename
+ */
+ async renamed(page) {
+ // not used
+ },
+ /**
+ * REBUILD INDEX
+ */
+ async rebuild() {
+ // not used
+ }
+}
diff --git a/server/modules/search/solr/definition.yml b/server/modules/search/solr/definition.yml
index 1a5216f7..299fdc85 100644
--- a/server/modules/search/solr/definition.yml
+++ b/server/modules/search/solr/definition.yml
@@ -4,4 +4,31 @@ description: Solr is the popular, blazing-fast, open source enterprise search pl
author: requarks.io
logo: https://static.requarks.io/logo/solr.svg
website: http://lucene.apache.org/solr/
-props: {}
+props:
+ host:
+ type: String
+ title: Host
+ hint: Host of the Solr server (e.g. 12.34.56.78 or solr.example.com)
+ default: solr
+ order: 1
+ port:
+ type: Number
+ title: Port
+ hint: Port of the Solr server
+ default: 8983
+ order: 2
+ core:
+ type: String
+ title: Core
+ hint: Core name (e.g. wiki)
+ default: wiki
+ order: 3
+ protocol:
+ type: String
+ title: Protocol
+ hint: Request protocol
+ default: http
+ enum:
+ - http
+ - https
+ order: 4