diff --git a/bower.json b/bower.json index c756b45e6..12eee0c96 100644 --- a/bower.json +++ b/bower.json @@ -44,7 +44,8 @@ "angular-sanitize": "latest", "moment": "latest", "angular-strap": "latest", - "datetimepicker": "latest" + "datetimepicker": "latest", + "angular-summernote": "latest" }, "overrides": { "jquery": { @@ -161,6 +162,9 @@ "build/css/bootstrap-datetimepicker.min.css", "build/js/bootstrap-datetimepicker.min.js" ] + }, + "angular-summernote": { + "main": "dist/angular-summernote.js" } }, "resolutions": { diff --git a/src/main/java/com/techlooper/config/CoreConfiguration.java b/src/main/java/com/techlooper/config/CoreConfiguration.java index 902961791..a2d52e915 100644 --- a/src/main/java/com/techlooper/config/CoreConfiguration.java +++ b/src/main/java/com/techlooper/config/CoreConfiguration.java @@ -61,472 +61,475 @@ @Configuration @ComponentScan(basePackages = "com.techlooper") @PropertySources({ - @PropertySource("classpath:techlooper.properties"), - @PropertySource("classpath:secret.properties")}) + @PropertySource("classpath:techlooper.properties"), + @PropertySource("classpath:secret.properties")}) @EnableScheduling @EnableAspectJAutoProxy @EnableCaching(proxyTargetClass = true) public class CoreConfiguration implements ApplicationContextAware { - @Resource - private Environment environment; - - @Value("${mail.techlooper.form}") - private String mailTechlooperForm; + @Resource + private Environment environment; + + @Value("${mail.techlooper.form}") + private String mailTechlooperForm; - @Value("${mail.techlooper.reply_to}") - private String mailTechlooperReplyTo; + @Value("${mail.techlooper.reply_to}") + private String mailTechlooperReplyTo; - @Value("${mail.form}") - private String mailForm; - - @Value("${mail.reply_to}") - private String mailReplyTo; - - @Value("${mail.citibank.cc_promotion.to}") - private String mailCitibankCreditCardPromotionTo; - - @Value("${mail.citibank.cc_promotion.subject}") - private String mailCitibankCreditCardPromotionSubject; - - @Value("classpath:vnwConfig.json") - private org.springframework.core.io.Resource vnwConfigRes; - - @Value("classpath:google-auth/techLooper.p12") - private org.springframework.core.io.Resource googleApiAuthResource; - - private ApplicationContext applicationContext; - - @Bean - public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { - PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); - configurer.setFileEncoding("UTF-8"); - return configurer; - } - - @Bean - public CacheManager cacheManager() { - CompositeCacheManager manager = new CompositeCacheManager(); - manager.setCacheManagers(Arrays.asList( - new ConcurrentMapCacheManager("SOCIAL_CONFIG"), - new ConcurrentMapCacheManager("COMMON_TERM"), - new ConcurrentMapCacheManager("SKILL_CONFIG"))); - return manager; - } - - @Bean - public RestTemplate restTemplate() { - return new RestTemplate(clientHttpRequestFactory()); - } - - @Bean - public MultipartResolver multipartResolver() { - CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); - multipartResolver.setMaxUploadSize(500000); - return multipartResolver; - } - - @Bean - public Mapper dozerBeanMapper() { - DozerBeanMapper dozerBeanMapper = new DozerBeanMapper(); - dozerBeanMapper.addMapping(new BeanMappingBuilder() { - protected void configure() { - mapping(FacebookProfile.class, com.techlooper.entity.FacebookProfile.class) - .fields("locale", "locale", FieldsMappingOptions.customConverter(LocaleConverter.class)); - - mapping(TwitterProfile.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) - .fields("name", "firstName", FieldsMappingOptions.copyByReference()) - .fields("screenName", "userName", FieldsMappingOptions.copyByReference()); - - mapping(GitHubUserProfile.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) - .fields("name", "firstName", FieldsMappingOptions.copyByReference()) - .fields("email", "emailAddress", FieldsMappingOptions.copyByReference()); - - mapping(Person.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) - .fields("givenName", "firstName", FieldsMappingOptions.copyByReference()) - .fields("familyName", "lastName", FieldsMappingOptions.copyByReference()) - .fields("accountEmail", "emailAddress", FieldsMappingOptions.copyByReference()) - .fields("imageUrl", "profileImageUrl", FieldsMappingOptions.copyByReference()); - - mapping(com.techlooper.entity.FacebookProfile.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) - .fields("email", "emailAddress", FieldsMappingOptions.copyByReference()); - - mapping(LinkedInProfile.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) - .fields("profilePictureUrl", "profileImageUrl", FieldsMappingOptions.copyByReference()); - - mapping(UserEntity.class, UserInfo.class, TypeMappingOptions.oneWay()) - .fields("profiles", "profileNames", FieldsMappingOptions.customConverter(ProfileNameConverter.class)); - - mapping(UserInfo.class, UserEntity.class, TypeMappingOptions.oneWay()) - .fields("profileNames", "profiles", FieldsMappingOptions.customConverter(ProfileNameConverter.class)); - - mapping(UserEntity.class, VnwUserProfile.class).exclude("accessGrant"); - - mapping(SalaryReviewEntity.class, VNWJobSearchRequest.class) - .fields("jobLevelIds", "jobLevel") - .fields("jobCategories", "jobCategories", FieldsMappingOptions.customConverter(ListCSVStringConverter.class)) - .fields("netSalary", "jobSalary") - .fields("locationId", "jobLocation"); - - mapping(VnwJobAlert.class, VnwJobAlertRequest.class) - .fields("jobLocations", "locationId", FieldsMappingOptions.customConverter(ListCSVStringConverter.class)) - .fields("minSalary", "netSalary"); - - mapping(WebinarInfoDto.class, WebinarEntity.class, TypeMappingOptions.oneWay()) - .exclude("createdDateTime"); - - mapping(ScrapeJobEntity.class, VNWJobSearchResponseDataItem.class) - .fields("jobTitle", "title") - .fields("jobTitleUrl", "url") - .fields("companyLogoUrl", "logoUrl") - .fields("createdDateTime", "postedOn"); - - mapping(ScrapeJobEntity.class, JobResponse.class) - .fields("jobTitle", "title") - .fields("jobTitleUrl", "url") - .fields("createdDateTime", "postedOn") - .fields("companyLogoUrl", "logoUrl"); - - mapping(ChallengeEntity.class, ChallengeDto.class) - .fields("startDateTime", "startDate") - .fields("submissionDateTime", "submissionDate") - .fields("registrationDateTime", "registrationDate") - .fields("ideaSubmissionDateTime", "ideaSubmissionDate") - .fields("uxSubmissionDateTime", "uxSubmissionDate") - .fields("prototypeSubmissionDateTime", "prototypeSubmissionDate"); - - } - }); - return dozerBeanMapper; - } - - @Bean - public TextEncryptor textEncryptor() { - BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); - textEncryptor.setPassword(environment.getProperty("core.textEncryptor.password")); - return textEncryptor; - } - - @Bean - public JavaMailSender mailSender() { - JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); - mailSender.setHost("localhost"); - mailSender.setPort(25); - - Properties javaMailProperties = new Properties(); - javaMailProperties.put("mail.transport.protocol", "smtp"); - mailSender.setJavaMailProperties(javaMailProperties); - return mailSender; - } - - @Bean - public SimpleMailMessage citibankCreditCardPromotionMailMessage() { - SimpleMailMessage mailMessage = new SimpleMailMessage(); - mailMessage.setFrom(mailForm); - mailMessage.setTo(mailCitibankCreditCardPromotionTo); - mailMessage.setReplyTo(mailReplyTo); - mailMessage.setSubject(mailCitibankCreditCardPromotionSubject); - return mailMessage; - } - - @Bean - public freemarker.template.Configuration freemakerConfig() throws IOException, URISyntaxException { - freemarker.template.Configuration cfg = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_22); - cfg.setDirectoryForTemplateLoading(Paths.get(this.getClass().getClassLoader().getResource("/template").toURI()).toFile()); - cfg.setDefaultEncoding("UTF-8"); - cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); - return cfg; - } - - @Bean - public Template citibankCreditCardPromotionTemplate(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("citibankCreditCardPromotion.ftl"); - return template; - } - - @Bean - public Map locationMap() { - Map locations = new HashMap<>(); - locations.put(29L, "Ho Chi Minh"); - locations.put(24L, "Ha Noi"); - return locations; - } - - @Bean - public MimeMessage salaryReviewMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { - MimeMessage mailMessage = mailSender.createMimeMessage(); - mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); - mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); - return mailMessage; - } - - @Bean - public MimeMessage getPromotedMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { - MimeMessage mailMessage = mailSender.createMimeMessage(); - mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); - mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); - return mailMessage; - } - - @Bean - public MimeMessage postChallengeMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { - MimeMessage mailMessage = mailSender.createMimeMessage(); - mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); - mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); - return mailMessage; - } - - @Bean - public MimeMessage applyJobMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { - MimeMessage mailMessage = mailSender.createMimeMessage(); - mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); - return mailMessage; - } - - @Bean - public MimeMessage jobAlertMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { - MimeMessage mailMessage = mailSender.createMimeMessage(); - mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); - mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); - return mailMessage; - } - - @Bean - public MimeMessage alertEventOrganiserMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { - MimeMessage mailMessage = mailSender.createMimeMessage(); - mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); - return mailMessage; - } - - @Bean - public Template salaryReviewReportTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("salaryReviewReport.en.ftl"); - return template; - } - - @Bean - public Template salaryReviewReportTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("salaryReviewReport.vi.ftl"); - return template; - } - - @Bean - public Template getPromotedTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("getPromoted.en.ftl"); - return template; - } - - @Bean - public Template getPromotedTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("getPromoted.vi.ftl"); - return template; - } - - @Bean - public Template postChallengeMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("postChallenge.en.ftl"); - return template; - } - - @Bean - public Template notifyChallengeTimelineMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("notifyChallengeTimeline.vi.ftl"); - return template; - } - - @Bean - public Template notifyChallengeTimelineMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("notifyChallengeTimeline.en.ftl"); - return template; - } - - @Bean - public Template postChallengeUpdateMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("updateChallenge.en.ftl"); - return template; - } - - @Bean - public Template postChallengeMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("postChallenge.vi.ftl"); - return template; - } - - @Bean - public Template confirmUserJoinChallengeMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("confirmUserJoinChallenge.en.ftl"); - return template; - } - - @Bean - public Template confirmUserJoinChallengeMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("confirmUserJoinChallenge.vi.ftl"); - return template; - } - - @Bean - public Template alertEmployerChallengeMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("alertEmployerChallenge.en.ftl"); - return template; - } - - @Bean - public Template alertEmployerChallengeMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("alertEmployerChallenge.vi.ftl"); - return template; - } - - @Bean - public Template alertJobSeekerApplyJobMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("alertJobSeekerApplyJob.en.ftl"); - return template; - } - - @Bean - public Template alertJobSeekerApplyJobMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("alertJobSeekerApplyJob.vi.ftl"); - return template; - } - - @Bean - public Template alertEmployerApplyJobMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("alertEmployerApplyJob.en.ftl"); - return template; - } - - @Bean - public Template alertEmployerApplyJobMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("alertEmployerApplyJob.vi.ftl"); - return template; - } - - @Bean - public Template alertEmployerPostJobMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("alertEmployerPostJob.vi.ftl"); - return template; - } - - @Bean - public Template alertEmployerPostJobMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("alertEmployerPostJob.en.ftl"); - return template; - } - - @Bean - public Template alertTechloopiesPostJobMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("alertTechloopiesApplyJob.en.ftl"); - return template; - } - - @Bean - public Template jobAlertMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("jobAlert.en.ftl"); - return template; - } - - @Bean - public Template jobAlertMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("jobAlert.vi.ftl"); - return template; - } - - @Bean - public Template alertEventOrganiserMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("webinar.en.ftl"); - return template; - } - - @Bean - public Template alertEventOrganiserMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("webinar.vi.ftl"); - return template; - } - - @Bean - public Template onBoardingMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("onboarding.en.ftl"); - return template; - } - - @Bean - public Template onBoardingMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("onboarding.vi.ftl"); - return template; - } - - @Bean - public Template dailyChallengeSummaryMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("challengeDailySummary.en.ftl"); - return template; - } - - @Bean - public Template dailyChallengeSummaryMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("challengeDailySummary.vi.ftl"); - return template; - } - - @Bean - public JsonNode vietnamworksConfiguration() throws IOException { - return new ObjectMapper().readTree(vnwConfigRes.getInputStream()); - } - - @Bean - @DependsOn("jsonConfigRepository") - public SocialConfig googleSocialConfig() { - return applicationContext.getBean(JsonConfigRepository.class).getSocialConfig().stream() - .filter(socialConfig -> socialConfig.getProvider() == SocialProvider.GOOGLE) - .findFirst().get(); - } - - @Bean - public Calendar googleCalendar() throws GeneralSecurityException, IOException { - JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport(); - SocialConfig googleConfig = googleSocialConfig(); - HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); - GoogleCredential credential = new GoogleCredential.Builder() - .setTransport(httpTransport) - .setJsonFactory(jsonFactory) - .setServiceAccountId(googleConfig.getServiceAccountEmail()) - .setServiceAccountPrivateKeyFromP12File(googleApiAuthResource.getFile()) - .setServiceAccountScopes(Collections.singleton(CalendarScopes.CALENDAR)) - .setServiceAccountUser(googleConfig.getCalendarOwner()) - .build(); - - return new Calendar.Builder(transport, jsonFactory, credential) - .setApplicationName("Techlooper").build(); - } - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - this.applicationContext.getEnvironment().acceptsProfiles(environment.getProperty("spring.profiles.active")); - } - - @Bean - public MimeMessage fromTechlooperMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { - MimeMessage mailMessage = mailSender.createMimeMessage(); - mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); - mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); - return mailMessage; - } - - private ClientHttpRequestFactory clientHttpRequestFactory() { - HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); - factory.setReadTimeout(5000); - factory.setConnectTimeout(5000); - return factory; - } - - @Bean - public Template challengeEmployerMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("challengeEmployerEmail.en.ftl"); - return template; - } - - @Bean - public Template challengeEmployerMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { - Template template = freemakerConfig.getTemplate("challengeEmployerEmail.vi.ftl"); - return template; - } + @Value("${mail.form}") + private String mailForm; + + @Value("${mail.reply_to}") + private String mailReplyTo; + + @Value("${mail.citibank.cc_promotion.to}") + private String mailCitibankCreditCardPromotionTo; + + @Value("${mail.citibank.cc_promotion.subject}") + private String mailCitibankCreditCardPromotionSubject; + + @Value("classpath:vnwConfig.json") + private org.springframework.core.io.Resource vnwConfigRes; + + @Value("classpath:google-auth/techLooper.p12") + private org.springframework.core.io.Resource googleApiAuthResource; + + private ApplicationContext applicationContext; + + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); + configurer.setFileEncoding("UTF-8"); + return configurer; + } + + @Bean + public CacheManager cacheManager() { + CompositeCacheManager manager = new CompositeCacheManager(); + manager.setCacheManagers(Arrays.asList( + new ConcurrentMapCacheManager("SOCIAL_CONFIG"), + new ConcurrentMapCacheManager("COMMON_TERM"), + new ConcurrentMapCacheManager("SKILL_CONFIG"))); + return manager; + } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(clientHttpRequestFactory()); + } + + @Bean + public MultipartResolver multipartResolver() { + CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); + multipartResolver.setMaxUploadSize(500000); + return multipartResolver; + } + + @Bean + public Mapper dozerBeanMapper() { + DozerBeanMapper dozerBeanMapper = new DozerBeanMapper(); + dozerBeanMapper.addMapping(new BeanMappingBuilder() { + protected void configure() { + mapping(FacebookProfile.class, com.techlooper.entity.FacebookProfile.class) + .fields("locale", "locale", FieldsMappingOptions.customConverter(LocaleConverter.class)); + + mapping(TwitterProfile.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) + .fields("name", "firstName", FieldsMappingOptions.copyByReference()) + .fields("screenName", "userName", FieldsMappingOptions.copyByReference()); + + mapping(GitHubUserProfile.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) + .fields("name", "firstName", FieldsMappingOptions.copyByReference()) + .fields("email", "emailAddress", FieldsMappingOptions.copyByReference()); + + mapping(Person.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) + .fields("givenName", "firstName", FieldsMappingOptions.copyByReference()) + .fields("familyName", "lastName", FieldsMappingOptions.copyByReference()) + .fields("accountEmail", "emailAddress", FieldsMappingOptions.copyByReference()) + .fields("imageUrl", "profileImageUrl", FieldsMappingOptions.copyByReference()); + + mapping(com.techlooper.entity.FacebookProfile.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) + .fields("email", "emailAddress", FieldsMappingOptions.copyByReference()); + + mapping(LinkedInProfile.class, com.techlooper.entity.UserEntity.class, TypeMappingOptions.oneWay()) + .fields("profilePictureUrl", "profileImageUrl", FieldsMappingOptions.copyByReference()); + + mapping(UserEntity.class, UserInfo.class, TypeMappingOptions.oneWay()) + .fields("profiles", "profileNames", FieldsMappingOptions.customConverter(ProfileNameConverter.class)); + + mapping(UserInfo.class, UserEntity.class, TypeMappingOptions.oneWay()) + .fields("profileNames", "profiles", FieldsMappingOptions.customConverter(ProfileNameConverter.class)); + + mapping(UserEntity.class, VnwUserProfile.class).exclude("accessGrant"); + + mapping(SalaryReviewEntity.class, VNWJobSearchRequest.class) + .fields("jobLevelIds", "jobLevel") + .fields("jobCategories", "jobCategories", FieldsMappingOptions.customConverter(ListCSVStringConverter.class)) + .fields("netSalary", "jobSalary") + .fields("locationId", "jobLocation"); + + mapping(VnwJobAlert.class, VnwJobAlertRequest.class) + .fields("jobLocations", "locationId", FieldsMappingOptions.customConverter(ListCSVStringConverter.class)) + .fields("minSalary", "netSalary"); + + mapping(WebinarInfoDto.class, WebinarEntity.class, TypeMappingOptions.oneWay()) + .exclude("createdDateTime"); + + mapping(ScrapeJobEntity.class, VNWJobSearchResponseDataItem.class) + .fields("jobTitle", "title") + .fields("jobTitleUrl", "url") + .fields("companyLogoUrl", "logoUrl") + .fields("createdDateTime", "postedOn"); + + mapping(ScrapeJobEntity.class, JobResponse.class) + .fields("jobTitle", "title") + .fields("jobTitleUrl", "url") + .fields("createdDateTime", "postedOn") + .fields("companyLogoUrl", "logoUrl"); + + mapping(ChallengeEntity.class, ChallengeDto.class) + .fields("startDateTime", "startDate") + .fields("submissionDateTime", "submissionDate") + .fields("registrationDateTime", "registrationDate") + .fields("ideaSubmissionDateTime", "ideaSubmissionDate") + .fields("uxSubmissionDateTime", "uxSubmissionDate") + .fields("prototypeSubmissionDateTime", "prototypeSubmissionDate"); + + mapping(ChallengeRegistrantDto.class, ChallengeRegistrantEntity.class, TypeMappingOptions.oneWay()) + .exclude("activePhase"); + + } + }); + return dozerBeanMapper; + } + + @Bean + public TextEncryptor textEncryptor() { + BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); + textEncryptor.setPassword(environment.getProperty("core.textEncryptor.password")); + return textEncryptor; + } + + @Bean + public JavaMailSender mailSender() { + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + mailSender.setHost("localhost"); + mailSender.setPort(25); + + Properties javaMailProperties = new Properties(); + javaMailProperties.put("mail.transport.protocol", "smtp"); + mailSender.setJavaMailProperties(javaMailProperties); + return mailSender; + } + + @Bean + public SimpleMailMessage citibankCreditCardPromotionMailMessage() { + SimpleMailMessage mailMessage = new SimpleMailMessage(); + mailMessage.setFrom(mailForm); + mailMessage.setTo(mailCitibankCreditCardPromotionTo); + mailMessage.setReplyTo(mailReplyTo); + mailMessage.setSubject(mailCitibankCreditCardPromotionSubject); + return mailMessage; + } + + @Bean + public freemarker.template.Configuration freemakerConfig() throws IOException, URISyntaxException { + freemarker.template.Configuration cfg = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_22); + cfg.setDirectoryForTemplateLoading(Paths.get(this.getClass().getClassLoader().getResource("/template").toURI()).toFile()); + cfg.setDefaultEncoding("UTF-8"); + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + return cfg; + } + + @Bean + public Template citibankCreditCardPromotionTemplate(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("citibankCreditCardPromotion.ftl"); + return template; + } + + @Bean + public Map locationMap() { + Map locations = new HashMap<>(); + locations.put(29L, "Ho Chi Minh"); + locations.put(24L, "Ha Noi"); + return locations; + } + + @Bean + public MimeMessage salaryReviewMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { + MimeMessage mailMessage = mailSender.createMimeMessage(); + mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); + mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); + return mailMessage; + } + + @Bean + public MimeMessage getPromotedMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { + MimeMessage mailMessage = mailSender.createMimeMessage(); + mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); + mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); + return mailMessage; + } + + @Bean + public MimeMessage postChallengeMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { + MimeMessage mailMessage = mailSender.createMimeMessage(); + mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); + mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); + return mailMessage; + } + + @Bean + public MimeMessage applyJobMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { + MimeMessage mailMessage = mailSender.createMimeMessage(); + mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); + return mailMessage; + } + + @Bean + public MimeMessage jobAlertMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { + MimeMessage mailMessage = mailSender.createMimeMessage(); + mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); + mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); + return mailMessage; + } + + @Bean + public MimeMessage alertEventOrganiserMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { + MimeMessage mailMessage = mailSender.createMimeMessage(); + mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); + return mailMessage; + } + + @Bean + public Template salaryReviewReportTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("salaryReviewReport.en.ftl"); + return template; + } + + @Bean + public Template salaryReviewReportTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("salaryReviewReport.vi.ftl"); + return template; + } + + @Bean + public Template getPromotedTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("getPromoted.en.ftl"); + return template; + } + + @Bean + public Template getPromotedTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("getPromoted.vi.ftl"); + return template; + } + + @Bean + public Template postChallengeMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("postChallenge.en.ftl"); + return template; + } + + @Bean + public Template notifyChallengeTimelineMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("notifyChallengeTimeline.vi.ftl"); + return template; + } + + @Bean + public Template notifyChallengeTimelineMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("notifyChallengeTimeline.en.ftl"); + return template; + } + + @Bean + public Template postChallengeUpdateMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("updateChallenge.en.ftl"); + return template; + } + + @Bean + public Template postChallengeMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("postChallenge.vi.ftl"); + return template; + } + + @Bean + public Template confirmUserJoinChallengeMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("confirmUserJoinChallenge.en.ftl"); + return template; + } + + @Bean + public Template confirmUserJoinChallengeMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("confirmUserJoinChallenge.vi.ftl"); + return template; + } + + @Bean + public Template alertEmployerChallengeMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("alertEmployerChallenge.en.ftl"); + return template; + } + + @Bean + public Template alertEmployerChallengeMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("alertEmployerChallenge.vi.ftl"); + return template; + } + + @Bean + public Template alertJobSeekerApplyJobMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("alertJobSeekerApplyJob.en.ftl"); + return template; + } + + @Bean + public Template alertJobSeekerApplyJobMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("alertJobSeekerApplyJob.vi.ftl"); + return template; + } + + @Bean + public Template alertEmployerApplyJobMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("alertEmployerApplyJob.en.ftl"); + return template; + } + + @Bean + public Template alertEmployerApplyJobMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("alertEmployerApplyJob.vi.ftl"); + return template; + } + + @Bean + public Template alertEmployerPostJobMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("alertEmployerPostJob.vi.ftl"); + return template; + } + + @Bean + public Template alertEmployerPostJobMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("alertEmployerPostJob.en.ftl"); + return template; + } + + @Bean + public Template alertTechloopiesPostJobMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("alertTechloopiesApplyJob.en.ftl"); + return template; + } + + @Bean + public Template jobAlertMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("jobAlert.en.ftl"); + return template; + } + + @Bean + public Template jobAlertMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("jobAlert.vi.ftl"); + return template; + } + + @Bean + public Template alertEventOrganiserMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("webinar.en.ftl"); + return template; + } + + @Bean + public Template alertEventOrganiserMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("webinar.vi.ftl"); + return template; + } + + @Bean + public Template onBoardingMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("onboarding.en.ftl"); + return template; + } + + @Bean + public Template onBoardingMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("onboarding.vi.ftl"); + return template; + } + + @Bean + public Template dailyChallengeSummaryMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("challengeDailySummary.en.ftl"); + return template; + } + + @Bean + public Template dailyChallengeSummaryMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("challengeDailySummary.vi.ftl"); + return template; + } + + @Bean + public JsonNode vietnamworksConfiguration() throws IOException { + return new ObjectMapper().readTree(vnwConfigRes.getInputStream()); + } + + @Bean + @DependsOn("jsonConfigRepository") + public SocialConfig googleSocialConfig() { + return applicationContext.getBean(JsonConfigRepository.class).getSocialConfig().stream() + .filter(socialConfig -> socialConfig.getProvider() == SocialProvider.GOOGLE) + .findFirst().get(); + } + + @Bean + public Calendar googleCalendar() throws GeneralSecurityException, IOException { + JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance(); + HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport(); + SocialConfig googleConfig = googleSocialConfig(); + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + GoogleCredential credential = new GoogleCredential.Builder() + .setTransport(httpTransport) + .setJsonFactory(jsonFactory) + .setServiceAccountId(googleConfig.getServiceAccountEmail()) + .setServiceAccountPrivateKeyFromP12File(googleApiAuthResource.getFile()) + .setServiceAccountScopes(Collections.singleton(CalendarScopes.CALENDAR)) + .setServiceAccountUser(googleConfig.getCalendarOwner()) + .build(); + + return new Calendar.Builder(transport, jsonFactory, credential) + .setApplicationName("Techlooper").build(); + } + + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + this.applicationContext.getEnvironment().acceptsProfiles(environment.getProperty("spring.profiles.active")); + } + + @Bean + public MimeMessage fromTechlooperMailMessage(JavaMailSender mailSender) throws MessagingException, UnsupportedEncodingException { + MimeMessage mailMessage = mailSender.createMimeMessage(); + mailMessage.setFrom(new InternetAddress(mailTechlooperForm, "TechLooper", "UTF-8")); + mailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); + return mailMessage; + } + + private ClientHttpRequestFactory clientHttpRequestFactory() { + HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); + factory.setReadTimeout(5000); + factory.setConnectTimeout(5000); + return factory; + } + + @Bean + public Template challengeEmployerMailTemplateEn(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("challengeEmployerEmail.en.ftl"); + return template; + } + + @Bean + public Template challengeEmployerMailTemplateVi(freemarker.template.Configuration freemakerConfig) throws IOException { + Template template = freemakerConfig.getTemplate("challengeEmployerEmail.vi.ftl"); + return template; + } } \ No newline at end of file diff --git a/src/main/java/com/techlooper/config/web/DispatcherServletInitializer.java b/src/main/java/com/techlooper/config/web/DispatcherServletInitializer.java index cabcfb13c..83c80f873 100644 --- a/src/main/java/com/techlooper/config/web/DispatcherServletInitializer.java +++ b/src/main/java/com/techlooper/config/web/DispatcherServletInitializer.java @@ -19,8 +19,11 @@ import com.techlooper.config.CoreConfiguration; import com.techlooper.config.VnwDbConfiguration; import com.techlooper.config.web.sec.SecurityConfiguration; +import com.techlooper.config.web.sec.SessionListener; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; import javax.servlet.ServletRegistration.Dynamic; public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @@ -31,6 +34,12 @@ public class DispatcherServletInitializer extends AbstractAnnotationConfigDispat // @Value("${spring.profiles.active}") // private String profile; + public void onStartup(ServletContext servletContext) throws ServletException { + super.onStartup(servletContext); + servletContext.getSessionCookieConfig().setMaxAge(15770000); + servletContext.addListener(new SessionListener()); + } + protected Class[] getRootConfigClasses() { return null; } diff --git a/src/main/java/com/techlooper/config/web/sec/SecurityConfiguration.java b/src/main/java/com/techlooper/config/web/sec/SecurityConfiguration.java index 9fc1be545..ae859d301 100644 --- a/src/main/java/com/techlooper/config/web/sec/SecurityConfiguration.java +++ b/src/main/java/com/techlooper/config/web/sec/SecurityConfiguration.java @@ -10,10 +10,13 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl; +import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; import javax.servlet.http.HttpServletResponse; import java.util.Arrays; @@ -27,58 +30,58 @@ @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { - @Bean - public AuthenticationProvider vnwAuthenticationProvider() { - return new VnwAuthenticationProvider(); - } + @Bean + public AuthenticationProvider vnwAuthenticationProvider() { + return new VnwAuthenticationProvider(); + } - @Bean - public AuthenticationProvider socialAuthenticationProvider() { - return new SocialAuthenticationProvider(); - } + @Bean + public AuthenticationProvider socialAuthenticationProvider() { + return new SocialAuthenticationProvider(); + } - @Bean - public AuthenticationProvider switchingAuthenticationProvider() { - SwitchingAuthenticationProvider switchingAuthenticationProvider = new SwitchingAuthenticationProvider(); - Map authenticationProviders = new HashMap<>(); - authenticationProviders.put(SocialProvider.VIETNAMWORKS, vnwAuthenticationProvider()); - authenticationProviders.put(SocialProvider.FACEBOOK, socialAuthenticationProvider()); - authenticationProviders.put(SocialProvider.GOOGLE, socialAuthenticationProvider()); - switchingAuthenticationProvider.setProviders(authenticationProviders); - return switchingAuthenticationProvider; - } + @Bean + public AuthenticationProvider switchingAuthenticationProvider() { + SwitchingAuthenticationProvider switchingAuthenticationProvider = new SwitchingAuthenticationProvider(); + Map authenticationProviders = new HashMap<>(); + authenticationProviders.put(SocialProvider.VIETNAMWORKS, vnwAuthenticationProvider()); + authenticationProviders.put(SocialProvider.FACEBOOK, socialAuthenticationProvider()); + authenticationProviders.put(SocialProvider.GOOGLE, socialAuthenticationProvider()); + switchingAuthenticationProvider.setProviders(authenticationProviders); + return switchingAuthenticationProvider; + } - @Bean - public AuthenticationManager authenticationManager() { - return new ProviderManager(Arrays.asList(switchingAuthenticationProvider())); - } + @Bean + public AuthenticationManager authenticationManager() { + return new ProviderManager(Arrays.asList(switchingAuthenticationProvider())); + } - protected void configure(HttpSecurity http) throws Exception { - http.csrf().disable() - .authorizeRequests() - .and().formLogin().loginPage("/login").usernameParameter("us").passwordParameter("pwd").successHandler(getSuccessHandler()).failureHandler(getAuthenticationFailureHandler()) - .and().logout().logoutUrl("/logout").logoutSuccessHandler(getLogoutSuccessHandler()).invalidateHttpSession(true).deleteCookies("SESSION").permitAll() - .and().exceptionHandling().authenticationEntryPoint(exceptionHandler()); + protected void configure(HttpSecurity http) throws Exception { + http.csrf().disable(); + http.headers().frameOptions().disable(); + http.authorizeRequests() + .and().formLogin().loginPage("/login").usernameParameter("us").passwordParameter("pwd").successHandler(getSuccessHandler()).failureHandler(getAuthenticationFailureHandler()) + .and().logout().logoutUrl("/logout").logoutSuccessHandler(getLogoutSuccessHandler()).invalidateHttpSession(true).deleteCookies("JSESSIONID").permitAll() + .and().exceptionHandling().authenticationEntryPoint(exceptionHandler()); + } - } + private AuthenticationEntryPoint exceptionHandler() { + return (request, response, authException) -> response.setStatus(HttpServletResponse.SC_FORBIDDEN); + } - private AuthenticationEntryPoint exceptionHandler() { - return (request, response, authException) -> response.setStatus(HttpServletResponse.SC_FORBIDDEN); - } + private LogoutSuccessHandler getLogoutSuccessHandler() { + return (request, response, authentication) -> response.setStatus(HttpServletResponse.SC_NO_CONTENT); + } - private LogoutSuccessHandler getLogoutSuccessHandler() { - return (request, response, authentication) -> response.setStatus(HttpServletResponse.SC_NO_CONTENT); - } + private AuthenticationFailureHandler getAuthenticationFailureHandler() { + return (request, response, exception) -> response.setStatus(HttpServletResponse.SC_FORBIDDEN); + } - private AuthenticationFailureHandler getAuthenticationFailureHandler() { - return (request, response, exception) -> response.setStatus(HttpServletResponse.SC_FORBIDDEN); - } + private AuthenticationSuccessHandler getSuccessHandler() { + return (request, response, authentication) -> response.setStatus(HttpServletResponse.SC_NO_CONTENT); + } - private AuthenticationSuccessHandler getSuccessHandler() { - return (request, response, authentication) -> response.setStatus(HttpServletResponse.SC_NO_CONTENT); - } - - public void configure(WebSecurity web) throws Exception { - web.ignoring().antMatchers("/images/**", "/css/**", "/generate-resources/**", "/modules/**", "/bower_components/**", "/custom-js/**"); - } + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/images/**", "/css/**", "/generate-resources/**", "/modules/**", "/bower_components/**", "/custom-js/**"); + } } \ No newline at end of file diff --git a/src/main/java/com/techlooper/config/web/sec/SessionListener.java b/src/main/java/com/techlooper/config/web/sec/SessionListener.java new file mode 100644 index 000000000..96a1f85ac --- /dev/null +++ b/src/main/java/com/techlooper/config/web/sec/SessionListener.java @@ -0,0 +1,17 @@ +package com.techlooper.config.web.sec; + +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +/** + * Created by phuonghqh on 10/12/15. + */ +public class SessionListener implements HttpSessionListener { + + public void sessionCreated(HttpSessionEvent event) { + event.getSession().setMaxInactiveInterval(15770000); + } + + public void sessionDestroyed(HttpSessionEvent se) { + } +} diff --git a/src/main/java/com/techlooper/controller/ChallengeController.java b/src/main/java/com/techlooper/controller/ChallengeController.java index e1387de44..3ae318013 100644 --- a/src/main/java/com/techlooper/controller/ChallengeController.java +++ b/src/main/java/com/techlooper/controller/ChallengeController.java @@ -19,121 +19,121 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.text.ParseException; import java.util.List; import java.util.Set; @RestController public class ChallengeController { - private final static Logger LOGGER = LoggerFactory.getLogger(ChallengeController.class); + private final static Logger LOGGER = LoggerFactory.getLogger(ChallengeController.class); + + @Resource + private ChallengeService challengeService; + + @Resource + private EmployerService employerService; + + @Resource + private LeadAPIService leadAPIService; + + @Resource + private ChallengeRegistrantRepository challengeRegistrantRepository; + + @PreAuthorize("hasAuthority('EMPLOYER')") + @RequestMapping(value = "/challenge/publish", method = RequestMethod.POST) + public ChallengeResponse publishChallenge(@RequestBody ChallengeDto challengeDto, HttpServletRequest servletRequest) throws Exception { + int responseCode = 0; + String employerEmail = servletRequest.getRemoteUser(); + challengeDto.setAuthorEmail(employerEmail); + ChallengeEntity challengeEntity = challengeService.savePostChallenge(challengeDto); + boolean newEntity = challengeDto.getChallengeId() == null; + if (newEntity) { + if (challengeEntity != null) { + if (EmailValidator.validate(challengeEntity.getAuthorEmail())) { + challengeService.sendPostChallengeEmailToEmployer(challengeEntity); + } + challengeService.sendPostChallengeEmailToTechloopies(challengeEntity, Boolean.TRUE); + } + + // Call Lead Management API to create new lead on CRM system + try { + VnwUser employer = employerService.findEmployerByUsername(employerEmail); + VnwCompany company = employerService.findCompanyById(employer.getCompanyId()); + if (employer != null && company != null) { + responseCode = leadAPIService.createNewLead( + employer, company, LeadEventEnum.POST_CHALLENGE, challengeEntity.getChallengeName()); + + String logMessage = "Create Lead API Response Code : %d ,EmployerID : %d ,CompanyID : %d"; + LOGGER.info(String.format(logMessage, responseCode, employer.getUserId(), company.getCompanyId())); + } + } catch (Exception ex) { + LOGGER.error(ex.getMessage(), ex); + } + } else { + challengeService.sendPostChallengeEmailToTechloopies(challengeEntity, Boolean.FALSE); + } - @Resource - private ChallengeService challengeService; + return new ChallengeResponse(challengeEntity.getChallengeId(), responseCode); + } - @Resource - private EmployerService employerService; + @RequestMapping(value = "/challenge/{challengeId}", method = RequestMethod.GET) + public ChallengeDetailDto getChallengeDetail(@PathVariable Long challengeId, HttpServletRequest request, HttpServletResponse response) throws Exception { + ChallengeDetailDto challengeDetail = challengeService.getChallengeDetail(challengeId, request.getRemoteUser()); + if (challengeDetail == null) response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return challengeDetail; + } - @Resource - private LeadAPIService leadAPIService; + @RequestMapping(value = "/challenge/join", method = RequestMethod.POST) + public long joinChallenge(@RequestBody ChallengeRegistrantDto joinChallenge) throws Exception { + return challengeService.joinChallenge(joinChallenge); + } - @Resource - private ChallengeRegistrantRepository challengeRegistrantRepository; + @RequestMapping(value = "/challenge/list", method = RequestMethod.GET) + public List listChallenges() throws Exception { + return challengeService.listChallenges(); + } - @PreAuthorize("hasAuthority('EMPLOYER')") - @RequestMapping(value = "/challenge/publish", method = RequestMethod.POST) - public ChallengeResponse publishChallenge(@RequestBody ChallengeDto challengeDto, HttpServletRequest servletRequest) throws Exception { - int responseCode = 0; - String employerEmail = servletRequest.getRemoteUser(); - challengeDto.setAuthorEmail(employerEmail); - ChallengeEntity challengeEntity = challengeService.savePostChallenge(challengeDto); - boolean newEntity = challengeDto.getChallengeId() == null; - if (newEntity) { - if (challengeEntity != null) { - if (EmailValidator.validate(challengeEntity.getAuthorEmail())) { - challengeService.sendPostChallengeEmailToEmployer(challengeEntity); - } - challengeService.sendPostChallengeEmailToTechloopies(challengeEntity, Boolean.TRUE); - } - - // Call Lead Management API to create new lead on CRM system - try { - VnwUser employer = employerService.findEmployerByUsername(employerEmail); - VnwCompany company = employerService.findCompanyById(employer.getCompanyId()); - if (employer != null && company != null) { - responseCode = leadAPIService.createNewLead( - employer, company, LeadEventEnum.POST_CHALLENGE, challengeEntity.getChallengeName()); - - String logMessage = "Create Lead API Response Code : %d ,EmployerID : %d ,CompanyID : %d"; - LOGGER.info(String.format(logMessage, responseCode, employer.getUserId(), company.getCompanyId())); + @RequestMapping(value = "/challenge/stats", method = RequestMethod.GET) + public ChallengeStatsDto getChallengeStatistics() throws Exception { + ChallengeStatsDto challengeStatsDto = new ChallengeStatsDto(); + challengeStatsDto.setNumberOfChallenges(challengeService.getTotalNumberOfChallenges()); + challengeStatsDto.setNumberOfRegistrants(challengeService.getTotalNumberOfRegistrants()); + challengeStatsDto.setTotalPrizeAmount(challengeService.getTotalAmountOfPrizeValues()); + return challengeStatsDto; + } + + @PreAuthorize("hasAuthority('EMPLOYER')") + @RequestMapping(value = "/challenge/{id}", method = RequestMethod.DELETE) + public void deleteChallengeById(@PathVariable Long id, HttpServletRequest request, HttpServletResponse response) { + if (!challengeService.delete(id, request.getRemoteUser())) { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); } - } - catch (Exception ex) { - LOGGER.error(ex.getMessage(), ex); - } } - else { - challengeService.sendPostChallengeEmailToTechloopies(challengeEntity, Boolean.FALSE); + + @RequestMapping(value = "/challenges/{challengeId}", method = RequestMethod.GET) + public ChallengeDto findChallengeById(@PathVariable Long challengeId) throws Exception { + return challengeService.findChallengeById(challengeId); + } + + @PreAuthorize("hasAuthority('EMPLOYER')") + @RequestMapping(value = "/challenges/{challengeId}/registrants", method = RequestMethod.POST) + public Set getRegistrantsById(@PathVariable Long challengeId, @RequestBody RegistrantFilterCondition condition, HttpServletRequest request) throws ParseException { + condition.setAuthorEmail(request.getRemoteUser()); + return challengeService.findRegistrantsByOwner(condition); + } + + + @PreAuthorize("hasAuthority('EMPLOYER')") + @RequestMapping(value = "/challengeDetail/registrant", method = RequestMethod.POST) + public ChallengeRegistrantDto saveRegistrant(@RequestBody ChallengeRegistrantDto dto, HttpServletRequest request) { + return challengeService.saveRegistrant(request.getRemoteUser(), dto); } - return new ChallengeResponse(challengeEntity.getChallengeId(), responseCode); - } - - @RequestMapping(value = "/challenge/{challengeId}", method = RequestMethod.GET) - public ChallengeDetailDto getChallengeDetail(@PathVariable Long challengeId, HttpServletResponse response) throws Exception { - ChallengeDetailDto challengeDetail = challengeService.getChallengeDetail(challengeId); - if (challengeDetail == null) response.setStatus(HttpServletResponse.SC_NOT_FOUND); - return challengeDetail; - } - - @RequestMapping(value = "/challenge/join", method = RequestMethod.POST) - public long joinChallenge(@RequestBody ChallengeRegistrantDto joinChallenge) throws Exception { - return challengeService.joinChallenge(joinChallenge); - } - - @RequestMapping(value = "/challenge/list", method = RequestMethod.GET) - public List listChallenges() throws Exception { - return challengeService.listChallenges(); - } - - @RequestMapping(value = "/challenge/stats", method = RequestMethod.GET) - public ChallengeStatsDto getChallengeStatistics() throws Exception { - ChallengeStatsDto challengeStatsDto = new ChallengeStatsDto(); - challengeStatsDto.setNumberOfChallenges(challengeService.getTotalNumberOfChallenges()); - challengeStatsDto.setNumberOfRegistrants(challengeService.getTotalNumberOfRegistrants()); - challengeStatsDto.setTotalPrizeAmount(challengeService.getTotalAmountOfPrizeValues()); - return challengeStatsDto; - } - - @PreAuthorize("hasAuthority('EMPLOYER')") - @RequestMapping(value = "/challenge/{id}", method = RequestMethod.DELETE) - public void deleteChallengeById(@PathVariable Long id, HttpServletRequest request, HttpServletResponse response) { - if (!challengeService.delete(id, request.getRemoteUser())) { - response.setStatus(HttpServletResponse.SC_FORBIDDEN); + @PreAuthorize("hasAuthority('EMPLOYER')") + @RequestMapping(value = "challengeRegistrant/fullName/{registrantId}", method = RequestMethod.GET) + public String getChallengeRegistrant(@PathVariable Long registrantId) { + ChallengeRegistrantEntity registrantEntity = challengeRegistrantRepository.findOne(registrantId); + return registrantEntity.getRegistrantFirstName() + " " + registrantEntity.getRegistrantLastName(); } - } - - @RequestMapping(value = "/challenges/{challengeId}", method = RequestMethod.GET) - public ChallengeDto findChallengeById(@PathVariable Long challengeId) throws Exception { - return challengeService.findChallengeById(challengeId); - } - - @PreAuthorize("hasAuthority('EMPLOYER')") - @RequestMapping(value = "/challenges/{challengeId}/registrants", method = RequestMethod.GET) - public Set getRegistrantsById(@PathVariable Long challengeId, HttpServletRequest request, HttpServletResponse response) { - return challengeService.findRegistrantsByOwner(request.getRemoteUser(), challengeId); - } - - - @PreAuthorize("hasAuthority('EMPLOYER')") - @RequestMapping(value = "/challengeDetail/registrant", method = RequestMethod.POST) - public ChallengeRegistrantDto saveRegistrant(@RequestBody ChallengeRegistrantDto dto, HttpServletRequest request) { - return challengeService.saveRegistrant(request.getRemoteUser(), dto); - } - - @PreAuthorize("hasAuthority('EMPLOYER')") - @RequestMapping(value = "challengeRegistrant/fullName/{registrantId}", method = RequestMethod.GET) - public String getChallengeRegistrant(@PathVariable Long registrantId) { - ChallengeRegistrantEntity registrantEntity = challengeRegistrantRepository.findOne(registrantId); - return registrantEntity.getRegistrantFirstName() + " " + registrantEntity.getRegistrantLastName(); - } } diff --git a/src/main/java/com/techlooper/controller/ChallengeSubmissionController.java b/src/main/java/com/techlooper/controller/ChallengeSubmissionController.java new file mode 100644 index 000000000..a1695efe3 --- /dev/null +++ b/src/main/java/com/techlooper/controller/ChallengeSubmissionController.java @@ -0,0 +1,27 @@ +package com.techlooper.controller; + +import com.techlooper.entity.ChallengeSubmissionEntity; +import com.techlooper.model.ChallengeSubmissionDto; +import com.techlooper.service.ChallengeSubmissionService; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * Created by phuonghqh on 10/9/15. + */ +@RestController +public class ChallengeSubmissionController { + + @Resource + private ChallengeSubmissionService challengeSubmissionService; + + @RequestMapping(value = "user/challengeSubmission", method = RequestMethod.POST) + public ChallengeSubmissionEntity submitMyResult(@RequestBody ChallengeSubmissionDto challengeSubmissionDto) { + return challengeSubmissionService.submitMyResult(challengeSubmissionDto); + } + +} diff --git a/src/main/java/com/techlooper/controller/SharingController.java b/src/main/java/com/techlooper/controller/SharingController.java index e4489afb8..2fd3d6ebe 100644 --- a/src/main/java/com/techlooper/controller/SharingController.java +++ b/src/main/java/com/techlooper/controller/SharingController.java @@ -1,18 +1,20 @@ package com.techlooper.controller; -import com.techlooper.repository.JsonConfigRepository; +import com.techlooper.dto.ResourceDto; import com.techlooper.repository.elasticsearch.ProjectRepository; import com.techlooper.repository.elasticsearch.SalaryReviewRepository; import com.techlooper.service.ChallengeService; -import com.techlooper.service.ProjectService; import com.techlooper.service.WebinarService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.net.HttpURLConnection; +import java.net.URL; /** * Created by phuonghqh on 5/11/15. @@ -20,6 +22,8 @@ @Controller public class SharingController { + private final Logger LOGGER = LoggerFactory.getLogger(SharingController.class); + @Resource private SalaryReviewRepository salaryReviewRepository; @@ -43,7 +47,7 @@ public String renderReport(@PathVariable String language, @PathVariable Long sal @RequestMapping(value = "shareChallenge/{language}/{id}") public String renderChallenge(@PathVariable String language, @PathVariable Long id, ModelMap model) { - model.put("challenge", challengeService.getChallengeDetail(id)); + model.put("challenge", challengeService.getChallengeDetail(id, "")); model.put("lang", language); model.put("baseUrl", baseUrl); return "/jsp/challenge-sharing.jsp"; @@ -64,4 +68,37 @@ public String renderFreelancerProject(@PathVariable String language, @PathVariab model.put("baseUrl", baseUrl); return "/jsp/freelancer-sharing.jsp"; } + + @ResponseBody + @RequestMapping(value = "resource/getUrlResponseCode", method = RequestMethod.POST) + public Long getUrlResponseCode(@RequestBody ResourceDto resourceDto) { + try { + HttpURLConnection.setFollowRedirects(false); + String url = resourceDto.getUrl().trim(); + url = (url.startsWith("https://") || url.startsWith("http://")) ? url : "http://" + url; + HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); + con.setRequestMethod("HEAD"); + int responseCode = con.getResponseCode(); + return Long.valueOf(responseCode); + } + catch (Exception e) { + LOGGER.debug("Url not exist", e); + } + return 404L; + } +// +// public static void main(String[] args) { +// try { +// HttpURLConnection.setFollowRedirects(false); +// String url = "https://facebook.com"; +// url = (url.startsWith("https://") || url.startsWith("http://")) ? url : "http://" + url; +// HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); +// con.setRequestMethod("HEAD"); +// int responseCode = con.getResponseCode(); +// System.out.println(responseCode); +// } +// catch (Exception e) { +// e.printStackTrace(); +// } +// } } diff --git a/src/main/java/com/techlooper/controller/UserController.java b/src/main/java/com/techlooper/controller/UserController.java index 3ec542550..527111c6d 100644 --- a/src/main/java/com/techlooper/controller/UserController.java +++ b/src/main/java/com/techlooper/controller/UserController.java @@ -3,10 +3,7 @@ import com.techlooper.dto.DashBoardInfo; import com.techlooper.dto.JoinBySocialDto; import com.techlooper.dto.WebinarInfoDto; -import com.techlooper.entity.ChallengeRegistrantEntity; -import com.techlooper.entity.GetPromotedEntity; -import com.techlooper.entity.PriceJobEntity; -import com.techlooper.entity.SalaryReviewEntity; +import com.techlooper.entity.*; import com.techlooper.entity.userimport.UserImportEntity; import com.techlooper.entity.vnw.dto.VnwUserDto; import com.techlooper.model.*; @@ -407,4 +404,10 @@ public void sendFeedbackToRegistrant(HttpServletRequest request, HttpServletResp response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } } + + @PreAuthorize("hasAuthority('EMPLOYER')") + @RequestMapping(value = "user/challenge/accept/{registrantId}", method = RequestMethod.GET) + public ChallengeRegistrantDto acceptChallengeRegistrant(HttpServletRequest request, @PathVariable Long registrantId) { + return challengeService.acceptRegistrant(request.getRemoteUser(), registrantId); + } } diff --git a/src/main/java/com/techlooper/cron/ChallengeTimelineNotifier.java b/src/main/java/com/techlooper/cron/ChallengeTimelineNotifier.java index 786464401..a6b770935 100644 --- a/src/main/java/com/techlooper/cron/ChallengeTimelineNotifier.java +++ b/src/main/java/com/techlooper/cron/ChallengeTimelineNotifier.java @@ -4,6 +4,8 @@ import com.techlooper.entity.ChallengeRegistrantDto; import com.techlooper.entity.ChallengeRegistrantEntity; import com.techlooper.model.ChallengePhaseEnum; +import com.techlooper.model.EmailSentResultEnum; +import com.techlooper.model.RegistrantFilterCondition; import com.techlooper.service.ChallengeService; import org.apache.commons.lang3.StringUtils; import org.dozer.Mapper; @@ -15,9 +17,12 @@ import javax.annotation.Resource; import java.util.Arrays; +import java.util.Date; import java.util.List; import java.util.Set; +import static com.techlooper.util.DateTimeUtils.*; + @Service public class ChallengeTimelineNotifier { @@ -33,7 +38,7 @@ public class ChallengeTimelineNotifier { private Boolean enableJobAlert; @Scheduled(cron = "${scheduled.cron.notifyChallengeTimeline}") - public void notifyRegistrantAboutChallengeTimeline() throws Exception { + public synchronized void notifyRegistrantAboutChallengeTimeline() throws Exception { if (enableJobAlert) { List challengePhases = Arrays.asList(ChallengePhaseEnum.REGISTRATION, ChallengePhaseEnum.IN_PROGRESS); @@ -42,19 +47,31 @@ public void notifyRegistrantAboutChallengeTimeline() throws Exception { List challengeEntities = challengeService.listChallengesByPhase(challengePhase); for (ChallengeEntity challengeEntity : challengeEntities) { - Set challengeRegistrants = challengeService.findRegistrantsByOwner( - challengeEntity.getAuthorEmail(), challengeEntity.getChallengeId()); + RegistrantFilterCondition condition = new RegistrantFilterCondition(); + condition.setAuthorEmail(challengeEntity.getAuthorEmail()); + condition.setChallengeId(challengeEntity.getChallengeId()); + Set challengeRegistrants = challengeService.findRegistrantsByOwner(condition); for (ChallengeRegistrantDto challengeRegistrant : challengeRegistrants) { - ChallengeRegistrantEntity challengeRegistrantEntity = dozerMapper.map(challengeRegistrant, ChallengeRegistrantEntity.class); - try { - if (StringUtils.isNotEmpty(challengeRegistrantEntity.getRegistrantEmail())) { - challengeService.sendEmailNotifyRegistrantAboutChallengeTimeline( - challengeEntity, challengeRegistrantEntity, challengePhase); - count++; + if (StringUtils.isEmpty(challengeRegistrant.getLastEmailSentDateTime())) { + challengeRegistrant.setLastEmailSentDateTime(yesterdayDate(BASIC_DATE_TIME_PATTERN)); + } + + Date lastSentDate = string2Date(challengeRegistrant.getLastEmailSentDateTime(), BASIC_DATE_TIME_PATTERN); + Date currentDate = new Date(); + if (daysBetween(lastSentDate, currentDate) > 0) { + ChallengeRegistrantEntity challengeRegistrantEntity = dozerMapper.map(challengeRegistrant, ChallengeRegistrantEntity.class); + try { + if (StringUtils.isNotEmpty(challengeRegistrantEntity.getRegistrantEmail())) { + challengeService.sendEmailNotifyRegistrantAboutChallengeTimeline( + challengeEntity, challengeRegistrantEntity, challengePhase); + challengeService.updateSendEmailToContestantResultCode(challengeRegistrantEntity, EmailSentResultEnum.OK); + count++; + } + } catch (Exception ex) { + LOGGER.error(ex.getMessage(), ex); + challengeService.updateSendEmailToContestantResultCode(challengeRegistrantEntity, EmailSentResultEnum.ERROR); } - } catch (Exception ex) { - LOGGER.error(ex.getMessage(), ex); } } } diff --git a/src/main/java/com/techlooper/cron/DailyChallengeSummaryEmailSender.java b/src/main/java/com/techlooper/cron/DailyChallengeSummaryEmailSender.java index 18af951bd..0d3974501 100644 --- a/src/main/java/com/techlooper/cron/DailyChallengeSummaryEmailSender.java +++ b/src/main/java/com/techlooper/cron/DailyChallengeSummaryEmailSender.java @@ -2,7 +2,9 @@ import com.techlooper.entity.ChallengeEntity; import com.techlooper.model.ChallengePhaseEnum; +import com.techlooper.model.EmailSentResultEnum; import com.techlooper.service.ChallengeService; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -11,8 +13,11 @@ import javax.annotation.Resource; import java.util.Arrays; +import java.util.Date; import java.util.List; +import static com.techlooper.util.DateTimeUtils.*; + @Service public class DailyChallengeSummaryEmailSender { @@ -25,7 +30,7 @@ public class DailyChallengeSummaryEmailSender { private Boolean enableJobAlert; @Scheduled(cron = "${scheduled.cron.dailyChallengeSummary}") - public void sendDailyEmailAboutChallengeSummary() throws Exception { + public synchronized void sendDailyEmailAboutChallengeSummary() throws Exception { if (enableJobAlert) { List challengePhases = Arrays.asList(ChallengePhaseEnum.REGISTRATION, ChallengePhaseEnum.IN_PROGRESS); @@ -35,9 +40,19 @@ public void sendDailyEmailAboutChallengeSummary() throws Exception { for (ChallengeEntity challengeEntity : challengeEntities) { try { - challengeService.sendDailySummaryEmailToChallengeOwner(challengeEntity); - count++; + if (StringUtils.isEmpty(challengeEntity.getLastEmailSentDateTime())) { + challengeEntity.setLastEmailSentDateTime(yesterdayDate(BASIC_DATE_TIME_PATTERN)); + } + + Date lastSentDate = string2Date(challengeEntity.getLastEmailSentDateTime(), BASIC_DATE_TIME_PATTERN); + Date currentDate = new Date(); + if (daysBetween(lastSentDate, currentDate) > 0) { + challengeService.sendDailySummaryEmailToChallengeOwner(challengeEntity); + challengeService.updateSendEmailToChallengeOwnerResultCode(challengeEntity, EmailSentResultEnum.OK); + count++; + } } catch (Exception ex) { + challengeService.updateSendEmailToChallengeOwnerResultCode(challengeEntity, EmailSentResultEnum.ERROR); LOGGER.error(ex.getMessage(), ex); } } diff --git a/src/main/java/com/techlooper/cron/JobAlertEmailSender.java b/src/main/java/com/techlooper/cron/JobAlertEmailSender.java index a67b9f829..0409924cf 100644 --- a/src/main/java/com/techlooper/cron/JobAlertEmailSender.java +++ b/src/main/java/com/techlooper/cron/JobAlertEmailSender.java @@ -5,6 +5,7 @@ import com.techlooper.model.JobSearchCriteria; import com.techlooper.model.JobSearchResponse; import com.techlooper.service.JobAggregatorService; +import org.apache.commons.lang3.StringUtils; import org.dozer.Mapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,10 +14,12 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.util.Date; import java.util.List; import static com.techlooper.model.JobAlertEmailResultEnum.EMAIL_SENT; import static com.techlooper.model.JobAlertEmailResultEnum.JOB_NOT_FOUND; +import static com.techlooper.util.DateTimeUtils.*; /** * This is cron job class that automatically sends job alert email to user periodically @@ -46,7 +49,7 @@ public class JobAlertEmailSender { * @throws Exception */ @Scheduled(cron = "${scheduled.cron.jobAlert}") - public void sendJobAlertEmail() throws Exception { + public synchronized void sendJobAlertEmail() throws Exception { if (enableJobAlert) { List jobAlertRegistrationEntities = jobAggregatorService.findJobAlertRegistration(JobAlertPeriodEnum.WEEKLY); @@ -54,14 +57,22 @@ public void sendJobAlertEmail() throws Exception { if (!jobAlertRegistrationEntities.isEmpty()) { int count = 0; for (JobAlertRegistrationEntity jobAlertRegistrationEntity : jobAlertRegistrationEntities) { - JobSearchCriteria criteria = dozerMapper.map(jobAlertRegistrationEntity, JobSearchCriteria.class); - JobSearchResponse jobSearchResponse = jobAggregatorService.findJob(criteria); - if (jobSearchResponse.getTotalJob() > 0) { - jobAggregatorService.sendEmail(jobAlertRegistrationEntity, jobSearchResponse); - jobAggregatorService.updateSendEmailResultCode(jobAlertRegistrationEntity, EMAIL_SENT); - count++; - } else { - jobAggregatorService.updateSendEmailResultCode(jobAlertRegistrationEntity, JOB_NOT_FOUND); + if (StringUtils.isEmpty(jobAlertRegistrationEntity.getLastEmailSentDateTime())) { + jobAlertRegistrationEntity.setLastEmailSentDateTime(yesterdayDate(BASIC_DATE_TIME_PATTERN)); + } + + Date lastSentDate = string2Date(jobAlertRegistrationEntity.getLastEmailSentDateTime(), BASIC_DATE_TIME_PATTERN); + Date currentDate = new Date(); + if (daysBetween(lastSentDate, currentDate) > 0) { + JobSearchCriteria criteria = dozerMapper.map(jobAlertRegistrationEntity, JobSearchCriteria.class); + JobSearchResponse jobSearchResponse = jobAggregatorService.findJob(criteria); + if (jobSearchResponse.getTotalJob() > 0) { + jobAggregatorService.sendEmail(jobAlertRegistrationEntity, jobSearchResponse); + jobAggregatorService.updateSendEmailResultCode(jobAlertRegistrationEntity, EMAIL_SENT); + count++; + } else { + jobAggregatorService.updateSendEmailResultCode(jobAlertRegistrationEntity, JOB_NOT_FOUND); + } } } LOGGER.info("There are " + count + " job alert emails has been sent"); diff --git a/src/main/java/com/techlooper/dto/ResourceDto.java b/src/main/java/com/techlooper/dto/ResourceDto.java new file mode 100644 index 000000000..7fe5c44be --- /dev/null +++ b/src/main/java/com/techlooper/dto/ResourceDto.java @@ -0,0 +1,19 @@ +package com.techlooper.dto; + +import java.io.Serializable; + +/** + * Created by phuonghqh on 10/9/15. + */ +public class ResourceDto implements Serializable { + + private String url; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/src/main/java/com/techlooper/entity/ChallengeEntity.java b/src/main/java/com/techlooper/entity/ChallengeEntity.java index 12a776e4d..3f7d409ed 100644 --- a/src/main/java/com/techlooper/entity/ChallengeEntity.java +++ b/src/main/java/com/techlooper/entity/ChallengeEntity.java @@ -10,6 +10,7 @@ import java.util.List; import static org.springframework.data.elasticsearch.annotations.FieldType.Boolean; +import static org.springframework.data.elasticsearch.annotations.FieldType.Integer; import static org.springframework.data.elasticsearch.annotations.FieldType.String; /** @@ -87,6 +88,12 @@ public class ChallengeEntity { @Field(type = Boolean) private Boolean expired; + @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "dd/MM/yyyy HH:mm") + private String lastEmailSentDateTime; + + @Field(type = Integer) + private int lastEmailSentResultCode; + public Boolean getExpired() { return expired; } @@ -270,4 +277,20 @@ public String getChallengeOverview() { public void setChallengeOverview(String challengeOverview) { this.challengeOverview = challengeOverview; } + + public String getLastEmailSentDateTime() { + return lastEmailSentDateTime; + } + + public void setLastEmailSentDateTime(String lastEmailSentDateTime) { + this.lastEmailSentDateTime = lastEmailSentDateTime; + } + + public int getLastEmailSentResultCode() { + return lastEmailSentResultCode; + } + + public void setLastEmailSentResultCode(int lastEmailSentResultCode) { + this.lastEmailSentResultCode = lastEmailSentResultCode; + } } diff --git a/src/main/java/com/techlooper/entity/ChallengeRegistrantDto.java b/src/main/java/com/techlooper/entity/ChallengeRegistrantDto.java index 6df3ec0cd..7845ccc81 100644 --- a/src/main/java/com/techlooper/entity/ChallengeRegistrantDto.java +++ b/src/main/java/com/techlooper/entity/ChallengeRegistrantDto.java @@ -1,7 +1,11 @@ package com.techlooper.entity; +import com.techlooper.model.ChallengePhaseEnum; +import com.techlooper.model.ChallengeSubmissionDto; import com.techlooper.model.Language; +import java.util.List; + /** * Created by NguyenDangKhoa on 7/6/15. */ @@ -25,6 +29,20 @@ public class ChallengeRegistrantDto { private String disqualifiedReason; + private String lastEmailSentDateTime; + + private List submissions; + + private ChallengePhaseEnum activePhase; + + public ChallengePhaseEnum getActivePhase() { + return activePhase; + } + + public void setActivePhase(ChallengePhaseEnum activePhase) { + this.activePhase = activePhase; + } + public String getDisqualifiedReason() { return disqualifiedReason; } @@ -96,4 +114,20 @@ public Language getLang() { public void setLang(Language lang) { this.lang = lang; } + + public List getSubmissions() { + return submissions; + } + + public void setSubmissions(List submissions) { + this.submissions = submissions; + } + + public String getLastEmailSentDateTime() { + return lastEmailSentDateTime; + } + + public void setLastEmailSentDateTime(String lastEmailSentDateTime) { + this.lastEmailSentDateTime = lastEmailSentDateTime; + } } diff --git a/src/main/java/com/techlooper/entity/ChallengeRegistrantEntity.java b/src/main/java/com/techlooper/entity/ChallengeRegistrantEntity.java index 646aac345..e17b478a9 100644 --- a/src/main/java/com/techlooper/entity/ChallengeRegistrantEntity.java +++ b/src/main/java/com/techlooper/entity/ChallengeRegistrantEntity.java @@ -1,13 +1,13 @@ package com.techlooper.entity; +import com.techlooper.model.ChallengePhaseEnum; import com.techlooper.model.Language; import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.annotations.FieldIndex; +import org.springframework.data.elasticsearch.annotations.*; import static org.springframework.data.elasticsearch.annotations.FieldType.Boolean; import static org.springframework.data.elasticsearch.annotations.FieldType.Double; +import static org.springframework.data.elasticsearch.annotations.FieldType.Integer; import static org.springframework.data.elasticsearch.annotations.FieldType.Long; import static org.springframework.data.elasticsearch.annotations.FieldType.String; @@ -47,6 +47,15 @@ public class ChallengeRegistrantEntity { @Field(type = String, index = FieldIndex.not_analyzed) private String disqualifiedReason; + @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "dd/MM/yyyy HH:mm") + private String lastEmailSentDateTime; + + @Field(type = Integer) + private int lastEmailSentResultCode; + + @Field(type = String, index = FieldIndex.not_analyzed) + private ChallengePhaseEnum activePhase; + public ChallengeRegistrantEntity() { } @@ -136,4 +145,28 @@ public Language getLang() { public void setLang(Language lang) { this.lang = lang; } + + public String getLastEmailSentDateTime() { + return lastEmailSentDateTime; + } + + public void setLastEmailSentDateTime(String lastEmailSentDateTime) { + this.lastEmailSentDateTime = lastEmailSentDateTime; + } + + public int getLastEmailSentResultCode() { + return lastEmailSentResultCode; + } + + public void setLastEmailSentResultCode(int lastEmailSentResultCode) { + this.lastEmailSentResultCode = lastEmailSentResultCode; + } + + public ChallengePhaseEnum getActivePhase() { + return activePhase; + } + + public void setActivePhase(ChallengePhaseEnum activePhase) { + this.activePhase = activePhase; + } } diff --git a/src/main/java/com/techlooper/entity/ChallengeSubmissionEntity.java b/src/main/java/com/techlooper/entity/ChallengeSubmissionEntity.java index 96878de84..1ec4de309 100644 --- a/src/main/java/com/techlooper/entity/ChallengeSubmissionEntity.java +++ b/src/main/java/com/techlooper/entity/ChallengeSubmissionEntity.java @@ -1,7 +1,10 @@ package com.techlooper.entity; import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.annotations.*; +import org.springframework.data.elasticsearch.annotations.DateFormat; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; import static org.springframework.data.elasticsearch.annotations.FieldType.Long; import static org.springframework.data.elasticsearch.annotations.FieldType.String; @@ -9,94 +12,139 @@ @Document(indexName = "techlooper", type = "challengeSubmission") public class ChallengeSubmissionEntity { - @Id - private Long challengeSubmissionId; + @Id + private Long challengeSubmissionId; - @Field(type = Long) - private Long registrantId; + @Field(type = Long) + private Long registrantId; - @Field(type = String) - private String registrantName; + @Field(type = String) + private String registrantName; - @Field(type = Long) - private Long challengeId; + @Field(type = Long) + private Long challengeId; - @Field(type = String) - private String submissionURL; + @Field(type = String) + private String submissionURL; - @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "dd/MM/yyyy") - private String submissionDateTime; + @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "dd/MM/yyyy") + private String submissionDateTime; - @Field(type = String) - private String submissionDescription; + @Field(type = String) + private String submissionDescription; - @Field(type = String, index = FieldIndex.not_analyzed) - private String submissionStatus; + public java.lang.Long getRegistrantId() { + return registrantId; + } - public ChallengeSubmissionEntity() { - } + public void setRegistrantId(java.lang.Long registrantId) { + this.registrantId = registrantId; + } - public Long getChallengeSubmissionId() { - return challengeSubmissionId; - } + public java.lang.Long getChallengeSubmissionId() { + return challengeSubmissionId; + } - public void setChallengeSubmissionId(Long challengeSubmissionId) { - this.challengeSubmissionId = challengeSubmissionId; - } + public void setChallengeSubmissionId(java.lang.Long challengeSubmissionId) { + this.challengeSubmissionId = challengeSubmissionId; + } - public Long getRegistrantId() { - return registrantId; - } + public java.lang.String getRegistrantName() { + return registrantName; + } - public void setRegistrantId(Long registrantId) { - this.registrantId = registrantId; - } + public void setRegistrantName(java.lang.String registrantName) { + this.registrantName = registrantName; + } + + public java.lang.Long getChallengeId() { + return challengeId; + } + + public void setChallengeId(java.lang.Long challengeId) { + this.challengeId = challengeId; + } + + public java.lang.String getSubmissionURL() { + return submissionURL; + } + + public void setSubmissionURL(java.lang.String submissionURL) { + this.submissionURL = submissionURL; + } + + public java.lang.String getSubmissionDateTime() { + return submissionDateTime; + } + + public void setSubmissionDateTime(java.lang.String submissionDateTime) { + this.submissionDateTime = submissionDateTime; + } + + public java.lang.String getSubmissionDescription() { + return submissionDescription; + } + + public void setSubmissionDescription(java.lang.String submissionDescription) { + this.submissionDescription = submissionDescription; + } + + public static class ChallengeSubmissionEntityBuilder { + private ChallengeSubmissionEntity challengeSubmissionEntity; - public String getSubmissionURL() { - return submissionURL; + private ChallengeSubmissionEntityBuilder() { + challengeSubmissionEntity = new ChallengeSubmissionEntity(); } - public String getRegistrantName() { - return registrantName; + private ChallengeSubmissionEntityBuilder(ChallengeSubmissionEntity challengeSubmissionEntity) { + this.challengeSubmissionEntity = challengeSubmissionEntity; } - public void setRegistrantName(String registrantName) { - this.registrantName = registrantName; + public ChallengeSubmissionEntityBuilder withChallengeSubmissionId(Long challengeSubmissionId) { + challengeSubmissionEntity.challengeSubmissionId = challengeSubmissionId; + return this; } - public Long getChallengeId() { - return challengeId; + public ChallengeSubmissionEntityBuilder withRegistrantId(Long registrantId) { + challengeSubmissionEntity.registrantId = registrantId; + return this; } - public void setChallengeId(Long challengeId) { - this.challengeId = challengeId; + public ChallengeSubmissionEntityBuilder withRegistrantName(String registrantName) { + challengeSubmissionEntity.registrantName = registrantName; + return this; } - public void setSubmissionURL(String submissionURL) { - this.submissionURL = submissionURL; + public ChallengeSubmissionEntityBuilder withChallengeId(Long challengeId) { + challengeSubmissionEntity.challengeId = challengeId; + return this; } - public String getSubmissionDateTime() { - return submissionDateTime; + public ChallengeSubmissionEntityBuilder withSubmissionURL(String submissionURL) { + challengeSubmissionEntity.submissionURL = submissionURL; + return this; } - public void setSubmissionDateTime(String submissionDateTime) { - this.submissionDateTime = submissionDateTime; + public ChallengeSubmissionEntityBuilder withSubmissionDateTime(String submissionDateTime) { + challengeSubmissionEntity.submissionDateTime = submissionDateTime; + return this; } - public String getSubmissionDescription() { - return submissionDescription; + public ChallengeSubmissionEntityBuilder withSubmissionDescription(String submissionDescription) { + challengeSubmissionEntity.submissionDescription = submissionDescription; + return this; } - public void setSubmissionDescription(String submissionDescription) { - this.submissionDescription = submissionDescription; + public static ChallengeSubmissionEntityBuilder challengeSubmissionEntity() { + return new ChallengeSubmissionEntityBuilder(); } - public String getSubmissionStatus() { - return submissionStatus; + public static ChallengeSubmissionEntityBuilder challengeSubmissionEntity(ChallengeSubmissionEntity entity) { + return new ChallengeSubmissionEntityBuilder(entity); } - public void setSubmissionStatus(String submissionStatus) { - this.submissionStatus = submissionStatus; + public ChallengeSubmissionEntity build() { + return challengeSubmissionEntity; } + } } diff --git a/src/main/java/com/techlooper/model/ChallengeDetailDto.java b/src/main/java/com/techlooper/model/ChallengeDetailDto.java index 518229cf9..fd5245c6d 100644 --- a/src/main/java/com/techlooper/model/ChallengeDetailDto.java +++ b/src/main/java/com/techlooper/model/ChallengeDetailDto.java @@ -51,6 +51,28 @@ public class ChallengeDetailDto { private Boolean expired; + private ChallengePhaseEnum currentPhase; + + private ChallengePhaseEnum nextPhase; + + private Boolean isAuthor; + + public ChallengePhaseEnum getCurrentPhase() { + return currentPhase; + } + + public void setCurrentPhase(ChallengePhaseEnum currentPhase) { + this.currentPhase = currentPhase; + } + + public ChallengePhaseEnum getNextPhase() { + return nextPhase; + } + + public void setNextPhase(ChallengePhaseEnum nextPhase) { + this.nextPhase = nextPhase; + } + public Boolean getExpired() { return expired; } @@ -226,4 +248,12 @@ public Long getNumberOfRegistrants() { public void setNumberOfRegistrants(Long numberOfRegistrants) { this.numberOfRegistrants = numberOfRegistrants; } + + public Boolean getIsAuthor() { + return isAuthor; + } + + public void setIsAuthor(Boolean isAuthor) { + this.isAuthor = isAuthor; + } } diff --git a/src/main/java/com/techlooper/model/ChallengePhaseEnum.java b/src/main/java/com/techlooper/model/ChallengePhaseEnum.java index df9051b16..648eecb64 100644 --- a/src/main/java/com/techlooper/model/ChallengePhaseEnum.java +++ b/src/main/java/com/techlooper/model/ChallengePhaseEnum.java @@ -5,43 +5,46 @@ */ public enum ChallengePhaseEnum { - REGISTRATION("startDateTime", "registrationDateTime", "REGISTRATION"), + REGISTRATION("startDateTime", "registrationDateTime", "REGISTRATION"), + IN_PROGRESS("registrationDateTime", "submissionDateTime", "IN_PROGRESS"), + IDEA("registrationDateTime", "ideaSubmissionDateTime", "IDEA"), + UIUX("ideaSubmissionDateTime", "uxSubmissionDateTime", "UIUX"), + PROTOTYPE("uxSubmissionDateTime", "prototypeSubmissionDateTime", "PROTOTYPE"), + FINAL("prototypeSubmissionDateTime", "submissionDateTime", "FINAL"); - IN_PROGRESS("registrationDateTime", "submissionDateTime", "IN_PROGRESS"); + private String fromDateTimeField; - private String fromDateTimeField; + private String toDateTimeField; - private String toDateTimeField; + private String value; - private String value; + ChallengePhaseEnum(String fromDateTimeField, String toDateTimeField, String value) { + this.fromDateTimeField = fromDateTimeField; + this.toDateTimeField = toDateTimeField; + this.value = value; + } - private ChallengePhaseEnum(String fromDateTimeField, String toDateTimeField, String value) { - this.fromDateTimeField = fromDateTimeField; - this.toDateTimeField = toDateTimeField; - this.value = value; - } + public String getFromDateTimeField() { + return fromDateTimeField; + } - public String getFromDateTimeField() { - return fromDateTimeField; - } + public void setFromDateTimeField(String fromDateTimeField) { + this.fromDateTimeField = fromDateTimeField; + } - public void setFromDateTimeField(String fromDateTimeField) { - this.fromDateTimeField = fromDateTimeField; - } + public String getToDateTimeField() { + return toDateTimeField; + } - public String getToDateTimeField() { - return toDateTimeField; - } + public void setToDateTimeField(String toDateTimeField) { + this.toDateTimeField = toDateTimeField; + } - public void setToDateTimeField(String toDateTimeField) { - this.toDateTimeField = toDateTimeField; - } + public String getValue() { + return value; + } - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } + public void setValue(String value) { + this.value = value; + } } diff --git a/src/main/java/com/techlooper/model/ChallengeRegistrantFilterTypeEnum.java b/src/main/java/com/techlooper/model/ChallengeRegistrantFilterTypeEnum.java new file mode 100644 index 000000000..f4394b1ea --- /dev/null +++ b/src/main/java/com/techlooper/model/ChallengeRegistrantFilterTypeEnum.java @@ -0,0 +1,19 @@ +package com.techlooper.model; + +public enum ChallengeRegistrantFilterTypeEnum { + + BY_REGISTRANT("registrantId"), + + BY_SUBMISSION("challengeSubmission"); + + private String value; + + private ChallengeRegistrantFilterTypeEnum(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + +} diff --git a/src/main/java/com/techlooper/model/ChallengeSubmissionDto.java b/src/main/java/com/techlooper/model/ChallengeSubmissionDto.java new file mode 100644 index 000000000..874d35ef0 --- /dev/null +++ b/src/main/java/com/techlooper/model/ChallengeSubmissionDto.java @@ -0,0 +1,99 @@ +package com.techlooper.model; + +import java.io.Serializable; + +/** + * Created by NguyenDangKhoa on 10/6/15. + */ +public class ChallengeSubmissionDto implements Serializable { + + private Long challengeSubmissionId; + + private String registrantEmail; + + private String registrantFirstName; + + private String registrantLastName; + + private Long challengeId; + + private Long registrantId; + + private String submissionURL; + + private String submissionDescription; + + private String submissionDateTime; + + public Long getChallengeSubmissionId() { + return challengeSubmissionId; + } + + public void setChallengeSubmissionId(Long challengeSubmissionId) { + this.challengeSubmissionId = challengeSubmissionId; + } + + public Long getRegistrantId() { + return registrantId; + } + + public void setRegistrantId(Long registrantId) { + this.registrantId = registrantId; + } + + public String getRegistrantFirstName() { + return registrantFirstName; + } + + public void setRegistrantFirstName(String registrantFirstName) { + this.registrantFirstName = registrantFirstName; + } + + public String getRegistrantLastName() { + return registrantLastName; + } + + public void setRegistrantLastName(String registrantLastName) { + this.registrantLastName = registrantLastName; + } + + public String getRegistrantEmail() { + return registrantEmail; + } + + public void setRegistrantEmail(String registrantEmail) { + this.registrantEmail = registrantEmail; + } + + public Long getChallengeId() { + return challengeId; + } + + public void setChallengeId(Long challengeId) { + this.challengeId = challengeId; + } + + public String getSubmissionDateTime() { + return submissionDateTime; + } + + public void setSubmissionDateTime(String submissionDateTime) { + this.submissionDateTime = submissionDateTime; + } + + public String getSubmissionURL() { + return submissionURL; + } + + public void setSubmissionURL(String submissionURL) { + this.submissionURL = submissionURL; + } + + public String getSubmissionDescription() { + return submissionDescription; + } + + public void setSubmissionDescription(String submissionDescription) { + this.submissionDescription = submissionDescription; + } +} diff --git a/src/main/java/com/techlooper/model/EmailSentResultEnum.java b/src/main/java/com/techlooper/model/EmailSentResultEnum.java new file mode 100644 index 000000000..b457d7d68 --- /dev/null +++ b/src/main/java/com/techlooper/model/EmailSentResultEnum.java @@ -0,0 +1,19 @@ +package com.techlooper.model; + +public enum EmailSentResultEnum { + + OK(200), + + ERROR(500); + + private int value; + + private EmailSentResultEnum(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + +} diff --git a/src/main/java/com/techlooper/model/RegistrantFilterCondition.java b/src/main/java/com/techlooper/model/RegistrantFilterCondition.java new file mode 100644 index 000000000..52786de63 --- /dev/null +++ b/src/main/java/com/techlooper/model/RegistrantFilterCondition.java @@ -0,0 +1,57 @@ +package com.techlooper.model; + +/** + * Created by NguyenDangKhoa on 10/7/15. + */ +public class RegistrantFilterCondition { + + private String authorEmail; + + private Long challengeId; + + private String filterType; + + private String fromDate; + + private String toDate; + + public String getAuthorEmail() { + return authorEmail; + } + + public void setAuthorEmail(String authorEmail) { + this.authorEmail = authorEmail; + } + + public Long getChallengeId() { + return challengeId; + } + + public void setChallengeId(Long challengeId) { + this.challengeId = challengeId; + } + + public String getFilterType() { + return filterType; + } + + public void setFilterType(String filterType) { + this.filterType = filterType; + } + + public String getFromDate() { + return fromDate; + } + + public void setFromDate(String fromDate) { + this.fromDate = fromDate; + } + + public String getToDate() { + return toDate; + } + + public void setToDate(String toDate) { + this.toDate = toDate; + } +} diff --git a/src/main/java/com/techlooper/service/ChallengeService.java b/src/main/java/com/techlooper/service/ChallengeService.java index 76ebcd4ca..8a7237d4e 100644 --- a/src/main/java/com/techlooper/service/ChallengeService.java +++ b/src/main/java/com/techlooper/service/ChallengeService.java @@ -9,6 +9,7 @@ import javax.mail.MessagingException; import java.io.IOException; +import java.text.ParseException; import java.util.Collection; import java.util.List; import java.util.Set; @@ -30,7 +31,7 @@ void sendPostChallengeEmailToTechloopies(ChallengeEntity challengeEntity, Boolea void sendEmailNotifyRegistrantAboutChallengeTimeline(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity, ChallengePhaseEnum challengePhase) throws Exception; - ChallengeDetailDto getChallengeDetail(Long challengeId); + ChallengeDetailDto getChallengeDetail(Long challengeId, String loginEmail); Long getNumberOfRegistrants(Long challengeId); @@ -40,7 +41,9 @@ void sendApplicationEmailToContestant(ChallengeEntity challengeEntity, Challenge void sendApplicationEmailToEmployer(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity) throws MessagingException, IOException, TemplateException; - long joinChallenge(ChallengeRegistrantDto challengeRegistrantDto) throws MessagingException, IOException, TemplateException; + ChallengeRegistrantEntity joinChallengeEntity(ChallengeRegistrantDto challengeRegistrantDto); + + long joinChallenge(ChallengeRegistrantDto challengeRegistrantDto); List listChallenges(); @@ -68,13 +71,15 @@ void sendApplicationEmailToEmployer(ChallengeEntity challengeEntity, ChallengeRe ChallengeDto findChallengeById(Long id); - Set findRegistrantsByOwner(String ownerEmail, Long challengeId); + Set findRegistrantsByOwner(RegistrantFilterCondition condition) throws ParseException; ChallengeRegistrantDto saveRegistrant(String ownerEmail, ChallengeRegistrantDto challengeRegistrantDto); List findChallengeRegistrantWithinPeriod( Long challengeId, Long currentDateTime, TimePeriodEnum period); + List filterChallengeRegistrantByDate(RegistrantFilterCondition condition) throws ParseException; + List findChallengeSubmissionWithinPeriod( Long challengeId, Long currentDateTime, TimePeriodEnum period); @@ -86,4 +91,14 @@ List findChallengeSubmissionWithinPeriod( boolean sendEmailToRegistrant(String challengeOwner, Long challengeId, Long registrantId, EmailContent emailContent); + List findChallengeSubmissionByRegistrant(Long challengeId, Long registrantId); + + void updateSendEmailToContestantResultCode(ChallengeRegistrantEntity challengeRegistrantEntity, EmailSentResultEnum code); + + void updateSendEmailToChallengeOwnerResultCode(ChallengeEntity challengeEntity, EmailSentResultEnum code); + + Set findRegistrantByChallengeSubmissionDate(Long challengeId, String fromDate, String toDate); + + ChallengeRegistrantDto acceptRegistrant(String ownerEmail, Long registrantId); + } diff --git a/src/main/java/com/techlooper/service/ChallengeSubmissionService.java b/src/main/java/com/techlooper/service/ChallengeSubmissionService.java new file mode 100644 index 000000000..5820d07b7 --- /dev/null +++ b/src/main/java/com/techlooper/service/ChallengeSubmissionService.java @@ -0,0 +1,14 @@ +package com.techlooper.service; + +import com.techlooper.entity.ChallengeSubmissionEntity; +import com.techlooper.model.ChallengeSubmissionDto; + +/** + * Created by phuonghqh on 10/9/15. + */ +public interface ChallengeSubmissionService { + + ChallengeSubmissionEntity submitMyResult(ChallengeSubmissionDto challengeSubmissionDto); + + +} diff --git a/src/main/java/com/techlooper/service/impl/ChallengeServiceImpl.java b/src/main/java/com/techlooper/service/impl/ChallengeServiceImpl.java index b341341fa..ddcd96da2 100644 --- a/src/main/java/com/techlooper/service/impl/ChallengeServiceImpl.java +++ b/src/main/java/com/techlooper/service/impl/ChallengeServiceImpl.java @@ -10,6 +10,7 @@ import com.techlooper.repository.elasticsearch.ChallengeSubmissionRepository; import com.techlooper.service.ChallengeService; import com.techlooper.service.EmailService; +import com.techlooper.util.DataUtils; import com.techlooper.util.DateTimeUtils; import freemarker.template.Template; import freemarker.template.TemplateException; @@ -49,8 +50,9 @@ import java.text.SimpleDateFormat; import java.util.*; import java.util.function.Predicate; -import java.util.stream.Collectors; +import static com.techlooper.util.DateTimeUtils.*; +import static java.util.stream.Collectors.*; import static org.elasticsearch.index.query.FilterBuilders.*; import static org.elasticsearch.index.query.QueryBuilders.*; import static org.elasticsearch.search.aggregations.AggregationBuilders.sum; @@ -62,260 +64,276 @@ @Service public class ChallengeServiceImpl implements ChallengeService { - private final static Logger LOGGER = LoggerFactory.getLogger(ChallengeServiceImpl.class); + private final static Logger LOGGER = LoggerFactory.getLogger(ChallengeServiceImpl.class); - @Resource - private ElasticsearchTemplate elasticsearchTemplateUserImport; + private final static ChallengePhaseEnum CHALLENGE_TIMELINE[] = { + ChallengePhaseEnum.FINAL, + ChallengePhaseEnum.PROTOTYPE, + ChallengePhaseEnum.UIUX, + ChallengePhaseEnum.IDEA, + ChallengePhaseEnum.REGISTRATION + }; - @Resource - private MimeMessage postChallengeMailMessage; + @Resource + private ElasticsearchTemplate elasticsearchTemplateUserImport; - @Resource - private Template postChallengeMailTemplateEn; + @Resource + private MimeMessage postChallengeMailMessage; - @Resource - private Template postChallengeUpdateMailTemplateEn; + @Resource + private Template postChallengeMailTemplateEn; - @Resource - private Template postChallengeMailTemplateVi; + @Resource + private Template postChallengeUpdateMailTemplateEn; - @Value("${mail.postChallenge.subject.vn}") - private String postChallengeMailSubjectVn; + @Resource + private Template postChallengeMailTemplateVi; - @Value("${mail.postChallenge.subject.en}") - private String postChallengeMailSubjectEn; + @Value("${mail.postChallenge.subject.vn}") + private String postChallengeMailSubjectVn; - @Value("${mail.postChallenge.techloopies.mailSubject}") - private String postChallengeTechloopiesMailSubject; + @Value("${mail.postChallenge.subject.en}") + private String postChallengeMailSubjectEn; - @Value("${mail.postChallenge.techloopies.updateMailSubject}") - private String postChallengeTechloopiesUpdateMailSubject; + @Value("${mail.postChallenge.techloopies.mailSubject}") + private String postChallengeTechloopiesMailSubject; - @Value("${mail.postChallenge.techloopies.mailList}") - private String postChallengeTechloopiesMailList; + @Value("${mail.postChallenge.techloopies.updateMailSubject}") + private String postChallengeTechloopiesUpdateMailSubject; - @Value("${web.baseUrl}") - private String webBaseUrl; + @Value("${mail.postChallenge.techloopies.mailList}") + private String postChallengeTechloopiesMailList; - @Resource - private Template confirmUserJoinChallengeMailTemplateEn; + @Value("${web.baseUrl}") + private String webBaseUrl; - @Resource - private Template confirmUserJoinChallengeMailTemplateVi; + @Resource + private Template confirmUserJoinChallengeMailTemplateEn; - @Value("${mail.confirmUserJoinChallenge.subject.vn}") - private String confirmUserJoinChallengeMailSubjectVn; + @Resource + private Template confirmUserJoinChallengeMailTemplateVi; - @Value("${mail.confirmUserJoinChallenge.subject.en}") - private String confirmUserJoinChallengeMailSubjectEn; + @Value("${mail.confirmUserJoinChallenge.subject.vn}") + private String confirmUserJoinChallengeMailSubjectVn; - @Resource - private Template alertEmployerChallengeMailTemplateEn; + @Value("${mail.confirmUserJoinChallenge.subject.en}") + private String confirmUserJoinChallengeMailSubjectEn; - @Resource - private Template alertEmployerChallengeMailTemplateVi; + @Resource + private Template alertEmployerChallengeMailTemplateEn; - @Value("${mail.alertEmployerChallenge.subject.vn}") - private String alertEmployerChallengeMailSubjectVn; + @Resource + private Template alertEmployerChallengeMailTemplateVi; - @Value("${mail.alertEmployerChallenge.subject.en}") - private String alertEmployerChallengeMailSubjectEn; + @Value("${mail.alertEmployerChallenge.subject.vn}") + private String alertEmployerChallengeMailSubjectVn; - @Value("${mail.techlooper.reply_to}") - private String mailTechlooperReplyTo; + @Value("${mail.alertEmployerChallenge.subject.en}") + private String alertEmployerChallengeMailSubjectEn; - @Resource - private JavaMailSender mailSender; + @Value("${mail.techlooper.reply_to}") + private String mailTechlooperReplyTo; - @Resource - private ChallengeRepository challengeRepository; + @Resource + private JavaMailSender mailSender; - @Resource - private ChallengeRegistrantRepository challengeRegistrantRepository; + @Resource + private ChallengeRepository challengeRepository; - @Resource - private ChallengeSubmissionRepository challengeSubmissionRepository; + @Resource + private ChallengeRegistrantRepository challengeRegistrantRepository; - @Resource - private Mapper dozerMapper; + @Resource + private ChallengeSubmissionRepository challengeSubmissionRepository; - @Value("${elasticsearch.userimport.index.name}") - private String techlooperIndex; + @Resource + private Mapper dozerMapper; - @Value("${mail.notifyChallengeTimelineRegistration.subject.vn}") - private String notifyChallengeTimelineRegistrationMailSubjectVn; + @Value("${elasticsearch.userimport.index.name}") + private String techlooperIndex; - @Value("${mail.notifyChallengeTimelineRegistration.subject.en}") - private String notifyChallengeTimelineRegistrationMailSubjectEn; + @Value("${mail.notifyChallengeTimelineRegistration.subject.vn}") + private String notifyChallengeTimelineRegistrationMailSubjectVn; - @Value("${mail.notifyChallengeTimelineInProgress.subject.vn}") - private String notifyChallengeTimelineInProgressMailSubjectVn; + @Value("${mail.notifyChallengeTimelineRegistration.subject.en}") + private String notifyChallengeTimelineRegistrationMailSubjectEn; - @Value("${mail.notifyChallengeTimelineInProgress.subject.en}") - private String notifyChallengeTimelineInProgressMailSubjectEn; + @Value("${mail.notifyChallengeTimelineInProgress.subject.vn}") + private String notifyChallengeTimelineInProgressMailSubjectVn; - @Value("${mail.dailyChallengeSummary.subject.en}") - private String dailyChallengeSummaryMailSubjectEn; + @Value("${mail.notifyChallengeTimelineInProgress.subject.en}") + private String notifyChallengeTimelineInProgressMailSubjectEn; - @Value("${mail.dailyChallengeSummary.subject.vi}") - private String dailyChallengeSummaryMailSubjectVi; + @Value("${mail.dailyChallengeSummary.subject.en}") + private String dailyChallengeSummaryMailSubjectEn; - @Resource - private Template notifyChallengeTimelineMailTemplateVi; + @Value("${mail.dailyChallengeSummary.subject.vi}") + private String dailyChallengeSummaryMailSubjectVi; - @Resource - private Template notifyChallengeTimelineMailTemplateEn; + @Resource + private Template notifyChallengeTimelineMailTemplateVi; - @Resource - private Template dailyChallengeSummaryMailTemplateVi; + @Resource + private Template notifyChallengeTimelineMailTemplateEn; - @Resource - private Template dailyChallengeSummaryMailTemplateEn; + @Resource + private Template dailyChallengeSummaryMailTemplateVi; - @Resource - private EmailService emailService; + @Resource + private Template dailyChallengeSummaryMailTemplateEn; - public ChallengeEntity savePostChallenge(ChallengeDto challengeDto) throws Exception { - ChallengeEntity challengeEntity = dozerMapper.map(challengeDto, ChallengeEntity.class); - if (challengeDto.getChallengeId() == null) { - challengeEntity.setChallengeId(new Date().getTime()); - } - return challengeRepository.save(challengeEntity); - } - - public void sendPostChallengeEmailToEmployer(ChallengeEntity challengeEntity) - throws MessagingException, IOException, TemplateException { - String mailSubject = challengeEntity.getLang() == Language.vi ? postChallengeMailSubjectVn : postChallengeMailSubjectEn; - Address[] recipientAddresses = getRecipientAddresses(challengeEntity, true); - Template template = challengeEntity.getLang() == Language.vi ? postChallengeMailTemplateVi : postChallengeMailTemplateEn; - sendPostChallengeEmail(challengeEntity, mailSubject, recipientAddresses, template); - } + @Resource + private EmailService emailService; - public void sendPostChallengeEmailToTechloopies(ChallengeEntity challengeEntity, Boolean isNewChallenge) - throws MessagingException, IOException, TemplateException { - String mailSubject = isNewChallenge ? postChallengeTechloopiesMailSubject : - String.format(postChallengeTechloopiesUpdateMailSubject, challengeEntity.getChallengeName()); - Template mailTemplate = isNewChallenge ? postChallengeMailTemplateEn : postChallengeUpdateMailTemplateEn; - Address[] recipientAddresses = InternetAddress.parse(postChallengeTechloopiesMailList); - sendPostChallengeEmail(challengeEntity, mailSubject, recipientAddresses, mailTemplate); + public ChallengeEntity savePostChallenge(ChallengeDto challengeDto) throws Exception { + ChallengeEntity challengeEntity = dozerMapper.map(challengeDto, ChallengeEntity.class); + if (challengeDto.getChallengeId() == null) { + challengeEntity.setChallengeId(new Date().getTime()); } + return challengeRepository.save(challengeEntity); + } - @Override - public void sendEmailNotifyRegistrantAboutChallengeTimeline(ChallengeEntity challengeEntity, - ChallengeRegistrantEntity challengeRegistrantEntity, ChallengePhaseEnum challengePhase) throws Exception { - String mailSubject = getNotifyRegistrantChallengeTimelineSubject(challengeRegistrantEntity, challengePhase); - Address[] recipientAddresses = InternetAddress.parse(challengeRegistrantEntity.getRegistrantEmail()); - Template template = challengeRegistrantEntity.getLang() == Language.vi ? - notifyChallengeTimelineMailTemplateVi : notifyChallengeTimelineMailTemplateEn; - postChallengeMailMessage.setRecipients(Message.RecipientType.TO, recipientAddresses); - postChallengeMailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); - StringWriter stringWriter = new StringWriter(); - - Map templateModel = new HashMap<>(); - templateModel.put("challengeEntity", challengeEntity); - templateModel.put("webBaseUrl", webBaseUrl); - templateModel.put("technologies", StringUtils.join(challengeEntity.getTechnologies(), "
")); - templateModel.put("receivedEmails", StringUtils.join(challengeEntity.getReceivedEmails(), "
")); - templateModel.put("firstPlaceReward", challengeEntity.getFirstPlaceReward() != null ? challengeEntity.getFirstPlaceReward() : 0); - templateModel.put("secondPlaceReward", challengeEntity.getSecondPlaceReward() != null ? challengeEntity.getSecondPlaceReward() : 0); - templateModel.put("thirdPlaceReward", challengeEntity.getThirdPlaceReward() != null ? challengeEntity.getThirdPlaceReward() : 0); - templateModel.put("challengeId", challengeEntity.getChallengeId().toString()); - templateModel.put("challengeNameAlias", challengeEntity.getChallengeName().replaceAll("\\W", "-")); - - int numberOfDays = 0; - if (challengePhase == ChallengePhaseEnum.REGISTRATION) { - numberOfDays = DateTimeUtils.daysBetween(DateTimeUtils.currentDate(), challengeEntity.getRegistrationDateTime()) + 1; - } else if (challengePhase == ChallengePhaseEnum.IN_PROGRESS) { - numberOfDays = DateTimeUtils.daysBetween(DateTimeUtils.currentDate(), challengeEntity.getSubmissionDateTime()) + 1; - } + public void sendPostChallengeEmailToEmployer(ChallengeEntity challengeEntity) + throws MessagingException, IOException, TemplateException { + String mailSubject = challengeEntity.getLang() == Language.vi ? postChallengeMailSubjectVn : postChallengeMailSubjectEn; + Address[] recipientAddresses = getRecipientAddresses(challengeEntity, true); + Template template = challengeEntity.getLang() == Language.vi ? postChallengeMailTemplateVi : postChallengeMailTemplateEn; + sendPostChallengeEmail(challengeEntity, mailSubject, recipientAddresses, template); + } - templateModel.put("numberOfDays", numberOfDays); - templateModel.put("challengePhase", challengePhase.getValue()); - templateModel.put("challengeRegistrant", challengeRegistrantEntity); + public void sendPostChallengeEmailToTechloopies(ChallengeEntity challengeEntity, Boolean isNewChallenge) + throws MessagingException, IOException, TemplateException { + String mailSubject = isNewChallenge ? postChallengeTechloopiesMailSubject : + String.format(postChallengeTechloopiesUpdateMailSubject, challengeEntity.getChallengeName()); + Template mailTemplate = isNewChallenge ? postChallengeMailTemplateEn : postChallengeUpdateMailTemplateEn; + Address[] recipientAddresses = InternetAddress.parse(postChallengeTechloopiesMailList); + sendPostChallengeEmail(challengeEntity, mailSubject, recipientAddresses, mailTemplate); + } - template.process(templateModel, stringWriter); - mailSubject = String.format(mailSubject, numberOfDays, challengeEntity.getChallengeName()); - postChallengeMailMessage.setSubject(MimeUtility.encodeText(mailSubject, "UTF-8", null)); - postChallengeMailMessage.setText(stringWriter.toString(), "UTF-8", "html"); + @Override + public void sendEmailNotifyRegistrantAboutChallengeTimeline(ChallengeEntity challengeEntity, + ChallengeRegistrantEntity challengeRegistrantEntity, ChallengePhaseEnum challengePhase) throws Exception { + String mailSubject = getNotifyRegistrantChallengeTimelineSubject(challengeRegistrantEntity, challengePhase); + Address[] recipientAddresses = InternetAddress.parse(challengeRegistrantEntity.getRegistrantEmail()); + Template template = challengeRegistrantEntity.getLang() == Language.vi ? + notifyChallengeTimelineMailTemplateVi : notifyChallengeTimelineMailTemplateEn; + postChallengeMailMessage.setRecipients(Message.RecipientType.TO, recipientAddresses); + postChallengeMailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); + StringWriter stringWriter = new StringWriter(); + + Map templateModel = new HashMap<>(); + templateModel.put("challengeEntity", challengeEntity); + templateModel.put("webBaseUrl", webBaseUrl); + templateModel.put("technologies", StringUtils.join(challengeEntity.getTechnologies(), "
")); + templateModel.put("receivedEmails", StringUtils.join(challengeEntity.getReceivedEmails(), "
")); + templateModel.put("firstPlaceReward", challengeEntity.getFirstPlaceReward() != null ? challengeEntity.getFirstPlaceReward() : 0); + templateModel.put("secondPlaceReward", challengeEntity.getSecondPlaceReward() != null ? challengeEntity.getSecondPlaceReward() : 0); + templateModel.put("thirdPlaceReward", challengeEntity.getThirdPlaceReward() != null ? challengeEntity.getThirdPlaceReward() : 0); + templateModel.put("challengeId", challengeEntity.getChallengeId().toString()); + templateModel.put("challengeNameAlias", challengeEntity.getChallengeName().replaceAll("\\W", "-")); + + int numberOfDays = 0; + if (challengePhase == ChallengePhaseEnum.REGISTRATION) { + numberOfDays = daysBetween(currentDate(), challengeEntity.getRegistrationDateTime()) + 1; + } + else if (challengePhase == ChallengePhaseEnum.IN_PROGRESS) { + numberOfDays = daysBetween(currentDate(), challengeEntity.getSubmissionDateTime()) + 1; + } + + templateModel.put("numberOfDays", numberOfDays); + templateModel.put("challengePhase", challengePhase.getValue()); + templateModel.put("challengeRegistrant", challengeRegistrantEntity); + + template.process(templateModel, stringWriter); + mailSubject = String.format(mailSubject, numberOfDays, challengeEntity.getChallengeName()); + postChallengeMailMessage.setSubject(MimeUtility.encodeText(mailSubject, "UTF-8", null)); + postChallengeMailMessage.setText(stringWriter.toString(), "UTF-8", "html"); + + stringWriter.flush(); + postChallengeMailMessage.saveChanges(); + mailSender.send(postChallengeMailMessage); + LOGGER.info(postChallengeMailMessage.getMessageID() + " has been sent to users " + + postChallengeMailMessage.getAllRecipients() + " with challengeId = " + challengeEntity.getChallengeId()); + } - stringWriter.flush(); - postChallengeMailMessage.saveChanges(); - mailSender.send(postChallengeMailMessage); - LOGGER.info(postChallengeMailMessage.getMessageID() + " has been sent to users " + - postChallengeMailMessage.getAllRecipients() + " with challengeId = " + challengeEntity.getChallengeId()); + private String getNotifyRegistrantChallengeTimelineSubject( + ChallengeRegistrantEntity challengeRegistrantEntity, ChallengePhaseEnum challengePhase) { + if (challengeRegistrantEntity.getLang() == Language.vi) { + if (challengePhase == ChallengePhaseEnum.REGISTRATION) { + return notifyChallengeTimelineRegistrationMailSubjectVn; + } + else { + return notifyChallengeTimelineInProgressMailSubjectVn; + } } - - private String getNotifyRegistrantChallengeTimelineSubject( - ChallengeRegistrantEntity challengeRegistrantEntity, ChallengePhaseEnum challengePhase) { - if (challengeRegistrantEntity.getLang() == Language.vi) { - if (challengePhase == ChallengePhaseEnum.REGISTRATION) { - return notifyChallengeTimelineRegistrationMailSubjectVn; - } else { - return notifyChallengeTimelineInProgressMailSubjectVn; - } - } else { - if (challengePhase == ChallengePhaseEnum.REGISTRATION) { - return notifyChallengeTimelineRegistrationMailSubjectEn; - } else { - return notifyChallengeTimelineInProgressMailSubjectEn; - } - } + else { + if (challengePhase == ChallengePhaseEnum.REGISTRATION) { + return notifyChallengeTimelineRegistrationMailSubjectEn; + } + else { + return notifyChallengeTimelineInProgressMailSubjectEn; + } } + } - public ChallengeDetailDto getChallengeDetail(Long challengeId) { - ChallengeEntity challengeEntity = challengeRepository.findOne(challengeId); - if (challengeEntity != null && !Boolean.TRUE.equals(challengeEntity.getExpired())) { - ChallengeDetailDto challengeDetailDto = dozerMapper.map(challengeEntity, ChallengeDetailDto.class); - challengeDetailDto.setNumberOfRegistrants(getNumberOfRegistrants(challengeId)); - return challengeDetailDto; - } - return null; - } + public Long getNumberOfRegistrants(Long challengeId) { + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withSearchType(SearchType.COUNT); + searchQueryBuilder.withFilter(FilterBuilders.termFilter("challengeId", challengeId)); + return challengeRegistrantRepository.search(searchQueryBuilder.build()).getTotalElements(); + } - public Long getNumberOfRegistrants(Long challengeId) { - NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withSearchType(SearchType.COUNT); - searchQueryBuilder.withFilter(FilterBuilders.termFilter("challengeId", challengeId)); - return challengeRegistrantRepository.search(searchQueryBuilder.build()).getTotalElements(); - } + public void sendApplicationEmailToContestant(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity) throws MessagingException, IOException, TemplateException { + Template template = challengeRegistrantEntity.getLang() == Language.vi ? + confirmUserJoinChallengeMailTemplateVi : confirmUserJoinChallengeMailTemplateEn; + String mailSubject = challengeRegistrantEntity.getLang() == Language.vi ? + confirmUserJoinChallengeMailSubjectVn : confirmUserJoinChallengeMailSubjectEn; + mailSubject = String.format(mailSubject, challengeEntity.getChallengeName()); + Address[] emailAddress = InternetAddress.parse(challengeRegistrantEntity.getRegistrantEmail()); + sendContestApplicationEmail(template, mailSubject, emailAddress, challengeEntity, challengeRegistrantEntity, false); + } - public void sendApplicationEmailToContestant(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity) throws MessagingException, IOException, TemplateException { - Template template = challengeRegistrantEntity.getLang() == Language.vi ? - confirmUserJoinChallengeMailTemplateVi : confirmUserJoinChallengeMailTemplateEn; - String mailSubject = challengeRegistrantEntity.getLang() == Language.vi ? - confirmUserJoinChallengeMailSubjectVn : confirmUserJoinChallengeMailSubjectEn; - mailSubject = String.format(mailSubject, challengeEntity.getChallengeName()); - Address[] emailAddress = InternetAddress.parse(challengeRegistrantEntity.getRegistrantEmail()); - sendContestApplicationEmail(template, mailSubject, emailAddress, challengeEntity, challengeRegistrantEntity, false); - } + public void sendApplicationEmailToEmployer(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity) throws MessagingException, IOException, TemplateException { + Template template = challengeRegistrantEntity.getLang() == Language.vi ? + alertEmployerChallengeMailTemplateVi : alertEmployerChallengeMailTemplateEn; + String mailSubject = challengeRegistrantEntity.getLang() == Language.vi ? + alertEmployerChallengeMailSubjectVn : alertEmployerChallengeMailSubjectEn; + mailSubject = String.format(mailSubject, challengeEntity.getChallengeName()); + Address[] emailAddress = getRecipientAddresses(challengeEntity, false); + sendContestApplicationEmail(template, mailSubject, emailAddress, challengeEntity, challengeRegistrantEntity, true); + } - public void sendApplicationEmailToEmployer(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity) throws MessagingException, IOException, TemplateException { - Template template = challengeRegistrantEntity.getLang() == Language.vi ? - alertEmployerChallengeMailTemplateVi : alertEmployerChallengeMailTemplateEn; - String mailSubject = challengeRegistrantEntity.getLang() == Language.vi ? - alertEmployerChallengeMailSubjectVn : alertEmployerChallengeMailSubjectEn; - mailSubject = String.format(mailSubject, challengeEntity.getChallengeName()); - Address[] emailAddress = getRecipientAddresses(challengeEntity, false); - sendContestApplicationEmail(template, mailSubject, emailAddress, challengeEntity, challengeRegistrantEntity, true); + public long joinChallenge(ChallengeRegistrantDto challengeRegistrantDto) { + ChallengeRegistrantEntity entity = joinChallengeEntity(challengeRegistrantDto); + if (entity != null) { + return getNumberOfRegistrants(challengeRegistrantDto.getChallengeId()); } + return 0; + } - public long joinChallenge(ChallengeRegistrantDto challengeRegistrantDto) throws MessagingException, IOException, TemplateException { - Long challengeId = challengeRegistrantDto.getChallengeId(); - boolean isExist = checkIfChallengeRegistrantExist(challengeId, challengeRegistrantDto.getRegistrantEmail()); - - if (!isExist) { - ChallengeRegistrantEntity challengeRegistrantEntity = dozerMapper.map(challengeRegistrantDto, ChallengeRegistrantEntity.class); - ChallengeEntity challengeEntity = challengeRepository.findOne(challengeId); - sendApplicationEmailToContestant(challengeEntity, challengeRegistrantEntity); - sendApplicationEmailToEmployer(challengeEntity, challengeRegistrantEntity); - challengeRegistrantEntity.setMailSent(Boolean.TRUE); - challengeRegistrantEntity.setRegistrantId(new Date().getTime()); - challengeRegistrantRepository.save(challengeRegistrantEntity); - } + public ChallengeRegistrantEntity joinChallengeEntity(ChallengeRegistrantDto challengeRegistrantDto) { + Long challengeId = challengeRegistrantDto.getChallengeId(); + boolean isExist = checkIfChallengeRegistrantExist(challengeId, challengeRegistrantDto.getRegistrantEmail()); - return getNumberOfRegistrants(challengeId); + if (!isExist) { + ChallengeRegistrantEntity challengeRegistrantEntity = dozerMapper.map(challengeRegistrantDto, ChallengeRegistrantEntity.class); + ChallengeEntity challengeEntity = challengeRepository.findOne(challengeId); + challengeRegistrantEntity.setRegistrantId(new Date().getTime()); + challengeRegistrantEntity = challengeRegistrantRepository.save(challengeRegistrantEntity); + try { + sendApplicationEmailToContestant(challengeEntity, challengeRegistrantEntity); + sendApplicationEmailToEmployer(challengeEntity, challengeRegistrantEntity); + challengeRegistrantEntity.setMailSent(Boolean.TRUE); + return challengeRegistrantRepository.save(challengeRegistrantEntity); + } + catch (Exception e) { + LOGGER.debug("Can not send email", e); + } } - public List listChallenges() { + return null; + } + + public List listChallenges() { // List challenges = new ArrayList<>(); // Iterator challengeIter = challengeRepository.findAll().iterator(); // while (challengeIter.hasNext()) { @@ -325,169 +343,173 @@ public List listChallenges() { // challenges.add(challengeDetailDto); // } // return sortChallengesByDescendingStartDate(challenges); - TermQueryBuilder notExpiredQuery = termQuery("expired", Boolean.TRUE); - Iterable challengeIterator = challengeRepository.search(boolQuery().mustNot(notExpiredQuery)); - ArrayList challenges = new ArrayList<>(); - challengeIterator.forEach(challengeEntity -> { - ChallengeDetailDto challengeDetailDto = dozerMapper.map(challengeEntity, ChallengeDetailDto.class); - challengeDetailDto.setNumberOfRegistrants(getNumberOfRegistrants(challengeEntity.getChallengeId())); - challenges.add(challengeDetailDto); - }); - return sortChallengesByDescendingStartDate(challenges); - } - - private void sendContestApplicationEmail(Template template, String mailSubject, Address[] recipientAddresses, - ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity, boolean hasReplyTo) - throws MessagingException, IOException, TemplateException { - postChallengeMailMessage.setRecipients(Message.RecipientType.TO, recipientAddresses); + TermQueryBuilder notExpiredQuery = termQuery("expired", Boolean.TRUE); + Iterable challengeIterator = challengeRepository.search(boolQuery().mustNot(notExpiredQuery)); + ArrayList challenges = new ArrayList<>(); + challengeIterator.forEach(challengeEntity -> { + ChallengeDetailDto challengeDetailDto = dozerMapper.map(challengeEntity, ChallengeDetailDto.class); + challengeDetailDto.setNumberOfRegistrants(getNumberOfRegistrants(challengeEntity.getChallengeId())); + challenges.add(challengeDetailDto); + }); + return sortChallengesByDescendingStartDate(challenges); + } - if (hasReplyTo) { - postChallengeMailMessage.setReplyTo(InternetAddress.parse(challengeRegistrantEntity.getRegistrantEmail())); - } else { - postChallengeMailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); - } + private void sendContestApplicationEmail(Template template, String mailSubject, Address[] recipientAddresses, + ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity, boolean hasReplyTo) + throws MessagingException, IOException, TemplateException { + postChallengeMailMessage.setRecipients(Message.RecipientType.TO, recipientAddresses); + + if (hasReplyTo) { + postChallengeMailMessage.setReplyTo(InternetAddress.parse(challengeRegistrantEntity.getRegistrantEmail())); + } + else { + postChallengeMailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); + } + + StringWriter stringWriter = new StringWriter(); + Map templateModel = new HashMap<>(); + templateModel.put("webBaseUrl", webBaseUrl); + templateModel.put("challengeName", challengeEntity.getChallengeName()); + templateModel.put("businessRequirement", challengeEntity.getBusinessRequirement()); + templateModel.put("generalNote", challengeEntity.getGeneralNote()); + templateModel.put("technologies", StringUtils.join(challengeEntity.getTechnologies(), "
")); + templateModel.put("documents", challengeEntity.getDocuments()); + templateModel.put("deliverables", challengeEntity.getDeliverables()); + templateModel.put("receivedEmails", StringUtils.join(challengeEntity.getReceivedEmails(), "
")); + templateModel.put("reviewStyle", challengeEntity.getReviewStyle()); + templateModel.put("startDate", challengeEntity.getStartDateTime()); + templateModel.put("registrationDate", challengeEntity.getRegistrationDateTime()); + templateModel.put("submissionDate", challengeEntity.getSubmissionDateTime()); + templateModel.put("qualityIdea", challengeEntity.getQualityIdea()); + templateModel.put("firstPlaceReward", challengeEntity.getFirstPlaceReward() != null ? challengeEntity.getFirstPlaceReward() : 0); + templateModel.put("secondPlaceReward", challengeEntity.getSecondPlaceReward() != null ? challengeEntity.getSecondPlaceReward() : 0); + templateModel.put("thirdPlaceReward", challengeEntity.getThirdPlaceReward() != null ? challengeEntity.getThirdPlaceReward() : 0); + templateModel.put("challengeId", challengeEntity.getChallengeId().toString()); + templateModel.put("authorEmail", challengeEntity.getAuthorEmail()); + templateModel.put("challengeOverview", challengeEntity.getChallengeOverview()); + templateModel.put("firstName", challengeRegistrantEntity.getRegistrantFirstName()); + templateModel.put("lastName", challengeRegistrantEntity.getRegistrantLastName()); + templateModel.put("registrantEmail", challengeRegistrantEntity.getRegistrantEmail()); + templateModel.put("challengeNameAlias", challengeEntity.getChallengeName().replaceAll("\\W", "-")); + + template.process(templateModel, stringWriter); + postChallengeMailMessage.setSubject(MimeUtility.encodeText(mailSubject, "UTF-8", null)); + postChallengeMailMessage.setText(stringWriter.toString(), "UTF-8", "html"); + + stringWriter.flush(); + postChallengeMailMessage.saveChanges(); + mailSender.send(postChallengeMailMessage); + } - StringWriter stringWriter = new StringWriter(); - Map templateModel = new HashMap<>(); - templateModel.put("webBaseUrl", webBaseUrl); - templateModel.put("challengeName", challengeEntity.getChallengeName()); - templateModel.put("businessRequirement", challengeEntity.getBusinessRequirement()); - templateModel.put("generalNote", challengeEntity.getGeneralNote()); - templateModel.put("technologies", StringUtils.join(challengeEntity.getTechnologies(), "
")); - templateModel.put("documents", challengeEntity.getDocuments()); - templateModel.put("deliverables", challengeEntity.getDeliverables()); - templateModel.put("receivedEmails", StringUtils.join(challengeEntity.getReceivedEmails(), "
")); - templateModel.put("reviewStyle", challengeEntity.getReviewStyle()); - templateModel.put("startDate", challengeEntity.getStartDateTime()); - templateModel.put("registrationDate", challengeEntity.getRegistrationDateTime()); - templateModel.put("submissionDate", challengeEntity.getSubmissionDateTime()); - templateModel.put("qualityIdea", challengeEntity.getQualityIdea()); - templateModel.put("firstPlaceReward", challengeEntity.getFirstPlaceReward() != null ? challengeEntity.getFirstPlaceReward() : 0); - templateModel.put("secondPlaceReward", challengeEntity.getSecondPlaceReward() != null ? challengeEntity.getSecondPlaceReward() : 0); - templateModel.put("thirdPlaceReward", challengeEntity.getThirdPlaceReward() != null ? challengeEntity.getThirdPlaceReward() : 0); - templateModel.put("challengeId", challengeEntity.getChallengeId().toString()); - templateModel.put("authorEmail", challengeEntity.getAuthorEmail()); - templateModel.put("challengeOverview", challengeEntity.getChallengeOverview()); - templateModel.put("firstName", challengeRegistrantEntity.getRegistrantFirstName()); - templateModel.put("lastName", challengeRegistrantEntity.getRegistrantLastName()); - templateModel.put("registrantEmail", challengeRegistrantEntity.getRegistrantEmail()); - templateModel.put("challengeNameAlias", challengeEntity.getChallengeName().replaceAll("\\W", "-")); - - template.process(templateModel, stringWriter); - postChallengeMailMessage.setSubject(MimeUtility.encodeText(mailSubject, "UTF-8", null)); - postChallengeMailMessage.setText(stringWriter.toString(), "UTF-8", "html"); - - stringWriter.flush(); - postChallengeMailMessage.saveChanges(); - mailSender.send(postChallengeMailMessage); - } + private void sendPostChallengeEmail(ChallengeEntity challengeEntity, String mailSubject, + Address[] recipientAddresses, Template template) throws MessagingException, IOException, TemplateException { + postChallengeMailMessage.setRecipients(Message.RecipientType.TO, recipientAddresses); + postChallengeMailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); + StringWriter stringWriter = new StringWriter(); + + Map templateModel = new HashMap<>(); + templateModel.put("webBaseUrl", webBaseUrl); + templateModel.put("challengeName", challengeEntity.getChallengeName()); + templateModel.put("businessRequirement", challengeEntity.getBusinessRequirement()); + templateModel.put("generalNote", challengeEntity.getGeneralNote()); + templateModel.put("technologies", StringUtils.join(challengeEntity.getTechnologies(), "
")); + templateModel.put("documents", challengeEntity.getDocuments()); + templateModel.put("deliverables", challengeEntity.getDeliverables()); + templateModel.put("receivedEmails", StringUtils.join(challengeEntity.getReceivedEmails(), "
")); + templateModel.put("reviewStyle", challengeEntity.getReviewStyle()); + templateModel.put("startDate", challengeEntity.getStartDateTime()); + templateModel.put("registrationDate", challengeEntity.getRegistrationDateTime()); + templateModel.put("submissionDate", challengeEntity.getSubmissionDateTime()); + templateModel.put("qualityIdea", challengeEntity.getQualityIdea()); + templateModel.put("firstPlaceReward", challengeEntity.getFirstPlaceReward() != null ? challengeEntity.getFirstPlaceReward() : 0); + templateModel.put("secondPlaceReward", challengeEntity.getSecondPlaceReward() != null ? challengeEntity.getSecondPlaceReward() : 0); + templateModel.put("thirdPlaceReward", challengeEntity.getThirdPlaceReward() != null ? challengeEntity.getThirdPlaceReward() : 0); + templateModel.put("challengeId", challengeEntity.getChallengeId().toString()); + templateModel.put("authorEmail", challengeEntity.getAuthorEmail()); + templateModel.put("challengeOverview", challengeEntity.getChallengeOverview()); + templateModel.put("challengeNameAlias", challengeEntity.getChallengeName().replaceAll("\\W", "-")); + + template.process(templateModel, stringWriter); + mailSubject = String.format(mailSubject, challengeEntity.getAuthorEmail(), challengeEntity.getChallengeName()); + postChallengeMailMessage.setSubject(MimeUtility.encodeText(mailSubject, "UTF-8", null)); + postChallengeMailMessage.setText(stringWriter.toString(), "UTF-8", "html"); + + stringWriter.flush(); + postChallengeMailMessage.saveChanges(); + mailSender.send(postChallengeMailMessage); + } - private void sendPostChallengeEmail(ChallengeEntity challengeEntity, String mailSubject, - Address[] recipientAddresses, Template template) throws MessagingException, IOException, TemplateException { - postChallengeMailMessage.setRecipients(Message.RecipientType.TO, recipientAddresses); - postChallengeMailMessage.setReplyTo(InternetAddress.parse(mailTechlooperReplyTo)); - StringWriter stringWriter = new StringWriter(); - - Map templateModel = new HashMap<>(); - templateModel.put("webBaseUrl", webBaseUrl); - templateModel.put("challengeName", challengeEntity.getChallengeName()); - templateModel.put("businessRequirement", challengeEntity.getBusinessRequirement()); - templateModel.put("generalNote", challengeEntity.getGeneralNote()); - templateModel.put("technologies", StringUtils.join(challengeEntity.getTechnologies(), "
")); - templateModel.put("documents", challengeEntity.getDocuments()); - templateModel.put("deliverables", challengeEntity.getDeliverables()); - templateModel.put("receivedEmails", StringUtils.join(challengeEntity.getReceivedEmails(), "
")); - templateModel.put("reviewStyle", challengeEntity.getReviewStyle()); - templateModel.put("startDate", challengeEntity.getStartDateTime()); - templateModel.put("registrationDate", challengeEntity.getRegistrationDateTime()); - templateModel.put("submissionDate", challengeEntity.getSubmissionDateTime()); - templateModel.put("qualityIdea", challengeEntity.getQualityIdea()); - templateModel.put("firstPlaceReward", challengeEntity.getFirstPlaceReward() != null ? challengeEntity.getFirstPlaceReward() : 0); - templateModel.put("secondPlaceReward", challengeEntity.getSecondPlaceReward() != null ? challengeEntity.getSecondPlaceReward() : 0); - templateModel.put("thirdPlaceReward", challengeEntity.getThirdPlaceReward() != null ? challengeEntity.getThirdPlaceReward() : 0); - templateModel.put("challengeId", challengeEntity.getChallengeId().toString()); - templateModel.put("authorEmail", challengeEntity.getAuthorEmail()); - templateModel.put("challengeOverview", challengeEntity.getChallengeOverview()); - templateModel.put("challengeNameAlias", challengeEntity.getChallengeName().replaceAll("\\W", "-")); - - template.process(templateModel, stringWriter); - mailSubject = String.format(mailSubject, challengeEntity.getAuthorEmail(), challengeEntity.getChallengeName()); - postChallengeMailMessage.setSubject(MimeUtility.encodeText(mailSubject, "UTF-8", null)); - postChallengeMailMessage.setText(stringWriter.toString(), "UTF-8", "html"); - - stringWriter.flush(); - postChallengeMailMessage.saveChanges(); - mailSender.send(postChallengeMailMessage); + private Address[] getRecipientAddresses(ChallengeEntity challengeEntity, boolean includeAuthor) throws AddressException { + Set emails = new HashSet<>(challengeEntity.getReceivedEmails()); + if (includeAuthor) { + emails.add(challengeEntity.getAuthorEmail()); } + return InternetAddress.parse(StringUtils.join(emails, ',')); + } - private Address[] getRecipientAddresses(ChallengeEntity challengeEntity, boolean includeAuthor) throws AddressException { - Set emails = new HashSet<>(challengeEntity.getReceivedEmails()); - if (includeAuthor) { - emails.add(challengeEntity.getAuthorEmail()); + private List sortChallengesByDescendingStartDate(List challenges) { + SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); + return challenges.stream().sorted((challenge1, challenge2) -> { + try { + if (challenge2.getStartDateTime() == null) { + return -1; } - return InternetAddress.parse(StringUtils.join(emails, ',')); - } - - private List sortChallengesByDescendingStartDate(List challenges) { - SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); - return challenges.stream().sorted((challenge1, challenge2) -> { - try { - if (challenge2.getStartDateTime() == null) { - return -1; - } else if (challenge1.getStartDateTime() == null) { - return 1; - } - long challenge2StartDate = sdf.parse(challenge2.getStartDateTime()).getTime(); - long challenge1StartDate = sdf.parse(challenge1.getStartDateTime()).getTime(); - if (challenge2StartDate - challenge1StartDate > 0) { - return 1; - } else if (challenge2StartDate - challenge1StartDate < 0) { - return -1; - } else { - return 0; - } - } catch (ParseException e) { - return 0; - } - }).collect(Collectors.toList()); - } + else if (challenge1.getStartDateTime() == null) { + return 1; + } + long challenge2StartDate = sdf.parse(challenge2.getStartDateTime()).getTime(); + long challenge1StartDate = sdf.parse(challenge1.getStartDateTime()).getTime(); + if (challenge2StartDate - challenge1StartDate > 0) { + return 1; + } + else if (challenge2StartDate - challenge1StartDate < 0) { + return -1; + } + else { + return 0; + } + } + catch (ParseException e) { + return 0; + } + }).collect(toList()); + } - public boolean checkIfChallengeRegistrantExist(Long challengeId, String email) { - NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder(); - searchQueryBuilder.withQuery(boolQuery() - .must(matchPhraseQuery("registrantEmail", email)) - .must(termQuery("challengeId", challengeId)) - .must(termQuery("mailSent", true))); + public boolean checkIfChallengeRegistrantExist(Long challengeId, String email) { + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder(); + searchQueryBuilder.withQuery(boolQuery() + .must(matchPhraseQuery("registrantEmail", email)) + .must(termQuery("challengeId", challengeId))); - long total = challengeRegistrantRepository.search(searchQueryBuilder.build()).getTotalElements(); - return (total > 0); - } + long total = challengeRegistrantRepository.search(searchQueryBuilder.build()).getTotalElements(); + return (total > 0); + } - @Override - public Long getTotalNumberOfChallenges() { - return challengeRepository.count(); - } + @Override + public Long getTotalNumberOfChallenges() { + return challengeRepository.count(); + } - @Override - public Double getTotalAmountOfPrizeValues() { - NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withSearchType(SearchType.COUNT); - searchQueryBuilder.withQuery(matchAllQuery()); + @Override + public Double getTotalAmountOfPrizeValues() { + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withSearchType(SearchType.COUNT); + searchQueryBuilder.withQuery(matchAllQuery()); - SumBuilder sumPrizeBuilder = sum("sumPrize").script("doc['firstPlaceReward'].value + doc['secondPlaceReward'].value + doc['thirdPlaceReward'].value"); - searchQueryBuilder.addAggregation(sumPrizeBuilder); + SumBuilder sumPrizeBuilder = sum("sumPrize").script("doc['firstPlaceReward'].value + doc['secondPlaceReward'].value + doc['thirdPlaceReward'].value"); + searchQueryBuilder.addAggregation(sumPrizeBuilder); - Aggregations aggregations = elasticsearchTemplateUserImport.query(searchQueryBuilder.build(), SearchResponse::getAggregations); - Sum sumReponse = aggregations.get("sumPrize"); - return sumReponse != null ? sumReponse.getValue() : 0D; - } + Aggregations aggregations = elasticsearchTemplateUserImport.query(searchQueryBuilder.build(), SearchResponse::getAggregations); + Sum sumReponse = aggregations.get("sumPrize"); + return sumReponse != null ? sumReponse.getValue() : 0D; + } - @Override - public Long getTotalNumberOfRegistrants() { - return challengeRegistrantRepository.count(); - } + @Override + public Long getTotalNumberOfRegistrants() { + return challengeRegistrantRepository.count(); + } - @Override - public ChallengeDetailDto getTheLatestChallenge() { + @Override + public ChallengeDetailDto getTheLatestChallenge() { // NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder(); // searchQueryBuilder.withQuery(QueryBuilders.matchAllQuery()); // searchQueryBuilder.withSort(SortBuilders.fieldSort("challengeId").order(SortOrder.DESC)); @@ -498,241 +520,269 @@ public ChallengeDetailDto getTheLatestChallenge() { // ChallengeEntity challengeEntity = challengeEntities.get(0); // return dozerMapper.map(challengeEntity, ChallengeDetailDto.class); // } - return listChallenges().get(0); - } + return listChallenges().get(0); + } + + public Collection findByOwnerAndCondition(String owner, + Predicate condition) { + NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withIndices(techlooperIndex).withTypes("challenge"); + QueryStringQueryBuilder query = queryStringQuery(owner).defaultField("authorEmail"); + queryBuilder.withFilter(FilterBuilders.queryFilter(query)); + + int pageIndex = 0; + Set challenges = new HashSet<>(); + while (true) { + queryBuilder.withPageable(new PageRequest(pageIndex++, 100)); + FacetedPage page = challengeRepository.search(queryBuilder.build()); + if (!page.hasContent()) { + break; + } - public Collection findByOwnerAndCondition(String owner, - Predicate condition) { - NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withIndices(techlooperIndex).withTypes("challenge"); - QueryStringQueryBuilder query = queryStringQuery(owner).defaultField("authorEmail"); - queryBuilder.withFilter(FilterBuilders.queryFilter(query)); - - int pageIndex = 0; - Set challenges = new HashSet<>(); - while (true) { - queryBuilder.withPageable(new PageRequest(pageIndex++, 100)); - FacetedPage page = challengeRepository.search(queryBuilder.build()); - if (!page.hasContent()) { - break; - } - - page.spliterator().forEachRemaining(challenge -> { - if (condition.test(challenge)) { - ChallengeDetailDto challengeDetailDto = dozerMapper.map(challenge, ChallengeDetailDto.class); - challengeDetailDto.setNumberOfRegistrants(countRegistrantsByChallengeId(challenge.getChallengeId())); - challenges.add(challengeDetailDto); - } - }); + page.spliterator().forEachRemaining(challenge -> { + if (condition.test(challenge)) { + ChallengeDetailDto challengeDetailDto = dozerMapper.map(challenge, ChallengeDetailDto.class); + challengeDetailDto.setNumberOfRegistrants(countRegistrantsByChallengeId(challenge.getChallengeId())); + challenges.add(challengeDetailDto); } - return challenges; + }); } + return challenges; + } - public List listChallenges(String ownerEmail) { - MatchQueryBuilder authorEmailQuery = matchQuery("authorEmail", ownerEmail).minimumShouldMatch("100%"); - TermQueryBuilder notExpiredQuery = termQuery("expired", Boolean.TRUE); - Iterable challenges = challengeRepository.search(boolQuery().must(authorEmailQuery).mustNot(notExpiredQuery)); - ArrayList dtos = new ArrayList<>(); - challenges.forEach(challengeEntity -> { - ChallengeDetailDto challengeDetailDto = dozerMapper.map(challengeEntity, ChallengeDetailDto.class); - challengeDetailDto.setNumberOfRegistrants(getNumberOfRegistrants(challengeEntity.getChallengeId())); - dtos.add(challengeDetailDto); - }); - dozerMapper.map(challenges, dtos); - return dtos; - } + public List listChallenges(String ownerEmail) { + List result = new ArrayList<>(); + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withTypes("challenge"); + MatchQueryBuilder authorEmailQuery = matchQuery("authorEmail", ownerEmail).minimumShouldMatch("100%"); + TermQueryBuilder notExpiredQuery = termQuery("expired", Boolean.TRUE); - public Collection findInProgressChallenges(String owner) { - DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("dd/MM/yyyy"); - return findByOwnerAndCondition(owner, challengeEntity -> { - DateTime startDate = dateTimeFormatter.parseDateTime(challengeEntity.getStartDateTime()); - DateTime submissionDate = dateTimeFormatter.parseDateTime(challengeEntity.getSubmissionDateTime()); - DateTime now = DateTime.now(); - boolean inRange = now.isAfter(startDate) && now.isBefore(submissionDate); - boolean atBoundary = now.isEqual(startDate) || now.isEqual(submissionDate); - return inRange || atBoundary; - }); - } + searchQueryBuilder.withQuery(boolQuery().must(authorEmailQuery).mustNot(notExpiredQuery)); + List challengeEntities = DataUtils.getAllEntities(challengeRepository, searchQueryBuilder); - public Long countRegistrantsByChallengeId(Long challengeId) { - NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withIndices(techlooperIndex).withTypes("challengeRegistrant"); - queryBuilder.withFilter(FilterBuilders.queryFilter(termQuery("challengeId", challengeId))) - .withSearchType(SearchType.COUNT); - return challengeRegistrantRepository.search(queryBuilder.build()).getTotalElements(); + for (ChallengeEntity challengeEntity : challengeEntities) { + ChallengeDetailDto challengeDetailDto = dozerMapper.map(challengeEntity, ChallengeDetailDto.class); + challengeDetailDto.setNumberOfRegistrants(getNumberOfRegistrants(challengeDetailDto.getChallengeId())); + result.add(challengeDetailDto); } + return result; + } - public boolean delete(Long id, String ownerEmail) { - ChallengeEntity challenge = challengeRepository.findOne(id); - if (challenge.getAuthorEmail().equalsIgnoreCase(ownerEmail)) { - challenge.setExpired(Boolean.TRUE); - challengeRepository.save(challenge); - return true; - } - return false; - } + public Collection findInProgressChallenges(String owner) { + DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("dd/MM/yyyy"); + return findByOwnerAndCondition(owner, challengeEntity -> { + DateTime startDate = dateTimeFormatter.parseDateTime(challengeEntity.getStartDateTime()); + DateTime submissionDate = dateTimeFormatter.parseDateTime(challengeEntity.getSubmissionDateTime()); + DateTime now = DateTime.now(); + boolean inRange = now.isAfter(startDate) && now.isBefore(submissionDate); + boolean atBoundary = now.isEqual(startDate) || now.isEqual(submissionDate); + return inRange || atBoundary; + }); + } - public ChallengeDto findChallengeById(Long id) { - return dozerMapper.map(challengeRepository.findOne(id), ChallengeDto.class); + public Long countRegistrantsByChallengeId(Long challengeId) { + NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withIndices(techlooperIndex).withTypes("challengeRegistrant"); + queryBuilder.withFilter(FilterBuilders.queryFilter(termQuery("challengeId", challengeId))) + .withSearchType(SearchType.COUNT); + return challengeRegistrantRepository.search(queryBuilder.build()).getTotalElements(); + } + + public boolean delete(Long id, String ownerEmail) { + ChallengeEntity challenge = challengeRepository.findOne(id); + if (challenge.getAuthorEmail().equalsIgnoreCase(ownerEmail)) { + challenge.setExpired(Boolean.TRUE); + challengeRepository.save(challenge); + return true; } + return false; + } - public Set findRegistrantsByOwner(String ownerEmail, Long challengeId) { - BoolQueryBuilder boolQueryBuilder = boolQuery(); + public ChallengeDto findChallengeById(Long id) { + return dozerMapper.map(challengeRepository.findOne(id), ChallengeDto.class); + } - if (StringUtils.isNotEmpty(ownerEmail)) { - boolQueryBuilder.must(matchQuery("authorEmail", ownerEmail).minimumShouldMatch("100%")); - } + public Set findRegistrantsByOwner(RegistrantFilterCondition condition) throws ParseException { + Set result = new HashSet<>(); + Long challengeId = condition.getChallengeId(); + ChallengeEntity challengeEntity = challengeRepository.findOne(challengeId); + + if (challengeEntity != null && challengeEntity.getAuthorEmail().equals(condition.getAuthorEmail())) { + List registrants = filterChallengeRegistrantByDate(condition); + for (ChallengeRegistrantEntity registrant : registrants) { + ChallengeRegistrantDto registrantDto = dozerMapper.map(registrant, ChallengeRegistrantDto.class); + registrantDto.setSubmissions(findChallengeSubmissionByRegistrant(challengeId, registrant.getRegistrantId())); + result.add(registrantDto); + } + } - TermQueryBuilder challengeQuery = termQuery("challengeId", challengeId); - if (challengeId != null) { - boolQueryBuilder.must(challengeQuery); - } + return result; + } - boolQueryBuilder.mustNot(termQuery("expired", Boolean.TRUE)); - Iterator challengeIterator = challengeRepository.search(boolQueryBuilder).iterator(); - Set registrantDtos = new HashSet<>(); + public ChallengeRegistrantDto saveRegistrant(String ownerEmail, ChallengeRegistrantDto challengeRegistrantDto) { + ChallengeEntity challenge = challengeRepository.findOne(challengeRegistrantDto.getChallengeId()); + if (ownerEmail.equalsIgnoreCase(challenge.getAuthorEmail())) { + ChallengeRegistrantEntity registrant = challengeRegistrantRepository.findOne(challengeRegistrantDto.getRegistrantId()); + challengeRegistrantDto.setRegistrantEmail(registrant.getRegistrantEmail()); + dozerMapper.map(challengeRegistrantDto, registrant); + registrant = challengeRegistrantRepository.save(registrant); + challengeRegistrantDto = dozerMapper.map(registrant, ChallengeRegistrantDto.class); +// challengeRegistrantDto.setRegistrantEmail(null); + } + return challengeRegistrantDto; + } - if (challengeIterator.hasNext()) { - Iterator registrants = challengeRegistrantRepository.search(challengeQuery).iterator(); - registrants.forEachRemaining(registrant -> registrantDtos.add(dozerMapper.map(registrant, ChallengeRegistrantDto.class))); - } + @Override + public List findChallengeRegistrantWithinPeriod( + Long challengeId, Long currentDateTime, TimePeriodEnum period) { + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withTypes("challengeRegistrant"); - return registrantDtos; - } + BoolQueryBuilder boolQueryBuilder = boolQuery(); + boolQueryBuilder.must(termQuery("challengeId", challengeId)); - public ChallengeRegistrantDto saveRegistrant(String ownerEmail, ChallengeRegistrantDto challengeRegistrantDto) { - ChallengeEntity challenge = challengeRepository.findOne(challengeRegistrantDto.getChallengeId()); - if (ownerEmail.equalsIgnoreCase(challenge.getAuthorEmail())) { - ChallengeRegistrantEntity registrant = challengeRegistrantRepository.findOne(challengeRegistrantDto.getRegistrantId()); - challengeRegistrantDto.setRegistrantEmail(registrant.getRegistrantEmail()); - dozerMapper.map(challengeRegistrantDto, registrant); - registrant = challengeRegistrantRepository.save(registrant); - challengeRegistrantDto = dozerMapper.map(registrant, ChallengeRegistrantDto.class); -// challengeRegistrantDto.setRegistrantEmail(null); + Long pastTime = currentDateTime - period.getMiliseconds() > 0 ? currentDateTime - period.getMiliseconds() : 0; + boolQueryBuilder.must(rangeQuery("registrantId").from(pastTime)); + searchQueryBuilder.withQuery(boolQueryBuilder); + searchQueryBuilder.withSort(fieldSort("registrantId").order(SortOrder.DESC)); + return DataUtils.getAllEntities(challengeRegistrantRepository, searchQueryBuilder); + } + + @Override + public List filterChallengeRegistrantByDate(RegistrantFilterCondition condition) throws ParseException { + List result = new ArrayList<>(); + + if (ChallengeRegistrantFilterTypeEnum.BY_SUBMISSION.getValue().equals(condition.getFilterType())) { + Set registrantIds = findRegistrantByChallengeSubmissionDate( + condition.getChallengeId(), condition.getFromDate(), condition.getToDate()); + for (Long registrantId : registrantIds) { + ChallengeRegistrantEntity registrantEntity = challengeRegistrantRepository.findOne(registrantId); + if (registrantEntity != null) { + result.add(registrantEntity); } - return challengeRegistrantDto; + } } + else { + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withTypes("challengeRegistrant"); + BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); - @Override - public List findChallengeRegistrantWithinPeriod( - Long challengeId, Long currentDateTime, TimePeriodEnum period) { - NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withTypes("challengeRegistrant"); - - BoolQueryBuilder boolQueryBuilder = boolQuery(); - boolQueryBuilder.must(termQuery("challengeId", challengeId)); + if (condition.getChallengeId() != null) { + boolQueryBuilder.must(termQuery("challengeId", condition.getChallengeId())); + } - Long pastTime = currentDateTime - period.getMiliseconds() > 0 ? currentDateTime - period.getMiliseconds() : 0; - boolQueryBuilder.must(rangeQuery("registrantId").from(pastTime)); - searchQueryBuilder.withQuery(boolQueryBuilder); - searchQueryBuilder.withSort(fieldSort("registrantId").order(SortOrder.DESC)); - searchQueryBuilder.withPageable(new PageRequest(0, 100)); + if (StringUtils.isNotEmpty(condition.getFilterType()) && + (StringUtils.isNotEmpty(condition.getFromDate()) || StringUtils.isNotEmpty(condition.getToDate()))) { + RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(condition.getFilterType()); - List result = new ArrayList<>(); - Iterator iterator = challengeRegistrantRepository.search(searchQueryBuilder.build()).iterator(); - while (iterator.hasNext()) { - result.add(iterator.next()); + if (StringUtils.isNotEmpty(condition.getFromDate())) { + Long from = string2Date(condition.getFromDate(), BASIC_DATE_PATTERN).getTime(); + rangeQueryBuilder.from(from); + } + if (StringUtils.isNotEmpty(condition.getToDate())) { + Long to = string2Date(condition.getToDate(), BASIC_DATE_PATTERN).getTime() + + TimePeriodEnum.TWENTY_FOUR_HOURS.getMiliseconds(); + rangeQueryBuilder.to(to); } - return result; + boolQueryBuilder.must(rangeQueryBuilder); + } + + searchQueryBuilder.withQuery(boolQueryBuilder); + result.addAll(DataUtils.getAllEntities(challengeRegistrantRepository, searchQueryBuilder)); } - @Override - public List findChallengeSubmissionWithinPeriod( - Long challengeId, Long currentDateTime, TimePeriodEnum period) { - NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withTypes("challengeSubmission"); + return result; + } - BoolQueryBuilder boolQueryBuilder = boolQuery(); - boolQueryBuilder.must(termQuery("challengeId", challengeId)); + @Override + public List findChallengeSubmissionWithinPeriod( + Long challengeId, Long currentDateTime, TimePeriodEnum period) { + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withTypes("challengeSubmission"); - Long pastTime = currentDateTime - period.getMiliseconds() > 0 ? currentDateTime - period.getMiliseconds() : 0; - boolQueryBuilder.must(rangeQuery("challengeSubmissionId").from(pastTime)); - searchQueryBuilder.withQuery(boolQueryBuilder); - searchQueryBuilder.withSort(fieldSort("challengeSubmissionId").order(SortOrder.DESC)); - searchQueryBuilder.withPageable(new PageRequest(0, 100)); + BoolQueryBuilder boolQueryBuilder = boolQuery(); + boolQueryBuilder.must(termQuery("challengeId", challengeId)); - List result = new ArrayList<>(); - Iterator iterator = challengeSubmissionRepository.search(searchQueryBuilder.build()).iterator(); - while (iterator.hasNext()) { - result.add(iterator.next()); - } + boolQueryBuilder.must(rangeQuery("submissionDateTime").from(yesterdayDate())); + searchQueryBuilder.withQuery(boolQueryBuilder); + searchQueryBuilder.withSort(fieldSort("challengeSubmissionId").order(SortOrder.DESC)); - return result; - } + return DataUtils.getAllEntities(challengeSubmissionRepository, searchQueryBuilder); + } - @Override - public List listChallengesByPhase(ChallengePhaseEnum challengePhase) { - List challengeEntities = new ArrayList<>(); - // from <= NOW < to - RangeFilterBuilder fromFilter = rangeFilter(challengePhase.getFromDateTimeField()).lt("now/d"); - RangeFilterBuilder toFilter = rangeFilter(challengePhase.getToDateTimeField()).gte("now/d"); - TermFilterBuilder expiredChallengeFilter = termFilter("expired", Boolean.TRUE); - BoolFilterBuilder dateTimeRangeFilter = boolFilter().must(fromFilter).must(toFilter).mustNot(expiredChallengeFilter); - - Iterator challengeIterator = - challengeRepository.search(filteredQuery(matchAllQuery(), dateTimeRangeFilter)).iterator(); - while (challengeIterator.hasNext()) { - challengeEntities.add(challengeIterator.next()); - } + @Override + public List listChallengesByPhase(ChallengePhaseEnum challengePhase) { + List challengeEntities = new ArrayList<>(); + // from <= NOW < to + RangeFilterBuilder fromFilter = rangeFilter(challengePhase.getFromDateTimeField()).lt("now/d"); + RangeFilterBuilder toFilter = rangeFilter(challengePhase.getToDateTimeField()).gte("now/d"); + TermFilterBuilder expiredChallengeFilter = termFilter("expired", Boolean.TRUE); + BoolFilterBuilder dateTimeRangeFilter = boolFilter().must(fromFilter).must(toFilter).mustNot(expiredChallengeFilter); - return challengeEntities; + Iterator challengeIterator = + challengeRepository.search(filteredQuery(matchAllQuery(), dateTimeRangeFilter)).iterator(); + while (challengeIterator.hasNext()) { + challengeEntities.add(challengeIterator.next()); } - @Override - public void sendDailySummaryEmailToChallengeOwner(ChallengeEntity challengeEntity) throws Exception { - String mailSubject = challengeEntity.getLang() == Language.vi ? dailyChallengeSummaryMailSubjectVi : - dailyChallengeSummaryMailSubjectEn; - Address[] recipientAddresses = getRecipientAddresses(challengeEntity, true); - Template template = challengeEntity.getLang() == Language.vi ? - dailyChallengeSummaryMailTemplateVi : dailyChallengeSummaryMailTemplateEn; - postChallengeMailMessage.setRecipients(Message.RecipientType.TO, recipientAddresses); - Address[] replyToAddresses = InternetAddress.parse(postChallengeTechloopiesMailList); - postChallengeMailMessage.setReplyTo(replyToAddresses); - StringWriter stringWriter = new StringWriter(); - - Map templateModel = new HashMap<>(); - templateModel.put("webBaseUrl", webBaseUrl); - templateModel.put("challengeName", challengeEntity.getChallengeName()); - templateModel.put("challengeId", challengeEntity.getChallengeId().toString()); - templateModel.put("challengeNameAlias", challengeEntity.getChallengeName().replaceAll("\\W", "-")); - templateModel.put("currentDateTime", String.valueOf(new Date().getTime())); - - Long currentDateTime = new Date().getTime(); - List latestRegistrants = findChallengeRegistrantWithinPeriod( - challengeEntity.getChallengeId(), currentDateTime, TimePeriodEnum.TWENTY_FOUR_HOURS); - templateModel.put("numberOfRegistrants", latestRegistrants.size()); - templateModel.put("latestRegistrants", latestRegistrants); - - List latestSubmissions = findChallengeSubmissionWithinPeriod( - challengeEntity.getChallengeId(), currentDateTime, TimePeriodEnum.TWENTY_FOUR_HOURS); - templateModel.put("numberOfSubmissions", latestSubmissions.size()); - templateModel.put("latestSubmissions", latestSubmissions); - - template.process(templateModel, stringWriter); - mailSubject = String.format(mailSubject, challengeEntity.getChallengeName()); - postChallengeMailMessage.setSubject(MimeUtility.encodeText(mailSubject, "UTF-8", null)); - postChallengeMailMessage.setText(stringWriter.toString(), "UTF-8", "html"); - - stringWriter.flush(); - postChallengeMailMessage.saveChanges(); - mailSender.send(postChallengeMailMessage); - } + return challengeEntities; + } - public boolean isOwnerOfChallenge(String ownerEmail, Long challengeId) { - ChallengeEntity challenge = challengeRepository.findOne(challengeId); - return challenge.getAuthorEmail().equalsIgnoreCase(ownerEmail); - } + @Override + public void sendDailySummaryEmailToChallengeOwner(ChallengeEntity challengeEntity) throws Exception { + String mailSubject = challengeEntity.getLang() == Language.vi ? dailyChallengeSummaryMailSubjectVi : + dailyChallengeSummaryMailSubjectEn; + Address[] recipientAddresses = getRecipientAddresses(challengeEntity, true); + Template template = challengeEntity.getLang() == Language.vi ? + dailyChallengeSummaryMailTemplateVi : dailyChallengeSummaryMailTemplateEn; + postChallengeMailMessage.setRecipients(Message.RecipientType.TO, recipientAddresses); + Address[] replyToAddresses = InternetAddress.parse(postChallengeTechloopiesMailList); + postChallengeMailMessage.setReplyTo(replyToAddresses); + StringWriter stringWriter = new StringWriter(); + + Map templateModel = new HashMap<>(); + templateModel.put("webBaseUrl", webBaseUrl); + templateModel.put("challengeName", challengeEntity.getChallengeName()); + templateModel.put("challengeId", challengeEntity.getChallengeId().toString()); + templateModel.put("challengeNameAlias", challengeEntity.getChallengeName().replaceAll("\\W", "-")); + templateModel.put("currentDateTime", String.valueOf(new Date().getTime())); + templateModel.put("yesterdayDateTime", DateTimeUtils.yesterdayDate()); + + Long currentDateTime = new Date().getTime(); + List latestRegistrants = findChallengeRegistrantWithinPeriod( + challengeEntity.getChallengeId(), currentDateTime, TimePeriodEnum.TWENTY_FOUR_HOURS); + templateModel.put("numberOfRegistrants", latestRegistrants.size()); + templateModel.put("latestRegistrants", latestRegistrants); + + List latestSubmissions = findChallengeSubmissionWithinPeriod( + challengeEntity.getChallengeId(), currentDateTime, TimePeriodEnum.TWENTY_FOUR_HOURS); + templateModel.put("numberOfSubmissions", latestSubmissions.size()); + templateModel.put("latestSubmissions", latestSubmissions); + + template.process(templateModel, stringWriter); + mailSubject = String.format(mailSubject, challengeEntity.getChallengeName()); + postChallengeMailMessage.setSubject(MimeUtility.encodeText(mailSubject, "UTF-8", null)); + postChallengeMailMessage.setText(stringWriter.toString(), "UTF-8", "html"); + + stringWriter.flush(); + postChallengeMailMessage.saveChanges(); + mailSender.send(postChallengeMailMessage); + } - public boolean sendEmailToDailyChallengeRegistrants(String challengeOwner, Long challengeId, Long now, EmailContent emailContent) { - if (isOwnerOfChallenge(challengeOwner, challengeId)) { - List registrants = findChallengeRegistrantWithinPeriod(challengeId, now, TimePeriodEnum.TWENTY_FOUR_HOURS); - String csvEmails = registrants.stream().map(ChallengeRegistrantEntity::getRegistrantEmail).distinct().collect(Collectors.joining(",")); - try { - emailContent.setRecipients(InternetAddress.parse(csvEmails)); - } catch (AddressException e) { - LOGGER.debug("Can not parse email address", e); - return false; - } - } - return emailService.sendEmail(emailContent); + public boolean isOwnerOfChallenge(String ownerEmail, Long challengeId) { + ChallengeEntity challenge = challengeRepository.findOne(challengeId); + return challenge.getAuthorEmail().equalsIgnoreCase(ownerEmail); + } + + public boolean sendEmailToDailyChallengeRegistrants(String challengeOwner, Long challengeId, Long now, EmailContent emailContent) { + if (isOwnerOfChallenge(challengeOwner, challengeId)) { + List registrants = findChallengeRegistrantWithinPeriod(challengeId, now, TimePeriodEnum.TWENTY_FOUR_HOURS); + String csvEmails = registrants.stream().map(ChallengeRegistrantEntity::getRegistrantEmail).distinct().collect(joining(",")); + try { + emailContent.setRecipients(InternetAddress.parse(csvEmails)); + } + catch (AddressException e) { + LOGGER.debug("Can not parse email address", e); + return false; + } } + return emailService.sendEmail(emailContent); + } public boolean sendEmailToRegistrant(String challengeOwner, Long challengeId, Long registrantId, EmailContent emailContent) { if (isOwnerOfChallenge(challengeOwner, challengeId)) { @@ -749,4 +799,224 @@ public boolean sendEmailToRegistrant(String challengeOwner, Long challengeId, Lo return emailService.sendEmail(emailContent); } + @Override + public List findChallengeSubmissionByRegistrant(Long challengeId, Long registrantId) { + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withTypes("challengeSubmission"); + BoolFilterBuilder boolFilterBuilder = new BoolFilterBuilder(); + boolFilterBuilder.must(termFilter("challengeId", challengeId)); + boolFilterBuilder.must(termFilter("registrantId", registrantId)); + + searchQueryBuilder.withQuery(filteredQuery(matchAllQuery(), boolFilterBuilder)); + List submissions = DataUtils.getAllEntities(challengeSubmissionRepository, searchQueryBuilder); + return submissions.stream().map(submission -> dozerMapper.map(submission, ChallengeSubmissionDto.class)).collect(toList()); + } + + @Override + public void updateSendEmailToContestantResultCode(ChallengeRegistrantEntity challengeRegistrantEntity, EmailSentResultEnum code) { + if (challengeRegistrantEntity != null) { + challengeRegistrantEntity.setLastEmailSentDateTime(currentDate(BASIC_DATE_TIME_PATTERN)); + challengeRegistrantEntity.setLastEmailSentResultCode(code.getValue()); + challengeRegistrantRepository.save(challengeRegistrantEntity); + } + } + + public void updateSendEmailToChallengeOwnerResultCode(ChallengeEntity challengeEntity, EmailSentResultEnum code) { + if (challengeEntity != null) { + challengeEntity.setLastEmailSentDateTime(currentDate(BASIC_DATE_TIME_PATTERN)); + challengeEntity.setLastEmailSentResultCode(code.getValue()); + challengeRepository.save(challengeEntity); + } + } + + public Set findRegistrantByChallengeSubmissionDate(Long challengeId, String fromDate, String toDate) { + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withTypes("challengeSubmission"); + BoolQueryBuilder boolQueryBuilder = boolQuery(); + boolQueryBuilder.must(termQuery("challengeId", challengeId)); + + RangeQueryBuilder submissionDateQuery = QueryBuilders.rangeQuery("submissionDateTime"); + if (StringUtils.isNotEmpty(fromDate) || StringUtils.isNotEmpty(toDate)) { + if (StringUtils.isNotEmpty(fromDate)) { + submissionDateQuery.from(fromDate); + } + + if (StringUtils.isNotEmpty(toDate)) { + submissionDateQuery.to(toDate); + } + + boolQueryBuilder.must(submissionDateQuery); + } + + searchQueryBuilder.withQuery(boolQueryBuilder); + List submissions = DataUtils.getAllEntities(challengeSubmissionRepository, searchQueryBuilder); + return submissions.stream().map(submission -> submission.getRegistrantId()).collect(toSet()); + } + + public ChallengeDetailDto getChallengeDetail(Long challengeId, String loginEmail) { + NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withTypes("challenge"); + TermQueryBuilder challengeIdQuery = termQuery("challengeId", challengeId); + //MatchQueryBuilder authorEmailQuery = matchQuery("authorEmail", loginEmail).minimumShouldMatch("100%"); + TermQueryBuilder expiredChallengeQuery = termQuery("expired", Boolean.TRUE); + + searchQueryBuilder.withQuery(boolQuery().must(challengeIdQuery).mustNot(expiredChallengeQuery)); + List challengeEntities = DataUtils.getAllEntities(challengeRepository, searchQueryBuilder); + + if (!challengeEntities.isEmpty()) { + ChallengeEntity challengeEntity = challengeEntities.get(0); + ChallengeDetailDto challengeDetailDto = dozerMapper.map(challengeEntity, ChallengeDetailDto.class); + challengeDetailDto.setNumberOfRegistrants(getNumberOfRegistrants(challengeId)); + calculateChallengePhases(challengeDetailDto); +// challengeDetailDto.setCurrentPhase(getChallengeCurrentPhase(challengeEntity)); +// challengeDetailDto.setNextPhase(getChallengeNextPhase(challengeEntity)); + calculateChallengePhases(challengeDetailDto); + challengeDetailDto.setIsAuthor(challengeEntity.getAuthorEmail().equals(loginEmail)); + return challengeDetailDto; + } + return null; + } + + public static void calculateChallengePhases(ChallengeDetailDto challengeDetailDto) { + String now = DateTimeUtils.currentDate(); + + String timeline[] = { + challengeDetailDto.getSubmissionDateTime(), + challengeDetailDto.getPrototypeSubmissionDateTime(), + challengeDetailDto.getUxSubmissionDateTime(), + challengeDetailDto.getIdeaSubmissionDateTime(), + challengeDetailDto.getRegistrationDateTime() + }; + + int currentIndex = -1; + int nextIndex = -1; + for (int i = 0; i < timeline.length; ++i) { + try { + String milestone = timeline[i]; + if (DateTimeUtils.daysBetween(now, milestone) >= 0) { + nextIndex = currentIndex; + currentIndex = i; + } + } + catch (Exception e) { + continue; + } + } + + if (currentIndex == -1) {//FINAL + challengeDetailDto.setCurrentPhase(ChallengePhaseEnum.FINAL); + challengeDetailDto.setNextPhase(ChallengePhaseEnum.FINAL); + } + else { + challengeDetailDto.setCurrentPhase(CHALLENGE_TIMELINE[currentIndex]); + challengeDetailDto.setNextPhase(CHALLENGE_TIMELINE[nextIndex > -1 ? nextIndex : currentIndex]); + } + } + +// public static void main(String[] args) { +// ChallengeDetailDto challengeDetailDto = new ChallengeDetailDto(); +// +//// challengeDetailDto.setStartDateTime("12/10/2015");//final, final +//// challengeDetailDto.setRegistrationDateTime("14/10/2015"); +//// challengeDetailDto.setSubmissionDateTime("15/10/2015"); +// +//// calculateChallengePhases(challengeDetailDto); +//// System.out.println(); +//// System.out.println(challengeDetailDto.getCurrentPhase()); +//// System.out.println(challengeDetailDto.getNextPhase()); +// +// +// +// challengeDetailDto.setStartDateTime("11/10/2015");//curr: idea, next: uiux +// challengeDetailDto.setRegistrationDateTime("14/10/2015"); +//// challengeDetailDto.setIdeaSubmissionDateTime("15/10/2015"); +// challengeDetailDto.setUxSubmissionDateTime("17/10/2015"); +// challengeDetailDto.setPrototypeSubmissionDateTime("19/10/2015"); +// challengeDetailDto.setSubmissionDateTime("20/10/2015"); +// +// calculateChallengePhases(challengeDetailDto); +// System.out.println(); +// System.out.println(challengeDetailDto.getCurrentPhase()); +// System.out.println(challengeDetailDto.getNextPhase()); +// +// +// +//// challengeDetailDto.setStartDateTime("12/10/2015");//current = UIUX, next=final +//// challengeDetailDto.setRegistrationDateTime("13/10/2015"); +//// challengeDetailDto.setIdeaSubmissionDateTime("14/10/2015"); +//// challengeDetailDto.setUxSubmissionDateTime("18/10/2015"); +//// challengeDetailDto.setSubmissionDateTime("19/10/2015"); +//// +//// calculateChallengePhases(challengeDetailDto); +//// System.out.println(); +//// System.out.println(challengeDetailDto.getCurrentPhase()); +//// System.out.println(challengeDetailDto.getNextPhase()); +// } + + public ChallengeRegistrantDto acceptRegistrant(String ownerEmail, Long registrantId) { + ChallengeRegistrantEntity registrant = challengeRegistrantRepository.findOne(registrantId); + if (registrant == null) { + return null; + } + + ChallengeEntity challenge = challengeRepository.findOne(registrant.getChallengeId()); + if (!ownerEmail.equalsIgnoreCase(challenge.getAuthorEmail())) { + return null; + } + + ChallengeDetailDto challengeDetailDto = dozerMapper.map(challenge, ChallengeDetailDto.class); + calculateChallengePhases(challengeDetailDto); + ChallengePhaseEnum activePhase = challengeDetailDto.getNextPhase(); + if (activePhase != registrant.getActivePhase()) { + registrant.setActivePhase(activePhase); + registrant = challengeRegistrantRepository.save(registrant); + } + + return dozerMapper.map(registrant, ChallengeRegistrantDto.class); + } + +// private ChallengePhaseEnum getChallengeNextPhase(ChallengeEntity challengeEntity) { +// int nextMilestoneIndex = getChallengeCurrentPhaseIndex(challengeEntity); +// if (nextMilestoneIndex == -1) { +// return ChallengePhaseEnum.FINAL; +// } +// +// return CHALLENGE_TIMELINE[Math.max(0, nextMilestoneIndex - 1)]; +// } + +// private ChallengePhaseEnum getChallengeCurrentPhase(ChallengeEntity challengeEntity) { +// int nextMilestoneIndex = getChallengeCurrentPhaseIndex(challengeEntity); +// if (nextMilestoneIndex == -1) { +// return ChallengePhaseEnum.FINAL; +// } +// return CHALLENGE_TIMELINE[nextMilestoneIndex]; +// } +// +// private int getNextChallengeCurrentPhaseIndex(ChallengeEntity challengeEntity) { +// +// } + +// private int getChallengeCurrentPhaseIndex(ChallengeEntity challengeEntity) { +// String now = from == null ? DateTimeUtils.currentDate() : from; +// +// String timeline[] = { +// challengeEntity.getSubmissionDateTime(), +// challengeEntity.getPrototypeSubmissionDateTime(), +// challengeEntity.getUxSubmissionDateTime(), +// challengeEntity.getIdeaSubmissionDateTime(), +// challengeEntity.getRegistrationDateTime() +// }; +// +// int currentMilestoneIndex = -1; +// for (int i = 0; i < timeline.length; ++i) { +// try { +// String milestone = timeline[i]; +// if (DateTimeUtils.daysBetween(now, milestone) < 0) { +// break; +// } +// currentMilestoneIndex = i; +// } +// catch (ParseException | NullPointerException e) { +// continue; +// } +// } +// return currentMilestoneIndex; +// } } diff --git a/src/main/java/com/techlooper/service/impl/ChallengeSubmissionServiceImpl.java b/src/main/java/com/techlooper/service/impl/ChallengeSubmissionServiceImpl.java new file mode 100644 index 000000000..0d5720a18 --- /dev/null +++ b/src/main/java/com/techlooper/service/impl/ChallengeSubmissionServiceImpl.java @@ -0,0 +1,61 @@ +package com.techlooper.service.impl; + +import com.techlooper.entity.ChallengeRegistrantDto; +import com.techlooper.entity.ChallengeRegistrantEntity; +import com.techlooper.entity.ChallengeSubmissionEntity; +import com.techlooper.entity.ChallengeSubmissionEntity.ChallengeSubmissionEntityBuilder; +import com.techlooper.model.ChallengeSubmissionDto; +import com.techlooper.repository.elasticsearch.ChallengeRegistrantRepository; +import com.techlooper.repository.elasticsearch.ChallengeSubmissionRepository; +import com.techlooper.service.ChallengeService; +import com.techlooper.service.ChallengeSubmissionService; +import com.techlooper.util.DateTimeUtils; +import org.dozer.Mapper; +import org.elasticsearch.common.joda.time.DateTime; +import org.elasticsearch.index.query.MatchQueryBuilder; +import org.elasticsearch.index.query.TermQueryBuilder; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +import java.util.Iterator; + +import static org.elasticsearch.index.query.QueryBuilders.*; + +/** + * Created by phuonghqh on 10/9/15. + */ +@Service +public class ChallengeSubmissionServiceImpl implements ChallengeSubmissionService { + + @Resource + private ChallengeRegistrantRepository challengeRegistrantRepository; + + @Resource + private ChallengeService challengeService; + + @Resource + private Mapper dozerMapper; + + @Resource + private ChallengeSubmissionRepository challengeSubmissionRepository; + + public ChallengeSubmissionEntity submitMyResult(ChallengeSubmissionDto challengeSubmissionDto) { + MatchQueryBuilder registrantEmailQuery = matchQuery("registrantEmail", challengeSubmissionDto.getRegistrantEmail()).minimumShouldMatch("100%"); + TermQueryBuilder challengeQuery = termQuery("challengeId", challengeSubmissionDto.getChallengeId()); + Iterator registrantIterator = challengeRegistrantRepository.search( + boolQuery().must(registrantEmailQuery).must(challengeQuery)).iterator(); + + ChallengeRegistrantEntity registrant = registrantIterator.hasNext() ? registrantIterator.next() : + challengeService.joinChallengeEntity(dozerMapper.map(challengeSubmissionDto, ChallengeRegistrantDto.class)); + + ChallengeSubmissionEntity challengeSubmissionEntity = dozerMapper.map(challengeSubmissionDto, ChallengeSubmissionEntity.class); + ChallengeSubmissionEntityBuilder.challengeSubmissionEntity(challengeSubmissionEntity) + .withChallengeSubmissionId(DateTime.now().getMillis()) + .withRegistrantId(registrant.getRegistrantId()) + .withRegistrantName(String.format("%s %s", registrant.getRegistrantFirstName(), registrant.getRegistrantLastName())) + .withSubmissionDateTime(DateTimeUtils.currentDate()); + + return challengeSubmissionRepository.save(challengeSubmissionEntity); + } +} diff --git a/src/main/java/com/techlooper/service/impl/JobQueryBuilderImpl.java b/src/main/java/com/techlooper/service/impl/JobQueryBuilderImpl.java index e713adc0b..f152f60d5 100644 --- a/src/main/java/com/techlooper/service/impl/JobQueryBuilderImpl.java +++ b/src/main/java/com/techlooper/service/impl/JobQueryBuilderImpl.java @@ -277,12 +277,22 @@ public NativeSearchQueryBuilder getSearchQueryForPriceJobReport(PriceJobEntity p FilterBuilder approvedDateRangeFilterBuilder = getRangeFilterBuilder("approvedDate", "now-6M/M", null); FilterBuilder salaryRangeFilterBuilder = getSalaryRangeFilterBuilder(MIN_SALARY_ACCEPTABLE, MAX_SALARY_ACCEPTABLE); - queryBuilder.withQuery(filteredQuery(jobTitleQueryBuilder, - boolFilter().must(locationFilterBuilder) - .must(jobLevelFilterBuilder) - .must(approvedDateRangeFilterBuilder) - .must(jobIndustriesFilterBuilder) - .must(salaryRangeFilterBuilder))); + BoolFilterBuilder boolFilterBuilder = boolFilter(); + if (priceJobEntity.getLocationId() != null && priceJobEntity.getLocationId() != 1) { + boolFilterBuilder.must(locationFilterBuilder); + } + + if (!priceJobEntity.getJobLevelIds().isEmpty()) { + boolFilterBuilder.must(jobLevelFilterBuilder); + } + + if (!priceJobEntity.getJobCategories().isEmpty()) { + boolFilterBuilder.must(jobIndustriesFilterBuilder); + } + + boolFilterBuilder.must(approvedDateRangeFilterBuilder); + boolFilterBuilder.must(salaryRangeFilterBuilder); + queryBuilder.withQuery(filteredQuery(jobTitleQueryBuilder, boolFilterBuilder)); return queryBuilder; } diff --git a/src/main/java/com/techlooper/util/DataUtils.java b/src/main/java/com/techlooper/util/DataUtils.java new file mode 100644 index 000000000..6e95cc172 --- /dev/null +++ b/src/main/java/com/techlooper/util/DataUtils.java @@ -0,0 +1,31 @@ +package com.techlooper.util; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.core.FacetedPage; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by NguyenDangKhoa on 10/9/15. + */ +public class DataUtils { + + public static List getAllEntities(ElasticsearchRepository repository, NativeSearchQueryBuilder searchQueryBuilder) { + List result = new ArrayList<>(); + + FacetedPage facetedPage = repository.search(searchQueryBuilder.build()); + int totalPages = facetedPage.getTotalPages(); + int pageIndex = 0; + + while (pageIndex < totalPages) { + searchQueryBuilder.withPageable(new PageRequest(pageIndex, 50)); + result.addAll(repository.search(searchQueryBuilder.build()).getContent()); + pageIndex++; + } + + return result; + } +} diff --git a/src/main/java/com/techlooper/util/DateTimeUtils.java b/src/main/java/com/techlooper/util/DateTimeUtils.java index c1fbee33c..fafcbd566 100644 --- a/src/main/java/com/techlooper/util/DateTimeUtils.java +++ b/src/main/java/com/techlooper/util/DateTimeUtils.java @@ -2,6 +2,10 @@ import org.joda.time.DateTime; import org.joda.time.Days; +import org.joda.time.format.DateTimeFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -12,27 +16,52 @@ */ public class DateTimeUtils { + public static final Logger LOGGER = LoggerFactory.getLogger(DateTimeUtils.class); + public static final String BASIC_DATE_PATTERN = "dd/MM/yyyy"; public static final String BASIC_DATE_TIME_PATTERN = "dd/MM/yyyy HH:mm"; - public static final String ISO_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZZ"; +// public static final String ISO_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZZ"; + + public static DateTime parseBasicDate(String text) { + if (StringUtils.hasText(text)) { + try { + return DateTimeFormat.forPattern(BASIC_DATE_PATTERN).parseDateTime(text); + } catch (Exception e) { + LOGGER.debug("Couldn't parse date-time [{}] by format [{}]", text, BASIC_DATE_PATTERN); + } + } + return null; + } public static Date string2Date(String datetime, String pattern) throws ParseException { SimpleDateFormat formatter = new SimpleDateFormat(pattern); return formatter.parse(datetime); } - public static String date2String(Date datetime, String pattern) { - SimpleDateFormat formatter = new SimpleDateFormat(pattern); - return formatter.format(datetime); - } +// public static String date2String(Date datetime, String pattern) { +// SimpleDateFormat formatter = new SimpleDateFormat(pattern); +// return formatter.format(datetime); +// } public static String currentDate() { SimpleDateFormat formatter = new SimpleDateFormat(BASIC_DATE_PATTERN); return formatter.format(new Date()); } + public static String yesterdayDate() { + SimpleDateFormat formatter = new SimpleDateFormat(BASIC_DATE_PATTERN); + DateTime yesterday = DateTime.now().minusDays(1); + return formatter.format(yesterday.toDate()); + } + + public static String yesterdayDate(String pattern) { + SimpleDateFormat formatter = new SimpleDateFormat(pattern); + DateTime yesterday = DateTime.now().minusDays(1); + return formatter.format(yesterday.toDate()); + } + public static String currentDate(String pattern) { SimpleDateFormat formatter = new SimpleDateFormat(pattern); return formatter.format(new Date()); @@ -48,4 +77,8 @@ public static int daysBetween(String firstDateStr, String secondDateStr) throws return Days.daysBetween(firstDateTime, secondDateTime).getDays(); } + public static void main(String args[]) { + System.out.println(yesterdayDate()); + } + } diff --git a/src/main/resources/local/logback.groovy b/src/main/resources/local/logback.groovy index 500e3fafb..9c759ef5e 100644 --- a/src/main/resources/local/logback.groovy +++ b/src/main/resources/local/logback.groovy @@ -11,29 +11,14 @@ import static ch.qos.logback.classic.Level.OFF scan() -def LOG_FOLDER = "./log/" - -new File(LOG_FOLDER).mkdirs() - -appender("ROOT_FILE", RollingFileAppender) { - file = "${LOG_FOLDER}techlooper-all.log" - rollingPolicy(TimeBasedRollingPolicy) { - fileNamePattern = "${LOG_FOLDER}%d{yyyyMMdd}-techlooper.log" - maxHistory = 30 - } - encoder(PatternLayoutEncoder) { - pattern = "%d{HH:mm:ss.SSS} %p [%t] %c{1}: %m%n" - } -} - appender("CONSOLE", ConsoleAppender) { encoder(PatternLayoutEncoder) { pattern = "%d{dd-MM-yyyy HH:mm:ss.SSS} %p [%t] %c{1}: %m%n" } } -logger("org.elasticsearch", ERROR) -logger("org.hibernate", ERROR) -logger("org.dozer", ERROR) +//logger("org.elasticsearch", ERROR) +//logger("org.hibernate", ERROR) +//logger("org.dozer", ERROR) root(DEBUG, ["CONSOLE"]) \ No newline at end of file diff --git a/src/main/resources/local/techlooper.properties b/src/main/resources/local/techlooper.properties index bef1afd40..19c177591 100644 --- a/src/main/resources/local/techlooper.properties +++ b/src/main/resources/local/techlooper.properties @@ -1,12 +1,12 @@ -elasticsearch.cluster.name = staging-es-w-chef +elasticsearch.cluster.name = dev-es-w-chef elasticsearch.index.name = vietnamworks #find new way to use template ip:port -elasticsearch.host = 172.16.22.27:9300 +elasticsearch.host = es-dev.vietnamworks.com:9300 -elasticsearch.userimport.cluster.name = staging-es-w-chef +elasticsearch.userimport.cluster.name = dev-es-w-chef elasticsearch.userimport.index.name = techlooper -elasticsearch.userimport.host = 172.16.22.27:9300 +elasticsearch.userimport.host = es-dev.vietnamworks.com:9300 couchbase.connectionUri = http://127.0.0.1:8091 couchbase.adminUser = Administrator diff --git a/src/main/resources/production/logback.groovy b/src/main/resources/production/logback.groovy index b35b913de..f481aa475 100644 --- a/src/main/resources/production/logback.groovy +++ b/src/main/resources/production/logback.groovy @@ -28,8 +28,8 @@ appender("ROOT_FILE", RollingFileAppender) { } } -logger("org.elasticsearch", ERROR) -logger("org.hibernate", ERROR) -logger("org.dozer", ERROR) +//logger("org.elasticsearch", ERROR) +//logger("org.hibernate", ERROR) +//logger("org.dozer", ERROR) -root(ALL, ["ROOT_FILE"]) \ No newline at end of file +root(ERROR, ["ROOT_FILE"]) \ No newline at end of file diff --git a/src/main/resources/template/challengeDailySummary.en.ftl b/src/main/resources/template/challengeDailySummary.en.ftl index b71eeda6c..00ec33cbe 100644 --- a/src/main/resources/template/challengeDailySummary.en.ftl +++ b/src/main/resources/template/challengeDailySummary.en.ftl @@ -322,19 +322,23 @@ - +
${latestSubmission_index + 1} ${latestSubmission.registrantName}
- +
+
Review Feedback + Accept +
diff --git a/src/main/resources/template/challengeDailySummary.vi.ftl b/src/main/resources/template/challengeDailySummary.vi.ftl index 8c46889d0..0556b68af 100644 --- a/src/main/resources/template/challengeDailySummary.vi.ftl +++ b/src/main/resources/template/challengeDailySummary.vi.ftl @@ -322,19 +322,22 @@ - +
${latestSubmission_index + 1} ${latestSubmission.registrantName}
- +
+
Xem Trước Phản Hồi + Đi Tiếp +
diff --git a/src/main/resources/template/jobAlert.en.ftl b/src/main/resources/template/jobAlert.en.ftl index 04f3efbef..52db7cc08 100644 --- a/src/main/resources/template/jobAlert.en.ftl +++ b/src/main/resources/template/jobAlert.en.ftl @@ -473,7 +473,7 @@ - View More Topics diff --git a/src/main/resources/template/jobAlert.vi.ftl b/src/main/resources/template/jobAlert.vi.ftl index c250baf16..58e9ea5db 100644 --- a/src/main/resources/template/jobAlert.vi.ftl +++ b/src/main/resources/template/jobAlert.vi.ftl @@ -405,7 +405,7 @@ - Xem Thêm Chủ Đề diff --git a/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote/summernote-bs3.css b/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote 10.58.36/summernote-bs3.css similarity index 100% rename from src/main/webapp/assets/custom-css/swrap-bootstrap/summernote/summernote-bs3.css rename to src/main/webapp/assets/custom-css/swrap-bootstrap/summernote 10.58.36/summernote-bs3.css diff --git a/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote/summernote.css b/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote 10.58.36/summernote.css similarity index 100% rename from src/main/webapp/assets/custom-css/swrap-bootstrap/summernote/summernote.css rename to src/main/webapp/assets/custom-css/swrap-bootstrap/summernote 10.58.36/summernote.css diff --git a/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote-bs3.css b/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote-bs3.css new file mode 100644 index 000000000..5090cd9fe --- /dev/null +++ b/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote-bs3.css @@ -0,0 +1,5970 @@ +.note-editor { + /*! normalize.css v2.1.3 | MIT License | git.io/normalize */ + +} +.note-editor article, +.note-editor aside, +.note-editor details, +.note-editor figcaption, +.note-editor figure, +.note-editor footer, +.note-editor header, +.note-editor hgroup, +.note-editor main, +.note-editor nav, +.note-editor section, +.note-editor summary { + display: block; +} +.note-editor audio, +.note-editor canvas, +.note-editor video { + display: inline-block; +} +.note-editor audio:not([controls]) { + display: none; + height: 0; +} +.note-editor [hidden], +.note-editor template { + display: none; +} +.note-editor html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +.note-editor body { + margin: 0; +} +.note-editor a { + background: transparent; +} +.note-editor a:focus { + outline: thin dotted; +} +.note-editor a:active, +.note-editor a:hover { + outline: 0; +} +.note-editor h1 { + font-size: 2em; + margin: 0.67em 0; +} +.note-editor abbr[title] { + border-bottom: 1px dotted; +} +.note-editor b, +.note-editor strong { + font-weight: bold; +} +.note-editor dfn { + font-style: italic; +} +.note-editor hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +.note-editor mark { + background: #ff0; + color: #000; +} +.note-editor code, +.note-editor kbd, +.note-editor pre, +.note-editor samp { + font-family: monospace, serif; + font-size: 1em; +} +.note-editor pre { + white-space: pre-wrap; +} +.note-editor q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} +.note-editor small { + font-size: 80%; +} +.note-editor sub, +.note-editor sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +.note-editor sup { + top: -0.5em; +} +.note-editor sub { + bottom: -0.25em; +} +.note-editor img { + border: 0; +} +.note-editor svg:not(:root) { + overflow: hidden; +} +.note-editor figure { + margin: 0; +} +.note-editor fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +.note-editor legend { + border: 0; + padding: 0; +} +.note-editor button, +.note-editor input, +.note-editor select, +.note-editor textarea { + font-family: inherit; + font-size: 100%; + margin: 0; +} +.note-editor button, +.note-editor input { + line-height: normal; +} +.note-editor button, +.note-editor select { + text-transform: none; +} +.note-editor button, +.note-editor html input[type="button"], +.note-editor input[type="reset"], +.note-editor input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +.note-editor button[disabled], +.note-editor html input[disabled] { + cursor: default; +} +.note-editor input[type="checkbox"], +.note-editor input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +.note-editor input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +.note-editor input[type="search"]::-webkit-search-cancel-button, +.note-editor input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +.note-editor button::-moz-focus-inner, +.note-editor input::-moz-focus-inner { + border: 0; + padding: 0; +} +.note-editor textarea { + overflow: auto; + vertical-align: top; +} +.note-editor table { + border-collapse: collapse; + border-spacing: 0; +} +@media print { + .note-editor * { + text-shadow: none !important; + color: #000 !important; + background: transparent !important; + box-shadow: none !important; + } + .note-editor a, + .note-editor a:visited { + text-decoration: underline; + } + .note-editor a[href]:after { + content: " (" attr(href) ")"; + } + .note-editor abbr[title]:after { + content: " (" attr(title) ")"; + } + .note-editor .ir a:after, + .note-editor a[href^="javascript:"]:after, + .note-editor a[href^="#"]:after { + content: ""; + } + .note-editor pre, + .note-editor blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + .note-editor thead { + display: table-header-group; + } + .note-editor tr, + .note-editor img { + page-break-inside: avoid; + } + .note-editor img { + max-width: 100% !important; + } + @page { + margin: 2cm .5cm; + } + .note-editor p, + .note-editor h2, + .note-editor h3 { + orphans: 3; + widows: 3; + } + .note-editor h2, + .note-editor h3 { + page-break-after: avoid; + } + .note-editor .navbar { + display: none; + } + .note-editor .table td, + .note-editor .table th { + background-color: #fff !important; + } + .note-editor .btn > .caret, + .note-editor .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .note-editor .label { + border: 1px solid #000; + } + .note-editor .table { + border-collapse: collapse !important; + } + .note-editor .table-bordered th, + .note-editor .table-bordered td { + border: 1px solid #ddd !important; + } +} +.note-editor *, +.note-editor *:before, +.note-editor *:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.note-editor html { + font-size: 62.5%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +.note-editor body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.428571429; + color: #333333; + background-color: #ffffff; +} +.note-editor input, +.note-editor button, +.note-editor select, +.note-editor textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +.note-editor a { + color: #428bca; + text-decoration: none; +} +.note-editor a:hover, +.note-editor a:focus { + color: #2a6496; + text-decoration: underline; +} +.note-editor a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.note-editor img { + vertical-align: middle; +} +.note-editor .img-responsive { + display: block; + max-width: 100%; + height: auto; +} +.note-editor .img-rounded { + border-radius: 6px; +} +.note-editor .img-thumbnail { + padding: 4px; + line-height: 1.428571429; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.note-editor .img-circle { + border-radius: 50%; +} +.note-editor hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} +.note-editor .sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.note-editor p { + margin: 0 0 10px; +} +.note-editor .lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 200; + line-height: 1.4; +} +@media (min-width: 768px) { + .note-editor .lead { + font-size: 21px; + } +} +.note-editor small, +.note-editor .small { + font-size: 85%; +} +.note-editor cite { + font-style: normal; +} +.note-editor .text-muted { + color: #999999; +} +.note-editor .text-primary { + color: #428bca; +} +.note-editor .text-primary:hover { + color: #3071a9; +} +.note-editor .text-warning { + color: #c09853; +} +.note-editor .text-warning:hover { + color: #a47e3c; +} +.note-editor .text-danger { + color: #b94a48; +} +.note-editor .text-danger:hover { + color: #953b39; +} +.note-editor .text-success { + color: #468847; +} +.note-editor .text-success:hover { + color: #356635; +} +.note-editor .text-info { + color: #3a87ad; +} +.note-editor .text-info:hover { + color: #2d6987; +} +.note-editor .text-left { + text-align: left; +} +.note-editor .text-right { + text-align: right; +} +.note-editor .text-center { + text-align: center; +} +.note-editor h1, +.note-editor h2, +.note-editor h3, +.note-editor h4, +.note-editor h5, +.note-editor h6, +.note-editor .h1, +.note-editor .h2, +.note-editor .h3, +.note-editor .h4, +.note-editor .h5, +.note-editor .h6 { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +.note-editor h1 small, +.note-editor h2 small, +.note-editor h3 small, +.note-editor h4 small, +.note-editor h5 small, +.note-editor h6 small, +.note-editor .h1 small, +.note-editor .h2 small, +.note-editor .h3 small, +.note-editor .h4 small, +.note-editor .h5 small, +.note-editor .h6 small, +.note-editor h1 .small, +.note-editor h2 .small, +.note-editor h3 .small, +.note-editor h4 .small, +.note-editor h5 .small, +.note-editor h6 .small, +.note-editor .h1 .small, +.note-editor .h2 .small, +.note-editor .h3 .small, +.note-editor .h4 .small, +.note-editor .h5 .small, +.note-editor .h6 .small { + font-weight: normal; + line-height: 1; + color: #999999; +} +.note-editor h1, +.note-editor h2, +.note-editor h3 { + margin-top: 20px; + margin-bottom: 10px; +} +.note-editor h1 small, +.note-editor h2 small, +.note-editor h3 small, +.note-editor h1 .small, +.note-editor h2 .small, +.note-editor h3 .small { + font-size: 65%; +} +.note-editor h4, +.note-editor h5, +.note-editor h6 { + margin-top: 10px; + margin-bottom: 10px; +} +.note-editor h4 small, +.note-editor h5 small, +.note-editor h6 small, +.note-editor h4 .small, +.note-editor h5 .small, +.note-editor h6 .small { + font-size: 75%; +} +.note-editor h1, +.note-editor .h1 { + font-size: 36px; +} +.note-editor h2, +.note-editor .h2 { + font-size: 30px; +} +.note-editor h3, +.note-editor .h3 { + font-size: 24px; +} +.note-editor h4, +.note-editor .h4 { + font-size: 18px; +} +.note-editor h5, +.note-editor .h5 { + font-size: 14px; +} +.note-editor h6, +.note-editor .h6 { + font-size: 12px; +} +.note-editor .page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} +.note-editor ul, +.note-editor ol { + margin-top: 0; + margin-bottom: 10px; +} +.note-editor ul ul, +.note-editor ol ul, +.note-editor ul ol, +.note-editor ol ol { + margin-bottom: 0; +} +.note-editor .list-unstyled { + padding-left: 0; + list-style: none; +} +.note-editor .list-inline { + padding-left: 0; + list-style: none; +} +.note-editor .list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +.note-editor dl { + margin-bottom: 20px; +} +.note-editor dt, +.note-editor dd { + line-height: 1.428571429; +} +.note-editor dt { + font-weight: bold; +} +.note-editor dd { + margin-left: 0; +} +@media (min-width: 768px) { + .note-editor .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .note-editor .dl-horizontal dd { + margin-left: 180px; + } + .note-editor .dl-horizontal dd:before, + .note-editor .dl-horizontal dd:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + + } + .note-editor .dl-horizontal dd:after { + clear: both; + } + .note-editor .dl-horizontal dd:before, + .note-editor .dl-horizontal dd:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + + } + .note-editor .dl-horizontal dd:after { + clear: both; + } +} +.note-editor abbr[title], +.note-editor abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} +.note-editor abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} +.note-editor blockquote { + padding: 10px 20px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} +.note-editor blockquote p { + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} +.note-editor blockquote p:last-child { + margin-bottom: 0; +} +.note-editor blockquote small { + display: block; + line-height: 1.428571429; + color: #999999; +} +.note-editor blockquote small:before { + content: '\2014 \00A0'; +} +.note-editor blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} +.note-editor blockquote.pull-right p, +.note-editor blockquote.pull-right small, +.note-editor blockquote.pull-right .small { + text-align: right; +} +.note-editor blockquote.pull-right small:before, +.note-editor blockquote.pull-right .small:before { + content: ''; +} +.note-editor blockquote.pull-right small:after, +.note-editor blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +.note-editor blockquote:before, +.note-editor blockquote:after { + content: ""; +} +.note-editor address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.428571429; +} +.note-editor code, +.note-editor kdb, +.note-editor pre, +.note-editor samp { + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; +} +.note-editor code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + white-space: nowrap; + border-radius: 4px; +} +.note-editor pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.428571429; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} +.note-editor pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.note-editor .pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.note-editor .container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.note-editor .container:before, +.note-editor .container:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .container:after { + clear: both; +} +.note-editor .container:before, +.note-editor .container:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .container:after { + clear: both; +} +.note-editor .row { + margin-left: -15px; + margin-right: -15px; +} +.note-editor .row:before, +.note-editor .row:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .row:after { + clear: both; +} +.note-editor .row:before, +.note-editor .row:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .row:after { + clear: both; +} +.note-editor .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.note-editor .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11 { + float: left; +} +.note-editor .col-xs-12 { + width: 100%; +} +.note-editor .col-xs-11 { + width: 91.66666666666666%; +} +.note-editor .col-xs-10 { + width: 83.33333333333334%; +} +.note-editor .col-xs-9 { + width: 75%; +} +.note-editor .col-xs-8 { + width: 66.66666666666666%; +} +.note-editor .col-xs-7 { + width: 58.333333333333336%; +} +.note-editor .col-xs-6 { + width: 50%; +} +.note-editor .col-xs-5 { + width: 41.66666666666667%; +} +.note-editor .col-xs-4 { + width: 33.33333333333333%; +} +.note-editor .col-xs-3 { + width: 25%; +} +.note-editor .col-xs-2 { + width: 16.666666666666664%; +} +.note-editor .col-xs-1 { + width: 8.333333333333332%; +} +.note-editor .col-xs-pull-12 { + right: 100%; +} +.note-editor .col-xs-pull-11 { + right: 91.66666666666666%; +} +.note-editor .col-xs-pull-10 { + right: 83.33333333333334%; +} +.note-editor .col-xs-pull-9 { + right: 75%; +} +.note-editor .col-xs-pull-8 { + right: 66.66666666666666%; +} +.note-editor .col-xs-pull-7 { + right: 58.333333333333336%; +} +.note-editor .col-xs-pull-6 { + right: 50%; +} +.note-editor .col-xs-pull-5 { + right: 41.66666666666667%; +} +.note-editor .col-xs-pull-4 { + right: 33.33333333333333%; +} +.note-editor .col-xs-pull-3 { + right: 25%; +} +.note-editor .col-xs-pull-2 { + right: 16.666666666666664%; +} +.note-editor .col-xs-pull-1 { + right: 8.333333333333332%; +} +.note-editor .col-xs-push-12 { + left: 100%; +} +.note-editor .col-xs-push-11 { + left: 91.66666666666666%; +} +.note-editor .col-xs-push-10 { + left: 83.33333333333334%; +} +.note-editor .col-xs-push-9 { + left: 75%; +} +.note-editor .col-xs-push-8 { + left: 66.66666666666666%; +} +.note-editor .col-xs-push-7 { + left: 58.333333333333336%; +} +.note-editor .col-xs-push-6 { + left: 50%; +} +.note-editor .col-xs-push-5 { + left: 41.66666666666667%; +} +.note-editor .col-xs-push-4 { + left: 33.33333333333333%; +} +.note-editor .col-xs-push-3 { + left: 25%; +} +.note-editor .col-xs-push-2 { + left: 16.666666666666664%; +} +.note-editor .col-xs-push-1 { + left: 8.333333333333332%; +} +.note-editor .col-xs-offset-12 { + margin-left: 100%; +} +.note-editor .col-xs-offset-11 { + margin-left: 91.66666666666666%; +} +.note-editor .col-xs-offset-10 { + margin-left: 83.33333333333334%; +} +.note-editor .col-xs-offset-9 { + margin-left: 75%; +} +.note-editor .col-xs-offset-8 { + margin-left: 66.66666666666666%; +} +.note-editor .col-xs-offset-7 { + margin-left: 58.333333333333336%; +} +.note-editor .col-xs-offset-6 { + margin-left: 50%; +} +.note-editor .col-xs-offset-5 { + margin-left: 41.66666666666667%; +} +.note-editor .col-xs-offset-4 { + margin-left: 33.33333333333333%; +} +.note-editor .col-xs-offset-3 { + margin-left: 25%; +} +.note-editor .col-xs-offset-2 { + margin-left: 16.666666666666664%; +} +.note-editor .col-xs-offset-1 { + margin-left: 8.333333333333332%; +} +@media (min-width: 768px) { + .note-editor .container { + width: 750px; + } + .note-editor .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11 { + float: left; + } + .note-editor .col-sm-12 { + width: 100%; + } + .note-editor .col-sm-11 { + width: 91.66666666666666%; + } + .note-editor .col-sm-10 { + width: 83.33333333333334%; + } + .note-editor .col-sm-9 { + width: 75%; + } + .note-editor .col-sm-8 { + width: 66.66666666666666%; + } + .note-editor .col-sm-7 { + width: 58.333333333333336%; + } + .note-editor .col-sm-6 { + width: 50%; + } + .note-editor .col-sm-5 { + width: 41.66666666666667%; + } + .note-editor .col-sm-4 { + width: 33.33333333333333%; + } + .note-editor .col-sm-3 { + width: 25%; + } + .note-editor .col-sm-2 { + width: 16.666666666666664%; + } + .note-editor .col-sm-1 { + width: 8.333333333333332%; + } + .note-editor .col-sm-pull-12 { + right: 100%; + } + .note-editor .col-sm-pull-11 { + right: 91.66666666666666%; + } + .note-editor .col-sm-pull-10 { + right: 83.33333333333334%; + } + .note-editor .col-sm-pull-9 { + right: 75%; + } + .note-editor .col-sm-pull-8 { + right: 66.66666666666666%; + } + .note-editor .col-sm-pull-7 { + right: 58.333333333333336%; + } + .note-editor .col-sm-pull-6 { + right: 50%; + } + .note-editor .col-sm-pull-5 { + right: 41.66666666666667%; + } + .note-editor .col-sm-pull-4 { + right: 33.33333333333333%; + } + .note-editor .col-sm-pull-3 { + right: 25%; + } + .note-editor .col-sm-pull-2 { + right: 16.666666666666664%; + } + .note-editor .col-sm-pull-1 { + right: 8.333333333333332%; + } + .note-editor .col-sm-push-12 { + left: 100%; + } + .note-editor .col-sm-push-11 { + left: 91.66666666666666%; + } + .note-editor .col-sm-push-10 { + left: 83.33333333333334%; + } + .note-editor .col-sm-push-9 { + left: 75%; + } + .note-editor .col-sm-push-8 { + left: 66.66666666666666%; + } + .note-editor .col-sm-push-7 { + left: 58.333333333333336%; + } + .note-editor .col-sm-push-6 { + left: 50%; + } + .note-editor .col-sm-push-5 { + left: 41.66666666666667%; + } + .note-editor .col-sm-push-4 { + left: 33.33333333333333%; + } + .note-editor .col-sm-push-3 { + left: 25%; + } + .note-editor .col-sm-push-2 { + left: 16.666666666666664%; + } + .note-editor .col-sm-push-1 { + left: 8.333333333333332%; + } + .note-editor .col-sm-offset-12 { + margin-left: 100%; + } + .note-editor .col-sm-offset-11 { + margin-left: 91.66666666666666%; + } + .note-editor .col-sm-offset-10 { + margin-left: 83.33333333333334%; + } + .note-editor .col-sm-offset-9 { + margin-left: 75%; + } + .note-editor .col-sm-offset-8 { + margin-left: 66.66666666666666%; + } + .note-editor .col-sm-offset-7 { + margin-left: 58.333333333333336%; + } + .note-editor .col-sm-offset-6 { + margin-left: 50%; + } + .note-editor .col-sm-offset-5 { + margin-left: 41.66666666666667%; + } + .note-editor .col-sm-offset-4 { + margin-left: 33.33333333333333%; + } + .note-editor .col-sm-offset-3 { + margin-left: 25%; + } + .note-editor .col-sm-offset-2 { + margin-left: 16.666666666666664%; + } + .note-editor .col-sm-offset-1 { + margin-left: 8.333333333333332%; + } +} +@media (min-width: 992px) { + .note-editor .container { + width: 970px; + } + .note-editor .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11 { + float: left; + } + .note-editor .col-md-12 { + width: 100%; + } + .note-editor .col-md-11 { + width: 91.66666666666666%; + } + .note-editor .col-md-10 { + width: 83.33333333333334%; + } + .note-editor .col-md-9 { + width: 75%; + } + .note-editor .col-md-8 { + width: 66.66666666666666%; + } + .note-editor .col-md-7 { + width: 58.333333333333336%; + } + .note-editor .col-md-6 { + width: 50%; + } + .note-editor .col-md-5 { + width: 41.66666666666667%; + } + .note-editor .col-md-4 { + width: 33.33333333333333%; + } + .note-editor .col-md-3 { + width: 25%; + } + .note-editor .col-md-2 { + width: 16.666666666666664%; + } + .note-editor .col-md-1 { + width: 8.333333333333332%; + } + .note-editor .col-md-pull-12 { + right: 100%; + } + .note-editor .col-md-pull-11 { + right: 91.66666666666666%; + } + .note-editor .col-md-pull-10 { + right: 83.33333333333334%; + } + .note-editor .col-md-pull-9 { + right: 75%; + } + .note-editor .col-md-pull-8 { + right: 66.66666666666666%; + } + .note-editor .col-md-pull-7 { + right: 58.333333333333336%; + } + .note-editor .col-md-pull-6 { + right: 50%; + } + .note-editor .col-md-pull-5 { + right: 41.66666666666667%; + } + .note-editor .col-md-pull-4 { + right: 33.33333333333333%; + } + .note-editor .col-md-pull-3 { + right: 25%; + } + .note-editor .col-md-pull-2 { + right: 16.666666666666664%; + } + .note-editor .col-md-pull-1 { + right: 8.333333333333332%; + } + .note-editor .col-md-push-12 { + left: 100%; + } + .note-editor .col-md-push-11 { + left: 91.66666666666666%; + } + .note-editor .col-md-push-10 { + left: 83.33333333333334%; + } + .note-editor .col-md-push-9 { + left: 75%; + } + .note-editor .col-md-push-8 { + left: 66.66666666666666%; + } + .note-editor .col-md-push-7 { + left: 58.333333333333336%; + } + .note-editor .col-md-push-6 { + left: 50%; + } + .note-editor .col-md-push-5 { + left: 41.66666666666667%; + } + .note-editor .col-md-push-4 { + left: 33.33333333333333%; + } + .note-editor .col-md-push-3 { + left: 25%; + } + .note-editor .col-md-push-2 { + left: 16.666666666666664%; + } + .note-editor .col-md-push-1 { + left: 8.333333333333332%; + } + .note-editor .col-md-offset-12 { + margin-left: 100%; + } + .note-editor .col-md-offset-11 { + margin-left: 91.66666666666666%; + } + .note-editor .col-md-offset-10 { + margin-left: 83.33333333333334%; + } + .note-editor .col-md-offset-9 { + margin-left: 75%; + } + .note-editor .col-md-offset-8 { + margin-left: 66.66666666666666%; + } + .note-editor .col-md-offset-7 { + margin-left: 58.333333333333336%; + } + .note-editor .col-md-offset-6 { + margin-left: 50%; + } + .note-editor .col-md-offset-5 { + margin-left: 41.66666666666667%; + } + .note-editor .col-md-offset-4 { + margin-left: 33.33333333333333%; + } + .note-editor .col-md-offset-3 { + margin-left: 25%; + } + .note-editor .col-md-offset-2 { + margin-left: 16.666666666666664%; + } + .note-editor .col-md-offset-1 { + margin-left: 8.333333333333332%; + } +} +@media (min-width: 1200px) { + .note-editor .container { + width: 1170px; + } + .note-editor .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11 { + float: left; + } + .note-editor .col-lg-12 { + width: 100%; + } + .note-editor .col-lg-11 { + width: 91.66666666666666%; + } + .note-editor .col-lg-10 { + width: 83.33333333333334%; + } + .note-editor .col-lg-9 { + width: 75%; + } + .note-editor .col-lg-8 { + width: 66.66666666666666%; + } + .note-editor .col-lg-7 { + width: 58.333333333333336%; + } + .note-editor .col-lg-6 { + width: 50%; + } + .note-editor .col-lg-5 { + width: 41.66666666666667%; + } + .note-editor .col-lg-4 { + width: 33.33333333333333%; + } + .note-editor .col-lg-3 { + width: 25%; + } + .note-editor .col-lg-2 { + width: 16.666666666666664%; + } + .note-editor .col-lg-1 { + width: 8.333333333333332%; + } + .note-editor .col-lg-pull-12 { + right: 100%; + } + .note-editor .col-lg-pull-11 { + right: 91.66666666666666%; + } + .note-editor .col-lg-pull-10 { + right: 83.33333333333334%; + } + .note-editor .col-lg-pull-9 { + right: 75%; + } + .note-editor .col-lg-pull-8 { + right: 66.66666666666666%; + } + .note-editor .col-lg-pull-7 { + right: 58.333333333333336%; + } + .note-editor .col-lg-pull-6 { + right: 50%; + } + .note-editor .col-lg-pull-5 { + right: 41.66666666666667%; + } + .note-editor .col-lg-pull-4 { + right: 33.33333333333333%; + } + .note-editor .col-lg-pull-3 { + right: 25%; + } + .note-editor .col-lg-pull-2 { + right: 16.666666666666664%; + } + .note-editor .col-lg-pull-1 { + right: 8.333333333333332%; + } + .note-editor .col-lg-push-12 { + left: 100%; + } + .note-editor .col-lg-push-11 { + left: 91.66666666666666%; + } + .note-editor .col-lg-push-10 { + left: 83.33333333333334%; + } + .note-editor .col-lg-push-9 { + left: 75%; + } + .note-editor .col-lg-push-8 { + left: 66.66666666666666%; + } + .note-editor .col-lg-push-7 { + left: 58.333333333333336%; + } + .note-editor .col-lg-push-6 { + left: 50%; + } + .note-editor .col-lg-push-5 { + left: 41.66666666666667%; + } + .note-editor .col-lg-push-4 { + left: 33.33333333333333%; + } + .note-editor .col-lg-push-3 { + left: 25%; + } + .note-editor .col-lg-push-2 { + left: 16.666666666666664%; + } + .note-editor .col-lg-push-1 { + left: 8.333333333333332%; + } + .note-editor .col-lg-offset-12 { + margin-left: 100%; + } + .note-editor .col-lg-offset-11 { + margin-left: 91.66666666666666%; + } + .note-editor .col-lg-offset-10 { + margin-left: 83.33333333333334%; + } + .note-editor .col-lg-offset-9 { + margin-left: 75%; + } + .note-editor .col-lg-offset-8 { + margin-left: 66.66666666666666%; + } + .note-editor .col-lg-offset-7 { + margin-left: 58.333333333333336%; + } + .note-editor .col-lg-offset-6 { + margin-left: 50%; + } + .note-editor .col-lg-offset-5 { + margin-left: 41.66666666666667%; + } + .note-editor .col-lg-offset-4 { + margin-left: 33.33333333333333%; + } + .note-editor .col-lg-offset-3 { + margin-left: 25%; + } + .note-editor .col-lg-offset-2 { + margin-left: 16.666666666666664%; + } + .note-editor .col-lg-offset-1 { + margin-left: 8.333333333333332%; + } +} +.note-editor table { + max-width: 100%; + background-color: transparent; +} +.note-editor th { + text-align: left; +} +.note-editor .table { + width: 100%; + margin-bottom: 20px; +} +.note-editor .table > thead > tr > th, +.note-editor .table > tbody > tr > th, +.note-editor .table > tfoot > tr > th, +.note-editor .table > thead > tr > td, +.note-editor .table > tbody > tr > td, +.note-editor .table > tfoot > tr > td { + padding: 8px; + line-height: 1.428571429; + vertical-align: top; + border-top: 1px solid #dddddd; +} +.note-editor .table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; +} +.note-editor .table > caption + thead > tr:first-child > th, +.note-editor .table > colgroup + thead > tr:first-child > th, +.note-editor .table > thead:first-child > tr:first-child > th, +.note-editor .table > caption + thead > tr:first-child > td, +.note-editor .table > colgroup + thead > tr:first-child > td, +.note-editor .table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.note-editor .table > tbody + tbody { + border-top: 2px solid #dddddd; +} +.note-editor .table .table { + background-color: #ffffff; +} +.note-editor .table-condensed > thead > tr > th, +.note-editor .table-condensed > tbody > tr > th, +.note-editor .table-condensed > tfoot > tr > th, +.note-editor .table-condensed > thead > tr > td, +.note-editor .table-condensed > tbody > tr > td, +.note-editor .table-condensed > tfoot > tr > td { + padding: 5px; +} +.note-editor .table-bordered { + border: 1px solid #dddddd; +} +.note-editor .table-bordered > thead > tr > th, +.note-editor .table-bordered > tbody > tr > th, +.note-editor .table-bordered > tfoot > tr > th, +.note-editor .table-bordered > thead > tr > td, +.note-editor .table-bordered > tbody > tr > td, +.note-editor .table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; +} +.note-editor .table-bordered > thead > tr > th, +.note-editor .table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.note-editor .table-striped > tbody > tr:nth-child(odd) > td, +.note-editor .table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} +.note-editor .table-hover > tbody > tr:hover > td, +.note-editor .table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} +.note-editor table col[class*="col-"] { + float: none; + display: table-column; +} +.note-editor table td[class*="col-"], +.note-editor table th[class*="col-"] { + float: none; + display: table-cell; +} +.note-editor .table > thead > tr > td.active, +.note-editor .table > tbody > tr > td.active, +.note-editor .table > tfoot > tr > td.active, +.note-editor .table > thead > tr > th.active, +.note-editor .table > tbody > tr > th.active, +.note-editor .table > tfoot > tr > th.active, +.note-editor .table > thead > tr.active > td, +.note-editor .table > tbody > tr.active > td, +.note-editor .table > tfoot > tr.active > td, +.note-editor .table > thead > tr.active > th, +.note-editor .table > tbody > tr.active > th, +.note-editor .table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.note-editor .table > thead > tr > td.success, +.note-editor .table > tbody > tr > td.success, +.note-editor .table > tfoot > tr > td.success, +.note-editor .table > thead > tr > th.success, +.note-editor .table > tbody > tr > th.success, +.note-editor .table > tfoot > tr > th.success, +.note-editor .table > thead > tr.success > td, +.note-editor .table > tbody > tr.success > td, +.note-editor .table > tfoot > tr.success > td, +.note-editor .table > thead > tr.success > th, +.note-editor .table > tbody > tr.success > th, +.note-editor .table > tfoot > tr.success > th { + background-color: #dff0d8; + border-color: #d6e9c6; +} +.note-editor .table-hover > tbody > tr > td.success:hover, +.note-editor .table-hover > tbody > tr > th.success:hover, +.note-editor .table-hover > tbody > tr.success:hover > td, +.note-editor .table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; + border-color: #c9e2b3; +} +.note-editor .table > thead > tr > td.danger, +.note-editor .table > tbody > tr > td.danger, +.note-editor .table > tfoot > tr > td.danger, +.note-editor .table > thead > tr > th.danger, +.note-editor .table > tbody > tr > th.danger, +.note-editor .table > tfoot > tr > th.danger, +.note-editor .table > thead > tr.danger > td, +.note-editor .table > tbody > tr.danger > td, +.note-editor .table > tfoot > tr.danger > td, +.note-editor .table > thead > tr.danger > th, +.note-editor .table > tbody > tr.danger > th, +.note-editor .table > tfoot > tr.danger > th { + background-color: #f2dede; + border-color: #ebccd1; +} +.note-editor .table-hover > tbody > tr > td.danger:hover, +.note-editor .table-hover > tbody > tr > th.danger:hover, +.note-editor .table-hover > tbody > tr.danger:hover > td, +.note-editor .table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; + border-color: #e4b9c0; +} +.note-editor .table > thead > tr > td.warning, +.note-editor .table > tbody > tr > td.warning, +.note-editor .table > tfoot > tr > td.warning, +.note-editor .table > thead > tr > th.warning, +.note-editor .table > tbody > tr > th.warning, +.note-editor .table > tfoot > tr > th.warning, +.note-editor .table > thead > tr.warning > td, +.note-editor .table > tbody > tr.warning > td, +.note-editor .table > tfoot > tr.warning > td, +.note-editor .table > thead > tr.warning > th, +.note-editor .table > tbody > tr.warning > th, +.note-editor .table > tfoot > tr.warning > th { + background-color: #fcf8e3; + border-color: #faebcc; +} +.note-editor .table-hover > tbody > tr > td.warning:hover, +.note-editor .table-hover > tbody > tr > th.warning:hover, +.note-editor .table-hover > tbody > tr.warning:hover > td, +.note-editor .table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; + border-color: #f7e1b5; +} +@media (max-width: 767px) { + .note-editor .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + overflow-x: scroll; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #dddddd; + -webkit-overflow-scrolling: touch; + } + .note-editor .table-responsive > .table { + margin-bottom: 0; + } + .note-editor .table-responsive > .table > thead > tr > th, + .note-editor .table-responsive > .table > tbody > tr > th, + .note-editor .table-responsive > .table > tfoot > tr > th, + .note-editor .table-responsive > .table > thead > tr > td, + .note-editor .table-responsive > .table > tbody > tr > td, + .note-editor .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .note-editor .table-responsive > .table-bordered { + border: 0; + } + .note-editor .table-responsive > .table-bordered > thead > tr > th:first-child, + .note-editor .table-responsive > .table-bordered > tbody > tr > th:first-child, + .note-editor .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .note-editor .table-responsive > .table-bordered > thead > tr > td:first-child, + .note-editor .table-responsive > .table-bordered > tbody > tr > td:first-child, + .note-editor .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .note-editor .table-responsive > .table-bordered > thead > tr > th:last-child, + .note-editor .table-responsive > .table-bordered > tbody > tr > th:last-child, + .note-editor .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .note-editor .table-responsive > .table-bordered > thead > tr > td:last-child, + .note-editor .table-responsive > .table-bordered > tbody > tr > td:last-child, + .note-editor .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .note-editor .table-responsive > .table-bordered > tbody > tr:last-child > th, + .note-editor .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .note-editor .table-responsive > .table-bordered > tbody > tr:last-child > td, + .note-editor .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +.note-editor fieldset { + padding: 0; + margin: 0; + border: 0; +} +.note-editor legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +.note-editor label { + display: inline-block; + margin-bottom: 5px; + font-weight: bold; +} +.note-editor input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.note-editor input[type="radio"], +.note-editor input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + /* IE8-9 */ + + line-height: normal; +} +.note-editor input[type="file"] { + display: block; +} +.note-editor select[multiple], +.note-editor select[size] { + height: auto; +} +.note-editor select optgroup { + font-size: inherit; + font-style: inherit; + font-family: inherit; +} +.note-editor input[type="file"]:focus, +.note-editor input[type="radio"]:focus, +.note-editor input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.note-editor input[type="number"]::-webkit-outer-spin-button, +.note-editor input[type="number"]::-webkit-inner-spin-button { + height: auto; +} +.note-editor output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.428571429; + color: #555555; + vertical-align: middle; +} +.note-editor .form-control:-moz-placeholder { + color: #999999; +} +.note-editor .form-control::-moz-placeholder { + color: #999999; +} +.note-editor .form-control:-ms-input-placeholder { + color: #999999; +} +.note-editor .form-control::-webkit-input-placeholder { + color: #999999; +} +.note-editor .form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + color: #555555; + vertical-align: middle; + background-color: #ffffff; + background-image: none; + border: 1px solid #cccccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.note-editor .form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.note-editor .form-control[disabled], +.note-editor .form-control[readonly], +fieldset[disabled] .note-editor .form-control { + cursor: not-allowed; + background-color: #eeeeee; +} +textarea.note-editor .form-control { + height: auto; +} +.note-editor .form-group { + margin-bottom: 15px; +} +.note-editor .radio, +.note-editor .checkbox { + display: block; + min-height: 20px; + margin-top: 10px; + margin-bottom: 10px; + padding-left: 20px; + vertical-align: middle; +} +.note-editor .radio label, +.note-editor .checkbox label { + display: inline; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.note-editor .radio input[type="radio"], +.note-editor .radio-inline input[type="radio"], +.note-editor .checkbox input[type="checkbox"], +.note-editor .checkbox-inline input[type="checkbox"] { + float: left; + margin-left: -20px; +} +.note-editor .radio + .radio, +.note-editor .checkbox + .checkbox { + margin-top: -5px; +} +.note-editor .radio-inline, +.note-editor .checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.note-editor .radio-inline + .radio-inline, +.note-editor .checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +.note-editor input[type="radio"][disabled], +.note-editor input[type="checkbox"][disabled], +.note-editor .radio[disabled], +.note-editor .radio-inline[disabled], +.note-editor .checkbox[disabled], +.note-editor .checkbox-inline[disabled], +fieldset[disabled] .note-editor input[type="radio"], +fieldset[disabled] .note-editor input[type="checkbox"], +fieldset[disabled] .note-editor .radio, +fieldset[disabled] .note-editor .radio-inline, +fieldset[disabled] .note-editor .checkbox, +fieldset[disabled] .note-editor .checkbox-inline { + cursor: not-allowed; +} +.note-editor .input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.note-editor .input-sm { + height: 30px; + line-height: 30px; +} +textarea.note-editor .input-sm { + height: auto; +} +.note-editor .input-lg { + height: 45px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.note-editor .input-lg { + height: 45px; + line-height: 45px; +} +textarea.note-editor .input-lg { + height: auto; +} +.note-editor .has-warning .help-block, +.note-editor .has-warning .control-label { + color: #c09853; +} +.note-editor .has-warning .form-control { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.note-editor .has-warning .form-control:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; +} +.note-editor .has-warning .input-group-addon { + color: #c09853; + border-color: #c09853; + background-color: #fcf8e3; +} +.note-editor .has-error .help-block, +.note-editor .has-error .control-label { + color: #b94a48; +} +.note-editor .has-error .form-control { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.note-editor .has-error .form-control:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} +.note-editor .has-error .input-group-addon { + color: #b94a48; + border-color: #b94a48; + background-color: #f2dede; +} +.note-editor .has-success .help-block, +.note-editor .has-success .control-label { + color: #468847; +} +.note-editor .has-success .form-control { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.note-editor .has-success .form-control:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; +} +.note-editor .has-success .input-group-addon { + color: #468847; + border-color: #468847; + background-color: #dff0d8; +} +.note-editor .form-control-static { + margin-bottom: 0; +} +.note-editor .help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .note-editor .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .note-editor .form-inline .form-control { + display: inline-block; + } + .note-editor .form-inline .radio, + .note-editor .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; + } + .note-editor .form-inline .radio input[type="radio"], + .note-editor .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } +} +.note-editor .form-horizontal .control-label, +.note-editor .form-horizontal .radio, +.note-editor .form-horizontal .checkbox, +.note-editor .form-horizontal .radio-inline, +.note-editor .form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.note-editor .form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +.note-editor .form-horizontal .form-group:before, +.note-editor .form-horizontal .form-group:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .form-horizontal .form-group:after { + clear: both; +} +.note-editor .form-horizontal .form-group:before, +.note-editor .form-horizontal .form-group:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .form-horizontal .form-group:after { + clear: both; +} +.note-editor .form-horizontal .form-control-static { + padding-top: 7px; +} +@media (min-width: 768px) { + .note-editor .form-horizontal .control-label { + text-align: right; + } +} +.note-editor .btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} +.note-editor .btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.note-editor .btn:hover, +.note-editor .btn:focus { + color: #333333; + text-decoration: none; +} +.note-editor .btn:active, +.note-editor .btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.note-editor .btn.disabled, +.note-editor .btn[disabled], +fieldset[disabled] .note-editor .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.note-editor .btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.note-editor .btn-default:hover, +.note-editor .btn-default:focus, +.note-editor .btn-default:active, +.note-editor .btn-default.active, +.open .dropdown-toggle.note-editor .btn-default { + color: #333333; + background-color: #ebebeb; + border-color: #adadad; +} +.note-editor .btn-default:active, +.note-editor .btn-default.active, +.open .dropdown-toggle.note-editor .btn-default { + background-image: none; +} +.note-editor .btn-default.disabled, +.note-editor .btn-default[disabled], +fieldset[disabled] .note-editor .btn-default, +.note-editor .btn-default.disabled:hover, +.note-editor .btn-default[disabled]:hover, +fieldset[disabled] .note-editor .btn-default:hover, +.note-editor .btn-default.disabled:focus, +.note-editor .btn-default[disabled]:focus, +fieldset[disabled] .note-editor .btn-default:focus, +.note-editor .btn-default.disabled:active, +.note-editor .btn-default[disabled]:active, +fieldset[disabled] .note-editor .btn-default:active, +.note-editor .btn-default.disabled.active, +.note-editor .btn-default[disabled].active, +fieldset[disabled] .note-editor .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.note-editor .btn-primary { + color: #ffffff; + background-color: #428bca; + border-color: #357ebd; +} +.note-editor .btn-primary:hover, +.note-editor .btn-primary:focus, +.note-editor .btn-primary:active, +.note-editor .btn-primary.active, +.open .dropdown-toggle.note-editor .btn-primary { + color: #ffffff; + background-color: #3276b1; + border-color: #285e8e; +} +.note-editor .btn-primary:active, +.note-editor .btn-primary.active, +.open .dropdown-toggle.note-editor .btn-primary { + background-image: none; +} +.note-editor .btn-primary.disabled, +.note-editor .btn-primary[disabled], +fieldset[disabled] .note-editor .btn-primary, +.note-editor .btn-primary.disabled:hover, +.note-editor .btn-primary[disabled]:hover, +fieldset[disabled] .note-editor .btn-primary:hover, +.note-editor .btn-primary.disabled:focus, +.note-editor .btn-primary[disabled]:focus, +fieldset[disabled] .note-editor .btn-primary:focus, +.note-editor .btn-primary.disabled:active, +.note-editor .btn-primary[disabled]:active, +fieldset[disabled] .note-editor .btn-primary:active, +.note-editor .btn-primary.disabled.active, +.note-editor .btn-primary[disabled].active, +fieldset[disabled] .note-editor .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} +.note-editor .btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.note-editor .btn-warning:hover, +.note-editor .btn-warning:focus, +.note-editor .btn-warning:active, +.note-editor .btn-warning.active, +.open .dropdown-toggle.note-editor .btn-warning { + color: #ffffff; + background-color: #ed9c28; + border-color: #d58512; +} +.note-editor .btn-warning:active, +.note-editor .btn-warning.active, +.open .dropdown-toggle.note-editor .btn-warning { + background-image: none; +} +.note-editor .btn-warning.disabled, +.note-editor .btn-warning[disabled], +fieldset[disabled] .note-editor .btn-warning, +.note-editor .btn-warning.disabled:hover, +.note-editor .btn-warning[disabled]:hover, +fieldset[disabled] .note-editor .btn-warning:hover, +.note-editor .btn-warning.disabled:focus, +.note-editor .btn-warning[disabled]:focus, +fieldset[disabled] .note-editor .btn-warning:focus, +.note-editor .btn-warning.disabled:active, +.note-editor .btn-warning[disabled]:active, +fieldset[disabled] .note-editor .btn-warning:active, +.note-editor .btn-warning.disabled.active, +.note-editor .btn-warning[disabled].active, +fieldset[disabled] .note-editor .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.note-editor .btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.note-editor .btn-danger:hover, +.note-editor .btn-danger:focus, +.note-editor .btn-danger:active, +.note-editor .btn-danger.active, +.open .dropdown-toggle.note-editor .btn-danger { + color: #ffffff; + background-color: #d2322d; + border-color: #ac2925; +} +.note-editor .btn-danger:active, +.note-editor .btn-danger.active, +.open .dropdown-toggle.note-editor .btn-danger { + background-image: none; +} +.note-editor .btn-danger.disabled, +.note-editor .btn-danger[disabled], +fieldset[disabled] .note-editor .btn-danger, +.note-editor .btn-danger.disabled:hover, +.note-editor .btn-danger[disabled]:hover, +fieldset[disabled] .note-editor .btn-danger:hover, +.note-editor .btn-danger.disabled:focus, +.note-editor .btn-danger[disabled]:focus, +fieldset[disabled] .note-editor .btn-danger:focus, +.note-editor .btn-danger.disabled:active, +.note-editor .btn-danger[disabled]:active, +fieldset[disabled] .note-editor .btn-danger:active, +.note-editor .btn-danger.disabled.active, +.note-editor .btn-danger[disabled].active, +fieldset[disabled] .note-editor .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.note-editor .btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.note-editor .btn-success:hover, +.note-editor .btn-success:focus, +.note-editor .btn-success:active, +.note-editor .btn-success.active, +.open .dropdown-toggle.note-editor .btn-success { + color: #ffffff; + background-color: #47a447; + border-color: #398439; +} +.note-editor .btn-success:active, +.note-editor .btn-success.active, +.open .dropdown-toggle.note-editor .btn-success { + background-image: none; +} +.note-editor .btn-success.disabled, +.note-editor .btn-success[disabled], +fieldset[disabled] .note-editor .btn-success, +.note-editor .btn-success.disabled:hover, +.note-editor .btn-success[disabled]:hover, +fieldset[disabled] .note-editor .btn-success:hover, +.note-editor .btn-success.disabled:focus, +.note-editor .btn-success[disabled]:focus, +fieldset[disabled] .note-editor .btn-success:focus, +.note-editor .btn-success.disabled:active, +.note-editor .btn-success[disabled]:active, +fieldset[disabled] .note-editor .btn-success:active, +.note-editor .btn-success.disabled.active, +.note-editor .btn-success[disabled].active, +fieldset[disabled] .note-editor .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.note-editor .btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.note-editor .btn-info:hover, +.note-editor .btn-info:focus, +.note-editor .btn-info:active, +.note-editor .btn-info.active, +.open .dropdown-toggle.note-editor .btn-info { + color: #ffffff; + background-color: #39b3d7; + border-color: #269abc; +} +.note-editor .btn-info:active, +.note-editor .btn-info.active, +.open .dropdown-toggle.note-editor .btn-info { + background-image: none; +} +.note-editor .btn-info.disabled, +.note-editor .btn-info[disabled], +fieldset[disabled] .note-editor .btn-info, +.note-editor .btn-info.disabled:hover, +.note-editor .btn-info[disabled]:hover, +fieldset[disabled] .note-editor .btn-info:hover, +.note-editor .btn-info.disabled:focus, +.note-editor .btn-info[disabled]:focus, +fieldset[disabled] .note-editor .btn-info:focus, +.note-editor .btn-info.disabled:active, +.note-editor .btn-info[disabled]:active, +fieldset[disabled] .note-editor .btn-info:active, +.note-editor .btn-info.disabled.active, +.note-editor .btn-info[disabled].active, +fieldset[disabled] .note-editor .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.note-editor .btn-link { + color: #428bca; + font-weight: normal; + cursor: pointer; + border-radius: 0; +} +.note-editor .btn-link, +.note-editor .btn-link:active, +.note-editor .btn-link[disabled], +fieldset[disabled] .note-editor .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.note-editor .btn-link, +.note-editor .btn-link:hover, +.note-editor .btn-link:focus, +.note-editor .btn-link:active { + border-color: transparent; +} +.note-editor .btn-link:hover, +.note-editor .btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} +.note-editor .btn-link[disabled]:hover, +fieldset[disabled] .note-editor .btn-link:hover, +.note-editor .btn-link[disabled]:focus, +fieldset[disabled] .note-editor .btn-link:focus { + color: #999999; + text-decoration: none; +} +.note-editor .btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.note-editor .btn-sm, +.note-editor .btn-xs { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.note-editor .btn-xs { + padding: 1px 5px; +} +.note-editor .btn-block { + display: block; + width: 100%; + padding-left: 0; + padding-right: 0; +} +.note-editor .btn-block + .btn-block { + margin-top: 5px; +} +.note-editor input[type="submit"].btn-block, +.note-editor input[type="reset"].btn-block, +.note-editor input[type="button"].btn-block { + width: 100%; +} +.note-editor .fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.note-editor .fade.in { + opacity: 1; +} +.note-editor .collapse { + display: none; +} +.note-editor .collapse.in { + display: block; +} +.note-editor .collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + transition: height 0.35s ease; +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.note-editor .glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.note-editor .glyphicon:empty { + width: 1em; +} +.note-editor .glyphicon-asterisk:before { + content: "\2a"; +} +.note-editor .glyphicon-plus:before { + content: "\2b"; +} +.note-editor .glyphicon-euro:before { + content: "\20ac"; +} +.note-editor .glyphicon-minus:before { + content: "\2212"; +} +.note-editor .glyphicon-cloud:before { + content: "\2601"; +} +.note-editor .glyphicon-envelope:before { + content: "\2709"; +} +.note-editor .glyphicon-pencil:before { + content: "\270f"; +} +.note-editor .glyphicon-glass:before { + content: "\e001"; +} +.note-editor .glyphicon-music:before { + content: "\e002"; +} +.note-editor .glyphicon-search:before { + content: "\e003"; +} +.note-editor .glyphicon-heart:before { + content: "\e005"; +} +.note-editor .glyphicon-star:before { + content: "\e006"; +} +.note-editor .glyphicon-star-empty:before { + content: "\e007"; +} +.note-editor .glyphicon-user:before { + content: "\e008"; +} +.note-editor .glyphicon-film:before { + content: "\e009"; +} +.note-editor .glyphicon-th-large:before { + content: "\e010"; +} +.note-editor .glyphicon-th:before { + content: "\e011"; +} +.note-editor .glyphicon-th-list:before { + content: "\e012"; +} +.note-editor .glyphicon-ok:before { + content: "\e013"; +} +.note-editor .glyphicon-remove:before { + content: "\e014"; +} +.note-editor .glyphicon-zoom-in:before { + content: "\e015"; +} +.note-editor .glyphicon-zoom-out:before { + content: "\e016"; +} +.note-editor .glyphicon-off:before { + content: "\e017"; +} +.note-editor .glyphicon-signal:before { + content: "\e018"; +} +.note-editor .glyphicon-cog:before { + content: "\e019"; +} +.note-editor .glyphicon-trash:before { + content: "\e020"; +} +.note-editor .glyphicon-home:before { + content: "\e021"; +} +.note-editor .glyphicon-file:before { + content: "\e022"; +} +.note-editor .glyphicon-time:before { + content: "\e023"; +} +.note-editor .glyphicon-road:before { + content: "\e024"; +} +.note-editor .glyphicon-download-alt:before { + content: "\e025"; +} +.note-editor .glyphicon-download:before { + content: "\e026"; +} +.note-editor .glyphicon-upload:before { + content: "\e027"; +} +.note-editor .glyphicon-inbox:before { + content: "\e028"; +} +.note-editor .glyphicon-play-circle:before { + content: "\e029"; +} +.note-editor .glyphicon-repeat:before { + content: "\e030"; +} +.note-editor .glyphicon-refresh:before { + content: "\e031"; +} +.note-editor .glyphicon-list-alt:before { + content: "\e032"; +} +.note-editor .glyphicon-lock:before { + content: "\e033"; +} +.note-editor .glyphicon-flag:before { + content: "\e034"; +} +.note-editor .glyphicon-headphones:before { + content: "\e035"; +} +.note-editor .glyphicon-volume-off:before { + content: "\e036"; +} +.note-editor .glyphicon-volume-down:before { + content: "\e037"; +} +.note-editor .glyphicon-volume-up:before { + content: "\e038"; +} +.note-editor .glyphicon-qrcode:before { + content: "\e039"; +} +.note-editor .glyphicon-barcode:before { + content: "\e040"; +} +.note-editor .glyphicon-tag:before { + content: "\e041"; +} +.note-editor .glyphicon-tags:before { + content: "\e042"; +} +.note-editor .glyphicon-book:before { + content: "\e043"; +} +.note-editor .glyphicon-bookmark:before { + content: "\e044"; +} +.note-editor .glyphicon-print:before { + content: "\e045"; +} +.note-editor .glyphicon-camera:before { + content: "\e046"; +} +.note-editor .glyphicon-font:before { + content: "\e047"; +} +.note-editor .glyphicon-bold:before { + content: "\e048"; +} +.note-editor .glyphicon-italic:before { + content: "\e049"; +} +.note-editor .glyphicon-text-height:before { + content: "\e050"; +} +.note-editor .glyphicon-text-width:before { + content: "\e051"; +} +.note-editor .glyphicon-align-left:before { + content: "\e052"; +} +.note-editor .glyphicon-align-center:before { + content: "\e053"; +} +.note-editor .glyphicon-align-right:before { + content: "\e054"; +} +.note-editor .glyphicon-align-justify:before { + content: "\e055"; +} +.note-editor .glyphicon-list:before { + content: "\e056"; +} +.note-editor .glyphicon-indent-left:before { + content: "\e057"; +} +.note-editor .glyphicon-indent-right:before { + content: "\e058"; +} +.note-editor .glyphicon-facetime-video:before { + content: "\e059"; +} +.note-editor .glyphicon-picture:before { + content: "\e060"; +} +.note-editor .glyphicon-map-marker:before { + content: "\e062"; +} +.note-editor .glyphicon-adjust:before { + content: "\e063"; +} +.note-editor .glyphicon-tint:before { + content: "\e064"; +} +.note-editor .glyphicon-edit:before { + content: "\e065"; +} +.note-editor .glyphicon-share:before { + content: "\e066"; +} +.note-editor .glyphicon-check:before { + content: "\e067"; +} +.note-editor .glyphicon-move:before { + content: "\e068"; +} +.note-editor .glyphicon-step-backward:before { + content: "\e069"; +} +.note-editor .glyphicon-fast-backward:before { + content: "\e070"; +} +.note-editor .glyphicon-backward:before { + content: "\e071"; +} +.note-editor .glyphicon-play:before { + content: "\e072"; +} +.note-editor .glyphicon-pause:before { + content: "\e073"; +} +.note-editor .glyphicon-stop:before { + content: "\e074"; +} +.note-editor .glyphicon-forward:before { + content: "\e075"; +} +.note-editor .glyphicon-fast-forward:before { + content: "\e076"; +} +.note-editor .glyphicon-step-forward:before { + content: "\e077"; +} +.note-editor .glyphicon-eject:before { + content: "\e078"; +} +.note-editor .glyphicon-chevron-left:before { + content: "\e079"; +} +.note-editor .glyphicon-chevron-right:before { + content: "\e080"; +} +.note-editor .glyphicon-plus-sign:before { + content: "\e081"; +} +.note-editor .glyphicon-minus-sign:before { + content: "\e082"; +} +.note-editor .glyphicon-remove-sign:before { + content: "\e083"; +} +.note-editor .glyphicon-ok-sign:before { + content: "\e084"; +} +.note-editor .glyphicon-question-sign:before { + content: "\e085"; +} +.note-editor .glyphicon-info-sign:before { + content: "\e086"; +} +.note-editor .glyphicon-screenshot:before { + content: "\e087"; +} +.note-editor .glyphicon-remove-circle:before { + content: "\e088"; +} +.note-editor .glyphicon-ok-circle:before { + content: "\e089"; +} +.note-editor .glyphicon-ban-circle:before { + content: "\e090"; +} +.note-editor .glyphicon-arrow-left:before { + content: "\e091"; +} +.note-editor .glyphicon-arrow-right:before { + content: "\e092"; +} +.note-editor .glyphicon-arrow-up:before { + content: "\e093"; +} +.note-editor .glyphicon-arrow-down:before { + content: "\e094"; +} +.note-editor .glyphicon-share-alt:before { + content: "\e095"; +} +.note-editor .glyphicon-resize-full:before { + content: "\e096"; +} +.note-editor .glyphicon-resize-small:before { + content: "\e097"; +} +.note-editor .glyphicon-exclamation-sign:before { + content: "\e101"; +} +.note-editor .glyphicon-gift:before { + content: "\e102"; +} +.note-editor .glyphicon-leaf:before { + content: "\e103"; +} +.note-editor .glyphicon-fire:before { + content: "\e104"; +} +.note-editor .glyphicon-eye-open:before { + content: "\e105"; +} +.note-editor .glyphicon-eye-close:before { + content: "\e106"; +} +.note-editor .glyphicon-warning-sign:before { + content: "\e107"; +} +.note-editor .glyphicon-plane:before { + content: "\e108"; +} +.note-editor .glyphicon-calendar:before { + content: "\e109"; +} +.note-editor .glyphicon-random:before { + content: "\e110"; +} +.note-editor .glyphicon-comment:before { + content: "\e111"; +} +.note-editor .glyphicon-magnet:before { + content: "\e112"; +} +.note-editor .glyphicon-chevron-up:before { + content: "\e113"; +} +.note-editor .glyphicon-chevron-down:before { + content: "\e114"; +} +.note-editor .glyphicon-retweet:before { + content: "\e115"; +} +.note-editor .glyphicon-shopping-cart:before { + content: "\e116"; +} +.note-editor .glyphicon-folder-close:before { + content: "\e117"; +} +.note-editor .glyphicon-folder-open:before { + content: "\e118"; +} +.note-editor .glyphicon-resize-vertical:before { + content: "\e119"; +} +.note-editor .glyphicon-resize-horizontal:before { + content: "\e120"; +} +.note-editor .glyphicon-hdd:before { + content: "\e121"; +} +.note-editor .glyphicon-bullhorn:before { + content: "\e122"; +} +.note-editor .glyphicon-bell:before { + content: "\e123"; +} +.note-editor .glyphicon-certificate:before { + content: "\e124"; +} +.note-editor .glyphicon-thumbs-up:before { + content: "\e125"; +} +.note-editor .glyphicon-thumbs-down:before { + content: "\e126"; +} +.note-editor .glyphicon-hand-right:before { + content: "\e127"; +} +.note-editor .glyphicon-hand-left:before { + content: "\e128"; +} +.note-editor .glyphicon-hand-up:before { + content: "\e129"; +} +.note-editor .glyphicon-hand-down:before { + content: "\e130"; +} +.note-editor .glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.note-editor .glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.note-editor .glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.note-editor .glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.note-editor .glyphicon-globe:before { + content: "\e135"; +} +.note-editor .glyphicon-wrench:before { + content: "\e136"; +} +.note-editor .glyphicon-tasks:before { + content: "\e137"; +} +.note-editor .glyphicon-filter:before { + content: "\e138"; +} +.note-editor .glyphicon-briefcase:before { + content: "\e139"; +} +.note-editor .glyphicon-fullscreen:before { + content: "\e140"; +} +.note-editor .glyphicon-dashboard:before { + content: "\e141"; +} +.note-editor .glyphicon-paperclip:before { + content: "\e142"; +} +.note-editor .glyphicon-heart-empty:before { + content: "\e143"; +} +.note-editor .glyphicon-link:before { + content: "\e144"; +} +.note-editor .glyphicon-phone:before { + content: "\e145"; +} +.note-editor .glyphicon-pushpin:before { + content: "\e146"; +} +.note-editor .glyphicon-usd:before { + content: "\e148"; +} +.note-editor .glyphicon-gbp:before { + content: "\e149"; +} +.note-editor .glyphicon-sort:before { + content: "\e150"; +} +.note-editor .glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.note-editor .glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.note-editor .glyphicon-sort-by-order:before { + content: "\e153"; +} +.note-editor .glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.note-editor .glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.note-editor .glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.note-editor .glyphicon-unchecked:before { + content: "\e157"; +} +.note-editor .glyphicon-expand:before { + content: "\e158"; +} +.note-editor .glyphicon-collapse-down:before { + content: "\e159"; +} +.note-editor .glyphicon-collapse-up:before { + content: "\e160"; +} +.note-editor .glyphicon-log-in:before { + content: "\e161"; +} +.note-editor .glyphicon-flash:before { + content: "\e162"; +} +.note-editor .glyphicon-log-out:before { + content: "\e163"; +} +.note-editor .glyphicon-new-window:before { + content: "\e164"; +} +.note-editor .glyphicon-record:before { + content: "\e165"; +} +.note-editor .glyphicon-save:before { + content: "\e166"; +} +.note-editor .glyphicon-open:before { + content: "\e167"; +} +.note-editor .glyphicon-saved:before { + content: "\e168"; +} +.note-editor .glyphicon-import:before { + content: "\e169"; +} +.note-editor .glyphicon-export:before { + content: "\e170"; +} +.note-editor .glyphicon-send:before { + content: "\e171"; +} +.note-editor .glyphicon-floppy-disk:before { + content: "\e172"; +} +.note-editor .glyphicon-floppy-saved:before { + content: "\e173"; +} +.note-editor .glyphicon-floppy-remove:before { + content: "\e174"; +} +.note-editor .glyphicon-floppy-save:before { + content: "\e175"; +} +.note-editor .glyphicon-floppy-open:before { + content: "\e176"; +} +.note-editor .glyphicon-credit-card:before { + content: "\e177"; +} +.note-editor .glyphicon-transfer:before { + content: "\e178"; +} +.note-editor .glyphicon-cutlery:before { + content: "\e179"; +} +.note-editor .glyphicon-header:before { + content: "\e180"; +} +.note-editor .glyphicon-compressed:before { + content: "\e181"; +} +.note-editor .glyphicon-earphone:before { + content: "\e182"; +} +.note-editor .glyphicon-phone-alt:before { + content: "\e183"; +} +.note-editor .glyphicon-tower:before { + content: "\e184"; +} +.note-editor .glyphicon-stats:before { + content: "\e185"; +} +.note-editor .glyphicon-sd-video:before { + content: "\e186"; +} +.note-editor .glyphicon-hd-video:before { + content: "\e187"; +} +.note-editor .glyphicon-subtitles:before { + content: "\e188"; +} +.note-editor .glyphicon-sound-stereo:before { + content: "\e189"; +} +.note-editor .glyphicon-sound-dolby:before { + content: "\e190"; +} +.note-editor .glyphicon-sound-5-1:before { + content: "\e191"; +} +.note-editor .glyphicon-sound-6-1:before { + content: "\e192"; +} +.note-editor .glyphicon-sound-7-1:before { + content: "\e193"; +} +.note-editor .glyphicon-copyright-mark:before { + content: "\e194"; +} +.note-editor .glyphicon-registration-mark:before { + content: "\e195"; +} +.note-editor .glyphicon-cloud-download:before { + content: "\e197"; +} +.note-editor .glyphicon-cloud-upload:before { + content: "\e198"; +} +.note-editor .glyphicon-tree-conifer:before { + content: "\e199"; +} +.note-editor .glyphicon-tree-deciduous:before { + content: "\e200"; +} +.note-editor .caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + border-bottom: 0 dotted; +} +.note-editor .dropdown { + position: relative; +} +.note-editor .dropdown-toggle:focus { + outline: 0; +} +.note-editor .dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.note-editor .dropdown-menu.pull-right { + right: 0; + left: auto; +} +.note-editor .dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.note-editor .dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; + color: #333333; + white-space: nowrap; +} +.note-editor .dropdown-menu > li > a:hover, +.note-editor .dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} +.note-editor .dropdown-menu > .active > a, +.note-editor .dropdown-menu > .active > a:hover, +.note-editor .dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} +.note-editor .dropdown-menu > .disabled > a, +.note-editor .dropdown-menu > .disabled > a:hover, +.note-editor .dropdown-menu > .disabled > a:focus { + color: #999999; +} +.note-editor .dropdown-menu > .disabled > a:hover, +.note-editor .dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.note-editor .open > .dropdown-menu { + display: block; +} +.note-editor .open > a { + outline: 0; +} +.note-editor .dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.428571429; + color: #999999; +} +.note-editor .dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.note-editor .pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.note-editor .dropup .caret, +.note-editor .navbar-fixed-bottom .dropdown .caret { + border-top: 0 dotted; + border-bottom: 4px solid #000000; + content: ""; +} +.note-editor .dropup .dropdown-menu, +.note-editor .navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 768px) { + .note-editor .navbar-right .dropdown-menu { + right: 0; + left: auto; + } +} +.btn-default .note-editor .caret { + border-top-color: #333333; +} +.btn-primary .note-editor .caret, +.btn-success .note-editor .caret, +.btn-warning .note-editor .caret, +.btn-danger .note-editor .caret, +.btn-info .note-editor .caret { + border-top-color: #fff; +} +.note-editor .dropup .btn-default .caret { + border-bottom-color: #333333; +} +.note-editor .dropup .btn-primary .caret, +.note-editor .dropup .btn-success .caret, +.note-editor .dropup .btn-warning .caret, +.note-editor .dropup .btn-danger .caret, +.note-editor .dropup .btn-info .caret { + border-bottom-color: #fff; +} +.note-editor .btn-group, +.note-editor .btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.note-editor .btn-group > .btn, +.note-editor .btn-group-vertical > .btn { + position: relative; + float: left; +} +.note-editor .btn-group > .btn:hover, +.note-editor .btn-group-vertical > .btn:hover, +.note-editor .btn-group > .btn:focus, +.note-editor .btn-group-vertical > .btn:focus, +.note-editor .btn-group > .btn:active, +.note-editor .btn-group-vertical > .btn:active, +.note-editor .btn-group > .btn.active, +.note-editor .btn-group-vertical > .btn.active { + z-index: 2; +} +.note-editor .btn-group > .btn:focus, +.note-editor .btn-group-vertical > .btn:focus { + outline: none; +} +.note-editor .btn-group .btn + .btn, +.note-editor .btn-group .btn + .btn-group, +.note-editor .btn-group .btn-group + .btn, +.note-editor .btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.note-editor .btn-toolbar:before, +.note-editor .btn-toolbar:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .btn-toolbar:after { + clear: both; +} +.note-editor .btn-toolbar:before, +.note-editor .btn-toolbar:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .btn-toolbar:after { + clear: both; +} +.note-editor .btn-toolbar .btn-group { + float: left; +} +.note-editor .btn-toolbar > .btn + .btn, +.note-editor .btn-toolbar > .btn-group + .btn, +.note-editor .btn-toolbar > .btn + .btn-group, +.note-editor .btn-toolbar > .btn-group + .btn-group { + margin-left: 5px; +} +.note-editor .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.note-editor .btn-group > .btn:first-child { + margin-left: 0; +} +.note-editor .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.note-editor .btn-group > .btn:last-child:not(:first-child), +.note-editor .btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.note-editor .btn-group > .btn-group { + float: left; +} +.note-editor .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.note-editor .btn-group > .btn-group:first-child > .btn:last-child, +.note-editor .btn-group > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.note-editor .btn-group > .btn-group:last-child > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.note-editor .btn-group .dropdown-toggle:active, +.note-editor .btn-group.open .dropdown-toggle { + outline: 0; +} +.note-editor .btn-group-xs > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; + padding: 1px 5px; +} +.note-editor .btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.note-editor .btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.note-editor .btn-group > .btn + .dropdown-toggle { + padding-left: 5px; + padding-right: 5px; +} +.note-editor .btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.note-editor .btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.note-editor .btn .caret { + margin-left: 0; +} +.note-editor .btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.note-editor .dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.note-editor .btn-group-vertical > .btn, +.note-editor .btn-group-vertical > .btn-group { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.note-editor .btn-group-vertical > .btn-group:before, +.note-editor .btn-group-vertical > .btn-group:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .btn-group-vertical > .btn-group:after { + clear: both; +} +.note-editor .btn-group-vertical > .btn-group:before, +.note-editor .btn-group-vertical > .btn-group:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .btn-group-vertical > .btn-group:after { + clear: both; +} +.note-editor .btn-group-vertical > .btn-group > .btn { + float: none; +} +.note-editor .btn-group-vertical > .btn + .btn, +.note-editor .btn-group-vertical > .btn + .btn-group, +.note-editor .btn-group-vertical > .btn-group + .btn, +.note-editor .btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.note-editor .btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.note-editor .btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.note-editor .btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.note-editor .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.note-editor .btn-group-vertical > .btn-group:first-child > .btn:last-child, +.note-editor .btn-group-vertical > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.note-editor .btn-group-vertical > .btn-group:last-child > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.note-editor .btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.note-editor .btn-group-justified .btn { + float: none; + display: table-cell; + width: 1%; +} +.note-editor [data-toggle="buttons"] > .btn > input[type="radio"], +.note-editor [data-toggle="buttons"] > .btn > input[type="checkbox"] { + display: none; +} +.note-editor .input-group { + position: relative; + display: table; + border-collapse: separate; +} +.note-editor .input-group.col { + float: none; + padding-left: 0; + padding-right: 0; +} +.note-editor .input-group .form-control { + width: 100%; + margin-bottom: 0; +} +.note-editor .input-group-lg > .form-control, +.note-editor .input-group-lg > .input-group-addon, +.note-editor .input-group-lg > .input-group-btn > .btn { + height: 45px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.note-editor .input-group-lg > .form-control, +select.note-editor .input-group-lg > .input-group-addon, +select.note-editor .input-group-lg > .input-group-btn > .btn { + height: 45px; + line-height: 45px; +} +textarea.note-editor .input-group-lg > .form-control, +textarea.note-editor .input-group-lg > .input-group-addon, +textarea.note-editor .input-group-lg > .input-group-btn > .btn { + height: auto; +} +.note-editor .input-group-sm > .form-control, +.note-editor .input-group-sm > .input-group-addon, +.note-editor .input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.note-editor .input-group-sm > .form-control, +select.note-editor .input-group-sm > .input-group-addon, +select.note-editor .input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.note-editor .input-group-sm > .form-control, +textarea.note-editor .input-group-sm > .input-group-addon, +textarea.note-editor .input-group-sm > .input-group-btn > .btn { + height: auto; +} +.note-editor .input-group-addon, +.note-editor .input-group-btn, +.note-editor .input-group .form-control { + display: table-cell; +} +.note-editor .input-group-addon:not(:first-child):not(:last-child), +.note-editor .input-group-btn:not(:first-child):not(:last-child), +.note-editor .input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.note-editor .input-group-addon, +.note-editor .input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.note-editor .input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #cccccc; + border-radius: 4px; +} +.note-editor .input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.note-editor .input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.note-editor .input-group-addon input[type="radio"], +.note-editor .input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.note-editor .input-group .form-control:first-child, +.note-editor .input-group-addon:first-child, +.note-editor .input-group-btn:first-child > .btn, +.note-editor .input-group-btn:first-child > .dropdown-toggle, +.note-editor .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.note-editor .input-group-addon:first-child { + border-right: 0; +} +.note-editor .input-group .form-control:last-child, +.note-editor .input-group-addon:last-child, +.note-editor .input-group-btn:last-child > .btn, +.note-editor .input-group-btn:last-child > .dropdown-toggle, +.note-editor .input-group-btn:first-child > .btn:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.note-editor .input-group-addon:last-child { + border-left: 0; +} +.note-editor .input-group-btn { + position: relative; + white-space: nowrap; +} +.note-editor .input-group-btn:first-child > .btn { + margin-right: -1px; +} +.note-editor .input-group-btn:last-child > .btn { + margin-left: -1px; +} +.note-editor .input-group-btn > .btn { + position: relative; +} +.note-editor .input-group-btn > .btn + .btn { + margin-left: -4px; +} +.note-editor .input-group-btn > .btn:hover, +.note-editor .input-group-btn > .btn:active { + z-index: 2; +} +.note-editor .nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.note-editor .nav:before, +.note-editor .nav:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .nav:after { + clear: both; +} +.note-editor .nav:before, +.note-editor .nav:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .nav:after { + clear: both; +} +.note-editor .nav > li { + position: relative; + display: block; +} +.note-editor .nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.note-editor .nav > li > a:hover, +.note-editor .nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.note-editor .nav > li.disabled > a { + color: #999999; +} +.note-editor .nav > li.disabled > a:hover, +.note-editor .nav > li.disabled > a:focus { + color: #999999; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.note-editor .nav .open > a, +.note-editor .nav .open > a:hover, +.note-editor .nav .open > a:focus { + background-color: #eeeeee; + border-color: #428bca; +} +.note-editor .nav .open > a .caret, +.note-editor .nav .open > a:hover .caret, +.note-editor .nav .open > a:focus .caret { + border-top-color: #2a6496; + border-bottom-color: #2a6496; +} +.note-editor .nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.note-editor .nav > li > a > img { + max-width: none; +} +.note-editor .nav-tabs { + border-bottom: 1px solid #dddddd; +} +.note-editor .nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.note-editor .nav-tabs > li > a { + margin-right: 2px; + line-height: 1.428571429; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.note-editor .nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} +.note-editor .nav-tabs > li.active > a, +.note-editor .nav-tabs > li.active > a:hover, +.note-editor .nav-tabs > li.active > a:focus { + color: #555555; + background-color: #ffffff; + border: 1px solid #dddddd; + border-bottom-color: transparent; + cursor: default; +} +.note-editor .nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.note-editor .nav-tabs.nav-justified > li { + float: none; +} +.note-editor .nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +@media (min-width: 768px) { + .note-editor .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .note-editor .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.note-editor .nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.note-editor .nav-tabs.nav-justified > .active > a, +.note-editor .nav-tabs.nav-justified > .active > a:hover, +.note-editor .nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .note-editor .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .note-editor .nav-tabs.nav-justified > .active > a, + .note-editor .nav-tabs.nav-justified > .active > a:hover, + .note-editor .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.note-editor .nav-pills > li { + float: left; +} +.note-editor .nav-pills > li > a { + border-radius: 4px; +} +.note-editor .nav-pills > li + li { + margin-left: 2px; +} +.note-editor .nav-pills > li.active > a, +.note-editor .nav-pills > li.active > a:hover, +.note-editor .nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #428bca; +} +.note-editor .nav-pills > li.active > a .caret, +.note-editor .nav-pills > li.active > a:hover .caret, +.note-editor .nav-pills > li.active > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} +.note-editor .nav-stacked > li { + float: none; +} +.note-editor .nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.note-editor .nav-justified { + width: 100%; +} +.note-editor .nav-justified > li { + float: none; +} +.note-editor .nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +@media (min-width: 768px) { + .note-editor .nav-justified > li { + display: table-cell; + width: 1%; + } + .note-editor .nav-justified > li > a { + margin-bottom: 0; + } +} +.note-editor .nav-tabs-justified { + border-bottom: 0; +} +.note-editor .nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.note-editor .nav-tabs-justified > .active > a, +.note-editor .nav-tabs-justified > .active > a:hover, +.note-editor .nav-tabs-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .note-editor .nav-tabs-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .note-editor .nav-tabs-justified > .active > a, + .note-editor .nav-tabs-justified > .active > a:hover, + .note-editor .nav-tabs-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.note-editor .tab-content > .tab-pane { + display: none; +} +.note-editor .tab-content > .active { + display: block; +} +.note-editor .nav .caret { + border-top-color: #428bca; + border-bottom-color: #428bca; +} +.note-editor .nav a:hover .caret { + border-top-color: #2a6496; + border-bottom-color: #2a6496; +} +.note-editor .nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.note-editor .navbar { + position: relative; + z-index: 1000; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +.note-editor .navbar:before, +.note-editor .navbar:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .navbar:after { + clear: both; +} +.note-editor .navbar:before, +.note-editor .navbar:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .navbar:after { + clear: both; +} +@media (min-width: 768px) { + .note-editor .navbar { + border-radius: 4px; + } +} +.note-editor .navbar-header:before, +.note-editor .navbar-header:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .navbar-header:after { + clear: both; +} +.note-editor .navbar-header:before, +.note-editor .navbar-header:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .navbar-header:after { + clear: both; +} +@media (min-width: 768px) { + .note-editor .navbar-header { + float: left; + } +} +.note-editor .navbar-collapse { + max-height: 340px; + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.note-editor .navbar-collapse:before, +.note-editor .navbar-collapse:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .navbar-collapse:after { + clear: both; +} +.note-editor .navbar-collapse:before, +.note-editor .navbar-collapse:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .navbar-collapse:after { + clear: both; +} +.note-editor .navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .note-editor .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .note-editor .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .note-editor .navbar-collapse.in { + overflow-y: visible; + } + .note-editor .navbar-collapse .navbar-nav.navbar-left:first-child { + margin-left: -15px; + } + .note-editor .navbar-collapse .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } + .note-editor .navbar-collapse .navbar-text:last-child { + margin-right: 0; + } +} +.note-editor .container > .navbar-header, +.note-editor .container > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .note-editor .container > .navbar-header, + .note-editor .container > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.note-editor .navbar-static-top { + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .note-editor .navbar-static-top { + border-radius: 0; + } +} +.note-editor .navbar-fixed-top, +.note-editor .navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .note-editor .navbar-fixed-top, + .note-editor .navbar-fixed-bottom { + border-radius: 0; + } +} +.note-editor .navbar-fixed-top { + z-index: 1030; + top: 0; +} +.note-editor .navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; +} +.note-editor .navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.note-editor .navbar-brand:hover, +.note-editor .navbar-brand:focus { + text-decoration: none; +} +@media (min-width: 768px) { + .navbar > .container .note-editor .navbar-brand { + margin-left: -15px; + } +} +.note-editor .navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + border: 1px solid transparent; + border-radius: 4px; +} +.note-editor .navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.note-editor .navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .note-editor .navbar-toggle { + display: none; + } +} +.note-editor .navbar-nav { + margin: 7.5px -15px; +} +.note-editor .navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .note-editor .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .note-editor .navbar-nav .open .dropdown-menu > li > a, + .note-editor .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .note-editor .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .note-editor .navbar-nav .open .dropdown-menu > li > a:hover, + .note-editor .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .note-editor .navbar-nav { + float: left; + margin: 0; + } + .note-editor .navbar-nav > li { + float: left; + } + .note-editor .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +@media (min-width: 768px) { + .note-editor .navbar-left { + float: left !important; + } + .note-editor .navbar-right { + float: right !important; + } +} +.note-editor .navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 8px; + margin-bottom: 8px; +} +@media (min-width: 768px) { + .note-editor .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .note-editor .navbar-form .form-control { + display: inline-block; + } + .note-editor .navbar-form .radio, + .note-editor .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; + } + .note-editor .navbar-form .radio input[type="radio"], + .note-editor .navbar-form .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } +} +@media (max-width: 767px) { + .note-editor .navbar-form .form-group { + margin-bottom: 5px; + } +} +@media (min-width: 768px) { + .note-editor .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.note-editor .navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.note-editor .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.note-editor .navbar-nav.pull-right > li > .dropdown-menu, +.note-editor .navbar-nav > li > .dropdown-menu.pull-right { + left: auto; + right: 0; +} +.note-editor .navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.note-editor .navbar-text { + float: left; + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .note-editor .navbar-text { + margin-left: 15px; + margin-right: 15px; + } +} +.note-editor .navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.note-editor .navbar-default .navbar-brand { + color: #777777; +} +.note-editor .navbar-default .navbar-brand:hover, +.note-editor .navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.note-editor .navbar-default .navbar-text { + color: #777777; +} +.note-editor .navbar-default .navbar-nav > li > a { + color: #777777; +} +.note-editor .navbar-default .navbar-nav > li > a:hover, +.note-editor .navbar-default .navbar-nav > li > a:focus { + color: #333333; + background-color: transparent; +} +.note-editor .navbar-default .navbar-nav > .active > a, +.note-editor .navbar-default .navbar-nav > .active > a:hover, +.note-editor .navbar-default .navbar-nav > .active > a:focus { + color: #555555; + background-color: #e7e7e7; +} +.note-editor .navbar-default .navbar-nav > .disabled > a, +.note-editor .navbar-default .navbar-nav > .disabled > a:hover, +.note-editor .navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.note-editor .navbar-default .navbar-toggle { + border-color: #dddddd; +} +.note-editor .navbar-default .navbar-toggle:hover, +.note-editor .navbar-default .navbar-toggle:focus { + background-color: #dddddd; +} +.note-editor .navbar-default .navbar-toggle .icon-bar { + background-color: #cccccc; +} +.note-editor .navbar-default .navbar-collapse, +.note-editor .navbar-default .navbar-form { + border-color: #e7e7e7; +} +.note-editor .navbar-default .navbar-nav > .dropdown > a:hover .caret, +.note-editor .navbar-default .navbar-nav > .dropdown > a:focus .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} +.note-editor .navbar-default .navbar-nav > .open > a, +.note-editor .navbar-default .navbar-nav > .open > a:hover, +.note-editor .navbar-default .navbar-nav > .open > a:focus { + background-color: #e7e7e7; + color: #555555; +} +.note-editor .navbar-default .navbar-nav > .open > a .caret, +.note-editor .navbar-default .navbar-nav > .open > a:hover .caret, +.note-editor .navbar-default .navbar-nav > .open > a:focus .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} +.note-editor .navbar-default .navbar-nav > .dropdown > a .caret { + border-top-color: #777777; + border-bottom-color: #777777; +} +@media (max-width: 767px) { + .note-editor .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + .note-editor .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .note-editor .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333333; + background-color: transparent; + } + .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.note-editor .navbar-default .navbar-link { + color: #777777; +} +.note-editor .navbar-default .navbar-link:hover { + color: #333333; +} +.note-editor .navbar-inverse { + background-color: #222222; + border-color: #080808; +} +.note-editor .navbar-inverse .navbar-brand { + color: #999999; +} +.note-editor .navbar-inverse .navbar-brand:hover, +.note-editor .navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; +} +.note-editor .navbar-inverse .navbar-text { + color: #999999; +} +.note-editor .navbar-inverse .navbar-nav > li > a { + color: #999999; +} +.note-editor .navbar-inverse .navbar-nav > li > a:hover, +.note-editor .navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; +} +.note-editor .navbar-inverse .navbar-nav > .active > a, +.note-editor .navbar-inverse .navbar-nav > .active > a:hover, +.note-editor .navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; +} +.note-editor .navbar-inverse .navbar-nav > .disabled > a, +.note-editor .navbar-inverse .navbar-nav > .disabled > a:hover, +.note-editor .navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; +} +.note-editor .navbar-inverse .navbar-toggle { + border-color: #333333; +} +.note-editor .navbar-inverse .navbar-toggle:hover, +.note-editor .navbar-inverse .navbar-toggle:focus { + background-color: #333333; +} +.note-editor .navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} +.note-editor .navbar-inverse .navbar-collapse, +.note-editor .navbar-inverse .navbar-form { + border-color: #101010; +} +.note-editor .navbar-inverse .navbar-nav > .open > a, +.note-editor .navbar-inverse .navbar-nav > .open > a:hover, +.note-editor .navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #ffffff; +} +.note-editor .navbar-inverse .navbar-nav > .dropdown > a:hover .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} +.note-editor .navbar-inverse .navbar-nav > .dropdown > a .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} +.note-editor .navbar-inverse .navbar-nav > .open > a .caret, +.note-editor .navbar-inverse .navbar-nav > .open > a:hover .caret, +.note-editor .navbar-inverse .navbar-nav > .open > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} +@media (max-width: 767px) { + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #999999; + } + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} +.note-editor .navbar-inverse .navbar-link { + color: #999999; +} +.note-editor .navbar-inverse .navbar-link:hover { + color: #ffffff; +} +.note-editor .breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.note-editor .breadcrumb > li { + display: inline-block; +} +.note-editor .breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #cccccc; +} +.note-editor .breadcrumb > .active { + color: #999999; +} +.note-editor .pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.note-editor .pagination > li { + display: inline; +} +.note-editor .pagination > li > a, +.note-editor .pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.428571429; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; + margin-left: -1px; +} +.note-editor .pagination > li:first-child > a, +.note-editor .pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.note-editor .pagination > li:last-child > a, +.note-editor .pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.note-editor .pagination > li > a:hover, +.note-editor .pagination > li > span:hover, +.note-editor .pagination > li > a:focus, +.note-editor .pagination > li > span:focus { + background-color: #eeeeee; +} +.note-editor .pagination > .active > a, +.note-editor .pagination > .active > span, +.note-editor .pagination > .active > a:hover, +.note-editor .pagination > .active > span:hover, +.note-editor .pagination > .active > a:focus, +.note-editor .pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + background-color: #428bca; + border-color: #428bca; + cursor: default; +} +.note-editor .pagination > .disabled > span, +.note-editor .pagination > .disabled > span:hover, +.note-editor .pagination > .disabled > span:focus, +.note-editor .pagination > .disabled > a, +.note-editor .pagination > .disabled > a:hover, +.note-editor .pagination > .disabled > a:focus { + color: #999999; + background-color: #ffffff; + border-color: #dddddd; + cursor: not-allowed; +} +.note-editor .pagination-lg > li > a, +.note-editor .pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.note-editor .pagination-lg > li:first-child > a, +.note-editor .pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} +.note-editor .pagination-lg > li:last-child > a, +.note-editor .pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.note-editor .pagination-sm > li > a, +.note-editor .pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.note-editor .pagination-sm > li:first-child > a, +.note-editor .pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.note-editor .pagination-sm > li:last-child > a, +.note-editor .pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.note-editor .pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; +} +.note-editor .pager:before, +.note-editor .pager:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .pager:after { + clear: both; +} +.note-editor .pager:before, +.note-editor .pager:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .pager:after { + clear: both; +} +.note-editor .pager li { + display: inline; +} +.note-editor .pager li > a, +.note-editor .pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 15px; +} +.note-editor .pager li > a:hover, +.note-editor .pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.note-editor .pager .next > a, +.note-editor .pager .next > span { + float: right; +} +.note-editor .pager .previous > a, +.note-editor .pager .previous > span { + float: left; +} +.note-editor .pager .disabled > a, +.note-editor .pager .disabled > a:hover, +.note-editor .pager .disabled > a:focus, +.note-editor .pager .disabled > span { + color: #999999; + background-color: #ffffff; + cursor: not-allowed; +} +.note-editor .label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +.note-editor .label[href]:hover, +.note-editor .label[href]:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.note-editor .label:empty { + display: none; +} +.note-editor .label-default { + background-color: #999999; +} +.note-editor .label-default[href]:hover, +.note-editor .label-default[href]:focus { + background-color: #808080; +} +.note-editor .label-primary { + background-color: #428bca; +} +.note-editor .label-primary[href]:hover, +.note-editor .label-primary[href]:focus { + background-color: #3071a9; +} +.note-editor .label-success { + background-color: #5cb85c; +} +.note-editor .label-success[href]:hover, +.note-editor .label-success[href]:focus { + background-color: #449d44; +} +.note-editor .label-info { + background-color: #5bc0de; +} +.note-editor .label-info[href]:hover, +.note-editor .label-info[href]:focus { + background-color: #31b0d5; +} +.note-editor .label-warning { + background-color: #f0ad4e; +} +.note-editor .label-warning[href]:hover, +.note-editor .label-warning[href]:focus { + background-color: #ec971f; +} +.note-editor .label-danger { + background-color: #d9534f; +} +.note-editor .label-danger[href]:hover, +.note-editor .label-danger[href]:focus { + background-color: #c9302c; +} +.note-editor .badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #ffffff; + line-height: 1; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: #999999; + border-radius: 10px; +} +.note-editor .badge:empty { + display: none; +} +.note-editor a.badge:hover, +.note-editor a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.note-editor .btn .badge { + position: relative; + top: -1px; +} +.note-editor a.list-group-item.active > .badge, +.note-editor .nav-pills > .active > a > .badge { + color: #428bca; + background-color: #ffffff; +} +.note-editor .nav-pills > li > a > .badge { + margin-left: 3px; +} +.note-editor .jumbotron { + padding: 30px; + margin-bottom: 30px; + font-size: 21px; + font-weight: 200; + line-height: 2.1428571435; + color: inherit; + background-color: #eeeeee; +} +.note-editor .jumbotron h1 { + line-height: 1; + color: inherit; +} +.note-editor .jumbotron p { + line-height: 1.4; +} +.container .note-editor .jumbotron { + border-radius: 6px; +} +@media screen and (min-width: 768px) { + .note-editor .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .note-editor .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .note-editor .jumbotron h1 { + font-size: 63px; + } +} +.note-editor .thumbnail { + padding: 4px; + line-height: 1.428571429; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; + display: block; + margin-bottom: 20px; +} +.note-editor .thumbnail > img { + display: block; + max-width: 100%; + height: auto; +} +.note-editor a.thumbnail:hover, +.note-editor a.thumbnail:focus, +.note-editor a.thumbnail.active { + border-color: #428bca; +} +.note-editor .thumbnail > img { + margin-left: auto; + margin-right: auto; +} +.note-editor .thumbnail .caption { + padding: 9px; + color: #333333; +} +.note-editor .alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.note-editor .alert h4 { + margin-top: 0; + color: inherit; +} +.note-editor .alert .alert-link { + font-weight: bold; +} +.note-editor .alert > p, +.note-editor .alert > ul { + margin-bottom: 0; +} +.note-editor .alert > p + p { + margin-top: 5px; +} +.note-editor .alert-dismissable { + padding-right: 35px; +} +.note-editor .alert-dismissable .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.note-editor .alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #468847; +} +.note-editor .alert-success hr { + border-top-color: #c9e2b3; +} +.note-editor .alert-success .alert-link { + color: #356635; +} +.note-editor .alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #3a87ad; +} +.note-editor .alert-info hr { + border-top-color: #a6e1ec; +} +.note-editor .alert-info .alert-link { + color: #2d6987; +} +.note-editor .alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #c09853; +} +.note-editor .alert-warning hr { + border-top-color: #f7e1b5; +} +.note-editor .alert-warning .alert-link { + color: #a47e3c; +} +.note-editor .alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #b94a48; +} +.note-editor .alert-danger hr { + border-top-color: #e4b9c0; +} +.note-editor .alert-danger .alert-link { + color: #953b39; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.note-editor .progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.note-editor .progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #ffffff; + text-align: center; + background-color: #428bca; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.note-editor .progress-striped .progress-bar { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.note-editor .progress.active .progress-bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.note-editor .progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .note-editor .progress-bar-success { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.note-editor .progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .note-editor .progress-bar-info { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.note-editor .progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .note-editor .progress-bar-warning { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.note-editor .progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .note-editor .progress-bar-danger { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.note-editor .media, +.note-editor .media-body { + overflow: hidden; + zoom: 1; +} +.note-editor .media, +.note-editor .media .media { + margin-top: 15px; +} +.note-editor .media:first-child { + margin-top: 0; +} +.note-editor .media-object { + display: block; +} +.note-editor .media-heading { + margin: 0 0 5px; +} +.note-editor .media > .pull-left { + margin-right: 10px; +} +.note-editor .media > .pull-right { + margin-left: 10px; +} +.note-editor .media-list { + padding-left: 0; + list-style: none; +} +.note-editor .list-group { + margin-bottom: 20px; + padding-left: 0; +} +.note-editor .list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} +.note-editor .list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.note-editor .list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.note-editor .list-group-item > .badge { + float: right; +} +.note-editor .list-group-item > .badge + .badge { + margin-right: 5px; +} +.note-editor a.list-group-item { + color: #555555; +} +.note-editor a.list-group-item .list-group-item-heading { + color: #333333; +} +.note-editor a.list-group-item:hover, +.note-editor a.list-group-item:focus { + text-decoration: none; + background-color: #f5f5f5; +} +.note-editor a.list-group-item.active, +.note-editor a.list-group-item.active:hover, +.note-editor a.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #428bca; + border-color: #428bca; +} +.note-editor a.list-group-item.active .list-group-item-heading, +.note-editor a.list-group-item.active:hover .list-group-item-heading, +.note-editor a.list-group-item.active:focus .list-group-item-heading { + color: inherit; +} +.note-editor a.list-group-item.active .list-group-item-text, +.note-editor a.list-group-item.active:hover .list-group-item-text, +.note-editor a.list-group-item.active:focus .list-group-item-text { + color: #e1edf7; +} +.note-editor .list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.note-editor .list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.note-editor .panel { + margin-bottom: 20px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.note-editor .panel-body { + padding: 15px; +} +.note-editor .panel-body:before, +.note-editor .panel-body:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .panel-body:after { + clear: both; +} +.note-editor .panel-body:before, +.note-editor .panel-body:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.note-editor .panel-body:after { + clear: both; +} +.note-editor .panel > .list-group { + margin-bottom: 0; +} +.note-editor .panel > .list-group .list-group-item { + border-width: 1px 0; +} +.note-editor .panel > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.note-editor .panel > .list-group .list-group-item:last-child { + border-bottom: 0; +} +.note-editor .panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.note-editor .panel > .table, +.note-editor .panel > .table-responsive { + margin-bottom: 0; +} +.note-editor .panel > .panel-body + .table, +.note-editor .panel > .panel-body + .table-responsive { + border-top: 1px solid #dddddd; +} +.note-editor .panel > .table-bordered, +.note-editor .panel > .table-responsive > .table-bordered { + border: 0; +} +.note-editor .panel > .table-bordered > thead > tr > th:first-child, +.note-editor .panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.note-editor .panel > .table-bordered > tbody > tr > th:first-child, +.note-editor .panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.note-editor .panel > .table-bordered > tfoot > tr > th:first-child, +.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.note-editor .panel > .table-bordered > thead > tr > td:first-child, +.note-editor .panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.note-editor .panel > .table-bordered > tbody > tr > td:first-child, +.note-editor .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.note-editor .panel > .table-bordered > tfoot > tr > td:first-child, +.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.note-editor .panel > .table-bordered > thead > tr > th:last-child, +.note-editor .panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.note-editor .panel > .table-bordered > tbody > tr > th:last-child, +.note-editor .panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.note-editor .panel > .table-bordered > tfoot > tr > th:last-child, +.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.note-editor .panel > .table-bordered > thead > tr > td:last-child, +.note-editor .panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.note-editor .panel > .table-bordered > tbody > tr > td:last-child, +.note-editor .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.note-editor .panel > .table-bordered > tfoot > tr > td:last-child, +.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.note-editor .panel > .table-bordered > thead > tr:last-child > th, +.note-editor .panel > .table-responsive > .table-bordered > thead > tr:last-child > th, +.note-editor .panel > .table-bordered > tbody > tr:last-child > th, +.note-editor .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.note-editor .panel > .table-bordered > tfoot > tr:last-child > th, +.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th, +.note-editor .panel > .table-bordered > thead > tr:last-child > td, +.note-editor .panel > .table-responsive > .table-bordered > thead > tr:last-child > td, +.note-editor .panel > .table-bordered > tbody > tr:last-child > td, +.note-editor .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.note-editor .panel > .table-bordered > tfoot > tr:last-child > td, +.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; +} +.note-editor .panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.note-editor .panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; +} +.note-editor .panel-title > a { + color: inherit; +} +.note-editor .panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.note-editor .panel-group .panel { + margin-bottom: 0; + border-radius: 4px; + overflow: hidden; +} +.note-editor .panel-group .panel + .panel { + margin-top: 5px; +} +.note-editor .panel-group .panel-heading { + border-bottom: 0; +} +.note-editor .panel-group .panel-heading + .panel-collapse .panel-body { + border-top: 1px solid #dddddd; +} +.note-editor .panel-group .panel-footer { + border-top: 0; +} +.note-editor .panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; +} +.note-editor .panel-default { + border-color: #dddddd; +} +.note-editor .panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; +} +.note-editor .panel-default > .panel-heading + .panel-collapse .panel-body { + border-top-color: #dddddd; +} +.note-editor .panel-default > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #dddddd; +} +.note-editor .panel-primary { + border-color: #428bca; +} +.note-editor .panel-primary > .panel-heading { + color: #ffffff; + background-color: #428bca; + border-color: #428bca; +} +.note-editor .panel-primary > .panel-heading + .panel-collapse .panel-body { + border-top-color: #428bca; +} +.note-editor .panel-primary > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #428bca; +} +.note-editor .panel-success { + border-color: #d6e9c6; +} +.note-editor .panel-success > .panel-heading { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.note-editor .panel-success > .panel-heading + .panel-collapse .panel-body { + border-top-color: #d6e9c6; +} +.note-editor .panel-success > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #d6e9c6; +} +.note-editor .panel-warning { + border-color: #faebcc; +} +.note-editor .panel-warning > .panel-heading { + color: #c09853; + background-color: #fcf8e3; + border-color: #faebcc; +} +.note-editor .panel-warning > .panel-heading + .panel-collapse .panel-body { + border-top-color: #faebcc; +} +.note-editor .panel-warning > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #faebcc; +} +.note-editor .panel-danger { + border-color: #ebccd1; +} +.note-editor .panel-danger > .panel-heading { + color: #b94a48; + background-color: #f2dede; + border-color: #ebccd1; +} +.note-editor .panel-danger > .panel-heading + .panel-collapse .panel-body { + border-top-color: #ebccd1; +} +.note-editor .panel-danger > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #ebccd1; +} +.note-editor .panel-info { + border-color: #bce8f1; +} +.note-editor .panel-info > .panel-heading { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} +.note-editor .panel-info > .panel-heading + .panel-collapse .panel-body { + border-top-color: #bce8f1; +} +.note-editor .panel-info > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #bce8f1; +} +.note-editor .well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.note-editor .well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.note-editor .well-lg { + padding: 24px; + border-radius: 6px; +} +.note-editor .well-sm { + padding: 9px; + border-radius: 3px; +} +.note-editor .close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.note-editor .close:hover, +.note-editor .close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.note-editor .close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: auto; + overflow-y: scroll; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-dialog { + margin-left: auto; + margin-right: auto; + width: auto; + padding: 10px; + z-index: 1050; +} +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: none; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.428571429px; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.428571429; +} +.modal-body { + position: relative; + padding: 20px; +} +.modal-footer { + margin-top: 15px; + padding: 19px 20px 20px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer:before, +.modal-footer:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.modal-footer:after { + clear: both; +} +.modal-footer:before, +.modal-footer:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.modal-footer:after { + clear: both; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +@media screen and (min-width: 768px) { + .modal-dialog { + width: 600px; + padding-top: 30px; + padding-bottom: 30px; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } +} +.tooltip { + position: absolute; + z-index: 1030; + display: block; + visibility: visible; + font-size: 12px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + right: 5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + background-color: #ffffff; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover .arrow { + border-width: 11px; +} +.popover .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; + line-height: 1; +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-control.left { + background-image: -webkit-gradient(linear, 0% top, 100% top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0%), color-stop(rgba(0, 0, 0, 0.0001) 100%)); + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-gradient(linear, 0% top, 100% top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0%), color-stop(rgba(0, 0, 0, 0.5) 100%)); + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicons-chevron-left, + .carousel-control .glyphicons-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + margin-left: -15px; + font-size: 30px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.clearfix:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +tr.visible-xs, +th.visible-xs, +td.visible-xs { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-xs.visible-sm { + display: block !important; + } + tr.visible-xs.visible-sm { + display: table-row !important; + } + th.visible-xs.visible-sm, + td.visible-xs.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-xs.visible-md { + display: block !important; + } + tr.visible-xs.visible-md { + display: table-row !important; + } + th.visible-xs.visible-md, + td.visible-xs.visible-md { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-xs.visible-lg { + display: block !important; + } + tr.visible-xs.visible-lg { + display: table-row !important; + } + th.visible-xs.visible-lg, + td.visible-xs.visible-lg { + display: table-cell !important; + } +} +.visible-sm, +tr.visible-sm, +th.visible-sm, +td.visible-sm { + display: none !important; +} +@media (max-width: 767px) { + .visible-sm.visible-xs { + display: block !important; + } + tr.visible-sm.visible-xs { + display: table-row !important; + } + th.visible-sm.visible-xs, + td.visible-sm.visible-xs { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-sm.visible-md { + display: block !important; + } + tr.visible-sm.visible-md { + display: table-row !important; + } + th.visible-sm.visible-md, + td.visible-sm.visible-md { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-sm.visible-lg { + display: block !important; + } + tr.visible-sm.visible-lg { + display: table-row !important; + } + th.visible-sm.visible-lg, + td.visible-sm.visible-lg { + display: table-cell !important; + } +} +.visible-md, +tr.visible-md, +th.visible-md, +td.visible-md { + display: none !important; +} +@media (max-width: 767px) { + .visible-md.visible-xs { + display: block !important; + } + tr.visible-md.visible-xs { + display: table-row !important; + } + th.visible-md.visible-xs, + td.visible-md.visible-xs { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-md.visible-sm { + display: block !important; + } + tr.visible-md.visible-sm { + display: table-row !important; + } + th.visible-md.visible-sm, + td.visible-md.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-md.visible-lg { + display: block !important; + } + tr.visible-md.visible-lg { + display: table-row !important; + } + th.visible-md.visible-lg, + td.visible-md.visible-lg { + display: table-cell !important; + } +} +.visible-lg, +tr.visible-lg, +th.visible-lg, +td.visible-lg { + display: none !important; +} +@media (max-width: 767px) { + .visible-lg.visible-xs { + display: block !important; + } + tr.visible-lg.visible-xs { + display: table-row !important; + } + th.visible-lg.visible-xs, + td.visible-lg.visible-xs { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-lg.visible-sm { + display: block !important; + } + tr.visible-lg.visible-sm { + display: table-row !important; + } + th.visible-lg.visible-sm, + td.visible-lg.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-lg.visible-md { + display: block !important; + } + tr.visible-lg.visible-md { + display: table-row !important; + } + th.visible-lg.visible-md, + td.visible-lg.visible-md { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +.hidden-xs { + display: block !important; +} +tr.hidden-xs { + display: table-row !important; +} +th.hidden-xs, +td.hidden-xs { + display: table-cell !important; +} +@media (max-width: 767px) { + .hidden-xs, + tr.hidden-xs, + th.hidden-xs, + td.hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-xs.hidden-sm, + tr.hidden-xs.hidden-sm, + th.hidden-xs.hidden-sm, + td.hidden-xs.hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-xs.hidden-md, + tr.hidden-xs.hidden-md, + th.hidden-xs.hidden-md, + td.hidden-xs.hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-xs.hidden-lg, + tr.hidden-xs.hidden-lg, + th.hidden-xs.hidden-lg, + td.hidden-xs.hidden-lg { + display: none !important; + } +} +.hidden-sm { + display: block !important; +} +tr.hidden-sm { + display: table-row !important; +} +th.hidden-sm, +td.hidden-sm { + display: table-cell !important; +} +@media (max-width: 767px) { + .hidden-sm.hidden-xs, + tr.hidden-sm.hidden-xs, + th.hidden-sm.hidden-xs, + td.hidden-sm.hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm, + tr.hidden-sm, + th.hidden-sm, + td.hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-sm.hidden-md, + tr.hidden-sm.hidden-md, + th.hidden-sm.hidden-md, + td.hidden-sm.hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-sm.hidden-lg, + tr.hidden-sm.hidden-lg, + th.hidden-sm.hidden-lg, + td.hidden-sm.hidden-lg { + display: none !important; + } +} +.hidden-md { + display: block !important; +} +tr.hidden-md { + display: table-row !important; +} +th.hidden-md, +td.hidden-md { + display: table-cell !important; +} +@media (max-width: 767px) { + .hidden-md.hidden-xs, + tr.hidden-md.hidden-xs, + th.hidden-md.hidden-xs, + td.hidden-md.hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-md.hidden-sm, + tr.hidden-md.hidden-sm, + th.hidden-md.hidden-sm, + td.hidden-md.hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md, + tr.hidden-md, + th.hidden-md, + td.hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-md.hidden-lg, + tr.hidden-md.hidden-lg, + th.hidden-md.hidden-lg, + td.hidden-md.hidden-lg { + display: none !important; + } +} +.hidden-lg { + display: block !important; +} +tr.hidden-lg { + display: table-row !important; +} +th.hidden-lg, +td.hidden-lg { + display: table-cell !important; +} +@media (max-width: 767px) { + .hidden-lg.hidden-xs, + tr.hidden-lg.hidden-xs, + th.hidden-lg.hidden-xs, + td.hidden-lg.hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-lg.hidden-sm, + tr.hidden-lg.hidden-sm, + th.hidden-lg.hidden-sm, + td.hidden-lg.hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-lg.hidden-md, + tr.hidden-lg.hidden-md, + th.hidden-lg.hidden-md, + td.hidden-lg.hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg, + tr.hidden-lg, + th.hidden-lg, + td.hidden-lg { + display: none !important; + } +} +.visible-print, +tr.visible-print, +th.visible-print, +td.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } + .hidden-print, + tr.hidden-print, + th.hidden-print, + td.hidden-print { + display: none !important; + } +} diff --git a/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote.css b/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote.css new file mode 100644 index 000000000..01cb03315 --- /dev/null +++ b/src/main/webapp/assets/custom-css/swrap-bootstrap/summernote.css @@ -0,0 +1,446 @@ +.note-editor { + height: 300px; +} + +.note-editor .note-dropzone { + position: absolute; + z-index: 1; + display: none; + color: #87cefa; + background-color: white; + border: 2px dashed #87cefa; + opacity: .95; + pointer-event: none +} + +.note-editor .note-dropzone .note-dropzone-message { + display: table-cell; + font-size: 28px; + font-weight: bold; + text-align: center; + vertical-align: middle +} + +.note-editor .note-dropzone.hover { + color: #098ddf; + border: 2px dashed #098ddf +} + +.note-editor.dragover .note-dropzone { + display: table +} + +.note-editor.fullscreen { + position: fixed; + top: 0; + left: 0; + z-index: 1050; + width: 100% +} + +.note-editor.fullscreen .note-editable { + background-color: white +} + +.note-editor.fullscreen .note-resizebar { + display: none +} + +.note-editor.codeview .note-editable { + display: none +} + +.note-editor.codeview .note-codable { + display: block +} + +.note-editor .note-toolbar { + padding-bottom: 5px; + padding-left: 10px; + padding-top: 5px; + margin: 0; + background-color: #f5f5f5; + border-bottom: 1px solid #E7EAEC +} + +.note-editor .note-toolbar > .btn-group { + margin-top: 5px; + margin-right: 5px; + margin-left: 0 +} + +.note-editor .note-toolbar .note-table .dropdown-menu { + min-width: 0; + padding: 5px +} + +.note-editor .note-toolbar .note-table .dropdown-menu .note-dimension-picker { + font-size: 18px +} + +.note-editor .note-toolbar .note-table .dropdown-menu .note-dimension-picker .note-dimension-picker-mousecatcher { + position: absolute !important; + z-index: 3; + width: 10em; + height: 10em; + cursor: pointer +} + +.note-editor .note-toolbar .note-table .dropdown-menu .note-dimension-picker .note-dimension-picker-unhighlighted { + position: relative !important; + z-index: 1; + width: 5em; + height: 5em; + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIj4+Pjp6ekKlAqjAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKhmnaJzPAAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC') repeat +} + +.note-editor .note-toolbar .note-table .dropdown-menu .note-dimension-picker .note-dimension-picker-highlighted { + position: absolute !important; + z-index: 2; + width: 1em; + height: 1em; + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIjd6vvD2f9LKLW+AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKwNDEVT0AAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC') repeat +} + +.note-editor .note-toolbar .note-style h1, .note-editor .note-toolbar .note-style h2, .note-editor .note-toolbar .note-style h3, .note-editor .note-toolbar .note-style h4, .note-editor .note-toolbar .note-style h5, .note-editor .note-toolbar .note-style h6, .note-editor .note-toolbar .note-style blockquote { + margin: 0 +} + +.note-editor .note-toolbar .note-color .dropdown-toggle { + width: 20px; + padding-left: 5px +} + +.note-editor .note-toolbar .note-color .dropdown-menu { + min-width: 290px +} + +.note-editor .note-toolbar .note-color .dropdown-menu .btn-group { + margin: 0 +} + +.note-editor .note-toolbar .note-color .dropdown-menu .btn-group:first-child { + margin: 0 5px +} + +.note-editor .note-toolbar .note-color .dropdown-menu .btn-group .note-palette-title { + margin: 2px 7px; + font-size: 12px; + text-align: center; + border-bottom: 1px solid #eee +} + +.note-editor .note-toolbar .note-color .dropdown-menu .btn-group .note-color-reset { + padding: 0 3px; + margin: 5px; + font-size: 12px; + cursor: pointer; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px +} + +.note-editor .note-toolbar .note-color .dropdown-menu .btn-group .note-color-reset:hover { + background: #eee +} + +.note-editor .note-toolbar .note-para .dropdown-menu { + min-width: 216px; + padding: 5px +} + +.note-editor .note-toolbar .note-para .dropdown-menu > div:first-child { + margin-right: 5px +} + +.note-editor .note-statusbar { + background-color: #f5f5f5 +} + +.note-editor .note-statusbar .note-resizebar { + width: 100%; + height: 8px; + cursor: s-resize; + border-top: 1px solid #a9a9a9 +} + +.note-editor .note-statusbar .note-resizebar .note-icon-bar { + width: 20px; + margin: 1px auto; + border-top: 1px solid #a9a9a9 +} + +.note-editor .note-popover .popover { + max-width: none +} + +.note-editor .note-popover .popover .popover-content { + padding: 5px +} + +.note-editor .note-popover .popover .popover-content a { + display: inline-block; + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + vertical-align: middle +} + +.note-editor .note-popover .popover .popover-content .btn-group + .btn-group { + margin-left: 5px +} + +.note-editor .note-popover .popover .arrow { + left: 20px +} + +.note-editor .note-handle .note-control-selection { + position: absolute; + display: none; + border: 1px solid black +} + +.note-editor .note-handle .note-control-selection > div { + position: absolute +} + +.note-editor .note-handle .note-control-selection .note-control-selection-bg { + width: 100%; + height: 100%; + background-color: black; + -webkit-opacity: .3; + -khtml-opacity: .3; + -moz-opacity: .3; + opacity: .3; + -ms-filter: alpha(opacity=30); + filter: alpha(opacity=30) +} + +.note-editor .note-handle .note-control-selection .note-control-handle { + width: 7px; + height: 7px; + border: 1px solid black +} + +.note-editor .note-handle .note-control-selection .note-control-holder { + width: 7px; + height: 7px; + border: 1px solid black +} + +.note-editor .note-handle .note-control-selection .note-control-sizing { + width: 7px; + height: 7px; + background-color: white; + border: 1px solid black +} + +.note-editor .note-handle .note-control-selection .note-control-nw { + top: -5px; + left: -5px; + border-right: 0; + border-bottom: 0 +} + +.note-editor .note-handle .note-control-selection .note-control-ne { + top: -5px; + right: -5px; + border-bottom: 0; + border-left: none +} + +.note-editor .note-handle .note-control-selection .note-control-sw { + bottom: -5px; + left: -5px; + border-top: 0; + border-right: 0 +} + +.note-editor .note-handle .note-control-selection .note-control-se { + right: -5px; + bottom: -5px; + cursor: se-resize +} + +.note-editor .note-handle .note-control-selection .note-control-selection-info { + right: 0; + bottom: 0; + padding: 5px; + margin: 5px; + font-size: 12px; + color: white; + background-color: black; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-opacity: .7; + -khtml-opacity: .7; + -moz-opacity: .7; + opacity: .7; + -ms-filter: alpha(opacity=70); + filter: alpha(opacity=70) +} + +.note-editor .note-dialog > div { + display: none +} + +.note-editor .note-dialog .note-image-dialog .note-dropzone { + min-height: 100px; + margin-bottom: 10px; + font-size: 30px; + line-height: 4; + color: lightgray; + text-align: center; + border: 4px dashed lightgray +} + +.note-editor .note-dialog .note-help-dialog { + font-size: 12px; + color: #ccc; + background: transparent; + background-color: #222 !important; + border: 0; + -webkit-opacity: .9; + -khtml-opacity: .9; + -moz-opacity: .9; + opacity: .9; + -ms-filter: alpha(opacity=90); + filter: alpha(opacity=90) +} + +.note-editor .note-dialog .note-help-dialog .modal-content { + background: transparent; + border: 1px solid white; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none +} + +.note-editor .note-dialog .note-help-dialog a { + font-size: 12px; + color: white +} + +.note-editor .note-dialog .note-help-dialog .title { + padding-bottom: 5px; + font-size: 14px; + font-weight: bold; + color: white; + border-bottom: white 1px solid +} + +.note-editor .note-dialog .note-help-dialog .modal-close { + font-size: 14px; + color: #dd0; + cursor: pointer +} + +.note-editor .note-dialog .note-help-dialog .note-shortcut-layout { + width: 100% +} + +.note-editor .note-dialog .note-help-dialog .note-shortcut-layout td { + vertical-align: top +} + +.note-editor .note-dialog .note-help-dialog .note-shortcut { + margin-top: 8px +} + +.note-editor .note-dialog .note-help-dialog .note-shortcut th { + font-size: 13px; + color: #dd0; + text-align: left +} + +.note-editor .note-dialog .note-help-dialog .note-shortcut td:first-child { + min-width: 110px; + padding-right: 10px; + font-family: "Courier New"; + color: #dd0; + text-align: right +} + +.note-editor .note-editable { + padding: 20px; + overflow: auto; + outline: 0 +} + +.note-editor .note-editable[contenteditable="false"] { + background-color: #e5e5e5 +} + +.note-editor .note-codable { + display: none; + width: 100%; + padding: 10px; + margin-bottom: 0; + font-family: Menlo, Monaco, monospace, sans-serif; + font-size: 14px; + color: #ccc; + background-color: #222; + border: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + box-shadow: none; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + resize: none +} + +.note-editor .dropdown-menu { + min-width: 90px +} + +.note-editor .dropdown-menu.right { + right: 0; + left: auto +} + +.note-editor .dropdown-menu.right::before { + right: 9px; + left: auto !important +} + +.note-editor .dropdown-menu.right::after { + right: 10px; + left: auto !important +} + +.note-editor .dropdown-menu li a i { + color: deepskyblue; + visibility: hidden +} + +.note-editor .dropdown-menu li a.checked i { + visibility: visible +} + +.note-editor .note-fontsize-10 { + font-size: 10px +} + +.note-editor .note-color-palette { + line-height: 1 +} + +.note-editor .note-color-palette div .note-color-btn { + width: 17px; + height: 17px; + padding: 0; + margin: 0; + border: 1px solid #fff +} + +.note-editor .note-color-palette div .note-color-btn:hover { + border: 1px solid #000 +} \ No newline at end of file diff --git a/src/main/webapp/assets/custom-js/extention.js b/src/main/webapp/assets/custom-js/extention.js new file mode 100644 index 000000000..25642aa46 --- /dev/null +++ b/src/main/webapp/assets/custom-js/extention.js @@ -0,0 +1,7 @@ +String.prototype.capitalize = function(){ + var sa = this.replace(/-/g,' '); + var saa = sa.toLowerCase(); + var sb = saa.replace( /(^|\s)([a-z])/g , function(m,p1,p2){ return p1+p2.toUpperCase(); } ); + var sc = sb.replace(/\s+/g, '-'); + return sc; +}; \ No newline at end of file diff --git a/src/main/webapp/assets/custom-js/plugins/slimscroll/jquery.slimscroll.js b/src/main/webapp/assets/custom-js/plugins/slimscroll/jquery.slimscroll.js deleted file mode 100644 index 9c3b4dde2..000000000 --- a/src/main/webapp/assets/custom-js/plugins/slimscroll/jquery.slimscroll.js +++ /dev/null @@ -1,470 +0,0 @@ -/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la) - * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) - * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. - * - * Version: 1.3.6 - * - */ -(function($) { - - $.fn.extend({ - slimScroll: function(options) { - - var defaults = { - - // width in pixels of the visible scroll area - width : 'auto', - - // height in pixels of the visible scroll area - height : '250px', - - // width in pixels of the scrollbar and rail - size : '7px', - - // scrollbar color, accepts any hex/color value - color: '#000', - - // scrollbar position - left/right - position : 'right', - - // distance in pixels between the side edge and the scrollbar - distance : '1px', - - // default scroll position on load - top / bottom / $('selector') - start : 'top', - - // sets scrollbar opacity - opacity : .4, - - // enables always-on mode for the scrollbar - alwaysVisible : false, - - // check if we should hide the scrollbar when user is hovering over - disableFadeOut : false, - - // sets visibility of the rail - railVisible : false, - - // sets rail color - railColor : '#333', - - // sets rail opacity - railOpacity : .2, - - // whether we should use jQuery UI Draggable to enable bar dragging - railDraggable : true, - - // defautlt CSS class of the slimscroll rail - railClass : 'slimScrollRail', - - // defautlt CSS class of the slimscroll bar - barClass : 'slimScrollBar', - - // defautlt CSS class of the slimscroll wrapper - wrapperClass : 'slimScrollDiv', - - // check if mousewheel should scroll the window if we reach top/bottom - allowPageScroll : false, - - // scroll amount applied to each mouse wheel step - wheelStep : 20, - - // scroll amount applied when user is using gestures - touchScrollStep : 200, - - // sets border radius - borderRadius: '7px', - - // sets border radius of the rail - railBorderRadius : '7px' - }; - - var o = $.extend(defaults, options); - - // do it for every element that matches selector - this.each(function(){ - - var isOverPanel, isOverBar, isDragg, queueHide, touchDif, - barHeight, percentScroll, lastScroll, - divS = '
', - minBarHeight = 30, - releaseScroll = false; - - // used in event handlers and for better minification - var me = $(this); - - // ensure we are not binding it again - if (me.parent().hasClass(o.wrapperClass)) - { - // start from last bar position - var offset = me.scrollTop(); - - // find bar and rail - bar = me.closest('.' + o.barClass); - rail = me.closest('.' + o.railClass); - - getBarHeight(); - - // check if we should scroll existing instance - if ($.isPlainObject(options)) - { - // Pass height: auto to an existing slimscroll object to force a resize after contents have changed - if ( 'height' in options && options.height == 'auto' ) { - me.parent().css('height', 'auto'); - me.css('height', 'auto'); - var height = me.parent().parent().height(); - me.parent().css('height', height); - me.css('height', height); - } - - if ('scrollTo' in options) - { - // jump to a static point - offset = parseInt(o.scrollTo); - } - else if ('scrollBy' in options) - { - // jump by value pixels - offset += parseInt(o.scrollBy); - } - else if ('destroy' in options) - { - // remove slimscroll elements - bar.remove(); - rail.remove(); - me.unwrap(); - return; - } - - // scroll content by the given offset - scrollContent(offset, false, true); - } - - return; - } - else if ($.isPlainObject(options)) - { - if ('destroy' in options) - { - return; - } - } - - // optionally set height to the parent's height - o.height = (o.height == 'auto') ? me.parent().height() : o.height; - - // wrap content - var wrapper = $(divS) - .addClass(o.wrapperClass) - .css({ - position: 'relative', - overflow: 'hidden', - width: o.width, - height: o.height - }); - - // update style for the div - me.css({ - overflow: 'hidden', - width: o.width, - height: o.height - }); - - // create scrollbar rail - var rail = $(divS) - .addClass(o.railClass) - .css({ - width: o.size, - height: '100%', - position: 'absolute', - top: 0, - display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none', - 'border-radius': o.railBorderRadius, - background: o.railColor, - opacity: o.railOpacity, - zIndex: 90 - }); - - // create scrollbar - var bar = $(divS) - .addClass(o.barClass) - .css({ - background: o.color, - width: o.size, - position: 'absolute', - top: 0, - opacity: o.opacity, - display: o.alwaysVisible ? 'block' : 'none', - 'border-radius' : o.borderRadius, - BorderRadius: o.borderRadius, - MozBorderRadius: o.borderRadius, - WebkitBorderRadius: o.borderRadius, - zIndex: 99 - }); - - // set position - var posCss = (o.position == 'right') ? { right: o.distance } : { left: o.distance }; - rail.css(posCss); - bar.css(posCss); - - // wrap it - me.wrap(wrapper); - - // append to parent div - me.parent().append(bar); - me.parent().append(rail); - - // make it draggable and no longer dependent on the jqueryUI - if (o.railDraggable){ - bar.bind("mousedown", function(e) { - var $doc = $(document); - isDragg = true; - t = parseFloat(bar.css('top')); - pageY = e.pageY; - - $doc.bind("mousemove.slimscroll", function(e){ - currTop = t + e.pageY - pageY; - bar.css('top', currTop); - scrollContent(0, bar.position().top, false);// scroll content - }); - - $doc.bind("mouseup.slimscroll", function(e) { - isDragg = false;hideBar(); - $doc.unbind('.slimscroll'); - }); - return false; - }).bind("selectstart.slimscroll", function(e){ - e.stopPropagation(); - e.preventDefault(); - return false; - }); - } - - // on rail over - rail.hover(function(){ - showBar(); - }, function(){ - hideBar(); - }); - - // on bar over - bar.hover(function(){ - isOverBar = true; - }, function(){ - isOverBar = false; - }); - - // show on parent mouseover - me.hover(function(){ - isOverPanel = true; - showBar(); - hideBar(); - }, function(){ - isOverPanel = false; - hideBar(); - }); - - // support for mobile - me.bind('touchstart', function(e,b){ - if (e.originalEvent.touches.length) - { - // record where touch started - touchDif = e.originalEvent.touches[0].pageY; - } - }); - - me.bind('touchmove', function(e){ - // prevent scrolling the page if necessary - if(!releaseScroll) - { - e.originalEvent.preventDefault(); - } - if (e.originalEvent.touches.length) - { - // see how far user swiped - var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep; - // scroll content - scrollContent(diff, true); - touchDif = e.originalEvent.touches[0].pageY; - } - }); - - // set up initial height - getBarHeight(); - - // check start position - if (o.start === 'bottom') - { - // scroll content to bottom - bar.css({ top: me.outerHeight() - bar.outerHeight() }); - scrollContent(0, true); - } - else if (o.start !== 'top') - { - // assume jQuery selector - scrollContent($(o.start).position().top, null, true); - - // make sure bar stays hidden - if (!o.alwaysVisible) { bar.hide(); } - } - - // attach scroll events - attachWheel(this); - - function _onWheel(e) - { - // use mouse wheel only when mouse is over - if (!isOverPanel) { return; } - - var e = e || window.event; - - var delta = 0; - if (e.wheelDelta) { delta = -e.wheelDelta/120; } - if (e.detail) { delta = e.detail / 3; } - - var target = e.target || e.srcTarget || e.srcElement; - if ($(target).closest('.' + o.wrapperClass).is(me.parent())) { - // scroll content - scrollContent(delta, true); - } - - // stop window scroll - if (e.preventDefault && !releaseScroll) { e.preventDefault(); } - if (!releaseScroll) { e.returnValue = false; } - } - - function scrollContent(y, isWheel, isJump) - { - releaseScroll = false; - var delta = y; - var maxTop = me.outerHeight() - bar.outerHeight(); - - if (isWheel) - { - // move bar with mouse wheel - delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight(); - - // move bar, make sure it doesn't go out - delta = Math.min(Math.max(delta, 0), maxTop); - - // if scrolling down, make sure a fractional change to the - // scroll position isn't rounded away when the scrollbar's CSS is set - // this flooring of delta would happened automatically when - // bar.css is set below, but we floor here for clarity - delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta); - - // scroll the scrollbar - bar.css({ top: delta + 'px' }); - } - - // calculate actual scroll amount - percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight()); - delta = percentScroll * (me[0].scrollHeight - me.outerHeight()); - - if (isJump) - { - delta = y; - var offsetTop = delta / me[0].scrollHeight * me.outerHeight(); - offsetTop = Math.min(Math.max(offsetTop, 0), maxTop); - bar.css({ top: offsetTop + 'px' }); - } - - // scroll content - me.scrollTop(delta); - - // fire scrolling event - me.trigger('slimscrolling', ~~delta); - - // ensure bar is visible - showBar(); - - // trigger hide when scroll is stopped - hideBar(); - } - - function attachWheel(target) - { - if (window.addEventListener) - { - target.addEventListener('DOMMouseScroll', _onWheel, false ); - target.addEventListener('mousewheel', _onWheel, false ); - } - else - { - document.attachEvent("onmousewheel", _onWheel) - } - } - - function getBarHeight() - { - // calculate scrollbar height and make sure it is not too small - barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight); - bar.css({ height: barHeight + 'px' }); - - // hide scrollbar if content is not long enough - var display = barHeight == me.outerHeight() ? 'none' : 'block'; - bar.css({ display: display }); - } - - function showBar() - { - // recalculate bar height - getBarHeight(); - clearTimeout(queueHide); - - // when bar reached top or bottom - if (percentScroll == ~~percentScroll) - { - //release wheel - releaseScroll = o.allowPageScroll; - - // publish approporiate event - if (lastScroll != percentScroll) - { - var msg = (~~percentScroll == 0) ? 'top' : 'bottom'; - me.trigger('slimscroll', msg); - } - } - else - { - releaseScroll = false; - } - lastScroll = percentScroll; - - // show only when required - if(barHeight >= me.outerHeight()) { - //allow window scroll - releaseScroll = true; - return; - } - bar.stop(true,true).fadeIn('fast'); - if (o.railVisible) { rail.stop(true,true).fadeIn('fast'); } - } - - function hideBar() - { - // only hide when options allow it - if (!o.alwaysVisible) - { - queueHide = setTimeout(function(){ - if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg) - { - bar.fadeOut('slow'); - rail.fadeOut('slow'); - } - }, 1000); - } - } - - }); - - // maintain chainability - return this; - } - }); - - $.fn.extend({ - slimscroll: $.fn.slimScroll - }); - -})(jQuery); \ No newline at end of file diff --git a/src/main/webapp/assets/custom-js/plugins/slimscroll/jquery.slimscroll.min.js b/src/main/webapp/assets/custom-js/plugins/slimscroll/jquery.slimscroll.min.js deleted file mode 100644 index 7ecb25283..000000000 --- a/src/main/webapp/assets/custom-js/plugins/slimscroll/jquery.slimscroll.min.js +++ /dev/null @@ -1,16 +0,0 @@ -/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la) - * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) - * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. - * - * Version: 1.3.6 - * - */ -(function(e){e.fn.extend({slimScroll:function(g){var a=e.extend({width:"auto",height:"250px",size:"7px",color:"#000",position:"right",distance:"1px",start:"top",opacity:.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"},g);this.each(function(){function v(d){if(r){d=d||window.event; - var c=0;d.wheelDelta&&(c=-d.wheelDelta/120);d.detail&&(c=d.detail/3);e(d.target||d.srcTarget||d.srcElement).closest("."+a.wrapperClass).is(b.parent())&&m(c,!0);d.preventDefault&&!k&&d.preventDefault();k||(d.returnValue=!1)}}function m(d,e,g){k=!1;var f=d,h=b.outerHeight()-c.outerHeight();e&&(f=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),f=Math.min(Math.max(f,0),h),f=0=b.outerHeight()?k=!0:(c.stop(!0, - !0).fadeIn("fast"),a.railVisible&&h.stop(!0,!0).fadeIn("fast"))}function p(){a.alwaysVisible||(B=setTimeout(function(){a.disableFadeOut&&r||y||z||(c.fadeOut("slow"),h.fadeOut("slow"))},1E3))}var r,y,z,B,A,u,l,C,k=!1,b=e(this);if(b.parent().hasClass(a.wrapperClass)){var n=b.scrollTop(),c=b.closest("."+a.barClass),h=b.closest("."+a.railClass);x();if(e.isPlainObject(g)){if("height"in g&&"auto"==g.height){b.parent().css("height","auto");b.css("height","auto");var q=b.parent().parent().height();b.parent().css("height", - q);b.css("height",q)}if("scrollTo"in g)n=parseInt(a.scrollTo);else if("scrollBy"in g)n+=parseInt(a.scrollBy);else if("destroy"in g){c.remove();h.remove();b.unwrap();return}m(n,!1,!0)}}else if(!(e.isPlainObject(g)&&"destroy"in g)){a.height="auto"==a.height?b.parent().height():a.height;n=e("
").addClass(a.wrapperClass).css({position:"relative",overflow:"hidden",width:a.width,height:a.height});b.css({overflow:"hidden",width:a.width,height:a.height});var h=e("
").addClass(a.railClass).css({width:a.size, - height:"100%",position:"absolute",top:0,display:a.alwaysVisible&&a.railVisible?"block":"none","border-radius":a.railBorderRadius,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=e("
").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible?"block":"none","border-radius":a.borderRadius,BorderRadius:a.borderRadius,MozBorderRadius:a.borderRadius,WebkitBorderRadius:a.borderRadius,zIndex:99}),q="right"==a.position? -{right:a.distance}:{left:a.distance};h.css(q);c.css(q);b.wrap(n);b.parent().append(c);b.parent().append(h);a.railDraggable&&c.bind("mousedown",function(a){var b=e(document);z=!0;t=parseFloat(c.css("top"));pageY=a.pageY;b.bind("mousemove.slimscroll",function(a){currTop=t+a.pageY-pageY;c.css("top",currTop);m(0,c.position().top,!1)});b.bind("mouseup.slimscroll",function(a){z=!1;p();b.unbind(".slimscroll")});return!1}).bind("selectstart.slimscroll",function(a){a.stopPropagation();a.preventDefault();return!1}); - h.hover(function(){w()},function(){p()});c.hover(function(){y=!0},function(){y=!1});b.hover(function(){r=!0;w();p()},function(){r=!1;p()});b.bind("touchstart",function(a,b){a.originalEvent.touches.length&&(A=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){k||b.originalEvent.preventDefault();b.originalEvent.touches.length&&(m((A-b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0),A=b.originalEvent.touches[0].pageY)});x();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}), - m(0,!0)):"top"!==a.start&&(m(e(a.start).position().top,null,!0),a.alwaysVisible||c.hide());window.addEventListener?(this.addEventListener("DOMMouseScroll",v,!1),this.addEventListener("mousewheel",v,!1)):document.attachEvent("onmousewheel",v)}});return this}});e.fn.extend({slimscroll:e.fn.slimScroll})})(jQuery); \ No newline at end of file diff --git a/src/main/webapp/assets/custom-js/plugins/summernote/summernote.min.js b/src/main/webapp/assets/custom-js/plugins/summernote/summernote.min.js deleted file mode 100644 index 6290d1c64..000000000 --- a/src/main/webapp/assets/custom-js/plugins/summernote/summernote.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(a){"function"==typeof define&&define.amd?define(["jquery","codemirror"],a):a(window.jQuery,window.CodeMirror)}(function(a,b){"function"!=typeof Array.prototype.reduce&&(Array.prototype.reduce=function(a,b){var c,d,e=this.length>>>0,f=!1;for(1c;++c)this.hasOwnProperty(c)&&(f?d=a(d,this[c],c,this):(d=this[c],f=!0));if(!f)throw new TypeError("Reduce of empty array with no initial value");return d});var c={bMac:navigator.appVersion.indexOf("Mac")>-1,bMSIE:navigator.userAgent.indexOf("MSIE")>-1||navigator.userAgent.indexOf("Trident")>-1,bFF:navigator.userAgent.indexOf("Firefox")>-1,jqueryVersion:parseFloat(a.fn.jquery),bCodeMirror:!!b},d=function(){var a=function(a){return function(b){return a===b}},b=function(a,b){return a===b},c=function(){return!0},d=function(){return!1},e=function(a){return function(){return!a.apply(a,arguments)}},f=function(a){return a};return{eq:a,eq2:b,ok:c,fail:d,not:e,self:f}}(),e=function(){var a=function(a){return a[0]},b=function(a){return a[a.length-1]},c=function(a){return a.slice(0,a.length-1)},e=function(a){return a.slice(1)},f=function(a,b){var c=a.indexOf(b);return-1===c?null:a[c+1]},g=function(a,b){var c=a.indexOf(b);return-1===c?null:a[c-1]},h=function(a,b){return b=b||d.self,a.reduce(function(a,c){return a+b(c)},0)},i=function(a){for(var b=[],c=-1,d=a.length;++cc;c++)a[c]&&b.push(a[c]);return b};return{head:a,last:b,initial:c,tail:e,prev:g,next:f,sum:h,from:i,compact:k,clusterBy:j}}(),f=function(){var b=function(b){return b&&a(b).hasClass("note-editable")},g=function(b){return b&&a(b).hasClass("note-control-sizing")},h=function(a){var b=function(b){return function(){return a.find(b)}};return{editor:function(){return a},dropzone:b(".note-dropzone"),toolbar:b(".note-toolbar"),editable:b(".note-editable"),codable:b(".note-codable"),statusbar:b(".note-statusbar"),popover:b(".note-popover"),handle:b(".note-handle"),dialog:b(".note-dialog")}},i=function(a){return function(b){return b&&b.nodeName===a}},j=function(a){return a&&/^DIV|^P|^LI|^H[1-7]/.test(a.nodeName)},k=function(a){return a&&/^UL|^OL/.test(a.nodeName)},l=function(a){return a&&/^TD|^TH/.test(a.nodeName)},m=function(a,c){for(;a;){if(c(a))return a;if(b(a))break;a=a.parentNode}return null},n=function(a,b){b=b||d.fail;var c=[];return m(a,function(a){return c.push(a),b(a)}),c},o=function(b,c){for(var d=n(b),e=c;e;e=e.parentNode)if(a.inArray(e,d)>-1)return e;return null},p=function(a,b){var c=[],d=!1,e=!1;return function f(g){if(g){if(g===a&&(d=!0),d&&!e&&c.push(g),g===b)return void(e=!0);for(var h=0,i=g.childNodes.length;i>h;h++)f(g.childNodes[h])}}(o(a,b)),c},q=function(a,b){b=b||d.fail;for(var c=[];a&&(c.push(a),!b(a));)a=a.previousSibling;return c},r=function(a,b){b=b||d.fail;for(var c=[];a&&(c.push(a),!b(a));)a=a.nextSibling;return c},s=function(a,b){var c=[];return b=b||d.ok,function e(d){a!==d&&b(d)&&c.push(d);for(var f=0,g=d.childNodes.length;g>f;f++)e(d.childNodes[f])}(a),c},t=function(a,b){var c=b.nextSibling,d=b.parentNode;return c?d.insertBefore(a,c):d.appendChild(a),a},u=function(b,c){return a.each(c,function(a,c){b.appendChild(c)}),b},v=i("#text"),w=function(a){return v(a)?a.nodeValue.length:a.childNodes.length},x=function(a){for(var b=0;a=a.previousSibling;)b+=1;return b},y=function(b,c){var f=e.initial(n(c,d.eq(b)));return a.map(f,x).reverse()},z=function(a,b){for(var c=a,d=0,e=b.length;e>d;d++)c=c.childNodes[b[d]];return c},A=function(a,b){if(0===b)return a;if(b>=w(a))return a.nextSibling;if(v(a))return a.splitText(b);var c=a.childNodes[b];return a=t(a.cloneNode(!1),a),u(a,r(c))},B=function(a,b,c){var e=n(b,d.eq(a));return 1===e.length?A(b,c):e.reduce(function(a,d){var e=d.cloneNode(!1);return t(e,d),a===b&&(a=A(a,c)),u(e,r(a)),e})},C=function(a,b){if(a&&a.parentNode){if(a.removeNode)return a.removeNode(b);var c=a.parentNode;if(!b){var d,e,f=[];for(d=0,e=a.childNodes.length;e>d;d++)f.push(a.childNodes[d]);for(d=0,e=f.length;e>d;d++)c.insertBefore(f[d],a)}c.removeChild(a)}},D=function(a){return f.isTextarea(a[0])?a.val():a.html()};return{blank:c.bMSIE?" ":"
",emptyPara:"


",isEditable:b,isControlSizing:g,buildLayoutInfo:h,isText:v,isPara:j,isList:k,isTable:i("TABLE"),isCell:l,isAnchor:i("A"),isDiv:i("DIV"),isLi:i("LI"),isSpan:i("SPAN"),isB:i("B"),isU:i("U"),isS:i("S"),isI:i("I"),isImg:i("IMG"),isTextarea:i("TEXTAREA"),ancestor:m,listAncestor:n,listNext:r,listPrev:q,listDescendant:s,commonAncestor:o,listBetween:p,insertAfter:t,position:x,makeOffsetPath:y,fromOffsetPath:z,split:B,remove:C,html:D}}(),g={version:"0.5.2",options:{width:null,height:null,focus:!1,tabsize:4,styleWithSpan:!0,disableLinkTarget:!1,disableDragAndDrop:!1,codemirror:null,lang:"en-US",direction:null,toolbar:[["style",["style"]],["font",["bold","italic","underline","clear"]],["fontname",["fontname"]],["color",["color"]],["para",["ul","ol","paragraph"]],["height",["height"]],["table",["table"]],["insert",["link","picture","video"]],["view",["fullscreen","codeview"]],["help",["help"]]],oninit:null,onfocus:null,onblur:null,onenter:null,onkeyup:null,onkeydown:null,onImageUpload:null,onImageUploadError:null,onToolbarClick:null,keyMap:{pc:{"CTRL+Z":"undo","CTRL+Y":"redo",TAB:"tab","SHIFT+TAB":"untab","CTRL+B":"bold","CTRL+I":"italic","CTRL+U":"underline","CTRL+SHIFT+S":"strikethrough","CTRL+BACKSLASH":"removeFormat","CTRL+SHIFT+L":"justifyLeft","CTRL+SHIFT+E":"justifyCenter","CTRL+SHIFT+R":"justifyRight","CTRL+SHIFT+J":"justifyFull","CTRL+SHIFT+NUM7":"insertUnorderedList","CTRL+SHIFT+NUM8":"insertOrderedList","CTRL+LEFTBRACKET":"outdent","CTRL+RIGHTBRACKET":"indent","CTRL+NUM0":"formatPara","CTRL+NUM1":"formatH1","CTRL+NUM2":"formatH2","CTRL+NUM3":"formatH3","CTRL+NUM4":"formatH4","CTRL+NUM5":"formatH5","CTRL+NUM6":"formatH6","CTRL+ENTER":"insertHorizontalRule"},mac:{"CMD+Z":"undo","CMD+SHIFT+Z":"redo",TAB:"tab","SHIFT+TAB":"untab","CMD+B":"bold","CMD+I":"italic","CMD+U":"underline","CMD+SHIFT+S":"strikethrough","CMD+BACKSLASH":"removeFormat","CMD+SHIFT+L":"justifyLeft","CMD+SHIFT+E":"justifyCenter","CMD+SHIFT+R":"justifyRight","CMD+SHIFT+J":"justifyFull","CMD+SHIFT+NUM7":"insertUnorderedList","CMD+SHIFT+NUM8":"insertOrderedList","CMD+LEFTBRACKET":"outdent","CMD+RIGHTBRACKET":"indent","CMD+NUM0":"formatPara","CMD+NUM1":"formatH1","CMD+NUM2":"formatH2","CMD+NUM3":"formatH3","CMD+NUM4":"formatH4","CMD+NUM5":"formatH5","CMD+NUM6":"formatH6","CMD+ENTER":"insertHorizontalRule"}}},lang:{"en-US":{font:{bold:"Bold",italic:"Italic",underline:"Underline",strike:"Strike",clear:"Remove Font Style",height:"Line Height",name:"Font Family",size:"Font Size"},image:{image:"Picture",insert:"Insert Image",resizeFull:"Resize Full",resizeHalf:"Resize Half",resizeQuarter:"Resize Quarter",floatLeft:"Float Left",floatRight:"Float Right",floatNone:"Float None",dragImageHere:"Drag an image here",selectFromFiles:"Select from files",url:"Image URL",remove:"Remove Image"},link:{link:"Link",insert:"Insert Link",unlink:"Unlink",edit:"Edit",textToDisplay:"Text to display",url:"To what URL should this link go?",openInNewWindow:"Open in new window"},video:{video:"Video",videoLink:"Video Link",insert:"Insert Video",url:"Video URL?",providers:"(YouTube, Vimeo, Vine, Instagram, or DailyMotion)"},table:{table:"Table"},hr:{insert:"Insert Horizontal Rule"},style:{style:"Style",normal:"Normal",blockquote:"Quote",pre:"Code",h1:"Header 1",h2:"Header 2",h3:"Header 3",h4:"Header 4",h5:"Header 5",h6:"Header 6"},lists:{unordered:"Unordered list",ordered:"Ordered list"},options:{help:"Help",fullscreen:"Full Screen",codeview:"Code View"},paragraph:{paragraph:"Paragraph",outdent:"Outdent",indent:"Indent",left:"Align left",center:"Align center",right:"Align right",justify:"Justify full"},color:{recent:"Recent Color",more:"More Color",background:"BackColor",foreground:"FontColor",transparent:"Transparent",setTransparent:"Set transparent",reset:"Reset",resetToDefault:"Reset to default"},shortcut:{shortcuts:"Keyboard shortcuts",close:"Close",textFormatting:"Text formatting",action:"Action",paragraphFormatting:"Paragraph formatting",documentStyle:"Document Style"},history:{undo:"Undo",redo:"Redo"}}}},h=function(){var b=function(b){return a.Deferred(function(c){a.extend(new FileReader,{onload:function(a){var b=a.target.result;c.resolve(b)},onerror:function(){c.reject(this)}}).readAsDataURL(b)}).promise()},c=function(b){return a.Deferred(function(c){a("").one("load",function(){c.resolve(a(this))}).one("error abort",function(){c.reject(a(this))}).css({display:"none"}).appendTo(document.body).attr("src",b)}).promise()};return{readFileAsDataURL:b,createImage:c}}(),i={isEdit:function(a){return-1!==[8,9,13,32].indexOf(a)},nameFromCode:{8:"BACKSPACE",9:"TAB",13:"ENTER",32:"SPACE",48:"NUM0",49:"NUM1",50:"NUM2",51:"NUM3",52:"NUM4",53:"NUM5",54:"NUM6",55:"NUM7",56:"NUM8",66:"B",69:"E",73:"I",74:"J",75:"K",76:"L",82:"R",83:"S",85:"U",89:"Y",90:"Z",191:"SLASH",219:"LEFTBRACKET",220:"BACKSLASH",221:"RIGHTBRACKET"}},j=function(){var b=function(b,d){if(c.jqueryVersion<1.9){var e={};return a.each(d,function(a,c){e[c]=b.css(c)}),e}return b.css.call(b,d)};this.stylePara=function(b,c){a.each(b.nodes(f.isPara),function(b,d){a(d).css(c)})},this.current=function(c,d){var e=a(f.isText(c.sc)?c.sc.parentNode:c.sc),g=["font-family","font-size","text-align","list-style-type","line-height"],h=b(e,g)||{};if(h["font-size"]=parseInt(h["font-size"],10),h["font-bold"]=document.queryCommandState("bold")?"bold":"normal",h["font-italic"]=document.queryCommandState("italic")?"italic":"normal",h["font-underline"]=document.queryCommandState("underline")?"underline":"normal",h["font-strikethrough"]=document.queryCommandState("strikeThrough")?"strikethrough":"normal",c.isOnList()){var i=["circle","disc","disc-leading-zero","square"],j=a.inArray(h["list-style-type"],i)>-1;h["list-style"]=j?"unordered":"ordered"}else h["list-style"]="none";var k=f.ancestor(c.sc,f.isPara);if(k&&k.style["line-height"])h["line-height"]=k.style.lineHeight;else{var l=parseInt(h["line-height"],10)/parseInt(h["font-size"],10);h["line-height"]=l.toFixed(1)}return h.image=f.isImg(d)&&d,h.anchor=c.isOnAnchor()&&f.ancestor(c.sc,f.isAnchor),h.aAncestor=f.listAncestor(c.sc,f.isEditable),h}},k=function(){var b=!!document.createRange,c=function(a,b){var c,d,g=a.parentElement(),h=document.body.createTextRange(),i=e.from(g.childNodes);for(c=0;c=0)break;d=i[c]}if(0!==c&&f.isText(i[c-1])){var j=document.body.createTextRange(),k=null;j.moveToElementText(d||g),j.collapse(!d),k=d?d.nextSibling:g.firstChild;var l=a.duplicate();l.setEndPoint("StartToStart",j);for(var m=l.text.replace(/[\r\n]/g,"").length;m>k.nodeValue.length&&k.nextSibling;)m-=k.nodeValue.length,k=k.nextSibling;{k.nodeValue}b&&k.nextSibling&&f.isText(k.nextSibling)&&m===k.nodeValue.length&&(m-=k.nodeValue.length,k=k.nextSibling),g=k,c=m}return{cont:g,offset:c}},g=function(a){var b=function(a,c){var g,h;if(f.isText(a)){var i=f.listPrev(a,d.not(f.isText)),j=e.last(i).previousSibling;g=j||a.parentNode,c+=e.sum(e.tail(i),f.length),h=!j}else{if(g=a.childNodes[c]||a,f.isText(g))return b(g,c);c=0,h=!1}return{cont:g,collapseToStart:h,offset:c}},c=document.body.createTextRange(),g=b(a.cont,a.offset);return c.moveToElementText(g.cont),c.collapse(g.collapseToStart),c.moveStart("character",g.offset),c},h=function(c,h,i,j){this.sc=c,this.so=h,this.ec=i,this.eo=j;var k=function(){if(b){var a=document.createRange();return a.setStart(c,h),a.setEnd(i,j),a}var d=g({cont:c,offset:h});return d.setEndPoint("EndToEnd",g({cont:i,offset:j})),d};this.select=function(){var a=k();if(b){var c=document.getSelection();c.rangeCount>0&&c.removeAllRanges(),c.addRange(a)}else a.select()},this.nodes=function(b){var g=f.listBetween(c,i),h=e.compact(a.map(g,function(a){return f.ancestor(a,b)}));return a.map(e.clusterBy(h,d.eq2),e.head)},this.commonAncestor=function(){return f.commonAncestor(c,i)};var l=function(a){return function(){var b=f.ancestor(c,a);return!!b&&b===f.ancestor(i,a)}};this.isOnEditable=l(f.isEditable),this.isOnList=l(f.isList),this.isOnAnchor=l(f.isAnchor),this.isOnCell=l(f.isCell),this.isCollapsed=function(){return c===i&&h===j},this.insertNode=function(a){var c=k();b?c.insertNode(a):c.pasteHTML(a.outerHTML)},this.toString=function(){var a=k();return b?a.toString():a.text},this.bookmark=function(a){return{s:{path:f.makeOffsetPath(a,c),offset:h},e:{path:f.makeOffsetPath(a,i),offset:j}}}};return{create:function(a,d,e,f){if(0===arguments.length)if(b){var g=document.getSelection();if(0===g.rangeCount)return null;var i=g.getRangeAt(0);a=i.startContainer,d=i.startOffset,e=i.endContainer,f=i.endOffset}else{var j=document.selection.createRange(),k=j.duplicate();k.collapse(!1);var l=j;l.collapse(!0);var m=c(l,!0),n=c(k,!1);a=m.cont,d=m.offset,e=n.cont,f=n.offset}else 2===arguments.length&&(e=a,f=d);return new h(a,d,e,f)},createFromNode:function(a){return this.create(a,0,a,1)},createFromBookmark:function(a,b){var c=f.fromOffsetPath(a,b.s.path),d=b.s.offset,e=f.fromOffsetPath(a,b.e.path),g=b.e.offset;return new h(c,d,e,g)}}}(),l=function(){this.tab=function(a,b){var c=f.ancestor(a.commonAncestor(),f.isCell),d=f.ancestor(c,f.isTable),g=f.listDescendant(d,f.isCell),h=e[b?"prev":"next"](g,c);h&&k.create(h,0).select()},this.createTable=function(b,c){for(var d,e=[],g=0;b>g;g++)e.push(""+f.blank+"");d=e.join("");for(var h,i=[],j=0;c>j;j++)i.push(""+d+"");h=i.join("");var k=''+h+"
";return a(k)[0]}},m=function(){var b=new j,d=new l;this.saveRange=function(a){a.data("range",k.create())},this.restoreRange=function(a){var b=a.data("range");b&&b.select()},this.currentStyle=function(a){var c=k.create();return c.isOnEditable()&&b.current(c,a)},this.undo=function(a){a.data("NoteHistory").undo(a)},this.redo=function(a){a.data("NoteHistory").redo(a)};for(var e=this.recordUndo=function(a){a.data("NoteHistory").recordUndo(a)},g=["bold","italic","underline","strikethrough","justifyLeft","justifyCenter","justifyRight","justifyFull","insertOrderedList","insertUnorderedList","indent","outdent","formatBlock","removeFormat","backColor","foreColor","insertHorizontalRule","fontName"],i=0,m=g.length;m>i;i++)this[g[i]]=function(a){return function(b,c){e(b),document.execCommand(a,!1,c)}}(g[i]);var n=function(b,c,d){e(b);var g=new Array(d+1).join(" ");c.insertNode(a(''+g+"")[0]);var h=a("#noteTab").removeAttr("id");c=k.create(h[0],1),c.select(),f.remove(h[0])};this.tab=function(a,b){var c=k.create();c.isCollapsed()&&c.isOnCell()?d.tab(c):n(a,c,b.tabsize)},this.untab=function(){var a=k.create();a.isCollapsed()&&a.isOnCell()&&d.tab(a,!0)},this.insertImage=function(a,b){h.createImage(b).then(function(b){e(a),b.css({display:"",width:Math.min(a.width(),b.width())}),k.create().insertNode(b[0])}).fail(function(){var b=a.data("callbacks");b.onImageUploadError&&b.onImageUploadError()})},this.insertVideo=function(b,c){e(b);var d,f=/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/,g=c.match(f),h=/\/\/instagram.com\/p\/(.[a-zA-Z0-9]*)/,i=c.match(h),j=/\/\/vine.co\/v\/(.[a-zA-Z0-9]*)/,l=c.match(j),m=/\/\/(player.)?vimeo.com\/([a-z]*\/)*([0-9]{6,11})[?]?.*/,n=c.match(m),o=/.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/,p=c.match(o);if(g&&11===g[2].length){var q=g[2];d=a("