├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src ├── main ├── java │ └── com │ │ └── libqa │ │ ├── Application.java │ │ ├── application │ │ ├── dto │ │ │ ├── FileDto.java │ │ │ ├── QaDto.java │ │ │ └── SecurityUserDto.java │ │ ├── enums │ │ │ ├── ActionType.java │ │ │ ├── ActivityType.java │ │ │ ├── DayType.java │ │ │ ├── FavoriteType.java │ │ │ ├── FileType.java │ │ │ ├── KeywordType.java │ │ │ ├── ListType.java │ │ │ ├── PostType.java │ │ │ ├── ProcessType.java │ │ │ ├── QaSearchType.java │ │ │ ├── Role.java │ │ │ ├── SearchTargetPage.java │ │ │ ├── SocialChannelType.java │ │ │ ├── SpaceView.java │ │ │ ├── StatusCode.java │ │ │ ├── UserPoint.java │ │ │ ├── WaitReplyType.java │ │ │ ├── WikiLikesType.java │ │ │ ├── WikiRevisionActionType.java │ │ │ └── converter │ │ │ │ └── QaSearchTypeEnumConverter.java │ │ ├── exception │ │ │ ├── FilePermitMsgException.java │ │ │ └── UserNotCreateException.java │ │ ├── framework │ │ │ └── ResponseData.java │ │ ├── handler │ │ │ ├── CustomLoginFailureHandler.java │ │ │ ├── CustomLoginSuccessHandler.java │ │ │ └── ErrorAccessHandler.java │ │ ├── helper │ │ │ └── HandlebarsHelper.java │ │ └── util │ │ │ ├── DateUtil.java │ │ │ ├── FileHandler.java │ │ │ ├── GetThumbImage.java │ │ │ ├── HtmlContentHandler.java │ │ │ ├── LibqaConstant.java │ │ │ ├── LoggedUserManager.java │ │ │ ├── PageUtil.java │ │ │ ├── RequestUtil.java │ │ │ └── StringUtil.java │ │ ├── config │ │ ├── CacheConfiguration.java │ │ ├── LoginUserHandlerInterceptor.java │ │ ├── SendMailConfiguration.java │ │ ├── WebAppInitializer.java │ │ ├── WebMvcConfiguration.java │ │ ├── WebSecurityConfiguration.java │ │ └── security │ │ │ ├── CustomAuthenticationProvider.java │ │ │ ├── UserDetailsImpl.java │ │ │ └── UserDetailsServiceImpl.java │ │ └── web │ │ ├── controller │ │ ├── CommonController.java │ │ ├── ErrorPageController.java │ │ ├── FeedController.java │ │ ├── FeedPageController.java │ │ ├── IndexController.java │ │ ├── MyListController.java │ │ ├── QaController.java │ │ ├── RestControllerAdvice.java │ │ ├── SearchController.java │ │ ├── SpaceController.java │ │ ├── UserController.java │ │ └── WikiController.java │ │ ├── domain │ │ ├── Activity.java │ │ ├── FeedAction.java │ │ ├── FeedFile.java │ │ ├── FeedReply.java │ │ ├── FeedThread.java │ │ ├── Keyword.java │ │ ├── KeywordList.java │ │ ├── PersistentLogins.java │ │ ├── QaContent.java │ │ ├── QaFile.java │ │ ├── QaRecommend.java │ │ ├── QaReply.java │ │ ├── SendMailInfo.java │ │ ├── Space.java │ │ ├── SpaceAccessUser.java │ │ ├── User.java │ │ ├── UserFavorite.java │ │ ├── UserKeyword.java │ │ ├── UserPoint.java │ │ ├── Vote.java │ │ ├── Wiki.java │ │ ├── WikiFile.java │ │ ├── WikiLike.java │ │ ├── WikiReply.java │ │ └── WikiSnapShot.java │ │ ├── repository │ │ ├── ActivityRepository.java │ │ ├── FeedActionRepository.java │ │ ├── FeedFileRepository.java │ │ ├── FeedReplyRepository.java │ │ ├── FeedThreadRepository.java │ │ ├── KeywordListRepository.java │ │ ├── KeywordRepository.java │ │ ├── QaContentRepository.java │ │ ├── QaFileRepository.java │ │ ├── QaRecommendRepository.java │ │ ├── QaReplyRepository.java │ │ ├── SpaceAccessUserRepository.java │ │ ├── SpaceRepository.java │ │ ├── UserFavoriteRepository.java │ │ ├── UserKeywordRepository.java │ │ ├── UserPointRepository.java │ │ ├── UserRepository.java │ │ ├── VoteRepository.java │ │ ├── WikiFileRepository.java │ │ ├── WikiLikeRepository.java │ │ ├── WikiReplyRepository.java │ │ ├── WikiRepository.java │ │ └── WikiSnapShotRepository.java │ │ ├── service │ │ ├── common │ │ │ ├── ActivityService.java │ │ │ ├── ActivityServiceImpl.java │ │ │ ├── KeywordListService.java │ │ │ ├── KeywordListServiceImpl.java │ │ │ ├── KeywordService.java │ │ │ └── KeywordServiceImpl.java │ │ ├── feed │ │ │ ├── FeedActionService.java │ │ │ ├── FeedFileService.java │ │ │ ├── FeedReplyService.java │ │ │ ├── FeedThreadService.java │ │ │ └── actor │ │ │ │ ├── FeedActionActor.java │ │ │ │ ├── FeedReplyClaim.java │ │ │ │ ├── FeedReplyLike.java │ │ │ │ ├── FeedThreadClaim.java │ │ │ │ └── FeedThreadLike.java │ │ ├── index │ │ │ └── IndexCrawler.java │ │ ├── qa │ │ │ ├── QaFileService.java │ │ │ ├── QaFileServiceImpl.java │ │ │ ├── QaRecommendService.java │ │ │ ├── QaRecommendServiceImpl.java │ │ │ ├── QaReplyService.java │ │ │ ├── QaReplyServiceImpl.java │ │ │ ├── QaService.java │ │ │ ├── QaServiceImpl.java │ │ │ ├── VoteService.java │ │ │ └── VoteServiceImpl.java │ │ ├── search │ │ │ └── IntegrationSearcher.java │ │ ├── space │ │ │ ├── SpaceService.java │ │ │ └── SpaceServiceImpl.java │ │ ├── user │ │ │ ├── UserFavoriteService.java │ │ │ ├── UserFavoriteServiceImpl.java │ │ │ ├── UserKeywordService.java │ │ │ ├── UserKeywordServiceImpl.java │ │ │ ├── UserService.java │ │ │ └── UserServiceImpl.java │ │ └── wiki │ │ │ ├── WikiFileService.java │ │ │ ├── WikiFileServiceImpl.java │ │ │ ├── WikiReplyService.java │ │ │ ├── WikiReplyServiceImpl.java │ │ │ ├── WikiService.java │ │ │ └── WikiServiceImpl.java │ │ ├── validator │ │ └── QaValidator.java │ │ └── view │ │ ├── feed │ │ ├── DisplayDate.java │ │ ├── DisplayFeed.java │ │ ├── DisplayFeedAction.java │ │ ├── DisplayFeedActionBuilder.java │ │ ├── DisplayFeedBuilder.java │ │ ├── DisplayFeedFile.java │ │ ├── DisplayFeedReply.java │ │ └── DisplayFeedReplyBuilder.java │ │ ├── index │ │ ├── DisplayIndex.java │ │ ├── IndexFeed.java │ │ ├── IndexKeyword.java │ │ ├── IndexNotice.java │ │ ├── IndexQaContent.java │ │ ├── IndexSpace.java │ │ └── IndexWiki.java │ │ ├── qa │ │ ├── DisplayQa.java │ │ └── DisplayQaReply.java │ │ ├── search │ │ ├── DisplaySearchResult.java │ │ └── DisplaySearchResultBuilder.java │ │ ├── space │ │ ├── SpaceActivityList.java │ │ ├── SpaceMain.java │ │ ├── SpaceMainList.java │ │ ├── SpaceWiki.java │ │ ├── SpaceWikiList.java │ │ └── TreeModel.java │ │ ├── user │ │ └── UserList.java │ │ └── wiki │ │ ├── DisplayAjaxWiki.java │ │ ├── DisplayWiki.java │ │ └── DisplayWikiLike.java ├── resources │ ├── application.properties │ ├── banner.txt │ ├── import.sql │ ├── log4jdbc.log4j2.properties │ ├── logback.xml │ └── mail.properties └── webapp │ ├── WEB-INF │ └── views │ │ ├── common │ │ ├── _indicator.hbs │ │ ├── _keywordBadge.hbs │ │ └── _keywordList.hbs │ │ ├── error │ │ ├── 401.hbs │ │ ├── 403.hbs │ │ ├── 404.hbs │ │ └── 500.hbs │ │ ├── feed │ │ ├── main.hbs │ │ ├── template │ │ │ ├── list.hbs │ │ │ └── reply.hbs │ │ └── view.hbs │ │ ├── index.hbs │ │ ├── my │ │ ├── favorList.hbs │ │ ├── feedList.hbs │ │ ├── qaList.hbs │ │ └── wikiList.hbs │ │ ├── qa │ │ ├── edit.hbs │ │ ├── form.hbs │ │ ├── list.hbs │ │ ├── main.hbs │ │ ├── template │ │ │ ├── _fileList.hbs │ │ │ ├── _mainList.hbs │ │ │ ├── _myList.hbs │ │ │ ├── _noData.hbs │ │ │ ├── _qaBest.hbs │ │ │ ├── _recentList.hbs │ │ │ ├── _replyList.hbs │ │ │ ├── _searchList.hbs │ │ │ └── _waitReplyList.hbs │ │ └── view.hbs │ │ ├── search │ │ ├── form │ │ │ ├── qa.hbs │ │ │ ├── space.hbs │ │ │ └── wiki.hbs │ │ └── result.hbs │ │ ├── space │ │ ├── ajaxUpload.hbs │ │ ├── center.hbs │ │ ├── edit.hbs │ │ ├── form.hbs │ │ ├── left.hbs │ │ ├── main.hbs │ │ ├── right.hbs │ │ ├── spaces.hbs │ │ └── template │ │ │ ├── _activityList.hbs │ │ │ ├── _activityRight.hbs │ │ │ ├── _allSpaceList.hbs │ │ │ ├── _myfavoriteList.hbs │ │ │ ├── _recentWikiList.hbs │ │ │ ├── _spaceList.hbs │ │ │ ├── _spaceTopMenu.hbs │ │ │ ├── _updateWikiList.hbs │ │ │ └── _userList.hbs │ │ ├── template │ │ ├── base.hbs │ │ ├── guest.hbs │ │ ├── layout.hbs │ │ ├── login.hbs │ │ └── temp.hbs │ │ ├── user │ │ ├── auth.hbs │ │ ├── form.hbs │ │ ├── loginPage.hbs │ │ ├── profile.hbs │ │ └── view.hbs │ │ └── wiki │ │ ├── list.hbs │ │ ├── main.hbs │ │ ├── template │ │ ├── _allList.hbs │ │ ├── _bestList.hbs │ │ └── _recentList.hbs │ │ ├── view.hbs │ │ └── write.hbs │ └── resource │ ├── app │ ├── css │ │ └── common.css │ └── js │ │ ├── DualEditor │ │ ├── DualEditor-core.js │ │ ├── css │ │ │ └── DualEditor.css │ │ ├── img │ │ │ ├── 2_l.png │ │ │ ├── 2_m.png │ │ │ ├── 2_s.png │ │ │ ├── 3_l.png │ │ │ ├── 3_m.png │ │ │ ├── 3_s.png │ │ │ ├── 4_l.png │ │ │ ├── 4_m.png │ │ │ └── 4_s.png │ │ ├── module │ │ │ ├── mALERT.js │ │ │ ├── mALIGN.js │ │ │ ├── mBOLD.js │ │ │ ├── mDEL.js │ │ │ ├── mFIELD.js │ │ │ ├── mFONT.js │ │ │ ├── mH1.js │ │ │ ├── mHR.js │ │ │ ├── mINFO.js │ │ │ ├── mITALIC.js │ │ │ ├── mLAYOUT.js │ │ │ ├── mLINK.js │ │ │ ├── mORDERLIST.js │ │ │ ├── mSUBERSCRIPT.js │ │ │ ├── mSUPERSCRIPT.js │ │ │ ├── mSyntax.js │ │ │ ├── mTABLE.js │ │ │ └── mUNDERLINING.js │ │ ├── syntaxhiglight │ │ │ ├── highlight.pack.js │ │ │ └── styles │ │ │ │ ├── agate.css │ │ │ │ ├── androidstudio.css │ │ │ │ ├── arduino-light.css │ │ │ │ ├── arta.css │ │ │ │ ├── ascetic.css │ │ │ │ ├── atelier-cave-dark.css │ │ │ │ ├── atelier-cave-light.css │ │ │ │ ├── atelier-dune-dark.css │ │ │ │ ├── atelier-dune-light.css │ │ │ │ ├── atelier-estuary-dark.css │ │ │ │ ├── atelier-estuary-light.css │ │ │ │ ├── atelier-forest-dark.css │ │ │ │ ├── atelier-forest-light.css │ │ │ │ ├── atelier-heath-dark.css │ │ │ │ ├── atelier-heath-light.css │ │ │ │ ├── atelier-lakeside-dark.css │ │ │ │ ├── atelier-lakeside-light.css │ │ │ │ ├── atelier-plateau-dark.css │ │ │ │ ├── atelier-plateau-light.css │ │ │ │ ├── atelier-savanna-dark.css │ │ │ │ ├── atelier-savanna-light.css │ │ │ │ ├── atelier-seaside-dark.css │ │ │ │ ├── atelier-seaside-light.css │ │ │ │ ├── atelier-sulphurpool-dark.css │ │ │ │ ├── atelier-sulphurpool-light.css │ │ │ │ ├── atom-one-dark.css │ │ │ │ ├── atom-one-light.css │ │ │ │ ├── brown-paper.css │ │ │ │ ├── brown-papersq.png │ │ │ │ ├── codepen-embed.css │ │ │ │ ├── color-brewer.css │ │ │ │ ├── darcula.css │ │ │ │ ├── dark.css │ │ │ │ ├── darkula.css │ │ │ │ ├── default.css │ │ │ │ ├── docco.css │ │ │ │ ├── dracula.css │ │ │ │ ├── far.css │ │ │ │ ├── foundation.css │ │ │ │ ├── github-gist.css │ │ │ │ ├── github.css │ │ │ │ ├── googlecode.css │ │ │ │ ├── grayscale.css │ │ │ │ ├── gruvbox-dark.css │ │ │ │ ├── gruvbox-light.css │ │ │ │ ├── hopscotch.css │ │ │ │ ├── hybrid.css │ │ │ │ ├── idea.css │ │ │ │ ├── ir-black.css │ │ │ │ ├── kimbie.dark.css │ │ │ │ ├── kimbie.light.css │ │ │ │ ├── magula.css │ │ │ │ ├── mono-blue.css │ │ │ │ ├── monokai-sublime.css │ │ │ │ ├── monokai.css │ │ │ │ ├── obsidian.css │ │ │ │ ├── ocean.css │ │ │ │ ├── paraiso-dark.css │ │ │ │ ├── paraiso-light.css │ │ │ │ ├── pojoaque.css │ │ │ │ ├── pojoaque.jpg │ │ │ │ ├── purebasic.css │ │ │ │ ├── qtcreator_dark.css │ │ │ │ ├── qtcreator_light.css │ │ │ │ ├── railscasts.css │ │ │ │ ├── rainbow.css │ │ │ │ ├── school-book.css │ │ │ │ ├── school-book.png │ │ │ │ ├── solarized-dark.css │ │ │ │ ├── solarized-light.css │ │ │ │ ├── sunburst.css │ │ │ │ ├── tomorrow-night-blue.css │ │ │ │ ├── tomorrow-night-bright.css │ │ │ │ ├── tomorrow-night-eighties.css │ │ │ │ ├── tomorrow-night.css │ │ │ │ ├── tomorrow.css │ │ │ │ ├── vs.css │ │ │ │ ├── xcode.css │ │ │ │ ├── xt256.css │ │ │ │ └── zenburn.css │ │ └── util │ │ │ ├── fn-block-range.js │ │ │ ├── fn-editor-layer.js │ │ │ ├── fn-editor-util.js │ │ │ └── fn-editor.js │ │ ├── feed │ │ └── app.js │ │ ├── google │ │ └── analytics.js │ │ ├── helpers │ │ └── helper.js │ │ ├── keywordList │ │ └── keywordList.js │ │ ├── space │ │ └── tree.js │ │ └── summernote │ │ ├── font │ │ ├── summernote.eot │ │ ├── summernote.ttf │ │ └── summernote.woff │ │ ├── summernote-ext-highlight.js │ │ ├── summernote.css │ │ ├── summernote.js │ │ ├── summernote.min.js │ │ └── summernote_sub.js │ ├── images │ ├── avatar.png │ ├── howling_space.png │ ├── jqtree-circle.png │ ├── loading-spinner.svg │ └── symbol-dashboard.png │ └── public │ ├── bootstrap-3.3.6-dist │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── bootstrap-theme │ └── bootswatch │ │ ├── cerulean │ │ └── bootstrap.min.css │ │ └── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── css │ ├── bootstrap-tag-cloud │ │ └── bootstrap-tag-cloud.css │ ├── bootstrap-treeview.css │ ├── errors.css │ ├── jquery-confirm.min.css │ ├── layout-default-latest.css │ ├── login.css │ ├── main.css │ └── mobile.css │ ├── ekko-lightbox │ ├── dark-theme.css │ ├── ekko-lightbox.css │ ├── ekko-lightbox.js │ ├── ekko-lightbox.min.css │ └── ekko-lightbox.min.js │ ├── font-awesome │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── less │ │ ├── animated.less │ │ ├── bordered-pulled.less │ │ ├── core.less │ │ ├── fixed-width.less │ │ ├── font-awesome.less │ │ ├── icons.less │ │ ├── larger.less │ │ ├── list.less │ │ ├── mixins.less │ │ ├── path.less │ │ ├── rotated-flipped.less │ │ ├── spinning.less │ │ ├── stacked.less │ │ └── variables.less │ └── scss │ │ ├── _animated.scss │ │ ├── _bordered-pulled.scss │ │ ├── _core.scss │ │ ├── _fixed-width.scss │ │ ├── _icons.scss │ │ ├── _larger.scss │ │ ├── _list.scss │ │ ├── _mixins.scss │ │ ├── _path.scss │ │ ├── _rotated-flipped.scss │ │ ├── _spinning.scss │ │ ├── _stacked.scss │ │ ├── _variables.scss │ │ └── font-awesome.scss │ ├── images │ ├── apple-touch-icon-retina.png │ ├── apple-touch-icon.png │ ├── avatar.png │ ├── favicon.ico │ ├── grails_logo.png │ ├── icons │ │ ├── cameras.png │ │ ├── photos.png │ │ └── pictures.png │ ├── skin │ │ ├── database_add.png │ │ ├── database_delete.png │ │ ├── database_edit.png │ │ ├── database_save.png │ │ ├── database_table.png │ │ ├── exclamation.png │ │ ├── house.png │ │ ├── information.png │ │ ├── shadow.jpg │ │ ├── sorted_asc.gif │ │ └── sorted_desc.gif │ ├── spinner.gif │ ├── springsource.png │ └── tree │ │ ├── ajax-loader.gif │ │ ├── file.gif │ │ ├── folder-closed.gif │ │ ├── folder.gif │ │ ├── minus.gif │ │ ├── plus.gif │ │ ├── treeview-black-line.gif │ │ ├── treeview-black.gif │ │ ├── treeview-default-line.gif │ │ ├── treeview-default.gif │ │ ├── treeview-famfamfam-line.gif │ │ ├── treeview-famfamfam.gif │ │ ├── treeview-gray-line.gif │ │ ├── treeview-gray.gif │ │ ├── treeview-red-line.gif │ │ └── treeview-red.gif │ └── js │ ├── bootstrap-tag-cloud │ └── bootstrap-tag-cloud.js │ ├── bootstrap-treeview.js │ ├── handlebars.min.js │ ├── html2canvas.js │ ├── html2canvas.svg.js │ └── jquery │ ├── jquery-1.11.2.min.js │ ├── jquery-confirm.min.js │ ├── jquery-ui-latest.js │ ├── jquery.cookie.js │ ├── jquery.layout-latest.js │ └── plugin │ └── jquery-panelslider │ └── jquery.panelslider.min.js └── test ├── java └── com │ └── libqa │ ├── application │ └── util │ │ ├── FileHandlerTest.java │ │ ├── FileHandlerTestConfig.java │ │ └── HtmlContentHandlerTest.java │ ├── testsupport │ ├── LibqaRepositoryTest.java │ └── RepositoryTestConfiguration.java │ └── web │ ├── controller │ ├── FeedControllerTest.java │ └── FeedPageControllerTest.java │ ├── repository │ ├── FeedActionRepositoryTest.java │ ├── FeedFileRepositoryTest.java │ ├── FeedReplyRepositoryTest.java │ ├── FeedThreadRepositoryTest.java │ ├── QaContentRepositoryTest.java │ ├── SpaceRepositoryTest.java │ └── WikiRepositoryTest.java │ ├── service │ ├── FeedActionServiceTest.java │ ├── FeedFileServiceTest.java │ ├── feed │ │ └── FeedThreadServiceTest.java │ ├── index │ │ └── IndexCrawlerTest.java │ └── search │ │ └── SearchTargetPageTest.java │ └── view │ └── DisplayDateTest.java └── resources └── application-spring-test.properties /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .#* 3 | *# 4 | *~ 5 | /build 6 | /code 7 | .classpath 8 | .project 9 | .settings 10 | .metadata 11 | bin 12 | build 13 | lib/ 14 | target 15 | .springBeans 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea 20 | *.jar 21 | .DS_Store 22 | *.MF 23 | bin/ 24 | tmp/ 25 | gradle/ 26 | out/ 27 | 28 | #libqa 29 | webapp/resource/temp/ 30 | src/main/webapp/resource/profile/ 31 | src/main/webapp/resource/temp/ 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 howling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libqa™ Project 2 | Keyword based Social Q&A Community (http://www.libqa.com) 3 | 4 | ### Social Q&A & Knowledge sharing platform based GLiDER Wiki. created by GLiDER Wiki Team(http://www.gliderwiki.org) 5 | 6 | Howling™ - Social Q&A & Wiki for Community Version 7 | Howling™ is free software, available under the terms of a MIT license.(http://opensource.org/licenses/mit-license.php) 8 | 9 | DB Configuration (for mysql) 10 | ======= 11 | ``` 12 | cd /usr/local/mysql/bin 13 | ./mysql -u root -p 14 | 15 | GRANT ALL PRIVILEGES on howling.* to 'howlingproject'@'localhost' identified by 'libqa2014'; 16 | GRANT ALL PRIVILEGES on howling.* to 'howlingproject'@'%' identified by 'libqa2014'; 17 | flush privileges; 18 | 19 | CREATE SCHEMA `howling` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; 20 | ``` 21 | 22 | ### developer 23 | 24 | 25 | QuicK (performizer@gmail.com) 26 | 27 | Jun (devseonz@gmail.com) 28 | 29 | Songanji (songanji@gmail.com) 30 | 31 | Yonghee (seeds.pear.jr@gmail.com) 32 | 33 | 34 | Contact to site - http://www.libqa.com 35 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Mar 01 01:08:00 KST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip 7 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/dto/FileDto.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.dto; 2 | 3 | import com.libqa.application.enums.FileType; 4 | import lombok.Data; 5 | 6 | /** 7 | * File Upload 속성 정의 8 | * Created by yion on 2015. 3. 1.. 9 | */ 10 | @Data 11 | public class FileDto { 12 | 13 | private String realName; // 실제 파일명 14 | 15 | private String savedName; // 저장 파일 명 16 | 17 | private String rootPath; // 경로 18 | 19 | private String filePath; // 파일 경로 20 | 21 | private double fileSize; // 파일 사이즈 22 | 23 | private String fileExtendType; // 확장자 타입 24 | 25 | private String uploadType; // 업로드 타입 26 | 27 | private FileType fileType; // 파일 타입 28 | 29 | private String thumbYn; // 섬네일 유무 30 | 31 | private String thumbPath; // 섬네일 패스 32 | 33 | private String thumbName; // 섬네일 파일 명 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/dto/QaDto.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.dto; 2 | 3 | import com.libqa.application.enums.DayType; 4 | import com.libqa.application.enums.QaSearchType; 5 | import com.libqa.application.enums.WaitReplyType; 6 | import lombok.Data; 7 | 8 | /** 9 | * Created by yong on 2015-05-15. 10 | * 11 | * @author yong 12 | */ 13 | @Data 14 | public class QaDto { 15 | private String keywordName; 16 | 17 | private String keywordType; 18 | 19 | private DayType dayType; 20 | 21 | private WaitReplyType waitReplyType; 22 | 23 | private QaSearchType qaSearchType; 24 | 25 | private Integer lastQaId; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/dto/SecurityUserDto.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @Author : yion 7 | * @Date : 2015. 4. 19. 8 | * @Description : 9 | */ 10 | @Data 11 | public class SecurityUserDto { 12 | private String userEmail; 13 | private String role; 14 | private String userIp; 15 | private boolean isAuthenticated; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/ActionType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | public enum ActionType { 4 | LIKE, CLAIM 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/ActivityType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @Author : yion 7 | * @Date : 2015. 6. 21. 8 | * @Description : 9 | */ 10 | public enum ActivityType { 11 | // 공간 12 | CREATE_SPACE("공간을 생성 하였습니다."), 13 | UPDATE_SPACE("공간을 수정 하였습니다."), 14 | ADD_SPACE_FAVORITE("공간을 즐겨찾기에 추가 하였습니다."), 15 | 16 | // 위키 17 | INSERT_WIKI("위키를 생성 하였습니다."), 18 | UPDATE_WIKI("위키를 수정 하였습니다."), 19 | INSERT_REPLY_WIKI("위키에 댓글을 생성 하였습니다."), 20 | ADD_WIKI_FAVORITE("위키를 즐겨찾기에 추가 하였습니다."), 21 | 22 | // QA 23 | INSERT_REPLY_QA("QA 에 댓글 생성 하였습니다."), 24 | ADD_VOTE_YES("추천에 투표 하였습니다."), 25 | ADD_VOTE_NO("비추천에 투표 하였습니다."), 26 | ADD_REPLY_RECOMMEND("댓글을 추천 하였습니다.") 27 | ; 28 | 29 | 30 | @Getter 31 | private String code; 32 | 33 | ActivityType(String code) { 34 | this.code = code; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/DayType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * Created by yong on 2015-04-25. 7 | * 8 | * @author yong 9 | */ 10 | public enum DayType { 11 | TODAY("TODAY"), // 오늘 12 | WEEK("WEEK"), // 일주일 13 | ALL("ALL"); // 전체 14 | 15 | @Getter 16 | private String code; 17 | 18 | private DayType(final String code) { 19 | this.code = code; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/FavoriteType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | /** 4 | * Created by yion on 2015. 2. 1.. 5 | */ 6 | public enum FavoriteType { 7 | SPACE, 8 | WIKI, 9 | QA 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/FileType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | public enum FileType { 4 | FILE, IMAGE 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/KeywordType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * Created by yong on 15. 2. 1.. 7 | */ 8 | public enum KeywordType { 9 | FEED("FEED"), // 피드 10 | WIKI("WIKI"), // 위키 11 | SPACE("SPACE"), // 공간 12 | QA("QA"); // QA 13 | 14 | @Getter 15 | private String code; 16 | 17 | private KeywordType(final String code) { 18 | this.code = code; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/ListType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * Created by songanji on 2015. 6. 28.. 7 | */ 8 | public enum ListType { 9 | BEST("best"), 10 | ALL("all"), 11 | RESENT("resent"), 12 | KEYWORD("keyword") 13 | ; 14 | 15 | @Getter 16 | private String name; 17 | 18 | private ListType(final String name) { 19 | this.name = name; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/PostType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | public enum PostType { 4 | THREAD, 5 | REPLY 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/ProcessType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | /** 4 | * @Author : yion 5 | * @Date : 2015. 4. 26. 6 | * @Description : 자동처리, 수동처리 7 | */ 8 | public enum ProcessType { 9 | AUTO, MANUAL 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/QaSearchType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * Created by yong on 2016. 8. 18.. 7 | */ 8 | public enum QaSearchType { 9 | TOTAL("TOTAL"), 10 | WAIT_REPLY("WAIT_REPLY"); 11 | 12 | @Getter 13 | private String name; 14 | 15 | private QaSearchType(final String name){ 16 | this.name = name; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/Role.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | /** 4 | * @Author : yion 5 | * @Date : 2015. 3. 29. 6 | * @Description : 7 | */ 8 | public enum Role { 9 | GUEST, USER, ADMIN 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/SearchTargetPage.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | public enum SearchTargetPage { 4 | QA("qa", "Q&A"), 5 | SPACE("space", "Space"), 6 | WIKI("wiki", "Wiki"), 7 | INVALID("invalid", "Invalid"); 8 | 9 | final String page; 10 | final String desc; 11 | 12 | SearchTargetPage(String page, String desc) { 13 | this.page = page; 14 | this.desc = desc; 15 | } 16 | 17 | public static SearchTargetPage get(String page) { 18 | for (SearchTargetPage each : SearchTargetPage.values()) { 19 | if(page.equals(each.getPage())) { 20 | return each; 21 | } 22 | } 23 | return INVALID; 24 | } 25 | 26 | public boolean isInValidPage() { 27 | return get(page) == INVALID; 28 | } 29 | 30 | public String getPage() { 31 | return page; 32 | } 33 | 34 | public String getDesc() { 35 | return desc; 36 | } 37 | 38 | public boolean isQA() { 39 | return this == QA; 40 | } 41 | 42 | public boolean isSpace() { 43 | return this == SPACE; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/SocialChannelType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * 가입 시점의 소셜 연동 타입 7 | * @Author : yion 8 | * @Date : 2015. 4. 12. 9 | * @Description : 10 | */ 11 | public enum SocialChannelType { 12 | WEB("Web"), 13 | Mobile("Mobile"), 14 | FACEBOOK("Facebook"), 15 | TWITTER("Twitter") 16 | ; 17 | 18 | 19 | @Getter 20 | private String name; 21 | 22 | private SocialChannelType(final String name) { 23 | this.name = name; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/SpaceView.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | /** 4 | * Created by yion on 2015. 2. 1.. 5 | */ 6 | public enum SpaceView { 7 | RIGHT, 8 | LEFT, 9 | CENTER 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/StatusCode.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * Created by yion on 2015. 2. 20.. 7 | */ 8 | public enum StatusCode { 9 | FAIL(-1, "예상치 못한 에러가 발생했습니다."), 10 | NONE(0, "NA"), 11 | SUCCESS(1, "SUCCESS"), 12 | NEED_LOGIN(10, "로그인이 필요합니다"), 13 | NOT_MATCH_USER(11, "사용자가 일치하지 않습니다."), 14 | EXIST_REPLY(21, "해당 게시물에 답변이 존재합니다."), 15 | EXIST_RECOMMEND(22, "해당 게시물에 추천 또는 비추천이 존재합니다."), 16 | EXIST_CHOICE(23, "해당 게시물에 선정된 답변이 존재합니다"), 17 | DUPLICATE(99, "중복된 데이터"), 18 | SIZE_LIMIT_EXCEEDED(100, "허용 용량 초과"), 19 | INVALID_FILE(101, "올바른 파일 형식이 아닙니다."), 20 | INVALID_STATUS(102, "잘못된 상태"), 21 | INVALID_PARAMETER(900, "잘못된 파라미터"), 22 | INTERNAL(990, "내부 오류"), 23 | SYSTEM_ERROR(999, "시스템 오류"); 24 | 25 | @Getter 26 | private final int code; 27 | 28 | @Getter 29 | private final String comment; 30 | 31 | StatusCode(final int code, final String comment) { 32 | this.code = code; 33 | this.comment = comment; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/UserPoint.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | /** 4 | * Created by yion on 2015. 2. 1.. 5 | */ 6 | public enum UserPoint { 7 | WRITE_WIKI("위키 글쓰기"), 8 | QA_REPLY("QA 답변"), 9 | QA_RECOMMEND("QA 추천"), 10 | SHARE_COUNT("공유 갯수"), 11 | LOGIN_COUNT("로그인 횟수"), 12 | WRITE_FEED("FEED 쓰기"), 13 | FEED_REPLY("FEED 답변"), 14 | FEED_LIKE("FEED 좋아요"), 15 | ADD_FAVORITE("즐겨찾기 추가"); 16 | 17 | 18 | 19 | private String type; 20 | 21 | private UserPoint(String type) { 22 | this.type = type; 23 | } 24 | 25 | public String toString() { 26 | return this.type; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/WaitReplyType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * Created by yong on 2016-10-12. 7 | * 8 | * @author yong 9 | */ 10 | public enum WaitReplyType { 11 | WAIT("WAIT"), // 답변을 기다리는 12 | REPLIED("REPLIED"); // 답변 존재 13 | 14 | @Getter 15 | private String code; 16 | 17 | private WaitReplyType(final String code){ this.code = code; } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/WikiLikesType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | /** 4 | * Created by songanji on 2015. 10. 4.. 5 | */ 6 | public enum WikiLikesType { 7 | WIKI, COMMENT 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/WikiRevisionActionType.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums; 2 | 3 | /** 4 | * Created by songanji on 2015. 2. 8.. 5 | */ 6 | public enum WikiRevisionActionType { 7 | UPDATE_WIKI("위키 글쓰기"), 8 | UPDATE_TITLE("QA 답변"), 9 | UPDATE_FILE("첨부파일"), 10 | UPDATE_DELETE("내용삭제"); 11 | 12 | private String type; 13 | 14 | private WikiRevisionActionType(String type) { 15 | this.type = type; 16 | } 17 | 18 | public String toString() { 19 | return this.type; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/enums/converter/QaSearchTypeEnumConverter.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.enums.converter; 2 | 3 | import com.libqa.application.enums.QaSearchType; 4 | 5 | import java.beans.PropertyEditorSupport; 6 | 7 | /** 8 | * Created by yong on 2016. 8. 19.. 9 | */ 10 | public class QaSearchTypeEnumConverter extends PropertyEditorSupport { 11 | @Override 12 | public void setAsText(String text) throws IllegalArgumentException { 13 | 14 | String capitalized = text.toUpperCase(); 15 | QaSearchType qaSearchType = QaSearchType.valueOf(capitalized); 16 | setValue(qaSearchType); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/exception/FilePermitMsgException.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.exception; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | /** 7 | * Created by yion on 2015. 3. 1.. 8 | */ 9 | 10 | @EqualsAndHashCode(callSuper = false) 11 | @Data 12 | public class FilePermitMsgException extends RuntimeException { 13 | private static final long serialVersionUID = 1L; 14 | private String customMsg; 15 | 16 | public FilePermitMsgException(String customMsg) { 17 | this.customMsg = customMsg; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/exception/UserNotCreateException.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.exception; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | /** 6 | * @Author : yion 7 | * @Date : 2015. 4. 12. 8 | * @Description : 9 | */ 10 | @Slf4j 11 | public class UserNotCreateException extends Throwable { 12 | public UserNotCreateException(String msg, Exception e) { 13 | log.error("### UserNotCreateException Message = {}", msg); 14 | log.error("### Error Message = {}", e); 15 | } 16 | 17 | public UserNotCreateException(String msg) { 18 | super(msg); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/handler/ErrorAccessHandler.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.handler; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.security.access.AccessDeniedException; 6 | import org.springframework.security.web.access.AccessDeniedHandler; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | 13 | /** 14 | * @Author : yion 15 | * @Date : 2015. 4. 19. 16 | * @Description : 17 | */ 18 | public class ErrorAccessHandler implements AccessDeniedHandler { 19 | 20 | @Setter 21 | @Getter 22 | private String errorPage; 23 | 24 | public ErrorAccessHandler() { 25 | 26 | } 27 | 28 | @Override 29 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { 30 | System.out.println("### Access Denied Handler !!"); 31 | response.sendRedirect(errorPage); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/util/HtmlContentHandler.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.util; 2 | 3 | import com.twitter.Autolink; 4 | 5 | public class HtmlContentHandler { 6 | private String text; 7 | 8 | public HtmlContentHandler(String text) { 9 | this.text = text; 10 | } 11 | 12 | public HtmlContentHandler urlWithLink() { 13 | Autolink autoLink = new Autolink(); 14 | autoLink.setUrlTarget("_blank"); 15 | text = autoLink.autoLink(text); 16 | return this; 17 | } 18 | 19 | public HtmlContentHandler nl2br() { 20 | text = text.replaceAll("(\\r\\n|\\n)", "
"); 21 | return this; 22 | } 23 | 24 | public String parse() { 25 | return text; 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/util/LibqaConstant.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.util; 2 | 3 | /** 4 | * @Author : yion 5 | * @Date : 2016. 4. 17. 6 | * @Description : 상수 정의 - 업무명_상수명_타입 : WIKI_PAGE_SIZE 7 | */ 8 | public class LibqaConstant { 9 | 10 | public static final String DEFAULT_RETURN_URL = "/index"; 11 | 12 | public static final Integer PAGE_START_INDEX = 0; 13 | public static final Integer SPACE_PAGE_SIZE = 10; 14 | public static final Integer SPACE_WIKI_SIZE = 10; 15 | 16 | public static final String SORT_TYPE_TITLE = "title"; 17 | public static final String SORT_TYPE_DATE = "updateDate"; 18 | 19 | public static final Integer ZERO = 0; 20 | 21 | public class ErrorPagePath { 22 | public static final String DEFAULT_ERROR = "/error"; 23 | public static final String ERROR_401 = DEFAULT_ERROR + "/401"; 24 | public static final String ERROR_403 = DEFAULT_ERROR + "/403"; 25 | public static final String ERROR_404 = DEFAULT_ERROR + "/404"; 26 | public static final String ERROR_500 = DEFAULT_ERROR + "/500"; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/util/LoggedUserManager.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.util; 2 | 3 | import com.libqa.web.domain.User; 4 | import com.libqa.web.service.user.UserService; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.core.Authentication; 9 | import org.springframework.security.core.context.SecurityContextHolder; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Slf4j 13 | @Component 14 | public class LoggedUserManager { 15 | 16 | @Autowired 17 | private UserService userService; 18 | 19 | /** 20 | * 로그인 사용자 정보를 조회한다. 21 | * 22 | * @return logged user 23 | */ 24 | public User getUser() { 25 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 26 | String userEmail = authentication.getName(); 27 | 28 | log.debug("### userEmail:{}, isGuestUser:{}", userEmail, isGuestUser(userEmail)); 29 | 30 | if (isGuestUser(userEmail)) { 31 | return User.createGuest(); 32 | } 33 | 34 | return userService.findByEmail(userEmail); 35 | } 36 | 37 | private boolean isGuestUser(String userEmail) { 38 | return StringUtils.isBlank(userEmail) || "anonymousUser".equals(userEmail); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/application/util/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.libqa.application.util; 2 | 3 | 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | /** 7 | * Created by yion on 2015. 3. 1.. 8 | */ 9 | public class StringUtil extends StringUtils { 10 | 11 | public static String nullToString(String str) { 12 | return nullToString(str, ""); 13 | } 14 | 15 | public static String nullToString(String str, String defaultStr) { 16 | if (str == null) { 17 | return defaultStr; 18 | } 19 | return str; 20 | } 21 | 22 | public static String abbreviateString(String str) { 23 | return StringUtils.defaultIfEmpty(str, "..."); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/config/WebAppInitializer.java: -------------------------------------------------------------------------------- 1 | package com.libqa.config; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.web.WebApplicationInitializer; 5 | import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 6 | import org.springframework.web.servlet.DispatcherServlet; 7 | 8 | import javax.servlet.ServletContext; 9 | import javax.servlet.ServletException; 10 | import javax.servlet.ServletRegistration.Dynamic; 11 | 12 | /** 13 | * @Author : yion 14 | * @Date : 2015. 9. 6. 15 | * @Description : 16 | */ 17 | @Slf4j 18 | public class WebAppInitializer implements WebApplicationInitializer { 19 | 20 | @Override 21 | public void onStartup(ServletContext servletContext) throws ServletException { 22 | AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); 23 | ctx.register(WebMvcConfiguration.class); 24 | ctx.setServletContext(servletContext); 25 | Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx)); 26 | dynamic.addMapping("/"); 27 | dynamic.setLoadOnStartup(1); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/config/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libqa.config.security; 2 | 3 | import com.libqa.web.domain.User; 4 | import com.libqa.web.service.user.UserService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | import org.springframework.security.core.userdetails.UserDetailsService; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.stereotype.Service; 10 | 11 | /** 12 | * Created by Yong on 2016-05-17. 13 | * 14 | * @author Yong 15 | */ 16 | @Service 17 | public class UserDetailsServiceImpl implements UserDetailsService { 18 | 19 | @Autowired 20 | private UserService userService; 21 | 22 | @Override 23 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 24 | User user = userService.findByEmailAndIsCertification(username); 25 | 26 | if(user == null) { 27 | throw new UsernameNotFoundException("Not Exist User"); 28 | } 29 | return new UserDetailsImpl(user); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/controller/ErrorPageController.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.controller; 2 | 3 | import org.springframework.boot.autoconfigure.web.ErrorController; 4 | import org.springframework.stereotype.Controller; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | import static com.libqa.application.util.LibqaConstant.ErrorPagePath.*; 8 | import static org.springframework.web.bind.annotation.RequestMethod.GET; 9 | 10 | @Controller 11 | public class ErrorPageController implements ErrorController { 12 | 13 | @RequestMapping(value = DEFAULT_ERROR, method = GET) 14 | public String defaultError() { 15 | return error500(); 16 | } 17 | 18 | @RequestMapping(value = ERROR_401, method = GET) 19 | public String error401() { 20 | return "error/401"; 21 | } 22 | 23 | @RequestMapping(value = ERROR_403, method = GET) 24 | public String error403() { 25 | return "error/403"; 26 | } 27 | 28 | @RequestMapping(value = ERROR_404, method = GET) 29 | public String error404() { 30 | return "error/404"; 31 | } 32 | 33 | @RequestMapping(value = ERROR_500, method = GET) 34 | public String error500() { 35 | return "error/500"; 36 | } 37 | 38 | @Override 39 | public String getErrorPath() { 40 | return DEFAULT_ERROR; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.controller; 2 | 3 | import com.libqa.web.service.index.IndexCrawler; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.servlet.ModelAndView; 9 | 10 | @Slf4j 11 | @Controller 12 | public class IndexController { 13 | @Autowired 14 | private IndexCrawler indexCrawler; 15 | 16 | @RequestMapping({"", "/index"}) 17 | public ModelAndView index(ModelAndView mav) { 18 | mav.addObject("displayIndex", indexCrawler.crawl()); 19 | mav.setViewName("index"); 20 | return mav; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/controller/RestControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.controller; 2 | 3 | import com.libqa.application.framework.ResponseData; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.security.access.AccessDeniedException; 6 | import org.springframework.web.bind.annotation.ControllerAdvice; 7 | import org.springframework.web.bind.annotation.ExceptionHandler; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import java.util.Optional; 12 | 13 | import static com.libqa.application.framework.ResponseData.createFailResult; 14 | 15 | @Slf4j 16 | @ControllerAdvice(annotations = RestController.class) 17 | public class RestControllerAdvice { 18 | 19 | @ResponseBody 20 | @ExceptionHandler(RuntimeException.class) 21 | public ResponseData handleException(RuntimeException ex) { 22 | log.error("An error has occurred.", ex); 23 | return createFailResult(); 24 | } 25 | 26 | @ExceptionHandler(AccessDeniedException.class) 27 | public void handleAccessDeniedException(AccessDeniedException ex) { 28 | Optional optional = Optional.ofNullable(ex); 29 | if (optional.isPresent()) { 30 | throw optional.get(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/domain/KeywordList.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.domain; 2 | 3 | import com.libqa.application.enums.KeywordType; 4 | import lombok.Data; 5 | 6 | import javax.persistence.*; 7 | 8 | /** 9 | * Created by yong on 15. 2. 1.. 10 | */ 11 | @Entity 12 | @Data 13 | @Table(indexes = { 14 | @Index(name="IDX_KEYWORDLIST_KEYWORD_TYPE",columnList = "keywordType"), 15 | @Index(name="IDX_KEYWORDLIST_KEYWORD_NAME",columnList = "keywordName") 16 | }) 17 | public class KeywordList { 18 | public KeywordList(){ 19 | 20 | } 21 | 22 | @Id 23 | @Column(nullable = false) 24 | @GeneratedValue(strategy = GenerationType.AUTO) 25 | private Integer keywordListId; 26 | 27 | @Column(nullable = false, length = 40) 28 | private String keywordName; 29 | 30 | @Column(nullable = false, columnDefinition = "int default 0") 31 | private Integer keywordCount; 32 | 33 | @Enumerated(EnumType.STRING) 34 | @Column(length = 20) 35 | private KeywordType keywordType; 36 | 37 | @Column(nullable = false, columnDefinition="TINYINT(1) DEFAULT 0") 38 | private boolean isDeleted; 39 | 40 | public KeywordList(String keywordName, KeywordType keywordType, Integer keywordCount) { 41 | this.keywordName = keywordName; 42 | this.keywordType = keywordType; 43 | this.keywordCount = keywordCount; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/domain/PersistentLogins.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.domain; 2 | 3 | /** 4 | * @Author : yion 5 | * @Date : 2015. 10. 11. 6 | * @Description : 7 | */ 8 | 9 | import lombok.Data; 10 | import lombok.EqualsAndHashCode; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken; 13 | 14 | import javax.persistence.*; 15 | import java.util.Date; 16 | 17 | @Data 18 | @Entity 19 | @Table(name = "persistent_logins") 20 | @Slf4j 21 | @EqualsAndHashCode 22 | public class PersistentLogins { 23 | 24 | @Id 25 | @Column(length = 64, nullable = false) 26 | private String series; 27 | 28 | @Column(length = 64, nullable = false) 29 | private String username; 30 | 31 | @Column(length = 64, nullable = false) 32 | private String token; 33 | 34 | @Temporal(TemporalType.TIMESTAMP) 35 | @Column(nullable = false) 36 | private Date lastUsed; 37 | 38 | public PersistentLogins(PersistentRememberMeToken persistentRememberMeToken) { 39 | log.debug("########## PersistentLogin : {}", persistentRememberMeToken.toString()); 40 | this.username = persistentRememberMeToken.getUsername(); 41 | this.series = persistentRememberMeToken.getSeries(); 42 | this.lastUsed = persistentRememberMeToken.getDate(); 43 | this.token = persistentRememberMeToken.getTokenValue(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/domain/QaRecommend.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.domain; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | import java.util.Date; 7 | 8 | /** 9 | * Created by yong on 15. 2. 1.. 10 | */ 11 | @Entity 12 | @Data 13 | public class QaRecommend { 14 | 15 | @Id 16 | @Column(nullable = false) 17 | @GeneratedValue(strategy = GenerationType.AUTO) 18 | private Integer qaRecommendId; 19 | 20 | @Column(nullable = false) 21 | private Integer qaId; 22 | 23 | @Column(nullable = false) 24 | private Integer userId; 25 | 26 | @Column(nullable = false, length = 40) 27 | private String userNick; 28 | 29 | @Column(nullable = false, columnDefinition = "TINYINT(1) DEFAULT 0") 30 | private Boolean isCommend; 31 | 32 | @Column(nullable = false, columnDefinition = "TINYINT(1) DEFAULT 0") 33 | private boolean isCanceled; 34 | 35 | @Temporal(TemporalType.TIMESTAMP) 36 | @Column(nullable = false) 37 | private Date insertDate; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/domain/SpaceAccessUser.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.domain; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | import javax.persistence.*; 7 | import java.util.Date; 8 | 9 | /** 10 | * Created by yion on 2015. 2. 1.. 11 | */ 12 | 13 | @Data 14 | @Entity 15 | @Table(name = "space_access_user") 16 | @EqualsAndHashCode 17 | public class SpaceAccessUser { 18 | 19 | @Id 20 | @Column(nullable = false) 21 | @GeneratedValue(strategy = GenerationType.AUTO) 22 | private Integer spaceAccessUserId; 23 | 24 | @ManyToOne 25 | @JoinColumn(name="spaceId", referencedColumnName="spaceId", nullable=false) 26 | private Space space; 27 | 28 | @Column(nullable = false) 29 | private Integer userId; 30 | 31 | @Column(columnDefinition="TINYINT(1) DEFAULT 0") 32 | private boolean isDeleted; 33 | 34 | @Temporal(TemporalType.DATE) 35 | @Column(nullable = false) 36 | private Date insertDate; 37 | 38 | @Temporal(TemporalType.DATE) 39 | private Date updateDate; 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/domain/UserKeyword.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonBackReference; 4 | import lombok.Data; 5 | 6 | import javax.persistence.*; 7 | import java.util.Date; 8 | 9 | /** 10 | * Created by yion on 2015. 2. 1.. 11 | */ 12 | 13 | @Data 14 | @Entity 15 | public class UserKeyword { 16 | @Id 17 | @Column(nullable = false) 18 | @GeneratedValue(strategy = GenerationType.AUTO) 19 | private Integer userKeywordId; 20 | 21 | @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 22 | @JoinColumn(name = "userId", referencedColumnName = "userId", nullable = false) 23 | @JsonBackReference 24 | private User user; 25 | 26 | @Column(length = 20) 27 | private String keywordName; 28 | 29 | @Column(columnDefinition = "TINYINT(1) DEFAULT 0") 30 | private boolean isDeleted; 31 | 32 | @Temporal(TemporalType.DATE) 33 | @Column(nullable = false) 34 | private Date insertDate; 35 | 36 | @Temporal(TemporalType.DATE) 37 | private Date updateDate; 38 | 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/domain/UserPoint.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.domain; 2 | 3 | 4 | 5 | import lombok.Data; 6 | 7 | import javax.persistence.*; 8 | import java.util.Date; 9 | 10 | /** 11 | * Created by yion on 2015. 2. 1.. 12 | */ 13 | @Data 14 | @Entity 15 | public class UserPoint { 16 | 17 | @Id 18 | @Column(nullable = false) 19 | @GeneratedValue(strategy = GenerationType.AUTO) 20 | private Integer userPointId; 21 | 22 | @ManyToOne 23 | @JoinColumn(name = "userId", referencedColumnName = "userId", nullable = false) 24 | private User user; 25 | 26 | @Column(nullable = false, columnDefinition = "int default 0") 27 | private Integer userPoint; 28 | 29 | @Enumerated(EnumType.STRING) 30 | @Column(length = 20) 31 | private com.libqa.application.enums.UserPoint pointType; 32 | 33 | 34 | @Temporal(TemporalType.DATE) 35 | private Date insertDate; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/domain/Vote.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.domain; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | import java.util.Date; 7 | 8 | /** 9 | * Created by yong on 15. 2. 1.. 10 | */ 11 | @Entity 12 | @Data 13 | public class Vote { 14 | @Id 15 | @Column(nullable = false) 16 | @GeneratedValue(strategy = GenerationType.AUTO) 17 | private Integer voteId; 18 | 19 | @Column(nullable = false) 20 | private Integer replyId; 21 | 22 | @Column(nullable = false) 23 | private Integer userId; 24 | 25 | @Column(nullable = false) 26 | private String userNick; 27 | 28 | @Column(nullable = false, columnDefinition = "TINYINT(1) DEFAULT 0") 29 | private Boolean isVote; 30 | 31 | @Column(nullable = false, columnDefinition = "TINYINT(1) DEFAULT 0") 32 | private boolean isCancel; 33 | 34 | @Temporal(TemporalType.DATE) 35 | @Column(nullable = false) 36 | private Date insertDate; 37 | 38 | @Temporal(TemporalType.DATE) 39 | private Date updateDate; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/domain/WikiFile.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.domain; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | import java.util.Date; 7 | 8 | /** 9 | * Created by songanji on 2015. 2. 8.. 10 | */ 11 | @Entity 12 | @Data 13 | public class WikiFile{ 14 | 15 | @Id 16 | @Column(nullable = false) 17 | @GeneratedValue(strategy = GenerationType.AUTO) 18 | private Integer fileId; 19 | 20 | @Temporal(TemporalType.TIMESTAMP) 21 | @Column(nullable = false) 22 | private Date insertDate; 23 | 24 | @Temporal(TemporalType.TIMESTAMP) 25 | private Date updateDate; 26 | 27 | @Column(nullable = false, length = 255) 28 | private String realName; 29 | 30 | @Column(nullable = false, length = 255) 31 | private String savedName; 32 | 33 | @Column(nullable = false, length = 80) 34 | private String filePath; 35 | 36 | @Column(nullable = false) 37 | private Integer fileSize; 38 | 39 | @Column(nullable = true, length = 10) 40 | private String fileType; 41 | 42 | @Column(columnDefinition = "TINYINT(1) DEFAULT 0") 43 | private boolean isDeleted; 44 | 45 | @Column(nullable = false) 46 | private Integer userId; 47 | 48 | private Integer wikiId; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/domain/WikiLike.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.domain; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | 7 | /** 8 | * Created by songanji on 2015. 10. 11.. 9 | */ 10 | @Entity 11 | @Data 12 | @Table(uniqueConstraints = { 13 | @UniqueConstraint(columnNames = {"userId","wikiId"}), 14 | @UniqueConstraint(columnNames = {"userId","replyId"}) 15 | }) 16 | public class WikiLike { 17 | 18 | @Id 19 | @Column(nullable = false) 20 | @GeneratedValue(strategy = GenerationType.AUTO) 21 | private Integer likeId; 22 | 23 | @Column(nullable = false) 24 | private Integer userId; 25 | 26 | private Integer wikiId; 27 | 28 | private Integer replyId; 29 | 30 | } -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/ActivityRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.Activity; 4 | import org.springframework.data.domain.Sort; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Author : yion 11 | * @Date : 2015. 6. 28. 12 | * @Description : 13 | */ 14 | public interface ActivityRepository extends JpaRepository { 15 | List findBySpaceIdAndIsDeleted(Integer spaceId, boolean isDeleted, Sort sort); 16 | List findByWikiId(Integer WikiId); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/FeedActionRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.application.enums.ActionType; 4 | import com.libqa.application.enums.PostType; 5 | import com.libqa.web.domain.FeedAction; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import java.util.List; 9 | 10 | public interface FeedActionRepository extends JpaRepository { 11 | List findByFeedActorIdAndUserIdAndIsCanceledFalse(Integer feedActorId, Integer userId); 12 | 13 | Integer countByFeedActorIdAndPostTypeAndActionTypeAndIsCanceledFalse( 14 | Integer feedActorId, PostType postType, ActionType actionType); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/FeedFileRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.FeedFile; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface FeedFileRepository extends JpaRepository { 9 | List findByFeedThreadFeedThreadId(Integer feedThreadId); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/FeedReplyRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.FeedThread; 4 | import com.libqa.web.domain.FeedReply; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.List; 8 | 9 | public interface FeedReplyRepository extends JpaRepository { 10 | List findByFeedThreadFeedThreadId(Integer feedThreadId); 11 | Integer countByFeedThreadAndIsDeletedFalse(FeedThread feedThread); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/FeedThreadRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.FeedThread; 4 | import org.springframework.data.domain.Pageable; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.List; 8 | 9 | public interface FeedThreadRepository extends JpaRepository { 10 | List findByIsDeletedFalse(Pageable pageable); 11 | List findByFeedThreadIdLessThanAndIsDeletedFalse(Integer feedThreadId, Pageable pageable); 12 | List findByUserIdAndIsDeletedFalse(Integer userId, Pageable pageable); 13 | List findByUserIdAndFeedThreadIdLessThanAndIsDeletedFalse(Integer userId, Integer feedThreadId, Pageable pageable); 14 | Integer countFeedRepliesByFeedThreadId(Integer feedThreadId); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/KeywordListRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.application.enums.KeywordType; 4 | import com.libqa.web.domain.KeywordList; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by yong on 15. 2. 8.. 11 | */ 12 | public interface KeywordListRepository extends JpaRepository { 13 | List findByKeywordNameAndKeywordType(String keywordName, KeywordType keywordType); 14 | 15 | List findByKeywordTypeAndIsDeleted(KeywordType keywordType, boolean isDeleted); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/KeywordRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.application.enums.KeywordType; 4 | import com.libqa.web.domain.Keyword; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by yong on 15. 2. 8.. 11 | */ 12 | public interface KeywordRepository extends JpaRepository { 13 | 14 | List findAllByQaIdAndIsDeletedFalse(Integer qaId); 15 | 16 | List findAllByKeywordTypeAndIsDeleted(KeywordType keywordType, boolean isDeleted); 17 | 18 | List findAllByKeywordTypeAndKeywordNameAndIsDeleted(KeywordType keywordType, String keywordName, boolean isDeleted); 19 | 20 | List findAllByWikiIdAndIsDeleted(Integer wikiId, boolean isDeleted); 21 | 22 | List findAllByKeywordIdAndIsDeleted(Integer keywordId, boolean isDeleted); 23 | 24 | List findAllBySpaceIdAndIsDeleted(Integer spaceId, boolean isDeleted); 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/QaFileRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.QaFile; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * Created by yong on 15. 2. 8.. 8 | */ 9 | public interface QaFileRepository extends JpaRepository { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/QaRecommendRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.QaRecommend; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by yong on 15. 2. 8.. 10 | */ 11 | public interface QaRecommendRepository extends JpaRepository { 12 | List findByUserIdAndIsCommendTrueAndIsCanceledFalse(Integer userId); 13 | 14 | QaRecommend findByQaIdAndUserIdAndIsCanceledFalse(Integer qaId, Integer userId); 15 | 16 | QaRecommend findByQaIdAndUserIdAndIsCommendAndIsCanceledFalse(Integer qaId, Integer userId, boolean isCommend); 17 | 18 | List findByQaIdAndIsCommendAndIsCanceledFalse(Integer qaId, boolean isCommend); 19 | 20 | int countByQaIdAndIsCanceledFalse(Integer qaId); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/SpaceAccessUserRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.SpaceAccessUser; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * Created by yong on 15. 2. 8.. 8 | */ 9 | public interface SpaceAccessUserRepository extends JpaRepository { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/SpaceRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.Space; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.domain.Sort; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | import org.springframework.data.jpa.repository.Query; 9 | import org.springframework.data.repository.query.Param; 10 | import org.springframework.stereotype.Repository; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * Created by yion on 15. 2. 8.. 16 | */ 17 | public interface SpaceRepository extends JpaRepository { 18 | 19 | 20 | List findAllByIsDeleted(Sort orders, boolean isDeleted); 21 | 22 | Page findPagingByIsDeleted(Pageable pageable, boolean isDeleted); 23 | 24 | @Query(value = "SELECT s.* FROM space s " + 25 | "WHERE s.is_deleted = 0 " + 26 | " AND (s.title LIKE CONCAT('%',:searchValue,'%') OR s.description_markup LIKE CONCAT('%',:searchValue,'%') ) " + 27 | "ORDER BY s.space_id DESC", nativeQuery = true) 28 | List findAllBySearchValue(@Param("searchValue") String searchValue); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/UserFavoriteRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.application.enums.FavoriteType; 4 | import com.libqa.web.domain.UserFavorite; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by yong on 15. 2. 8.. 11 | */ 12 | public interface UserFavoriteRepository extends JpaRepository{ 13 | 14 | List findBySpaceIdAndUserId(Integer spaceId, Integer userId); 15 | 16 | List findByFavoriteTypeAndUserIdAndIsDeleted(FavoriteType favoriteType, Integer userId, boolean isDeleted); 17 | 18 | List findBySpaceIdAndUserIdAndIsDeleted(Integer spaceId, Integer userId, boolean isDeleted); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/UserKeywordRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.User; 4 | import com.libqa.web.domain.UserKeyword; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by yong on 15. 2. 8.. 11 | */ 12 | public interface UserKeywordRepository extends JpaRepository { 13 | List findByUserAndIsDeleted(User user, boolean isDeleted); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/UserPointRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.UserPoint; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * Created by yong on 15. 2. 8.. 8 | */ 9 | public interface UserPointRepository extends JpaRepository { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.application.enums.Role; 4 | import com.libqa.web.domain.User; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by yion on 2015. 1. 25.. 11 | */ 12 | public interface UserRepository extends JpaRepository { 13 | User findByUserEmail(String userEmail); 14 | 15 | User findByUserNick(String userNick); 16 | 17 | List findByRoleAndIsDeleted(Role role, boolean isDeleted); 18 | 19 | List findAllByIsDeleted(boolean isDeleted); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/VoteRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.Vote; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by yong on 15. 2. 8.. 10 | */ 11 | public interface VoteRepository extends JpaRepository { 12 | Vote findByReplyIdAndUserIdAndIsCancel(Integer replyId, Integer userId, boolean isCancel); 13 | 14 | Vote findByReplyIdAndUserIdAndIsVoteAndIsCancel(Integer replyId, int userId, boolean isVoted, boolean isCanceled); 15 | 16 | List findByReplyIdAndIsVoteAndIsCancelFalse(Integer replyId, boolean isVote); 17 | 18 | int countByReplyIdAndIsCancelFalse(Integer replyId); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/WikiFileRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.WikiFile; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * Created by yong on 15. 2. 8.. 8 | */ 9 | public interface WikiFileRepository extends JpaRepository { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/WikiLikeRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.WikiLike; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by yong on 15. 2. 8.. 10 | */ 11 | public interface WikiLikeRepository extends JpaRepository { 12 | 13 | WikiLike findOneByUserIdAndWikiId(Integer userId, Integer wikiId); 14 | 15 | WikiLike findOneByUserIdAndReplyId(Integer userId, Integer wikiId); 16 | } -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/WikiReplyRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.Wiki; 4 | import com.libqa.web.domain.WikiReply; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | /** 8 | * Created by yong on 15. 2. 8.. 9 | */ 10 | public interface WikiReplyRepository extends JpaRepository{ 11 | 12 | int countByWikiId(Integer wiki); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/repository/WikiSnapShotRepository.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.repository; 2 | 3 | import com.libqa.web.domain.WikiSnapShot; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * Created by yong on 15. 2. 8.. 8 | */ 9 | public interface WikiSnapShotRepository extends JpaRepository { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/common/ActivityService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.common; 2 | 3 | import com.libqa.web.domain.Activity; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @Author : yion 9 | * @Date : 2015. 6. 28. 10 | * @Description : 11 | */ 12 | public interface ActivityService { 13 | 14 | Activity saveActivity(Activity activity, String title); 15 | 16 | List findBySpaceId(Integer spaceId); 17 | 18 | List findByWikiId(Integer wikiId); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/common/KeywordListService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.common; 2 | 3 | import com.libqa.application.enums.KeywordType; 4 | import com.libqa.web.domain.KeywordList; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by yong on 2015-03-08. 10 | * 11 | * @author yong 12 | */ 13 | public interface KeywordListService { 14 | List findByKeywordType(String keywordType, boolean isDeleted); 15 | 16 | List findByKeywordNameAndKeywordType(String keywordName, KeywordType keywordType); 17 | 18 | void save(KeywordList keyword); 19 | 20 | void save(List keywordList); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/common/KeywordService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.common; 2 | 3 | import com.libqa.application.enums.KeywordType; 4 | import com.libqa.web.domain.Keyword; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by yong on 2015-03-08. 10 | * 11 | * @author yong 12 | */ 13 | public interface KeywordService { 14 | 15 | boolean saveKeywordAndList(String[] keywordNames, String[] deleteKeywordParams, KeywordType keywordType, Integer entityId); 16 | 17 | List findByQaId(Integer qaId); 18 | 19 | List findAllByKeywordTypeAndKeywordNameAndIsDeleted(KeywordType keywordType, String keywordName, boolean isDeleted); 20 | 21 | List findByWikiId(Integer wikiId, boolean isDeleted); 22 | 23 | List findBykeywordId(Integer keywordId, boolean isDeleted); 24 | 25 | List findBySpaceId(Integer spaceId, boolean isDeleted); 26 | 27 | void delete(Integer qaId, Integer userId); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/feed/actor/FeedActionActor.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.feed.actor; 2 | 3 | import com.libqa.application.enums.ActionType; 4 | import com.libqa.application.enums.PostType; 5 | import com.libqa.web.domain.User; 6 | import lombok.Getter; 7 | 8 | public abstract class FeedActionActor { 9 | @Getter 10 | private Integer feedActorId; 11 | @Getter 12 | private User actionUser; 13 | 14 | /** 15 | * @param feedActorId 각 actor 의 unique key 를 나타낸다.
16 | * feed => feedThreadId, feedReply => feedReplyId 17 | * @param actionUser action 을 취한 user 18 | */ 19 | FeedActionActor(Integer feedActorId, User actionUser) { 20 | this.feedActorId = feedActorId; 21 | this.actionUser = actionUser; 22 | } 23 | 24 | public abstract PostType getPostType(); 25 | 26 | public abstract ActionType getActionType(); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/feed/actor/FeedReplyClaim.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.feed.actor; 2 | 3 | import com.libqa.application.enums.ActionType; 4 | import com.libqa.application.enums.PostType; 5 | import com.libqa.web.domain.User; 6 | 7 | public class FeedReplyClaim extends FeedActionActor { 8 | private FeedReplyClaim(Integer feedReplyId, User actionUser) { 9 | super(feedReplyId, actionUser); 10 | } 11 | 12 | public static FeedReplyClaim of(Integer feedReplyId, User actionUser) { 13 | return new FeedReplyClaim(feedReplyId, actionUser); 14 | } 15 | 16 | @Override 17 | public PostType getPostType() { 18 | return PostType.REPLY; 19 | } 20 | 21 | @Override 22 | public ActionType getActionType() { 23 | return ActionType.CLAIM; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/feed/actor/FeedReplyLike.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.feed.actor; 2 | 3 | import com.libqa.application.enums.ActionType; 4 | import com.libqa.application.enums.PostType; 5 | import com.libqa.web.domain.User; 6 | 7 | public class FeedReplyLike extends FeedActionActor { 8 | private FeedReplyLike(Integer feedReplyId, User actionUser) { 9 | super(feedReplyId, actionUser); 10 | } 11 | 12 | public static FeedReplyLike of(Integer feedReplyId, User actionUser) { 13 | return new FeedReplyLike(feedReplyId, actionUser); 14 | } 15 | 16 | @Override 17 | public PostType getPostType() { 18 | return PostType.REPLY; 19 | } 20 | 21 | @Override 22 | public ActionType getActionType() { 23 | return ActionType.LIKE; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/feed/actor/FeedThreadClaim.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.feed.actor; 2 | 3 | import com.libqa.application.enums.ActionType; 4 | import com.libqa.application.enums.PostType; 5 | import com.libqa.web.domain.User; 6 | 7 | public class FeedThreadClaim extends FeedActionActor { 8 | private FeedThreadClaim(Integer feedThreadId, User actionUser) { 9 | super(feedThreadId, actionUser); 10 | } 11 | 12 | public static FeedThreadClaim of(Integer feedThreadId, User actionUser) { 13 | return new FeedThreadClaim(feedThreadId, actionUser); 14 | } 15 | 16 | @Override 17 | public PostType getPostType() { 18 | return PostType.THREAD; 19 | } 20 | 21 | @Override 22 | public ActionType getActionType() { 23 | return ActionType.CLAIM; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/feed/actor/FeedThreadLike.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.feed.actor; 2 | 3 | import com.libqa.application.enums.ActionType; 4 | import com.libqa.application.enums.PostType; 5 | import com.libqa.web.domain.User; 6 | 7 | public class FeedThreadLike extends FeedActionActor { 8 | private FeedThreadLike(Integer feedThreadId, User actionUser) { 9 | super(feedThreadId, actionUser); 10 | } 11 | 12 | public static FeedThreadLike of(Integer feedThreadId, User actionUser) { 13 | return new FeedThreadLike(feedThreadId, actionUser); 14 | } 15 | 16 | @Override 17 | public PostType getPostType() { 18 | return PostType.THREAD; 19 | } 20 | 21 | @Override 22 | public ActionType getActionType() { 23 | return ActionType.LIKE; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/qa/QaFileService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.qa; 2 | 3 | import com.libqa.web.domain.QaFile; 4 | 5 | /** 6 | * Created by yong on 2015-03-28. 7 | * 8 | * @author yong 9 | */ 10 | public interface QaFileService { 11 | boolean moveQaFilesToProductAndSave(Integer qaId, QaFile qaFiles); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/qa/QaRecommendService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.qa; 2 | 3 | import com.libqa.web.domain.QaContent; 4 | import com.libqa.web.domain.QaRecommend; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by yong on 2016-01-31. 10 | * 11 | * @author yong 12 | */ 13 | public interface QaRecommendService { 14 | List findByUserIdAndIsCommendTrue(Integer userId); 15 | 16 | QaRecommend findByQaIdAndUserIdAndIsCommend(Integer qaId, Integer userId, boolean isCommend); 17 | 18 | QaContent saveRecommend(QaRecommend paramQaRecommend, Integer userId, String userNick) throws Exception; 19 | 20 | List findByQaIdAndIsCommend(Integer qaId, boolean isCommend); 21 | 22 | int getCountByQaId(Integer qaId); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/qa/VoteService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.qa; 2 | 3 | import com.libqa.web.domain.QaReply; 4 | import com.libqa.web.domain.Vote; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by yong on 2015-05-25. 10 | * 11 | * @author yong 12 | */ 13 | public interface VoteService { 14 | Vote findByReplyIdAndUserIdAndIsCancel(Integer replyId, Integer userId, boolean isCancel); 15 | 16 | void saveByQaReply(QaReply qaReply, Integer userId, String userNick, boolean isVote); 17 | 18 | void deleteByQaReply(QaReply qaReply, Integer userId); 19 | 20 | Vote findByReplyIdAndUserIdAndIsVoteAndIsCancel(Integer replyId, int userId, boolean isVote, boolean isCancel); 21 | 22 | boolean hasRecommendUser(Integer replyId, Integer userId); 23 | 24 | boolean hasNonRecommendUser(Integer replyId, Integer userId); 25 | 26 | List findByReplyIdAndIsVote(Integer replyId, boolean isVote); 27 | 28 | int getCountByReplyId(Integer replyId); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/user/UserFavoriteService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.user; 2 | 3 | import com.libqa.application.enums.FavoriteType; 4 | import com.libqa.web.domain.UserFavorite; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @Author : yion 10 | * @Date : 2015. 5. 20. 11 | * @Description : 사용자 즐겨찾기 서비스 12 | */ 13 | public interface UserFavoriteService { 14 | /** 15 | * 사용자가 즐겨찾기 한 타입 리스트 조회 16 | * @param typeEnum 17 | * @param userId 18 | * @return 19 | */ 20 | List findByFavoriteTypeAndUserIdAndIsDeleted(FavoriteType typeEnum, Integer userId, boolean isDeleted); 21 | 22 | 23 | /** 24 | * 사용자가 추가한 공간 즐겨 찾기 조회 25 | * @param spaceId 26 | * @param userId 27 | * @return 28 | */ 29 | List findBySpaceIdAndUserId(Integer spaceId, Integer userId); 30 | 31 | List findBySpaceIdAndUserIdAndIsDeleted(Integer spaceId, Integer userId, boolean isDeleted); 32 | 33 | void save(UserFavorite userFavorite); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/user/UserKeywordService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.user; 2 | 3 | import com.libqa.web.domain.User; 4 | import com.libqa.web.domain.UserKeyword; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @Author : yion 10 | * @Date : 2015. 11. 10. 11 | * @Description : 12 | */ 13 | public interface UserKeywordService { 14 | 15 | List findByUserAndIsDeleted(User user); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/user/UserKeywordServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.user; 2 | 3 | import com.libqa.web.domain.User; 4 | import com.libqa.web.domain.UserKeyword; 5 | import com.libqa.web.repository.UserKeywordRepository; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @Author : yion 14 | * @Date : 2015. 11. 10. 15 | * @Description : 16 | */ 17 | @Slf4j 18 | @Service 19 | public class UserKeywordServiceImpl implements UserKeywordService { 20 | 21 | @Autowired 22 | private UserKeywordRepository userKeywordRepository; 23 | 24 | @Override 25 | public List findByUserAndIsDeleted(User user) { 26 | List userKeywords = userKeywordRepository.findByUserAndIsDeleted(user, false); 27 | return userKeywords; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/wiki/WikiFileService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.wiki; 2 | 3 | import com.libqa.web.domain.WikiFile; 4 | 5 | /** 6 | * Created by songanji on 2015. 4. 19.. 7 | */ 8 | public interface WikiFileService { 9 | boolean saveWikiFileAndList(WikiFile wikiFile); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/wiki/WikiFileServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.wiki; 2 | 3 | import com.libqa.web.domain.WikiFile; 4 | import com.libqa.web.repository.WikiFileRepository; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * Created by songanji on 2015. 4. 19.. 11 | */ 12 | @Service 13 | @Slf4j 14 | public class WikiFileServiceImpl implements WikiFileService { 15 | @Autowired 16 | WikiFileRepository wikiFileRepository; 17 | 18 | @Override 19 | public boolean saveWikiFileAndList(WikiFile wikiFile) { 20 | wikiFileRepository.save(wikiFile); 21 | return true; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/service/wiki/WikiReplyService.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.service.wiki; 2 | 3 | import com.libqa.web.domain.Wiki; 4 | import com.libqa.web.domain.WikiReply; 5 | 6 | /** 7 | * Created by songanji on 2015. 4. 26.. 8 | */ 9 | public interface WikiReplyService { 10 | int countByWiki(Integer wikiId); 11 | WikiReply findById(Integer replyId); 12 | WikiReply save(WikiReply wikiReply); 13 | WikiReply update(WikiReply wikiReply); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/feed/DisplayDate.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.feed; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | public class DisplayDate { 7 | private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; 8 | 9 | public static String parse(Date date) { 10 | return new SimpleDateFormat(DATE_FORMAT).format(date); 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/feed/DisplayFeedAction.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.feed; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class DisplayFeedAction { 7 | private boolean hasActor = false; 8 | private Integer count = 0; 9 | 10 | DisplayFeedAction(boolean hasActor, Integer count) { 11 | this.hasActor = hasActor; 12 | this.count = count; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/feed/DisplayFeedFile.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.feed; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | class DisplayFeedFile { 9 | private Integer fileId; 10 | private String realName; 11 | private String fullPath; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/feed/DisplayFeedReply.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.feed; 2 | 3 | import com.libqa.web.domain.FeedReply; 4 | import com.libqa.web.domain.User; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | public class DisplayFeedReply { 10 | private Integer feedReplyId; 11 | private String userNick; 12 | private String userImage; 13 | private String insertDate; 14 | private String feedReplyContent; 15 | private Boolean isReplyWriter; 16 | 17 | @Setter 18 | private DisplayFeedAction likeFeedAction; 19 | @Setter 20 | private DisplayFeedAction claimFeedAction; 21 | 22 | DisplayFeedReply(FeedReply feedReply, User user, Boolean isReplyWriter) { 23 | this.feedReplyId = feedReply.getFeedReplyId(); 24 | this.userNick = feedReply.getUserNick(); 25 | this.userImage = user.getUserImage(); 26 | this.insertDate = DisplayDate.parse(feedReply.getInsertDate()); 27 | this.feedReplyContent = feedReply.getFeedReplyContent(); 28 | this.isReplyWriter = isReplyWriter; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/index/DisplayIndex.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.index; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | import java.util.List; 8 | 9 | @Getter 10 | @Setter 11 | @NoArgsConstructor(staticName = "of") 12 | public class DisplayIndex { 13 | private IndexNotice notice; 14 | private List qaContents; 15 | private List wikies; 16 | private List spaces; 17 | private List feeds; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/index/IndexFeed.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.index; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @NoArgsConstructor(staticName = "of") 10 | public class IndexFeed { 11 | private Integer feedThreadId; 12 | private String userNick; 13 | private String userImage; 14 | private String feedContent; 15 | private Integer countOfReply; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/index/IndexKeyword.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.index; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | @Setter 8 | @Getter 9 | @NoArgsConstructor(staticName = "of") 10 | public class IndexKeyword { 11 | private String name; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/index/IndexNotice.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.index; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @NoArgsConstructor(staticName = "of") 10 | public class IndexNotice { 11 | private static final IndexNotice EMPTY = IndexNotice.of(); 12 | 13 | private String viewUrl; 14 | private String moreUrl; 15 | private String title; 16 | private String contents; 17 | private String insertDate; 18 | private int countOfReply; 19 | 20 | public static IndexNotice empty() { 21 | return EMPTY; 22 | } 23 | 24 | public boolean isEmpty() { 25 | return this == EMPTY; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/index/IndexQaContent.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.index; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | import java.util.List; 8 | 9 | @Getter 10 | @Setter 11 | @NoArgsConstructor(staticName = "of") 12 | public class IndexQaContent { 13 | private Integer qaId; 14 | private String title; 15 | private String contents; 16 | private String userImage; 17 | private String userNick; 18 | private String insertDate; 19 | private List keywords; 20 | private Integer countOfReply; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/index/IndexSpace.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.index; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @NoArgsConstructor(staticName = "of") 10 | public class IndexSpace { 11 | private Integer spaceId; 12 | private String title; 13 | private String description; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/index/IndexWiki.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.index; 2 | 3 | 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @NoArgsConstructor(staticName = "of") 11 | public class IndexWiki { 12 | private Integer wikiId; 13 | private String title; 14 | private String description; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/search/DisplaySearchResult.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.search; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | import java.util.List; 8 | 9 | @Getter 10 | @Setter 11 | @NoArgsConstructor(staticName = "of") 12 | public class DisplaySearchResult { 13 | private Integer id; 14 | private String title; 15 | private String contents; 16 | private String userImage; 17 | private String userNick; 18 | private String insertDate; 19 | private String insertUserNick; 20 | private List keywords; 21 | private Integer countOfReply; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/space/SpaceActivityList.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.space; 2 | 3 | import com.libqa.web.domain.Activity; 4 | import com.libqa.web.domain.User; 5 | import lombok.Getter; 6 | 7 | /** 8 | * @Author : yion 9 | * @Date : 2015. 10. 11. 10 | * @Description : 11 | */ 12 | 13 | @Getter 14 | public class SpaceActivityList { 15 | 16 | private Activity activity; 17 | private User user; 18 | 19 | public SpaceActivityList(Activity activity, User user) { 20 | this.activity = activity; 21 | this.user = user; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/space/SpaceMainList.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.space; 2 | 3 | import com.libqa.web.domain.Space; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Author : yion 12 | * @Date : 2016. 3. 27. 13 | * @Description : 14 | */ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class SpaceMainList { 19 | private Integer currentPage; 20 | private Integer totalPages; 21 | private Long totalElements; 22 | private List spaceMainList; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/space/SpaceWiki.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.space; 2 | 3 | import com.libqa.web.domain.Keyword; 4 | import com.libqa.web.domain.User; 5 | import com.libqa.web.domain.Wiki; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @Author : yion 13 | * @Date : 2016. 4. 17. 14 | * @Description : 15 | */ 16 | @Setter 17 | @Getter 18 | public class SpaceWiki { 19 | 20 | private Wiki wiki; 21 | private User user; 22 | private List keywords; 23 | private int replyCount; 24 | 25 | public SpaceWiki(Wiki wiki, User user, List keywords, int replyCount) { 26 | this.wiki = wiki; 27 | this.user = user; 28 | this.keywords = keywords; 29 | this.replyCount = replyCount; 30 | } 31 | 32 | 33 | public SpaceWiki() { 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/space/SpaceWikiList.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.space; 2 | 3 | import com.libqa.web.domain.Keyword; 4 | import com.libqa.web.domain.User; 5 | import com.libqa.web.domain.Wiki; 6 | import lombok.*; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Author : yion 12 | * @Date : 2015. 8. 23. 13 | * @Description : 14 | */ 15 | 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class SpaceWikiList { 20 | private Integer currentPage; 21 | private Integer totalPages; 22 | private Long totalElements; 23 | private List spaceWikiList; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/space/TreeModel.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.space; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @Author : yion 11 | * @Date : 2016. 3. 1. 12 | * @Description : 13 | */ 14 | @Getter 15 | @Setter 16 | public class TreeModel { 17 | 18 | private Integer id; 19 | private String text; 20 | private Integer parentId; 21 | private String href; 22 | private String[] tags = new String[0]; 23 | 24 | private boolean hasChild; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/user/UserList.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.user; 2 | 3 | import com.libqa.web.domain.User; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Author : yion 12 | * @Date : 2016. 8. 28. 13 | * @Description : 14 | */ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class UserList { 19 | private Integer currentPage; 20 | private Integer totalPages; 21 | private Long totalElements; 22 | private List userList; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/wiki/DisplayAjaxWiki.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.wiki; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by songanji on 2016. 3. 27.. 9 | */ 10 | @Data 11 | public class DisplayAjaxWiki { 12 | private List allWiki; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/wiki/DisplayWiki.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.wiki; 2 | 3 | import com.libqa.web.domain.Keyword; 4 | import com.libqa.web.domain.User; 5 | import com.libqa.web.domain.Wiki; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Created by songanji on 2015. 11. 22.. 13 | */ 14 | @Data 15 | @NoArgsConstructor 16 | public class DisplayWiki { 17 | private Wiki wiki; 18 | private User user; 19 | private List keywords; 20 | 21 | public DisplayWiki (Wiki wiki){ 22 | this.wiki = wiki; 23 | } 24 | public DisplayWiki(Wiki wiki, User user){ 25 | this.wiki = wiki; 26 | this.user = user; 27 | } 28 | public DisplayWiki(Wiki wiki, User user, List keywords){ 29 | this.wiki = wiki; 30 | this.user = user; 31 | this.keywords = keywords; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/libqa/web/view/wiki/DisplayWikiLike.java: -------------------------------------------------------------------------------- 1 | package com.libqa.web.view.wiki; 2 | 3 | import com.libqa.web.domain.WikiLike; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | 7 | /** 8 | * Created by songanji on 2015. 12. 6.. 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | public class DisplayWikiLike { 13 | private Integer result; 14 | private WikiLike wikiLike; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Hibernate config 2 | spring.jpa.hibernate.ddl-auto=update 3 | spring.jpa.generate-ddl=false 4 | spring.jpa.database=MYSQL 5 | spring.jpa.show-sql=false 6 | spring.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 7 | spring.jpa.properties.hibernate.format_sql=false 8 | spring.datasource.validation-query=SELECT 1 9 | spring.datasource.test-on-borrow=true 10 | spring.datasource.test-on-return=true 11 | spring.datasource.tomcat.validation-interval=20000 12 | 13 | # JDBC 14 | spring.datasource.url=jdbc:mysql://localhost:3306/howling?useUnicode=true&charaterEncoding=utf-8 15 | spring.datasource.username=howlingproject 16 | spring.datasource.password=libqa2014 17 | spring.datasource.driverClassName=net.sf.log4jdbc.sql.jdbcapi.DriverSpy 18 | spring.datasource.maxIdle=20 19 | spring.datasource.maxActive=200 20 | spring.datasource.maxWait=10000 21 | 22 | # file Size 23 | multipart.maxFileSize=10Mb 24 | 25 | # log level config 26 | logging.level.root=INFO 27 | logging.level.org.springframework.web=WARN 28 | logging.level.org.hibernate=WARN 29 | 30 | # server 31 | server.port=8080 32 | 33 | # libqa configuration 34 | libqa.viewResolver.cached=false 35 | libqa.file.uploadPath=~/libqa/files -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ _ _ _ _ 2 | | | | | _____ __ (_)_ __ __ _ | | (_) |__ __ _ __ _ 3 | | |_| |/ _ \ \ /\ / / | | '_ \ / _` |_____| | | | '_ \ / _` |/ _` | 4 | | _ | (_) \ V V /| | | | | | (_| |_____| |___| | |_) | (_| | (_| | 5 | |_| |_|\___/ \_/\_/ |_|_|_| |_|\__, | |_____|_|_.__/ \__, |\__,_| 6 | |___/ |_| -------------------------------------------------------------------------------- /src/main/resources/log4jdbc.log4j2.properties: -------------------------------------------------------------------------------- 1 | log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/mail.properties: -------------------------------------------------------------------------------- 1 | mail.protocol=smtp 2 | mail.host=smtp.gmail.com 3 | mail.port=587 4 | mail.encoding:UTF-8 5 | mail.smtp.auth=true 6 | mail.smtp.starttls.enable=true 7 | mail.from=libqa \uC790\uB3D9 \uBC1C\uC1A1 8 | mail.username=LibQA 9 | mail.password=libqa2014 10 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/common/_keywordList.hbs: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/error/401.hbs: -------------------------------------------------------------------------------- 1 | {{#partial "title"}}LibQA~{{/partial}} 2 | 3 | {{# partial "content" }} 4 |
5 |

Not Authorized

6 |

Sorry, but you are not authorized to view this page. :(

7 |
8 | {{/partial}} 9 | 10 | {{> template/base}} 11 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/error/403.hbs: -------------------------------------------------------------------------------- 1 | {{!-- 2 | Created by IntelliJ IDEA. 3 | User: yion 4 | Date: 2014. 12. 7. 5 | Time: 16:20 6 | To change this template use File | Settings | File Templates. 7 | --}} 8 | {{#partial "style"}} 9 | {{!-- 여기에 사용자 css 정의 --}} 10 | 11 | {{/partial}} 12 | 13 | {{#partial "plugin-style"}} 14 | {{!-- 여기에 .css 파일 경로 --}} 15 | 16 | {{/partial}} 17 | {{#partial "script-header"}} 18 | 19 | {{/partial}} 20 | 21 | {{#partial "title"}}LibQA~{{/partial}} 22 | 23 | {{# partial "content" }} 24 | 25 |
26 |

Access is denied

27 |

{{msg}}

28 |
29 | {{/partial}} 30 | 31 | 32 | {{# partial "script-page" }} 33 | 36 | {{/partial}} 37 | 38 | {{> template/base}} 39 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/error/404.hbs: -------------------------------------------------------------------------------- 1 | {{!-- 2 | Created by IntelliJ IDEA. 3 | User: yion 4 | Date: 2014. 12. 7. 5 | Time: 16:20 6 | To change this template use File | Settings | File Templates. 7 | --}} 8 | {{#partial "style"}} 9 | {{!-- 여기에 사용자 css 정의 --}} 10 | 11 | {{/partial}} 12 | 13 | {{#partial "plugin-style"}} 14 | {{!-- 여기에 .css 파일 경로 --}} 15 | 16 | {{/partial}} 17 | {{#partial "script-header"}} 18 | 19 | {{/partial}} 20 | 21 | {{#partial "title"}}LibQA~{{/partial}} 22 | 23 | {{# partial "content" }} 24 | 25 |
26 |

Page Not found :(

27 |

{{msg}}

28 |
29 | 30 | {{/partial}} 31 | 32 | 33 | {{# partial "script-page" }} 34 | 37 | {{/partial}} 38 | 39 | {{> template/base}} 40 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/error/500.hbs: -------------------------------------------------------------------------------- 1 | {{#partial "title"}}LibQA~{{/partial}} 2 | 3 | {{# partial "content" }} 4 |
5 |

Server Error

6 |

Sorry, but there was an error with the server that prevented this page from being displayed. :(

7 |
8 | {{/partial}} 9 | 10 | {{> template/base}} 11 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/feed/template/reply.hbs: -------------------------------------------------------------------------------- 1 |
  • 2 |
    3 | 6 |
    7 |
    {{userNick}}
    8 |
    {{insertDate}}
    9 |
    10 |
    11 |
    {{feedReplyContent}}
    12 |
    13 | 14 | 15 | 16 | 17 | ({{claimFeedAction.count}}) 18 | 19 |
    20 |
    21 |
  • 22 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/qa/template/_fileList.hbs: -------------------------------------------------------------------------------- 1 | {{#each data}} 2 |
    3 | 4 | 5 | 6 | 7 | 8 | 9 | {{realName}} 10 | 11 | 12 | 13 |
    14 | {{/each}} -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/qa/template/_mainList.hbs: -------------------------------------------------------------------------------- 1 | {{#each data}} 2 |
    3 |
    4 | {{title}} 5 |
    6 | {{#each keywords}} 7 | {{#keywordBadge keywordName}}{{/keywordBadge}} 8 | {{/each}} 9 |
    10 |
    11 |
    12 | 15 |
    16 | {{subString (htmlDelete contents) 0 150 }} 17 | {{replyCnt}} 18 |
    19 |
    20 | {{userNick}} 21 | 22 |
    23 |
    24 | {{recommendCount}} 25 | {{formatDate insertDate "yyyy-MM-dd hh:MM"}} 26 |
    27 |
    28 |
    29 | {{/each}} -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/qa/template/_noData.hbs: -------------------------------------------------------------------------------- 1 |
    2 | 작성된 Q&A가 없습니다. 3 |
    4 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/qa/template/_qaBest.hbs: -------------------------------------------------------------------------------- 1 | {{#unless bestQAContents}} 2 |
    3 | 최근에 작성된 Q&A가 없습니다. 4 |
    5 | {{/unless}} 6 | 7 | {{#each bestQAContents}} 8 |
    9 |
    10 | {{{abbreviate (htmlDelete title) 30}}} 11 | {{replyCnt}} 12 |
    {{> common/_keywordBadge}} 13 |
    14 |
    15 | 16 | 19 | 20 |
    21 | {{subString (htmlDelete contents) 0 78 }} 22 |
    23 | 26 |
    {{formatDate insertDate "yyyy-MM-dd hh:MM"}}
    27 |
    28 |
    29 | {{/each}} 30 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/search/form/qa.hbs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/search/form/space.hbs: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/search/form/wiki.hbs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/space/template/_activityList.hbs: -------------------------------------------------------------------------------- 1 | {{#if spaceActivityLists}} 2 | {{#each spaceActivityLists}} 3 |
    4 | 5 | 8 | 9 | 10 |
    11 | {{activity.activityDesc}} 12 | {{formatDate activity.insertDate "yyyy-MM-dd hh:MM:ss"}} 13 |
    14 |
    15 | {{/each}} 16 | 더보기 17 | 18 | {{^}} 19 |
    20 |
    21 | 활동 내역이 존재하지 않습니다. 22 |
    23 |
    24 | {{/if}} -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/space/template/_activityRight.hbs: -------------------------------------------------------------------------------- 1 | {{#if spaceActivityLists}} 2 | {{#each spaceActivityLists}} 3 |
    4 | 5 | 8 | 9 | 10 |
    11 | {{activity.activityDesc}} 12 | {{formatDate activity.insertDate "yyyy-MM-dd hh:MM:ss"}} 13 |
    14 |
    15 | {{/each}} 16 | 더보기 17 | 18 | {{^}} 19 |
    20 |
    21 | 활동 내역이 존재하지 않습니다. 22 |
    23 |
    24 | {{/if}} -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/space/template/_allSpaceList.hbs: -------------------------------------------------------------------------------- 1 | {{#each spaceMainList}} 2 |
    3 | 4 |
    5 | {{title}} 6 |
    7 | {{#each keywords}} 8 | {{#keywordBadge keywordName}}{{/keywordBadge}} 9 | {{/each}} 10 |
    11 |
    12 |
    13 | 14 | 17 | 18 |
    {{subString (htmlDelete description) 0 100 }} 19 |
    20 | {{wikiCount}} 21 |
    22 |
    23 |
    {{insertUserNick}}
    24 |
    {{updateDate}}
    25 |
    26 |
    27 | {{/each}} 28 | 29 | {{#unless spaceMainList}} 30 |
    31 | 생성된 공간이 없습니다. 32 |
    33 | {{/unless}} 34 | 35 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/space/template/_myfavoriteList.hbs: -------------------------------------------------------------------------------- 1 | {{#if myFavoriteSpaceList}} 2 | {{#each myFavoriteSpaceList}} 3 |
    4 |
    5 | {{> common/_keywordBadge}} 6 | {{title}} 7 |
    8 |
    9 | 10 | 13 | 14 |
    15 | {{subString (htmlDelete description) 0 70 }} 16 |
    {{wikiCount}}
    17 |
    18 | 21 |
    {{insertUserNick}}
    22 |
    {{updateDate}}
    23 | 24 |
    25 |
    26 | {{/each}} 27 | {{^}} 28 |
    29 | 즐겨찾기 공간이 없습니다. 30 |
    31 | {{/if}} -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/space/template/_spaceTopMenu.hbs: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 |
    5 |
    6 | 7 | 8 | 위키 생성 9 | 첨부파일 목록 10 | 공간수정 11 | {{#if canDeleted}} 12 | 공간삭제 13 | {{/if}} 14 |
    15 |
    16 | 17 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/space/template/_userList.hbs: -------------------------------------------------------------------------------- 1 | 2 | {{#if userList}} 3 | {{#each userList}} 4 | 5 | 6 | {{userNick}} 7 | {{userEmail}} 8 | {{role}} 9 | 10 | {{/each}} 11 | {{^}} 12 | 13 | 회원 정보가 없습니다. 14 | 15 | 16 | {{/if}} 17 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/template/guest.hbs: -------------------------------------------------------------------------------- 1 | 2 |
  • 3 | Sign Up 4 |
  • 5 |
  • 6 | 7 |
  • 8 | Log in 9 |
  • -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/template/login.hbs: -------------------------------------------------------------------------------- 1 |
  • 2 | Profile 3 |
  • 4 |
  • 5 | 비밀번호변경 6 |
  • 7 | 8 |
  • 9 | Inbox 10 |
  • 11 | 12 |
  • 13 | 14 |
  • 15 | Log Out 16 |
  • -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/template/temp.hbs: -------------------------------------------------------------------------------- 1 | {{!-- 2 | Created by IntelliJ IDEA. 3 | User: yion 4 | Date: 2014. 12. 7. 5 | Time: 16:20 6 | To change this template use File | Settings | File Templates. 7 | --}} 8 | {{#partial "style"}} 9 | {{!-- 여기에 사용자 css 정의 --}} 10 | 11 | {{/partial}} 12 | 13 | {{#partial "plugin-style"}} 14 | {{!-- 여기에 .css 파일 경로 --}} 15 | 16 | {{/partial}} 17 | {{#partial "script-header"}} 18 | 19 | {{/partial}} 20 | 21 | {{#partial "title"}}LibQA~{{/partial}} 22 | 23 | {{# partial "content" }} 24 | 25 |
    26 | 복사용 파일 27 |
    28 | 29 | {{/partial}} 30 | 31 | 32 | {{# partial "script-page" }} 33 | 36 | {{/partial}} 37 | 38 | {{> template/base}} 39 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/user/auth.hbs: -------------------------------------------------------------------------------- 1 | {{!-- 2 | Created by IntelliJ IDEA. 3 | User: yion 4 | Date: 2014. 12. 7. 5 | Time: 16:20 6 | To change this template use File | Settings | File Templates. 7 | --}} 8 | {{#partial "style"}} 9 | {{!-- 여기에 사용자 css 정의 --}} 10 | 11 | {{/partial}} 12 | 13 | {{#partial "plugin-style"}} 14 | {{!-- 여기에 .css 파일 경로 --}} 15 | 16 | {{/partial}} 17 | {{#partial "script-header"}} 18 | 19 | {{/partial}} 20 | 21 | {{#partial "title"}}LibQA~{{/partial}} 22 | 23 | {{# partial "content" }} 24 | 25 |
    26 | 인증 페이지. 27 | 사용자 인증 정상 처리시 로그인 처리 하여 index로 리다이렉션 28 |
    29 | 30 | {{/partial}} 31 | 32 | 33 | {{# partial "script-page" }} 34 | 37 | {{/partial}} 38 | 39 | {{> template/base}} 40 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/user/view.hbs: -------------------------------------------------------------------------------- 1 | {{!-- 2 | Created by IntelliJ IDEA. 3 | User: yion 4 | Date: 2014. 12. 7. 5 | Time: 16:20 6 | To change this template use File | Settings | File Templates. 7 | --}} 8 | {{#partial "style"}} 9 | {{!-- 여기에 사용자 css 정의 --}} 10 | 11 | {{/partial}} 12 | 13 | {{#partial "plugin-style"}} 14 | {{!-- 여기에 .css 파일 경로 --}} 15 | 16 | {{/partial}} 17 | {{#partial "script-header"}} 18 | 19 | {{/partial}} 20 | 21 | {{#partial "title"}}LibQA~{{/partial}} 22 | 23 | {{# partial "content" }} 24 | 25 |
    26 | 메일 {{loginUserInfo.userEmail}}
    27 | 롤 {{loginUserInfo.role}}
    28 | ip {{loginUserInfo.userIp}}
    29 | 30 |
    31 | 32 | {{/partial}} 33 | 34 | 35 | {{# partial "script-page" }} 36 | 39 | {{/partial}} 40 | 41 | {{> template/base}} 42 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/img/2_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/img/2_l.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/img/2_m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/img/2_m.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/img/2_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/img/2_s.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/img/3_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/img/3_l.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/img/3_m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/img/3_m.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/img/3_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/img/3_s.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/img/4_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/img/4_l.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/img/4_m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/img/4_m.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/img/4_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/img/4_s.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mALERT.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.ALERT = function(contents){ 2 | contents = contents.replace(/\[alert\]([\w\W]+?)\[alert\]/gm, "
    $1
    "); 3 | return contents; 4 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mALIGN.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.ALIGN = function(contents){ 2 | contents = contents.replace(/\[align\:(left|right|center)\]([\w\W]+?)\[align\]/gm, "
    $2
    "); 3 | return contents; 4 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mBOLD.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.BOLD = function(contents){ 2 | contents = contents.replace(/\*{2}([\w\W]+?)\*{2}/gm, "$1"); 3 | contents = contents.replace(/\_{2}([\w\W]+?)\_{2}/gm, "$1"); 4 | return contents; 5 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mDEL.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.DEL = function(contents){ 2 | contents = contents.replace(/~~([\w\W]+?)~~/gm, "$1"); 3 | return contents; 4 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mFIELD.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.FIELD = function(contents){ 2 | //debugger; 3 | contents = contents.replace(/\[field(\|([\w\W]+?))?\]([\w\W]+?)\[field\]/gm, "

    $2

    $3
    "); 4 | return contents; 5 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mFONT.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.FONT = function(contents){ 2 | var rex = /\[font\|(.*?)\]([\w\W]+?)\[font\]/gm; 3 | if( contents.match(rex) == null ) return contents; 4 | var font = contents.match(rex).toString().replace(rex, "$1"); 5 | 6 | var fontType; 7 | if( "돋움" == font ){ 8 | fontType = "dotum"; 9 | }else if( "굴림" == font ){ 10 | fontType = "gulim"; 11 | }else if( "궁서" == font ){ 12 | fontType = "gungsuh"; 13 | }else if( "바탕" == font ){ 14 | fontType = "batang"; 15 | } 16 | 17 | contents = contents.replace(rex, "$2"); 18 | return contents; 19 | }; 20 | 21 | DualEditor.markup.FONTSIZE = function(contents){ 22 | contents = contents.replace(/\[size\|(.*?)\]([\w\W]+?)\[size\]/igm, "$2"); 23 | return contents; 24 | }; 25 | 26 | DualEditor.markup.FONTSTYLE = function(contents){ 27 | var rex = /(h1\.(\s{0,}))(.*)?/igm; 28 | if( contents.match(rex) != null ){ 29 | contents = contents.replace(rex, "

    $3

    "); 30 | } 31 | 32 | var rex = /(h2\.(\s{0,}))(.*)?/igm; 33 | if( contents.match(rex) != null ){ 34 | contents = contents.replace(rex, "

    $3

    "); 35 | } 36 | 37 | var rex = /(h3\.(\s{0,}))(.*)?/igm; 38 | if( contents.match(rex) != null ){ 39 | contents = contents.replace(rex, "

    $3

    "); 40 | } 41 | 42 | return contents; 43 | }; 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mH1.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.H1 = function(contents){ 2 | contents = contents.replace(/^(
    #|^#) (.*)/igm, "

    $2

    "); 3 | contents = contents.replace(/^(
    ##|^##) (.*)/igm, "

    $2

    "); 4 | contents = contents.replace(/^(
    ###|^###) (.*)/igm, "

    $2

    "); 5 | 6 | return contents; 7 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mHR.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.HR = function(contents){ 2 | contents = contents.replace(/^
    \*\*\*$/igm, "
    "); 3 | return contents; 4 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mINFO.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.INFO = function(contents){ 2 | contents = contents.replace(/\[info\]([\w\W]+?)\[info\]/gm, "
    $1
    "); 3 | return contents; 4 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mITALIC.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.ITALIC = function(contents){ 2 | contents = contents.replace(/\_([\w\W]+?)\_/gm, "$1"); 3 | return contents; 4 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mLAYOUT.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.LAYOUT = function(contents){ 2 | function replacer(match, p1, p2, offset, string) { 3 | if( idx == 0 ){ 4 | p2 = "
    "+p2+"
    "; 5 | }else{ 6 | p2 = "
    "+p2+"
    "; 7 | } 8 | idx++; 9 | return p2; 10 | } 11 | if( contents.match(/(
    )?\[layout\]([\W\w]+?)\[layout\]/igm) != null ){ 12 | var layoutSize = contents.match(/(
    )?\[layout\]([\W\w]+?)\[layout\]/igm).length; 13 | var idx = 0; 14 | if( layoutSize != null && layoutSize > 1 && layoutSize <= 4 ){ 15 | contents = contents.replace(/(
    )?\[layout\]([\W\w]+?)\[layout\]/igm, replacer); 16 | } 17 | } 18 | return contents; 19 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mLINK.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.LINK = function(contents){ 2 | contents = contents.replace(/[!]\[(.*)\]\(([\w\W]+?)\)/igm, 3 | function(match, p1,p2){ 4 | p2 = p2.replace(/|<\/em>/igm,"_") 5 | return "

    \""+p1+"\"

    "; 6 | } 7 | ); 8 | contents = contents.replace(/\[(.*)\]\(([\w\W]+?)\)/igm, 9 | function(match, p1,p2){ 10 | p1 = p1.replace(/|<\/em>/igm,"_") 11 | return ""+p1+""; 12 | } 13 | ); 14 | return contents; 15 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mSUBERSCRIPT.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.SUBERSCRIPT = function(contents){ 2 | contents = contents.replace(/\[sp\]([\w\W]+?)\[sp\]/gm, "$1"); 3 | return contents; 4 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mSUPERSCRIPT.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.SUPERSCRIPT = function(contents){ 2 | contents = contents.replace(/\[sb\]([\w\W]+?)\[sb\]/gm, "$1"); 3 | return contents; 4 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mSyntax.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.SYNTAX = function(contents){ 2 | var idx = 0; 3 | function replacer(match, p1, p2, offset, string) { 4 | var type = ["Apache","Bash","CoffeeScript","C++","C","C#","CSS","Diff","HTTP","Ini","Java","JavaScript","JSON","Makefile","Markdown","Nginx","Objective-C","Perl","PHP","Python","Ruby","SQL","HTML","XML"]; 5 | var data = syntaxData[idx]; 6 | p1 = p1.replace(//ig, ""); 8 | for( var i=0; i< type.length; i++ ){ 9 | if( type[i] == p1 ){ 10 | idx++; 11 | return "
    "+data+"
    "; 12 | } 13 | } 14 | return p2; 15 | } 16 | contents = contents.replace(/\[syntax ([\w\W]+?)\]([\w\W]+?)\[syntax\]/gm, replacer); 17 | return contents; 18 | }; 19 | 20 | DualEditor.markup.SYNTAX_BEFORE = function(contents){ 21 | var idx = 0; 22 | function replacer(match, p1, p2, offset, string) { 23 | syntaxData.push(p2); 24 | idx++; 25 | return "[syntax "+p1+"] [syntax]"; 26 | } 27 | contents.replace(/\[syntax ([\w\W]+?)\]([\w\W]+?)\[syntax\]/gm, replacer); 28 | return contents; 29 | }; 30 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/module/mUNDERLINING.js: -------------------------------------------------------------------------------- 1 | DualEditor.markup.UNDERLINING = function(contents){ 2 | contents = contents.replace(/([^http:])\/{2}([\w\W]+?)\/{2}/igm, "$1$2"); 3 | return contents; 4 | }; -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/androidstudio.css: -------------------------------------------------------------------------------- 1 | /* 2 | Date: 24 Fev 2015 3 | Author: Pedro Oliveira 4 | */ 5 | 6 | .hljs { 7 | color: #a9b7c6; 8 | background: #282b2e; 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | } 13 | 14 | .hljs-number, 15 | .hljs-literal, 16 | .hljs-symbol, 17 | .hljs-bullet { 18 | color: #6897BB; 19 | } 20 | 21 | .hljs-keyword, 22 | .hljs-selector-tag, 23 | .hljs-deletion { 24 | color: #cc7832; 25 | } 26 | 27 | .hljs-variable, 28 | .hljs-template-variable, 29 | .hljs-link { 30 | color: #629755; 31 | } 32 | 33 | .hljs-comment, 34 | .hljs-quote { 35 | color: #808080; 36 | } 37 | 38 | .hljs-meta { 39 | color: #bbb529; 40 | } 41 | 42 | .hljs-string, 43 | .hljs-attribute, 44 | .hljs-addition { 45 | color: #6A8759; 46 | } 47 | 48 | .hljs-section, 49 | .hljs-title, 50 | .hljs-type { 51 | color: #ffc66d; 52 | } 53 | 54 | .hljs-name, 55 | .hljs-selector-id, 56 | .hljs-selector-class { 57 | color: #e8bf6a; 58 | } 59 | 60 | .hljs-emphasis { 61 | font-style: italic; 62 | } 63 | 64 | .hljs-strong { 65 | font-weight: bold; 66 | } 67 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/arta.css: -------------------------------------------------------------------------------- 1 | /* 2 | Date: 17.V.2011 3 | Author: pumbur 4 | */ 5 | 6 | .hljs { 7 | display: block; 8 | overflow-x: auto; 9 | padding: 0.5em; 10 | background: #222; 11 | } 12 | 13 | .hljs, 14 | .hljs-subst { 15 | color: #aaa; 16 | } 17 | 18 | .hljs-section { 19 | color: #fff; 20 | } 21 | 22 | .hljs-comment, 23 | .hljs-quote, 24 | .hljs-meta { 25 | color: #444; 26 | } 27 | 28 | .hljs-string, 29 | .hljs-symbol, 30 | .hljs-bullet, 31 | .hljs-regexp { 32 | color: #ffcc33; 33 | } 34 | 35 | .hljs-number, 36 | .hljs-addition { 37 | color: #00cc66; 38 | } 39 | 40 | .hljs-built_in, 41 | .hljs-builtin-name, 42 | .hljs-literal, 43 | .hljs-type, 44 | .hljs-template-variable, 45 | .hljs-attribute, 46 | .hljs-link { 47 | color: #32aaee; 48 | } 49 | 50 | .hljs-keyword, 51 | .hljs-selector-tag, 52 | .hljs-name, 53 | .hljs-selector-id, 54 | .hljs-selector-class { 55 | color: #6644aa; 56 | } 57 | 58 | .hljs-title, 59 | .hljs-variable, 60 | .hljs-deletion, 61 | .hljs-template-tag { 62 | color: #bb1166; 63 | } 64 | 65 | .hljs-section, 66 | .hljs-doctag, 67 | .hljs-strong { 68 | font-weight: bold; 69 | } 70 | 71 | .hljs-emphasis { 72 | font-style: italic; 73 | } 74 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/ascetic.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Original style from softwaremaniacs.org (c) Ivan Sagalaev 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background: white; 12 | color: black; 13 | } 14 | 15 | .hljs-string, 16 | .hljs-variable, 17 | .hljs-template-variable, 18 | .hljs-symbol, 19 | .hljs-bullet, 20 | .hljs-section, 21 | .hljs-addition, 22 | .hljs-attribute, 23 | .hljs-link { 24 | color: #888; 25 | } 26 | 27 | .hljs-comment, 28 | .hljs-quote, 29 | .hljs-meta, 30 | .hljs-deletion { 31 | color: #ccc; 32 | } 33 | 34 | .hljs-keyword, 35 | .hljs-selector-tag, 36 | .hljs-section, 37 | .hljs-name, 38 | .hljs-type, 39 | .hljs-strong { 40 | font-weight: bold; 41 | } 42 | 43 | .hljs-emphasis { 44 | font-style: italic; 45 | } 46 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/brown-paper.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Brown Paper style from goldblog.com.ua (c) Zaripov Yura 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background:#b7a68e url(./brown-papersq.png); 12 | } 13 | 14 | .hljs-keyword, 15 | .hljs-selector-tag, 16 | .hljs-literal { 17 | color:#005599; 18 | font-weight:bold; 19 | } 20 | 21 | .hljs, 22 | .hljs-subst { 23 | color: #363c69; 24 | } 25 | 26 | .hljs-string, 27 | .hljs-title, 28 | .hljs-section, 29 | .hljs-type, 30 | .hljs-attribute, 31 | .hljs-symbol, 32 | .hljs-bullet, 33 | .hljs-built_in, 34 | .hljs-addition, 35 | .hljs-variable, 36 | .hljs-template-tag, 37 | .hljs-template-variable, 38 | .hljs-link, 39 | .hljs-name { 40 | color: #2c009f; 41 | } 42 | 43 | .hljs-comment, 44 | .hljs-quote, 45 | .hljs-meta, 46 | .hljs-deletion { 47 | color: #802022; 48 | } 49 | 50 | .hljs-keyword, 51 | .hljs-selector-tag, 52 | .hljs-literal, 53 | .hljs-doctag, 54 | .hljs-title, 55 | .hljs-section, 56 | .hljs-type, 57 | .hljs-name, 58 | .hljs-strong { 59 | font-weight: bold; 60 | } 61 | 62 | .hljs-emphasis { 63 | font-style: italic; 64 | } 65 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/brown-papersq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/brown-papersq.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/codepen-embed.css: -------------------------------------------------------------------------------- 1 | /* 2 | codepen.io Embed Theme 3 | Author: Justin Perry 4 | Original theme - https://github.com/chriskempson/tomorrow-theme 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background: #222; 12 | color: #fff; 13 | } 14 | 15 | .hljs-comment, 16 | .hljs-quote { 17 | color: #777; 18 | } 19 | 20 | .hljs-variable, 21 | .hljs-template-variable, 22 | .hljs-tag, 23 | .hljs-regexp, 24 | .hljs-meta, 25 | .hljs-number, 26 | .hljs-built_in, 27 | .hljs-builtin-name, 28 | .hljs-literal, 29 | .hljs-params, 30 | .hljs-symbol, 31 | .hljs-bullet, 32 | .hljs-link, 33 | .hljs-deletion { 34 | color: #ab875d; 35 | } 36 | 37 | .hljs-section, 38 | .hljs-title, 39 | .hljs-name, 40 | .hljs-selector-id, 41 | .hljs-selector-class, 42 | .hljs-type, 43 | .hljs-attribute { 44 | color: #9b869b; 45 | } 46 | 47 | .hljs-string, 48 | .hljs-keyword, 49 | .hljs-selector-tag, 50 | .hljs-addition { 51 | color: #8f9c6c; 52 | } 53 | 54 | .hljs-emphasis { 55 | font-style: italic; 56 | } 57 | 58 | .hljs-strong { 59 | font-weight: bold; 60 | } 61 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/color-brewer.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Colorbrewer theme 4 | Original: https://github.com/mbostock/colorbrewer-theme (c) Mike Bostock 5 | Ported by Fabrício Tavares de Oliveira 6 | 7 | */ 8 | 9 | .hljs { 10 | display: block; 11 | overflow-x: auto; 12 | padding: 0.5em; 13 | background: #fff; 14 | } 15 | 16 | .hljs, 17 | .hljs-subst { 18 | color: #000; 19 | } 20 | 21 | .hljs-string, 22 | .hljs-meta, 23 | .hljs-symbol, 24 | .hljs-template-tag, 25 | .hljs-template-variable, 26 | .hljs-addition { 27 | color: #756bb1; 28 | } 29 | 30 | .hljs-comment, 31 | .hljs-quote { 32 | color: #636363; 33 | } 34 | 35 | .hljs-number, 36 | .hljs-regexp, 37 | .hljs-literal, 38 | .hljs-bullet, 39 | .hljs-link { 40 | color: #31a354; 41 | } 42 | 43 | .hljs-deletion, 44 | .hljs-variable { 45 | color: #88f; 46 | } 47 | 48 | 49 | 50 | .hljs-keyword, 51 | .hljs-selector-tag, 52 | .hljs-title, 53 | .hljs-section, 54 | .hljs-built_in, 55 | .hljs-doctag, 56 | .hljs-type, 57 | .hljs-tag, 58 | .hljs-name, 59 | .hljs-selector-id, 60 | .hljs-selector-class, 61 | .hljs-strong { 62 | color: #3182bd; 63 | } 64 | 65 | .hljs-emphasis { 66 | font-style: italic; 67 | } 68 | 69 | .hljs-attribute { 70 | color: #e6550d; 71 | } 72 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/darcula.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Darcula color scheme from the JetBrains family of IDEs 4 | 5 | */ 6 | 7 | 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #2b2b2b; 13 | } 14 | 15 | .hljs { 16 | color: #bababa; 17 | } 18 | 19 | .hljs-strong, 20 | .hljs-emphasis { 21 | color: #a8a8a2; 22 | } 23 | 24 | .hljs-bullet, 25 | .hljs-quote, 26 | .hljs-link, 27 | .hljs-number, 28 | .hljs-regexp, 29 | .hljs-literal { 30 | color: #6896ba; 31 | } 32 | 33 | .hljs-code, 34 | .hljs-selector-class { 35 | color: #a6e22e; 36 | } 37 | 38 | .hljs-emphasis { 39 | font-style: italic; 40 | } 41 | 42 | .hljs-keyword, 43 | .hljs-selector-tag, 44 | .hljs-section, 45 | .hljs-attribute, 46 | .hljs-name, 47 | .hljs-variable { 48 | color: #cb7832; 49 | } 50 | 51 | .hljs-params { 52 | color: #b9b9b9; 53 | } 54 | 55 | .hljs-string { 56 | color: #6a8759; 57 | } 58 | 59 | .hljs-subst, 60 | .hljs-type, 61 | .hljs-built_in, 62 | .hljs-builtin-name, 63 | .hljs-symbol, 64 | .hljs-selector-id, 65 | .hljs-selector-attr, 66 | .hljs-selector-pseudo, 67 | .hljs-template-tag, 68 | .hljs-template-variable, 69 | .hljs-addition { 70 | color: #e0c46c; 71 | } 72 | 73 | .hljs-comment, 74 | .hljs-deletion, 75 | .hljs-meta { 76 | color: #7f7f7f; 77 | } 78 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Dark style from softwaremaniacs.org (c) Ivan Sagalaev 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background: #444; 12 | } 13 | 14 | .hljs-keyword, 15 | .hljs-selector-tag, 16 | .hljs-literal, 17 | .hljs-section, 18 | .hljs-link { 19 | color: white; 20 | } 21 | 22 | .hljs, 23 | .hljs-subst { 24 | color: #ddd; 25 | } 26 | 27 | .hljs-string, 28 | .hljs-title, 29 | .hljs-name, 30 | .hljs-type, 31 | .hljs-attribute, 32 | .hljs-symbol, 33 | .hljs-bullet, 34 | .hljs-built_in, 35 | .hljs-addition, 36 | .hljs-variable, 37 | .hljs-template-tag, 38 | .hljs-template-variable { 39 | color: #d88; 40 | } 41 | 42 | .hljs-comment, 43 | .hljs-quote, 44 | .hljs-deletion, 45 | .hljs-meta { 46 | color: #777; 47 | } 48 | 49 | .hljs-keyword, 50 | .hljs-selector-tag, 51 | .hljs-literal, 52 | .hljs-title, 53 | .hljs-section, 54 | .hljs-doctag, 55 | .hljs-type, 56 | .hljs-name, 57 | .hljs-strong { 58 | font-weight: bold; 59 | } 60 | 61 | .hljs-emphasis { 62 | font-style: italic; 63 | } 64 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/darkula.css: -------------------------------------------------------------------------------- 1 | /* 2 | Deprecated due to a typo in the name and left here for compatibility purpose only. 3 | Please use darcula.css instead. 4 | */ 5 | 6 | @import url('darcula.css'); 7 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/dracula.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Dracula Theme v1.2.0 4 | 5 | https://github.com/zenorocha/dracula-theme 6 | 7 | Copyright 2015, All rights reserved 8 | 9 | Code licensed under the MIT license 10 | http://zenorocha.mit-license.org 11 | 12 | @author Éverton Ribeiro 13 | @author Zeno Rocha 14 | 15 | */ 16 | 17 | .hljs { 18 | display: block; 19 | overflow-x: auto; 20 | padding: 0.5em; 21 | background: #282a36; 22 | } 23 | 24 | .hljs-keyword, 25 | .hljs-selector-tag, 26 | .hljs-literal, 27 | .hljs-section, 28 | .hljs-link { 29 | color: #8be9fd; 30 | } 31 | 32 | .hljs-function .hljs-keyword { 33 | color: #ff79c6; 34 | } 35 | 36 | .hljs, 37 | .hljs-subst { 38 | color: #f8f8f2; 39 | } 40 | 41 | .hljs-string, 42 | .hljs-title, 43 | .hljs-name, 44 | .hljs-type, 45 | .hljs-attribute, 46 | .hljs-symbol, 47 | .hljs-bullet, 48 | .hljs-addition, 49 | .hljs-variable, 50 | .hljs-template-tag, 51 | .hljs-template-variable { 52 | color: #f1fa8c; 53 | } 54 | 55 | .hljs-comment, 56 | .hljs-quote, 57 | .hljs-deletion, 58 | .hljs-meta { 59 | color: #6272a4; 60 | } 61 | 62 | .hljs-keyword, 63 | .hljs-selector-tag, 64 | .hljs-literal, 65 | .hljs-title, 66 | .hljs-section, 67 | .hljs-doctag, 68 | .hljs-type, 69 | .hljs-name, 70 | .hljs-strong { 71 | font-weight: bold; 72 | } 73 | 74 | .hljs-emphasis { 75 | font-style: italic; 76 | } 77 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/far.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | FAR Style (c) MajestiC 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background: #000080; 12 | } 13 | 14 | .hljs, 15 | .hljs-subst { 16 | color: #0ff; 17 | } 18 | 19 | .hljs-string, 20 | .hljs-attribute, 21 | .hljs-symbol, 22 | .hljs-bullet, 23 | .hljs-built_in, 24 | .hljs-builtin-name, 25 | .hljs-template-tag, 26 | .hljs-template-variable, 27 | .hljs-addition { 28 | color: #ff0; 29 | } 30 | 31 | .hljs-keyword, 32 | .hljs-selector-tag, 33 | .hljs-section, 34 | .hljs-type, 35 | .hljs-name, 36 | .hljs-selector-id, 37 | .hljs-selector-class, 38 | .hljs-variable { 39 | color: #fff; 40 | } 41 | 42 | .hljs-comment, 43 | .hljs-quote, 44 | .hljs-doctag, 45 | .hljs-deletion { 46 | color: #888; 47 | } 48 | 49 | .hljs-number, 50 | .hljs-regexp, 51 | .hljs-literal, 52 | .hljs-link { 53 | color: #0f0; 54 | } 55 | 56 | .hljs-meta { 57 | color: #008080; 58 | } 59 | 60 | .hljs-keyword, 61 | .hljs-selector-tag, 62 | .hljs-title, 63 | .hljs-section, 64 | .hljs-name, 65 | .hljs-strong { 66 | font-weight: bold; 67 | } 68 | 69 | .hljs-emphasis { 70 | font-style: italic; 71 | } 72 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/github-gist.css: -------------------------------------------------------------------------------- 1 | /** 2 | * GitHub Gist Theme 3 | * Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro 4 | */ 5 | 6 | .hljs { 7 | display: block; 8 | background: white; 9 | padding: 0.5em; 10 | color: #333333; 11 | overflow-x: auto; 12 | } 13 | 14 | .hljs-comment, 15 | .hljs-meta { 16 | color: #969896; 17 | } 18 | 19 | .hljs-string, 20 | .hljs-variable, 21 | .hljs-template-variable, 22 | .hljs-strong, 23 | .hljs-emphasis, 24 | .hljs-quote { 25 | color: #df5000; 26 | } 27 | 28 | .hljs-keyword, 29 | .hljs-selector-tag, 30 | .hljs-type { 31 | color: #a71d5d; 32 | } 33 | 34 | .hljs-literal, 35 | .hljs-symbol, 36 | .hljs-bullet, 37 | .hljs-attribute { 38 | color: #0086b3; 39 | } 40 | 41 | .hljs-section, 42 | .hljs-name { 43 | color: #63a35c; 44 | } 45 | 46 | .hljs-tag { 47 | color: #333333; 48 | } 49 | 50 | .hljs-title, 51 | .hljs-attr, 52 | .hljs-selector-id, 53 | .hljs-selector-class, 54 | .hljs-selector-attr, 55 | .hljs-selector-pseudo { 56 | color: #795da3; 57 | } 58 | 59 | .hljs-addition { 60 | color: #55a532; 61 | background-color: #eaffea; 62 | } 63 | 64 | .hljs-deletion { 65 | color: #bd2c00; 66 | background-color: #ffecec; 67 | } 68 | 69 | .hljs-link { 70 | text-decoration: underline; 71 | } 72 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/ir-black.css: -------------------------------------------------------------------------------- 1 | /* 2 | IR_Black style (c) Vasily Mikhailitchenko 3 | */ 4 | 5 | .hljs { 6 | display: block; 7 | overflow-x: auto; 8 | padding: 0.5em; 9 | background: #000; 10 | color: #f8f8f8; 11 | } 12 | 13 | .hljs-comment, 14 | .hljs-quote, 15 | .hljs-meta { 16 | color: #7c7c7c; 17 | } 18 | 19 | .hljs-keyword, 20 | .hljs-selector-tag, 21 | .hljs-tag, 22 | .hljs-name { 23 | color: #96cbfe; 24 | } 25 | 26 | .hljs-attribute, 27 | .hljs-selector-id { 28 | color: #ffffb6; 29 | } 30 | 31 | .hljs-string, 32 | .hljs-selector-attr, 33 | .hljs-selector-pseudo, 34 | .hljs-addition { 35 | color: #a8ff60; 36 | } 37 | 38 | .hljs-subst { 39 | color: #daefa3; 40 | } 41 | 42 | .hljs-regexp, 43 | .hljs-link { 44 | color: #e9c062; 45 | } 46 | 47 | .hljs-title, 48 | .hljs-section, 49 | .hljs-type, 50 | .hljs-doctag { 51 | color: #ffffb6; 52 | } 53 | 54 | .hljs-symbol, 55 | .hljs-bullet, 56 | .hljs-variable, 57 | .hljs-template-variable, 58 | .hljs-literal { 59 | color: #c6c5fe; 60 | } 61 | 62 | .hljs-number, 63 | .hljs-deletion { 64 | color:#ff73fd; 65 | } 66 | 67 | .hljs-emphasis { 68 | font-style: italic; 69 | } 70 | 71 | .hljs-strong { 72 | font-weight: bold; 73 | } 74 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/magula.css: -------------------------------------------------------------------------------- 1 | /* 2 | Description: Magula style for highligh.js 3 | Author: Ruslan Keba 4 | Website: http://rukeba.com/ 5 | Version: 1.0 6 | Date: 2009-01-03 7 | Music: Aphex Twin / Xtal 8 | */ 9 | 10 | .hljs { 11 | display: block; 12 | overflow-x: auto; 13 | padding: 0.5em; 14 | background-color: #f4f4f4; 15 | } 16 | 17 | .hljs, 18 | .hljs-subst { 19 | color: black; 20 | } 21 | 22 | .hljs-string, 23 | .hljs-title, 24 | .hljs-symbol, 25 | .hljs-bullet, 26 | .hljs-attribute, 27 | .hljs-addition, 28 | .hljs-variable, 29 | .hljs-template-tag, 30 | .hljs-template-variable { 31 | color: #050; 32 | } 33 | 34 | .hljs-comment, 35 | .hljs-quote { 36 | color: #777; 37 | } 38 | 39 | .hljs-number, 40 | .hljs-regexp, 41 | .hljs-literal, 42 | .hljs-type, 43 | .hljs-link { 44 | color: #800; 45 | } 46 | 47 | .hljs-deletion, 48 | .hljs-meta { 49 | color: #00e; 50 | } 51 | 52 | .hljs-keyword, 53 | .hljs-selector-tag, 54 | .hljs-doctag, 55 | .hljs-title, 56 | .hljs-section, 57 | .hljs-built_in, 58 | .hljs-tag, 59 | .hljs-name { 60 | font-weight: bold; 61 | color: navy; 62 | } 63 | 64 | .hljs-emphasis { 65 | font-style: italic; 66 | } 67 | 68 | .hljs-strong { 69 | font-weight: bold; 70 | } 71 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/mono-blue.css: -------------------------------------------------------------------------------- 1 | /* 2 | Five-color theme from a single blue hue. 3 | */ 4 | .hljs { 5 | display: block; 6 | overflow-x: auto; 7 | padding: 0.5em; 8 | background: #eaeef3; 9 | } 10 | 11 | .hljs { 12 | color: #00193a; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag, 17 | .hljs-title, 18 | .hljs-section, 19 | .hljs-doctag, 20 | .hljs-name, 21 | .hljs-strong { 22 | font-weight: bold; 23 | } 24 | 25 | .hljs-comment { 26 | color: #738191; 27 | } 28 | 29 | .hljs-string, 30 | .hljs-title, 31 | .hljs-section, 32 | .hljs-built_in, 33 | .hljs-literal, 34 | .hljs-type, 35 | .hljs-addition, 36 | .hljs-tag, 37 | .hljs-quote, 38 | .hljs-name, 39 | .hljs-selector-id, 40 | .hljs-selector-class { 41 | color: #0048ab; 42 | } 43 | 44 | .hljs-meta, 45 | .hljs-subst, 46 | .hljs-symbol, 47 | .hljs-regexp, 48 | .hljs-attribute, 49 | .hljs-deletion, 50 | .hljs-variable, 51 | .hljs-template-variable, 52 | .hljs-link, 53 | .hljs-bullet { 54 | color: #4c81c9; 55 | } 56 | 57 | .hljs-emphasis { 58 | font-style: italic; 59 | } 60 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/monokai.css: -------------------------------------------------------------------------------- 1 | /* 2 | Monokai style - ported by Luigi Maselli - http://grigio.org 3 | */ 4 | 5 | .hljs { 6 | display: block; 7 | overflow-x: auto; 8 | padding: 0.5em; 9 | background: #272822; color: #ddd; 10 | } 11 | 12 | .hljs-tag, 13 | .hljs-keyword, 14 | .hljs-selector-tag, 15 | .hljs-literal, 16 | .hljs-strong, 17 | .hljs-name { 18 | color: #f92672; 19 | } 20 | 21 | .hljs-code { 22 | color: #66d9ef; 23 | } 24 | 25 | .hljs-class .hljs-title { 26 | color: white; 27 | } 28 | 29 | .hljs-attribute, 30 | .hljs-symbol, 31 | .hljs-regexp, 32 | .hljs-link { 33 | color: #bf79db; 34 | } 35 | 36 | .hljs-string, 37 | .hljs-bullet, 38 | .hljs-subst, 39 | .hljs-title, 40 | .hljs-section, 41 | .hljs-emphasis, 42 | .hljs-type, 43 | .hljs-built_in, 44 | .hljs-builtin-name, 45 | .hljs-selector-attr, 46 | .hljs-selector-pseudo, 47 | .hljs-addition, 48 | .hljs-variable, 49 | .hljs-template-tag, 50 | .hljs-template-variable { 51 | color: #a6e22e; 52 | } 53 | 54 | .hljs-comment, 55 | .hljs-quote, 56 | .hljs-deletion, 57 | .hljs-meta { 58 | color: #75715e; 59 | } 60 | 61 | .hljs-keyword, 62 | .hljs-selector-tag, 63 | .hljs-literal, 64 | .hljs-doctag, 65 | .hljs-title, 66 | .hljs-section, 67 | .hljs-type, 68 | .hljs-selector-id { 69 | font-weight: bold; 70 | } 71 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/ocean.css: -------------------------------------------------------------------------------- 1 | /* Ocean Dark Theme */ 2 | /* https://github.com/gavsiu */ 3 | /* Original theme - https://github.com/chriskempson/base16 */ 4 | 5 | /* Ocean Comment */ 6 | .hljs-comment, 7 | .hljs-quote { 8 | color: #65737e; 9 | } 10 | 11 | /* Ocean Red */ 12 | .hljs-variable, 13 | .hljs-template-variable, 14 | .hljs-tag, 15 | .hljs-name, 16 | .hljs-selector-id, 17 | .hljs-selector-class, 18 | .hljs-regexp, 19 | .hljs-deletion { 20 | color: #bf616a; 21 | } 22 | 23 | /* Ocean Orange */ 24 | .hljs-number, 25 | .hljs-built_in, 26 | .hljs-builtin-name, 27 | .hljs-literal, 28 | .hljs-type, 29 | .hljs-params, 30 | .hljs-meta, 31 | .hljs-link { 32 | color: #d08770; 33 | } 34 | 35 | /* Ocean Yellow */ 36 | .hljs-attribute { 37 | color: #ebcb8b; 38 | } 39 | 40 | /* Ocean Green */ 41 | .hljs-string, 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-addition { 45 | color: #a3be8c; 46 | } 47 | 48 | /* Ocean Blue */ 49 | .hljs-title, 50 | .hljs-section { 51 | color: #8fa1b3; 52 | } 53 | 54 | /* Ocean Purple */ 55 | .hljs-keyword, 56 | .hljs-selector-tag { 57 | color: #b48ead; 58 | } 59 | 60 | .hljs { 61 | display: block; 62 | overflow-x: auto; 63 | background: #2b303b; 64 | color: #c0c5ce; 65 | padding: 0.5em; 66 | } 67 | 68 | .hljs-emphasis { 69 | font-style: italic; 70 | } 71 | 72 | .hljs-strong { 73 | font-weight: bold; 74 | } 75 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/paraiso-dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | Paraíso (dark) 3 | Created by Jan T. Sott (http://github.com/idleberg) 4 | Inspired by the art of Rubens LP (http://www.rubenslp.com.br) 5 | */ 6 | 7 | /* Paraíso Comment */ 8 | .hljs-comment, 9 | .hljs-quote { 10 | color: #8d8687; 11 | } 12 | 13 | /* Paraíso Red */ 14 | .hljs-variable, 15 | .hljs-template-variable, 16 | .hljs-tag, 17 | .hljs-name, 18 | .hljs-selector-id, 19 | .hljs-selector-class, 20 | .hljs-regexp, 21 | .hljs-link, 22 | .hljs-meta { 23 | color: #ef6155; 24 | } 25 | 26 | /* Paraíso Orange */ 27 | .hljs-number, 28 | .hljs-built_in, 29 | .hljs-builtin-name, 30 | .hljs-literal, 31 | .hljs-type, 32 | .hljs-params, 33 | .hljs-deletion { 34 | color: #f99b15; 35 | } 36 | 37 | /* Paraíso Yellow */ 38 | .hljs-title, 39 | .hljs-section, 40 | .hljs-attribute { 41 | color: #fec418; 42 | } 43 | 44 | /* Paraíso Green */ 45 | .hljs-string, 46 | .hljs-symbol, 47 | .hljs-bullet, 48 | .hljs-addition { 49 | color: #48b685; 50 | } 51 | 52 | /* Paraíso Purple */ 53 | .hljs-keyword, 54 | .hljs-selector-tag { 55 | color: #815ba4; 56 | } 57 | 58 | .hljs { 59 | display: block; 60 | overflow-x: auto; 61 | background: #2f1e2e; 62 | color: #a39e9b; 63 | padding: 0.5em; 64 | } 65 | 66 | .hljs-emphasis { 67 | font-style: italic; 68 | } 69 | 70 | .hljs-strong { 71 | font-weight: bold; 72 | } 73 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/paraiso-light.css: -------------------------------------------------------------------------------- 1 | /* 2 | Paraíso (light) 3 | Created by Jan T. Sott (http://github.com/idleberg) 4 | Inspired by the art of Rubens LP (http://www.rubenslp.com.br) 5 | */ 6 | 7 | /* Paraíso Comment */ 8 | .hljs-comment, 9 | .hljs-quote { 10 | color: #776e71; 11 | } 12 | 13 | /* Paraíso Red */ 14 | .hljs-variable, 15 | .hljs-template-variable, 16 | .hljs-tag, 17 | .hljs-name, 18 | .hljs-selector-id, 19 | .hljs-selector-class, 20 | .hljs-regexp, 21 | .hljs-link, 22 | .hljs-meta { 23 | color: #ef6155; 24 | } 25 | 26 | /* Paraíso Orange */ 27 | .hljs-number, 28 | .hljs-built_in, 29 | .hljs-builtin-name, 30 | .hljs-literal, 31 | .hljs-type, 32 | .hljs-params, 33 | .hljs-deletion { 34 | color: #f99b15; 35 | } 36 | 37 | /* Paraíso Yellow */ 38 | .hljs-title, 39 | .hljs-section, 40 | .hljs-attribute { 41 | color: #fec418; 42 | } 43 | 44 | /* Paraíso Green */ 45 | .hljs-string, 46 | .hljs-symbol, 47 | .hljs-bullet, 48 | .hljs-addition { 49 | color: #48b685; 50 | } 51 | 52 | /* Paraíso Purple */ 53 | .hljs-keyword, 54 | .hljs-selector-tag { 55 | color: #815ba4; 56 | } 57 | 58 | .hljs { 59 | display: block; 60 | overflow-x: auto; 61 | background: #e7e9db; 62 | color: #4f424c; 63 | padding: 0.5em; 64 | } 65 | 66 | .hljs-emphasis { 67 | font-style: italic; 68 | } 69 | 70 | .hljs-strong { 71 | font-weight: bold; 72 | } 73 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/pojoaque.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/pojoaque.jpg -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/qtcreator_dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Qt Creator dark color scheme 4 | 5 | */ 6 | 7 | 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #000000; 13 | } 14 | 15 | .hljs, 16 | .hljs-subst, 17 | .hljs-tag, 18 | .hljs-title { 19 | color: #aaaaaa; 20 | } 21 | 22 | .hljs-strong, 23 | .hljs-emphasis { 24 | color: #a8a8a2; 25 | } 26 | 27 | .hljs-bullet, 28 | .hljs-quote, 29 | .hljs-number, 30 | .hljs-regexp, 31 | .hljs-literal { 32 | color: #ff55ff; 33 | } 34 | 35 | .hljs-code 36 | .hljs-selector-class { 37 | color: #aaaaff; 38 | } 39 | 40 | .hljs-emphasis, 41 | .hljs-stronge, 42 | .hljs-type { 43 | font-style: italic; 44 | } 45 | 46 | .hljs-keyword, 47 | .hljs-selector-tag, 48 | .hljs-function, 49 | .hljs-section, 50 | .hljs-symbol, 51 | .hljs-name { 52 | color: #ffff55; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #ff5555; 57 | } 58 | 59 | .hljs-variable, 60 | .hljs-params, 61 | .hljs-class .hljs-title { 62 | color: #8888ff; 63 | } 64 | 65 | .hljs-string, 66 | .hljs-selector-id, 67 | .hljs-selector-attr, 68 | .hljs-selector-pseudo, 69 | .hljs-type, 70 | .hljs-built_in, 71 | .hljs-builtin-name, 72 | .hljs-template-tag, 73 | .hljs-template-variable, 74 | .hljs-addition, 75 | .hljs-link { 76 | color: #ff55ff; 77 | } 78 | 79 | .hljs-comment, 80 | .hljs-meta, 81 | .hljs-deletion { 82 | color: #55ffff; 83 | } 84 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/qtcreator_light.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Qt Creator light color scheme 4 | 5 | */ 6 | 7 | 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #ffffff; 13 | } 14 | 15 | .hljs, 16 | .hljs-subst, 17 | .hljs-tag, 18 | .hljs-title { 19 | color: #000000; 20 | } 21 | 22 | .hljs-strong, 23 | .hljs-emphasis { 24 | color: #000000; 25 | } 26 | 27 | .hljs-bullet, 28 | .hljs-quote, 29 | .hljs-number, 30 | .hljs-regexp, 31 | .hljs-literal { 32 | color: #000080; 33 | } 34 | 35 | .hljs-code 36 | .hljs-selector-class { 37 | color: #800080; 38 | } 39 | 40 | .hljs-emphasis, 41 | .hljs-stronge, 42 | .hljs-type { 43 | font-style: italic; 44 | } 45 | 46 | .hljs-keyword, 47 | .hljs-selector-tag, 48 | .hljs-function, 49 | .hljs-section, 50 | .hljs-symbol, 51 | .hljs-name { 52 | color: #808000; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #800000; 57 | } 58 | 59 | .hljs-variable, 60 | .hljs-params, 61 | .hljs-class .hljs-title { 62 | color: #0055AF; 63 | } 64 | 65 | .hljs-string, 66 | .hljs-selector-id, 67 | .hljs-selector-attr, 68 | .hljs-selector-pseudo, 69 | .hljs-type, 70 | .hljs-built_in, 71 | .hljs-builtin-name, 72 | .hljs-template-tag, 73 | .hljs-template-variable, 74 | .hljs-addition, 75 | .hljs-link { 76 | color: #008000; 77 | } 78 | 79 | .hljs-comment, 80 | .hljs-meta, 81 | .hljs-deletion { 82 | color: #008000; 83 | } 84 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/rainbow.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Style with support for rainbow parens 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background: #474949; 12 | color: #d1d9e1; 13 | } 14 | 15 | 16 | .hljs-comment, 17 | .hljs-quote { 18 | color: #969896; 19 | font-style: italic; 20 | } 21 | 22 | .hljs-keyword, 23 | .hljs-selector-tag, 24 | .hljs-literal, 25 | .hljs-type, 26 | .hljs-addition { 27 | color: #cc99cc; 28 | } 29 | 30 | .hljs-number, 31 | .hljs-selector-attr, 32 | .hljs-selector-pseudo { 33 | color: #f99157; 34 | } 35 | 36 | .hljs-string, 37 | .hljs-doctag, 38 | .hljs-regexp { 39 | color: #8abeb7; 40 | } 41 | 42 | .hljs-title, 43 | .hljs-name, 44 | .hljs-section, 45 | .hljs-built_in { 46 | color: #b5bd68; 47 | } 48 | 49 | .hljs-variable, 50 | .hljs-template-variable, 51 | .hljs-selector-id, 52 | .hljs-class .hljs-title { 53 | color: #ffcc66; 54 | } 55 | 56 | .hljs-section, 57 | .hljs-name, 58 | .hljs-strong { 59 | font-weight: bold; 60 | } 61 | 62 | .hljs-symbol, 63 | .hljs-bullet, 64 | .hljs-subst, 65 | .hljs-meta, 66 | .hljs-link { 67 | color: #f99157; 68 | } 69 | 70 | .hljs-deletion { 71 | color: #dc322f; 72 | } 73 | 74 | .hljs-formula { 75 | background: #eee8d5; 76 | } 77 | 78 | .hljs-attr, 79 | .hljs-attribute { 80 | color: #81a2be; 81 | } 82 | 83 | .hljs-emphasis { 84 | font-style: italic; 85 | } 86 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/school-book.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | School Book style from goldblog.com.ua (c) Zaripov Yura 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 15px 0.5em 0.5em 30px; 11 | font-size: 11px; 12 | line-height:16px; 13 | } 14 | 15 | pre{ 16 | background:#f6f6ae url(./school-book.png); 17 | border-top: solid 2px #d2e8b9; 18 | border-bottom: solid 1px #d2e8b9; 19 | } 20 | 21 | .hljs-keyword, 22 | .hljs-selector-tag, 23 | .hljs-literal { 24 | color:#005599; 25 | font-weight:bold; 26 | } 27 | 28 | .hljs, 29 | .hljs-subst { 30 | color: #3e5915; 31 | } 32 | 33 | .hljs-string, 34 | .hljs-title, 35 | .hljs-section, 36 | .hljs-type, 37 | .hljs-symbol, 38 | .hljs-bullet, 39 | .hljs-attribute, 40 | .hljs-built_in, 41 | .hljs-builtin-name, 42 | .hljs-addition, 43 | .hljs-variable, 44 | .hljs-template-tag, 45 | .hljs-template-variable, 46 | .hljs-link { 47 | color: #2c009f; 48 | } 49 | 50 | .hljs-comment, 51 | .hljs-quote, 52 | .hljs-deletion, 53 | .hljs-meta { 54 | color: #e60415; 55 | } 56 | 57 | .hljs-keyword, 58 | .hljs-selector-tag, 59 | .hljs-literal, 60 | .hljs-doctag, 61 | .hljs-title, 62 | .hljs-section, 63 | .hljs-type, 64 | .hljs-name, 65 | .hljs-selector-id, 66 | .hljs-strong { 67 | font-weight: bold; 68 | } 69 | 70 | .hljs-emphasis { 71 | font-style: italic; 72 | } 73 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/school-book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howlingproject/libqa/4688caf7368c4a9607189dcaffc30cec74073107/src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/school-book.png -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/tomorrow.css: -------------------------------------------------------------------------------- 1 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 2 | 3 | /* Tomorrow Comment */ 4 | .hljs-comment, 5 | .hljs-quote { 6 | color: #8e908c; 7 | } 8 | 9 | /* Tomorrow Red */ 10 | .hljs-variable, 11 | .hljs-template-variable, 12 | .hljs-tag, 13 | .hljs-name, 14 | .hljs-selector-id, 15 | .hljs-selector-class, 16 | .hljs-regexp, 17 | .hljs-deletion { 18 | color: #c82829; 19 | } 20 | 21 | /* Tomorrow Orange */ 22 | .hljs-number, 23 | .hljs-built_in, 24 | .hljs-builtin-name, 25 | .hljs-literal, 26 | .hljs-type, 27 | .hljs-params, 28 | .hljs-meta, 29 | .hljs-link { 30 | color: #f5871f; 31 | } 32 | 33 | /* Tomorrow Yellow */ 34 | .hljs-attribute { 35 | color: #eab700; 36 | } 37 | 38 | /* Tomorrow Green */ 39 | .hljs-string, 40 | .hljs-symbol, 41 | .hljs-bullet, 42 | .hljs-addition { 43 | color: #718c00; 44 | } 45 | 46 | /* Tomorrow Blue */ 47 | .hljs-title, 48 | .hljs-section { 49 | color: #4271ae; 50 | } 51 | 52 | /* Tomorrow Purple */ 53 | .hljs-keyword, 54 | .hljs-selector-tag { 55 | color: #8959a8; 56 | } 57 | 58 | .hljs { 59 | display: block; 60 | overflow-x: auto; 61 | background: white; 62 | color: #4d4d4c; 63 | padding: 0.5em; 64 | } 65 | 66 | .hljs-emphasis { 67 | font-style: italic; 68 | } 69 | 70 | .hljs-strong { 71 | font-weight: bold; 72 | } 73 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/vs.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Visual Studio-like style based on original C# coloring by Jason Diamond 4 | 5 | */ 6 | .hljs { 7 | display: block; 8 | overflow-x: auto; 9 | padding: 0.5em; 10 | background: white; 11 | color: black; 12 | } 13 | 14 | .hljs-comment, 15 | .hljs-quote, 16 | .hljs-variable { 17 | color: #008000; 18 | } 19 | 20 | .hljs-keyword, 21 | .hljs-selector-tag, 22 | .hljs-built_in, 23 | .hljs-name, 24 | .hljs-tag { 25 | color: #00f; 26 | } 27 | 28 | .hljs-string, 29 | .hljs-title, 30 | .hljs-section, 31 | .hljs-attribute, 32 | .hljs-literal, 33 | .hljs-template-tag, 34 | .hljs-template-variable, 35 | .hljs-type, 36 | .hljs-addition { 37 | color: #a31515; 38 | } 39 | 40 | .hljs-deletion, 41 | .hljs-selector-attr, 42 | .hljs-selector-pseudo, 43 | .hljs-meta { 44 | color: #2b91af; 45 | } 46 | 47 | .hljs-doctag { 48 | color: #808080; 49 | } 50 | 51 | .hljs-attr { 52 | color: #f00; 53 | } 54 | 55 | .hljs-symbol, 56 | .hljs-bullet, 57 | .hljs-link { 58 | color: #00b0e8; 59 | } 60 | 61 | 62 | .hljs-emphasis { 63 | font-style: italic; 64 | } 65 | 66 | .hljs-strong { 67 | font-weight: bold; 68 | } 69 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/syntaxhiglight/styles/zenburn.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Zenburn style from voldmar.ru (c) Vladimir Epifanov 4 | based on dark.css by Ivan Sagalaev 5 | 6 | */ 7 | 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #3f3f3f; 13 | color: #dcdcdc; 14 | } 15 | 16 | .hljs-keyword, 17 | .hljs-selector-tag, 18 | .hljs-tag { 19 | color: #e3ceab; 20 | } 21 | 22 | .hljs-template-tag { 23 | color: #dcdcdc; 24 | } 25 | 26 | .hljs-number { 27 | color: #8cd0d3; 28 | } 29 | 30 | .hljs-variable, 31 | .hljs-template-variable, 32 | .hljs-attribute { 33 | color: #efdcbc; 34 | } 35 | 36 | .hljs-literal { 37 | color: #efefaf; 38 | } 39 | 40 | .hljs-subst { 41 | color: #8f8f8f; 42 | } 43 | 44 | .hljs-title, 45 | .hljs-name, 46 | .hljs-selector-id, 47 | .hljs-selector-class, 48 | .hljs-section, 49 | .hljs-type { 50 | color: #efef8f; 51 | } 52 | 53 | .hljs-symbol, 54 | .hljs-bullet, 55 | .hljs-link { 56 | color: #dca3a3; 57 | } 58 | 59 | .hljs-deletion, 60 | .hljs-string, 61 | .hljs-built_in, 62 | .hljs-builtin-name { 63 | color: #cc9393; 64 | } 65 | 66 | .hljs-addition, 67 | .hljs-comment, 68 | .hljs-quote, 69 | .hljs-meta { 70 | color: #7f9f7f; 71 | } 72 | 73 | 74 | .hljs-emphasis { 75 | font-style: italic; 76 | } 77 | 78 | .hljs-strong { 79 | font-weight: bold; 80 | } 81 | -------------------------------------------------------------------------------- /src/main/webapp/resource/app/js/DualEditor/util/fn-editor-util.js: -------------------------------------------------------------------------------- 1 | (function() 2 | { 3 | /** 4 | * @description : 사용자의 브라우저를 판별한다. 5 | * @param : None 6 | * @return : String IE, FF, SC, OP 7 | * @example : $.clientBrowser(); 8 | */ 9 | jQuery.clientBrowser = function() 10 | { 11 | var client = ""; 12 | if(navigator.userAgent.toLowerCase().indexOf('msie') > -1){ // IE 13 | client = "IE"; 14 | }else{ 15 | client = "oher"; 16 | } 17 | return client; 18 | }; 19 | 20 | /** 21 | * @description : 화면에 레이어를 생성하여 출력한다. IE는 레이어, 기타는 console.log 를 사용한다. 22 | * @param : msg - 출력할 메시지 23 | * @return : None 24 | * @example : $.print('출력 메시지'); 25 | */ 26 | jQuery.print = function(msg){ 27 | var browser = $.clientBrowser(); 28 | if(browser == 'IE') { 29 | var $output = jQuery("#print-output"); 30 | 31 | if($output.length === 0) { 32 | $output = jQuery('