mirror of
				https://gitlab.com/MrFry/qmining-page
				synced 2025-04-01 20:23:44 +02:00 
			
		
		
		
	added selector component. all questions page fixes and improvements
This commit is contained in:
		
							
								
								
									
										16
									
								
								constants.js
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								constants.js
									
									
									
									
									
								
							@@ -1,16 +0,0 @@
 | 
				
			|||||||
// eslint-disable-next-line no-undef
 | 
					 | 
				
			||||||
const useLocalhost = process && process.env.NODE_ENV === 'development'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const constants = {
 | 
					 | 
				
			||||||
  siteUrl: !useLocalhost ? 'https://frylabs.net/' : 'http://localhost:8080/',
 | 
					 | 
				
			||||||
  apiUrl: !useLocalhost
 | 
					 | 
				
			||||||
    ? 'https://frylabs.net/api/'
 | 
					 | 
				
			||||||
    : 'http://localhost:8080/api/',
 | 
					 | 
				
			||||||
  chatUrl: !useLocalhost ? 'https://frylabs.net/' : 'http://localhost:8080/',
 | 
					 | 
				
			||||||
  mobileWindowWidth: 700,
 | 
					 | 
				
			||||||
  maxQuestionsToRender: 250,
 | 
					 | 
				
			||||||
  imageExts: ['gif', 'png', 'jpeg', 'jpg'],
 | 
					 | 
				
			||||||
  videoExts: ['mp4', 'mkv', 'webm'],
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default constants
 | 
					 | 
				
			||||||
@@ -6,8 +6,11 @@ function highlightText(text, toHighlight) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    const re = new RegExp(toHighlight, 'gi')
 | 
					    const re = new RegExp(toHighlight, 'gi')
 | 
				
			||||||
    const splitText = text.split(toHighlight)
 | 
					    const splitText = text.split(re)
 | 
				
			||||||
    console.log(splitText)
 | 
					    if (splitText.length === 1) {
 | 
				
			||||||
 | 
					      return text
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <>
 | 
					      <>
 | 
				
			||||||
        {splitText[0]}
 | 
					        {splitText[0]}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										48
									
								
								src/components/Selector.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/components/Selector.jsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					import React, { useState } from 'react'
 | 
				
			||||||
 | 
					import styles from './Selector.module.css'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function Selector(props) {
 | 
				
			||||||
 | 
					  const { activeItem, data, onSelect, getLength, getName } = props
 | 
				
			||||||
 | 
					  const [searchTerm, setSearchTerm] = useState('')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const dataToDisplay = data.filter((item) => {
 | 
				
			||||||
 | 
					    return getName(item).toLowerCase().includes(searchTerm.toLowerCase())
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div className={styles.container}>
 | 
				
			||||||
 | 
					      <input
 | 
				
			||||||
 | 
					        type={'text'}
 | 
				
			||||||
 | 
					        onChange={(e) => setSearchTerm(e.target.value)}
 | 
				
			||||||
 | 
					        placeholder={'Kezdj el írni a kereséshez ...'}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <div className="selector">
 | 
				
			||||||
 | 
					        {dataToDisplay.length === 0 && (
 | 
				
			||||||
 | 
					          <div className={styles.noResult}>
 | 
				
			||||||
 | 
					            <span className={styles.itemName}>{'Nincs találat'}</span>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					        {dataToDisplay.map((item, i) => {
 | 
				
			||||||
 | 
					          return (
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              className={
 | 
				
			||||||
 | 
					                activeItem && getName(activeItem) === getName(item)
 | 
				
			||||||
 | 
					                  ? 'selectorItem activeSelectorItem'
 | 
				
			||||||
 | 
					                  : 'selectorItem'
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              key={i}
 | 
				
			||||||
 | 
					              onClick={() => onSelect(item)}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <span className={styles.itemName}>{getName(item)}</span>
 | 
				
			||||||
 | 
					              {getLength && (
 | 
				
			||||||
 | 
					                <span className={styles.questionCount}>
 | 
				
			||||||
 | 
					                  [ {getLength(item)} ]
 | 
				
			||||||
 | 
					                </span>
 | 
				
			||||||
 | 
					              )}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        })}
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/components/Selector.module.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/components/Selector.module.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					.questionCount {
 | 
				
			||||||
 | 
					  justify-content: flex-end;
 | 
				
			||||||
 | 
					  white-space: nowrap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.itemName {
 | 
				
			||||||
 | 
					  word-wrap: break-word;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.container {
 | 
				
			||||||
 | 
					    width: 450px
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.container input {
 | 
				
			||||||
 | 
					  border: 1px solid var(--text-color);
 | 
				
			||||||
 | 
					  border-radius: 5px;
 | 
				
			||||||
 | 
					  padding: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.noResult {
 | 
				
			||||||
 | 
					    margin: 5px;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import React from 'react'
 | 
				
			||||||
import styles from './SubjectSelector.module.css'
 | 
					import styles from './SubjectSelector.module.css'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function SubjectSelector(props) {
 | 
					export default function SubjectSelector(props) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,14 +2,15 @@
 | 
				
			|||||||
const useLocalhost = process && process.env.NODE_ENV === 'development'
 | 
					const useLocalhost = process && process.env.NODE_ENV === 'development'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const constants = {
 | 
					const constants = {
 | 
				
			||||||
  siteUrl: !useLocalhost ? 'https://frylabs.net/' : 'http://localhost:8080/',
 | 
					  siteUrl: useLocalhost ? 'http://localhost:8080/' : 'https://frylabs.net/',
 | 
				
			||||||
  apiUrl: !useLocalhost
 | 
					  apiUrl: useLocalhost
 | 
				
			||||||
    ? 'https://frylabs.net/api/'
 | 
					    ? 'http://localhost:8080/api/'
 | 
				
			||||||
    : 'http://localhost:8080/api/',
 | 
					    : 'https://frylabs.net/api/',
 | 
				
			||||||
  chatUrl: !useLocalhost ? 'https://frylabs.net/' : 'http://localhost:8080/',
 | 
					  chatUrl: useLocalhost ? 'http://localhost:8080/' : 'https://frylabs.net/',
 | 
				
			||||||
  mobileWindowWidth: 700,
 | 
					  mobileWindowWidth: 700,
 | 
				
			||||||
  maxQuestionsToRender: 250,
 | 
					  maxQuestionsToRender: 250,
 | 
				
			||||||
  imageExts: ['gif', 'png', 'jpeg', 'jpg'],
 | 
					  imageExts: ['gif', 'png', 'jpeg', 'jpg'],
 | 
				
			||||||
  videoExts: ['mp4', 'mkv', 'webm'],
 | 
					  videoExts: ['mp4', 'mkv', 'webm'],
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default constants
 | 
					export default constants
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -112,6 +112,7 @@ input:focus {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.data {
 | 
					.data {
 | 
				
			||||||
 | 
					  word-wrap: anywhere;
 | 
				
			||||||
  font-size: 13px;
 | 
					  font-size: 13px;
 | 
				
			||||||
  color: #a1a1a1;
 | 
					  color: #a1a1a1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -123,10 +124,11 @@ input:focus {
 | 
				
			|||||||
  font-size: 30px;
 | 
					  font-size: 30px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.subjectSelector {
 | 
					.subjectSelector, .selector {
 | 
				
			||||||
  overflow: auto;
 | 
					  overflow: auto;
 | 
				
			||||||
  height: auto;
 | 
					  height: auto;
 | 
				
			||||||
  max-height: 250px;
 | 
					  max-height: 150px;
 | 
				
			||||||
 | 
					  min-height: 150px;
 | 
				
			||||||
  margin: 10px;
 | 
					  margin: 10px;
 | 
				
			||||||
  padding: 5px;
 | 
					  padding: 5px;
 | 
				
			||||||
  padding-right: 10px;
 | 
					  padding-right: 10px;
 | 
				
			||||||
@@ -134,8 +136,8 @@ input:focus {
 | 
				
			|||||||
  background-color: #141414;
 | 
					  background-color: #141414;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.subjItem {
 | 
					.subjItem, .selectorItem {
 | 
				
			||||||
  font-size: 18px;
 | 
					  font-size: 14px;
 | 
				
			||||||
  padding: 3px;
 | 
					  padding: 3px;
 | 
				
			||||||
  padding-top: 5px;
 | 
					  padding-top: 5px;
 | 
				
			||||||
  margin-top: 4px;
 | 
					  margin-top: 4px;
 | 
				
			||||||
@@ -144,12 +146,12 @@ input:focus {
 | 
				
			|||||||
  justify-content: space-between;
 | 
					  justify-content: space-between;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.activeSubjItem {
 | 
					.activeSubjItem, .activeSelectorItem {
 | 
				
			||||||
  background-color: var(--text-color);
 | 
					  background-color: var(--text-color);
 | 
				
			||||||
  color: black;
 | 
					  color: black;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.subjItem:hover:not(.activeSubjItem) {
 | 
					.subjItem:hover:not(.activeSubjItem), .selectorItem:hover:not(.activeSelectorItem) {
 | 
				
			||||||
  background-color: #555;
 | 
					  background-color: #555;
 | 
				
			||||||
  color: white;
 | 
					  color: white;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					import React from 'react'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function Error({ statusCode }) {
 | 
					function Error({ statusCode }) {
 | 
				
			||||||
  const render404 = () => {
 | 
					  const render404 = () => {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ import Subject from '../components/Subject'
 | 
				
			|||||||
import SubjectSelector from '../components/SubjectSelector'
 | 
					import SubjectSelector from '../components/SubjectSelector'
 | 
				
			||||||
import ExternalLinkIcon from '../components/externalLinkIcon'
 | 
					import ExternalLinkIcon from '../components/externalLinkIcon'
 | 
				
			||||||
import SearchBar from '../components/searchBar'
 | 
					import SearchBar from '../components/searchBar'
 | 
				
			||||||
 | 
					import Selector from '../components/Selector'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import styles from './allQuestions.module.css'
 | 
					import styles from './allQuestions.module.css'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -202,13 +203,16 @@ export default function AllQuestions({ router, globalState, setGlobalState }) {
 | 
				
			|||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div className={'selectContainer'}>
 | 
					          <div className={'selectContainer'}>
 | 
				
			||||||
            <select
 | 
					            <Selector
 | 
				
			||||||
              value={selectedDb}
 | 
					              data={[...dbs, { path: 'all', name: 'Összes kérdés' }]}
 | 
				
			||||||
              onChange={(event) => {
 | 
					              getName={(db) => db.name}
 | 
				
			||||||
                const key = event.target.value
 | 
					              activeItem={dbs[selectedDb]}
 | 
				
			||||||
 | 
					              onSelect={(item) => {
 | 
				
			||||||
 | 
					                // FIXME: active item is all then no highlight
 | 
				
			||||||
 | 
					                const key = dbs.findIndex((x) => x.path === item.path)
 | 
				
			||||||
                setData(null)
 | 
					                setData(null)
 | 
				
			||||||
                setSelectedDb(key)
 | 
					                setSelectedDb(key === 'all' ? 'all' : key)
 | 
				
			||||||
                if (parseInt(key) === -1) {
 | 
					                if (key === 'all') {
 | 
				
			||||||
                  router.replace(
 | 
					                  router.replace(
 | 
				
			||||||
                    `${router.pathname}?question=${encodeURIComponent(
 | 
					                    `${router.pathname}?question=${encodeURIComponent(
 | 
				
			||||||
                      searchTerm
 | 
					                      searchTerm
 | 
				
			||||||
@@ -228,19 +232,7 @@ export default function AllQuestions({ router, globalState, setGlobalState }) {
 | 
				
			|||||||
                  { shallow: true }
 | 
					                  { shallow: true }
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
            >
 | 
					            />
 | 
				
			||||||
              <option value={-1}>{' Válassz egy adatbázist!'}</option>
 | 
					 | 
				
			||||||
              {dbs.map((db, i) => {
 | 
					 | 
				
			||||||
                return (
 | 
					 | 
				
			||||||
                  <option value={i} key={db.path}>
 | 
					 | 
				
			||||||
                    {db.name}
 | 
					 | 
				
			||||||
                  </option>
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
              })}
 | 
					 | 
				
			||||||
              <option value={'all'} key={'all'}>
 | 
					 | 
				
			||||||
                {'Összes kérdés'}
 | 
					 | 
				
			||||||
              </option>
 | 
					 | 
				
			||||||
            </select>
 | 
					 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </>
 | 
					        </>
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user